MDL-66550 behat: Standardise finding in core functionality

This commit is contained in:
Andrew Nicols
2019-09-10 21:24:20 +08:00
parent 1b52ec70f0
commit 0c7478e4fa
5 changed files with 79 additions and 117 deletions
@@ -114,12 +114,8 @@ class behat_block_site_main_menu extends behat_base {
protected function get_site_menu_activity_element($element, $selectortype, $activityname) {
$activitynode = $this->get_site_menu_activity_node($activityname);
// Transforming to Behat selector/locator.
list($selector, $locator) = $this->transform_selector($selectortype, $element);
$exception = new ElementNotFoundException($this->getSession(), '"' . $element . '" "' .
$selectortype . '" in "' . $activityname . '" ');
return $this->find($selector, $locator, $exception, $activitynode);
$exception = new ElementNotFoundException($this->getSession(), "'{$element}' '{$selectortype}' in '${activityname}'");
return $this->find($selectortype, $element, $exception, $activitynode);
}
/**
@@ -114,12 +114,8 @@ class behat_block_social_activities extends behat_base {
protected function get_social_block_activity_element($element, $selectortype, $activityname) {
$activitynode = $this->get_social_block_activity_node($activityname);
// Transforming to Behat selector/locator.
list($selector, $locator) = $this->transform_selector($selectortype, $element);
$exception = new ElementNotFoundException($this->getSession(), '"' . $element . '" "' .
$selectortype . '" in "' . $activityname . '" ');
return $this->find($selector, $locator, $exception, $activitynode);
$exception = new ElementNotFoundException($this->getSession(), "'{$element}' '{$selectortype}' in '${activityname}'");
return $this->find($selectortype, $element, $exception, $activitynode);
}
/**
+2 -5
View File
@@ -1123,11 +1123,8 @@ class behat_course extends behat_base {
protected function get_activity_element($element, $selectortype, $activityname) {
$activitynode = $this->get_activity_node($activityname);
// Transforming to Behat selector/locator.
list($selector, $locator) = $this->transform_selector($selectortype, $element);
$exception = new ElementNotFoundException($this->getSession(), '"' . $element . '" "' . $selectortype . '" in "' . $activityname . '" ');
return $this->find($selector, $locator, $exception, $activitynode);
$exception = new ElementNotFoundException($this->getSession(), "'{$element}' '{$selectortype}' in '${activityname}'");
return $this->find($selectortype, $element, $exception, $activitynode);
}
/**
+30 -39
View File
@@ -371,12 +371,7 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
* @return NodeElement
*/
protected function get_selected_node($selectortype, $element) {
// Getting Mink selector and locator.
list($selector, $locator) = $this->transform_selector($selectortype, $element);
// Returns the NodeElement.
return $this->find($selector, $locator);
return $this->find($selectortype, $element);
}
/**
@@ -388,7 +383,6 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
* @return NodeElement
*/
protected function get_text_selector_node($selectortype, $element) {
// Getting Mink selector and locator.
list($selector, $locator) = $this->transform_text_selector($selectortype, $element);
@@ -407,18 +401,13 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
* @return NodeElement
*/
protected function get_node_in_container($selectortype, $element, $containerselectortype, $containerelement) {
// Gets the container, it will always be text based.
$containernode = $this->get_text_selector_node($containerselectortype, $containerelement);
list($selector, $locator) = $this->transform_selector($selectortype, $element);
// Specific exception giving info about where can't we find the element.
$locatorexceptionmsg = $element . '" in the "' . $containerelement. '" "' . $containerselectortype. '"';
$exception = new ElementNotFoundException($this->getSession(), $selectortype, null, $locatorexceptionmsg);
// Looks for the requested node inside the container node.
return $this->find($selector, $locator, $exception, $containernode);
return $this->find($selectortype, $element, $exception, $containernode);
}
/**
@@ -437,7 +426,6 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
* @return array Contains the selector and the locator expected by Mink.
*/
protected function transform_selector($selectortype, $element) {
// Here we don't know if an allowed text selector is being used.
$selectors = behat_selectors::get_allowed_selectors();
if (!isset($selectors[$selectortype])) {
@@ -482,63 +470,66 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
* Spins around an element until it exists
*
* @throws ExpectationException
* @param string $element
* @param string $locator
* @param string $selectortype
* @return void
*/
protected function ensure_element_exists($element, $selectortype) {
// Getting the behat selector & locator.
list($selector, $locator) = $this->transform_selector($selectortype, $element);
protected function ensure_element_exists($locator, $selectortype) {
// Exception if it timesout and the element is still there.
$msg = 'The "' . $element . '" element does not exist and should exist';
$msg = "The '{$locator}' element does not exist and should";
$exception = new ExpectationException($msg, $this->getSession());
// Normalise the values in order to perform the search.
$normalised = $this->normalise_selector($selectortype, $locator, $this->getSession()->getPage());
$selector = $normalised['selector'];
$locator = $normalised['locator'];
$container = $normalised['container'];
// It will stop spinning once the find() method returns true.
$this->spin(
function($context, $args) {
// We don't use behat_base::find as it is already spinning.
if ($context->getSession()->getPage()->find($args['selector'], $args['locator'])) {
function() use ($selector, $locator, $container) {
if ($container->find($selector, $locator)) {
return true;
}
return false;
},
array('selector' => $selector, 'locator' => $locator),
[],
self::get_extended_timeout(),
$exception,
true
);
}
/**
* Spins until the element does not exist
*
* @throws ExpectationException
* @param string $element
* @param string $locator
* @param string $selectortype
* @return void
*/
protected function ensure_element_does_not_exist($element, $selectortype) {
// Getting the behat selector & locator.
list($selector, $locator) = $this->transform_selector($selectortype, $element);
protected function ensure_element_does_not_exist($locator, $selectortype) {
// Exception if it timesout and the element is still there.
$msg = 'The "' . $element . '" element exists and should not exist';
$msg = "The '{$locator}' element exists and should not exist";
$exception = new ExpectationException($msg, $this->getSession());
// Normalise the values in order to perform the search.
$normalised = $this->normalise_selector($selectortype, $locator, $this->getSession()->getPage());
$selector = $normalised['selector'];
$locator = $normalised['locator'];
$container = $normalised['container'];
// It will stop spinning once the find() method returns false.
$this->spin(
function($context, $args) {
// We don't use behat_base::find() as we are already spinning.
if (!$context->getSession()->getPage()->find($args['selector'], $args['locator'])) {
return true;
function() use ($selector, $locator, $container) {
if ($container->find($selector, $locator)) {
return false;
}
return false;
return true;
},
array('selector' => $selector, 'locator' => $locator),
// Note: We cannot use $this because the find will then be $this->find(), which leads us to a nested spin().
// We cannot nest spins because the outer spin times out before the inner spin completes.
[],
self::get_extended_timeout(),
$exception,
true
+43 -61
View File
@@ -412,24 +412,22 @@ class behat_general extends behat_base {
* @param string $containerelement
* @param string $containerselectortype
*/
public function i_drag_and_i_drop_it_in($element, $selectortype, $containerelement, $containerselectortype) {
list($sourceselector, $sourcelocator) = $this->transform_selector($selectortype, $element);
$sourcexpath = $this->getSession()->getSelectorsHandler()->selectorToXpath($sourceselector, $sourcelocator);
list($containerselector, $containerlocator) = $this->transform_selector($containerselectortype, $containerelement);
$destinationxpath = $this->getSession()->getSelectorsHandler()->selectorToXpath($containerselector, $containerlocator);
$node = $this->get_selected_node("xpath_element", $sourcexpath);
if (!$node->isVisible()) {
throw new ExpectationException('"' . $sourcexpath . '" "xpath_element" is not visible', $this->getSession());
}
$node = $this->get_selected_node("xpath_element", $destinationxpath);
if (!$node->isVisible()) {
throw new ExpectationException('"' . $destinationxpath . '" "xpath_element" is not visible', $this->getSession());
public function i_drag_and_i_drop_it_in($source, $sourcetype, $target, $targettype) {
if (!$this->running_javascript()) {
throw new DriverException('Drag and drop steps require javascript');
}
$this->getSession()->getDriver()->dragTo($sourcexpath, $destinationxpath);
$source = $this->find($sourcetype, $source);
$target = $this->find($targettype, $target);
if (!$source->isVisible()) {
throw new ExpectationException("'{$source}' '{$sourcetype}' is not visible", $this->getSession());
}
if (!$target->isVisible()) {
throw new ExpectationException("'{$target}' '{$targettype}' is not visible", $this->getSession());
}
$this->getSession()->getDriver()->dragTo($source->getXpath(), $target->getXpath());
}
/**
@@ -968,12 +966,8 @@ EOF;
* @param string $selectortype The selector type
*/
public function should_exist($element, $selectortype) {
// Getting Mink selector and locator.
list($selector, $locator) = $this->transform_selector($selectortype, $element);
// Will throw an ElementNotFoundException if it does not exist.
$this->find($selector, $locator);
$this->find($selectortype, $element);
}
/**
@@ -987,35 +981,27 @@ EOF;
* @param string $selectortype The selector type
*/
public function should_not_exist($element, $selectortype) {
// Getting Mink selector and locator.
list($selector, $locator) = $this->transform_selector($selectortype, $element);
// Will throw an ElementNotFoundException if it does not exist, but, actually it should not exist, so we try &
// catch it.
try {
// Using directly the spin method as we want a reduced timeout but there is no
// need for a 0.1 seconds interval because in the optimistic case we will timeout.
$params = array('selector' => $selector, 'locator' => $locator);
// The exception does not really matter as we will catch it and will never "explode".
$exception = new ElementNotFoundException($this->getSession(), $selectortype, null, $element);
// Using the spin method as we want a reduced timeout but there is no need for a 0.1 seconds interval
// because in the optimistic case we will timeout.
// If all goes good it will throw an ElementNotFoundExceptionn that we will catch.
$this->spin(
function($context, $args) {
return $context->getSession()->getPage()->findAll($args['selector'], $args['locator']);
},
$params,
behat_base::get_reduced_timeout(),
$exception,
false
function($context, $args) use ($selectortype, $element) {
return $this->find($selectortype, $element);
}, [], behat_base::get_reduced_timeout(), $exception, false
);
} catch (ElementNotFoundException $e) {
// It passes.
// We expect the element to not be found.
return;
}
throw new ExpectationException('The "' . $element . '" "' . $selectortype .
'" exists in the current page', $this->getSession());
// The element was found and should not have been. Throw an exception.
throw new ExpectationException("The '{$element}' '{$selectortype}' exists in the current page", $this->getSession());
}
/**
@@ -1159,16 +1145,14 @@ EOF;
*/
public function should_exist_in_the($element, $selectortype, $containerelement, $containerselectortype) {
// Get the container node.
$containernode = $this->get_selected_node($containerselectortype, $containerelement);
list($selector, $locator) = $this->transform_selector($selectortype, $element);
$containernode = $this->find($containerselectortype, $containerelement);
// Specific exception giving info about where can't we find the element.
$locatorexceptionmsg = $element . '" in the "' . $containerelement. '" "' . $containerselectortype. '"';
$locatorexceptionmsg = "{$element} in the {$containerelement} {$containerselectortype}";
$exception = new ElementNotFoundException($this->getSession(), $selectortype, null, $locatorexceptionmsg);
// Looks for the requested node inside the container node.
$this->find($selector, $locator, $exception, $containernode);
$this->find($selectortype, $element, $exception, $containernode);
}
/**
@@ -1184,26 +1168,24 @@ EOF;
* @param string $containerselectortype The container locator
*/
public function should_not_exist_in_the($element, $selectortype, $containerelement, $containerselectortype) {
// Get the container node.
$containernode = $this->find($containerselectortype, $containerelement);
// Get the container node; here we throw an exception
// if the container node does not exist.
$containernode = $this->get_selected_node($containerselectortype, $containerelement);
list($selector, $locator) = $this->transform_selector($selectortype, $element);
// Will throw an ElementNotFoundException if it does not exist, but, actually
// it should not exist, so we try & catch it.
// Will throw an ElementNotFoundException if it does not exist, but, actually it should not exist, so we try &
// catch it.
try {
// Would be better to use a 1 second sleep because the element should not be there,
// but we would need to duplicate the whole find_all() logic to do it, the benefit of
// changing to 1 second sleep is not significant.
$this->find($selector, $locator, false, $containernode, behat_base::get_reduced_timeout());
// Looks for the requested node inside the container node.
$this->find($selectortype, $element, false, $containernode, behat_base::get_reduced_timeout());
} catch (ElementNotFoundException $e) {
// It passes.
// We expect the element to not be found.
return;
}
throw new ExpectationException('The "' . $element . '" "' . $selectortype . '" exists in the "' .
$containerelement . '" "' . $containerselectortype . '"', $this->getSession());
// The element was found and should not have been. Throw an exception.
throw new ExpectationException(
"The '{$element}' '{$selectortype}' exists in the '{$containerelement}' '{$containerselectortype}'",
$this->getSession()
);
}
/**
@@ -1754,8 +1736,8 @@ EOF;
if (!$this->running_javascript()) {
throw new DriverException('Checking focus on an element requires JavaScript');
}
list($a, $b) = $this->transform_selector($nodeselectortype, $nodeelement);
$element = $this->find($a, $b);
$element = $this->find($nodeselectortype, $nodeelement);
$xpath = addslashes_js($element->getXpath());
$script = 'return (function() { return document.activeElement === document.evaluate("' . $xpath . '",
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; })(); ';