Selenium Webdriver Fluent Wait Command with Examples

Hers is our latest submission to the series of Selenium Webdriver commands. In this tutorial, we’ve brought you a new perspective on the Webdriver Fluent Wait command. This post will highlight the most used Fluent Wait methods and provide a step by step description of their usage in your projects.

In all modern web applications which use HTML5 and AJAX for their user interface, Fluent Wait command is the best way to handle dynamic locators. It is an advanced Webdriver wait method which reduces chances of errors and increases stability. Another Webdriver command which you can use to manage wait is the Webdriver Wait command.

Perhaps you should refer our post which discusses the Webdriver Wait command at length. After reading both these posts, you would get a fair idea of the Wait commands. And you’ll be able to choose the right one from these Selenium Webdriver commands as per the context you are working.

Your choice of using Webdriver Wait command would depend on the nature of the web application. With the introduction of Ajax applications in the Web world, we have web elements which sometimes visible in just a second and sometimes take minutes to appear.

In such cases, it’s better to make use of Fluent Wait command as this wait tries to find the web element repeatedly at regular intervals until the timeout or till the object gets found.

Webdriver Fluent Wait Command Explained.

Selenium Webdriver Fluent Wait Command with Examples

1- How does the Fluent Wait Command work?

Fluent Wait uses two parameters – timeout value and polling frequency.

First of all, it sets the following values.

1- The maximum amount of time to wait for a condition, and

2- The frequency to check the success or failure of a specified condition.

Also, if you want to configure the wait to ignore exceptions such as <NoSuchElementException>, then you can add it to the Fluent Wait command syntax.

Below is a sample code which shows the implementation of Fluent Wait.

Wait wait = new FluentWait(driver)    
    .withTimeout(30, SECONDS)    
    .pollingEvery(5, SECONDS)   
    .ignoring(NoSuchElementException.class);

WebElement foo = wait.until(new Function() {    
    public WebElement apply(WebDriver driver) {    
        return driver.findElement(By.id("foo"));    
    }
});

Step by step analysis of the above sample code.

Step-1: Fluent Wait starts with capturing the start time to determine delay.

Step-2: Fluent Wait then checks the condition defined in the until() method.

Step-3: If the condition fails, Fluent Wait makes the application to wait as per the value set by the <pollingEvery(5, SECONDS)> method call. Here in this example, it’s 5 seconds.

Step-4: After the wait defined in Step 3 expires, start time is checked against the current time. If the difference of the wait start time (set in step-1) and the current time is less than the time set in <withTimeout(30, SECONDS)> method, then Step-2 will need to repeat.

The above steps will recur until either the timeout expires or the condition becomes true.

In the next section, we’ll see a summary of most used Fluent Wait methods which could be very useful in implementing Fluent Wait.

2- Important Methods of Webdriver Fluent Wait Commands.

2.1- Fluent Wait Command Methods.

2.1.1- Commonly used fluent wait methods.
Method Name               Syntax            Description
withTimeout
public FluentWait<T> withTimeout(long duration, java.util.concurrent.TimeUnit unit)

Parameters:

duration - The timeout duration.
unit - The unit of time.

Returns:

A self-reference.
Sets the wait for the condition to become true. The default timeout is FIVE_HUNDRED_MILLIS.
withMessage
public FluentWait<T> withMessage(java.lang.String message)

Parameters:

message - to be appended to default.

Returns:

A self-reference.
Sets the message which would appear after the timeout.
pollingEvery
public FluentWait<T> pollingEvery(long duration, java.util.concurrent.TimeUnit unit)

Parameters:

duration - The timeout duration.
unit - The unit of time.

Returns:

A self-reference.
Sets the frequency of condition should be evaluated. The default polling interval is FIVE_HUNDRED_MILLIS.
ignoring
public FluentWait<T> ignoring(java.lang.Class<? extends java.lang.Throwable> firstType, java.lang.Class<? extends java.lang.Throwable> secondType)

Parameters:

firstType - exception to ignore.
secondType - another exception to ignore.

Returns:

a self-reference.
Lists the exception that you want to skip when the timeouts.

 

2.1.2- Advanced fluent wait methods.
Method Name               Syntax            Description
until

 

public void until(com.google.common.base.Predicate<T> isTrue)

Parameters:

isTrue - The predicate to wait on.

Throws:

TimeoutException - If the timeout expires.
It’ll apply the instance’s input value to the given predicate until the timeout occurs or the predicate becomes true.
until

 

public<V>V until(com.google.common.base.Function<? super T,V> isTrue)

Specified by:

until in interface Wait<T>

Type Parameters:

V - The function's expected return type.

Parameters:

isTrue - the parameter to pass to the ExpectedCondition.

Returns:

The functions return value if the function returned something different from null or false before the timeout expired.

Throws:

TimeoutException- If the timeout expires.

It’ll apply the instance’s input value to the given function until one of the following conditions occurs:

  1. The function returns neither null nor false.
  2. The function throws an un-ignorable exception.
  3. The timeout expires.
  4. The current thread gets interrupted.

 

timeoutException

 

protected java.lang.RuntimeException timeoutException(java.lang.String message, java.lang.Throwable lastException)

Parameters:

message - The timeout message.
lastException - The last exception to be thrown and subsequently suppressed while waiting on a function.

Returns:

Nothing will ever be returned; this return type is only specified as a convenience.
Throws a timeout exception.

 

2.2- Summary of Fluent Wait Methods.

From the above table, you can see that <until()> is an overloaded function which takes two types of parameters.

1- A Function()
2- A Predicate()

In the next section, we’ll talk about these entities and give examples of Webdriver Fluent-Wait commands. But before you proceed, we recommend reading the below post. It’ll provide you step by step instructions to create a Selenium Webdriver project in Eclipse IDE. After going through this article, it would be easy for you to understand the sample code shown in the next section.

3- Fluent Wait command Examples with Sample Code.

Since the main logic of Fluent Wait revolves around a function and a predicate, so we’ll take up examples using these constructs. Also, we’ll give ready to use sample code so that you can use it directly in your projects.

3.1- Using Function() to Write Sample Code.

Package: com.google.common.base.Function

A Function is a general interface which requires the class to define the following method.

Function < WebDriver, Boolean > function = new Function < WebDriver, Boolean > () {

 public Boolean apply(WebDriver arg0) {
  return null;
 }

};

The above apply() method takes the Webdriver as an input argument and returns either true or false. Alternatively, we can derive this info from the below syntax:

Function <WebDriver, Boolean>.

It signifies that the first input parameter is the argument to the apply() method and the second indicates its return type. Also, you must note that without importing the <com.google.common.base.Function> package, your Fluent Wait code won’t compile instead will throw errors. So you would have to download the <com.google.common_1.0.0.201004262004.jar> file first. Then, by adding it as an external Jar, you’ll be able to run your code.

3.2- User Case Scenario and the HTML Code to Run Fluent Wait Command Sample.

Let’s now review the use case which we want to automate.

There is a simple button on the web page. The button gets highlighted in few seconds. We have to verify the color code of the highlighted text.

Below is the HTML code for the web page which we’ll use to demonstrate the given use case scenario.

You must save the HTML code in a file as <fluentWaitCommandDemoPage.html>. And then, you’ll need to add this file to your Selenium Webdriver project. In our samples, we’ll load this file to launch with the Firefox browser for running the tests.

3.2.1- HTML Test Page.
<html>
    <head>
        <script>
var timer1 = setInterval(dynamicColor, 2000);
var timer2 = 0;
function dynamicColor() {
	document.getElementById("dynamicColor").style.color="yellow";
	clearInterval(timer1);
	timer2 = setInterval(dynamicText, 2000);
} 
var counter1 = 0;
function dynamicText() {
	var mydiv = document.getElementById("dynamicText");
	var newElement = document.createElement('a');
	newElement.setAttribute('href',"http://www.goole.com/");
	newElement.setAttribute('id', "target");
	newElement.innerHTML = "dynamicText" + counter1;
	mydiv.appendChild(newElement);
	if(counter1 > 5) {
		clearInterval(timer2);
	}
	counter1 = counter1 + 1;
}
</script>
    </head>
    <body>
        <h1>Webdriver Commands Example.</h1>
        <p id="dynamicText"></p>
        <p>
            <button id="dynamicColor" style="color: white;">Dynamic Color</button>
        </p>
    </body>
</html>

 

Please note- If you have changed the location of this file (i.e. not adding it to the project), then please provide its correct path in the sample code before execution.

// Say, you have put the HTML file to a different location.
// Then, don't use the below two lines. Instead, use the code given next.
String workingDir = System.getProperty("user.dir");
driver.get(workingDir + "\\fluentWaitCommandDemoPage.html");

// Update HTML file path and use the below code.
driver.get("<Absolute Path of> fluentWaitCommandDemoPage.html");

 

3.2.2- HTML Test Page Live.

Probably when you would run the sample code, it’ll launch the HTML page. The page would look like the one given below at runtime.

Fluent Wait Command HTML Test Page

Fluent Wait Command HTML Test Page.

Below is the code implementing the apply() method for the above scenario. It will return false if the condition fails. And will return true if the condition becomes true. The apply() method will return false if the button is not highlighted (yellow) else it will return true.

3.3- Fluent Wait Command Sample Code Part -1 Using Function().

This code is fully functional. And you only need to copy/paste it to your project in eclipse.

package com.techbeamers.fluentwait;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.FluentWait;

import com.google.common.base.Function;

public class TestFunction {
	public static void main(String[] args) throws InterruptedException {

		WebDriver driver = new FirefoxDriver();
		String workingDir = System.getProperty("user.dir");
		driver.get(workingDir + "\\fluentWaitCommandDemoPage.html");

		FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);
		wait.pollingEvery(250, TimeUnit.MILLISECONDS);
		wait.withTimeout(2, TimeUnit.SECONDS);

		Function<WebDriver, Boolean> function = new Function<WebDriver, Boolean>() {
			public Boolean apply(WebDriver arg0) {
				WebElement element = arg0.findElement(By.id("dynamicColor"));
				String color = element.getCssValue("color");
				System.out.println("The button text has color :" + color);
				if (color.equals("rgba(255, 255, 0, 1)")) {
					return true;
				}
				return false;
			}
		};

		wait.until(function);
	}
}
3.3.1- Execution Summary.

After you run the above code, it’ll display the following output.

The button text has color :rgba(255, 255, 255, 1)
The button text has color :rgba(255, 255, 255, 1)
The button text has color :rgba(255, 255, 255, 1)
The button text has color :rgba(255, 255, 0, 1)

You can see that the function made four attempts to check the color of the button. And in the last attempt, it found the target color which is yellow. It’s a success case which would cause the wait condition to end.

 

3.4- Fluent Wait Command Sample Code – Part2.

You can also use a function to return objects in place of a Boolean value. In this case, the apply() method will return null till the time object is not available. Let’s take an example code. In the same HTML test page, we have a new object added dynamically after every few seconds. This object has an <id=”dynamicText”>. In this example, we will wait for this object using a fluent wait.

package com.techbeamers.fluentwait;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.FluentWait;

import com.google.common.base.Function;

public class CheckElement {
	public static void main(String[] args) throws InterruptedException {

		WebDriver driver = new FirefoxDriver();
		String workingDir = System.getProperty("user.dir");
		driver.get(workingDir + "\\fluentWaitCommandDemoPage.html");

		FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);
		wait.pollingEvery(250, TimeUnit.MILLISECONDS);
		wait.withTimeout(2, TimeUnit.MINUTES);
		wait.ignoring(NoSuchElementException.class); // We need to ignore this
														// exception.

		Function<WebDriver, WebElement> function = new Function<WebDriver, WebElement>() {
			public WebElement apply(WebDriver arg0) {
				System.out.println("Checking for the object!!");
				WebElement element = arg0.findElement(By.id("dynamicText"));
				if (element != null) {
					System.out.println("A new dynamic object is found.");
				}
				return element;
			}
		};

		wait.until(function);
	}
}
3.4.1- Execution Summary.
Checking for the object!!
A new dynamic object is found.

 

3.5- Fluent Wait Command Sample Code – Part3 Using Predicate.

A predicate is similar to a function. But it always returns a Boolean expression. You can use it in the following manner.

Predicate < WebDriver > predicate = new Predicate < WebDriver > () {

 public boolean apply(WebDriver arg0) {

  return false;
 }

};

Now see some real action in the example below.

3.5.1- Code for above scenario using Predicate is like this.
package com.techbeamers.fluentwait;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.FluentWait;

import com.google.common.base.Predicate;

public class PredicateTest {
	public static void main(String[] args) throws InterruptedException {

		WebDriver driver = new FirefoxDriver();
		String workingDir = System.getProperty("user.dir");
		driver.get(workingDir + "\\fluentWaitCommandDemoPage.html");

		FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);
		wait.pollingEvery(250, TimeUnit.MILLISECONDS);
		wait.withTimeout(2, TimeUnit.MINUTES);
		wait.ignoring(NoSuchElementException.class); // We need to ignore this
														// exception.

		Predicate<WebDriver> predicate = new Predicate<WebDriver>() {

			public boolean apply(WebDriver arg0) {
				WebElement element = arg0.findElement(By.id("dynamicColor"));
				String color = element.getCssValue("color");
				System.out.println("The button text has color :" + color);
				if (color.equals("rgba(255, 255, 0, 1)")) {
					return true;
				}
				return false;
			}
		};
		wait.until(predicate);
	}
}
3.5.2- Execution Summary.
The button text has color :rgba(255, 255, 255, 1)
The button text has color :rgba(255, 255, 255, 1)
The button text has color :rgba(255, 255, 255, 1)
The button text has color :rgba(255, 255, 0, 1)

Footnote.

We hope that the post “Selenium Webdriver Fluent Wait Command with Examples” would drive you on using the Fluent Wait in current projects. We have verified all the code used in this post is compilable and should run without any error.

If you have any query on the post or otherwise, then please don’t hesitate and write to us. We’ll try our best to respond as early as possible.

Best,

TechBeamers.

4 Comments

  1. jack chen Reply
    • Meenakshi Agarwal Reply
  2. shan Reply
    • Meenakshi Agarwal Reply