Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable12] Better handling of invisible elements in acceptance tests #8739

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions tests/acceptance/features/core/ElementWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@
* the element is stale it is found again using the same parameters to find it
* in the first place.
*
* NoSuchElement exceptions are sometimes thrown instead of
* StaleElementReference exceptions. This can happen when the Selenium2 driver
* for Mink performs an action on an element through the WebDriver session
* instead of directly through the WebDriver element. In that case, if the
* element with the given ID does not exist, a NoSuchElement exception would be
* thrown instead of a StaleElementReference exception, so those cases are
* handled like StaleElementReference exceptions.
*
* ElementNotVisible exceptions are thrown when the command requires the element
* to be visible but the element is not. Finding an element only guarantees that
* (at that time) the element is attached to the DOM, but it does not provide
Expand All @@ -50,11 +58,22 @@
* exceptions; if the element is not visible it is waited for it to be visible
* up to the timeout set to find it.
*
* MoveTargetOutOfBounds exceptions are sometimes thrown instead of
* ElementNotVisible exceptions. This can happen when the Selenium2 driver for
* Mink moves the cursor on an element using the "moveto" method of the
* WebDriver session, for example, before clicking on an element. In that case,
* if the element is not visible, "moveto" would throw a MoveTargetOutOfBounds
* exception instead of an ElementNotVisible exception, so those cases are
* handled like ElementNotVisible exceptions.
*
* Despite the automatic handling it is possible for the commands to throw those
* exceptions when they are executed again; this class does not handle cases
* like an element becoming stale several times in a row (uncommon) or an
* element not becoming visible before the timeout expires (which would mean
* that the timeout is too short or that the test has to, indeed, fail).
* that the timeout is too short or that the test has to, indeed, fail). In a
* similar way, MoveTargetOutOfBounds exceptions would be thrown again if
* originally they were thrown because the element was visible but "out of
* reach".
*
* If needed, automatically handling failed commands can be disabled calling
* "doNotHandleFailedCommands()"; as it returns the ElementWrapper it can be
Expand Down Expand Up @@ -189,8 +208,8 @@ public function click() {
/**
* Executes the given command.
*
* If a StaleElementReference exception is thrown the wrapped element is
* found again and, then, the command is executed again.
* If a StaleElementReference or a NoSuchElement exception is thrown the
* wrapped element is found again and, then, the command is executed again.
*
* @param \Closure $commandCallback the command to execute.
* @param string $errorMessage an error message that describes the failed
Expand All @@ -205,6 +224,8 @@ private function executeCommand(\Closure $commandCallback, $errorMessage) {
return $commandCallback();
} catch (\WebDriver\Exception\StaleElementReference $exception) {
$this->printFailedCommandMessage($exception, $errorMessage);
} catch (\WebDriver\Exception\NoSuchElement $exception) {
$this->printFailedCommandMessage($exception, $errorMessage);
}

$this->element = $this->elementFinder->find();
Expand All @@ -215,10 +236,11 @@ private function executeCommand(\Closure $commandCallback, $errorMessage) {
/**
* Executes the given command on a visible element.
*
* If a StaleElementReference exception is thrown the wrapped element is
* found again and, then, the command is executed again. If an
* ElementNotVisible exception is thrown it is waited for the wrapped
* element to be visible and, then, the command is executed again.
* If a StaleElementReference or a NoSuchElement exception is thrown the
* wrapped element is found again and, then, the command is executed again.
* If an ElementNotVisible or a MoveTargetOutOfBounds exception is thrown it
* is waited for the wrapped element to be visible and, then, the command is
* executed again.
*
* @param \Closure $commandCallback the command to execute.
* @param string $errorMessage an error message that describes the failed
Expand All @@ -233,6 +255,8 @@ private function executeCommandOnVisibleElement(\Closure $commandCallback, $erro
return $this->executeCommand($commandCallback, $errorMessage);
} catch (\WebDriver\Exception\ElementNotVisible $exception) {
$this->printFailedCommandMessage($exception, $errorMessage);
} catch (\WebDriver\Exception\MoveTargetOutOfBounds $exception) {
$this->printFailedCommandMessage($exception, $errorMessage);
}

$this->waitForElementToBeVisible();
Expand Down