MinkExtension icon indicating copy to clipboard operation
MinkExtension copied to clipboard

Nestable, easy to define, locations for Mink

Open jonathanjfshaw opened this issue 8 years ago • 1 comments

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 built-in behavior Then I should see "[^".*]"
  • The built-in location in the heading
  • 2 custom-defined locations: in the "[^".*]" block and in the "[^".*]" region

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?

jonathanjfshaw avatar Jan 08 '17 14:01 jonathanjfshaw

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.

aik099 avatar Jan 08 '17 18:01 aik099