Comments (49)
Session is a simple abstraction for the driver. So, what we really need is a:
- Support for multiple drivers of single type
- Support for switching between drivers inside scenario
Good news is we already have support for part 1 :-)
All we need is abstraction step for driver-switching inside scenario. Something like:
<?php
$steps->Given('/^(?P<step>.+) with (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
$world->getMink()->switchToDriver($driver);
$steps->Given($step);
});
This way we will be able to do insane deeds like:
Given I am on /news with goutte1
And I am on /users with goutte2
When I go to /homepage with goutte1
Then ...
What do you think?
from mink.
Very good idea. But a step like this may create lot of ambiguous steps.
maybe :
<?php
$steps->Given('/^(?P<step>.+) with client (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
$world->getMink()->switchToDriver($driver);
$steps->Given($step);
});
from mink.
Yeah, agree ;-)
from mink.
Now we have redundant steps, see : https://github.com/gordonslondon/Mink/commit/99a4aba97c2db0dab6c55db6d5abc3b8838bd8db
what do you think ?
EDIT : is it normal that these steps are redundant ?
for example this code should not throw a Redundant exception :
(because it's not the same step, no ?)
<?php
$steps->Given('/^(?P<step>.+) with client (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
$world->getMink()->switchToDriver($driver);
$steps->Given($step);
});
$steps->When('/^(?P<step>.+) with client (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
$world->getMink()->switchToDriver($driver);
$steps->When($step);
});
from mink.
You don't need steps for all step types. Behat does not differentiate Given|When|Then|And|But
steps, YOU should!
It means, that even if step is defined as Given
, you still be able to call it with When
or even Then
keyword and all localized equivalents ;-)
from mink.
a step like this might create ambiguous steps :
<?php
$steps->When('/^(?P<step>.+) with client (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
$world->getMink()->switchToDriver($driver);
$steps->When($step);
});
this one work, is it a good idea ? :
<?php
$steps->When('/^"(?P<step>.+)" with (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
$world->getMink()->switchToDriver($driver);
$steps->When($step);
});
from mink.
How about ? :
When I am on /news in browser goutte1
And I click "downloads" in browser goutte2
This one looks more natural to me, imo.
from mink.
I prefer client over browser, it seems a more accurate description.
from mink.
And how about adding akinf of tag ( like #goutte1 ) at the end of the string? like:
and on each rule, add this piece at the end with optional instance...
When I am on /news ~goutte
from mink.
Ok, now i think i understand possible ambigious steps. We need stable regex to be sure, that it will always much what it have to. So i propose:
<?php
$steps->When('/^(?P<step>.+) in mink:(?P<driver>.+) client$/', function($world, $driver, $step) use($steps) {
$world->getMink()->switchToDriver($driver);
$steps->When($step);
});
This way, we will be able to write something like:
When I am on /news in mink:goutte1 client
And I click "downloads" in mink:goutte2 client
This way we remove possible ambiguity and add possibility to write user-defined session steps. What do you think, guys?
It's kinda strange by first. But it solves problem and adds additional information layer on top of our steps without harming the humanability and readability of steps.
from mink.
I think this will make Gherking look and feel too technical for business people working with it.
I prefer to keep it simple in Gherkin over having it simple in PHP.
from mink.
@mmoreramerino interesting idea but, in this case, we lose readability in our steps, transforming them to another programmin language, which is bad turn for Gherkin and Behat, imo.
from mink.
@marijn you're talking about @mmoreramerino proposal or mine?
from mink.
We shouldn't need to modify the steps for this to work, I'd like to see it done with tags or at a higher level. Speaking of tags; Is it possible to apply them to steps?
@browser1
When I am on /news
@browser2
Then I should see "browser1 has visited this page"
Thanks for the email everzet.
from mink.
@ThePixelDeveloper tags are allowed only on scenarios, outlines and features in Gherkin DSL specification. And i don't want to break Gherkin specs. It's very readable and clean now. We'll make it only worse.
from mink.
@ThePixelDeveloper also, i think we should modify steps, cuz steps should tell reader about what type of interaction they actually describe. Tags are just meta information for filtering, hooking and categorizing. They doesn't tell reader anything useful about scenario itself, but steps should!
When you describing in your scenario communication between 2 clients, then you should talk about two clients in your steps!
from mink.
Then with each feature your regular expression becomes more and more complicated. From my point of view When I am on /news
should not know about the browser it's being run by, that's my point.
Now reading back, your regular expression above does what I suggest.
from mink.
@ThePixelDeveloper yes, we're not talking about initial step definitions change, but about adding new one with inline step-to-step call!
It's great demonstration of Behat extensibility, by the way ;-)
from mink.
Perhaps we're going the wrong way about this. I'm clueless about Behat
internals so perhaps this is not possible but why not:
When I am on /news
Using client goute
And I click "downloads"
Using client alternative-goute
from mink.
Aside from the fact that it's not in cucumber...
from mink.
It's possible, but NO!
It will break translations, readability and many other good things.
from mink.
Just spitballing :-)
I'm just not particular in favor of mink:client-name
but I can see that alternatives aren't any better...
from mink.
Agree. I don't like this mink:
part too
from mink.
From a natural language perspective putting it in braces might make sense:
Given I am on /news (with goute)
And another user is on /news/delete (with goute-alternative)
from mink.
with
doesn't makes sense:
Given I am on ... with ...
and what's even worse:
Given I fill in username with "everzet" (with goutte)
maybe
Given I am on /news (in goutte client)
And I am on /articles (in goutte-alternative client)
from mink.
You're right. Your suggestion to use in sounds good to me though. Within braces that is.
from mink.
What does the regex have to do with anything? People will use whatever language makes sense in their application.
The feature being requested is a way to change the "current session" from within a step.
from mink.
@cbandy please, read thread carefuly, before posting your get a life-comments:
Mink already supports this feature. The request and conversation is about using this feature in Behat steps by not breaking already existing ideology and defined in future user steps.
from mink.
I didn't realize Mink already supports switching sessions. @everzet's first comment seemed to imply that it does not:
\2. Support for switching between drivers inside scenario
What I gathered from reading the thread is that there isn't a clear, natural way to describe "which session" to which a rule applies. In my opinion, awkward language should be a compromise made by the users of your library, not one that is forced upon them.
from mink.
@cbandy awkward language? Gherkin? Please, try to throw away your scepsis and read this thread again, but from different point. What we're trying to do here is a simple way to switch between 2 or more browsers in single Behat scenario. Default, but not forced way. You can already do it by yourself, but it's common case to have clean out-of-the-box solution.
Behat is already awesome enough to happily use it, even without bundled with Mink web steps, without Sahi or Mink itself. But Mink does comes with Mink, Sahi integration and optional bundled steps, which newcomers can set up and use in matter of seconds. That's what i'm trying to achieve with Behat and Mink - to build very-useful libraries, that you can simply install and use very fast and very easy!
Yes, there's no yet clear natural way to describe which session to which step applies. And we're trying to find it. So, what's your point?
from mink.
this one works and doesn't seems ambiguous:
<?php
$steps->When('/^(?P<step>.+) in client (?P<driver>.+)$/', function($world, $driver, $step) use($steps) {
$world->getMink()->switchToDriver($driver);
$steps->When($step);
});
EDIT
I think this one is ambiguous:
Given I am on /news (in goutte client)
with this step :
<?php
$steps->Given('/^(?:|I )am on (?P<page>.+)$/', function($world, $page) {
$world->getSession()->visit($world->getPathTo($page));
});
from mink.
I'm thinking now about changing abstractions little bit. Switching driver, when you need to switch a session looks kinda stupid. Also, i'm pretty sure Mink will have easy configuration mechanics for sessions/drivers for multi-session testing. But i'm not sure about bundled step by 2 reasons:
- It still can bring some ambiguity in some cases and we don't know where
- It's very easy to write it by your own, when you need it (only 4 lines of code)
from mink.
@gordonslondon no it's not. Parens are not part of regex - it's just matcher ;-)
from mink.
It still can bring some ambiguity in some cases and we don't know where
It's very easy to write it by your own, when you need it (only 4 lines of code)
I agree whole heartedly. Just put the best example you came up with in the docs so people KNOW they can do this, and away they go.
Personally I will be using something like "Given visitor "david" is on the homepage" and just ensure that I do not write ambiguous test cases. My step code will create a driver/session for david if it doesn't exist or fetch the current one if it does; then run the step.
from mink.
Hey guys, i'm glad to announce, that i've removed driver
word from almost every part of Mink API (except drivers part itself, of course ;-) ). Now you work with session
s, which is more logical conception and make lot more sense in terms of multi-session support and readability of tests. Now you can really write multi-sessional tests with beautiful api ;-)
You can see changes in https://github.com/Behat/Mink#readme example ;-)
from mink.
why is this issue still open?
from mink.
@cordoval it waits Behat cookbook article "How to write multisessional Mink scenarios" ;-)
from mink.
maybe i misread the whole thread or do not understand but is this not already supported by putting @mink:sahi or other? on each scenario?
also i was in addition thinking on finding a way to assert methods, actions, and controllers for a sf2 app on behat ContexFeature
from mink.
@cordoval the @mink:sahi
tag is about changing the default session for a scenario. The current thread is about using multiple sessions in the same scenario.
And you should not assert controllers or action: it is not part of the behavior that can be observed by the user but of the internal implementation
from mink.
Thanks @stof, just went over it again and realized that the support was there all along:
// mix sessions
$mink->getSession('goutte1')->getPage()->findLink('Chat')->click();
$mink->getSession('goutte2')->getPage()->findLink('Chat')->click();
However the only problem was how to do this on a single line from steps...
So i guess that is still not fixed exemplified yet? @everzet
I would like to write the cookbook entry however, i don't see any examples yet on steps that are fixed
also I ran into weird problems when reseting when logging within a scenario, the next scenario (using FOSUB) would appear to have been already logged in. The sahi browser would reset on and off several times, it is not very great really but the only option to use when javascript is present... well so besides experimenting I ran into several problems that i half solved.
Anyway, thanks just wanted to comment and follow up with this development.
from mink.
@cordoval write a step to logout the client. It is easy as the only need is to visit the logout page
from mink.
I have the following hook to isolate the sessions as much as possible (note that this might come at a performance penalty for running your tests):
<?php
/**
* @AfterScenario
*/
public function stopSessions()
{
$mink = $this->getMink();
$mink->stopSessions();
$this->registerSessions($mink);
}
from mink.
@schmittjoh you don't need to stop/start sessions manually, cuz there's awesome:
$mink->restartSessions();
method in Mink 1.x: http://mink.behat.org/#resetting-the-session ;-)
from mink.
Also, there's much cleaner *.feature
-way to do this:
@insulated
Feature: ...
...
All scenarios in such feature will be insulated :-)
from mink.
Yeah, I think these methods weren't available when I wrote the code, but I'll check them out :)
from mink.
so the example is a chat between two users or a manager and a client I see hmm yeah interesting, i will have to write these kind of scenarios at some point too, mostly for an admin and a regular user of an app.
When @cordoval fills in "textarea" with "want to write the cookbook entry" (in sahi1)
When @cordoval clicks on "Comment" (in sahi1)
When @everzet clicks on "notification" (in goutte1)
Then @everzet will read somewhere "want to write the cookbook entry" (in goutte1)
so the idea is that for some things we need sahi for the javascript fanciness and then goutte for speed?
Else if not what is the use of this? What other scenarios could be out there?
from mink.
@cordoval interaction of two users on site. Sometimes it might be useful. For example, when user A does some things, which should change the context of user B.
from mink.
Hi Folks, interesting discussion. I've been thinking about this a lot, and I use Behat in stakeholder-facing places as often as possible, so I had a big interest in getting the "implementation details" out of the gherkin (read: we shouldn't require the driver name to appear in the gherkin) as well as not needing to rewrite all step definitions to be session-name aware.
Check out this comment: https://github.com/Behat/Mink/pull/368#issuecomment-22445924
for a sample step-definition that (together with that PR) gives a very stakeholder-friendly way to accomplish this --AND -- to make use of all available step definitions (no need to rewrite them all to be multi-persona aware).
The end result is acheived through a "session-switching" step, which I have suggested be formatted as:
Given I adopt the persona "John Doe"
The "persona" word is very stakeholder friendly, and the name you use is purely arbitrary and becomes the name of the Mink session, which means you can switch back and forth between personas and still be using the same session per person. Example in the linked comment.
from mink.
👍 I'm doing it quite in the same way, A step like
Given I adopt the persona "John Doe"
or even
Given "John Doe" is browsing
sounds good to me and making the new session the default one (as in #368 ) is really a good way to reuse existing steps.
from mink.
Related Issues (20)
- Feature: set basic auth after session start and reset HOT 3
- PHP 8.1 compatible release HOT 10
- Element attribute not exists HOT 1
- symfony/css-selector 6.0 compatibility with behat/mink HOT 1
- Symfony 6 compatible release
- Mink's use of stripos leads to some empty string behaviors in PHP 8 HOT 3
- Element not interactable even though it is in view (scrolled to) and visible HOT 1
- Add case-sensitive comparison option to function WebAssert::elementContains HOT 5
- Empty read; connection dead HOT 1
- Support Browserless HOT 2
- GET Request HOT 2
- Allow custom processing of WebAssert::assert through callback HOT 9
- Is this project active? HOT 2
- Strictly typed methods HOT 3
- Class "Behat\Mink\Mink" not found HOT 5
- Release with Symfony 7
- responseHeaderEquals() can no longer be used to check for existence HOT 3
- submit form and get resulting page?! HOT 1
- Unable to switch to frame on Selenium 3.x HOT 7
- Switching windows by name or handle? HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mink.