Resource library

QA How-To

How to Use Selenium fluent wait in Java (2026)

Learn selenium fluent wait java configuration with timeout, polling, ignored exceptions, custom conditions, diagnostics, and production-ready examples.

23 min read | 3,309 words

TL;DR

A Selenium fluent wait in Java repeatedly evaluates a function until it returns a non-null, non-false result or the timeout expires. Configure `new FluentWait<>(driver).withTimeout(...).pollingEvery(...).ignoring(...)`, then make `until` return the element or value your next step needs, while ignoring only exceptions that a later poll can legitimately resolve.

Key Takeaways

  • Create `FluentWait<WebDriver>` with a bounded timeout, an intentional polling interval, and only the transient exceptions the condition can recover from.
  • Make an `until` function return a useful non-null, non-false value only when the required state is ready.
  • Prefer `WebDriverWait` for ordinary browser waits and choose raw `FluentWait` when you need a different input type or clearly customized policy.
  • Ignore `NoSuchElementException` for late elements only when each poll performs a fresh lookup.
  • Do not ignore assertions, invalid selectors, session failures, or every runtime exception.
  • Treat timeout and polling values as application contracts, not arbitrary numbers copied across the suite.
  • Add condition names and state snapshots so a timeout explains what remained unready.

Use selenium fluent wait java when a page condition needs a bounded timeout plus explicit control over polling and recoverable exceptions. Build a FluentWait<WebDriver>, set withTimeout and pollingEvery, optionally add narrowly chosen ignored exceptions, then call until with a function that returns a useful value only when the UI is ready.

FluentWait is not a license to catch everything or poll as fast as possible. It is a policy object for repeated evaluation. The quality of the condition matters more than the syntax because a weak condition can pass before the user journey is actually ready. This guide shows complete Selenium 4 Java patterns for elements, values, collections, re-rendered DOM, framework utilities, and interview answers.

TL;DR

Wait<WebDriver> wait = new FluentWait<>(driver)
    .withTimeout(Duration.ofSeconds(10))
    .pollingEvery(Duration.ofMillis(250))
    .ignoring(NoSuchElementException.class)
    .withMessage("Checkout button did not become enabled");

WebElement checkout = wait.until(d -> {
  WebElement button = d.findElement(By.id("checkout"));
  return button.isDisplayed() && button.isEnabled() ? button : null;
});
Configuration Purpose Review question
withTimeout Maximum wait duration Does it represent the workflow's acceptable latency?
pollingEvery Delay between evaluations Is it responsive without creating needless remote calls?
ignoring Retries after one transient exception type Can the next poll genuinely recover from this exception?
ignoreAll Adds several transient exception types Are all types expected and narrow?
withMessage Adds timeout context Will the message identify the expected state?
until Evaluates the readiness function Does success return a useful value, not a guess?

For common element conditions, WebDriverWait plus ExpectedConditions is usually shorter. It extends FluentWait<WebDriver> and supplies browser-oriented defaults. Use raw FluentWait when its general type or explicit configuration makes the intent clearer.

1. What Selenium Fluent Wait Java Actually Does

FluentWait<T> is a generic Selenium support class that implements the Wait<T> interface. It repeatedly passes an input object of type T into a Java Function until one of four things happens: the function returns a value that is neither null nor false, the timeout expires, the current thread is interrupted, or the function throws an exception that the wait is not configured to ignore.

For browser automation, the input type is commonly WebDriver:

Wait<WebDriver> wait = new FluentWait<>(driver);

The generic type is broader than WebDriver. A framework can wait on an API client, page object, or another state holder, though using Selenium's wait class outside browser synchronization should remain a deliberate design decision. WebDriverWait is the specialized subclass most teams use for routine browser conditions.

FluentWait does not run in the background. The test thread evaluates the condition, waits for the polling interval, and evaluates again. Every locator and property call inside the function is a remote WebDriver command. A 50 ms poll is therefore not free, especially through Selenium Grid.

The configured timeout is the maximum waiting policy, but one condition evaluation can itself take time. An implicit wait, slow script, or remote command nested inside the function can extend observed timing. Keep each poll short and avoid mixing a large implicit timeout with this explicit loop.

Most importantly, FluentWait does not know what "ready" means. Your function defines success. A condition that returns an element as soon as it exists differs from one that waits until the element is visible, enabled, contains a particular attribute, and belongs to the correct application state.

2. Create and Run a Complete FluentWait Example

The following class starts Chrome, opens a self-contained page, waits for a delayed button to become enabled, and clicks it. Add the current Selenium 4 selenium-java dependency to the project. Selenium Manager supports common local driver setup when new ChromeDriver() creates the session.

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;

public class FluentWaitDemo {
  public static void main(String[] args) {
    WebDriver driver = new ChromeDriver();
    try {
      String html = """
          <h1>Build report</h1>
          <div id='status'>Preparing</div>
          <script>
            setTimeout(() => {
              const button = document.createElement('button');
              button.id = 'download';
              button.textContent = 'Download report';
              button.disabled = true;
              document.body.appendChild(button);
              setTimeout(() => {
                button.disabled = false;
                document.querySelector('#status').textContent = 'Ready';
              }, 600);
            }, 600);
          </script>
          """;
      driver.get("data:text/html;charset=utf-8;base64,"
          + Base64.getEncoder().encodeToString(html.getBytes(StandardCharsets.UTF_8)));

      Wait<WebDriver> wait = new FluentWait<>(driver)
          .withTimeout(Duration.ofSeconds(5))
          .pollingEvery(Duration.ofMillis(200))
          .ignoring(NoSuchElementException.class)
          .withMessage("Report download button did not become ready");

      WebElement download = wait.until(d -> {
        WebElement button = d.findElement(By.id("download"));
        return button.isDisplayed() && button.isEnabled() ? button : null;
      });

      download.click();
      System.out.println(driver.findElement(By.id("status")).getText());
    } finally {
      driver.quit();
    }
  }
}

The condition locates the button on every poll, which handles its late creation. NoSuchElementException is ignored because the page can legitimately resolve it on a later poll. Once found, a disabled button causes null, so polling continues. Success returns the ready WebElement, avoiding another immediate lookup.

3. Configure Timeout, Polling, Exceptions, and Message

A useful FluentWait configuration answers four operational questions. How long can this state reasonably take? How often should the suite check? Which failures are temporary during this transition? What evidence should appear when the deadline expires?

withTimeout(Duration) sets the overall deadline. Choose it from the application's expected behavior and test environment, not from a universal constant. An autosuggest response and a batch export do not have the same latency contract. If CI needs more time because the environment is overloaded, investigate capacity before doubling every test wait.

pollingEvery(Duration) controls the interval between attempts. Faster is not always better. Polling a local DOM property every 100 to 250 ms may be reasonable for an interactive state. Polling a long-running server job through the UI may need a slower interval. On Grid, every attempt adds protocol and browser work.

ignoring(Class<? extends Throwable>) adds an exception type that should not end the wait. ignoreAll(Collection<Class<? extends Throwable>>) adds several. The wait records the last ignored exception and may attach it to the timeout failure. Keep the list narrow and transition-specific.

withMessage(String) or its supplier form gives the timeout a meaningful description. Include the component and desired state, but do not include secrets or enormous page dumps. A message such as "Order 4821 did not reach Complete" is more actionable than "element wait failed".

Configuration calls mutate and return the same wait instance, allowing fluent chaining. Create a new wait or a carefully designed factory for different policies. Reconfiguring one shared mutable wait across parallel tests invites cross-test surprises.

4. Write Correct until Functions

The until function is the contract. For a result type other than Boolean, return null while waiting and the final value on success. For a Boolean condition, return false while waiting and true on success. If a non-ignored exception escapes, the wait ends immediately.

Return the object the caller needs:

WebElement banner = wait.until(d -> {
  WebElement candidate = d.findElement(By.cssSelector("[role='status']"));
  return candidate.isDisplayed() && candidate.getText().contains("Saved")
      ? candidate
      : null;
});

For a collection, do not return an empty list as the waiting value. An empty list is non-null and therefore counts as success for a non-Boolean result. Return null until the list meets the rule:

List<WebElement> rows = wait.until(d -> {
  List<WebElement> current = d.findElements(By.cssSelector("#orders tbody tr"));
  return current.size() >= 3 ? current : null;
});

Avoid side effects inside a condition. A click or form submission can run several times if the function returns a waiting value or a later command fails. Conditions should observe state. Perform the consequential action once after success. Selenium's official examples sometimes demonstrate a retryable interaction to explain customization, but production test design should prefer idempotent observation.

Give complex conditions a name instead of embedding a long lambda. A function such as orderHasStatus(orderId, "Complete") can capture domain context, provide targeted logging, and receive unit tests. Keep its polling work bounded and ensure it does not swallow unexpected errors.

5. Choose Ignored Exceptions Deliberately

Ignoring an exception means the wait considers it temporary. It does not fix the cause. The next poll must have a plausible path to success. NoSuchElementException is often appropriate when an element will be inserted later. StaleElementReferenceException can be appropriate when a component is re-rendering and every poll obtains a new reference.

Wait<WebDriver> wait = new FluentWait<>(driver)
    .withTimeout(Duration.ofSeconds(8))
    .pollingEvery(Duration.ofMillis(250))
    .ignoring(NoSuchElementException.class)
    .ignoring(org.openqa.selenium.StaleElementReferenceException.class);

Do not automatically ignore InvalidSelectorException. A later poll will not repair malformed CSS or XPath. Do not ignore NoSuchSessionException, because the browser session is gone. Do not ignore AssertionError, because an assertion is a test verdict, not a transient locator result. Never ignore Throwable or Exception to make a wait "robust". That turns browser crashes, coding defects, and real application errors into slow, vague timeouts.

If a condition uses findElements, missing elements produce an empty list rather than NoSuchElementException, so no ignored exception is needed for absence. Return null until the list reaches the desired state. This is often clearer for optional or collection-oriented conditions.

Review ignored exceptions together with the condition body. Ignoring staleness while evaluating a cached WebElement is usually pointless because every retry uses the same stale reference. Re-locate inside the function. The Selenium findElement and findElements Java guide explains the underlying finder contracts.

6. Set a Sensible Polling Interval

Polling should balance responsiveness, stability, and remote-call cost. There is no universally correct interval. Start with the user interaction and the system being observed. A DOM class change after a request can justify a few checks per second. A background report that normally takes tens of seconds does not need ten browser queries per second.

A poll function can issue several commands: find an element, read display state, read an attribute, and retrieve text. Across a remote Grid, those round trips add up. Consolidate the condition where possible and avoid logging a screenshot or full DOM on every attempt. Save expensive diagnostics for timeout or sample them deliberately.

Very short intervals can also observe intermediate states that the user never perceives and amplify races. Very long intervals can make a condition succeed noticeably after the interface is ready. Pick a value, measure the transition distribution in the target environment, and keep the total deadline independent of the polling cadence.

Do not use polling to compensate for a missing deterministic signal. If clicking Save triggers a known request and a status label, wait for the status label's semantic state. If the application emits no stable readiness signal, work with developers to add one, such as an accessible status, stable data attribute, or completed API state.

A framework-level wait policy can define defaults, but allow a named workflow to choose a different interval. Avoid arbitrary numbers scattered through page objects. Centralization helps review, while named overrides preserve the real product contract.

7. FluentWait vs WebDriverWait vs Implicit Wait

These mechanisms overlap, but they serve different design levels.

Wait type Scope Configuration style Best use Main risk
Implicit wait Every element lookup in the session driver.manage().timeouts().implicitlyWait(...) Small legacy baseline, if the team understands it Hidden cost in nested or explicit polling
WebDriverWait One explicit browser condition Constructor timeout plus inherited fluent methods Standard element, URL, frame, alert, and custom browser conditions Generic waits copied without domain meaning
FluentWait<T> One explicit condition over any input type Full fluent configuration Custom input type or clearly customized polling and exceptions Overengineering ordinary element waits
Fixed sleep Current thread only Thread.sleep(...) Rare diagnostic pause, not synchronization Always waits the full time and proves no state

WebDriverWait extends FluentWait<WebDriver>. It is not a competing engine. It provides a browser-specific constructor and ignores NoSuchElementException by default. You can still call pollingEvery, ignoring, and withMessage on it. For most Selenium page conditions, that specialized class plus ExpectedConditions is concise and familiar.

Raw FluentWait is useful when the generic input type matters or when code review benefits from a visibly specialized policy. Do not replace every WebDriverWait simply because FluentWait exposes the same knobs.

Avoid combining a large implicit wait with either explicit wait. A findElement inside each poll can block for the implicit duration, distorting the expected cadence. Many modern suites set implicit wait to zero and use explicit, state-specific waits.

8. Wait for Dynamic Elements and Collections

Element presence, visibility, interactability, and business readiness are different states. Select the narrowest success condition that guarantees the next step can run. For a form submission, visible and enabled may be enough. For a job result, text and a stable job ID may both matter.

record JobStatus(String id, String state) {}

JobStatus completed = wait.until(d -> {
  WebElement panel = d.findElement(By.cssSelector("[data-testid='job-status']"));
  String id = panel.getAttribute("data-job-id");
  String state = panel.getText().trim();
  return id != null && !id.isBlank() && state.equals("Complete")
      ? new JobStatus(id, state)
      : null;
});

Returning a small domain value separates the wait from later DOM changes. It also makes logs and assertions clearer. Use immutable values when the caller does not need to interact with the element itself.

For lists, define cardinality and content. "Any rows exist" may pass while a skeleton row is still present. Filter by a stable row marker and verify loading has finished. When exactly five results are expected, return only when the count is five. When at least one result or a valid empty state can occur, model both outcomes explicitly rather than waiting forever for a row.

If your condition becomes a page-specific state machine, place it in the page object or a named condition class. Tests should read in business terms. A fluent wait is an implementation detail, not the scenario vocabulary.

9. Handle Re-Renders and Stale Elements

A stale reference points to a DOM node that was removed or replaced. Client-side frameworks commonly replace a button, row, or entire component after a state update. A wait can tolerate that transition only if every attempt obtains fresh references.

By total = By.cssSelector("[data-testid='cart-total']");

String finalTotal = new FluentWait<>(driver)
    .withTimeout(Duration.ofSeconds(8))
    .pollingEvery(Duration.ofMillis(200))
    .ignoring(NoSuchElementException.class)
    .ignoring(org.openqa.selenium.StaleElementReferenceException.class)
    .until(d -> {
      String text = d.findElement(total).getText().trim();
      return text.equals("$42.00") ? text : null;
    });

Do not pass a cached element into a condition and expect ignored staleness to refresh it. The locator belongs inside the condition. Also avoid retrying a click after staleness unless the operation is known to be idempotent. The first click may have reached the application even if a subsequent response made the element stale. Duplicate checkout, payment, or delete actions are worse than a test failure.

If re-rendering is constant, find a stronger stable signal. An API response, status region, disabled loading attribute, or immutable result token can be safer than repeatedly sampling a changing label. The Selenium ElementNotInteractableException guide helps distinguish timing from actual interactability problems.

Bound retries through the wait deadline and preserve the last exception. An unbounded while (true) loop can hang a CI worker and makes failure ownership unclear.

10. Build a Reusable Wait Utility Without a God Wrapper

Centralizing default durations and messages can improve consistency. Centralizing every possible condition in one generic method usually makes tests harder to read. Build small factories and named condition functions, not a wrapper that accepts arbitrary lambdas, exception lists, sleeps, and logging flags from every call.

import java.time.Duration;
import java.util.function.Function;

public final class Waits {
  private Waits() {}

  public static <T> T until(
      WebDriver driver,
      Duration timeout,
      String message,
      Function<WebDriver, T> condition) {
    return new FluentWait<>(driver)
        .withTimeout(timeout)
        .pollingEvery(Duration.ofMillis(250))
        .ignoring(NoSuchElementException.class)
        .withMessage(message)
        .until(condition);
  }
}

This helper is intentionally small, but even it should not become the only API. A page object can expose waitUntilOrderCompletes(orderId) and use the utility internally. The test then communicates the product state.

Do not keep one static wait object. It contains an input reference and mutable configuration, and WebDriver instances should not be shared across parallel tests. Construct waits from the current test's driver. If using ThreadLocal<WebDriver>, pass the resolved driver into the page object and wait factory rather than hiding it behind global access.

Separate policy by workflow. A standard UI wait, short absence probe, and long asynchronous job wait have different semantics. Names such as UI_READY, TOAST_LIFETIME, and REPORT_COMPLETION are more reviewable than SHORT, MEDIUM, and LONG, although actual durations should still live in configuration.

11. Make Timeout Failures Diagnostic

A timeout should say which state failed and include focused evidence. withMessage is the first layer. Add the current URL, stable record identifier, and final observed value when safe. Capture a screenshot once on failure through the test listener or assertion layer, not on every poll.

For a custom condition, retain a compact last observation:

java.util.concurrent.atomic.AtomicReference<String> lastState =
    new java.util.concurrent.atomic.AtomicReference<>("not observed");

Wait<WebDriver> statusWait = new FluentWait<>(driver)
    .withTimeout(Duration.ofSeconds(12))
    .pollingEvery(Duration.ofMillis(500))
    .ignoring(NoSuchElementException.class)
    .withMessage(() -> "Order did not complete. Last state: " + lastState.get());

statusWait.until(d -> {
  String value = d.findElement(By.id("order-status")).getText().trim();
  lastState.set(value);
  return value.equals("Complete");
});

Keep state per wait invocation so parallel tests cannot overwrite it. Avoid placing passwords, access tokens, customer data, or complete page source in messages. CI logs and reports often have broad visibility.

Distinguish condition timeout from a browser command timeout and from the runner's test timeout. The outer test deadline can interrupt a longer FluentWait. Align budgets so the condition can finish and teardown can still run. Track which named waits consume time in CI. Repeated near-timeout success is a performance warning even when tests pass.

12. Selenium Fluent Wait Java Production Checklist

Use this checklist when introducing or reviewing a fluent wait:

  1. The condition names a product state rather than a vague delay.
  2. The timeout reflects the acceptable transition time in the target environment.
  3. The polling interval matches the state and cost of each attempt.
  4. Every ignored exception is transient and recoverable on a later poll.
  5. The function returns null or false while waiting and a useful value on success.
  6. Each poll is observational and avoids repeated side effects.
  7. Dynamic elements are located again inside the condition.
  8. An empty collection does not accidentally count as successful readiness.
  9. Large implicit waits do not distort the explicit wait.
  10. The timeout message identifies the component, record, and desired state.
  11. Failure evidence is focused, redacted, and captured once.
  12. The outer test timeout leaves enough room for failure handling and driver cleanup.

The most reliable synchronization code is often short because the application exposes a clear state. If a wait needs many ignored exceptions and several fallback locators, pause and investigate the page contract. Adding a stable status region or test attribute can be a better engineering fix than expanding the wait.

Interview Questions and Answers

Q: What is FluentWait in Selenium Java?

FluentWait<T> is a configurable implementation of Selenium's Wait<T> interface. It repeatedly evaluates a function until the function returns a non-null, non-false result, a non-ignored exception occurs, or the timeout expires. It supports timeout, polling interval, ignored exceptions, and a custom message.

Q: What is the difference between WebDriverWait and FluentWait?

WebDriverWait extends FluentWait<WebDriver>. It is specialized for WebDriver and ignores NoSuchElementException by default, while raw FluentWait is generic and starts with the policy you configure. I use WebDriverWait for ordinary browser conditions and raw FluentWait when a custom input type or explicit policy adds clarity.

Q: Which exceptions should a fluent wait ignore?

Only exceptions that are expected during the transition and can disappear on a later poll. Late element creation can justify NoSuchElementException, and re-rendering with fresh lookup can justify StaleElementReferenceException. I do not ignore invalid selectors, assertion failures, lost sessions, or all exceptions.

Q: What should an until lambda return?

It should return null or Boolean false while the condition is not ready. On success, it should return true or, preferably, the element or domain value the caller needs. An empty list is non-null, so it must not be returned as a waiting signal.

Q: Why can a FluentWait exceed the expected wall-clock time?

A condition evaluation can contain calls that block, including element lookup under an implicit wait or a slow remote command. The poll interval and timeout do not cancel a command midway. I keep implicit wait at zero or small, keep polls bounded, and align outer test timeouts.

Q: How do you handle stale elements in a wait?

I put the locator inside the condition so every poll gets a new reference. I may ignore StaleElementReferenceException for the known re-render window. I avoid retrying non-idempotent clicks because the first action might already have reached the application.

Q: How do you choose a polling interval?

I consider how quickly the state can change, how expensive each poll is, and whether WebDriver is remote. Interactive DOM transitions can use a moderately responsive interval, while long server jobs should poll less often. I measure rather than copying the shortest possible value.

Common Mistakes

  • Ignoring Exception, RuntimeException, or Throwable and converting real failures into slow timeouts.
  • Returning an empty list from until and accidentally treating it as success.
  • Performing clicks, submissions, or deletes inside a condition that may run multiple times.
  • Caching a WebElement while claiming the wait recovers from staleness.
  • Polling extremely often across Grid without considering remote-call cost.
  • Copying one timeout to every workflow regardless of the product expectation.
  • Combining a long implicit wait with an explicit condition that performs several find calls.
  • Using raw FluentWait everywhere even when WebDriverWait and ExpectedConditions express the requirement clearly.
  • Creating one mutable static wait for parallel tests and multiple drivers.
  • Writing a generic "wait failed" message with no record or desired state.
  • Capturing page source or screenshots on every poll.
  • Setting the condition timeout longer than the enclosing test deadline.

A wait is successful only when it improves both synchronization and diagnosis. If it merely delays a vague failure, the condition or application signal needs redesign.

Conclusion

The correct selenium fluent wait java pattern is a bounded, state-specific polling loop. Configure timeout and cadence from the workflow, ignore only exceptions a fresh poll can repair, and return the ready element or value from until.

Start with one flaky fixed sleep. Identify the observable state it was trying to protect, replace it with a named condition, add a focused timeout message, and verify the test under local and Grid execution. That is the practical path from delay-based tests to intentional synchronization.

Interview Questions and Answers

Describe how FluentWait.until works.

It repeatedly applies a function to the configured input. The wait succeeds when the function returns a value that is neither null nor false. It fails on timeout, interruption, or any exception not included in the ignored set.

How is WebDriverWait related to FluentWait?

WebDriverWait extends `FluentWait<WebDriver>`. It packages the common WebDriver use case and default handling of `NoSuchElementException`. The inherited methods still allow custom polling, messages, and additional ignored exceptions.

What makes an exception safe to ignore during a wait?

The exception must be expected in the current transition and a later poll must be able to recover. For example, a missing element may appear later. A malformed selector or terminated session will not repair itself, so ignoring those only hides the cause.

What is a subtle bug when waiting for a collection?

Returning an empty list signals success because it is non-null. The condition must return null or false until size and content meet the requirement. Returning the final list on success avoids a second lookup.

Why should wait conditions avoid side effects?

The condition may run several times, so a click or submission can be duplicated. It is also unclear whether the action succeeded when a later observation fails. I keep conditions observational and perform the action once after readiness.

How do implicit and fluent waits interact?

Each finder inside the fluent condition can consume the implicit timeout. That can distort polling and extend wall-clock duration beyond intuition. I prefer zero implicit wait with explicit state-specific waits, or I keep any implicit baseline small and measured.

How would you make a FluentWait timeout useful in CI?

I name the expected state with `withMessage`, include a stable record identifier and last safe observation, and capture one screenshot or trace at the test layer. I keep secrets and full page dumps out of the message. I also preserve the last ignored exception for root-cause analysis.

Frequently Asked Questions

How do I create a FluentWait in Selenium Java?

Instantiate `new FluentWait<>(driver)`, then chain `withTimeout`, `pollingEvery`, optional `ignoring`, and `withMessage`. Call `until` with a function that returns a successful value only when the required state is ready.

Is WebDriverWait the same as FluentWait?

`WebDriverWait` is a subclass of `FluentWait<WebDriver>`. It provides WebDriver-focused construction and ignores `NoSuchElementException` by default, while retaining the fluent configuration methods.

What is the default FluentWait polling interval?

Do not build framework behavior around an assumed default. Set `pollingEvery(Duration)` explicitly when cadence matters, and choose it based on transition speed and command cost.

Can FluentWait ignore StaleElementReferenceException?

Yes, you can configure it to ignore that exception. It is useful only when the condition locates a fresh element on each poll and the page is expected to stabilize within the deadline.

Why did my wait return an empty list immediately?

For non-Boolean conditions, any non-null result counts as success, including an empty list. Return `null` until the collection reaches the required size or content state.

Should I click inside a FluentWait condition?

Usually no. The condition can execute multiple times, so repeated side effects can create duplicate actions. Observe readiness in the condition and click once after it returns.

Can FluentWait replace Thread.sleep?

Yes for synchronization, because it waits only as long as needed and verifies a state. A fixed sleep always consumes its full duration and provides no evidence that the interface is ready.

Related Guides