diff --git a/.upgradenotes/MDL-75067-2026030210543707.yml b/.upgradenotes/MDL-75067-2026030210543707.yml new file mode 100644 index 00000000000..3d8a8b2d04e --- /dev/null +++ b/.upgradenotes/MDL-75067-2026030210543707.yml @@ -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 diff --git a/auth/tests/behat/loginform.feature b/auth/tests/behat/loginform.feature index 2f6c37d7e2b..0d2daf313d8 100644 --- a/auth/tests/behat/loginform.feature +++ b/auth/tests/behat/loginform.feature @@ -35,10 +35,12 @@ Feature: Test if the login form provides the correct feedback 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 "course/tests/fixtures/image.jpg" file to "Favicon" filemanager And I press "Save changes" And I log out And I follow "Log in" - Then "//img[@id='logoimage']" "xpath_element" should exist + Then "//img[@id='logoimage' and contains(@src, '/image.jpg')]" "xpath_element" should exist + And "//link[@rel='shortcut icon' and contains(@href, '/image.jpg')]" "xpath_element" should exist Scenario: Add a custom welcome message Given the following config values are set as admin: diff --git a/lib/behat/classes/behat_session_trait.php b/lib/behat/classes/behat_session_trait.php index bc4a810ee7b..fcc5f223efe 100644 --- a/lib/behat/classes/behat_session_trait.php +++ b/lib/behat/classes/behat_session_trait.php @@ -571,9 +571,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()); @@ -583,7 +583,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( @@ -606,9 +606,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()); @@ -618,7 +618,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( diff --git a/lib/behat/core_behat_file_helper.php b/lib/behat/core_behat_file_helper.php index 17285ed2c93..afc31dc5519 100644 --- a/lib/behat/core_behat_file_helper.php +++ b/lib/behat/core_behat_file_helper.php @@ -14,6 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +// 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.