In Playwright, many beginners use page.waitForTimeout() to add fixed delays in tests. However, this approach is discouraged because it slows down tests unnecessarily and can lead to flaky behavior.
What are the better alternatives for waiting on conditions or events in Playwright instead of using fixed timeouts?
I used to sprinkle page.waitForTimeout(5000) all over my Playwright tests to “just wait for things to load.” It worked locally but caused flaky tests in CI, sometimes the timeout was too short, other times it was wasted waiting unnecessarily.
Switching to page.waitForSelector(), page.waitForResponse(), or locator.waitFor() made tests much more reliable and faster because they wait only until the actual condition is met, not a fixed time.
Using page.waitForTimeout() is basically a blind sleep. In one of my projects, replacing it with explicit waits for elements or network calls reduced total test time by 40%!
For example, instead of page.waitForTimeout(3000), I now do:
await page.locator('#myButton').waitFor({ state: 'visible' });
This ensures Playwright continues immediately when the element is ready and avoids wasting time.
I ran into subtle flakiness when using fixed timeouts in Playwright. Sometimes animations or AJAX requests were slower, and waitForTimeout() wasn’t enough.
The better approach is to wait for specific events: page.waitForSelector(), page.waitForLoadState(), page.waitForResponse(), or using locator-based assertions like await expect(locator).toBeVisible(). This makes tests deterministic and eliminates arbitrary pauses.