In Selenium's ExpectedConditions, what do presenceOfElementLocated, visibilityOfElementLocated and elementToBeClickable each check?
answer
- Three separate checks, not one
- Existing is not the same as showing
- Rendered box needs non-zero size
- The strongest one also reads enabled state
- isDisplayed, then isEnabled
basics
~10 spresenceOfElementLocated 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 sThey 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 linesWebDriverWait 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
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.
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.
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.
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