Playwright Testing
Playwright is a modern end-to-end testing framework for web applications. It provides reliable, fast, and cross-browser testing with excellent developer experience.
When to Use This Skill
| Use this skill when... |
Use another skill instead when... |
| Writing E2E browser tests |
Writing unit tests (use vitest-testing) |
| Testing across Chromium, Firefox, WebKit |
Testing Python code (use python-testing) |
| Setting up visual regression testing |
Analyzing test quality (use test-quality-analysis) |
| Mocking network requests in E2E tests |
Generating property-based tests (use property-based-testing) |
| Testing mobile viewports |
Testing API contracts only (use api-testing) |
Core Expertise
- Cross-browser: Test on Chromium, Firefox, WebKit (Safari)
- Reliable: Auto-wait, auto-retry, no flaky tests
- Fast: Parallel execution, browser context isolation
- Modern: TypeScript-first, async/await, auto-complete
- Multi-platform: Windows, macOS, Linux
Installation
bun create playwright # Initialize (recommended)
bun add --dev @playwright/test # Or install manually
bunx playwright install # Install browsers
bunx playwright install --with-deps # With system deps (Linux)
bunx playwright --version # Verify
Configuration (playwright.config.ts)
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
timeout: 30000,
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
});
Essential Commands
bunx playwright test # Run all tests
bunx playwright test tests/login.spec.ts # Specific file
bunx playwright test --headed # See browser
bunx playwright test --debug # Debug mode
bunx playwright test --project=chromium # Specific browser
bunx playwright test --ui # UI mode
bunx playwright codegen http://localhost:3000 # Record tests
bunx playwright show-report # Last report
bunx playwright show-trace trace.zip # Trace viewer
bunx playwright test --update-snapshots # Update snapshots
Writing Tests
Basic Test Structure
import { test, expect } from '@playwright/test';
test('basic test', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveTitle(/Example/);
});
test.describe('login flow', () => {
test('should login successfully', async ({ page }) => {
await page.goto('/login');
await page.fill('input[name="email"]', 'user@example.com');
await page.fill('input[name="password"]', 'password123');
await page.click('button[type="submit"]');
await expect(page).toHaveURL('/dashboard');
});
});
Selectors and Locators
// Text/Role selectors (recommended)
await page.getByText('Sign in').click();
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByLabel('Email').fill('user@example.com');
await page.getByPlaceholder('Enter your name').fill('John');
await page.getByTestId('login-button').click();
// CSS/XPath selectors
await page.locator('.button-primary').click();
await page.locator('xpath=//button[text()="Submit"]').click();
// Chaining
await page.locator('.card').filter({ hasText: 'Product' }).getByRole('button').click();
Key Assertions
| Assertion |
Description |
toHaveTitle(title) |
Page title |
toHaveURL(url) |
Page URL |
toBeVisible() |
Element visible |
toBeEnabled() |
Element enabled |
toHaveText(text) |
Element text |
toContainText(text) |
Partial text |
toHaveAttribute(name, value) |
Attribute value |
toHaveClass(class) |
CSS class |
toHaveValue(value) |
Input value |
toBeEmpty() |
Empty input |
toHaveCount(n) |
Element count |
not.toBeDisabled() |
Negation |
Agentic Optimizations
| Context |
Command |
| Quick test |
bunx playwright test --reporter=line --bail |
| CI test |
bunx playwright test --reporter=github |
| Single browser |
bunx playwright test --project=chromium --reporter=line |
| Debug failing |
bunx playwright test --trace on --reporter=line |
| Headed debug |
bunx playwright test --headed --debug |
For detailed examples, advanced patterns, and best practices, see REFERENCE.md.
References
1---
2created: 2025-12-16
3modified: 2026-05-09
4reviewed: 2025-12-16
5name: playwright-testing
6description: "Playwright E2E testing — cross-browser, visual regression, API testing, mobile emulation. Use when writing E2E tests or setting up automated UI testing for web apps."
7user-invocable: false
8allowed-tools: Glob, Grep, Read, Bash, Edit, Write, TodoWrite, WebFetch, WebSearch
9---
10
11# Playwright Testing
12
13Playwright is a modern end-to-end testing framework for web applications. It provides reliable, fast, and cross-browser testing with excellent developer experience.
14
15## When to Use This Skill
16
17| Use this skill when... | Use another skill instead when... |
18|------------------------|----------------------------------|
19| Writing E2E browser tests | Writing unit tests (use vitest-testing) |
20| Testing across Chromium, Firefox, WebKit | Testing Python code (use python-testing) |
21| Setting up visual regression testing | Analyzing test quality (use test-quality-analysis) |
22| Mocking network requests in E2E tests | Generating property-based tests (use property-based-testing) |
23| Testing mobile viewports | Testing API contracts only (use api-testing) |
24
25## Core Expertise
26
27- **Cross-browser**: Test on Chromium, Firefox, WebKit (Safari)
28- **Reliable**: Auto-wait, auto-retry, no flaky tests
29- **Fast**: Parallel execution, browser context isolation
30- **Modern**: TypeScript-first, async/await, auto-complete
31- **Multi-platform**: Windows, macOS, Linux
32
33## Installation
34
35```bash
36bun create playwright # Initialize (recommended)
37bun add --dev @playwright/test # Or install manually
38bunx playwright install # Install browsers
39bunx playwright install --with-deps # With system deps (Linux)
40bunx playwright --version # Verify
41```
42
43## Configuration (playwright.config.ts)
44
45```typescript
46import { defineConfig, devices } from '@playwright/test';
47
48export default defineConfig({
49 testDir: './tests',
50 timeout: 30000,
51 use: {
52 baseURL: 'http://localhost:3000',
53 trace: 'on-first-retry',
54 },
55 projects: [
56 {
57 name: 'chromium',
58 use: { ...devices['Desktop Chrome'] },
59 },
60 ],
61});
62```
63
64## Essential Commands
65
66```bash
67bunx playwright test # Run all tests
68bunx playwright test tests/login.spec.ts # Specific file
69bunx playwright test --headed # See browser
70bunx playwright test --debug # Debug mode
71bunx playwright test --project=chromium # Specific browser
72bunx playwright test --ui # UI mode
73bunx playwright codegen http://localhost:3000 # Record tests
74bunx playwright show-report # Last report
75bunx playwright show-trace trace.zip # Trace viewer
76bunx playwright test --update-snapshots # Update snapshots
77```
78
79## Writing Tests
80
81### Basic Test Structure
82
83```typescript
84import { test, expect } from '@playwright/test';
85
86test('basic test', async ({ page }) => {
87 await page.goto('https://example.com');
88 await expect(page).toHaveTitle(/Example/);
89});
90
91test.describe('login flow', () => {
92 test('should login successfully', async ({ page }) => {
93 await page.goto('/login');
94 await page.fill('input[name="email"]', 'user@example.com');
95 await page.fill('input[name="password"]', 'password123');
96 await page.click('button[type="submit"]');
97 await expect(page).toHaveURL('/dashboard');
98 });
99});
100```
101
102### Selectors and Locators
103
104```typescript
105// Text/Role selectors (recommended)
106await page.getByText('Sign in').click();
107await page.getByRole('button', { name: 'Submit' }).click();
108await page.getByLabel('Email').fill('user@example.com');
109await page.getByPlaceholder('Enter your name').fill('John');
110await page.getByTestId('login-button').click();
111
112// CSS/XPath selectors
113await page.locator('.button-primary').click();
114await page.locator('xpath=//button[text()="Submit"]').click();
115
116// Chaining
117await page.locator('.card').filter({ hasText: 'Product' }).getByRole('button').click();
118```
119
120### Key Assertions
121
122| Assertion | Description |
123|-----------|-------------|
124| `toHaveTitle(title)` | Page title |
125| `toHaveURL(url)` | Page URL |
126| `toBeVisible()` | Element visible |
127| `toBeEnabled()` | Element enabled |
128| `toHaveText(text)` | Element text |
129| `toContainText(text)` | Partial text |
130| `toHaveAttribute(name, value)` | Attribute value |
131| `toHaveClass(class)` | CSS class |
132| `toHaveValue(value)` | Input value |
133| `toBeEmpty()` | Empty input |
134| `toHaveCount(n)` | Element count |
135| `not.toBeDisabled()` | Negation |
136
137## Agentic Optimizations
138
139| Context | Command |
140|---------|---------|
141| Quick test | `bunx playwright test --reporter=line --bail` |
142| CI test | `bunx playwright test --reporter=github` |
143| Single browser | `bunx playwright test --project=chromium --reporter=line` |
144| Debug failing | `bunx playwright test --trace on --reporter=line` |
145| Headed debug | `bunx playwright test --headed --debug` |
146
147For detailed examples, advanced patterns, and best practices, see [REFERENCE.md](REFERENCE.md).
148
149## References
150
151- Official docs: https://playwright.dev
152- Configuration: https://playwright.dev/docs/test-configuration
153- API reference: https://playwright.dev/docs/api/class-test
154- Best practices: https://playwright.dev/docs/best-practices
155- CI/CD: https://playwright.dev/docs/ci
156- Trace viewer: https://playwright.dev/docs/trace-viewer