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