MDL-66979 behat: Handle JS on elements better

This change introduces a new function to execute Javascript directly on
a node.

This should not, ordinarily, be used directly by steps, but may be
required in other parts of the Behat interaction.
This commit is contained in:
Andrew Nicols 2020-06-15 10:20:55 +08:00
parent c96cde27ea
commit 041b75f00a

View File

@ -30,6 +30,9 @@ use Behat\Mink\Exception\ExpectationException;
use Behat\Mink\Exception\ElementNotFoundException; use Behat\Mink\Exception\ElementNotFoundException;
use Behat\Mink\Exception\NoSuchWindowException; use Behat\Mink\Exception\NoSuchWindowException;
use Behat\Mink\Session; use Behat\Mink\Session;
use Facebook\WebDriver\Exception\ScriptTimeoutException;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\WebDriverElement;
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php. // NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
@ -1077,17 +1080,62 @@ EOF;
if (!$this->running_javascript()) { if (!$this->running_javascript()) {
$node->click(); $node->click();
} }
$this->ensure_node_is_visible($node); // Ensures hidden elements can't be clicked.
$xpath = $node->getXpath();
$driver = $this->getSession()->getDriver(); $driver = $this->getSession()->getDriver();
if ($driver instanceof \Moodle\BehatExtension\Driver\MoodleSelenium2Driver) { if ($driver instanceof \Moodle\BehatExtension\Driver\WebDriver) {
$script = "Syn.click({{ELEMENT}})"; $this->execute_js_on_node($node, '{{ELEMENT}}.click();');
$driver->triggerSynScript($xpath, $script);
} else { } else {
$driver->click($xpath); $this->ensure_node_is_visible($node); // Ensures hidden elements can't be clicked.
$driver->click($node->getXpath());
} }
} }
/**
* Execute JS on the specified NodeElement.
*
* @param NodeElement $node
* @param string $script
* @param bool $async
*/
protected function execute_js_on_node(NodeElement $node, string $script, bool $async = false): void {
$driver = $this->getSession()->getDriver();
if (!($driver instanceof \Moodle\BehatExtension\Driver\WebDriver)) {
throw new \coding_exception('Unknown driver');
}
if (preg_match('/^function[\s\(]/', $script)) {
$script = preg_replace('/;$/', '', $script);
$script = '(' . $script . ')';
}
$script = str_replace('{{ELEMENT}}', 'arguments[0]', $script);
$webdriver = $driver->getWebDriver();
$element = $this->get_webdriver_element_from_node_element($node);
if ($async) {
try {
$webdriver->executeAsyncScript($script, [$element]);
} catch (ScriptTimeoutException $e) {
throw new DriverException($e->getMessage(), $e->getCode(), $e);
}
} else {
$webdriver->executeScript($script, [$element]);
}
}
/**
* Translate a Mink NodeElement into a WebDriver Element.
*
* @param NodeElement $node
* @return WebDriverElement
*/
protected function get_webdriver_element_from_node_element(NodeElement $node): WebDriverElement {
return $this->getSession()
->getDriver()
->getWebDriver()
->findElement(WebDriverBy::xpath($node->getXpath()));
}
/** /**
* Convert page names to URLs for steps like 'When I am on the "[page name]" page'. * Convert page names to URLs for steps like 'When I am on the "[page name]" page'.
* *