This is the one you should use. WebDriverWait lets you wait for a specific condition on a specific element. "Wait until this button is clickable." "Wait until this spinner disappears." "Wait until the URL contains /dashboard." Precise, reliable, professional.
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
// Wait until the element is VISIBLE (not just in DOM)
WebElement welcome = wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.id("welcome-message")));
System.out.println("Welcome: " + welcome.getText());
// Wait until a button is CLICKABLE (visible + enabled)
WebElement btn = wait.until(
ExpectedConditions.elementToBeClickable(
By.id("transfer-btn")));
btn.click();
// Wait until text appears in an element
wait.until(
ExpectedConditions.textToBePresentInElementLocated(
By.id("status"), "Transfer Complete"));| Condition | When to Use | Returns |
|---|---|---|
| visibilityOfElementLocated | Need to read text or verify element is shown | WebElement |
| elementToBeClickable | Need to click a button or link | WebElement |
| invisibilityOfElementLocated | Waiting for spinner/overlay to disappear | Boolean |
| presenceOfElementLocated | Element in DOM but may be hidden (e.g., hidden input) | WebElement |
| textToBePresentInElementLocated | Waiting for dynamic text to update | Boolean |
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
// === Element Presence & Visibility ===
// Element exists in DOM (may be hidden)
wait.until(ExpectedConditions.presenceOfElementLocated(
By.id("csrf-token")));
// Element is visible on screen
wait.until(ExpectedConditions.visibilityOfElementLocated(
By.id("dashboard-header")));
// Element is NOT visible (or not in DOM)
// Perfect for loading spinners
wait.until(ExpectedConditions.invisibilityOfElementLocated(
By.cssSelector(".loading-spinner")));
// === Clickability ===
// Element is visible AND enabled (always use before clicking)
WebElement btn = wait.until(
ExpectedConditions.elementToBeClickable(
By.id("submit-btn")));
btn.click();
// === Text ===
// Element contains specific text
wait.until(ExpectedConditions.textToBePresentInElementLocated(
By.id("status"), "Success"));
// Input field value contains text
wait.until(ExpectedConditions.textToBePresentInElementValue(
By.id("search"), "Laptop"));
// === Page & URL ===
// URL contains string (after navigation)
wait.until(ExpectedConditions.urlContains("/dashboard"));
// Title contains string
wait.until(ExpectedConditions.titleContains("Dashboard"));
// === Alerts, Frames, Windows ===
// JavaScript alert appeared
wait.until(ExpectedConditions.alertIsPresent());
// iframe is loaded — auto-switches into it
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(
By.id("payment-iframe")));
// Wait for new window/tab to open
wait.until(ExpectedConditions.numberOfWindowsToBe(2));
// === Multiple Elements ===
// At least one element matching the locator
wait.until(ExpectedConditions.numberOfElementsToBeMoreThan(
By.cssSelector(".product-card"), 0));
// Exact number of elements
wait.until(ExpectedConditions.numberOfElementsToBe(
By.cssSelector(".cart-item"), 3));// AND — both must be true
wait.until(ExpectedConditions.and(
ExpectedConditions.visibilityOfElementLocated(By.id("dashboard")),
ExpectedConditions.urlContains("/dashboard")
));
// OR — at least one must be true
wait.until(ExpectedConditions.or(
ExpectedConditions.visibilityOfElementLocated(By.id("success-msg")),
ExpectedConditions.visibilityOfElementLocated(By.id("error-msg"))
));
// NOT — condition must be false
wait.until(ExpectedConditions.not(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector(".loading"))
));Q: What is the difference between implicit and explicit wait?
A: Implicit wait is global — set once via driver.manage().timeouts() and applies to ALL findElement() calls. It only checks if the element exists in the DOM. Explicit wait (WebDriverWait) is targeted — you specify exactly which condition to wait for (visibility, clickability, text, URL). It's more precise and recommended because implicit wait can't check for visibility or clickability — an element might be present in DOM but hidden behind a loading overlay.
Key Point: WebDriverWait + ExpectedConditions = the right way to handle timing. Use visibilityOfElementLocated for reading, elementToBeClickable for clicking.