Sometimes, built-in wait conditions are not enough. Custom ExpectedCondition lets you wait for exactly what you need in your test.
Custom ExpectedCondition in Selenium Java
ExpectedCondition<T> condition = new ExpectedCondition<T>() {
public T apply(WebDriver driver) {
// your custom logic here
return result != null ? result : null;
}
};The apply method returns a value when the condition is met, or null if not yet met.
You can use lambda expressions in Java 8+ for shorter syntax.
ExpectedCondition<Boolean> textToBePresent = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return driver.findElement(By.id("message")).getText().contains("Success");
}
};ExpectedCondition<WebElement> elementHasClass = driver -> {
WebElement el = driver.findElement(By.id("myElement"));
String classes = el.getAttribute("class");
return classes != null && classes.contains("active") ? el : null;
};This test opens example.com and waits up to 10 seconds for the page title to contain 'Example Domain' using a custom ExpectedCondition. It prints true if the condition is met.
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.ExpectedCondition; import org.openqa.selenium.support.ui.WebDriverWait; public class CustomExpectedConditionExample { public static void main(String[] args) { System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver"); WebDriver driver = new ChromeDriver(); try { driver.get("https://example.com"); ExpectedCondition<Boolean> waitForTitleContainsExample = new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver d) { return d.getTitle().contains("Example Domain"); } }; WebDriverWait wait = new WebDriverWait(driver, 10); boolean titleIsCorrect = wait.until(waitForTitleContainsExample); System.out.println("Title contains 'Example Domain': " + titleIsCorrect); } finally { driver.quit(); } } }
Always return null from apply() if the condition is not met yet.
Use WebDriverWait with your custom ExpectedCondition to wait smartly.
Custom ExpectedConditions improve test stability by waiting for exactly what you need.
Custom ExpectedCondition lets you create your own wait logic.
Use apply() method to check condition and return result or null.
Combine with WebDriverWait to pause test until condition is true.
Practice
Custom ExpectedCondition in Selenium Java?Solution
Step 1: Understand the role of ExpectedCondition
ExpectedCondition defines a condition that WebDriverWait checks repeatedly until it returns a non-null value or true.Step 2: Purpose of Custom ExpectedCondition
Creating a custom one allows you to specify your own logic for waiting, beyond built-in conditions.Final Answer:
To define a specific condition that WebDriverWait will wait for before proceeding -> Option DQuick Check:
Custom ExpectedCondition = Custom wait logic [OK]
- Thinking it replaces WebDriverWait
- Assuming it speeds up tests by skipping waits
- Confusing it with reporting features
Solution
Step 1: Recall ExpectedCondition interface
The ExpectedCondition interface requires implementing theapplymethod that takes a WebDriver and returns a result or null.Step 2: Identify correct method name
Onlyapply(WebDriver driver)is the correct method signature for custom conditions.Final Answer:
apply(WebDriver driver) -> Option AQuick Check:
Custom ExpectedCondition method = apply() [OK]
- Using wrong method names like waitForCondition or execute
- Confusing with WebElement methods
- Missing the WebDriver parameter
ExpectedCondition<Boolean> condition = driver -> {
WebElement el = driver.findElement(By.id("status"));
return el.getText().equals("Ready") ? true : null;
};
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
boolean result = wait.until(condition);Solution
Step 1: Analyze the condition logic
The condition returns true if the element's text equals "Ready", otherwise null.Step 2: Understand WebDriverWait behavior
WebDriverWait waits until the condition returns a non-null, true value. Since text is "Ready", condition returns true immediately.Final Answer:
The wait will pass and result will be true -> Option BQuick Check:
Condition true means wait passes [OK]
- Thinking null return means pass
- Assuming wait throws error on true
- Confusing null with false
ExpectedCondition<Boolean> condition = driver -> {
WebElement el = driver.findElement(By.id("submit"));
if(el.isDisplayed()) {
return true;
} else {
return false;
}
};Solution
Step 1: Understand ExpectedCondition return rules
ExpectedCondition should return null to continue waiting, true to stop waiting successfully.Step 2: Analyze the code's return values
Returning false causes wait.until to stop waiting and throw TimeoutException immediately, which is not desired.Final Answer:
Returning false instead of null causes wait.until to stop waiting prematurely -> Option CQuick Check:
Return null to keep waiting, not false [OK]
- Returning false instead of null to continue wait
- Assuming lambda is invalid
- Ignoring exception handling
Solution
Step 1: Understand the requirement
Wait until at least 3 elements with class 'item' are visible (isDisplayed() true).Step 2: Analyze each option
ExpectedCondition<Boolean> condition = driver -> { List<WebElement> items = driver.findElements(By.className("item")); long visibleCount = items.stream().filter(WebElement::isDisplayed).count(); return visibleCount >= 3 ? true : null; }; counts visible elements and returns true if count >= 3, else null to keep waiting. This matches requirement and wait logic.
ExpectedCondition<Boolean> condition = driver -> { List<WebElement> items = driver.findElements(By.className("item")); int count = 0; for(WebElement item : items) { if(item.isDisplayed()) count++; } return count > 3 ? true : false; }; returns false if count is not > 3, which stops wait prematurely.
ExpectedCondition<Boolean> condition = driver -> { List<WebElement> items = driver.findElements(By.className("item")); return items.size() >= 3; }; checks total size, ignoring visibility.
ExpectedCondition<Boolean> condition = driver -> { List<WebElement> items = driver.findElements(By.className("item")); return items.stream().allMatch(WebElement::isDisplayed); }; waits until all are visible, not at least 3.Final Answer:
Option A correctly waits for at least 3 visible elements -> Option AQuick Check:
Return true if condition met, else null to wait [OK]
- Returning false instead of null to continue wait
- Ignoring visibility check
- Checking all elements visible instead of at least 3
Ready to prove it?
Pass the test and this pattern moves unknown
