playwright-best-practices
A guide for writing robust Playwright E2E tests by using semantic selectors and auto-waiting while avoiding flaky patterns like hardcoded delays.
Install
mkdir -p .claude/skills/playwright-best-practices && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/19057" && unzip -o skill.zip -d .claude/skills/playwright-best-practices && rm skill.zipInstalls to .claude/skills/playwright-best-practices
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Playwright best practices including selectors, wait strategies, accessibility testing, responsive design, and flaky-test prevention. Use when writing or improving Playwright E2E tests.Key capabilities
- →Use semantic selectors like `getByRole` and `getByTestId`.
- →Employ auto-waiting and explicit assertions instead of hardcoded delays.
- →Test accessibility using `getByRole` and keyboard navigation.
- →Isolate tests to ensure independence and clean up test data.
- →Test responsive designs across multiple viewports.
- →Prevent flaky tests by using proper waits and stable selectors.
How it works
The skill provides best practices for Playwright tests, focusing on semantic selectors, auto-waiting strategies, accessibility testing, responsive design, and test isolation to prevent flakiness.
Inputs & outputs
When to use playwright-best-practices
- →Improving test stability
- →Refactoring flaky E2E tests
- →Implementing accessibility checks
- →Testing responsive designs
About this skill
Playwright Best Practices
Expert guidance for writing reliable, maintainable Playwright tests.
Quick Reference
| Concern | Best Practice | Avoid |
|---|---|---|
| Selectors | getByRole, getByTestId, getByLabel | CSS classes, DOM structure |
| Waits | Auto-waiting, explicit assertions | waitForTimeout, hardcoded delays |
| Accessibility | getByRole, a11y checks | Visual-only testing |
| Flaky tests | Proper waits, stable selectors | Timing-dependent assertions |
| Isolation | Cleanup after each test | Tests depending on each other |
| Parallel | Independent tests | Shared state |
Essential Principles
Use semantic selectors: getByRole, getByLabel, getByTestId are stable. CSS classes and DOM structure change frequently.
Never waitForTimeout: Hardcoded delays make tests slow and flaky. Use auto-waiting and explicit assertions.
Test accessibility: getByRole ensures accessible markup. Keyboard tests verify a11y.
Isolate tests: Each test should work independently. Clean up test data after each test.
Responsive testing: Test mobile, tablet, desktop viewports.
Selector Best Practices
// ❌ Bad: Fragile selectors
page.click('div > div > button')
page.click('.btn-primary')
page.click('#submit-btn-123')
// ✅ Good: Stable, semantic selectors
page.getByRole('button', { name: 'Submit' })
page.getByTestId('submit-button')
page.getByLabel('Email address')
Wait Strategies
// ❌ Bad: Hardcoded waits
page.waitForTimeout(5000) // Flaky, slow
// ✅ Good: Explicit waits
await page.waitForURL('/dashboard')
await page.waitForSelector('[data-testid="success-message"]')
await expect(page.getByTestId('loading')).toBeHidden()
await page.waitForResponse(resp => resp.url().includes('/api/users') && resp.status() === 200)
Accessibility Testing
// Good: Semantic selectors enforce a11y
await page.getByRole('button', { name: 'Submit' }).click()
// Good: Keyboard navigation test
test('is keyboard navigable', async ({ page }) => {
await page.goto('/form')
await page.keyboard.press('Tab')
await expect(page.getByTestId('name-input')).toBeFocused()
})
// Good: A11y assertions (with axe-core)
await expect(page).toHaveAccessibleTree()
Responsive Testing
test.describe('Mobile', () => {
test.use({ viewport: { width: 375, height: 667 } })
test('shows mobile menu', async ({ page }) => {
await page.goto('/')
await expect(page.getByTestId('hamburger-menu')).toBeVisible()
})
})
Common Anti-Patterns
| Anti-Pattern | Severity | Fix |
|---|---|---|
| waitForTimeout | Critical | Use explicit waits/assertions |
| CSS class selectors | High | Use getByRole/getByTestId |
| Tests depending on each other | High | Make tests independent |
| No cleanup | Medium | Use fixtures with proper cleanup |
| Only desktop testing | Low | Test multiple viewports |
| Hardcoded test data | Medium | Use data factories |
Success Criteria
Tests are reliable when:
- No waitForTimeout in tests
- Selectors are semantic (getByRole, getByTestId)
- Tests run in isolation (independent)
- Test data cleaned up after each test
- Multiple viewports tested
- Accessibility assertions present
- Tests are deterministic (no randomness)
When not to use it
- →When using CSS classes or DOM structure for selectors.
- →When using `waitForTimeout` or hardcoded delays.
- →When tests depend on each other or lack cleanup.
Limitations
- →Avoids `waitForTimeout` due to flakiness and slowness.
- →Discourages CSS class selectors due to fragility.
- →Requires tests to be independent and clean up after each run.
How it compares
This skill guides the user to write stable and maintainable Playwright tests by enforcing semantic selectors and proper wait strategies, unlike writing tests that rely on fragile DOM structures or hardcoded delays.
Compared to similar skills
playwright-best-practices side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| playwright-best-practices (this skill) | 0 | 20d | No flags | Intermediate |
| dependency-upgrade | 26 | 4mo | Review | Intermediate |
| vitest | 41 | 6mo | No flags | Intermediate |
| browser-tools | 6 | 8mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
dependency-upgrade
wshobson
Manage major dependency version upgrades with compatibility analysis, staged rollout, and comprehensive testing. Use when upgrading framework versions, updating major dependencies, or managing breaking changes in libraries.
vitest
antfu
Vitest fast unit testing framework powered by Vite with Jest-compatible API. Use when writing tests, mocking, configuring coverage, or working with test filtering and fixtures.
browser-tools
Whamp
Lightweight Chrome automation toolkit with shared configuration, JSON-first output, and six focused scripts for starting, navigating, inspecting, capturing, evaluating, and cleaning up browser sessions.
validate-typescript
BerryKuipers
Run TypeScript compiler type-checking (tsc --noEmit) to validate type safety and catch type errors. Works with any TypeScript project. Returns structured output with error counts, categories (type/syntax/import errors), and affected files. Used for quality gates and pre-commit validation.
ts-testing
johnlindquist
Design, implement, and maintain high‑value TypeScript test suites using popular JS/TS testing libraries. Use this skill whenever the user is adding tests, debugging failing tests, or refactoring code that should be covered by tests.
react-best-practices
redpanda-data
Client-side React performance optimization patterns.