Playwright Best Practices

Production-grade Playwright TypeScript patterns — framework architecture, authentication, CI/CD, flaky test prevention, accessibility, and 13 documented anti-patterns.

View on GitHub Quick Start
CI status Playwright 1.52+ TypeScript 5.x MIT License

10 Reference Sections

Every pattern sourced from official Playwright documentation or clearly labelled as an architectural decision.

01

Framework Architecture

POM vs Script decision guide, split locator/action pattern, ADR-style justification, and folder structure.

02

Fixtures

Fixture lifecycle, test vs worker scope, auth fixtures, and the official { scope: 'worker' } tuple syntax.

03

Locators

Priority order — getByRolegetByLabelgetByTestId → CSS → XPath. Filtering, chaining, and testIdAttribute.

04

Authentication

Three auth strategies with a decision tree, storageState TTL, setup projects, and multi-role testing.

05

Configuration

Full playwright.config.ts reference — CI-aware settings, retries, reporters, timeouts, and env variable layering.

06

Reporting

HTML reporter, Trace Viewer, Allure setup, and environment metadata for CI artifact uploads.

07

CI / CD

GitHub Actions matrix strategy, Azure Pipelines with JUnit reporter, sharding, secrets, and artifact upload.

08

Flaky Tests

Root cause taxonomy, expect.poll, waitForFunction, and a step-by-step trace debugging workflow.

09

Accessibility

axe-core integration, WCAG 2.1 tag filtering, keyboard navigation testing, and focus management.

10

Anti-Patterns

13 documented before/after examples — waitForTimeout, XPath abuse, shared state, over-abstraction, and more.

Three Runnable Example Frameworks

All three target SauceDemo and cover the same test scenarios — compare them to understand the full spectrum of Playwright architecture options.

simple-pom-framework

Single-class POM — locators and actions in one file

★ Start here
ComplexityMedium
Files per page1 class
ReportingHTML + JSON
Best forMost projects

pom-framework

Split locator/action pattern with Allure reporting

Advanced
ComplexityHigh
Files per page2 files
ReportingHTML + Allure
Best forLarge teams

script-framework

Plain helper functions — no page object classes

Minimal
ComplexityLow
Files per page0 classes
ReportingHTML + Allure
Best forPrototyping

Quick Start

Clone and run the recommended framework in under two minutes.

Terminal
# Clone and enter the recommended framework
git clone https://github.com/ZeeaanNawazHarall/\
  playwright-best-practices.git
cd playwright-best-practices/examples/simple-pom-framework

# Install dependencies and browser
npm install
npx playwright install chromium

# Copy public SauceDemo credentials and run
cp .env.example .env
npm test
playwright.config.ts — CI-aware defaults
export default defineConfig({
  // Fail build if test.only left in source
  forbidOnly: !!process.env.CI,

  // Retry twice on CI, never locally
  retries: process.env.CI ? 2 : 0,

  // Single worker on CI, auto locally
  workers: process.env.CI ? 1 : undefined,

  use: {
    trace:      'on-first-retry',
    screenshot: 'only-on-failure',
    video:      'retain-on-failure',
  },
});

Six Core Principles

These run through every section of this repo.

1

Never log in inside a test

Authentication belongs in fixtures. Tests should start already authenticated. → Authentication docs

2

Prefer role-based locators

getByRole()getByLabel()getByTestId() → CSS → XPath (last resort). → Locators docs

3

Never use waitForTimeout

Hard waits are flaky by definition. Use web-first assertions — they poll automatically until the condition is met. → Flaky tests docs

4

Isolate tests from each other

Tests sharing state fail randomly under parallelism. Each test should own its data and navigation. → Fixtures docs

5

Put every option in playwright.config.ts

Retries, timeouts, and reporter config scattered across test files become invisible and hard to change. → Configuration docs

6

Automated scans catch regressions, not everything

axe-core finds rule violations automatically. It cannot verify reading order, screen reader announcements, or real keyboard usability. → Accessibility docs