Answer
What is Auto-Waiting in Playwright?
Auto-waiting is one of Playwright's most powerful features. Before every action (click, fill, check, etc.), Playwright automatically waits for the target element to be in an actionable state — without you writing any wait code.
What Playwright Checks Before Each Action
When you call locator.click(), Playwright waits for ALL of these:
| Check | Description |
|---|---|
| Attached | Element exists in the DOM |
| Visible | Element is visible (not display:none, not opacity:0, not zero size) |
| Stable | Element is not animating or moving |
| Enabled | Element is not disabled |
| Editable | For fill/type — element is not readonly |
| Receives Events | No overlay is blocking the element |
Before Auto-waiting (Selenium-style)
// Selenium — you had to write this manually
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.elementToBeClickable(By.id("submit")));
driver.findElement(By.id("submit")).click();
With Playwright Auto-waiting
// Playwright — just click. It waits automatically.
await page.getByRole('button', { name: 'Submit' }).click();
Auto-waiting in Assertions
expect() also retries automatically — it re-checks until the assertion passes or times out:
// Playwright retries this assertion until it's true (up to timeout)
await expect(page.locator('.success-banner')).toBeVisible();
await expect(page.locator('#count')).toHaveText('10');
No need for sleep(2000) before checking!
Default Timeouts
| Context | Default Timeout |
|---|---|
Action timeout (click, fill, etc.) | 30 seconds |
expect() assertion | 5 seconds |
page.goto() navigation | 30 seconds |
Override globally in config:
// playwright.config.ts
export default defineConfig({
use: {
actionTimeout: 10_000, // 10s per action
navigationTimeout: 30_000, // 30s for navigation
},
expect: { timeout: 10_000 }, // 10s for assertions
});
Override per action:
await page.locator('#slow-element').click({ timeout: 60000 });
Why This Eliminates Flakiness
Most test flakiness comes from timing issues — an element isn't ready yet when the test tries to interact with it. Auto-waiting directly solves this by making every interaction inherently wait for the right state.
