Knowledge check
Nine questions on the decisions that matter most in a real Playwright suite. Each answer comes with a short explanation, so a wrong answer points you back to the right chapter.
1. A test clicks "Save" and then runs expect(await page.getByText('Saved').isVisible()).toBe(true). It fails about one run in ten. What is the best fix?
isVisible() answers immediately and never retries, so the generic toBe sees a snapshot. The web-first assertion retries until the text appears. Raising the timeout does nothing here, because nothing is waiting on it.
2. page.getByRole('checkbox', { name: 'Toggle Todo' }).check() throws a strict mode violation because three rows match. Which change best expresses the intent "complete the Pay rent item"?
Filtering the row by its content and then searching inside it targets the right item regardless of order. .first() and .nth() silently depend on list order, which is exactly what strictness is trying to stop you from relying on.
3. With fullyParallel: true and four workers, where should one-time "log in and save the session" work go?
beforeAll runs once per worker (and again after a worker restarts), and beforeEach logs in before every test. A setup project runs once before the dependent projects, shows up in the report and can record a trace.
4. A test failed on CI, passed on retry, and the job stayed green. Where do you look first?
The report marks it flaky for a reason: something in the test does not wait for the right state. trace: 'on-first-retry' exists so that you have a trace for exactly this case.
5. Your project uses devices['iPhone 12']. What does that give you?
Device presets are emulation: a browser engine plus viewport, user agent, scale factor and touch settings. That is great for responsive layout bugs, but it is not the real mobile browser on real hardware.
6. You shard a suite with --shard=1/4 ... --shard=4/4 across four GitHub jobs. How do you end up with a single HTML report?
Blob reports contain the full run data and are designed to be merged. Each HTML report is a self-contained site, so uploading four of them under one name just overwrites or collides.
7. A test only fails on CI and you were not watching. Which tool gives you DOM snapshots before and after every action, network calls and console output after the fact?
Codegen records new tests and the Inspector needs you there while the test runs. A trace is a recording of a run that already happened, which is what a CI failure needs.
8. In a Playwright Test project that connects to a remote Firefox through connectOptions.wsEndpoint, what else must the project set?
The runner calls connect() on the browser type named by the project's browserName, which defaults to chromium. Chrome and Edge use chromium, Firefox uses firefox, and Safari uses webkit.
9. Two parallel tests both log in as the same user and edit that user's profile. They pass alone and fail together. What is the root cause?
Every test already gets its own context, so nothing leaks in the browser. The collision is in the application's data. Give each worker its own account (for example keyed on testInfo.parallelIndex) or create unique data per test.
Where to go next#
If your suite is growing past a handful of files, the Page Object Model course shows how to structure locators and actions so the tests stay readable. To run what you built here across more browsers and operating systems, the Playwright documentation for TestingBot covers every language binding and option, and the official Playwright best practices guide is worth reading end to end.
You finished Playwright Tutorial: Zero to CI
Put what you learned into practice. Run your tests on 6100+ real browsers and physical iOS and Android devices.