Behat / MinkExtension

Mink extension (tight integration and configuration) for Behat
MIT License
636 stars 276 forks source link

Nestable, easy to define, locations for Mink #265

Open jonathanjfshaw opened 7 years ago

jonathanjfshaw commented 7 years ago

We often want to restrict the focus of a particular step to it a particular part of a page (a "location").

To do this easily I find myself tempted to write horrible steps like:

I should see "text" in the ".region-sidebar .block-search h2" element
I fill in "value" in the "field_myfieldname_value[1]" field

which leak implementation details into the tests in a way that violates the spirit of BDD.

It's obviously possible to write custom step definitions for these 2 steps; but what makes this tedious in practice is that there is a bazillion of possible individual locations if we have to define them all explicitly. To get round this we need to use arguments ('I should see "text" in a "search" block), but that approach bogs down because: 1) every possible location type I want to define has about 20 possible actions I might want to define in it 2) different locations sometimes need to be nestable inside each other and if we define the different possible nestings explicitly then the combinations explode.

The solution would seem to be to develop a syntax that allows defining locations (fields, blocks, regions, elements) separately from the behaviours (seeing, filling in, pressing, checking) that can be located in them.

Then we could have steps like

    Then I should see "Text" in the heading in the "Search" block in the "Sidebar" region

Which hypothetically would use 4 differently defined things:

The ideal way to achieve this would seem to be to 1) have a new type of step definition @Location joining the existing family of @Given, @When etc, and @Transformation. 2) Tag existing @When/Then steps with @Locatable if they can validly be called with additional location text appended to them 3) Have these existing location steps use session->getLocation() instead of session->getPage() to make them use only the part of the page specified by the @Locations.

I have implemented a messy less-ideal solution using transformations (see https://github.com/Behat/Behat/issues/978) for details and I know think a somewhat cleaner implementation might be possible using tokens (https://github.com/asgorobets/TokensExtension).

Probably this should be an extension of its own though, if it is not wanted as a core Mink feature. Anyone interested?

aik099 commented 7 years ago

What you're describing is PageObject approach, where the only place CSS used to locate stuff is stored inside PageObject classes and then in steps you just specify what you want to access.

There is a good library https://github.com/qa-tools/qa-tools that uses Mink to define PageObjects, but it's integration with Behat https://github.com/qa-tools/behat-extension is incomplete.