playwright-testing
Write and maintain end-to-end tests with Playwright. Use when someone asks to "add e2e tests", "test my web app", "set up Playwright", "write browser tests", "test login flow", "visual regression testing", "test across browsers", or "automate UI testing". Covers test setup, page objects, authentication, API mocking, visual comparisons, and CI integration.
Best use case
playwright-testing is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Write and maintain end-to-end tests with Playwright. Use when someone asks to "add e2e tests", "test my web app", "set up Playwright", "write browser tests", "test login flow", "visual regression testing", "test across browsers", or "automate UI testing". Covers test setup, page objects, authentication, API mocking, visual comparisons, and CI integration.
Teams using playwright-testing should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/playwright-testing/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How playwright-testing Compares
| Feature / Agent | playwright-testing | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Write and maintain end-to-end tests with Playwright. Use when someone asks to "add e2e tests", "test my web app", "set up Playwright", "write browser tests", "test login flow", "visual regression testing", "test across browsers", or "automate UI testing". Covers test setup, page objects, authentication, API mocking, visual comparisons, and CI integration.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Playwright Testing
## Overview
This skill helps AI agents write reliable end-to-end tests using Playwright. It covers project setup, writing tests with auto-waiting locators, page object patterns, authentication handling, API mocking, visual regression, accessibility testing, and CI/CD integration.
## Instructions
### Step 1: Project Setup
```bash
npm init playwright@latest
# Or add to existing project:
npm install -D @playwright/test && npx playwright install
```
```typescript
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: [['html', { open: 'never' }], ['junit', { outputFile: 'test-results/junit.xml' }]],
use: {
baseURL: process.env.BASE_URL || 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
{ name: 'mobile-chrome', use: { ...devices['Pixel 5'] } },
],
webServer: {
command: 'npm run dev',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
},
});
```
### Step 2: Write Tests
```typescript
import { test, expect } from '@playwright/test';
test.describe('Homepage', () => {
test('displays hero and navigates to features', async ({ page }) => {
await page.goto('/');
await expect(page.getByRole('heading', { name: /welcome/i })).toBeVisible();
await page.getByRole('link', { name: 'View Features' }).click();
await expect(page).toHaveURL(/.*features/);
});
test('shows search results', async ({ page }) => {
await page.goto('/');
await page.getByPlaceholder('Search...').fill('playwright');
await page.getByPlaceholder('Search...').press('Enter');
await expect(page.getByTestId('search-results')).toBeVisible();
await expect(page.getByTestId('search-result-item')).toHaveCount(10);
});
});
```
### Step 3: Authentication Pattern
```typescript
// tests/auth.setup.ts — authenticate once, reuse across tests
import { test as setup } from '@playwright/test';
import path from 'path';
const authFile = path.join(__dirname, '.auth/user.json');
setup('authenticate', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill('test@example.com');
await page.getByLabel('Password').fill('password123');
await page.getByRole('button', { name: 'Sign in' }).click();
await expect(page).toHaveURL('/dashboard');
await page.context().storageState({ path: authFile });
});
// In config: add setup dependency
// projects: [
// { name: 'setup', testMatch: /.*\.setup\.ts/ },
// { name: 'chromium', use: { ...devices['Desktop Chrome'], storageState: 'tests/.auth/user.json' }, dependencies: ['setup'] },
// ]
```
### Step 4: Page Object Pattern
```typescript
// tests/pages/login.page.ts
import { Page, Locator, expect } from '@playwright/test';
export class LoginPage {
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
readonly errorMessage: Locator;
constructor(private page: Page) {
this.emailInput = page.getByLabel('Email');
this.passwordInput = page.getByLabel('Password');
this.submitButton = page.getByRole('button', { name: 'Sign in' });
this.errorMessage = page.getByRole('alert');
}
async goto() { await this.page.goto('/login'); }
async login(email: string, password: string) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
async expectError(msg: string) { await expect(this.errorMessage).toContainText(msg); }
}
// tests/login.spec.ts
test.describe('Login', () => {
let loginPage: LoginPage;
test.beforeEach(async ({ page }) => { loginPage = new LoginPage(page); await loginPage.goto(); });
test('successful login redirects to dashboard', async ({ page }) => {
await loginPage.login('test@example.com', 'password123');
await expect(page).toHaveURL('/dashboard');
});
test('invalid credentials show error', async () => {
await loginPage.login('wrong@example.com', 'wrong');
await loginPage.expectError('Invalid email or password');
});
});
```
### Step 5: API Mocking
```typescript
test('shows error state when API fails', async ({ page }) => {
await page.route('**/api/projects', (route) => route.fulfill({
status: 500, contentType: 'application/json',
body: JSON.stringify({ error: 'Internal server error' }),
}));
await page.goto('/dashboard');
await expect(page.getByText('Failed to load projects')).toBeVisible();
});
test('modify API response for premium features', async ({ page }) => {
await page.route('**/api/user', async (route) => {
const response = await route.fetch();
const json = await response.json();
json.plan = 'enterprise';
await route.fulfill({ response, json });
});
await page.goto('/settings');
await expect(page.getByText('Enterprise Plan')).toBeVisible();
});
```
### Step 6: Visual & Accessibility Testing
```typescript
test('homepage visual regression', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot('homepage.png', { fullPage: true, maxDiffPixelRatio: 0.01 });
});
// Update snapshots: npx playwright test --update-snapshots
import AxeBuilder from '@axe-core/playwright';
test('no accessibility violations', async ({ page }) => {
await page.goto('/');
const results = await new AxeBuilder({ page }).withTags(['wcag2a', 'wcag2aa']).analyze();
expect(results.violations).toEqual([]);
});
```
### Step 7: CI Integration
```yaml
# .github/workflows/e2e.yml
name: E2E Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: npm }
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
- uses: actions/upload-artifact@v4
if: always()
with: { name: playwright-report, path: playwright-report/, retention-days: 30 }
```
### Useful Commands
```bash
npx playwright test # Run all tests
npx playwright test tests/login.spec.ts # Specific file
npx playwright test --headed # See browser
npx playwright test --project=chromium # Specific browser
npx playwright test --debug # Step-through debugger
npx playwright codegen http://localhost:3000 # Record actions
npx playwright show-report # View HTML report
```
## Examples
### Example 1: Add e2e tests for a login flow with page objects
**User prompt:** "Write Playwright tests for our login page that test successful login, invalid credentials, and form validation, using the page object pattern."
The agent will:
1. Create `tests/pages/login.page.ts` with locators for email, password, submit button, and error message using role-based selectors (`getByLabel`, `getByRole`)
2. Add `goto()`, `login()`, and `expectError()` methods to the page object
3. Write three tests: successful login verifying redirect to `/dashboard`, invalid credentials checking the error alert, and empty form submission checking validation messages
4. Set up `beforeEach` to instantiate the page object and navigate to `/login`
### Example 2: Mock API responses to test error and empty states
**User prompt:** "Add tests for our dashboard that verify it handles API errors gracefully and shows an empty state when there are no projects."
The agent will:
1. Use `page.route('**/api/projects', ...)` to intercept the API call
2. For the error test: fulfill with status 500 and verify the "Failed to load projects" message and Retry button appear
3. For the empty test: fulfill with status 200 and an empty projects array, then verify the "No projects yet" empty state is shown
4. Both tests run in isolation without needing a real backend, making them fast and reliable in CI
## Guidelines
- Use role-based locators (`getByRole`, `getByLabel`, `getByText`) over CSS selectors — more resilient to DOM changes
- Add `data-testid` attributes only when no semantic locator works
- Never use `page.waitForTimeout()` — use auto-waiting locators or `expect` with timeout
- Run auth setup once and share state across tests via `storageState`
- Use page objects for complex pages to keep tests readable
- Mock external APIs in tests — test UI behavior, not third-party services
- Run tests in parallel (`fullyParallel: true`) for speed
- Capture traces on first retry — invaluable for debugging flaky tests in CI
- Use `webServer` config to auto-start your dev server during tests
- Keep visual snapshots in version control and review changes in PRsRelated Skills
testing-library
Test UI components the way users interact with them using Testing Library — query by role, text, and label instead of implementation details. Use when someone asks to "test React components", "Testing Library", "user-centric testing", "test accessibility", "test without implementation details", or "render and query components in tests". Covers React Testing Library, queries, user events, async testing, and accessibility assertions.
stripe-testing
Test and debug Stripe payment integrations. Use when someone needs to verify webhook handling, simulate payment flows, debug failed charges, validate subscription lifecycle, or troubleshoot Stripe API errors. Trigger words: stripe, payment testing, webhook debugging, charge failed, subscription error, payment intent, checkout session.
ai-pentesting
Run autonomous AI-driven penetration tests on web applications using tools like Shannon, PentAGI, and similar frameworks. Use when tasks involve setting up automated penetration testing pipelines, combining AI agents with security tools (nmap, subfinder, nuclei, sqlmap), building autonomous exploit chains, generating pentest reports with proof-of-concept exploits, or integrating AI pentesting into CI/CD pipelines. Covers the full pentest lifecycle from reconnaissance to reporting using AI orchestration.
zustand
You are an expert in Zustand, the small, fast, and scalable state management library for React. You help developers manage global state without boilerplate using Zustand's hook-based stores, selectors for performance, middleware (persist, devtools, immer), computed values, and async actions — replacing Redux complexity with a simple, un-opinionated API in under 1KB.
zoho
Integrate and automate Zoho products. Use when a user asks to work with Zoho CRM, Zoho Books, Zoho Desk, Zoho Projects, Zoho Mail, or Zoho Creator, build custom integrations via Zoho APIs, automate workflows with Deluge scripting, sync data between Zoho apps and external systems, manage leads and deals, automate invoicing, build custom Zoho Creator apps, set up webhooks, or manage Zoho organization settings. Covers Zoho CRM, Books, Desk, Projects, Creator, and cross-product integrations.
zod
You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.
zipkin
Deploy and configure Zipkin for distributed tracing and request flow visualization. Use when a user needs to set up trace collection, instrument Java/Spring or other services with Zipkin, analyze service dependencies, or configure storage backends for trace data.
zig
Expert guidance for Zig, the systems programming language focused on performance, safety, and readability. Helps developers write high-performance code with compile-time evaluation, seamless C interop, no hidden control flow, and no garbage collector. Zig is used for game engines, operating systems, networking, and as a C/C++ replacement.
zed
Expert guidance for Zed, the high-performance code editor built in Rust with native collaboration, AI integration, and GPU-accelerated rendering. Helps developers configure Zed, create custom extensions, set up collaborative editing sessions, and integrate AI assistants for productive coding.
zeabur
Expert guidance for Zeabur, the cloud deployment platform that auto-detects frameworks, builds and deploys applications with zero configuration, and provides managed services like databases and message queues. Helps developers deploy full-stack applications with automatic scaling and one-click marketplace services.
zapier
Automate workflows between apps with Zapier. Use when a user asks to connect apps without code, automate repetitive tasks, sync data between services, or build no-code integrations between SaaS tools.
zabbix
Configure Zabbix for enterprise infrastructure monitoring with templates, triggers, discovery rules, and dashboards. Use when a user needs to set up Zabbix server, configure host monitoring, create custom templates, define trigger expressions, or automate host discovery and registration.