Playwright Waiting Timeout
This chapter provides an in-depth introduction to Playwright's auto-wait mechanism, as well as complete knowledge of manual waiting and timeout configuration.
* * *
## Why Auto-Wait is Needed
Modern web applications heavily use async rendering, and page content doesn't load instantly.
In traditional test frameworks, developers have to write `sleep` or `waitFor` to wait, but these operations are not flexible enough - either waiting too long slows down tests, or not waiting enough causes flaky tests.
Playwright builds wait logic into every Locator and Action, fundamentally solving this problem.
* * *
## Three-Layer Auto-Wait System
### First Layer: Locator's Auto-Wait
When you create a Locator, Playwright doesn't search for the element immediately. Instead, it starts searching and auto-waits when you perform an operation or assertion.
## Example
// Create Locator (element is not searched at this time)
const btn = page.getByRole('button',{ name:'Delayed Button'});
// Auto-wait for button to appear when clicking (waits up to action timeout)
await btn.click();
### Second Layer: Action's Operability Check
Before performing an operation (click, fill, etc.), Playwright ensures the element: Attached β Visible β Stable β Receives Events β Enabled.
### Third Layer: Assertion's Auto-Retry
When an assertion fails, it doesn't report an error immediately. Instead, it continuously retries until the condition is met or timeout occurs.
## Example
// This assertion will keep retrying for 5 seconds until the text appears or timeout
await expect(page.getByText('Data Loaded')).toBeVisible();
* * *
## Manual Waiting Methods
In special scenarios where auto-wait is not sufficient, Playwright also provides manual waiting methods.
### page.waitForTimeout(ms) β Fixed Wait
## Example
// Fixed wait for 2 seconds (generally not recommended)
await page.waitForTimeout(2000);
> Try to avoid using `waitForTimeout`. Fixed waits are extremely unstable under different device performance. Prioritize using the event-driven waits like `waitForURL` and `waitForResponse` mentioned later.
### page.waitForURL() β Wait for URL Change
## Example
// Wait for exact URL match
await page.waitForURL('');
// Wait for URL to contain specific pattern
await page.waitForURL(/dashboard/);
### page.waitForLoadState() β Wait for Load State
## Example
// Wait for load event
await page.waitForLoadState('load');
// Wait for DOMContentLoaded
await page.waitForLoadState('domcontentloaded');
// Wait for network idle
await page.waitForLoadState('networkidle');
### page.waitForResponse() β Wait for Network Response
## Example
// Wait for specific API response
const response = await page.waitForResponse(
resp => resp.url().includes('/api/data')&& resp.status()===200
);
// Get response data
const data = await response.json();
### page.waitForEvent() β Wait for Event
## Example
// Wait for dialog to appear
const dialogPromise = page.waitForEvent('dialog');
await page.getByRole('button',{ name:'Delete'}).click();
const dialog = await dialogPromise;
await dialog.accept();
// Wait for new page to open
const pagePromise = page.context().waitForEvent('page');
await page.getByRole('link',{ name:'Open New Window'}).click();
const newPage = await pagePromise;
* * *
## Timeout Configuration Details
Playwright has 4 types of timeouts, each acting on different levels:
| Timeout Type | Config File Location | Default Value | Target |
| --- | --- | --- | --- |
| Test timeout | `timeout` | 30000ms | Entire test case |
| Expect timeout | `expect.timeout` | 5000ms | Assertion retry |
| Action timeout | `use.actionTimeout` | None (unlimited) | Element operations (click, fill, etc.) |
| Navigation timeout | `use.navigationTimeout` | None (unlimited) | Page navigation (goto, goBack, etc.) |
### Global Configuration
## Example
// File path: playwright.config.ts
import{ defineConfig } from '@playwright/test';
export default defineConfig({
// Total timeout for each test (milliseconds)
timeout:60000,
// Timeout for assertion auto-retry
expect:{
timeout:10000,
},
use:{
// Timeout for each operation (click, fill, etc.)
actionTimeout:15000,
// Timeout for each navigation
navigationTimeout:30000,
},
});
### Single Setting (Higher Priority Than Global)
## Example
// Set total timeout for single test
test.setTimeout(120000);
// Set timeout for single operation
await page.getByRole('button').click({ timeout:30000});
// Set timeout for single navigation
await page.goto('',{ timeout:60000});
### Timeout Priority
Single setting > Config file global setting > Default value.
* * *
## Suggestions for Setting Timeouts Appropriately
| Scenario | Recommended Timeout | Description |
| --- | --- | --- |
| Local development | Default value | Local services respond quickly, default is sufficient |
| CI environment | 2~3x default value | CI machine performance fluctuates |
| Slow pages | `actionTimeout: 150
YouTip