Fluent Wait

Full Control over Polling

FluentWait lets you set the timeout, how often to check, and which exceptions to ignore while waiting. WebDriverWait is actually a FluentWait with defaults (poll every 500 ms, ignore NoSuchElementException).

Wait<WebDriver> wait = new FluentWait<>(driver)
        .withTimeout(Duration.ofSeconds(20))
        .pollingEvery(Duration.ofSeconds(2))
        .ignoring(NoSuchElementException.class)
        .ignoring(StaleElementReferenceException.class)
        .withMessage("order status never became Confirmed");

WebElement status = wait.until(d -> {
    WebElement el = d.findElement(By.id("order-status"));
    return el.getText().equals("Confirmed") ? el : null;   // null = keep waiting
});

A Polling Wait in Plain Java

Example

This runnable simulation is the same algorithm FluentWait uses: check the condition, if false sleep the polling interval, give up at the timeout. A fake clock replaces real time so the output is the same every run:

import java.util.function.Supplier;

public class Main {
    static long now = 0;   // fake clock in ms

    static <T> T until(Supplier<T> condition, long timeoutMs, long pollMs) {
        long end = now + timeoutMs;
        while (true) {
            T value = condition.get();
            if (value != null && !Boolean.FALSE.equals(value)) return value;
            if (now >= end) throw new RuntimeException("TimeoutException: condition not met after " + timeoutMs + " ms");
            System.out.println("  t=" + now + " ms: not yet");
            now += pollMs;   // instead of Thread.sleep(pollMs)
        }
    }

    public static void main(String[] args) {
        // the order status becomes "Confirmed" at t = 4500 ms
        Supplier<String> status = () -> now >= 4500 ? "Confirmed" : null;
        String result = until(status, 10_000, 2000);
        System.out.println("Got '" + result + "' at t=" + now + " ms");

        now = 0;
        try {
            until(() -> now >= 30_000 ? "Shipped" : null, 5000, 2000);
        } catch (RuntimeException e) {
            System.out.println(e.getMessage());
        }
    }
}

Output

  t=0 ms: not yet
  t=2000 ms: not yet
  t=4000 ms: not yet
Got 'Confirmed' at t=6000 ms
  t=0 ms: not yet
  t=2000 ms: not yet
  t=4000 ms: not yet
TimeoutException: condition not met after 5000 ms