-
Combining Steps in Behat for Drupal
Lately I have found myself repeating several lines of behat steps over and over again. Here is a sample of the behat code I use to choose a specific checkbox from an entity browser popup:
12345678And I press the "field_carousel_slides_0_subform_field_carousel_slide_img_entity_browser_entity_browser" buttonAnd I wait for AJAX to finishAnd I switch to the iframe "entity_browser_iframe_ifde_media_image_browser"Then I should see the button "Embed"When I click "Use existing image"And I check checkbox 3 in the element "#entity-browser-ifde-media-image-browser-form"And I press the "Embed" buttonAnd I wait for AJAX to finishThere are a few steps in here that are custom, but explaining them would be beyond the scope of this post; just assume they do what they describe (switching focus to an iframe, and clicking a checkbox).
The issue I was having is that every time I wanted to do that one action (pick an image from an entity browser) I was repeating all 8 lines of code.
I began looking for ways of making this set of steps repeatable. After some failed attempts at extending MinkContext and MinkAwareContext I came across scenario hooks via this StackOverflow post. I discovered the @BeforeScenario, which is executed before every scenario in each feature (where it’s used). Using this hook to access contexts from other contexts was documented on behat.org but required a few tweaks for the Drupal implementation. Here is what I ended up doing (based on the default FeatureContext.php you get when you install behat for the project:
-
Setting Drupal 8 Node Properties with Behat
The title of this post could also have been “Opening and Closing a Details Element with Behat” or “Clicking Any Element with Behat”.
The Drupal 8 node add/edit screen has a number properties on the right side of the screen. I wanted to use Behat to click the “Provide a menu link” checkbox. On page load this MENU SETTINGS pane is closed like the others.
Here’s an example:
The “URL SETTINGS”, “MENU SETTINGS”, actually mask a <details> element.
The “MENU SETTINGS” markup looks like this:
I expected to be able to write a few lines of Behat like this:
1234When I am at "/node/add/page"Then I should see the heading "Create Page" in the "header" regionThen I fill in "Title" with "Landing Page without Sidebar"And I check "Provide a menu link"Unfortunately this results in the failure: element not interactable.
So, I thought I may need to first click to open the MENU SETTINGS pane so that I can see the checkbox before I try to click it. I modified my code to look like this:
12345When I am at "/node/add/page"Then I should see the heading "Create Page" in the "header" regionThen I fill in "Title" with "Landing Page without Sidebar"And I click "Menu settings"And I check "Provide a menu link"Unfortunately this results in the failure: Link with id|title|alt|text “Menu settings” not found.
I tried using the edit-menu id, “MENU SETTINGS” in all caps, etc. but it always resulted in the same “Link with …”
I realized the click step is only looking for links.
Solution
I added a new step definition to my features/bootstrap/FeatureContext.php file:
1234567891011121314151617/*** Click any element.** @Given I click the :selector element** @see https://stackoverflow.com/a/33672497/1023773*/public function iClickTheElement($selector) {$page = $this->getSession()->getPage();$element = $page->find('css', $selector);if (empty($element)) {throw new Exception("No html element found for selector '{$selector}'");}$element->click();}
12345When I am at "/node/add/page"Then I should see the heading "Create Page" in the "header" regionThen I fill in "Title" with "Landing Page without Sidebar"And I click the "#edit-menu" elementAnd I check "Provide a menu link"