Resource library

QA How-To

How to Use Selenium ExpectedConditions in Java (2026)

Learn selenium ExpectedConditions java patterns for reliable explicit waits, correct condition selection, custom waits, stale elements, and runnable tests.

23 min read | 3,327 words

TL;DR

Create WebDriverWait with a Duration and pass a matching ExpectedConditions method to until. Use presenceOfElementLocated for DOM existence, visibilityOfElementLocated for a rendered element, elementToBeClickable for visible and enabled controls, and a custom condition for product-specific readiness.

Key Takeaways

  • WebDriverWait repeatedly evaluates an ExpectedCondition until it returns a successful value or reaches its timeout.
  • Choose the weakest condition that fully guarantees the next action, presence for DOM inspection, visibility for rendered content, and clickability for visible enabled controls.
  • Locator-based conditions usually tolerate re-renders better than conditions built from an early WebElement reference.
  • ExpectedConditions.elementToBeClickable does not prove that no overlay covers the element's click point.
  • Wait after an action for a durable result, not only before the action for a control.
  • Create small custom ExpectedCondition implementations for product-specific state and include useful timeout messages.

The selenium ExpectedConditions java API gives WebDriverWait reusable predicates for synchronizing tests with browser state. The core pattern is new WebDriverWait(driver, Duration.ofSeconds(10)).until(ExpectedConditions.someCondition(...)). Choose a condition that guarantees the next operation, and let the returned value flow directly into your test.

ExpectedConditions are not generic delays. They are repeated observations with a timeout and a defined success value. This guide explains current Selenium 4 Java syntax, the differences among presence, visibility, and clickability, stale-element strategies, custom conditions, diagnostics, and framework patterns that keep waits fast and meaningful.

TL;DR

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

WebElement save = wait.until(
    ExpectedConditions.elementToBeClickable(
        By.cssSelector("button[data-testid='save']")));
save.click();

wait.until(ExpectedConditions.visibilityOfElementLocated(
    By.cssSelector("[role='status'][data-state='saved']")));
Need before next step Condition Successful return
Node exists in DOM presenceOfElementLocated WebElement
Node is displayed with size visibilityOfElementLocated WebElement
Node is visible and enabled elementToBeClickable WebElement
Node disappears or becomes hidden invisibilityOfElementLocated Boolean
Old node is detached stalenessOf Boolean
Frame exists and should become active frameToBeAvailableAndSwitchToIt WebDriver
Alert is available alertIsPresent Alert

1. Selenium ExpectedConditions Java: How until Works

ExpectedCondition extends a function-like contract that accepts WebDriver and returns T. WebDriverWait, a specialization of FluentWait, calls that condition repeatedly until the return indicates success or the configured timeout expires. For object-returning conditions, a non-null value is successful. For Boolean conditions, true is successful. Selenium ignores NoSuchElementException during a standard WebDriverWait poll, which is why locator-based element conditions can wait through initial absence.

The default polling behavior is adequate for most UI tests. You provide the maximum Duration, not a mandatory sleep. If the condition succeeds after 150 milliseconds, until returns then. If it never succeeds, Selenium throws TimeoutException with information from the condition and any custom message supplied through withMessage.

ExpectedConditions is a collection of static factory methods. Calling visibilityOfElementLocated(locator) does not wait by itself. It creates an ExpectedCondition. Passing that object to wait.until performs the polling.

This distinction makes common bugs easy to spot. A test that creates a condition but never calls until has no synchronization. A test that calls findElement before constructing a locator-based condition can fail early with NoSuchElementException. Put the locator inside the condition when initial absence or replacement is expected.

The wait operates on the current WebDriver context. Window, frame, and alert selection still matter. A condition cannot find an element inside a frame until the driver has switched there, except for the condition designed to wait for and perform that frame switch.

2. Configure WebDriverWait and FluentWait Deliberately

The standard Selenium 4 Java constructor uses Duration:

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

WebDriverWait provides convenient defaults and ignores NoSuchElementException. FluentWait offers direct control over timeout, polling interval, ignored exceptions, and timeout message:

Wait<WebDriver> wait = new FluentWait<>(driver)
    .withTimeout(Duration.ofSeconds(10))
    .pollingEvery(Duration.ofMillis(200))
    .ignoring(NoSuchElementException.class)
    .withMessage("Order confirmation did not reach the complete state");

Do not tune polling merely to look sophisticated. Browser commands cross a process boundary and may cross a network to Grid. Extremely short intervals create command traffic without making the application faster. Extremely long intervals can miss a brief state and slow every success. Use the default unless the state has a documented characteristic that justifies adjustment.

Avoid a large implicit wait alongside explicit waits. Each condition poll that calls findElement can inherit the implicit timeout, so the total duration and polling rhythm become difficult to predict. Many automation frameworks set the implicit wait to zero and use explicit waits at meaningful boundaries.

Keep timeout values in configuration, but do not reduce every operation to one global wait. A component may use the standard UI timeout while a known long-running export has a separately named business timeout. Names communicate intent better than scattered numeric constants.

3. Presence, Visibility, and Clickability Compared

These three conditions are related but not interchangeable.

Condition Checks Does not guarantee Appropriate next operation
presenceOfElementLocated Locator finds an attached node Display, size, enabled state Read an attribute or establish DOM existence
visibilityOfElementLocated Element is displayed and has usable dimensions Enabled state or unobstructed click point Read visible text, inspect layout, sometimes type
elementToBeClickable Element is visible and enabled No overlay, animation stability, business readiness Click when no product-specific blocker remains
invisibilityOfElementLocated Element is absent or not visible Application succeeded Proceed after a loader or modal closes

Use presence when visibility is irrelevant. A hidden metadata node or script-injected marker can be present without being user-facing. Use visibility before reading rendered content or interacting with a field that becomes displayed. Use clickability before clicking a control that may be disabled during loading.

Clickability has a precise but limited meaning in ExpectedConditions: visible and enabled. It does not perform a trial click, inspect every point in the paint stack, or wait for all animations. If a sticky header or overlay covers the center, WebDriver can still throw ElementClickInterceptedException. Wait for that known obstruction to disappear or fix the layout.

Do not stack redundant waits such as presence, then visibility, then clickability for the same locator. The strongest needed condition already performs its own lookup. Redundant waits add commands and scatter the action's readiness contract across lines.

4. A Runnable Java Test With ExpectedConditions

This JUnit Jupiter test loads a self-contained page. The button starts disabled, becomes enabled, and then displays a success status after a click. The test synchronizes before and after the user action.

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Base64;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
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.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

class ExpectedConditionsTest {
  private WebDriver driver;
  private WebDriverWait wait;

  @BeforeEach
  void startBrowser() {
    driver = new ChromeDriver();
    wait = new WebDriverWait(driver, Duration.ofSeconds(5));
  }

  @AfterEach
  void stopBrowser() {
    if (driver != null) driver.quit();
  }

  @Test
  void waitsForActionAndResult() {
    String html = """
        <!doctype html>
        <button id="save" disabled>Save</button>
        <p id="status" role="status"></p>
        <script>
          const save = document.querySelector('#save');
          setTimeout(() => save.disabled = false, 300);
          save.addEventListener('click', () => {
            setTimeout(() => {
              document.querySelector('#status').textContent = 'Saved';
            }, 200);
          });
        </script>
        """;
    String encoded = Base64.getEncoder().encodeToString(
        html.getBytes(StandardCharsets.UTF_8));
    driver.get("data:text/html;base64," + encoded);

    WebElement save = wait.until(
        ExpectedConditions.elementToBeClickable(By.id("save")));
    save.click();

    WebElement status = wait.until(
        ExpectedConditions.visibilityOfElementLocated(By.id("status")));
    wait.until(ExpectedConditions.textToBePresentInElement(status, "Saved"));
    assertEquals("Saved", status.getText());
  }
}

The first condition returns the button, so an extra findElement is unnecessary. The post-click conditions verify a durable user-visible result rather than treating a successful click command as feature success. In a real application, one condition may be enough if the status becomes visible only when it contains the final text.

5. Choose Conditions for Text, Attributes, Counts, and Selection

ExpectedConditions includes more than element readiness. Use the factory whose return and semantics match the requirement:

  • textToBePresentInElementLocated waits for a substring in an element's visible text.
  • textToBePresentInElementValue waits for text in a value attribute.
  • attributeToBe and attributeContains wait for element attributes.
  • domPropertyToBe targets a DOM property value.
  • elementToBeSelected and elementSelectionStateToBe handle selection.
  • numberOfElementsToBe, numberOfElementsToBeMoreThan, and numberOfElementsToBeLessThan handle collection size.
  • titleIs and titleContains cover document title.
  • urlToBe, urlContains, urlMatches, and urlToBeOneOf cover navigation.

Choose an exact condition when exactness is part of the requirement. If the expected URL is known, urlToBe catches an unintended query or path. If a route legitimately appends dynamic parameters, urlMatches or a custom URI predicate can express allowed variation.

For counts, think about stable state. numberOfElementsToBeMoreThan(locator, 0) is useful for first results, but a test asserting a completed search might need both a loading indicator to disappear and an exact expected count from controlled data. Do not wait for any item and then immediately assert a final count while the list is still streaming.

Distinguish attributes from properties. User interaction changes properties such as an input's current value, while markup attributes can preserve initial values. Use getDomProperty and a matching condition when current runtime state is the requirement. Avoid asserting CSS classes as a proxy when an accessible state such as aria-expanded or a durable data-state is available.

6. Handle Frames, Alerts, Windows, and Page Transitions

frameToBeAvailableAndSwitchToIt combines readiness and the context change. It accepts a locator, frame name or ID, index, or WebElement overload according to the Java API. After work inside the frame, switch back explicitly.

wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(
    By.cssSelector("iframe[title='Checkout']")));
WebElement confirm = wait.until(
    ExpectedConditions.elementToBeClickable(By.id("confirm")));
confirm.click();
driver.switchTo().defaultContent();

alertIsPresent returns Alert, so accept and use that object directly:

Alert alert = wait.until(ExpectedConditions.alertIsPresent());
assertEquals("Delete item?", alert.getText());
alert.accept();

numberOfWindowsToBe is useful after an action expected to open a new tab. Capture the original handles, click, wait for the count, identify the new handle, and switch. The condition does not choose the new window for you.

For navigation, wait for a durable URL, title, or page-specific landmark after triggering the action. document.readyState alone does not prove a single-page application finished data loading. A route can update before its content is ready, so combine navigation evidence with one page landmark when the scenario requires both.

Avoid calling conditions against the wrong context and then increasing timeouts. A ten-minute wait in the top document never finds a control that exists only inside an iframe. Context setup belongs immediately before the locator condition.

7. Manage Re-Renders and Stale Elements

A locator-based condition re-runs the locator during polling, so it naturally adapts when an initially absent node appears. Conditions that accept a WebElement keep that specific reference. If the framework replaces the node, the reference becomes stale and cannot represent the new element.

Use stalenessOf when replacement is the expected transition:

WebElement oldTable = driver.findElement(By.id("results"));
driver.findElement(By.id("refresh")).click();
wait.until(ExpectedConditions.stalenessOf(oldTable));
WebElement newTable = wait.until(
    ExpectedConditions.visibilityOfElementLocated(By.id("results")));

This explicitly models two states: the old table is gone, then the replacement is visible. It is clearer than catching StaleElementReferenceException around random assertions.

ExpectedConditions.refreshed wraps a condition and retries when a redraw causes a stale reference during evaluation. It can be useful for a narrow find-then-check race:

WebElement total = wait.until(ExpectedConditions.refreshed(
    ExpectedConditions.visibilityOfElementLocated(By.id("order-total"))));

Do not wrap every condition in refreshed. Persistent staleness can signal an unstable locator, a component that never settles, or a test observing the wrong transition. Blind retries may also be dangerous around actions. Waiting can be safely repeated; submitting payment or moving an item may not be.

The StaleElementReferenceException Java guide covers re-location and idempotency in more depth.

8. Combine Conditions With and, or, and not

ExpectedConditions.and returns a Boolean condition that succeeds when all supplied conditions succeed. or succeeds when any does. not inverts the result of a condition. These combinators are useful for state, but their generic Boolean result means you do not receive the WebElement returned by an inner condition.

wait.until(ExpectedConditions.and(
    ExpectedConditions.invisibilityOfElementLocated(By.id("loading")),
    ExpectedConditions.textToBePresentInElementLocated(
        By.id("status"), "Ready")));

Use or for legitimate alternative outcomes, such as either a dashboard landmark or an authentication error appearing. After it succeeds, inspect which outcome occurred and branch explicitly. Do not use or to make a test pass on any vague page change.

wait.until(ExpectedConditions.or(
    ExpectedConditions.visibilityOfElementLocated(By.id("dashboard")),
    ExpectedConditions.visibilityOfElementLocated(By.id("login-error"))));

if (!driver.findElements(By.id("login-error")).isEmpty()) {
  throw new AssertionError("Login failed: "
      + driver.findElement(By.id("login-error")).getText());
}

Be cautious with not. Inversion can be confusing when the inner condition throws an exception that the wait ignores, and absence or invisibility may already have a purpose-built condition. Prefer invisibilityOfElementLocated to not(visibilityOfElementLocated(...)) because the named condition communicates intent and handles absence naturally.

Keep combinations short. A five-part Boolean expression usually hides a meaningful product concept that deserves a named custom condition or component method.

9. Write a Custom ExpectedCondition in Java

When the built-in collection cannot express a product-specific state, supply a lambda or an ExpectedCondition implementation. Return a useful value on success and null or false while waiting. Keep each poll read-only, fast, and safe to repeat.

This condition waits for a data-state value and returns the element:

static ExpectedCondition<WebElement> elementStateToBe(
    By locator, String expectedState) {
  return driver -> {
    WebElement element = driver.findElement(locator);
    String actual = element.getDomAttribute("data-state");
    return expectedState.equals(actual) ? element : null;
  };
}

WebElement editor = wait.withMessage(
        "Editor did not become ready")
    .until(elementStateToBe(
        By.cssSelector("[data-testid='editor']"), "ready"));

A named anonymous class can override toString so TimeoutException describes the expectation:

static ExpectedCondition<Boolean> orderStatusToBe(
    By locator, String expected) {
  return new ExpectedCondition<>() {
    @Override
    public Boolean apply(WebDriver driver) {
      return expected.equals(driver.findElement(locator).getText().trim());
    }

    @Override
    public String toString() {
      return "order status located by " + locator + " to equal " + expected;
    }
  };
}

Do not click, submit, refresh, or mutate test data inside a condition. WebDriverWait may call it many times. Side effects inside polling create duplicate operations and make the number of actions depend on timing. The condition should observe; the test should act once before or after it.

10. Diagnose TimeoutException With Better Evidence

TimeoutException is an outcome, not a root cause. The condition never reported success within its budget. The application may be broken, the locator may be wrong, the context may be wrong, the expectation may be too strict, or the precondition may never have been triggered.

Add a useful message with withMessage, and collect artifacts at the framework boundary:

WebElement receipt = new WebDriverWait(driver, Duration.ofSeconds(10))
    .withMessage(() -> "Receipt was not visible after checkout at "
        + driver.getCurrentUrl())
    .until(ExpectedConditions.visibilityOfElementLocated(
        By.cssSelector("[data-testid='receipt']")));

When the wait fails, attach a screenshot, relevant DOM excerpt, current URL, window handle, frame path, locator count, and safe application logs. A screenshot can show a modal; an element count can expose a hidden duplicate; console or network evidence can show why a component never initialized.

Do not catch TimeoutException and continue with null. That converts a clear synchronization failure into a later NullPointerException or incorrect assertion. Re-throw it with evidence or translate it into a domain-specific assertion while preserving the cause.

Avoid increasing the timeout until you know the condition eventually succeeds on a slow but acceptable run. If the locator points to an obsolete ID, more time has no value. If the product exceeds an agreed response budget, the timeout may be correctly exposing a defect.

11. Put Waits in Page Components Without Hiding Outcomes

A page component should own locators and readiness for its actions. A test should own the business expectation. For example:

public final class ProfileForm {
  private final WebDriver driver;
  private final WebDriverWait wait;
  private final By saveBy = By.cssSelector("button[data-testid='save-profile']");
  private final By savedBy = By.cssSelector("[role='status'][data-state='saved']");

  public ProfileForm(WebDriver driver, Duration timeout) {
    this.driver = driver;
    this.wait = new WebDriverWait(driver, timeout);
  }

  public void save() {
    wait.until(ExpectedConditions.elementToBeClickable(saveBy)).click();
    wait.until(ExpectedConditions.visibilityOfElementLocated(savedBy));
  }

  public String status() {
    return driver.findElement(savedBy).getText();
  }
}

The component waits for a control and its immediate result. The test can assert the exact status or persisted data. Avoid a global waitAndClick(By) utility that cannot know about overlays, frame context, post-click results, or whether the action is safe to repeat.

Prefer locator fields over cached WebElements for dynamic applications. PageFactory is not required for ExpectedConditions, and an early @FindBy proxy does not eliminate the need to model render transitions.

For a broader design, see the Selenium page object model Java guide. Synchronization should express component behavior rather than appear as sleeps scattered across tests.

12. Selenium ExpectedConditions Java Review Checklist

Before merging a wait, check:

  1. The condition describes the state required by the next operation.
  2. The locator is unique in the active window, frame, and shadow context.
  3. A locator-based overload is used when the node may not exist yet or may be replaced.
  4. The returned element, Alert, or WebDriver is reused instead of located again unnecessarily.
  5. Presence is not used as a substitute for visibility or enabled state.
  6. Clickability is not treated as proof that no overlay exists.
  7. The post-action business result has its own synchronization when needed.
  8. Polling is read-only and safe to repeat.
  9. Implicit waits do not distort the explicit wait budget.
  10. Timeout and polling settings have named reasons.
  11. Failure messages and artifacts identify the unmet state.
  12. Non-idempotent actions are outside the condition and are not blindly retried.

For teams migrating from fixed delays, replace one sleep at a time with the actual state that delay was hoping to cover. A wait for loader invisibility, final text, old-node staleness, or a selected state is both faster on success and more useful on failure.

The Selenium explicit waits Java guide provides additional framework-level timeout patterns.

Interview Questions and Answers

Q: What is ExpectedConditions in Selenium Java?

It is a utility class of static factories that create ExpectedCondition objects for common browser states. WebDriverWait repeatedly evaluates the condition until it succeeds or times out. Many conditions return the ready object, such as WebElement or Alert, rather than only true.

Q: What is the difference between presence and visibility?

Presence means a locator finds a node in the DOM. Visibility additionally requires the element to be displayed with a usable rendered size. I choose visibility before reading user-visible content and presence only when rendering is irrelevant.

Q: What does elementToBeClickable guarantee?

It waits for an element to be visible and enabled. It does not guarantee that no overlay covers its click point or that all animation has ended. I add a product-specific obstruction wait when the UI has one.

Q: Why prefer a By overload over a WebElement overload?

A locator-based condition performs lookup during polling and can find a node that appears later or replaces an earlier one. A WebElement overload holds one reference, which can become stale. I use a reference overload only when that exact node's lifecycle matters.

Q: How do you write a custom condition?

I provide a lambda or ExpectedCondition whose apply method reads browser state and returns a useful value on success, otherwise null or false. Polling must be fast, read-only, and idempotent. I add a descriptive timeout message or toString implementation.

Q: How do you wait through a re-render?

If replacement is expected, I wait for stalenessOf the old node and then locate the new one. For a narrow stale race during evaluation, refreshed can wrap a locator-based condition. I do not blindly retry actions that may already have side effects.

Q: Should every click have a wait before it?

Not mechanically. Wait at real asynchronous boundaries. A stable page can click an already ready element, while a disabled or dynamically rendered control needs a condition. I also wait after actions whose result arrives asynchronously.

Q: How do you diagnose an explicit wait timeout?

I inspect the condition, locator, active context, trigger action, screenshot, DOM, URL, and application logs. I determine whether the state was slow, impossible, or incorrectly expressed before changing the timeout.

Common Mistakes

  • Using presence before click: DOM existence does not establish visible, enabled interaction state.
  • Creating a condition without calling until: Factory methods do not wait by themselves.
  • Finding the element before the wait: Early findElement can fail before polling begins.
  • Stacking presence, visibility, and clickability: Use the one condition that fully predicts the next action.
  • Treating clickability as unobstructed: Overlays can still intercept the click point.
  • Mixing long implicit and explicit waits: Timing becomes difficult to calculate and diagnose.
  • Caching dynamic WebElements: Re-rendered components make early references stale.
  • Putting clicks inside custom conditions: Polling may repeat the side effect.
  • Ignoring the returned value: until often already returns the element, alert, or driver you need.
  • Catching TimeoutException and continuing: This hides the failed precondition and causes misleading later errors.
  • Using one timeout for every behavior: Named business operations can need distinct, justified budgets.
  • Waiting only before actions: Asynchronous results also require synchronization and assertions.

Conclusion

Effective selenium ExpectedConditions java code makes readiness explicit. Create WebDriverWait with Duration, choose a condition that guarantees the next operation, reuse its returned object, and wait for the user-visible result after asynchronous actions. Presence, visibility, clickability, and staleness are different contracts, not interchangeable delay recipes.

Start by replacing the most frequently failing sleep in your suite with a named state condition. Add evidence to its timeout, then use that pattern in the component that owns the behavior.

Interview Questions and Answers

Explain WebDriverWait and ExpectedConditions in Java.

WebDriverWait repeatedly applies an ExpectedCondition to WebDriver until it returns a successful value or reaches its timeout. ExpectedConditions supplies factories for common states such as visibility, clickability, frames, alerts, URLs, and staleness. The wait returns the condition's value.

How do presence, visibility, and clickability differ?

Presence checks DOM existence. Visibility adds displayed state and rendered size. Clickability adds enabled state, but it still does not prove the click point is free of overlays.

Why are locator-based conditions often more robust?

They perform lookup during each poll, so they can find elements that appear later or replace old nodes. A condition based on a stored WebElement retains one reference and can become stale during a re-render.

What should a custom ExpectedCondition return?

It should return a useful non-null object or true when satisfied, and null or false while waiting. Its polling work should be fast, read-only, and safe to repeat. A descriptive message should explain the target state.

How would you wait for an old component to be replaced?

I capture the old WebElement, trigger the refresh, wait for ExpectedConditions.stalenessOf(old), then wait for the replacement through a locator-based condition. This models the lifecycle explicitly.

Why avoid implicit and explicit wait mixing?

Element lookups inside each explicit-wait poll can inherit the implicit delay, making total timeout behavior difficult to predict. A framework based on explicit waits has clearer boundaries and failure timing.

What evidence helps diagnose TimeoutException?

I capture the condition description, locator, match count, screenshot, current URL, window and frame context, relevant DOM, and application logs. I verify that the action expected to trigger the state actually occurred.

Where should waits live in a page object model?

A page component should own readiness for its controls and immediate operation result. The test should retain the business assertion. I avoid universal wait-and-click helpers because they lack component-specific context.

Frequently Asked Questions

How do I use ExpectedConditions in Selenium Java?

Create WebDriverWait with a Duration and call until with an ExpectedConditions factory, such as visibilityOfElementLocated(locator). Store the returned WebElement when the condition provides one.

What is the difference between presenceOfElementLocated and visibilityOfElementLocated?

Presence means a node exists in the DOM. Visibility also requires it to be displayed with usable dimensions, which is appropriate for user-visible reading and many interactions.

Does elementToBeClickable guarantee the click will work?

It guarantees visibility and enabled state, not an unobstructed click point. A loading mask, sticky header, or animation can still intercept a click, so wait for known blockers separately.

Should I use WebDriverWait or FluentWait?

WebDriverWait is the usual choice for WebDriver and provides practical defaults. Use FluentWait when you have a justified need to customize polling, ignored exceptions, or messages more directly.

How do I handle stale elements in an explicit wait?

Prefer locator-based conditions for replaceable nodes. When replacement is the transition, wait for stalenessOf the old element and then locate the new one; refreshed can help with a narrow stale race.

Can I combine ExpectedConditions in Java?

Yes. ExpectedConditions.and, or, and not create Boolean combinations. Keep combinations focused, and use a named custom condition when several predicates represent one product state.

Why does my WebDriverWait still time out?

The condition never reported success within the budget. Check the locator, current frame or window, trigger action, application state, and whether the expectation is possible before increasing the timeout.

Related Guides