diff --git a/lib/behat/behat_base.php b/lib/behat/behat_base.php index 5510ae6ef28..4ebc6f62d21 100644 --- a/lib/behat/behat_base.php +++ b/lib/behat/behat_base.php @@ -1111,6 +1111,21 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext { /** * 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[] */ public static function get_exact_named_selectors(): array { @@ -1120,6 +1135,12 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext { /** * 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[] */ public static function get_partial_named_selectors(): array { @@ -1127,7 +1148,13 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext { } /** - * Return a list of the named replacements for the component. + * 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[] */ diff --git a/lib/behat/classes/behat_context_helper.php b/lib/behat/classes/behat_context_helper.php index 0a70011a9f2..d7a2b602eda 100644 --- a/lib/behat/classes/behat_context_helper.php +++ b/lib/behat/classes/behat_context_helper.php @@ -118,7 +118,7 @@ class behat_context_helper { } /** - * Return whether there is a context of the specified classnme. + * Return whether there is a context of the specified classname. * * @param string $classname * @return bool diff --git a/lib/behat/classes/component_named_replacement.php b/lib/behat/classes/component_named_replacement.php index a771c32749d..f11a4ceead7 100644 --- a/lib/behat/classes/component_named_replacement.php +++ b/lib/behat/classes/component_named_replacement.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * Moodle-specific Mink replacements. + * A class for recording the definition of Mink replacements. * * @package core * @category test @@ -24,7 +24,34 @@ */ /** - * Moodle-specific Mink replacements. + * A class for recording the definition of Mink replacements for use in Mink selectors. + * + * These are comprised of a source string, and a replacement. + * + * During use the source string is converted from the string to be in the format: + * + * %[component]/[string]% + * + * For example: + * + * %mod_forum/title% + * + * Mink replacements are used in xpath translation to translate regularly used items such as title. + * Here is an example from the upstream Mink project: + * + * '%tagTextMatch%' => 'contains(normalize-space(string(.)), %locator%)' + * + * And can be used in an xpath: + * + * .//label[%tagTextMatch%] + * + * This would be expanded to: + * + * .//label[contains(normalize-space(string(.)), %locator%)] + * + * Replacements can also be used in other replacements, as long as that replacement is defined later. + * + * '%linkMatch%' => '(%idMatch% or %tagTextMatch% or %titleMatch% or %relMatch%)' * * @package core * @category test @@ -41,8 +68,10 @@ class behat_component_named_replacement { /** * Create the replacement. * - * @param string $from - * @param string $to + * @param string $from this is the old selector that should no longer be used. + * For example 'group_message'. + * @param string $to this is the new equivalent that should be used instead. + * For example 'core_message > Message'. */ public function __construct(string $from, string $to) { $this->from = $from; diff --git a/lib/behat/classes/component_named_selector.php b/lib/behat/classes/component_named_selector.php index 70820ac88b1..8b58484fe1d 100644 --- a/lib/behat/classes/component_named_selector.php +++ b/lib/behat/classes/component_named_selector.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * Moodle-specific selectors. + * Class representing a named selector that can be used in Behat tests. * * @package core * @category test @@ -24,7 +24,21 @@ */ /** - * Moodle-specific selectors. + * Class representing a named selector that can be used in Behat tests. + * + * Named selectors are what make Behat steps like + * Then I should see "Useful text" in the "General" "fieldset" + * Here, "fieldset" is the named selector, and "General" is the locator. + * + * Selectors can either be exact, in which case the locator needs to + * match exactly, or can be partial, for example the way + * When I click "Save" "button" + * will trigger a "Save changes" button. + * + * Instances of this class get returned by the get_exact_named_selectors() + * and get_partial_named_selectors() methods in classes like behat_mod_mymod. + * The code that makes the magic work is in the trait behat_named_selector + * used by both behat_exact_named_selector and behat_partial_named_selector. * * @package core * @category test @@ -44,8 +58,22 @@ class behat_component_named_selector { /** * Create the selector definition. * + * As an example, if you define + * new behat_component_named_selector('Message', + * [".//*[@data-conversation-id]//img[contains(@alt, %locator%)]/.."]) + * in get_partial_named_selectors in behat_message in + * message/tests/behat/behat_message.php, then steps like + * When "Group 1" "core_message > Message" should exist + * will work. + * + * Text selectors are things that contain other things (e.g. some particular text), e.g. + * Then I can see "Some text" in the "Whatever" "text_selector" + * whereas non-text selectors are atomic things, like + * When I click the "Whatever" "widget". + * * @param string $alias The 'friendly' name of the thing. This will be prefixed with the component name. - * @param array $xpaths A list of xpaths + * For example, if the mod_mymod plugin, says 'Thingy', then "mod_mymod > Thingy" becomes a selector. + * @param array $xpaths A list of xpaths one or more XPaths that the selector gets transformed into. * @param bool $istextselector Whether this selector can also be used as a text selector. */ public function __construct(string $alias, array $xpaths, bool $istextselector = true) { diff --git a/lib/behat/classes/named_selector.php b/lib/behat/classes/named_selector.php index 087b6ec1161..e683ffcf291 100644 --- a/lib/behat/classes/named_selector.php +++ b/lib/behat/classes/named_selector.php @@ -26,6 +26,12 @@ /** * Common functions for named selectors. * + * This has to be a trait, because we need this in both the classes + * behat_exact_named_selector and behat_partial_named_selector, and + * those classes have to be subclasses of \Behat\Mink\Selector\ExactNamedSelector + * and \Behat\Mink\Selector\PartialNamedSelector. This trait is a way achieve + * that without duplciated code. + * * @package core * @category test * @copyright 2019 Andrew Nicols