MDL-75067 behat: always interact with filepicker inside active dialogue.

This allows for tests to interact with multiple elements of this type
during scenarios, whereas previously Behat would always try to interact
with the first (even when referring to latter file managers).
This commit is contained in:
Paul Holden
2026-03-02 10:59:43 +00:00
parent dcf942624d
commit f55ebaffb0
4 changed files with 35 additions and 35 deletions
@@ -0,0 +1,8 @@
issueNumber: MDL-75067
notes:
tool_behat:
- message: >-
The `behat_session_trait::ensure_element_[does_not_]exists(...)` methods
now accept optional `$container` parameter to define the parent node to
look within
type: improved
+4 -2
View File
@@ -34,10 +34,12 @@ Feature: Test if the login form provides the correct feedback
Scenario: Set logo for loginpage
Given I log in as "admin"
And I navigate to "Appearance > Logos" in site administration
And I upload "course/tests/fixtures/image.jpg" file to "Logo" filemanager
And I upload "lib/tests/fixtures/1.jpg" file to "Logo" filemanager
And I upload "lib/tests/fixtures/2.jpg" file to "Favicon" filemanager
And I press "Save changes"
And I log out
Then "//img[@id='logoimage']" "xpath_element" should exist
Then "//img[@id='logoimage' and contains(@src, '/1.jpg')]" "xpath_element" should exist
And "//link[@rel='shortcut icon' and contains(@href, '/2.jpg')]" "xpath_element" should exist
Scenario: Add a custom welcome message
Given the following config values are set as admin:
@@ -581,9 +581,9 @@ trait behat_session_trait {
* @throws ExpectationException
* @param string $locator
* @param string $selectortype
* @return void
* @param NodeElement $container Restrict the search to just children of the specified container
*/
protected function ensure_element_exists($locator, $selectortype) {
protected function ensure_element_exists($locator, $selectortype, $container = false) {
// Exception if it timesout and the element is still there.
$msg = "The '{$locator}' element does not exist and should";
$exception = new ExpectationException($msg, $this->getSession());
@@ -593,7 +593,7 @@ trait behat_session_trait {
'selector' => $selector,
'locator' => $locator,
'container' => $container,
] = $this->normalise_selector($selectortype, $locator, $this->getSession()->getPage());
] = $this->normalise_selector($selectortype, $locator, $container ?: $this->getSession()->getPage());
// It will stop spinning once the find() method returns true.
$this->spin(
@@ -616,9 +616,9 @@ trait behat_session_trait {
* @throws ExpectationException
* @param string $locator
* @param string $selectortype
* @return void
* @param NodeElement $container Restrict the search to just children of the specified container
*/
protected function ensure_element_does_not_exist($locator, $selectortype) {
protected function ensure_element_does_not_exist($locator, $selectortype, $container = false) {
// Exception if it timesout and the element is still there.
$msg = "The '{$locator}' element exists and should not exist";
$exception = new ExpectationException($msg, $this->getSession());
@@ -628,7 +628,7 @@ trait behat_session_trait {
'selector' => $selector,
'locator' => $locator,
'container' => $container,
] = $this->normalise_selector($selectortype, $locator, $this->getSession()->getPage());
] = $this->normalise_selector($selectortype, $locator, $container ?: $this->getSession()->getPage());
// It will stop spinning once the find() method returns false.
$this->spin(
+17 -27
View File
@@ -14,6 +14,12 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/behat_base.php');
use Behat\Mink\Exception\ExpectationException;
use Behat\Mink\Element\NodeElement;
/**
* Files interactions with behat.
*
@@ -25,25 +31,6 @@
* @copyright 2013 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/behat_base.php');
use Behat\Mink\Exception\ExpectationException as ExpectationException,
Behat\Mink\Element\NodeElement as NodeElement;
/**
* Files-related actions.
*
* Steps definitions related with filepicker or repositories should extend use this trait as it provides useful methods
* to deal with the common filepicker issues.
*
* @package core
* @category test
* @copyright 2013 David Monllaó
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
trait core_behat_file_helper {
/**
@@ -174,10 +161,8 @@ trait core_behat_file_helper {
* @throws ExpectationException Thrown by behat_base::find
* @param NodeElement $filemanagernode The filemanager or filepicker form element DOM node.
* @param mixed $repositoryname The repo name.
* @return void
*/
protected function open_add_file_window($filemanagernode, $repositoryname) {
$exception = new ExpectationException('No files can be added to the specified filemanager', $this->getSession());
// We should deal with single-file and multiple-file filemanagers,
// catching the exception thrown by behat_base::find() in case is not multiple
@@ -186,13 +171,17 @@ trait core_behat_file_helper {
$filemanagernode, 'NodeElement'
]);
$filepickerdialogue = $this->find('dialogue', get_string('filepicker', 'core_repository'));
// Wait for the default repository (if any) to load. This checks that
// the relevant div exists and that it does not include the loading image.
$this->ensure_element_exists(
"//div[contains(concat(' ', normalize-space(@class), ' '), ' file-picker ')]" .
"//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content ')]" .
"[not(descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content-loading ')])]",
'xpath_element');
"//div[contains(concat(' ', normalize-space(@class), ' '), ' file-picker ')]" .
"//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content ')]" .
"[not(descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content-loading ')])]",
'xpath_element',
$filepickerdialogue,
);
// Getting the repository link and opening it.
$repoexception = new ExpectationException('The "' . $repositoryname . '" repository has not been found', $this->getSession());
@@ -200,13 +189,14 @@ trait core_behat_file_helper {
// Avoid problems with both double and single quotes in the same string.
$repositoryname = behat_context_helper::escape($repositoryname);
// Here we don't need to look inside the selected element because there can only be one modal window.
// Select the repository link from inside the current filepicker dialogue.
$repositorylink = $this->find(
'xpath',
"//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-area ')]" .
"//descendant::span[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-name ')]" .
"[normalize-space(.)=$repositoryname]",
$repoexception
$repoexception,
$filepickerdialogue,
);
// Selecting the repo.