Early access The free plan is live — unlimited tests, no card, yours to keep Get started →
Resources

Playwright documentation, in reading order

Microsoft's browser automation library, and the official documentation for it, arranged in the order it is worth reading.

29 resources27 from official documentationTools

Playwright drives Chromium, Firefox and WebKit through one API, from JavaScript, TypeScript, Python, Java or .NET. It is open source under Apache 2.0 and maintained by Microsoft. It is also what QAright runs on, so treat everything below as a recommendation from an interested party — though the pages linked are Playwright's own, not ours.

Three design decisions account for most of the difference between a Playwright test and the browser tests people remember disliking. They are worth understanding before writing anything, because each one removes a category of code that older frameworks required you to write by hand.

The decisionWhat it removes
Every action re-checks that the element is actionable, and retries until it is or the timeout expiresExplicit waits, sleeps, and the retry helper every team used to write
Assertions are web-first: expect(locator).toBeVisible() polls rather than sampling onceThe race between asserting and rendering
Each test gets a fresh browser context — its own cookies, storage and cache — in millisecondsCross-test pollution, and the cost of a browser launch per test
locator.click()one line of your testAttached✓Visible✓Stable✓Receivesevents✓Enabled✓re-checked until all five pass — or the timeout expiresno sleep, no explicit wait, no retry loop of your own
What one call to click() actually does. Every check is re-evaluated until all of them hold.

The practical consequence is that a correct Playwright test tends to be shorter than the equivalent elsewhere, and that when it fails the failure usually means something. A test full of waitForTimeout calls is a test written against the wrong mental model, and the documentation says so directly.

import { test, expect } from '@playwright/test';

test('a signed-in customer can reach checkout', async ({ page }) => {
  await page.goto('https://example.com/');
  await page.getByRole('link', { name: 'Sign in' }).click();

  await page.getByLabel('Email').fill('ada@example.com');
  await page.getByLabel('Password').fill(process.env.PASSWORD);
  await page.getByRole('button', { name: 'Sign in' }).click();

  // Web-first: polls until the heading appears, or the timeout expires.
  await expect(page.getByRole('heading', { name: 'Basket' })).toBeVisible();
});
No sleeps, no explicit waits, no assertion helper. That is the whole point.
Pick your language, then read that version of the docs

playwright.dev serves a separate copy of every page per language, and the code samples change with it. The test runner — fixtures, projects, sharding, the HTML reporter — is richest in the JavaScript and TypeScript edition; the Python, Java and .NET bindings give you the same browser automation and integrate with that ecosystem's own runner instead.

Getting the first test running

4 entries

An hour, start to finish, including the install.

  1. Scaffolds a project, installs the browser binaries and runs an example. Read the note about --with-deps: on Linux the browsers ship with Playwright but the system libraries they link against do not, and that is the single most common first-run failure.

    playwright.dev
  2. Writing tests

    Official docs

    Actions, assertions, and test isolation, with the reasoning attached. The clearest short statement of what a Playwright test is made of.

    playwright.dev
  3. Records your clicks and emits code using the recommended locators. Best treated as a way to discover the right locator for an awkward control rather than as a way to author whole suites — generated code needs editing before it is worth keeping.

    playwright.dev
  4. UI mode

    Official docs

    A watch-mode runner with a time-travelling trace of every run, a DOM picker and a locator explorer. If you write tests daily and have not tried it, this is the page on this list most likely to change your afternoon.

    playwright.dev

The execution model

4 entries

The four pages that explain why a test behaves the way it does.

  1. Locators

    Official docs

    How to find elements, in the recommended order of preference, plus filtering, chaining and strict mode. The most load-bearing page in the whole documentation.

    playwright.dev
  2. The list of checks every action performs first — attached, visible, stable, receives events, enabled — and which actions perform which. Read it once and most timing questions answer themselves.

    playwright.dev
  3. Assertions

    Official docs

    Every matcher, split into the auto-retrying ones and the ones that check a value immediately. Using a non-retrying matcher on something the page renders asynchronously is the classic self-inflicted flake.

    playwright.dev
  4. Timeouts

    Official docs

    Test timeout, expect timeout, action timeout, navigation timeout, global timeout — what each covers and how they compose. Worth reading before raising any of them.

    playwright.dev

Structure, once there is more than one test

5 entries
  1. Fixtures

    Official docs

    Playwright's answer to setup and teardown, and a better one than before-each hooks: a fixture is requested by name, built only for the tests that ask for it, and torn down automatically. This is how you share a logged-in state or a seeded record without a web of globals.

    playwright.dev
  2. Page object models

    Official docs

    The official take, including the unfashionable but correct point that a page object is worth writing when it removes duplication and not before.

    playwright.dev
  3. Projects

    Official docs

    One config, several named runs: browsers, viewports, environments, and setup projects that other projects depend on. This is how a smoke subset and a full matrix live in one repository.

    playwright.dev
  4. Data-driven tests done properly: a list of cases, a test per case, and a distinct title for each so a failure names the row that failed. Also covers reading the cases from a CSV or JSON file, and parameterising a whole project through the config rather than the test.

    playwright.dev
  5. Every option in playwright.config, with defaults. The place to check before copying a config block from a blog post.

    playwright.dev

When it fails

4 entries

The pages that turn “it broke on CI” into a fixable statement.

  1. Trace viewer

    Official docs

    A recorded trace of a run: DOM snapshot at every step, network, console, source, and a timeline you can scrub. Turning traces on for retries costs almost nothing and is the highest-value line in most CI configs.

    playwright.dev
  2. Debugging tests

    Official docs

    The Playwright Inspector, VS Code integration, page.pause(), and headed mode. Covers the browser developer tools route as well, which people forget is available.

    playwright.dev
  3. Retries

    Official docs

    How to configure retries per project or per run, and the reporting rule that matters more than the configuration: a test that passes on a retry is reported as flaky, not as a pass. That is what makes retries survivable rather than corrosive.

    playwright.dev
  4. Capture on failure only, capture always, full-page or viewport, and how the artefacts attach to the report. A full-page screenshot is usually the right default: the error banner is often below the fold.

    playwright.dev

Beyond clicking things

6 entries
  1. API testing

    Official docs

    Playwright can issue HTTP requests directly, with the browser's cookies or without them. Use it to set up state in two seconds instead of twenty, and to assert on the response a UI action produced.

    playwright.dev
  2. Network and mocking

    Official docs

    Intercept, modify, stub or record and replay any request the page makes. The honest way to test an error state you cannot make a real backend produce on demand.

    playwright.dev
  3. Authentication

    Official docs

    Sign in once, save the storage state, reuse it across every test. This single technique removes more runtime from a typical suite than any other change on this page.

    playwright.dev
  4. Visual comparisons

    Official docs

    Screenshot assertions with a stored baseline, tolerance settings, and the masking you will need to make them survivable. Read the caveats before adopting these widely.

    playwright.dev
  5. Emulation

    Official docs

    Devices, viewports, locale, timezone, colour scheme, geolocation and permissions. How to test the mobile layout without a mobile device farm.

    playwright.dev
  6. The official guide to running axe inside a Playwright test, including how to scope a scan and how to handle known violations without switching the check off.

    playwright.dev

The other bindings, and the project itself

6 entries
  1. The same browser automation with pytest integration, sync and async APIs. The natural choice if the rest of your tooling is Python.

    playwright.dev
  2. Playwright for .NET

    Official docs

    NUnit and MSTest base classes, the idiomatic C# API, and the same trace viewer and codegen tooling. This is the binding QAright's exported test code targets, so the pages here describe the code a downloaded bundle actually contains.

    playwright.dev
  3. Playwright for Java

    Official docs

    The Java API surface and JUnit integration, for teams whose build is already Maven or Gradle and whose testers would rather not maintain a second toolchain in a second language just to drive a browser.

    playwright.dev
  4. Release notes

    Official docs

    Playwright ships often and the release notes are written to be read. Scanning them once a month is the cheapest way to find out that the workaround you maintain is now a built-in.

    playwright.dev
  5. The source, the issue tracker, and the place to check whether the behaviour surprising you is a known bug. Issues here are answered by the maintainers unusually often.

    github.com
  6. Discord, the community-maintained tool list, and the ambassador programme. Useful for the questions that are too vague for an issue.

    playwright.dev

What to take away

  • Read actionability once.Almost every “why do I need a wait here” question is answered by that one page, and the answer is usually that you do not.
  • Turn on traces for retries.One config line, and it converts “only fails in CI” from an argument into a recording.
  • Save the signed-in state.Authenticating once and reusing storage state is the biggest single runtime saving available to most suites.
Missing something? If there is a resource you send to every new tester on your team, tell us and we will read it. The list stays short on purpose; each entry has to earn its place, and entries that stop earning it get removed rather than left to rot.

Reading is the slow way to learn how a suite behaves. Record one against your own app, free, and watch what the report says.

Get started free See how it works