Best for
- Writing end-to-end tests with Playwright
- Automating browser interactions for testing
- Setting up visual regression testing
event4u-app/agent-config/src/skills/playwright-testing/SKILL.md
Use when writing Playwright E2E tests — browser automation, visual regression testing, Page Objects, fixtures, and reliable test patterns.
Decision brief
Use when writing Playwright E2E tests — browser automation, visual regression testing, Page Objects, fixtures, and reliable test patterns.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/event4u-app/agent-config --skill "src/skills/playwright-testing"Inspect the Agent Skill "playwright-testing" from https://github.com/event4u-app/agent-config/blob/0adf49a8ae84b0ff6e2de8759eea43257e020eff/src/skills/playwright-testing/SKILL.md at commit 0adf49a8ae84b0ff6e2de8759eea43257e020eff. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
1. Read the guideline — ../../../docs/guidelines/e2e/playwright.md for detailed conventions. 2. Check Playwright config — playwright.config.ts for browsers, base URL, timeouts. 3. Check existing tests — match patterns in tests/e2e/ or e2e/. 4. Check test utilities — look for pag…
Review the “Run with Playwright Inspector (step through)” section in the pinned source before continuing.
Design verification. When exercising a UI artifact, run the design-artifact verification checklist (open → console/load → viewport → text-fit → assets → interaction) and capture evidence; a design task with browser capability present is not "done" without it.
Review the “Test structure” section in the pinned source before continuing.
Prefer semantic locators (getByRole, getByLabel) over CSS selectors.
Permission review
The documentation asks the agent to run terminal commands or scripts.
npx playwright test --headedThe documentation asks the agent to run terminal commands or scripts.
npx playwright test --debugEvidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 95/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 7 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Design verification. When exercising a UI artifact, run the design-artifact verification checklist (open → console/load → viewport → text-fit → assets → interaction) and capture evidence; a design task with browser capability present is not "done" without it.
Use this skill when:
Guideline: ../../../docs/guidelines/e2e/playwright.md — full conventions, config templates, CI setup.
Mobile: for native iOS/Android or React Native E2E, do NOT reuse Playwright — see the mobile-e2e-strategy skill for framework selection.
../../../docs/guidelines/e2e/playwright.md for detailed conventions.playwright.config.ts for browsers, base URL, timeouts.tests/e2e/ or e2e/.test-case-discovery funnel per user flow before writing specs; cover the happy flow AND at least one boundary (empty state, max input) and one error path (failed request, validation rejection) per flow — never the happy flow alone.import { test, expect } from '@playwright/test'
test.describe('User Authentication', () => {
test('should login with valid credentials', async ({ page }) => {
await page.goto('/login')
await page.getByLabel('Email').fill('user@example.com')
await page.getByLabel('Password').fill('password123')
await page.getByRole('button', { name: 'Sign in' }).click()
await expect(page).toHaveURL('/dashboard')
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible()
})
test('should show error for invalid credentials', async ({ page }) => {
await page.goto('/login')
await page.getByLabel('Email').fill('wrong@example.com')
await page.getByLabel('Password').fill('wrong')
await page.getByRole('button', { name: 'Sign in' }).click()
await expect(page.getByText('Invalid credentials')).toBeVisible()
})
})
| Strategy | Example | When to use |
|---|---|---|
| Role | getByRole('button', { name: 'Submit' }) | Default — most accessible |
| Label | getByLabel('Email') | Form inputs |
| Text | getByText('Welcome') | Visible text content |
| Placeholder | getByPlaceholder('Search...') | Input placeholders |
| Test ID | getByTestId('submit-btn') | Last resort — when no semantic locator works |
| CSS | page.locator('.my-class') | Avoid — brittle |
Prefer semantic locators (getByRole, getByLabel) over CSS selectors.
// Wait for page to fully load
await page.goto('/dashboard', { waitUntil: 'networkidle' })
// Wait for specific API response
await page.waitForResponse(resp =>
resp.url().includes('/api/users') && resp.status() === 200
)
// ✅ Auto-retrying assertions (Playwright retries until timeout)
await expect(page.getByText('Success')).toBeVisible()
await expect(page.getByRole('list')).toHaveCount(5)
// ❌ Non-retrying — can be flaky
const text = await page.textContent('.message')
expect(text).toBe('Success')
// pages/LoginPage.ts
export class LoginPage {
constructor(private page: Page) {}
async goto() {
await this.page.goto('/login')
}
async login(email: string, password: string) {
await this.page.getByLabel('Email').fill(email)
await this.page.getByLabel('Password').fill(password)
await this.page.getByRole('button', { name: 'Sign in' }).click()
}
}
test('homepage visual regression', async ({ page }) => {
await page.goto('/')
await expect(page).toHaveScreenshot('homepage.png', {
maxDiffPixelRatio: 0.01,
})
})
tests/*.png (or configured path).npx playwright test --update-snapshots.test.describe('Responsive design', () => {
for (const viewport of [
{ width: 1440, height: 900, name: 'desktop' },
{ width: 768, height: 1024, name: 'tablet' },
{ width: 375, height: 812, name: 'mobile' },
]) {
test(`renders correctly on ${viewport.name}`, async ({ page }) => {
await page.setViewportSize(viewport)
await page.goto('/')
await expect(page).toHaveScreenshot(`home-${viewport.name}.png`)
})
}
})
# Run with headed browser (see what's happening)
npx playwright test --headed
# Run with Playwright Inspector (step through)
npx playwright test --debug
# View test report
npx playwright show-report
# Run specific test
npx playwright test -g "should login"
Use --grep, --reporter=json, plus jq/rg to keep diagnosis scoped:
# Targeted run — only matching specs
npx playwright test --grep '@smoke'
# JSON report, narrowed to failures via jq
npx playwright test --reporter=json > pw.json
jq '.suites[].specs[] | select(.tests[].results[].status=="failed")' pw.json
# Scan trace logs for one selector
rg --color=never 'getByRole.*Submit' test-results/
Run verification. The test run's exit code is the pass/fail signal — 0
means every spec passed, non-zero means at least one failed. Read the command
output (or the --reporter=json above) to diagnose the failing spec's
root cause; do not blindly re-run hoping it turns green — a retry-until-pass
is not a fix, and a flaky green hides the real defect.
| Problem | Solution |
|---|---|
| Element not ready | Use auto-retrying assertions (toBeVisible, toHaveText) |
| Animation interference | Use page.evaluate(() => document.body.style.setProperty('--transition-duration', '0s')) |
| Network timing | Wait for specific responses, not arbitrary timeouts |
| Test isolation | Use fresh browser context per test (Playwright default) |
| Shared state | Reset database/state before each test |
// Use storageState to avoid logging in via UI in every test
// auth.setup.ts
import { test as setup } from '@playwright/test'
setup('authenticate', async ({ page }) => {
await page.goto('/login')
await page.getByLabel('Email').fill(process.env.TEST_USER_EMAIL!)
await page.getByLabel('Password').fill(process.env.TEST_USER_PASSWORD!)
await page.getByRole('button', { name: 'Sign in' }).click()
await page.waitForURL('/dashboard')
await page.context().storageState({ path: '.auth/user.json' })
})
// playwright.config.ts — use storage state in projects
projects: [
{ name: 'setup', testMatch: /.*\.setup\.ts/ },
{
name: 'chromium',
use: { ...devices['Desktop Chrome'], storageState: '.auth/user.json' },
dependencies: ['setup'],
},
]
// Mock API responses for isolated testing
await page.route('**/api/users', route =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([{ id: 1, name: 'Test User' }]),
})
)
page.waitForTimeout() as a fix — it masks the real problem and makes tests flaky.getByRole, getByLabel.test.fixme() is for app bugs, test.skip() is for environment constraints — don't confuse them.test.fixme() and move on.baseURL from config..only — enforce via forbidOnly: !!process.env.CI.When a spec fails, do not retry blindly by re-running, swapping locators at random, or bumping timeouts until green. Diagnose the root cause first: open the trace viewer, inspect the failing locator's aria tree, identify the real reason (timing, locator, app state), then apply a targeted fix. Trial-and-error locator swaps mask flaky test design.
Alternatives
event4u-app/agent-config
Use when the user says "review the design", "check the UI", or wants a comprehensive UI/UX review. Uses a 7-phase methodology covering interaction, responsiveness, accessibility, and more.
JasonColapietro/suede-creator-skills
Design AI evals that catch regressions before users do: rubrics, test cases, failure modes, acceptance gates, and AI-SPEC artifacts.
github/awesome-copilot
This skill enables visual inspection of websites running locally or remotely to identify and fix design issues. Triggers on requests like "review website design", "check the UI", "fix the layout", "find design problems". Detects issues with responsive design, accessibility, visual consistency, and layout breakage, then performs fixes at the source code level.
affaan-m/ECC
Use this skill to automate visual testing and UI interaction verification using browser automation after deploying features.