Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions general/development/tools/behat/writing.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,70 @@ Sometimes, you will need to set up data that is specific to your plugin, or perf

As well as creating completely new steps, you can also extend some of the standard steps:

#### Calling other steps

When writing custom steps you will often want to perform actions, such as:

- clicking a link
- pressing a button
- typing into a field
- calling another existing step

When doing this you **should** use the `\behat_session_trait::execute()` method to call the existing step to perform the action.
You **should not** call the `->click()` method on a `NodeElement` manually as this will bypass some of the error detection states, and pausing to wait for JavaScript actions to take place.

The `\behat_session_trait::execute()` method accepts:

- the name of the method to call on a behat context class; and
- any arguments.

For example:

```php title="behat_general.php"
/**
* Toggles the specified admin switch.
*
* @When /^I toggle the "(?P<element_string>(?:[^"]|\\")*)" admin switch "(?P<state_string>on|off)"$/
* @param string $element Element we look for
* @param string $state The state of the switch
* @throws ElementNotFoundException Thrown by behat_base::find
*/
public function i_toggle_admin_switch($element, $state) {
// First check we are running Javascript, otherwise explode.
if (!$this->running_javascript()) {
throw new \Behat\Mink\Exception\DriverException('Switches are only available with JavaScript enabled');
}

// Next check that the node is available.
$node = $this->get_selected_node('checkbox', $element);
$this->ensure_node_is_visible($node);

// Update the state of the switch.
$field = $node->getAttribute('id');
if ($state == "on") {
$this->execute('behat_forms::i_set_the_field_to', [$field, 1]);
} else if ($state == "off") {
$this->execute('behat_forms::i_set_the_field_to', [$field, 0]);
} else {
throw new \Behat\Mink\Exception\ExpectationException('Invalid state for switch: ' . $state, $this->getSession());
}
}
```

<Since issueNumber="MDL-86231" versions={["4.1.21", "4.4.11", "4.5.7", "5.0.3"]} />

The `\behat_session_trait::execute()` method accepts the method on the behat context class in the callable array format:

```php
$this->execute([\behat_forms::class, 'i_set_the_field_to'], [$field, 0]);
```

:::note

Only the string format, adn the array callable are supported. You cannot pass a callback method.
Copy link

Copilot AI Aug 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a typo in 'adn' which should be 'and'.

Suggested change
Only the string format, adn the array callable are supported. You cannot pass a callback method.
Only the string format, and the array callable are supported. You cannot pass a callback method.

Copilot uses AI. Check for mistakes.

:::

#### Custom selectors (<tt>... in the "..." "..."</tt>)

There are a load of different steps which can refer to specific items on-screen, for example
Expand Down