From 7d84120a0ec3159add378d7ae31adf7cdce73fbc Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Fri, 16 Aug 2019 08:52:26 +0800 Subject: [PATCH] MDL-66378 behat: Add non-JS fallback for before/after --- lib/tests/behat/behat_general.php | 73 +++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/lib/tests/behat/behat_general.php b/lib/tests/behat/behat_general.php index 5a0e57c522d..3cb7e49a62d 100644 --- a/lib/tests/behat/behat_general.php +++ b/lib/tests/behat/behat_general.php @@ -763,33 +763,53 @@ class behat_general extends behat_base { /** * Checks, that the first specified element appears before the second one. * - * @Given /^"(?P(?:[^"]|\\")*)" "(?P(?:[^"]|\\")*)" should appear before "(?P(?:[^"]|\\")*)" "(?P(?:[^"]|\\")*)"$/ + * @Then :preelement :preselectortype should appear before :postelement :postselectortype * @throws ExpectationException * @param string $preelement The locator of the preceding element * @param string $preselectortype The locator of the preceding element * @param string $postelement The locator of the latest element * @param string $postselectortype The selector type of the latest element */ - public function should_appear_before($preelement, $preselectortype, $postelement, $postselectortype) { - $msg = '"' . $preelement . '" "' . $preselectortype . - '" does not appear before "' . $postelement . '" "' . $postselectortype . '"'; - $this->check_element_order($preelement, $preselectortype, $postelement, $postselectortype, $msg); + public function should_appear_before( + string $preelement, + string $preselectortype, + string $postelement, + string $postselectortype + ) { + $msg = "'{$preelement}' '{$preselectortype}' does not appear after '{$postelement}' '{$postselectortype}'"; + $this->check_element_order( + $preelement, + $preselectortype, + $postelement, + $postselectortype, + $msg + ); } /** * Checks, that the first specified element appears after the second one. * - * @Given /^"(?P(?:[^"]|\\")*)" "(?P(?:[^"]|\\")*)" should appear after "(?P(?:[^"]|\\")*)" "(?P(?:[^"]|\\")*)"$/ + * @Then :postelement :postselectortype should appear after :preelement :preselectortype * @throws ExpectationException * @param string $postelement The locator of the latest element * @param string $postselectortype The selector type of the latest element * @param string $preelement The locator of the preceding element * @param string $preselectortype The locator of the preceding element */ - public function should_appear_after($postelement, $postselectortype, $preelement, $preselectortype) { - $msg = '"' . $postelement . '" "' . $postselectortype . - '" does not appear after "' . $preelement . '" "' . $preselectortype . '"'; - $this->check_element_order($preelement, $preselectortype, $postelement, $postselectortype, $msg); + public function should_appear_after( + string $postelement, + string $postselectortype, + string $preelement, + string $preselectortype + ) { + $msg = "'{$postelement}' '{$postselectortype}' does not appear after '{$preelement}' '{$preselectortype}'"; + $this->check_element_order( + $preelement, + $preselectortype, + $postelement, + $postselectortype, + $msg + ); } /** @@ -801,21 +821,36 @@ class behat_general extends behat_base { * @param string $postselectortype The selector type of the following element * @param string $msg Message to output if this fails */ - protected function check_element_order(string $preelement, string $preselectortype, - string $postelement, string $postselectortype, string $msg) { + protected function check_element_order( + string $preelement, + string $preselectortype, + string $postelement, + string $postselectortype, + string $msg + ) { list($preselector, $prelocator) = $this->transform_selector($preselectortype, $preelement); list($postselector, $postlocator) = $this->transform_selector($postselectortype, $postelement); $prexpath = $this->find($preselector, $prelocator)->getXpath(); $postxpath = $this->find($postselector, $postlocator)->getXpath(); - // The xpath to do this was running really slowly on certain Chrome versions so we are using - // this DOM method instead. - $ok = $this->getSession()->getDriver()->evaluateScript('return (function() { ' . - 'var a = document.evaluate("' . $prexpath . '", document).iterateNext();' . - 'var b = document.evaluate("' . $postxpath . '", document).iterateNext();' . - 'return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_PRECEDING;})()' - ); + if ($this->running_javascript()) { + // The xpath to do this was running really slowly on certain Chrome versions so we are using + // this DOM method instead. + $js = <<getSession()->getDriver()->evaluateScript($js); + } else { + + // Using following xpath axe to find it. + $xpath = "{$prexpath}/following::*[contains(., {$postxpath})]"; + $ok = $this->getSession()->getDriver()->find($xpath); + } if (!$ok) { throw new ExpectationException($msg, $this->getSession());