ExpectedConditions in Selenium
In this Selenium tutorial, you will learn how to use Expected Conditions in Selenium to fix timing-related issues due to the dynamic loading of WebElements.
Join the DZone community and get the full member experience.
Join For FreeThe majority of web products use AJAX (Asynchronous JavaScript and XML), where elements on the page are loaded at varying time intervals. This can lead to timing issues when automation testing is performed using the Selenium framework. What if a test is run on a WebElement that is not present in the DOM? The findElement function will raise ElementNotVisibleException.
Here are other scenarios that can cause issues in Selenium due to the dynamic loading of elements:
- WebElement (e.g. button) is visible but not clickable.
- WebElement (e.g. label) is present in the DOM, but a certain text should be present in the element’s values attribute.
- The title of the WebPage should consist of a case-sensitive substring and more.
The ideal way to overcome issues arising due to the dynamic loading of WebElements is by introducing Selenium waits in the test code implementation. Waits will provide the additional buffer time required to complete the element’s loading and perform the necessary operation on the same. Rather than waiting for a specified time duration (also called Implicit Wait), a wait is performed on a certain condition. These are called Expected Conditions in Selenium.
An explicit wait (for a maximum time duration) can be performed till a ‘certain condition’ (e.g. till the Element is not visible) is met. If the condition is not satisfied even after the max duration has elapsed, an appropriate exception is raised.
Being an automation test engineer, I have come across cases where explicit wait using Expected Conditions in Selenium has helped fix timing-related issues due to the dynamic loading of WebElements. In this Selenium tutorial, we look at how to use Expected Conditions in Selenium Java.
ExpectedConditions In Selenium WebDriver
Expected Conditions provided by Selenium WebDriver are used for performing Explicit Waits on a certain condition. The Selenium WebDriver waits for the specified condition to occur before it can proceed further with the execution. This provides the required wait time between the actions that have to be performed, e.g. locating the WebElement or other valid operation with the element.
Explicit Wait With ExpectedConditions in Selenium
In Implicit Wait, the DOM is polled by the Selenium WebDriver for a specified amount of time when a particular WebElement is not immediately available. Once Implicit Wait is set, it is available for the entire life of the WebDriver object.
On the other hand, Explicit Wait using ExpectedConditions in Selenium lets you wait for the occurrence of a specified condition before execution can proceed to the next step. If the condition is not met within the expected time duration, an appropriate exception is raised.
driver = new ChromeDriver();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
By elem_dynamic = By.id("dynamic-element");
wait.until(ExpectedConditions.presenceOfElementLocated(elem_dynamic));
In the above snippet demonstrating expected conditions in Selenium Java, the Selenium WebDriver waits for a maximum duration of 10 seconds until the WebElement with ID ‘dynamic element is found. The ExpectedCondition is invoked by the Selenium WebDriver every 500 ms until it returns success.
If the WebElement is available within 10 seconds (i.e. maximum wait duration), the ExpectedCondition returns true, and execution proceeds to the next step. A TimeoutException is thrown if the element is not present in the DOM even at the elapse of the maximum duration of 10 seconds.
Types of Expected Conditions In Selenium Java
Expected Conditions in Selenium WebDriver provide conditions that are frequently used for automating test scenarios for Selenium automation testing. Like other Selenium language bindings, Expected Conditions in Java provide ways through which you can realize Explicit Waits in the test code.
Here are the two major categories of ExpectedConditions in Selenium:
ExpectedCondition <WebElement>
As the name indicates, the locator of the WebElement is used as the parameter in the ExpectedCondition. Depending on the condition type, the explicit wait is performed until the expected condition is satisfied or the wait duration has elapsed.
If the expected condition is met, it returns the WebElement/list of WebElement/other information depending on the core implementation of the ExpectedCondition.
For example, the numberOfElementsToBeLessThan method in ExpectedConditions class (of org.openqa.selenium.support.ui.ExpectedConditions package) returns a List of WebElements if the number of WebElements located using the web locator (passed as the argument) is less than the expected number (also passed as an argument).
The elementToBeClickable method in Expected Conditions in Selenium Java returns a WebElement if the located element is clickable (i.e. it can be clicked). The appropriate Selenium locator for locating the WebElement is passed to the method.
ExpectedCondition <WebDriver>
This category of ExpectedCondition returns a WebDriver instance after the required operation is successfully performed.
For example, the frameToBeAvailableAndSwitchToIt method in Expected Conditions in Selenium Java switches the WebDriver to the specified frame that is located using the frameLocator (which is passed as the argument to the method). The frame can be located using the ID or Name web locators.
An exception is raised if the given frame is not available to switch to.
ExpectedCondition <Boolean>
The condition of the type Boolean takes a String parameter, and the wait is applied to the condition of the parameter. On successful execution of the condition, the Boolean value true is returned, whereas false is returned if the condition is not met.
For example, the textToBePresentInElementLocated method returns true when the WebElement located by the web locator (which is passed as a parameter to the method) contains the specified text.
ExpectedCondition <Alert>
This category of Expected Conditions in Selenium Java returns an alert if a window of type Alert is present on the page. Once the alert is present, the WebDriver switches to the Alert window. Post switching, various operations like Accept(), Dismiss(), sendKeys(), and getText() can be performed on the Alert Window.
The method returns Null if the Alert window is not available within the specified wait duration.
Commonly Used ExpectedConditions In Selenium Java
Now that we have covered the different types (or categories) of Expected Conditions in Selenium Java, let’s have a look at some of the widely used ExpectedConditions for realizing Explicit Waits:
elementToBeSelected Method
elementToBeSelected is an overloaded method that belongs to the ExpectedCondition <Boolean> category.
Method Category – ExpectedCondition <Boolean>
ExpectedCondition<Boolean>elementToBeSelected(finalBy locator)
It lets the WebDriver wait until the WebElement is selected using the specified locator. This method of Expected Conditions in Selenium Java takes a single parameter ‘locator’ used for locating the required element.
It returns true once the element is selected, else it returns false.
Syntax
static ExpectedCondition<Boolean> elementToBeSelected(final By locator)
ExpectedCondition<Boolean>elementToBeSelected(final WebElement element)
The WebElement to be selected is passed as a parameter to the ‘elementToBeSelected ’ method. The elementToBeSelected method in turn calls the elementSelectionStateToBe method with the WebElement and Boolean value ‘true’ as the parameters to it.
Syntax
ExpectedCondition<Boolean> elementToBeSelected(final WebElement element)
elementToBeClickable Method
elementToBeSelected method of Expected Conditions in Selenium Java, is an overloaded method that belongs to the ExpectedCondition <WebElement> category. This method waits till the WebElement is visible and enabled so that the click operation can be performed on it.
Method Category – ExpectedCondition <WebElement>
Here is the brief of the elementToBeClickable method:
ExpectedCondition<WebElement>elementToBeClickable(By locator)
The Selenium WebDriver waits till the element located using the specified web locator is visible and enabled so that the element can be clicked.
Syntax
ExpectedCondition<WebElement> elementToBeClickable(final By locator)
ExpectedCondition<WebElement<elementToBeClickable(WebElement element)
The Selenium WebDriver waits till the WebElement which is passed as the parameter is visible and enabled for it to be clicked.
Syntax
ExpectedCondition<WebElement> elementToBeClickable(final WebElement element)
presenceOfElementLocated Method
This method waits for the specified WebElement to be present on the DOM of the page. The presence of an element does not necessarily mean that the particular element is visible.
The method takes the parameter – locator for finding the element on the page. It returns the WebElement once it is located.
Method Category – ExpectedCondition <WebElement>
Syntax
ExpectedCondition<WebElement> presenceOfElementLocated(final By locator)
visibilityOfElementLocated Method
This method is used to check if the specified element is present in the DOM of the page, but it is also visible.
The method takes the parameter – locator for finding the element on the page. It returns the WebElement once it is located.
Method Category – ExpectedCondition <WebElement>
Syntax
ExpectedCondition<WebElement> visibilityOfElementLocated(final By locator)
titleIs Method
This method of Expected Conditions in Selenium Java checks whether the title of the current page matches the expected title. It returns true if the title matches the expected title.
It returns false if the titles do not match.
Method Category – ExpectedCondition <Boolean>
Syntax
ExpectedCondition<Boolean> titleIs(final String title)
titleContains Method
It checks whether the current page title or the title of a WebElement contains a particular substring in it. It returns true if the case-sensitive substring is present in the title.
Method Category – ExpectedCondition <Boolean>
Syntax
ExpectedCondition< Boolean> titleContains(final String title)
textToBePresentInElementLocated Method
This ExpectedCondition checks if the given text (passed as a parameter to the method) is present in the WebElement that matches the given web locator.
It returns the Boolean value true if the specified text is present in the element; else, it returns false.
Method Category – ExpectedCondition <Boolean>
Syntax
ExpectedCondition <Boolean> textToBePresentInElementLocated(final By locator, final String text)
textToBePresentInElementLocated Method
This ExpectedCondition checks if the given text (passed as a parameter to the method) is present in the WebElement that matches the given web locator.
It returns the Boolean value true if the specified text is present in the element; else, it returns false.
Method Category – ExpectedCondition <Boolean>
Syntax
ExpectedCondition <Boolean> textToBePresentInElementLocated(final By locator, final String text)
urlToBe Method
This ExpectedCondition checks whether the current page URL matches (or is the same as) the URL passed as a parameter to the urlToBe() method.
It returns true if the current page URL is the same as the expected URL (in the parameter); else, it returns false.
Method Category – ExpectedCondition <Boolean>
Syntax
ExpectedCondition<Boolean> urlToBe(final String url)
frameToBeAvailableAndSwitchToIt Method
The frameToBeAvailableAndSwitchToIt method of Expected Conditions in Selenium Java is used for checking if the given frame is available to switch to. Frames in Selenium can be identified using any one of the following approaches:
- By locator
- Frame index (Integer)
- Frame name (String)
- WebElement (located using an appropriate web locator)
In those lines, the frameToBeAvailableAndSwitchToIt method is an overloaded method that provides the option to check for a given frame using the above-listed options for locating Frames (and iFrames) on a page.
If the said Frame (or iFrame) is present on the page, this method triggers a driver.switchTo().frame operation so that focus is shifted to the frame.
Method Category – ExpectedCondition<WebDriver>
Here are the details of the frameToBeAvailableAndSwitchToIt method:
ExpectedCondition<WebDriver>frameToBeAvailableAndSwitchToIt (By locator)
The ExpectedCondition checks whether the given frame is available to switch to. The required frame is located using the web locator passed to the method.
On successful execution, it switches the given driver to the specified frame; else, it returns null.
Syntax
ExpectedCondition<WebDriver> frameToBeAvailableAndSwitchToIt(final By locator)
ExpectedCondition<WebDriver>frameToBeAvailableAndSwitchToIt(int frameLocator)
It checks whether the given frame can be switched to. The frame on the page is located using the specified frameindex (or frameLocator), which is of Integer type.
Syntax
ExpectedCondition<WebDriver> frameToBeAvailableAndSwitchToIt(final int frameLocator)
ExpectedCondition<WebDriver>frameToBeAvailableAndSwitchToIt (WebElement locator)
The frame to be switched to is located using the WebElement on which the findElement method is executed. On successful execution, it returns a WebDriver instance after switching to the frame is completed.
Syntax
ExpectedCondition<WebDriver> frameToBeAvailableAndSwitchToIt(final WebElement frameLocator)
ExpectedCondition<WebDriver>frameToBeAvailableAndSwitchToIt(String frameLocator)
The given frame is located using the Frame Name, which is passed as a parameter to the frameToBeAvailableAndSwitchToIt method.
If the frame with the specified name is present on the page, it switches the WebDriver to the specified frame. If the frame is not present, it returns null.
Syntax
ExpectedCondition<WebDriver> frameToBeAvailableAndSwitchToIt(final String frameLocator)
alertIsPresent Method
As the name indicates, this ExpectedCondition instructs the command if an Alert window is available on the page. Based on the category of Alert Window (i.e. Simple Alert, Prompt Alert, Confirmation Alert), appropriate actions have to be performed on the window.
If the Alert window is present, this method internally triggers driver.switchTo().alert() so that the focus is on the Alert window.
Method Category – ExpectedCondition <Alert>
Syntax
ExpectedCondition<Alert> alertIsPresent()
Examples : ExpectedConditions in Selenium Java
For demonstrating ExpectedConditions in Selenium Java, we create a TestNG project in IntelliJ named ExpectedCond. The project contains a package named org.expconditions which in turn consists of a class file named Test_ExpConditions.
The TestNG framework is used for the creation and maintenance of test scenarios in Selenium automation testing. For the implementation, we use Selenium 4 for Java language bindings. The dependency for Selenium 4 Java (Alpha-7) is downloaded from Maven central repository:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.0.0-alpha-7</version>
</dependency>
The testng.xml configuration file helps in organizing the tests. Shown below is the complete implementation of pom.xml and testng.xml.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.expconditions</groupId>
<artifactId>expcond</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.9.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.28</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.0.0-alpha-7</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-remote-driver</artifactId>
<version>4.0.0-alpha-7</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>4.0.0-alpha-7</version>
</dependency>
</dependencies>
<build>
<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Expected Conditions Demo">
<test verbose="2" preserve-order="true" name="Explicit Wait with Expected Conditions">
<classes>
<class name="org.expconditions.Test_ExpConditions">
</class>
</classes>
</test>
</suite>
All the tests are run on the cloud Selenium Grid by LambdaTest. To access the Selenium Grid, you should note the user name and access key from the LambdaTest profile page. The tests are executed on Chrome (latest version) + Windows 10 combination – capabilities are generated using the LambdaTest Capabilities Generator. All the tests are run on Selenium 4 Grid.
Since all the tests would be a part of the same file, the Remote WebDriver is instantiated in method [testSetUp()], which is implemented under the @BeforeClass annotation. A string array str_url contains the test URLs used for the tests mentioned in the subsequent sections. The WebDriver instance is freed once all the tests that demonstrate ExpectedConditions in Selenium are executed.
Here is the implementation of the methods under @BeforeClass and @AfterClass annotations.
package org.expconditions;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class Test_ExpConditions
{
/* protected static ChromeDriver driver; */
WebDriver driver = null;
public static String status = "passed";
String username = "user-name";
String access_key = "access-key";
String[] str_urlarr =
{
"https://phptravels.com/demo/",
"http://the-internet.herokuapp.com/javascript_alerts",
"http://the-internet.herokuapp.com/dynamic_content?with_content=static",
"https://phptravels.com/demo/",
"https://jqueryui.com/spinner/",
"https://lambdatest.github.io/sample-todo-app/"
};
@BeforeClass
public void testSetUp() throws MalformedURLException {
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("build", "[Java] Testing Expected Conditions with Selenium");
capabilities.setCapability("name", "[Java] Testing Expected Conditions with Selenium");
capabilities.setCapability("platformName", "Windows 10");
capabilities.setCapability("browserName", "Chrome");
capabilities.setCapability("browserVersion","latest");
capabilities.setCapability("tunnel",false);
capabilities.setCapability("network",true);
capabilities.setCapability("console",true);
capabilities.setCapability("visual",true);
driver = new RemoteWebDriver(new URL("http://" + username + ":" + access_key + "@hub.lambdatest.com/wd/hub"),
capabilities);
System.out.println("Started session");
}
@Test(description="Demo of ExpectedConditions.elementToBeClickable", enabled=true)
protected void test_elem_clickable() throws InterruptedException
{
/* Implementation goes here */
}
@Test(description="Demo of ExpectedConditions.alertIsPresent", enabled=true)
protected void test_alert_present() throws InterruptedException
{
/* Implementation goes here */
}
@Test(description="Demo of ExpectedConditions.textToBePresentInElementLocated", enabled=true)
protected void test_text_present() throws InterruptedException
{
/* Implementation goes here */
}
@Test(description="Demo of ExpectedConditions.visibilityOfElementLocated", enabled=true)
protected void test_elem_visibility() throws InterruptedException
{
/* Implementation goes here */
}
@Test(description="Demo of ExpectedConditions.frameToBeAvailableAndSwitchToIt", enabled=true)
protected void test_available_frame() throws InterruptedException
{
/* Implementation goes here */
}
@Test(description="Demo of ExpectedConditions.elementToBeSelected", enabled=true)
protected void test_elem_selected() throws InterruptedException
{
/* Implementation goes here */
}
@AfterClass
public void tearDown()
{
if (driver != null)
{
driver.quit();
}
}
}
Let’s look at all respective tests where we demonstrate a few of the widely-used ExpectedConditions in Selenium.
elementToBeClickable ExpectedCondition In Selenium Java
Test Scenario
- Go to https://phptravels.com/demo/
- Locate the “Google Play” button
- Wait for the button to be clickable
- Click on the button
- Assert if the page URL (that opens up due to clicking the Google Play button) does not match the expected URL
Implementation
@Test(description="Demo of ExpectedConditions.elementToBeClickable", enabled=true)
protected void test_elem_clickable() throws InterruptedException
{
driver.navigate().to(str_urlarr[0]);
driver.manage().window().maximize();
String parentWindowHandle = driver.getWindowHandle();
/* Click on the Link */
By elem_gplay_locator = By.cssSelector(".fa-google");
((JavascriptExecutor)driver).executeScript("window.scrollBy(0,600)", "");
/* Selenium Java 3.141.59 */
/* WebDriverWait wait = new WebDriverWait(web_driver, 5); */
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
WebElement elem_gplay_btn = wait.until(ExpectedConditions.elementToBeClickable(elem_gplay_locator));
elem_gplay_btn.click();
/* Check if the link is clicked by comparing the window title */
Set<String> allWindowHandles = driver.getWindowHandles();
Iterator<String> iterator = allWindowHandles.iterator();
while(iterator.hasNext())
{
String chld_window = iterator.next();
if (!parentWindowHandle.equalsIgnoreCase(chld_window))
{
driver.switchTo().window(chld_window);
System.out.println("Switched to the window where Google Store is open");
}
}
Assert.assertEquals(driver.getCurrentUrl(), "https://play.google.com/store/apps/details?id=com.phptravelsnative");
Thread.sleep(3000);
System.out.println("Demo of ExpectedConditions.elementToBeClickable successful\n");
}
Code Walkthrough
1- Locate the “Get It On Google Play” button on https://phptravels.com/demo/.
By elem_gplay_locator = By.cssSelector(".fa-google");
2- Perform a vertical scroll by 600 pixels using the “window.scroll” command provided by JavascriptExecutor.
((JavascriptExecutor)driver).executeScript("window.scrollBy(0,600)", "");
3- Create a WebDriverWait (or Explicit Wait) with a wait duration of 5 seconds.
Since we are using selenium-java (4.0.0-alpha-7), WebDriver wait is created as below:
Selenium 4 (for Java)
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
If selenium-java (3.141.59) is used, wait (of 5 seconds) is created in the following manner:
Selenium 3 (for Java)
WebDriverWait wait = new WebDriverWait(web_driver, 5);
Since we are using Selenium 4 for Java, we have used the former approach for creating WebDriverWait (or Explicit Wait).
/* Selenium Java 3.141.59 */
/* WebDriverWait wait = new WebDriverWait(web_driver, 5); */
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
4- The WebDriver does an Explicit Wait for 5 seconds until the requisite element is clickable (i.e. it can be clicked). If the element is not found, an exception is raised; else, the execution moves to the next step, where we click the button.
WebElement elem_gplay_btn = wait.until(ExpectedConditions.elementToBeClickable(elem_gplay_locator));
elem_gplay_btn.click();
5- Since the link (after the click) opens in a new window (or tab), we switch to the new window using its window handle.
Set<String> allWindowHandles = driver.getWindowHandles();
Iterator<String> iterator = allWindowHandles.iterator();
while(iterator.hasNext())
{
String chld_window = iterator.next();
if (!parentWindowHandle.equalsIgnoreCase(chld_window))
{
driver.switchTo().window(chld_window);
System.out.println("Switched to the window where Google Store is open");
}
}
6- Assert if the current URL (in the new window) does not match with the expected URL.
Assert.assertEquals(driver.getCurrentUrl(), "https://play.google.com/store/apps/details?id=com.phptravelsnative");
Execution
As seen in the execution snapshot obtained from the Automation Dashboard on LambdaTest, the test was executed successfully.
alertIsPresent ExpectedCondition In Selenium Java
Test Scenario
- Go to http://the-internet.herokuapp.com/javascript_alerts.
- Locate the “Click for JS Alert” button.
- Click the button to invoke the alert window.
- Wait till the alert window is present.
- Accept the alert.
Implementation
@Test(description="Demo of ExpectedConditions.alertIsPresent", enabled=true)
protected void test_alert_present() throws InterruptedException
{
driver.navigate().to(str_urlarr[1]);
driver.manage().window().maximize();
WebElement elem_alert_btn = driver.findElement(By.xpath("//button[.='Click for JS Alert']"));
elem_alert_btn.click();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
Alert bAlertPresent = wait.until(ExpectedConditions.alertIsPresent());
System.out.println("Alert window is now present");
bAlertPresent.accept();
Thread.sleep(2000);
System.out.println("Demo of ExpectedConditions.alertIsPresent successful\n");
}
Code Walkthrough
- Go to the test URL http://the-internet.herokuapp.com/javascript_alerts and locate the button ‘Click on JS Alert’ using the findElement method in Selenium. The element is located using the XPath property.
WebElement elem_alert_btn = driver.findElement(By.xpath("//button[.='Click for JS Alert']"));
2- Click on the button to invoke the Alert.
elem_alert_btn.click();
3- Do an Explicit Wait of 5 seconds until the ExpectedCondition alertIsPresent is met (or satisfied).
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
Alert bAlertPresent = wait.until(ExpectedConditions.alertIsPresent());
4- If the alert is not present, an exception is thrown; else, the WebDriver switches to the Alert window. Accept the alert using the accept() method.
bAlertPresent.accept();
Execution
As seen below, the alert window is present, and the test executes successfully.
textToBePresentInElementLocated ExpectedCondition In Selenium Java
Test Scenario
- Go to http://the-internet.herokuapp.com/dynamic_content?with_content=static. The page contains dynamic content, i.e. content changes at every refresh.
- Go to the element (third text area) where the content dynamic is available.
- Check for the presence of the text “laudantium” in the text area specified in step(2). If the text is not found, refresh the page and again perform the search operation.
- Print the contents in the text area where the presence of the required text is detected.
Implementation
@Test(description="Demo of ExpectedConditions.textToBePresentInElementLocated", enabled=true)
protected void test_text_present() throws InterruptedException
{
String stText = "laudantium";
Integer counter = 1;
Boolean bTextPresent = false;
driver.navigate().to(str_urlarr[2]);
driver.manage().window().maximize();
By elem_dynam_con_locator = By.cssSelector("#content.large-10 > div:nth-of-type(3) > .large-10");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
while (!bTextPresent)
{
try
{
System.out.println(driver.findElement(elem_dynam_con_locator).getText());
bTextPresent = wait.until(ExpectedConditions.textToBePresentInElementLocated(elem_dynam_con_locator, stText));
if (bTextPresent)
{
System.out.println("The text " + stText + " is present");
break;
}
}
catch (TimeoutException e)
{
/* e.printStackTrace(); */
counter++;
System.out.println("Presence: " + bTextPresent + " Counter " + counter);
driver.navigate().refresh();
continue;
}
}
System.out.println("ExpectedConditions.textToBePresentInElement successful with text " + stText + " found after " + counter + " attempts\n");
}
Code Walkthrough
- Go to the test URL. As seen below, the text in the marked areas changes on every page reloads, whereas content in the remaining areas of the page remains constant (or is static even after the page is refreshed).
2- Create a variable of type “By” where we use the cssSelector property for locating the WebElement. Instead of the Inspect in Chrome, we made use of the POM Builder extension in Chrome to get the cssSelector of the required element.
By elem_dynam_con_locator = By.cssSelector("#content.large-10 > div:nth-of-type(3) > .large-10");
3- Create an Explicit Wait (or WebDriverWait) of 5 seconds.
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
4- In a While loop, the text in the element is compared with the expected text. If the text is not found (after a maximum duration of 5 seconds), a TimeoutException is thrown. In the catch (for TimeoutException), we increment the search counter and refresh the page using the navigate().refresh() method offered by Selenium.
try
{
.....................
.....................
.....................
bTextPresent = wait.until(ExpectedConditions.textToBePresentInElementLocated(elem_dynam_con_locator, stText));
catch (TimeoutException e)
{
/* e.printStackTrace(); */
counter++;
driver.navigate().refresh();
continue;
}
If the text is present, ExpectedCondition textToBePresentInElementLocated returns true.
bTextPresent = wait.until(ExpectedConditions.textToBePresentInElementLocated(elem_dynam_con_locator, stText));
Here is the complete implementation of Step (4).
while (!bTextPresent)
{
try
{
System.out.println(driver.findElement(elem_dynam_con_locator).getText());
bTextPresent = wait.until(ExpectedConditions.textToBePresentInElementLocated(elem_dynam_con_locator, stText));
if (bTextPresent)
{
System.out.println("The text " + stText + " is present");
break;
}
}
catch (TimeoutException e)
{
/* e.printStackTrace(); */
counter++;
driver.navigate().refresh();
continue;
}
}
Execution
If the search term is not present in the required WebElement, an exception is thrown and the counter is incremented. As seen in the execution screenshot, the search term “laudantium” is located after 11 attempts.
visibilityOfElementLocated ExpectedCondition In Selenium Java
Test Scenario
- Go to https://phptravels.com/demo/.
- Locate the link (or element) with the title “Affiliate”.
- Perform a vertical scroll till the ExpectedCondition visibilityOfElementLocated returns a WebElement mentioned in Step(2).
- Click on the WebElement and assert if the current page title does not match the required title.
Implementation
@Test(description="Demo of ExpectedConditions.visibilityOfElementLocated", enabled=true)
protected void test_elem_visibility() throws InterruptedException
{
WebElement elem_affiliate_link = null;
driver.navigate().to(str_urlarr[3]);
driver.manage().window().maximize();
By elem_affiliate_locator = By.cssSelector("a[title='Affiliate']");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
while (elem_affiliate_link != null)
{
elem_affiliate_link = wait.until(ExpectedConditions.visibilityOfElementLocated(elem_affiliate_locator));
if (elem_affiliate_link == null)
{
((JavascriptExecutor) driver).executeScript("window.scrollBy(0,100)", "");
/* Only for checking if the scroll goes through */
Thread.sleep(1000);
}
}
Thread.sleep(3000);
/* We have found the element that points to the Affiliate Link */
driver.findElement(elem_affiliate_locator).click();
Assert.assertEquals(driver.getTitle(), "Become an Affiliate Partner - PHPTRAVELS");
System.out.println("ExpectedConditions.visibilityOfElementLocated test successful\n");
}
Code Walkthrough
- On the test URL, create a variable of type ‘By’ and use the cssSelector property in it.
By elem_affiliate_locator = By.cssSelector("a[title='Affiliate']");
2- Create an Explicit Wait of 5 seconds.
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
3- In a while loop, perform a check if the ExpectedCondition visibilityOfElementLocated returns a valid WebElement. If the condition returns Null (i.e. the element is not present on the page or the Wait times out), perform a vertical scroll by 100 pixels and check for the presence of the required WebElement (i.e. Affiliate).
while (elem_affiliate_link != null)
{
elem_affiliate_link = wait.until(ExpectedConditions.visibilityOfElementLocated(elem_affiliate_locator));
if (elem_affiliate_link == null)
{
((JavascriptExecutor) driver).executeScript("window.scrollBy(0,100)", "");
/* Only for checking if the scroll goes through */
Thread.sleep(1000);
}
}
4- Perform a click operation on the Selenium WebElement located using ExpectedConditions.visibilityOfElementLocated (element_locator).
driver.findElement(elem_affiliate_locator).click();
5- Assert if the title of the current page does not match with the expected title.
Assert.assertEquals(driver.getTitle(), "Become an Affiliate Partner - PHPTRAVELS");
Execution
As shown below, the ‘affiliate link’ on the test URL is opened successfully.
frameToBeAvailableAndSwitchToIt ExpectedCondition In Selenium Java
Test Scenario
- Go to https://jqueryui.com/spinner/.
- Find the Elements with TagName “iframe” for checking the number of frames present on the web page.
- Perform a vertical scroll by 200 pixels till the intended frame is available.
- Switch to the intended frame using the ExpectedConditions.frameToBeAvailableAndSwitchToIt(frame_locator) method.
- Click on a button which is located inside the frame.
Implementation
@Test(description="Demo of ExpectedConditions.frameToBeAvailableAndSwitchToIt", enabled=true)
protected void test_available_frame() throws InterruptedException
{
driver.navigate().to(str_urlarr[4]);
driver.manage().window().maximize();
/* To check how many frames are available on the page */
List<WebElement> iframeElements = driver.findElements(By.tagName("iframe"));
System.out.println("The total number of iframes are " + iframeElements.size());
/* Scroll where the iFrame is present */
((JavascriptExecutor)driver).executeScript("window.scrollBy(0,200)", "");
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
By frame_locator = By.xpath("//*[@id=\"content\"]/iframe");
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(frame_locator));
Thread.sleep(3000);
/* Click the button inside the iFrame */
By elem_set_value = By.xpath("//button[@id='setvalue']");
wait.until(ExpectedConditions.presenceOfElementLocated(elem_set_value)).click();
Thread.sleep(2000);
System.out.println("ExpectedConditions.frameToBeAvailableAndSwitchToIt test successful\n");
}
Code Walkthrough
1- After navigating to the test URL https://jqueryui.com/spinner/, we find the total number of iFrames using findElements method with tagName ‘iframe’.
List<WebElement> iframeElements = driver.findElements(By.tagName("iframe"));
System.out.println("The total number of iframes are " + iframeElements.size());
2- Do a vertical scroll of 200 pixels using “window.scrollBy” with the executeScript method of JavascriptExecutor.
((JavascriptExecutor)driver).executeScript("window.scrollBy(0,200)", "");
3- Use WebDriverWait with a duration set to 5 seconds for creating an explicit wait.
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
4- The By class is instantiated so that the WebElement can be located using the findElement method in Selenium.
By frame_locator = By.xpath("//*[@id=\"content\"]/iframe");
5- The required frame is located using the web locator declared in step (4), and the frameToBeAvailableAndSwitchToIt method of Expected Conditions in Selenium Java switches to the intended frame. If the frame is not present on the page, the method returns null.
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(frame_locator));
6- Click on the ‘setValue’ button, which is located inside the frame.
By elem_set_value = By.xpath("//button[@id='setvalue']");
7- The presenceOfElementLocated method of Expected Conditions in Selenium Java is used for detecting the presence of the WebElement with the web locator defined in step (6). The click operation is performed on the button.
wait.until(ExpectedConditions.presenceOfElementLocated(elem_set_value)).click();
Execution
The execution snapshot obtained from the Automation Dashboard indicates that the test was executed successfully.
elementToBeSelected ExpectedCondition In Selenium Java
Test Scenario
- Go to https://lambdatest.github.io/sample-todo-app/.
- Locate the elements with the names “li1” and “li2”.
- Click (or enable) the elements located in step (2).
- Wait until the elements – “li1” and “li2” are selected (or enabled).
- Wait till the element with the name “li3” is selected.
- The test is passed if a Timeout Exception is thrown for element “li3”.
Implementation
@Test(description="Demo of ExpectedConditions.elementToBeSelected", enabled=true)
protected void test_elem_selected() throws InterruptedException
{
driver.navigate().to(str_urlarr[5]);
driver.manage().window().maximize();
WebElement elem_li1 = driver.findElement(By.name("li1"));
WebElement elem_li2 = driver.findElement(By.name("li2"));
elem_li1.click();
Thread.sleep(2000);
elem_li2.click();
Thread.sleep(2000);
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
wait.until(ExpectedConditions.elementToBeSelected(elem_li1));
wait.until(ExpectedConditions.elementToBeSelected(By.name("li2")));
try
{
/* wait for the element li3 to be selected */
wait.until(ExpectedConditions.elementToBeSelected(By.name("li3")));
}
catch (TimeoutException e)
{
e.printStackTrace();
System.out.println("Pass - Elem li3 is not selected");
}
System.out.println("ExpectedConditions.elementToBeSelected test successful\n");
}
Code Walkthrough
1- The findElement method in Selenium automation testing is used for locating the WebElements with the name “li1” and “li2”.
WebElement elem_li1 = driver.findElement(By.name("li1"));
WebElement elem_li2 = driver.findElement(By.name("li2"));
2- The elements are “selected” (or enabled) using the click method.
elem_li1.click();
Thread.sleep(2000);
elem_li2.click();
Thread.sleep(2000);
3- The elementToBeSelected method of Expected Conditions in Selenium Java is used for checking whether the elements “li1” and “li2” are selected. The maximum wait duration is set to 5 seconds.
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
wait.until(ExpectedConditions.elementToBeSelected(elem_li1));
wait.until(ExpectedConditions.elementToBeSelected(By.name("li2")));
4- The elementToBeSelected method is used for the element with name “li3”. After 5 seconds (maximum wait duration), ExpectedCondtions results in a Timeout Exception.
try
{
/* wait for the element li3 to be selected */
wait.until(ExpectedConditions.elementToBeSelected(By.name("li3")));
}
catch (TimeoutException e)
{
e.printStackTrace();
System.out.println("Pass - Elem li3 is not selected");
}
Execution
As expected, the test results in a Timeout Exception for elements with name “li3”.
Custom ExpectedConditions In Selenium
There are scenarios where you would want to combine multiple conditions into one and trigger the same in the test case. Consider a case where the test looks for the visibility of the element and post the visibility; it checks whether the element is clickable. This can be achieved by creating a custom ExpectedCondition’ in Selenium.
Custom ExpectedCondition is a class that:
- Implements the ExpectedCondition Interface (e.g. ExpectedCondition<WebElement>, ExpectedCondition<Boolean>, etc.)
- Has a constructor with parameters of the ExpectedCondition (Optional)
- Overrides the apply method using the @Override annotation in Java
Here is a sample implementation of a custom ExpectedCondition in Selenium Java:
class CustomElemLocated implements ExpectedCondition<WebElement>
{
By some_locator = By.cssSelector("some_css_locator");
WebElement elem_some_webelement;
@Override
public WebElement apply(WebDriver driver)
{
elem_some_webelement = driver.findElement(some_locator);
return elem_some_webelement;
}
}
Let’s look at how to create custom ExpectedCondition in Selenium Java by automating the following test scenario:
Test Scenario
- Go to https://phptravels.com/demo/.
- Locate the link (or element) with the title “Affiliate”.
- Click on the WebElement and assert if the current page title and URL do not match the required title & URL.
Implementation
We created a new file named Test_customconditions under the package org.expconditions. This is how the project and testng.xml looks like when the new file is created:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Expected Conditions Demo">
<test verbose="2" preserve-order="true" name="Explicit Wait with Expected Conditions">
<classes>
<class name="org.expconditions.Test_customconditions">
</class>
</classes>
</test>
</suite>
Implementation
package org.expconditions;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.*;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
public class Test_customconditions
{
WebDriver driver = null;
public static String status = "passed";
String username = "user-name";
String access_key = "access-key";
String testURL = "https://phptravels.com/demo/";
String testURLTitle = "Demo Script Test drive - PHPTRAVELS";
String affLinkURL = "https://phptravels.com/affiliate/";
String affLinkTitle = "Become an Affiliate Partner - PHPTRAVELS";
@BeforeClass
public void testSetUp() throws MalformedURLException {
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("build", "[Java] Testing Custom Expected Conditions with Selenium");
capabilities.setCapability("name", "[Java] Testing Custom Expected Conditions with Selenium");
capabilities.setCapability("platformName", "Windows 10");
capabilities.setCapability("browserName", "Chrome");
capabilities.setCapability("browserVersion","latest");
capabilities.setCapability("tunnel",false);
capabilities.setCapability("network",true);
capabilities.setCapability("console",true);
capabilities.setCapability("visual",true);
driver = new RemoteWebDriver(new URL("http://" + username + ":" + access_key + "@hub.lambdatest.com/wd/hub"),
capabilities);
System.out.println("Started session");
}
@AfterClass
public void tearDown()
{
if (driver != null)
{
driver.quit();
}
}
@Test(description="Demo of Custom ExpectedConditions in Selenium")
public void test_elem_visibility() throws InterruptedException
{
WebElement elem_affiliate_link = null;
driver.get(testURL);
Thread.sleep(5000);
/* Selenium Java 3.141.59 */
/* WebDriverWait wait = new WebDriverWait(web_driver, 5); */
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
if (((boolean) wait.until(new TestURLLoaded(testURL, testURLTitle))) == false)
{
throw new RuntimeException("PHP demo page is not displayed");
}
elem_affiliate_link = wait.until(new ElementLocated());
while ( elem_affiliate_link == null)
{
((JavascriptExecutor)driver).executeScript("window.scrollBy(0,100)", "");
elem_affiliate_link = wait.until(new ElementLocated());
}
/* Affiliate Link is visible */
if (elem_affiliate_link != null)
{
elem_affiliate_link.click();
Thread.sleep(2000);
if (((boolean) (wait.until(new TestURLLoaded(affLinkURL, affLinkTitle))) == false))
{
throw new RuntimeException("Affiliate link page is not displayed");
}
}
System.out.println("Demo of Custom ExpectedConditions in Selenium is successful\n");
}
}
/*
Custom ExpectedCondition function to check whether the Page Title & Page URL match
with the expected Page Title and Page URL
*/
class TestURLLoaded implements ExpectedCondition<Boolean>
{
String expTitle;
String expURL;
public TestURLLoaded(String expURL, String expTitle)
{
this.expTitle = expTitle;
this.expURL = expURL;
}
@Override
public Boolean apply(WebDriver driver)
{
Boolean bURL = false, bTitle = false;
bURL = driver.getCurrentUrl().contains(expURL);
bTitle = driver.getTitle().contains(expTitle);
return bTitle && bURL;
}
}
/*
Custom ExpectedCondition function to check whether the Affiliate Link Title & Page URL match
with the expected Page Title and Page URL
*/
class ElementLocated implements ExpectedCondition<WebElement>
{
By elem_affiliate_locator = By.cssSelector("a[title='Affiliate']");
WebElement elem_affiliate_link;
@Override
public WebElement apply(WebDriver driver)
{
elem_affiliate_link = driver.findElement(elem_affiliate_locator);
return elem_affiliate_link;
}
}
Code Walkthrough
We first use a custom ExpectedCondition that checks whether the URL and page title are inline with what is expected in the test. The class TestURLLoaded implements ExpectedCondition<Boolean> and overrides the apply method.
The apply method returns True if the Page title and Page URL are correct else it returns false.
class TestURLLoaded implements ExpectedCondition<Boolean>
{
String expTitle;
String expURL;
public TestURLLoaded(String expURL, String expTitle)
{
this.expTitle = expTitle;
this.expURL = expURL;
}
@Override
public Boolean apply(WebDriver driver)
{
Boolean bURL = false, bTitle = false;
bURL = driver.getCurrentUrl().contains(expURL);
bTitle = driver.getTitle().contains(expTitle);
return bTitle && bURL;
}
}
In the test code, we wait for a duration of 10 seconds on the custom condition implemented earlier.
@Test(description="Demo of Custom ExpectedConditions in Selenium")
public void test_elem_visibility() throws InterruptedException
{
WebElement elem_affiliate_link = null;
driver.get(testURL);
Thread.sleep(5000);
/* Selenium Java 3.141.59 */
/* WebDriverWait wait = new WebDriverWait(web_driver, 5); */
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
if (((boolean) wait.until(new TestURLLoaded(testURL, testURLTitle))) == false)
{
throw new RuntimeException("PHP demo page is not displayed");
}
....................................
....................................
....................................
}
The WebDriver waits for a maximum of 10 seconds until (((boolean) wait.until(new TestURLLoaded(testURL, testURLTitle)) returns either true or false. If the custom ExpectedCondition returns false (i.e. exception is raised), it means that the URL and Page titles are not as expected in the test.
A value of true means that we can proceed with the next step in the test scenario (i.e. locating the Affiliate link and clicking on the same).
The class ElementLocated is a custom condition class that implements ExpectedCondition<WebElement> interface.
class ElementLocated implements ExpectedCondition<WebElement>
{
By elem_affiliate_locator = By.cssSelector("a[title='Affiliate']");
WebElement elem_affiliate_link;
@Override
public WebElement apply(WebDriver driver)
{
elem_affiliate_link = driver.findElement(elem_affiliate_locator);
return elem_affiliate_link;
}
}
In the apply method, we locate the WebElement (i.e. Affiliate link) using the cssSelector locator and return the same for usage in the test code.
@Override
public WebElement apply(WebDriver driver)
{
elem_affiliate_link = driver.findElement(elem_affiliate_locator);
return elem_affiliate_link;
}
In the test case, a vertical scroll by 100 pixels is performed till the custom ExpectedCondition returns true (i.e. the required WebElement is located).
@Test(description="Demo of Custom ExpectedConditions in Selenium")
public void test_elem_visibility() throws InterruptedException
{
WebElement elem_affiliate_link = null;
......................
......................
while ( elem_affiliate_link == null)
{
((JavascriptExecutor)driver).executeScript("window.scrollBy(0,100)", "");
elem_affiliate_link = wait.until(new ElementLocated());
}
......................
......................
}
@Test(description="Demo of Custom ExpectedConditions in Selenium")
public void test_elem_visibility() throws InterruptedException
{
.....................
.....................
.....................
/* Affiliate Link is visible */
if (elem_affiliate_link != null)
{
elem_affiliate_link.click();
Thread.sleep(2000);
if (((boolean) (wait.until(new TestURLLoaded(affLinkURL, affLinkTitle))) == false))
{
throw new RuntimeException("Affiliate link page is not displayed");
}
}
.....................
.....................
}
Execution
As seen in the execution snapshot obtained from the automation dashboard on LambdaTest, the affiliate link on the test page was located, and the click operation on the link was successful:
The Condition Was as Expected
Expected Conditions are used for realizing Explicit Waits in Selenium. It is advantageous compared to Implicit Wait, where the wait is performed for the entire ‘wait’ duration even if the WebElement was located much earlier than the total duration. ExpectedCondition <Boolean>, ExpectedCondition <WebDriver>, ExpectedCondition <WebElement>, and ExpectedCondition <Alert> are the four major categories of ExpectedConditions in Selenium Java.
Custom ExpectedConditions in Selenium automation testing are useful when you want to combine different conditions to achieve a specific task. Custom ExpectedCondition implements the ExpectedCondition interface and overrides the apply method. To summarize, explicit waits with ExpectedConditions have a huge upper hand over Implicit Waits and should be preferred wherever applicable in the test implementation.
Published at DZone with permission of Himanshu Sheth. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments