With the explicit wait mechanism, we can also build custom-expected conditions along with common conditions using the ExpectedConditions
class. This comes in handy when a wait cannot be handled with a common condition supported by the ExpectedConditions
class.
In this recipe, we will explore how to create a custom condition.
We will create a test that will create a wait until an element appears on the page using the ExpectedCondition
class as follows:
@Test public void testExplicitWait() { WebDriver driver = new FirefoxDriver(); // Launch the sample Ajax application driver.get("http://cookbook.seleniumacademy.com/AjaxDemo.html"); try { driver.findElement(By.linkText("Page 4")).click(); WebElement message = new WebDriverWait(driver, 5) .until(new ExpectedCondition<WebElement>() { public WebElement apply(WebDriver d) { return d.findElement(By.id("page4")); } }); assertTrue(message.getText().contains("Nunc nibh tortor")); } finally { driver.quit(); } }
The Selenium WebDriver provides the ability to implement the custom ExpectedCondition
interface along with the WebDriverWait
class to create a custom-wait condition, as needed by a test. In this example, we created a custom condition, which returns a WebElement
object once the inner findElement()
method locates the element within a specified timeout, as follows:
WebElement message = new WebDriverWait(driver, 5) .until(new ExpectedCondition<WebElement>(){ @Override public WebElement apply(WebDriver d) { return d.findElement(By.id("page4")); }});
A custom wait can be created in various ways. In the following section, we will explore some common examples to implement a custom wait.
Based on the events and actions performed, the value of an element's attribute might change at runtime. For example, a disabled textbox gets enabled based on the user's rights. A custom wait can be created on the attribute value of the element. In the following example, ExpectedCondition
waits for a Boolean
return value, based on the attribute value of an element:
new WebDriverWait(driver, 10).until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver d) { return d.findElement(By.id("userName")).getAttribute("readonly").contains("true"); }});
Developers can hide or display elements based on the sequence of actions, user rights, and so on. The specific element might exist in the DOM but are hidden from the user, and when the user performs a certain action, it appears on the page. A custom wait condition can be created based on the element's visibility, as follows:
new WebDriverWait(driver, 10).until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver d) { return d.findElement(By.id("page4")).isDisplayed(); }});
The web application may be using a JavaScript framework such as jQuery for AJAX and content manipulation. For example, jQuery is used to load a big JSON file from the server asynchronously on the page. While jQuery is reading and processing this file, a test can check its status using the active
attribute. A custom wait can be implemented by executing the JavaScript code and checking the return value, as follows:
new WebDriverWait(driver, 10).until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver d) { JavascriptExecutor js = (JavascriptExecutor) d; return (Boolean)js.executeScript("return jQuery.active == 0"); }});
18.191.144.194