Expanding/clicking collapsed fieldsets
Faced with an issue that it's impossible/tricky to click on an element which is not a link. Counting that we have a lot of those in Drupal UI it feels natural to have a step definition in this great module.
This is a feature/support request to be able to expand collapsed element, like Menu settings on a
with something like When I expand "Menu settings" fieldset.
I would appreciate any help or pointers to how this could be archived.
There's a few options. If running in javascript, then you can go the verbose route, and say:
...
And I click "Menu Settings"
And I fill field...
if not running in JS, the fields should already be available that are hidden in that fieldset.
Alternatively, a custom step definition that does the actual clicking behind the scenes would work
/**
* @When I expand :link
*/
public function assertExpandFieldset($link)
{
$this->clickLink($link);
}
Thanks Jonathan!
The detail here is that those aren't links, and Then I click "foo" in Drupal\DrupalExtension\Context\MinkContext::assertClick() uses Mink Extension's clickLink(). I believe that only works on tags of type <a>?
In Seven theme in D9, the expandable sections on eg a node edit form for a collapsible section (whether in the main content edit column or the sidebar) are a <details> element with the clickable label being the contents text in the <summary> container (inside the first span, with more text following). They are themed to look like links (bold, blue colour).

<details class="path-form js-form-wrapper form-wrapper seven-details" data-drupal-selector="edit-path-0" id="edit-path-0">
<summary role="button" aria-controls="edit-path-0" aria-expanded="false" aria-pressed="false" class="seven-details__summary">
<span>URL alias</span>
<span class="summary"> (Automatic alias)</span>
</summary>
<div class="seven-details__wrapper details-wrapper">
<div class="js-form-item form-item js-form-type-checkbox form-type-checkbox js-form-item-path-0-pathauto form-item-path-0-pathauto">
<input data-drupal-selector="edit-path-0-pathauto" aria-describedby="edit-path-0-pathauto--description" type="checkbox" id="edit-path-0-pathauto" name="path[0][pathauto]" value="1" checked="checked" class="form-checkbox">
<label for="edit-path-0-pathauto" class="option">Generate automatic URL alias</label>
<!-- END OUTPUT from 'core/themes/seven/templates/classy/form/form-element-label.html.twig' -->
<div id="edit-path-0-pathauto--description" class="description">
Uncheck this to create a custom alias below. <a href="/admin/config/search/path/patterns">Configure URL alias patterns.</a>
</div>
</div>
<div class="js-form-item form-item js-form-type-textfield form-type-textfield js-form-item-path-0-alias form-item-path-0-alias form-disabled">
<label for="edit-path-0-alias">URL alias</label>
<input data-drupal-selector="edit-path-0-alias" aria-describedby="edit-path-0-alias--description" type="text" id="edit-path-0-alias" name="path[0][alias]" value="/section/level-2-page/level-3-page/level-4-page" size="60" maxlength="255" class="form-text" data-drupal-states="{"disabled":{"input[name=\u0022path[0][pathauto]\u0022]":{"checked":true}}}" disabled="">
<div id="edit-path-0-alias--description" class="description">
Specify an alternative path by which this data can be accessed. For example, type "/about" when writing an about page.
</div>
</div>
</div>
</details>
I started with this in our FeatureContext, but it's over-specific to the node form sidebar at present. Maybe we should target details > summary by text content instead.
/**
* Click an element by CSS selector.
*
* @Given I click the :arg1 element
*/
public function iClickTheElement($selector) {
$page = $this->getSession()->getPage();
$element = $page->find('css', $selector);
if (empty($element)) {
throw new Exception("No html element found for the selector ('$selector')");
}
$element->click();
}
/**
* Expand a details section in node edit meta (sidebar) section.
*
* @Given I expand node form details :details
*/
public function iExpandNodeFormSidebarDetails($details) {
// Eg: "Path", "rabbit-hole-settings", etc.
// Not all modules set a class for this; submit patches if not present.
$className = strtolower("${details}-form");
$this->iClickTheElement(".node-form .entity-meta .${className}");
}
The real question here is:
- is there existing functionality to do this in a way that's reasonably Behat-ish, and
- if there's no existing StepDefinition to do this (
Then I expand details for "blah"), would you consider a MR/pull req to add that to this extension?
Ah, I didn't realize those weren't links. Running in JS, the And I click :link I thought that worked with elements other than a but perhaps not...
I'd certainly review a new step definition that adds this capability. Since it's JS-specific, we'd probably want to add the $this->waitForAjaxToFinish() call after clicking the element to avoid timing issues...
PR is in #594.
It seems like $this->waitForAjaxToFinish() doesn't do the trick, nor did $this->getSession()->wait();. I used usleep() for 100ms instead - I guess what's happening there is a CSS animation so there's no Drupal ajaxing to poll for. Input welcome on that, I'm not delighted with it (but it does seem to work).