Reputation: 1115
I am using Selenium 3.4 with Java. I am testing a UI that is not very fast and use an implicit wait so that I don't have to care about manual explcit waiting every time something can take a couple of seconds to load.
However, sometimes I need an explicit wait anyway. And for that, I need to disable the implicit wait temporarily. To avoid cluttering up the code, I put the following method in my driver manager class:
public static void waitFor(ExpectedCondition<Boolean> condition,int timeoutSeconds) throws Exception {
setImplicitWait(0);
try {
(new WebDriverWait(driver, timeoutSeconds)).until(condition);
} finally {
setImplicitWait(WAIT_REGULAR);
}
}
The setImplicitWait
method is simple:
public static void setImplicitWait(int TimeoutSeconds) {
logger.debug("Setting implicit wait to {} seconds",TimeoutSeconds);
driver.manage().timeouts().implicitlyWait(TimeoutSeconds, TimeUnit.SECONDS);
}
So, this setup works for some waits, like this one:
DriverManager.waitFor(ExpectedConditions.invisibilityOfElementLocated(By.className("gridxLoad")), DriverManager.WAIT_HUGE);
However, if I try this one:
DriverManager.waitFor(ExpectedConditions.visibilityOfElementLocated(By.className("gridxMain")), DriverManager.WAIT_HUGE);
I get a compile error:
The method waitFor(ExpectedCondition, int) in the type DriverManager is not applicable for the arguments (ExpectedCondition, int)
If I change the parameter type in the definition of the method to ExpectedCondition<WebElement>
, then, of course, the second wait suceeds and the first one throws a compile error. If I try creating the same method for both ExpectedCondition<WebElement>
and ExpectedCondition<Boolean>
, I get a compile error:
Erasure of method waitFor(ExpectedCondition, int) is the same as another method in type DriverManager
Finally, if I try to define the parameter as just ExpectedCondition
, I get loads of compile warnings in the same small method:
ExpectedCondition is a raw type. References to generic type ExpectedCondition should be parameterized
Type safety: The expression of type ExpectedCondition needs unchecked conversion to conform to Function
Type safety: Unchecked invocation until(ExpectedCondition) of the generic method until(Function) of type FluentWait
I did also try defining the method like this:
public static void waitFor(Function<? super WebDriver,Object> condition,int timeoutSeconds) throws Exception {
But then both invocations of the method throw compiler errors.
What should I do? Go with a raw ExpectedCondition parameter and just ignore the warnings?
Upvotes: 1
Views: 1093
Reputation: 3384
One example of what you are asking can be following:
public WebElement waitFor(WebElement elem, String waitType, long waitInSeconds ) {
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(waitInSeconds, TimeUnit.SECONDS)
.pollingEvery(500, TimeUnit.MILLISECONDS)
.ignoring(NoSuchElementException.class);
try{
switch(waitType)
{
case "elementToBeClickable":
wait.until(ExpectedConditions.elementToBeClickable(elem));
break;
case "visibilityOf":
wait.until(ExpectedConditions.visibilityOf(elem));
break;
case "elementToBeSelected":
wait.until(ExpectedConditions.elementToBeSelected(elem));
break;
default:
wait.until(ExpectedConditions.visibilityOf(elem));
break;
}
}
catch(TimeoutException e) {
e.printStackTrace();
}
return elem;
}
Similarly if
ExpectedCondition
acts onBy
or requires extra parameters this can be changed as per the requirement.
Upvotes: 0
Reputation: 364
I am using these wrapper methods to handle synchronization at the time of locating elements. Try this:
public static void expWait_elementclick(WebDriver driver,By by){
try {
(new WebDriverWait(driver, 10)).until(ExpectedConditions.elementToBeClickable(by));
driver.findElement(by).click();
} catch (StaleElementReferenceException ser) {
// TODO Auto-generated catch block
driver.findElement(by).click();
}
}
public static void expWait_elementlocated(WebDriver driver,By by){
try {
(new WebDriverWait(driver, 10)).until(ExpectedConditions.presenceOfElementLocated(by));
driver.findElement(by).click();
} catch (StaleElementReferenceException ser) {
// TODO Auto-generated catch block
driver.findElement(by).click();
}
}
Upvotes: 1
Reputation: 11
We have a very nice customized wait-method in our projects that can be easily adapted to any condition you might wanna wait for
public static void waitForElementToBeVisible(WebDriver driver, int seconds, WebElement element) {
WebDriverWait wait = (WebDriverWait) new WebDriverWait(driver, seconds)
.ignoring(StaleElementReferenceException.class);
wait.withMessage(ERROR_START + element + ERROR_MIDDLE + seconds + ERROR_END);
wait.until((ExpectedCondition<Boolean>) webDriver -> element.isDisplayed());
}
Just replace element.isDisplayed()
with any boolean condition you want.
The int
param is the max. Timeout you wanna wait for a condition to become true.
Using it with Selenium 3.4 and it works like a charm.
Upvotes: 0
Reputation: 1115
I did eventually find what I think is the right solution:
public static void waitFor(ExpectedCondition<?> condition,int timeoutSeconds) throws Exception {
setImplicitWait(0);
try {
(new WebDriverWait(driver, timeoutSeconds)).until(condition);
} finally {
setImplicitWait(WAIT_REGULAR);
}
}
Upvotes: 1
Reputation: 42518
The methods visibilityOfElementLocated
and invisibilityOfElementLocated
don't return the same type:
public static ExpectedCondition<Boolean> invisibilityOfElementLocated(final By locator) { ... }
public static ExpectedCondition<WebElement> visibilityOfElementLocated(final By locator) { ... }
When the condition is applied, the first one returns a Boolean
while the second one returns a WebElement
.
So to make it work, you need to implement both:
public static void waitFor(ExpectedCondition<Boolean> condition,int timeoutSeconds) throws Exception {
setImplicitWait(0);
try {
(new WebDriverWait(driver, timeoutSeconds)).until(condition);
} finally {
setImplicitWait(WAIT_REGULAR);
}
}
public static WebElement waitFor(ExpectedCondition<WebElement> condition,int timeoutSeconds) throws Exception {
setImplicitWait(0);
try {
return (new WebDriverWait(driver, timeoutSeconds)).until(condition);
} finally {
setImplicitWait(WAIT_REGULAR);
}
}
Upvotes: 0