skip to content

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

level: juniorimportance: should knowfreq 72%

answer

  1. Three separate checks, not one
  2. Existing is not the same as showing
  3. Rendered box needs non-zero size
  4. The strongest one also reads enabled state
  5. isDisplayed, then isEnabled

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.

solid answer

~40 s

They are three escalating checks on the same node, and all three hand the `WebElement` back. `presenceOfElementLocated(By)` just calls `findElement` and returns the element as soon as it exists in the DOM, hidden or not. `visibilityOfElementLocated(By)` finds it and then requires `isDisplayed()` to be true, which rules out `display: none`, `visibility: hidden` and a zero-width or zero-height box. `elementToBeClickable(By)` does the displayed check and then also requires `isEnabled()`, and it records which of the two failed so the `TimeoutException` message tells you. Pick the weakest one that is true of the state you actually need: a handle for a script needs presence, reading rendered text needs visibility, a click needs clickability.

code

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

wait.until(ExpectedConditions.presenceOfElementLocated(By.id("placement-quiz")));

WebElement banner = wait.until(
    ExpectedConditions.visibilityOfElementLocated(
        By.cssSelector("#placement-quiz .level-banner")));

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

go deeper

for a junior

Be ready to name the three conditions and say in one line what each adds: exists, exists and is painted, painted and enabled. Knowing that all three give you the element back is the other half of the answer.

for a middle

Explain the mechanics: presence is a bare findElement, visibility routes the result through an isDisplayed check, and clickability adds isEnabled and records which half failed for the timeout message.

for a senior

Show judgment about picking the weakest condition that is genuinely true of the state under test, and explain why over-strengthening a wait produces timeouts that point at the wrong thing.

for a principal

Own the convention: which condition a team's page objects default to, and how that default shapes whether a failing wait reads as a product bug or as a test that asserted more than it needed.

## Three checks, three different questions `ExpectedConditions` is the class of ready-made predicates that ships with Selenium 4 in `org.openqa.selenium.support.ui`. Every static factory on it returns an `ExpectedCondition<T>`, and you hand that to `WebDriverWait.until(...)`. Three of those factories look interchangeable and are not: **presence**, **visibility** and **clickability** answer three escalating questions about the same node. Take a language-school placement quiz. The page paints a level selector, a `Start placement test` button that stays `disabled` until a level is chosen, and a results panel that is in the markup from the first render but styled `display: none` until grading finishes. - **Presence** asks *is this node in the DOM at all?* - **Visibility** asks *is it in the DOM and painted with a real box?* - **Clickability** asks *is it painted and does the browser report it as enabled?* ## presenceOfElementLocated `ExpectedConditions.presenceOfElementLocated(By)` calls `driver.findElement(locator)` on each poll. If the driver throws `NoSuchElementException` the condition returns `null`, which tells the wait to poll again; otherwise it returns the `WebElement`. That is the entire predicate. It never reads `isDisplayed()`, so the hidden results panel on the placement quiz satisfies it the moment the markup exists. Reach for it when what you need is a **handle** rather than a rendered thing: reading an attribute, counting children, or passing the element into a script. ## visibilityOfElementLocated `ExpectedConditions.visibilityOfElementLocated(By)` finds the element and then runs it through an internal `elementIfVisible` helper, which hands the element back when `element.isDisplayed()` is true and `null` otherwise. It also catches `StaleElementReferenceException` alongside `NoSuchElementException` and returns `null` for both, so a node re-rendered between the find and the display check costs one more poll instead of ending the wait. `isDisplayed()` is the browser's own rendered-ness verdict, not a CSS string comparison. An element that is `display: none`, `visibility: hidden`, or laid out with zero width or zero height is not displayed. There is a companion, `ExpectedConditions.visibilityOf(WebElement)`, that takes an element you already hold instead of a locator. It cannot re-find, so it is the wrong tool when the node is being replaced. ## elementToBeClickable `ExpectedConditions.elementToBeClickable(By)` finds the element and then checks two things, in order: `isDisplayed()`, and then `isEnabled()`. If the first check fails it records the note `was not visible`; if the second fails it records `was not enabled`. Those notes end up in the `TimeoutException` message, which is why a timeout on this condition tells you which half of the check never came true. When both pass, the `WebElement` is returned. An overload accepts a `WebElement` in place of a `By`. On the placement quiz this is the right condition for the `Start placement test` button: the button is painted immediately but stays `disabled` until a level is picked, so visibility alone would let the click fire too early. ## What each one hands back | Condition | What it evaluates | Value on success | Value while still waiting | |---|---|---|---| | `presenceOfElementLocated` | `findElement` succeeds | the `WebElement` | `null` on `NoSuchElementException` | | `visibilityOfElementLocated` | found **and** `isDisplayed()` | the `WebElement` | `null`, staleness included | | `elementToBeClickable` | `isDisplayed()` **and** `isEnabled()` | the `WebElement` | `null`, with a reason recorded | All three return the element itself, so `until` gives it straight back to you and there is no reason to find it a second time: ```java WebElement start = wait.until( ExpectedConditions.elementToBeClickable(By.id("start-placement-test"))); start.click(); ``` ## Picking the right one 1. Decide what you are about to do with the node. Reading rendered text needs visibility; clicking needs clickability; handing a reference to a script needs only presence. 2. Choose the **weakest condition that is still true** of the state you actually need. A stronger condition is not "safer" — it is a different assertion, and it can time out for a reason that has nothing to do with what your test is checking. 3. Keep the value `until` returns instead of re-finding the element, because all three of these hand it back. A few consequences worth carrying into an interview: - Presence passing tells you nothing about whether a learner could see the panel. - Visibility passing tells you nothing about whether the control accepts input, because a painted button can still carry `disabled`. - Clickability is the strongest of the three, and it is built out of exactly two reads on the element, `isDisplayed()` and `isEnabled()`. - Selenium 4's `WebDriverWait` takes a `java.time.Duration`, so these conditions are normally written as `new WebDriverWait(driver, Duration.ofSeconds(10)).until(...)`.

  • Why does visibilityOfElementLocated catch StaleElementReferenceException when presenceOfElementLocated does not?
    Visibility does two steps: find the element, then read `isDisplayed()` on it. The node can be replaced between those steps, so the condition catches staleness and returns `null` to poll again. Presence only does the find, so the only miss it has to absorb is `NoSuchElementException`.
  • When would you deliberately choose presenceOfElementLocated over visibilityOfElementLocated?
    When you need a reference rather than a rendered thing: passing the element into a script, reading an attribute off a node that is intentionally hidden, or counting children of a container whose wrapper has no box of its own. Waiting for visibility there would time out on a page that is behaving correctly.
  • What is the difference between visibilityOf and visibilityOfElementLocated?
    `visibilityOf(WebElement)` takes an element you already hold and only re-checks `isDisplayed()` on it, so it cannot recover if that node is replaced. `visibilityOfElementLocated(By)` re-runs the lookup on every poll, which is what you want whenever the page re-renders the region.

Presence is the student's name being on the register; visibility is the student actually sitting in the room; clickability is the student sitting there and allowed to start the paper.

saying these in an interview costs you the question

  • Says presenceOfElementLocated guarantees the element is showing on screen
  • Treats visibility and clickability as interchangeable conditions
  • Thinks an element with zero width and height still counts as displayed
  • Assumes elementToBeClickable ignores the element's enabled state
  • Confuses visibilityOf, which takes a WebElement, with visibilityOfElementLocated