WebDriverWait versus FluentWait in Selenium Webdriver
The
WebDriver code waits for the page to load but today we have dynamic websites
using things like angularjs and Ajax. WebDriver does not wait for the javascript
to execute. So you might have something like:
<a
href="http://{{env}}.company.com/foo/bar.html">{{env}}</a>
When the
page loads, javascript runs and converts {{env}} to some defined value. So on
the test environment {{env}} might convert to test, on stage it converts to
stage and on production it converts to www. However, WebDriver will not wait
for the javascript to make the substitution.
The end result is clicking the element will cause WebDriver to go to "{{env}}.company.com"
when we really wanted it to wait and go to "www.company.com".
So how do we
make WebDriver wait for the variable to be updated by javascript?
The answer
is WebDriverWait or FluentWait. Below are examples of how you can use
WebDriverWait and FluentWait to wait for the javascript to finish:
import
com.google.common.base.Function;
import
com.google.common.base.Predicate;
import
org.junit.After;
import
org.junit.Before;
import
org.junit.Test;
import
org.openqa.selenium.*;
import
org.openqa.selenium.chrome.ChromeDriver;
import
org.openqa.selenium.remote.DesiredCapabilities;
import
org.openqa.selenium.support.ui.*;
import
java.util.Arrays;
import
static java.util.concurrent.TimeUnit.*;
import
static org.junit.Assert.assertFalse;
public class
TestingFluentWaitAndWebDriverWait {
WebDriver driver;
WebElement button;
@Before
public void setUp() {
System.setProperty("webdriver.chrome.driver",
"/Users/ThoughtWorks/IdeaProjects/SeleniumTesting/chromedriver2");
DesiredCapabilities dc =
DesiredCapabilities.chrome();
dc.setCapability("driver.switches",
Arrays.asList("--start-maximized"));
driver = new ChromeDriver(dc);
driver.manage().window().maximize();
driver.get("http://www.google.com");
driver.findElement(By.cssSelector("#gbqfq")).sendKeys("\"Darrell
Grainger\"");
button =
driver.findElement(By.cssSelector("#gbqfb"));
}
@Test
public void testWebDriverWait() {
new WebDriverWait(driver,
3).until(ExpectedConditions.visibilityOf(button)).click();
assertMyBlogLinkExists();
}
@Test
public void testFluentWait() {
new
FluentWait<WebElement>(button).withTimeout(3, SECONDS)
.pollingEvery(100, MILLISECONDS)
.until(new Function<WebElement,
Boolean>() {
public Boolean apply(WebElement w) {
return w.isDisplayed();
}
});
button.click();
assertMyBlogLinkExists();
}
@Test
public void testFluentWaitPredicate() {
new
FluentWait<WebElement>(button).withTimeout(3, SECONDS)
.pollingEvery(100, MILLISECONDS)
.until(new
Predicate<WebElement>() {
public boolean apply(WebElement w) {
return w.isDisplayed();
}
});
button.click();
assertMyBlogLinkExists();
}
private void assertMyBlogLinkExists() {
final String linkText = "QA &
Testing";
try {
new
FluentWait<WebDriver>(driver).withTimeout(3, SECONDS)
.pollingEvery(100, MILLISECONDS)
.ignoring(NoSuchElementException.class)
.until(new Function<WebDriver,
Boolean>() {
public Boolean apply(WebDriver d) {
WebElement link =
d.findElement(By.linkText(linkText));
return link.isDisplayed();
}
});
} catch(TimeoutException te) {
assertFalse(String.format("Timeout
waiting for link: '%s'", linkText), true);
}
}
@After
public void tearDown() {
if(driver != null)
driver.quit();
}
}
All three
tests will result in the same outcome.
Comments
Post a Comment