On this page14 sections

Playwright + TypeScript E2E Automation

A complete end-to-end automation project using Playwright and TypeScript, covering Page Object Model, API setup, fixture factories, and GitHub Actions CI.

IntermediateE2EUI automationAPI testingVisual regressionui automation
Setup: ~20 minLanguage: TypeScriptFramework: PlaywrightPackage manager: npmBest for: Automation QA engineers

Overview

This project demonstrates a production-style Playwright + TypeScript test suite against a demo e-commerce application (Sauce Demo — saucedemo.com). It covers the full automation lifecycle: environment setup, Page Object Model design, fixture-based test isolation, API-assisted state setup (bypassing the UI for preconditions), parallel execution, and a GitHub Actions pipeline with HTML report upload. The goal is to show the patterns that interviewers actually look for — not just working tests, but a maintainable framework you could hand to a colleague.

Project goals

  • Implement a Page Object Model that separates locator management from test logic
  • Use Playwright fixtures to share authenticated page state across tests without repeating login steps
  • Set up test data via the API rather than the UI wherever possible to keep tests fast and stable
  • Achieve parallel execution across browsers (Chromium, Firefox, WebKit) with zero test interference
  • Generate an HTML report and publish it as a GitHub Actions artifact
  • Keep TypeScript strict-mode enabled with no type errors

Architecture

Page Object Model with Fixture Layer

Tests are isolated from UI implementation details by a POM layer. A custom fixture file extends the base Playwright test to provide pre-authenticated pages and shared helper instances. Data factories create test objects without coupling tests to specific UI flows.

tests/Test files (.spec.ts); contain only assertions and user-journey steps
pages/Page Object classes; own locators and page-level actions
fixtures/Custom Playwright fixtures; extend base test with shared context
utils/API helpers, data factories, environment config
playwright.config.tsBrowser projects, base URL, parallelism, reporter config

Prerequisites

  • Node.js 18 or later
  • npm 9 or later
  • Git
  • A GitHub account (for CI pipeline)
  • Familiarity with TypeScript basics (interfaces, async/await)

Folder structure

Project structure
Bash
playwright.config.ts                      # Browser projects, base URL, retry, reporter, and timeout config
.env.example                              # Template for environment variables — copy to .env
tests/                                    # All .spec.ts test files — one file per user journey
tests/auth/login.spec.ts                  # Login flow: happy path, wrong credentials, lockout
tests/shop/checkout.spec.ts               # Add-to-cart and checkout flow with payment details
tests/shop/product-filters.spec.ts        # Sort and filter behaviour on the product listing page
pages/                                    # Page Object Model classes
pages/LoginPage.ts                        # Locators and actions for the login page
pages/ProductPage.ts                      # Product listing interactions: sort, filter, add to cart
pages/CheckoutPage.ts                     # Multi-step checkout: cart → address → payment → confirmation
fixtures/                                 # Custom Playwright test fixtures
fixtures/auth.fixture.ts                  # Provides an authenticated storageState; avoids repeated login
fixtures/index.ts                         # Merges all custom fixtures into a single extended test export
utils/                                    # Shared helpers not tied to any page
utils/apiClient.ts                        # Thin Playwright APIRequestContext wrapper for pre-test data setup
utils/dataFactory.ts                      # Generates valid order and user objects for test data
utils/env.ts                              # Typed access to process.env with validation on startup

Setup & run

Installation

  1. 1.Clone the repository: git clone <repo-url> && cd playwright-typescript
  2. 2.Install dependencies: npm install
  3. 3.Install Playwright browsers: npx playwright install --with-deps
  4. 4.Copy environment config: cp .env.example .env
  5. 5.Set BASE_URL in .env (defaults to https://www.saucedemo.com)
  6. 6.Verify setup: npx playwright test --list

Commands

Run all tests (headless, all browsers)

npx playwright test

Runs the full suite across Chromium, Firefox, and WebKit in parallel

Run tests in a single browser

npx playwright test --project=chromium

Useful during development to get faster feedback

Run a specific test file

npx playwright test tests/checkout.spec.ts

Run tests in headed mode (watch the browser)

npx playwright test --headed

Run tests in UI mode (interactive trace viewer)

npx playwright test --ui

Opens Playwright's built-in visual test runner — great for debugging

Open last HTML report

npx playwright show-report

Debug a failing test

npx playwright test tests/login.spec.ts --debug

Opens the Playwright Inspector for step-by-step debugging

Environment

VariableDescriptionExampleRequired
BASE_URLRoot URL of the application under testhttps://www.saucedemo.comYes
TEST_USER_USERNAMEUsername for the standard test accountstandard_userYes
TEST_USER_PASSWORDPassword for the standard test accountsecret_sauceYes
HEADLESSSet to 'false' to run browsers in headed mode locallytrueNo

Test data strategy

  • Login state is captured once via the auth fixture and reused across tests using Playwright's storageState — no repeated UI logins
  • Cart and order data is seeded via API calls in beforeAll hooks so tests start from a known state without relying on the UI
  • The dataFactory utility generates unique email addresses using a timestamp suffix to prevent conflicts in parallel runs
  • Sensitive credentials live in .env (gitignored); CI injects them as GitHub Actions secrets
  • No test mutates shared data; each test either creates its own data or reads from a pre-seeded fixture

Reporting

  • Playwright HTML Report is generated on every run; open with `npx playwright show-report`
  • Failed tests attach a screenshot, a video, and a trace file automatically — viewable in the HTML report
  • GitHub Actions uploads the report as a downloadable artifact on every CI run, including failures
  • A JSON reporter is also configured to allow downstream processing (e.g. custom dashboards or Slack notifications)

CI/CD

  • A .github/workflows/playwright.yml workflow triggers on push and pull_request events
  • The workflow uses actions/setup-node@v4 pinned to Node 20 and caches npm dependencies
  • Browsers are installed with `npx playwright install --with-deps chromium` (Chromium only in CI for speed)
  • Tests run with `npx playwright test --project=chromium` to reduce CI minutes
  • The report directory is uploaded with actions/upload-artifact@v4 so failures are debuggable without a local environment
  • BASE_URL, TEST_USER_USERNAME, and TEST_USER_PASSWORD are passed as repository secrets

Common issues

Tests fail with 'Target closed' or 'Timeout' in parallel mode

Cause: Tests are sharing mutable state (e.g. a shared page object instance) across workers

Fix: Ensure each test creates its own page via the fixture; never share a Page object between tests

Auth fixture re-runs login on every test instead of reusing state

Cause: storageState file is not written to disk or its path is not referenced in the project config

Fix: Check that auth.fixture.ts writes storageState to a temp file and playwright.config.ts references it via `storageState` in the project options

Locators break after a page re-render (SPA navigation)

Cause: Using CSS selectors or XPath that depend on element position rather than semantic attributes

Fix: Switch to role-based locators (getByRole, getByLabel, getByTestId) which are resilient to layout changes

`npx playwright install` hangs or times out in a corporate network

Cause: Browser downloads are blocked by a proxy

Fix: Set HTTPS_PROXY and PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1, then download browsers manually via the Playwright CDN mirror

TypeScript errors on Playwright imports after upgrading

Cause: Type definitions are out of sync between @playwright/test and the installed browser binaries

Fix: Run `npm install @playwright/test@latest` and `npx playwright install` together

Best practices

  • Use `getByRole`, `getByLabel`, and `getByTestId` locators over CSS selectors — they match user intent and survive UI refactors
  • Keep Page Object classes focused: own locators and single-action methods, never assertions
  • Use `expect.soft` for non-critical assertions so a single field failure doesn't abort the whole test
  • Avoid `page.waitForTimeout`; rely on Playwright's auto-wait and `waitFor` with explicit conditions instead
  • Run with `--retries 1` in CI to catch intermittent network flakiness without masking real failures
  • Tag slow tests with `@slow` and use `test.slow()` to triple the default timeout only where needed
  • Keep the `playwright.config.ts` as the single source of truth for timeouts, base URL, and browser projects

Next steps

  • Add an accessibility spec using axe-playwright to catch WCAG violations on each key page
  • Extend the API helper to cover the full cart and order management API so tests can set up and tear down data without any UI interaction
  • Add visual comparison tests using `expect(page).toHaveScreenshot()` for UI-critical pages like the product listing
  • Set up a test environment in Docker so the suite can run against a locally served version of the app
  • Wire Allure Reporter as an alternative to the built-in HTML report for richer history and trend dashboards