66 / 139 · 13 Browser Automation with Playwright · Contexts, Waiting, and Assertions← prev⊞ allnext →☰ Read as one page
6.3Auto-Waiting
In Selenium, the #1 source of test flakiness is timing: the test tries to interact with an element before it is ready. Playwright eliminates this by auto-waiting before every action.
When you call page.click('button'), Playwright automatically waits for the element to be:
- Attached to the DOM
- Visible (not hidden by CSS)
- Stable (not animating)
- Enabled (not disabled)
- Receiving events (not obscured by another element)
Only then does the click execute. If any condition is not met, Playwright retries until the timeout.
// Playwright: just click — auto-waiting handles timing
await page.getByRole('button', { name: 'Submit' }).click();
// Selenium: must manually wait, then click
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//button[text()='Submit']"))
).click()
What Auto-Waiting Covers
| Action | Waits For |
|---|---|
click() |
Attached, visible, stable, enabled, receives events |
fill() |
Attached, visible, enabled, editable |
check() |
Attached, visible, stable, enabled |
selectOption() |
Attached, visible, enabled |
textContent() |
Attached |
isVisible() |
Nothing (returns immediately) |
When You Still Need Explicit Waits
Auto-waiting handles interactions, but sometimes you need to wait for a condition before proceeding:
// Wait for a specific response after triggering an action
await page.waitForResponse('**/api/orders');
// Wait for navigation
await page.waitForURL('**/dashboard');
// Wait for an element to disappear (loading spinner)
await page.getByTestId('spinner').waitFor({ state: 'hidden' });