The Beginner’s Guide To Explicit Waits

explicit wait flow

Test automation methods should synchronize with the web site every time they interact with elements.

For example, before clicking an element, the test method should make sure first that the element exists and that it is clickable.

Otherwise, an exception will be generated.

The synchronization is done using explicit waits and expected conditions.

Why do we need explicit waits?

Lets take the simplest Selenium WebDriver method:

driver.findElement(locator)

How does it work?

findElement() tries finding in the browser DOM the element matched by the locator.

If the element is found, findElement() returns it.

Otherwise, findElement() fails.

findElement() works well if the website is fast.

But if the website is slow and the element is not in the browser DOM when findElement() is executed, findElement() will fail.

We need a better way of interacting with website elements.

What are Explicit Waits?

Explicit wait objects are created for the WebDriverWait class.

Each wait object has 2 parameters:

  • the driver object
  • a timeout

First, we create the object:

WebDriverWait wait = new WebDriverWait(driver, timeout);

Then, we tell the wait object to wait until an expected condition is reached:

  • wait until the element is found and clickable
  • wait until the page title is correct
  • wait until the element is found and visible
  • wait until the page url matches a pattern

The waiting is being done by the until() method of the WebDriverWait class.

The until() method has a parameter as well which is the expected condition to wait for.

The expected condition is created using the ExpectedConditions class:

wait.until(ExpectedConditions.condition(parameter));

To explain how an explicit wait works, I will use the following example:

//create the id locator for the searchBox element
By searchBoxId = By.id("search-box");

//create the wait object
WebDriverWait wait = new WebDriverWait(driver, 10);

//find the searchBox element and save it in the WebElement variable
WebElement searchBoxElement = wait.until(
                                ExpectedConditions.
                                  elementToBeClickable
                                     (searchBoxId));

//type in the searchBox element
searchBoxElement.click();
searchBoxElement.clear();
searchBoxElement.sendKeys("java");

What does this code work?

  1. the locator of the searchBox element is created
  2. the wait object is created with the driver object and a 10 seconds timeout as parameters.
  3. the waiting for the searchBox element starts:
    1. until() method starts a timer.
    2. until() method verifies if searchBox is in the browser dom and is clickable
    3. if the condition is true (searchBox is in the browser dom and is clickable), the waiting ends and until() method returns the searchBox element
    4. if the condition is not met and the timer did not reach yet the timeout value, the code waits for 500 ms before continuing from step 3.2
  4. if until() method finds the element, it returns the searchBox element which is saved in the WebElement variable
  5. the code clicks the element, clears existing value and types the keyword in it
  6. if until() method cannot find the searchBox element within the 10 seconds timeout, it generates an exception; the remaining code is not executed

 

See below a simplified diagram that explains this process:

 

explicit wait

What can we do with explicit waits?

Explicit waits can be used for:

1. finding single web element

2. finding multiple web elements

3. checking the web page title and url

4. checking the element’s status

5. interacting with frames (not included in this article)

 

Find single web element

 

There are a few expected conditions that can help with finding a single web element.

1. elementToBeClickable

It defines an expectation for checking that an element is visible and enabled so that you can click it.

ExpectedCondition elementToBeClickable(By locator)
ExpectedCondition elementToBeClickable(WebElement element)

2. presenceOfElementLocated

It defines an expectation for checking that an element is present on the DOM of a page.

The element can be enabled or disabled.

Use this condition for checking for hidden elements.

ExpectedCondition presenceOfElementLocated(By locator)

3. visibilityOfElementLocated

ExpectedCondition visibilityOfElementLocated(By locator)

ExpectedCondition visibilityOf(WebElement element)

It defines an expectation for checking that an element is present on the DOM of a page and visible.

 

NOTE: All following examples are complete so that you can try them by yourself.

Example

The next code sample shows how the elementToBeClickable and visibilityOfElementLocated conditions are used for finding single elements.

It uses the Vancouver Public Library website.

It automates a test case that verifies if the search component works.

import org.junit.After;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class TestClass { 
  WebDriver driver; 
  WebDriverWait wait; 

  //this is where chromedriver.exe should be 
  String driverPath = "c:/browserdrivers/chromedriver.exe"; 

  @Before 
  public void setUp() { 
    System.setProperty("webdriver.chrome.driver"driverPath);           
    driver = new ChromeDriver(); 
    wait = new WebDriverWait(driver, 10); 
  } 

  @After 
  public void tearDown() { 
    driver.quit(); 
  } 
 
  @Test 
  public void clickElementWithExplicitWait() 
      throws InterruptedException { 
  
    //open site 
    driver.get("http://www.vpl.ca"); 

    //finds the search box using the elementToBeClickable condition
    By searchBoxId = By.id("edit-search"); 
    WebElement searchBox = wait.until(
                             ExpectedConditions
                               .elementToBeClickable
                                  (searchBoxId)); 

    //types in the search box 
    searchBox.click(); 
    searchBox.clear(); 
    searchBox.sendKeys("java"); 
    
    //finds search button using the visibilityOfElementLocated condition
    By searchButtonId = By.id("edit-submit"); 
    WebElement searchButton = wait.until(
                                ExpectedConditions.
                                  visibilityOfElementLocated
                                      (searchButtonId)); 
    
    //clicks the search button 
    searchButton.click();

    //delay so you can see whats happening in the browser 
    Thread.sleep(5000); 
  }
} 

 

find multiple web elements

There are a few expected conditions that can help with finding multiple web elements.

1. visibilityOfAllElementsLocatedBy

It defines an expectation for checking that all elements present on the web page that match the locator are visible.

ExpectedCondition<List> visibilityOfAllElementsLocatedBy(By locator)
ExpectedCondition<List> visibilityOfAllElements(List elements)

 

2. presenceOfAllElementsLocatedBy

It defines an expectation for checking that there is at least 1 element present on the page.

ExpectedCondition<List> presenceOfAllElementsLocatedBy(By locator)

Example

The next code sample continues the previous one.

After the search is done, on the results page, it checks that the

  • title count is 25
  • author count is > 0

It finds the title and author elements using the 2 expected conditions for finding multiple elements:

import static org.junit.Assert.*;
import static org.junit.Assert.*;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class TestClass { 
  WebDriver driver; 
  WebDriverWait wait; 

  //this is where chromedriver.exe should be 
  String driverPath = "c:/browserdrivers/chromedriver.exe"; 

  @Before 
  public void setUp() { 
    System.setProperty("webdriver.chrome.driver"driverPath); 
    driver = new ChromeDriver(); 
    wait = new WebDriverWait(driver, 10); 
  } 

  @After 
  public void tearDown() { 
    driver.quit(); 
  } 

  @Test 
  public void clickElementWithExplicitWait() 
    throws InterruptedException { 

    //open site 
    driver.get("http://www.vpl.ca"); 

    //finds the search box 
    By searchBoxId = By.id("edit-search"); 
    WebElement searchBox = wait.until
                              (ExpectedConditions
                                  .elementToBeClickable
                                     (searchBoxId)); 

    //types in the search box 
    searchBox.click(); 
    searchBox.clear(); 
    searchBox.sendKeys("java"); 

    //finds the search button 
    By searchButtonId = By.id("edit-submit"); 
    WebElement searchButton = wait.until
                               (ExpectedConditions
                                 .visibilityOfElementLocated
                                   (searchButtonId)); 

    //clicks the search button 
    searchButton.click(); 

    //delay so you can see whats happening in the browser 
    Thread.sleep(10000); 

    //find all titles using visibilityOfAllElementsLocatedBy 
    By titleLocator = By.xpath("//a[@testid = 'bib_link']"); 
    List<WebElement> titles = wait.until
                               (ExpectedConditions.
                                  visibilityOfAllElementsLocatedBy
                                    (titleLocator)); 

    //get the number of titles found 
    int titleCount = titles.size();

    //check that the title count is equal to 25 
    assertEquals(titleCount, 25); 
    System.out.println("title count = " + titleCount);

    //find all authors using presenceOfAllElementsLocatedBy 
    By authorLocator = By.xpath("//a[@testid = 'author_search']"); 
    List<WebElement> authors = wait.until(
                                 ExpectedConditions
                                   .presenceOfAllElementsLocatedBy
                                     (authorLocator)); 

    //get the number of authors found 
    int authorCount = authors.size();
  
    //check that the author count is > 0 
    assertTrue(authorCount > 0); 
    System.out.println("author count = " + authorCount);
 }
}

 

 

check web page title and url

The following expected conditions can be used for checking the web page title and url.

1. titleContains

It defines an expectation for checking that the title contains a case-sensitive substring.

ExpectedCondition titleContains(java.lang.String title)

2. titleIs

ExpectedCondition titleIs(java.lang.String title)

It defines an expectation for checking the title of a page.

3. urlContains

ExpectedCondition urlContains(java.lang.String fraction)

It defines an expectation for the URL of the current page to contain specific text.

4. urlToBe

It defines an expectation for the URL of the current page to be a specific url.

ExpectedCondition urlToBe(java.lang.String url)

5. urlMatches

ExpectedCondition urlMatches(java.lang.String regex)

It defines an expectation for the URL to match a specific regular expression

 

Example

Let’s improve the first code sample by checking that the page titles and urls are correct.

import static org.junit.Assert.*;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class TestClass { 
  WebDriver driver; 
  WebDriverWait wait; 

  //this is where chromedriver.exe should be 
  String driverPath = "c:/browserdrivers/chromedriver.exe"; 

  @Before 
  public void setUp() { 
    System.setProperty("webdriver.chrome.driver",            
                      driverPath); 
    driver = new ChromeDriver(); 
    wait = new WebDriverWait(driver, 10); 
  } 

  @After 
  public void tearDown() { 
    driver.quit(); 
  } 

  @Test 
  public void clickElementWithExplicitWait() 
       throws InterruptedException { 

    //open site 
    driver.get("http://www.vpl.ca"); 

    //check if the home title is correct String 
    expectedHomeTitle = "Vancouver Public Library |"; 
    boolean isTitleCorrect = wait.until 
                                (ExpectedConditions .
                                   titleIs(expectedHomeTitle)); 
    assertTrue(isTitleCorrect == true); 

    //finds the search box 
    By searchBoxId = By.id("edit-search"); 
    WebElement searchBox = wait.until(
                               ExpectedConditions .
                                 elementToBeClickable(searchBoxId)); 

    //types in the search box 
    searchBox.click(); 
    searchBox.clear(); 
    searchBox.sendKeys("java"); 

    //finds the search button 
    By searchButtonId = By.id("edit-submit"); 
    WebElement searchButton = wait.until(
                                 ExpectedConditions .
                                    visibilityOfElementLocated 
                                        (searchButtonId)); 

    //clicks the search button 
    searchButton.click(); 

    //check if the results url is correct 
    String expectedResultsUrl = "https://vpl.bibliocommons.com/search"; 
    boolean isUrlCorrect = wait.until (
                             ExpectedConditions .
                                urlContains(expectedResultsUrl)); 
    assertTrue(isUrlCorrect == true); 

    //delay so you can see whats happening in the browser 
    Thread.sleep(10000); 
 }
}

check elements status

All previous expected conditions are very common.

There are also other expected conditions that can be used but are less common.

No complete code samples are provided for them but feel free to try them out.

1. elementSelectionStateToBe

ExpectedCondition elementSelectionStateToBe(By locator, boolean selected)
ExpectedCondition elementSelectionStateToBe(WebElement element, boolean selected)

It defines an expectation for checking if the given element is selected.

Example

WebDriverWait wait = new WebDriverWait(driver, 10);
assertTrue(wait.until(ExpectedConditions.
                      elementSelectionStateToBe(locator, true)));

2. elementToBeSelected

ExpectedCondition elementToBeSelected(By locator)
ExpectedCondition elementToBeSelected(WebElement element)

It defines an expectation for checking if the given element is selected.

Example

WebDriverWait wait = new WebDriverWait(driver, 10);
assertTrue(wait.until(ExpectedConditions.
                      elementToBeSelected(locator)));

3. invisibilityOfElementLocated

ExpectedCondition invisibilityOfElementLocated(By locator)

It defines an expectation for checking that an element is either invisible or not present on the DOM.

Example

 

WebDriverWait wait = new WebDriverWait(driver, 10);
assertTrue(wait.until(ExpectedConditions.
                      invisibilityOfElementLocated(locator)));

4. invisibilityOfElementWithText

ExpectedCondition invisibilityOfElementWithText(By locator, java.lang.String text)

It defines an expectation for checking that an element with text is either invisible or not present on the DOM.

Example

WebDriverWait wait = new WebDriverWait(driver, 10);
assertTrue(wait.until(ExpectedConditions.
                      invisibilityOfElementWithText(locator, text)));

5. stalenessOf

ExpectedCondition stalenessOf(WebElement element)

Wait until an element is no longer attached to the DOM.

Example

WebDriverWait wait = new WebDriverWait(driver, 10);
assertTrue(wait.until(ExpectedConditions.
                      stalenessOf(element)));

6. textToBePresentInElement

ExpectedCondition textToBePresentInElement(WebElement element, java.lang.String text)
ExpectedCondition textToBePresentInElementLocated(By locator, java.lang.String text)

It defines an expectation for checking if the given text is present in the element that matches the given locator.

Example

WebDriverWait wait = new WebDriverWait(driver, 10);
assertTrue(wait.until(ExpectedConditions.
                      textToBePresentInElementLocated(locator, keyword)));

7. textToBePresentInElementValue

ExpectedCondition textToBePresentInElementValue(By locator, java.lang.String text)
ExpectedCondition textToBePresentInElementValue(WebElement element, java.lang.String text)

It defines an expectation for checking if the given text is present in the specified elements value attribute.

Example

WebDriverWait wait = new WebDriverWait(driver, 10);
assertTrue(wait.until(ExpectedConditions.
                      textToBePresentInElementValue(locator, keyword)));

 

RELATED ARTICLE

How to create custom expected conditions in Selenium

 

Advertisements