playwright-expert — Claude Code skill: what it does, how to install
Sets up Playwright E2E testing infrastructure, writes Page Object Model classes, and troubleshoots flaky tests using trace inspection.
npx skills add Jeffallan/claude-skills --skill playwright-expert -a claude-codeWhat playwright-expert does
This skill guides coding agents through writing end-to-end browser tests in Playwright. It enforces the Page Object Model pattern, keeps test cases completely isolated without shared state, and insists on built-in auto-waiting.
The instructions strictly ban waitForTimeout() and fragile CSS class selectors. Instead, the agent selects elements via getByRole or getByLabel, intercepts routes for API mocking, and configures parallel test runs.
When debugging flaky tests, it enables trace: 'on-first-retry' inside playwright.config.ts. It replaces arbitrary delays with element state waits, then verifies fixes with npx playwright test --repeat-each=10.
What it helps with
- generate Playwright test suites using the Page Object Model
- replace brittle CSS selectors with accessible role-based locators
- debug and eliminate flaky tests using Playwright Trace Viewer
- set up API route mocking and CI test execution
Example prompts for the agent
- Write a Page Object and test specs for our login flow using Playwright
- Debug this flaky test on the save button without using waitForTimeout
- Configure playwright.config.ts for parallel test execution in CI
How to install playwright-expert
1Skills CLI (Vercel)
npx skills add Jeffallan/claude-skills --skill playwright-expert -a claude-code2Manually: put the files in place
~/.claude/skills/playwright-expert/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/playwright-expert/
1Skills CLI (Vercel)
npx skills add Jeffallan/claude-skills --skill playwright-expert -a codex2Manually: put the files in place
.agents/skills/playwright-expert/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add Jeffallan/claude-skills --skill playwright-expert -a cursor2Manually: put the files in place
.cursor/skills/playwright-expert/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install Jeffallan/claude-skills playwright-expert2Manually: put the files in place
.github/skills/playwright-expert/SKILL.md1Skills CLI (Vercel)
npx skills add Jeffallan/claude-skills --skill playwright-expert -a gemini-cli2Platform CLI
gemini skills install https://github.com/Jeffallan/claude-skills --path skills/playwright-expertManually: put the files in place
.devin/skills/playwright-expert/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add Jeffallan/claude-skills --skill playwright-expert -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set61
The whole set →Similar
Questions about playwright-expert
How to install playwright-expert in Claude Code?
Run npx skills add Jeffallan/claude-skills --skill playwright-expert -a claude-code in your terminal. This writes the skill to ~/.claude/skills/playwright-expert/SKILL.md.
What does playwright-expert do?
It instructs the agent to write reliable Playwright tests using role-based selectors, Page Object classes, and auto-waiting while banning arbitrary sleep timeouts.
How does the skill handle flaky tests?
It turns on trace capture on retries, replaces fixed delays with element state waits like waitFor({ state: 'visible' }), and validates stability across repeated runs.
Source text
SKILL.md · MIT
---
name: playwright-expert
description: "Use when writing E2E tests with Playwright, setting up test infrastructure, or debugging flaky browser tests. Invoke to write test scripts, create page objects, configure test fixtures, set up reporters, add CI integration, implement API mocking, or perform visual regression testing. Trigger terms: Playwright, E2E test, end-to-end, browser testing, automation, UI testing, visual testing, Page Object Model, test flakiness."
license: MIT
metadata:
author: https://github.com/Jeffallan
company: https://synergetic.solutions
version: "1.1.0"
domain: quality
triggers: Playwright, E2E test, end-to-end, browser testing, automation, UI testing, visual testing
role: specialist
scope: testing
output-format: code
related-skills: test-master, react-expert, devops-engineer
---
# Playwright Expert
E2E testing specialist with deep expertise in Playwright for robust, maintainable browser automation.
## Core Workflow
1. **Analyze requirements** - Identify user flows to test
2. **Setup** - Configure Playwright with proper settings
3. **Write tests** - Use POM pattern, proper selectors, auto-waiting
4. **Debug** - Run test → check trace → identify issue → fix → verify fix
5. **Integrate** - Add to CI/CD pipeline
## Reference Guide
Load detailed guidance based on context:
| Topic | Reference | Load When |
|-------|-----------|-----------|
| Selectors | `references/selectors-locators.md` | Writing selectors, locator priority |
| Page Objects | `references/page-object-model.md` | POM patterns, fixtures |
| API Mocking | `references/api-mocking.md` | Route interception, mocking |
| Configuration | `references/configuration.md` | playwright.config.ts setup |
| Debugging | `references/debugging-flaky.md` | Flaky tests, trace viewer |
## Constraints
### MUST DO
- Use role-based selectors when possible
- Leverage auto-waiting (don't add arbitrary timeouts)
- Keep tests independent (no shared state)
- Use Page Object Model for maintainability
- Enable traces/screenshots for debugging
- Run tests in parallel
### MUST NOT DO
- Use `waitForTimeout()` (use proper waits)
- Rely on CSS class selectors (brittle)
- Share state between tests
- Ignore flaky tests
- Use `first()`, `nth()` without good reason
## Code Examples
### Selector: Role-based (correct) vs CSS class (brittle)
```typescript
// ✅ Role-based selector — resilient to styling changes
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByLabel('Email address').fill('[email protected]');
// ❌ CSS class selector — breaks on refactor
await page.locator('.btn-primary.submit-btn').click();
await page.locator('.email-input').fill('[email protected]');
```
### Page Object Model + Test File
```typescript
// pages/LoginPage.ts
import { type Page, type Locator } from '@playwright/test';
export class LoginPage {
readonly page: Page;
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
readonly errorMessage: Locator;
constructor(page: Page) {
this.page = page;
this.emailInput = page.getByLabel('Email address');
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();
}
}
```
```typescript
// tests/login.spec.ts
import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';
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('[email protected]', '<test-password>');
await expect(page).toHaveURL('/dashboard');
});
test('invalid credentials shows error', async () => {
await loginPage.login('[email protected]', '<wrong-password>');
await expect(loginPage.errorMessage).toBeVisible();
await expect(loginPage.errorMessage).toContainText('Invalid credentials');
});
});
```
### Debugging Workflow for Flaky Tests
```typescript
// 1. Run failing test with trace enabled
// playwright.config.ts
use: {
trace: 'on-first-retry',
screenshot: 'only-on-failure',
}
// 2. Re-run with retries to capture trace
// npx playwright test --retries=2
// 3. Open trace viewer to inspect timeline
// npx playwright show-trace test-results/.../trace.zip
// 4. Common fix — replace arbitrary timeout with proper wait
// ❌ Flaky
await page.waitForTimeout(2000);
await page.getByRole('button', { name: 'Save' }).click();
// ✅ Reliable — waits for element state
await page.getByRole('button', { name: 'Save' }).waitFor({ state: 'visible' });
await page.getByRole('button', { name: 'Save' }).click();
// 5. Verify fix — run test 10x to confirm stability
// npx playwright test --repeat-each=10
```
## Output Templates
When implementing Playwright tests, provide:
1. Page Object classes
2. Test files with proper assertions
3. Fixture setup if needed
4. Configuration recommendations
## Knowledge Reference
Playwright, Page Object Model, auto-waiting, locators, fixtures, API mocking, trace viewer, visual comparisons, parallel execution, CI/CD integration
Maintained by [@jeffallan](https://github.com/jeffallan), Principal Consultant at [Synergetic Solutions](https://synergetic.solutions)
[Documentation](https://jeffallan.github.io/claude-skills/skills/quality/playwright-expert/)
© https://github.com/Jeffallan · MIT · Jeffallan/claude-skills