All challenges · Core Interactions
Challenge 13 of 29 · Building fluency · Core Interactions
Wait for Dynamic Content Without Sleeps
Start something that finishes later, without adding a fixed delay. You learn why Playwright waits for you and why sleeps make tests slow and flaky.
Skills you will practise
- auto-waiting
- no fixed sleeps
- delayed content
The concept
Modern pages load data after the first render: a spinner appears, a request finishes, results arrive. A fixed delay such as waitForTimeout(5000) guesses how long that takes. Guess too short and the test fails on a slow CI runner; guess too long and every run wastes time.
Playwright is built to avoid guessing. Actions like click() and fill() auto-wait for the element to be attached, visible, stable, enabled and able to receive events. Web-first assertions such as expect(locator).toBeVisible() or toHaveText() keep retrying until the condition is true or the timeout (5 seconds by default) is reached.
So the rule is: wait for a state, not for a time. Describe what “done” looks like and assert on it.
The fragile version
await page.getByRole('button', { name: 'Load results' }).click();
await page.waitForTimeout(5000);
const text = await page.locator('#results').textContent();
expect(text).toContain('3 results');Why it breaks: The sleep is either too long (slow) or too short (flaky), and textContent() reads once with no retry.
A robust Playwright version
await page.getByRole('button', { name: 'Load results' }).click();
await expect(page.getByText('3 results')).toBeVisible();
// Need more than 5s? Raise the timeout for this check only:
await expect(page.getByRole('status')).toHaveText('Done', { timeout: 15000 });The test finishes as soon as the content arrives and only fails if it genuinely never does.
This is a general example on a made-up page, not the challenge’s reference solution.
Common mistakes
- Leaving
waitForTimeoutin committed tests; the Playwright docs say it is for debugging only. - Mixing non-retrying reads (
textContent,isVisible) with plainexpect. - Raising the global timeout instead of the one slow check.
FAQ
Is waitForTimeout bad in Playwright?
For real tests, yes. It is meant for debugging; prefer web-first assertions.
What does Playwright auto-wait for?
Before actions it checks the element is visible, stable, enabled and receives events, depending on the action.
How do I wait for a spinner to disappear?
await expect(spinner).toBeHidden().
Try it
Practise this in Challenge 13. You write the code in the browser editor with no setup. It runs in a fresh Chromium, a hidden validator checks what actually happened, and you get pass or fail, the logs and a video of the run. Create a free account to open the practice page and its hints. The reference solution and the hidden validator are shown only after you pass. We never publish solutions here.