It's convenient to wait for an WebElement
to be present with WebDriverWait
and ExpectedConditions
.
The problem is, what if WebElement.findElment
was the only possible way to locate the element , 'cause it has no id, no name, no unique class?
WebDriverWait
's constructor accepts only WebDriver
as arguments, not WebElement
.
I've set the implicitlyWait
time, so it seems not a good idea to use try{} catch(NoSuchElementException e){}
, 'cause I don't want to wait that long time for this element.
Here's the scenario:
There's one web page with a form containing many input
tags. Each input
tag has a format requirement.
A dynamic div
tag would be present after this input
tag when the format requirement is not satisfied.
As there're so many input
tags, I create a general method like:
public WebElement txtBox(String name) {
return driver.findElement(By.name(name));
}
instead of creating a data member for each input
tag.
Then I create a method isValid
to check whether user inputs in some input
are valid. All I should do in isValid
is to check whether a div
tag is present after inputboxToCheck
, with code like this:
public boolean isValid(WebElement inputboxToCheck) {
WebElementWait wait = new WebElementWait(inputboxToCheck, 1);
try {
wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("./following-sibling::div")));
return false;
} catch (TimeOutException e) {
return true;
}
}
WebElementWait
is an imaginary (not exist) class which works the same way as WebDriverWait
.
Selenium: Waiting Until the Element Is Visiblevar wait = new WebDriverWait(driver, TimeSpan. FromSeconds(20)); As you can see, we give the WebDriverWait object two parameters: the driver itself and a TimeSpan object that represents the timeout for trying to locate the element.
The findElement method throws a NoSuchElementException exception when the element is not available on the page. Whereas, the findElements method returns an empty list when the element is not available or doesn't exist on the page.
This can be achieved with synchronization in Selenium. We shall add an explicit wait criteria where we shall stop or wait till the element no longer exists. Timeout exception is thrown once the explicit wait time has elapsed and the expected behavior of the element is still not available on the page.
This type of exception is thrown when there is no element on the page which matches with the locator value. Check if there is any syntax error in our xpath expression. Add additional expected wait conditions for the element. Use an alternative xpath expression.
The WebElementWait class as metioned above:
package org.openqa.selenium.support.ui;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.NotFoundException;
import org.openqa.selenium.WebElement;
public class WebElementWait extends FluentWait<WebElement> {
public final static long DEFAULT_SLEEP_TIMEOUT = 500;
public WebElementWait(WebElement element, long timeOutInSeconds) {
this(element, new SystemClock(), Sleeper.SYSTEM_SLEEPER, timeOutInSeconds, DEFAULT_SLEEP_TIMEOUT);
}
public WebElementWait(WebElement element, long timeOutInSeconds, long sleepInMillis) {
this(element, new SystemClock(), Sleeper.SYSTEM_SLEEPER, timeOutInSeconds, sleepInMillis);
}
protected WebElementWait(WebElement element, Clock clock, Sleeper sleeper, long timeOutInSeconds,
long sleepTimeOut) {
super(element, clock, sleeper);
withTimeout(timeOutInSeconds, TimeUnit.SECONDS);
pollingEvery(sleepTimeOut, TimeUnit.MILLISECONDS);
ignoring(NotFoundException.class);
}
}
It's the same as WebDriverWait, except that the WebDriver
argument is replaced with WebElement
.
Then, the isValid method:
//import com.google.common.base.Function;
//import org.openqa.selenium.TimeoutException;
public boolean isValid(WebElement e) {
try {
WebElementWait wait = new WebElementWait(e, 1);
//@SuppressWarnings("unused")
//WebElement icon =
wait.until(new Function<WebElement, WebElement>() {
public WebElement apply(WebElement d) {
return d.findElement(By
.xpath("./following-sibling::div[class='invalid-icon']"));
}
});
return false;
} catch (TimeoutException exception) {
return true;
}
}
A more universal variant of user2432405's solution would be using SearchContext type rather then WebElement:
public class SearchContextWait extends FluentWait<SearchContext> {
...
This allows to do waits on both WebDriver and WebElement similarly as the SearchContext interface is the ancestor of both WebDriver and WebElement. The isValid method needs adjustment too:
...
WebElement icon = wait
.until(new Function<SearchContext, WebElement>() {
public WebElement apply(SearchContext d) {
...
Unfortunately, you lose all conveniences of ExpectedConditions.xxxx() methods as they use the WebDriver interface internally.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With