Setup & Installation
Install Playwright, configure projects, and run your first test.
Playwright is our E2E testing framework. It runs tests in real browsers and supports Chromium, Firefox, and WebKit.
Prerequisites
- Node.js 20 LTS, pnpm
- Application running locally (
pnpm dev) or a deployed Alpha/Beta URL
Install
From the frontend project root:
pnpm add -D @playwright/test
pnpm exec playwright installThe playwright install command downloads browser binaries. Commit playwright.config.ts — do not commit browser binaries.
Project structure
e2e/
├── fixtures/
│ └── auth.fixture.ts # Shared login helper
├── pages/
│ ├── login.page.ts # Page object models
│ └── dashboard.page.ts
├── specs/
│ ├── auth.spec.ts
│ └── checkout.spec.ts
└── playwright.config.tsConfiguration
// playwright.config.ts
import { defineConfig, devices } from "@playwright/test";
export default defineConfig({
testDir: "./e2e/specs",
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: [["html", { open: "never" }], ["list"]],
use: {
baseURL: process.env.PLAYWRIGHT_BASE_URL ?? "http://localhost:3000",
trace: "on-first-retry",
screenshot: "only-on-failure",
video: "retain-on-failure",
},
projects: [
{ name: "chromium", use: { ...devices["Desktop Chrome"] } },
{ name: "firefox", use: { ...devices["Desktop Firefox"] } },
{ name: "webkit", use: { ...devices["Desktop Safari"] } },
],
webServer: process.env.CI
? undefined
: {
command: "pnpm dev",
url: "http://localhost:3000",
reuseExistingServer: !process.env.CI,
timeout: 120_000,
},
});Environment variables
# Local
PLAYWRIGHT_BASE_URL=http://localhost:3000
# Alpha preview (CI sets this from PR deploy URL)
PLAYWRIGHT_BASE_URL=https://alpha-142.preview.company.com
# Beta smoke tests
PLAYWRIGHT_BASE_URL=https://beta.company.com
# Test user credentials (vault — never commit)
E2E_TEST_EMAIL=test-user@company.com
E2E_TEST_PASSWORD=...First test
// e2e/specs/smoke.spec.ts
import { test, expect } from "@playwright/test";
test("homepage loads", async ({ page }) => {
await page.goto("/");
await expect(page).toHaveTitle(/UXDL Docs/);
});
test("health endpoint responds", async ({ request }) => {
const res = await request.get("/api/health");
expect(res.ok()).toBeTruthy();
const body = await res.json();
expect(body.status).toBe("ok");
});Run tests
# Run all E2E tests (starts dev server automatically)
pnpm exec playwright test
# Run with UI mode (interactive debugging)
pnpm exec playwright test --ui
# Run a single spec
pnpm exec playwright test e2e/specs/auth.spec.ts
# Run headed (see the browser)
pnpm exec playwright test --headed
# View last HTML report
pnpm exec playwright show-reportAdd scripts to package.json:
{
"scripts": {
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
"test:e2e:report": "playwright show-report"
}
}Verify setup
pnpm exec playwright installcompletes without errors.pnpm devis running (orwebServerstarts it automatically).pnpm test:e2epasses the smoke spec.- HTML report opens with
pnpm test:e2e:report.