Built-in ExpectedConditions cover standard scenarios, but modern web applications often have custom business conditions: waiting for an element attribute to change (e.g. class="step completed"), waiting for a CSS width animation to reach 100%, or waiting for JavaScript document.readyState to be complete. In Selenium 4, you can write custom conditions using clean Java lambda expressions.
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(15));
// 1. Custom lambda: Wait for CSS width property to hit 100%
wait.until(d -> {
WebElement bar = d.findElement(By.id("progress-fill"));
return "100%".equals(bar.getCssValue("width"));
});
// 2. Custom lambda: Wait for JavaScript document readyState to be 'complete'
wait.until(d -> {
JavascriptExecutor js = (JavascriptExecutor) d;
return "complete".equals(js.executeScript("return document.readyState"));
});
// 3. Custom lambda: Wait until table row count exceeds previous baseline
int baselineCount = 5;
wait.until(d -> d.findElements(By.cssSelector("table#records tbody tr")).size() > baselineCount);package com.testerrank.waits;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
public class CustomWaits {
public static ExpectedCondition<Boolean> attributeContains(By locator, String attribute, String value) {
return new ExpectedCondition<Boolean>() {
private String actualValue = "";
@Override
public Boolean apply(WebDriver driver) {
try {
actualValue = driver.findElement(locator).getAttribute(attribute);
return actualValue != null && actualValue.contains(value);
} catch (Exception e) {
return false;
}
}
@Override
public String toString() {
return String.format("attribute '%s' to contain '%s'. Actual value: '%s'", attribute, value, actualValue);
}
};
}
}Key Point: When built-in conditions fall short, pass custom Java lambdas to wait.until() to evaluate arbitrary browser and DOM states.