Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

A trait containing functionality used by the behat base context, and form fields.

Copyright: 2020 Andrew Nicols <andrew@nicols.co.uk>
License: http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
File Size: 1724 lines (67 kb)
Included or required: 1 time
Referenced: 0 times
Includes or requires: 2 files
 lib/behat/classes/component_named_replacement.php
 lib/behat/classes/component_named_selector.php

Defines 60 functions

  locate_path()
  find()
  find_all()
  normalise_selector()
  get_selector_description()
  type_keys()
  __call()
  escape()
  spin()
  get_selected_node()
  get_text_selector_node()
  get_node_in_container()
  transform_selector()
  transform_text_selector()
  running_javascript()
  require_javascript()
  running_javascript_in_session()
  require_javascript_in_session()
  is_in_app()
  ensure_element_exists()
  ensure_element_does_not_exist()
  ensure_node_is_visible()
  ensure_node_attribute_is_set()
  ensure_element_is_visible()
  ensure_editors_are_loaded()
  has_tag()
  resize_window()
  wait_for_pending_js()
  wait_for_pending_js_in_session()
  look_for_exceptions()
  get_debug_text()
  execute()
  execute_in_matching_contexts()
  get_session_user()
  set_user()
  get_context()
  js_trigger_click()
  execute_js_on_node()
  get_webdriver_element_from_node_element()
  resolve_page_url()
  resolve_page_instance_url()
  get_real_timeout()
  get_timeout()
  get_reduced_timeout()
  get_extended_timeout()
  get_exact_named_selectors()
  get_partial_named_selectors()
  get_named_replacements()
  evaluate_script()
  evaluate_script_in_session()
  execute_script()
  execute_script_in_session()
  get_sesskey()
  set_test_timeout_factor()
  get_category_id()
  get_course_id()
  get_course_module_for_identifier()
  get_cm_by_activity_name()
  scope_tags_match()
  get_user_id_by_identifier()

Functions that are not part of a class:

locate_path($path)   X-Ref
Locates url, based on provided path.
Override to provide custom routing mechanism.

param: string $path
return: string

find($selector, $locator, $exception = false, $node = false, $timeout = false)   X-Ref
Returns the first matching element.

param: string $selector The selector type (css, xpath, named...)
param: mixed $locator It depends on the $selector, can be the xpath, a name, a css locator...
param: Exception $exception Otherwise we throw exception with generic info
param: NodeElement $node Spins around certain DOM node instead of the whole page
param: int $timeout Forces a specific time out (in seconds).
return: NodeElement

find_all($selector, $locator, $exception = false, $container = false, $timeout = false)   X-Ref
Returns all matching elements.

Adapter to Behat\Mink\Element\Element::findAll() using the spin() method.

param: string $selector The selector type (css, xpath, named...)
param: mixed $locator It depends on the $selector, can be the xpath, a name, a css locator...
param: Exception $exception Otherwise we throw expcetion with generic info
param: NodeElement $container Restrict the search to just children of the specified container
param: int $timeout Forces a specific time out (in seconds). If 0 is provided the default timeout will be applied.
return: array NodeElements list

normalise_selector(string $selector, $locator, Element $container)   X-Ref
No description

get_selector_description(string $selector, $locator)   X-Ref
Get a description of the selector and locator to use in an exception message.

param: string $selector The type of locator
param: mixed $locator The locator text
return: string

type_keys(Session $session, array $keys)   X-Ref
Send key presses straight to the currently active element.

The `$keys` array contains a list of key values to send to the session as defined in the WebDriver and JsonWire
specifications:
- JsonWire: https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#sessionsessionidkeys
- W3C WebDriver: https://www.w3.org/TR/webdriver/#keyboard-actions

This may be a combination of typable characters, modifier keys, and other supported keypoints.

The NULL_KEY should be used to release modifier keys. If the NULL_KEY is not used then modifier keys will remain
in the pressed state.

Example usage:

behat_base::type_keys($this->getSession(), [behat_keys::SHIFT, behat_keys::TAB, behat_keys::NULL_KEY]);
behat_base::type_keys($this->getSession(), [behat_keys::ENTER, behat_keys::NULL_KEY]);
behat_base::type_keys($this->getSession(), [behat_keys::ESCAPE, behat_keys::NULL_KEY]);

It can also be used to send text input, for example:

behat_base::type_keys(
$this->getSession(),
['D', 'o', ' ', 'y', 'o', 'u', ' ', 'p', 'l', 'a' 'y', ' ', 'G', 'o', '?', behat_base::NULL_KEY]
);


Please note: This function does not use the element/sendKeys variants but sends keys straight to the browser.

param: Session $session
param: string[] $keys

__call($name, $arguments)   X-Ref
Finds DOM nodes in the page using named selectors.

The point of using this method instead of Mink ones is the spin
method of behat_base::find() that looks for the element until it
is available or it timeouts, this avoids the false failures received
when selenium tries to execute commands on elements that are not
ready to be used.

All steps that requires elements to be available before interact with
them should use one of the find* methods.

The methods calls requires a {'find_' . $elementtype}($locator)
format, like find_link($locator), find_select($locator),
find_button($locator)...

param: string $name The name of the called method
param: mixed $arguments
return: NodeElement

escape($string)   X-Ref
Escapes the double quote character.

Double quote is the argument delimiter, it can be escaped
with a backslash, but we auto-remove this backslashes
before the step execution, this method is useful when using
arguments as arguments for other steps.

param: string $string
return: string

spin($lambda, $args = false, $timeout = false, $exception = false, $microsleep = false)   X-Ref
Executes the passed closure until returns true or time outs.

In most cases the document.readyState === 'complete' will be enough, but sometimes JS
requires more time to be completely loaded or an element to be visible or whatever is required to
perform some action on an element; this method receives a closure which should contain the
required statements to ensure the step definition actions and assertions have all their needs
satisfied and executes it until they are satisfied or it timeouts. Redirects the return of the
closure to the caller.

The closures requirements to work well with this spin method are:
- Must return false, null or '' if something goes wrong
- Must return something != false if finishes as expected, this will be the (mixed) value
returned by spin()

The arguments of the closure are mixed, use $args depending on your needs.

You can provide an exception to give more accurate feedback to tests writers, otherwise the
closure exception will be used, but you must provide an exception if the closure does not throw
an exception.

param: Function|array|string $lambda The function to execute or an array passed to call_user_func (maps to a class method)
param: mixed $args Arguments to pass to the closure
param: int $timeout Timeout in seconds
param: Exception $exception The exception to throw in case it time outs.
param: bool $microsleep If set to true it'll sleep micro seconds rather than seconds.
return: mixed The value returned by the closure

get_selected_node($selectortype, $element)   X-Ref
Gets a NodeElement based on the locator and selector type received as argument from steps definitions.

Use behat_base::get_text_selector_node() for text-based selectors.

param: string $selectortype
param: string $element
return: NodeElement

get_text_selector_node($selectortype, $element)   X-Ref
Gets a NodeElement based on the locator and selector type received as argument from steps definitions.

param: string $selectortype
param: string $element
return: NodeElement

get_node_in_container($selectortype, $element, $containerselectortype, $containerelement)   X-Ref
Gets the requested element inside the specified container.

param: mixed $selectortype The element selector type.
param: mixed $element The element locator.
param: mixed $containerselectortype The container selector type.
param: mixed $containerelement The container locator.
return: NodeElement

transform_selector($selectortype, $element)   X-Ref
Transforms from step definition's argument style to Mink format.

Mink has 3 different selectors css, xpath and named, where named
selectors includes link, button, field... to simplify and group multiple
steps in one we use the same interface, considering all link, buttons...
at the same level as css selectors and xpath; this method makes the
conversion from the arguments received by the steps to the selectors and locators
required to interact with Mink.

param: string $selectortype It can be css, xpath or any of the named selectors.
param: string $element The locator (or string) we are looking for.
return: array Contains the selector and the locator expected by Mink.

transform_text_selector($selectortype, $element)   X-Ref
Transforms from step definition's argument style to Mink format.

Delegates all the process to behat_base::transform_selector() checking
the provided $selectortype.

param: string $selectortype It can be css, xpath or any of the named selectors.
param: string $element The locator (or string) we are looking for.
return: array Contains the selector and the locator expected by Mink.

running_javascript()   X-Ref
Whether Javascript is available in the current Session.

return: boolean

require_javascript(?string $message = null)   X-Ref
Require that javascript be available in the current Session.

param: null|string $message An additional information message to show when JS is not available

running_javascript_in_session(Session $session)   X-Ref
Whether Javascript is available in the specified Session.

param: Session $session
return: boolean

require_javascript_in_session(Session $session, ?string $message = null)   X-Ref
Require that javascript be available for the specified Session.

param: Session $session
param: null|string $message An additional information message to show when JS is not available

is_in_app()   X-Ref
Checks if the current page is part of the mobile app.

return: bool True if it's in the app

ensure_element_exists($locator, $selectortype)   X-Ref
Spins around an element until it exists

param: string $locator
param: string $selectortype
return: void

ensure_element_does_not_exist($locator, $selectortype)   X-Ref
No description

ensure_node_is_visible($node)   X-Ref
No description

ensure_node_attribute_is_set($node, $attribute, $attributevalue)   X-Ref
No description

ensure_element_is_visible($element, $selectortype)   X-Ref
No description

ensure_editors_are_loaded()   X-Ref
Ensures that all the page's editors are loaded.

return: void

has_tag(string $tag)   X-Ref
Checks if the current scenario, or its feature, has a specified tag.

param: string $tag Tag to check
return: bool True if the tag exists in scenario or feature

resize_window($windowsize, $viewport = false)   X-Ref
Change browser window size.
- mobile: 425x750
- tablet: 768x1024
- small: 1024x768
- medium: 1366x768
- large: 2560x1600

param: string $windowsize size of window.
param: bool $viewport If true, changes viewport rather than window size

wait_for_pending_js()   X-Ref
Waits for all the JS to be loaded.

return: bool Whether any JS is still pending completion.

wait_for_pending_js_in_session(Session $session)   X-Ref
Waits for all the JS to be loaded.

param: Session $session The Mink Session where JS can be run
return: bool Whether any JS is still pending completion.

look_for_exceptions()   X-Ref
Internal step definition to find exceptions, debugging() messages and PHP debug messages.

Part of behat_hooks class as is part of the testing framework, is auto-executed
after each step so no features will splicitly use it.


get_debug_text($html)   X-Ref
Converts HTML tags to line breaks to display the info in CLI

param: string $html
return: string

execute($contextapi, $params = array()   X-Ref
Helper function to execute api in a given context.

param: string $contextapi context in which api is defined.
param: array $params list of params to pass.

execute_in_matching_contexts(string $prefix, string $method, array $params)   X-Ref
Execute a function in a specific behat context.

For example, to call the 'set_editor_value' function for all editors, you would call:

behat_base::execute_in_matching_contexts('editor', 'set_editor_value', ['Some value']);

This would find all behat contexts whose class name starts with 'behat_editor_' and
call the 'set_editor_value' function on that context.

param: string $prefix
param: string $method
param: array $params

get_session_user()   X-Ref
Get the actual user in the behat session (note $USER does not correspond to the behat session's user).

return: mixed

set_user($user = null)   X-Ref
Set current $USER, reset access cache.

In some cases, behat will execute the code as admin but in many cases we need to set an specific user as some
API's might rely on the logged user to take some action.

param: null|int|stdClass $user user record, null or 0 means non-logged-in, positive integer means userid

get_context(string $levelname, string $contextref)   X-Ref
Gets the internal moodle context id from the context reference.

The context reference changes depending on the context
level, it can be the system, a user, a category, a course or
a module.

param: string $levelname The context level string introduced by the test writer
param: string $contextref The context reference introduced by the test writer
return: context

js_trigger_click($node)   X-Ref
Trigger click on node via javascript instead of actually clicking on it via pointer.

This function resolves the issue of nested elements with click listeners or links - in these cases clicking via
the pointer may accidentally cause a click on the wrong element.
Example of issue: clicking to expand navigation nodes when the config value linkadmincategories is enabled.
param: NodeElement $node

execute_js_on_node(NodeElement $node, string $script, bool $async = false)   X-Ref
Execute JS on the specified NodeElement.

param: NodeElement $node
param: string $script
param: bool $async

get_webdriver_element_from_node_element(NodeElement $node)   X-Ref
Translate a Mink NodeElement into a WebDriver Element.

param: NodeElement $node
return: WebDriverElement

resolve_page_url(string $page)   X-Ref
Convert page names to URLs for steps like 'When I am on the "[page name]" page'.

You should override this as appropriate for your plugin. The method
{@link behat_navigation::resolve_core_page_url()} is a good example.

Your overridden method should document the recognised page types with
a table like this:

Recognised page names are:
| Page            | Description                                                    |

param: string $page name of the page, with the component name removed e.g. 'Admin notification'.
return: moodle_url the corresponding URL.

resolve_page_instance_url(string $type, string $identifier)   X-Ref
Convert page names to URLs for steps like 'When I am on the "[identifier]" "[page type]" page'.

A typical example might be:
When I am on the "Test quiz" "mod_quiz > Responses report" page
which would cause this method in behat_mod_quiz to be called with
arguments 'Responses report', 'Test quiz'.

You should override this as appropriate for your plugin. The method
{@link behat_navigation::resolve_core_page_instance_url()} is a good example.

Your overridden method should document the recognised page types with
a table like this:

Recognised page names are:
| Type      | identifier meaning | Description                                     |

param: string $type identifies which type of page this is, e.g. 'Attempt review'.
param: string $identifier identifies the particular page, e.g. 'Test quiz > student > Attempt 1'.
return: moodle_url the corresponding URL.

get_real_timeout(int $timeout)   X-Ref
Gets the required timeout in seconds.

param: int $timeout One of the TIMEOUT constants
return: int Actual timeout (in seconds)

get_timeout()   X-Ref
Gets the default timeout.

The timeout for each Behat step (load page, wait for an element to load...).

return: int Timeout in seconds

get_reduced_timeout()   X-Ref
Gets the reduced timeout.

A reduced timeout for cases where self::get_timeout() is too much
and a simple $this->getSession()->getPage()->find() could not
be enough.

return: int Timeout in seconds

get_extended_timeout()   X-Ref
Gets the extended timeout.

A longer timeout for cases where the normal timeout is not enough.

return: int Timeout in seconds

get_exact_named_selectors()   X-Ref
Return a list of the exact named selectors for the component.

Named selectors are what make Behat steps like
Then I should see "Useful text" in the "General" "fieldset"
work. Here, "fieldset" is the named selector, and "General" is the locator.

If you override this method in your plugin (e.g. mod_mymod), to define
new selectors specific to your plugin. For example, if you returned
new behat_component_named_selector('Thingy',
[".//some/xpath//img[contains(@alt, %locator%)]/.."])
then
Then I should see "Useful text" in the "Whatever" "mod_mymod > Thingy"
would work.

This method should return a list of {@link behat_component_named_selector} and
the docs on that class explain how it works.

return: behat_component_named_selector[]

get_partial_named_selectors()   X-Ref
Return a list of the partial named selectors for the component.

Like the exact named selectors above, but the locator only
needs to match part of the text. For example, the standard
"button" is a partial selector, so:
When I click "Save" "button"
will activate "Save changes".

return: behat_component_named_selector[]

get_named_replacements()   X-Ref
Return a list of the Mink named replacements for the component.

Named replacements allow you to define parts of an xpath that can be reused multiple times, or in multiple
xpaths.

This method should return a list of {@link behat_component_named_replacement} and the docs on that class explain
how it works.

return: behat_component_named_replacement[]

evaluate_script(string $script)   X-Ref
Evaluate the supplied script in the current session, returning the result.

param: string $script
return: mixed

evaluate_script_in_session(Session $session, string $script)   X-Ref
Evaluate the supplied script in the specified session, returning the result.

param: Session $session
param: string $script
return: mixed

execute_script(string $script)   X-Ref
Execute the supplied script in the current session.

No result will be returned.

param: string $script

execute_script_in_session(Session $session, string $script)   X-Ref
Excecute the supplied script in the specified session.

No result will be returned.

param: Session $session
param: string $script

get_sesskey()   X-Ref
Get the session key for the current session via Javascript.

return: string

set_test_timeout_factor(int $factor = 1)   X-Ref
Set the timeout factor for the remaining lifetime of the session.

param: int $factor A multiplication factor to use when calculating the timeout

get_category_id(string $identifier)   X-Ref
Get the course category id from an identifier.

The category idnumber, and name are checked.

param: string $identifier
return: int|null

get_course_id(string $identifier)   X-Ref
Get the course id from an identifier.

The course idnumber, shortname, and fullname are checked.

param: string $identifier
return: int|null

get_course_module_for_identifier(string $identifier)   X-Ref
Get the activity course module id from its idnumber.

Note: Only idnumber is supported here, not name at this time.

param: string $identifier
return: cm_info|null

get_cm_by_activity_name(string $activity, string $identifier)   X-Ref
Get a coursemodule from an activity name or idnumber.

param: string $activity
param: string $identifier
return: cm_info

scope_tags_match(HookScope $scope, callable $callback)   X-Ref
Check whether any of the tags availble to the current scope match using the given callable.

This function is typically called from within a Behat Hook, such as BeforeFeature, BeforeScenario, AfterStep, etc.

The callable is used as the second argument to `array_filter()`, and is passed a single string argument for each of the
tags available in the scope.

The tags passed will include:
- For a FeatureScope, the Feature tags only
- For a ScenarioScope, the Feature and Scenario tags
- For a StepScope, the Feature, Scenario, and Step tags

An example usage may be:

// Note: phpDoc beforeStep attribution not shown.
public function before_step(StepScope $scope) {
$callback = function (string $tag): bool {
return $tag === 'editor_atto' || substr($tag, 0, 5) === 'atto_';
};

if (!self::scope_tags_match($scope, $callback)) {
return;
}

// Do something here.
}

param: HookScope $scope The scope to check
param: callable $callback The callable to use to check the scope
return: boolean Whether any of the scope tags match

get_user_id_by_identifier(string $identifier)   X-Ref
Get the user id from an identifier.

The user username and email fields are checked.

param: string $identifier The user's username or email.
return: int|null The user id or null if not found.