skip to content

Prebuilt Condition Helpers

The shipped library of ready-made predicates, what each one hands back, and how they combine. Interviewers check that you treat presence, visibility and clickability as three different checks.

on this pageshow

explore

questions

4

In Selenium's ExpectedConditions, which helpers hand back a usable WebElement and which only hand back a Boolean?

level: middleimportance: must knowfreq 61%

answer

  1. The wait returns what the predicate returned
  2. Asks for a node versus asserts a fact
  3. Some give a list, one gives a dialog
  4. Negative checks have nothing to hand back
  5. Assign it instead of finding twice

basics

~20 s

Helpers that ask for a node return it: presenceOfElementLocated, visibilityOfElementLocated, visibilityOf and elementToBeClickable give a WebElement, the all-elements helpers give a list, alertIsPresent gives an Alert. Helpers that assert a page fact, such as invisibilityOfElementLocated, stalenessOf and titleIs, give only a Boolean.

solid answer

~30 s

`until` returns whatever the condition returned, unchanged, so the condition's type is what you get. The node-shaped helpers hand the element back — `presenceOfElementLocated`, `visibilityOfElementLocated`, `visibilityOf` and both `elementToBeClickable` overloads all produce a `WebElement`; `presenceOfAllElementsLocatedBy`, `visibilityOfAllElementsLocatedBy` and the `numberOfElementsToBe` family produce a `List<WebElement>`; `alertIsPresent` produces an `Alert`. The statement-shaped helpers produce only `Boolean`: `invisibilityOfElementLocated`, `stalenessOf`, `titleIs`, `textToBePresentInElementLocated`, `elementToBeSelected`, `numberOfWindowsToBe` and the `or`/`and`/`not` combinators. The practical rule is to assign the element-returning ones instead of finding the node a second time, which removes a re-render race between the wait and the action.

code

java · 11 lines
java
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

WebElement startButton = wait.until(
    ExpectedConditions.elementToBeClickable(By.id("start-placement-test")));
startButton.click();

List<WebElement> cards = wait.until(
    ExpectedConditions.presenceOfAllElementsLocatedBy(By.cssSelector(".quiz-question")));

boolean spinnerGone = wait.until(
    ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(".grading-spinner")));

go deeper

for a junior

Remember that a wait on visibility or clickability gives you the element, so you can chain the click straight onto the wait call rather than searching for it again.

for a middle

Explain the split by shape: node-shaped helpers return an element or a list, statement-shaped ones return a Boolean, and until passes the value through untouched.

for a senior

Show why the split matters in a real suite: the second lookup after a wait is a re-render race, and page-object signatures follow directly from which family a helper belongs to.

for a principal

Own the API convention your framework exposes, so that helper methods return what callers actually need and nobody re-finds a node the wait already located.

## `until` gives back exactly what the condition gave it `FluentWait.until(Function)` — the method `WebDriverWait` inherits — keeps calling the supplied function until it returns something that is neither `null` nor `Boolean.FALSE`, and then **returns that value to you**. Nothing in the wait converts or unwraps it. So the useful question about any member of Selenium 4's `ExpectedConditions` class is not only "what does it check" but "what type does it produce", because that type is what lands in your variable. Concretely, on a language-school placement quiz, `elementToBeClickable(By.id("start-placement-test"))` returns the button itself, so the wait and the click are one statement. `invisibilityOfElementLocated(By.cssSelector(".grading-spinner"))` returns `Boolean.TRUE`, so there is nothing to click and nothing to keep. ## The element-returning family These hand back a live reference you should keep: - `presenceOfElementLocated(By)` — the `WebElement` as soon as `findElement` succeeds. - `visibilityOfElementLocated(By)` — the `WebElement` once it is also displayed. - `visibilityOf(WebElement)` — the same element you passed in, once displayed. - `elementToBeClickable(By)` and `elementToBeClickable(WebElement)` — the element once it is displayed and enabled. - `presenceOfNestedElementLocatedBy(...)` — the nested `WebElement`. A second group returns a collection rather than a single node: `presenceOfAllElementsLocatedBy(By)`, `visibilityOfAllElementsLocatedBy(By)`, `visibilityOfNestedElementsLocatedBy(...)`, `numberOfElementsToBe(By, int)`, `numberOfElementsToBeMoreThan(...)` and `numberOfElementsToBeLessThan(...)` all produce a `List<WebElement>`. That is genuinely useful on a placement quiz: waiting for the twenty question cards and getting the list in the same call. One member stands alone: `alertIsPresent()` produces an `Alert` handle rather than a `WebElement` or a `Boolean`, returning `null` while no dialog is up. ## The Boolean family Everything phrased as a *statement about the page* rather than *a request for a node* returns `Boolean`: - `invisibilityOfElementLocated(By)` and `invisibilityOf(WebElement)` - `stalenessOf(WebElement)` - `titleIs(String)`, `titleContains(String)`, `urlToBe(String)`, `urlContains(String)` - `textToBePresentInElementLocated(By, String)` and `textToBe(By, String)` - `elementToBeSelected(...)` and `elementSelectionStateToBe(...)` - `numberOfWindowsToBe(int)` - `attributeToBe(...)`, `attributeContains(...)`, `domAttributeToBe(...)`, `domPropertyToBe(...)` - the combinators `or(...)`, `and(...)` and `not(...)` For all of these the only success value is `true`, because `FluentWait` treats `Boolean.FALSE` as "keep polling". Assigning the result is legal but tells you nothing you did not already know from the fact that the call returned rather than threw. | Shape | Example factories | Type from `until` | What you do next | |---|---|---|---| | Single node | `visibilityOfElementLocated`, `elementToBeClickable` | `WebElement` | act on the returned element | | Many nodes | `presenceOfAllElementsLocatedBy`, `numberOfElementsToBe` | `List<WebElement>` | iterate the returned list | | Dialog | `alertIsPresent` | `Alert` | keep the returned handle | | Page statement | `invisibilityOfElementLocated`, `stalenessOf`, `titleIs` | `Boolean` | carry on; nothing is handed back | ## Why the distinction is worth money 1. **It removes a race.** If you wait on `visibilityOfElementLocated` and then call `driver.findElement` with the same locator, you have done two finds, and the page can re-render between them. Assigning the returned element does one find. 2. **It shapes your page objects.** A method that wraps an element-returning condition can have a `WebElement` return type; one that wraps a Boolean condition cannot, and pretending otherwise forces a redundant lookup inside it. 3. **It explains the combinators.** `or(...)` and `and(...)` are declared to produce `Boolean`, so composing two element-returning conditions loses both elements. `refreshed(ExpectedCondition<T>)` is the exception — it is generic in `T` and preserves whatever the wrapped condition produced. ## A worked case from the placement quiz The submit step on a placement quiz needs all three shapes in a row, and each one is used differently: 1. `elementToBeClickable(By.id("submit-placement"))` returns the button, so the wait and the `click()` are one statement and no second lookup can race the re-render that the click triggers. 2. `invisibilityOfElementLocated(By.cssSelector(".grading-spinner"))` returns `Boolean.TRUE` and nothing else, so the next line has to locate the results panel on its own. 3. `presenceOfAllElementsLocatedBy(By.cssSelector(".score-row"))` returns the `List<WebElement>` of score rows, which you iterate directly instead of running `findElements` again. The pattern is the same each time: if the condition's name asks for a node, keep what comes back; if it asserts a fact about the page, the call's only product is the fact that it returned at all. ## Practical notes - The element you get back is an ordinary `WebElement`, with all the usual consequences: it can go stale later, and holding it across a navigation is not safe. - A Boolean-returning condition that never becomes true ends in `TimeoutException`, and the message includes the condition's own `toString()` — which is why the shipped conditions all override `toString()` with a readable phrase such as `element found by ... to become invisible`. - Selenium 4 spells the timeout as a `java.time.Duration`, so these are written `new WebDriverWait(driver, Duration.ofSeconds(10)).until(...)`; the older seconds-as-`long` constructor is gone.

  • Why is assigning the element returned by a wait better than finding it again on the next line?
    Finding it again is a second lookup, and the page can re-render between the two. The condition already did a find that succeeded, so keeping its result removes that window entirely and saves a round trip to the driver.
  • What happens to the element type when you wrap two element conditions in and()?
    It is lost. `and(...)` is declared as an `ExpectedCondition<Boolean>`, so it reports only that every branch passed. `refreshed(ExpectedCondition<T>)` is the one wrapper that stays generic and gives back whatever the condition it wraps produced.
  • Why can a Boolean-returning condition never end the wait by returning false?
    The polling loop treats `null` and `Boolean.FALSE` identically as 'not yet' and keeps going until the timeout. So the only value such a condition can end a wait with is `true`; a persistent false state ends in `TimeoutException` instead.

saying these in an interview costs you the question

  • Thinks every ExpectedConditions helper returns a WebElement
  • Calls findElement again right after a visibility wait succeeded
  • Expects invisibilityOfElementLocated to return the hidden element
  • Believes until converts the condition's result into a Boolean
  • Assumes a Boolean condition can end a wait by returning false
open as a page

In Selenium's ExpectedConditions, how do or(), and(), not() and refreshed() compose other conditions?

level: seniorimportance: must knowfreq 48%

basics

~20 s

or() passes when any branch is satisfied, and() when every branch is, and not() when the wrapped one is not. All three yield a Boolean, losing any element. refreshed() wraps a single condition, keeps its return type, and absorbs staleness so the poll retries.

open as a page

In Selenium's ExpectedConditions, what do presenceOfElementLocated, visibilityOfElementLocated and elementToBeClickable each check?

level: juniorimportance: should knowfreq 72%

basics

~10 s

presenceOfElementLocated only requires the element to exist in the DOM. visibilityOfElementLocated additionally requires it to be displayed with a non-zero box. elementToBeClickable requires that displayed state plus the element reporting itself as enabled.

open as a page

In Selenium, which page states make ExpectedConditions.invisibilityOfElementLocated return true instead of polling again?

level: middleimportance: should knowfreq 50%

basics

~20 s

Three states satisfy it: the element is found but not displayed, the locator matches nothing, or the element went stale mid-check. It returns a Boolean, not the element, and passes instantly when the locator never matched.

open as a page