Cheatsheets
Waits Cheatsheet
Implicit, Explicit, Fluent waits, Playwright auto-waiting, and ExpectedConditions reference.
Selenium Waits
Implicit Wait
Tells WebDriver to poll the DOM for a set time when trying to find elements. Applies globally to all findElement calls.
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
// Now every findElement will wait up to 10 seconds
driver.findElement(By.id("loginBtn")).click();Pros
- ✓One line setup — applies everywhere
- ✓Good for simple, stable pages
Cons
- ✗Slows down tests when element is truly absent (always waits full timeout)
- ✗Cannot wait for specific conditions (only element presence)
- ✗Mixing with explicit waits causes unpredictable timeouts
Explicit Wait (WebDriverWait)
Waits for a specific condition before proceeding. Most recommended approach — precise and flexible.
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
// Wait until element is clickable, then click
WebElement loginBtn = wait.until(
ExpectedConditions.elementToBeClickable(By.id("loginBtn"))
);
loginBtn.click();
// Wait for text to appear
wait.until(
ExpectedConditions.textToBePresentInElementLocated(
By.id("welcomeUser"), "Welcome"
)
);Pros
- ✓Waits for exact condition you need
- ✓Fails fast when condition is impossible
- ✓Industry standard — interviewers expect this
Cons
- ✗More verbose than implicit wait
- ✗Need to choose the right ExpectedCondition
Fluent Wait
Like explicit wait but with custom polling interval and exception ignoring. For special cases only.
Wait<WebDriver> fluentWait = new FluentWait<>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(2))
.ignoring(NoSuchElementException.class)
.ignoring(StaleElementReferenceException.class);
WebElement element = fluentWait.until(d ->
d.findElement(By.id("loadedContent"))
);Pros
- ✓Custom polling interval (default is 500ms)
- ✓Can ignore specific exceptions during polling
- ✓Useful for AJAX-heavy pages
Cons
- ✗Overkill for most scenarios
- ✗WebDriverWait is usually sufficient
Playwright Waits
Auto-waiting (Built-in)
Playwright automatically waits for elements to be actionable before performing actions. No explicit waits needed in most cases.
// Playwright auto-waits for element to be visible and stable
await page.locator("#loginBtn").click();
// Auto-waits for input to be editable
await page.locator("#userId").fill("testuser");
// Custom timeout per action
await page.locator("#result").click({ timeout: 15000 });- ✓Zero boilerplate — just write actions
- ✓Handles visibility, stability, and actionability checks
- ✓Per-action timeout override when needed
Assertions with expect()
Playwright Test assertions auto-retry until the condition is met or timeout.
// Auto-retries until text appears (default 5s)
await expect(page.locator("#welcomeUser")).toHaveText("Welcome");
// Wait for element to be visible
await expect(page.locator("#dashboard")).toBeVisible();
// Wait for element count
await expect(page.locator(".product-card")).toHaveCount(6);- ✓Clean, readable assertions
- ✓Auto-retry with configurable timeout
- ✓Better error messages than manual waits
ExpectedConditions Reference
Use with WebDriverWait.until()
| Condition | Description | Code |
|---|---|---|
visibilityOfElementLocated | Element is present in DOM AND visible | wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("dashboard"))) |
elementToBeClickable | Element is visible AND enabled | wait.until(ExpectedConditions.elementToBeClickable(By.id("loginBtn"))) |
presenceOfElementLocated | Element exists in DOM (may not be visible) | wait.until(ExpectedConditions.presenceOfElementLocated(By.id("hiddenInput"))) |
invisibilityOfElementLocated | Element is not visible or not in DOM | wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("loader"))) |
textToBePresentInElementLocated | Element contains specific text | wait.until(ExpectedConditions.textToBePresentInElementLocated(By.id("status"), "Approved")) |
titleContains | Page title contains substring | wait.until(ExpectedConditions.titleContains("Dashboard")) |
titleIs | Page title matches exactly | wait.until(ExpectedConditions.titleIs("Banking - Dashboard")) |
alertIsPresent | JavaScript alert is displayed | wait.until(ExpectedConditions.alertIsPresent()) |
frameToBeAvailableAndSwitchToIt | Frame is available and switches to it | wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("iframe")) |
numberOfWindowsToBe | Specific number of windows/tabs open | wait.until(ExpectedConditions.numberOfWindowsToBe(2)) |
stalenessOf | Element is no longer attached to DOM | wait.until(ExpectedConditions.stalenessOf(oldElement)) |
attributeToBe | Element attribute has specific value | wait.until(ExpectedConditions.attributeToBe(By.id("btn"), "disabled", "true")) |
Best Practices
Do
- ✓Use Explicit Waits (WebDriverWait) — precise and reliable
- ✓Wait for specific conditions, not arbitrary time
- ✓Set reasonable timeouts (5-15 seconds for most cases)
- ✓Use ExpectedConditions — pre-built and tested
- ✓In Playwright, trust the auto-waiting — add manual waits only when needed
Don't
- ✗Thread.sleep(5000) — hardcoded waits waste time and are unreliable
- ✗Mixing implicit + explicit waits — causes unpredictable behavior
- ✗Setting very long implicit waits (30+ seconds) — slows all findElement failures
- ✗Polling in a loop with Thread.sleep — use FluentWait instead
- ✗Catching exceptions to retry — let the wait framework handle retries