Source profileQuality 95/100Review permissions

event4u-app/agent-config/src/skills/playwright-testing/SKILL.md

playwright-testing

Use when writing Playwright E2E tests — browser automation, visual regression testing, Page Objects, fixtures, and reliable test patterns.

Source repository stars
7
Declared platforms
0
Static risk flags
1
Last source update
2026-07-28
Source checked
2026-07-28

Decision brief

What it does—and where it fits

Use when writing Playwright E2E tests — browser automation, visual regression testing, Page Objects, fixtures, and reliable test patterns.

Best for

  • Writing end-to-end tests with Playwright
  • Automating browser interactions for testing
  • Setting up visual regression testing

Not for

  • Tasks that require unconfirmed production actions or broad system permissions.
  • Environments where the pinned source and install steps cannot be inspected.

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/event4u-app/agent-config --skill "src/skills/playwright-testing"
Safe inspection promptEditorial

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

What the source asks the agent to do

  1. 01

    Procedure: Write Playwright tests

    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…

    Read the guideline — ../../../docs/guidelines/e2e/playwright.md for detailed conventions.Check Playwright config — playwright.config.ts for browsers, base URL, timeouts.Check existing tests — match patterns in tests/e2e/ or e2e/.
  2. 02

    Run with Playwright Inspector (step through)

    Review the “Run with Playwright Inspector (step through)” section in the pinned source before continuing.

    Review and apply the “Run with Playwright Inspector (step through)” source section.
  3. 03

    When to use

    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.

    Writing end-to-end tests with PlaywrightAutomating browser interactions for testingSetting up visual regression testing
  4. 04

    Test structure

    Review the “Test structure” section in the pinned source before continuing.

    Review and apply the “Test structure” source section.
  5. 05

    Locator strategies (priority order)

    Prefer semantic locators (getByRole, getByLabel) over CSS selectors.

    Prefer semantic locators (getByRole, getByLabel) over CSS selectors.

Permission review

Static risk signals and limitations

Runs scripts

medium · line 153

The documentation asks the agent to run terminal commands or scripts.

npx playwright test --headed

Runs scripts

medium · line 156

The documentation asks the agent to run terminal commands or scripts.

npx playwright test --debug

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score95/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars7SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
event4u-app/agent-config
Skill path
src/skills/playwright-testing/SKILL.md
Commit
0adf49a8ae84b0ff6e2de8759eea43257e020eff
License
MIT
Collected
2026-07-28
Default branch
main
View the original SKILL.md

playwright-testing

When to use

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:

  • Writing end-to-end tests with Playwright
  • Automating browser interactions for testing
  • Setting up visual regression testing
  • Using Playwright MCP for design reviews
  • Debugging flaky E2E tests
  • Configuring Playwright for CI/CD

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.

Procedure: Write Playwright tests

  1. Read the guideline../../../docs/guidelines/e2e/playwright.md for detailed conventions.
  2. Check Playwright configplaywright.config.ts for browsers, base URL, timeouts.
  3. Check existing tests — match patterns in tests/e2e/ or e2e/.
  4. Check test utilities — look for page objects, fixtures, helpers.
  5. Check CI setup — how are E2E tests run in the pipeline?
  6. Enumerate the cases — run the 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.

Test structure

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()
  })
})

Locator strategies (priority order)

StrategyExampleWhen to use
RolegetByRole('button', { name: 'Submit' })Default — most accessible
LabelgetByLabel('Email')Form inputs
TextgetByText('Welcome')Visible text content
PlaceholdergetByPlaceholder('Search...')Input placeholders
Test IDgetByTestId('submit-btn')Last resort — when no semantic locator works
CSSpage.locator('.my-class')Avoid — brittle

Prefer semantic locators (getByRole, getByLabel) over CSS selectors.

Reliable test patterns

Wait for network idle

// 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
)

Assertions with auto-retry

// ✅ 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')

Page Object Model

// 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()
  }
}

Visual regression testing

test('homepage visual regression', async ({ page }) => {
  await page.goto('/')
  await expect(page).toHaveScreenshot('homepage.png', {
    maxDiffPixelRatio: 0.01,
  })
})
  • Screenshots are stored in tests/*.png (or configured path).
  • First run creates baseline screenshots.
  • Subsequent runs compare against baselines.
  • Update baselines: npx playwright test --update-snapshots.

Viewport testing

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`)
    })
  }
})

Debugging

# 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"

Filter noisy Playwright output

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.

Avoiding flaky tests

ProblemSolution
Element not readyUse auto-retrying assertions (toBeVisible, toHaveText)
Animation interferenceUse page.evaluate(() => document.body.style.setProperty('--transition-duration', '0s'))
Network timingWait for specific responses, not arbitrary timeouts
Test isolationUse fresh browser context per test (Playwright default)
Shared stateReset database/state before each test

Authentication pattern

// 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'],
  },
]

Network mocking

// 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' }]),
  })
)

Output format

  1. Playwright test file with Page Object pattern
  2. Reliable locators using role/label selectors over CSS

Auto-trigger keywords

  • Playwright
  • E2E test
  • browser automation
  • visual regression
  • end-to-end

Gotcha

  • Don't use page.waitForTimeout() as a fix — it masks the real problem and makes tests flaky.
  • The model tends to use CSS selectors instead of semantic locators — always prefer getByRole, getByLabel.
  • test.fixme() is for app bugs, test.skip() is for environment constraints — don't confuse them.
  • After 3 failed fix attempts on one test, mark it test.fixme() and move on.

Do NOT

  • Do NOT skip assertions — every test must verify something meaningful.
  • Do NOT share state between tests — each test should be independent.
  • Do NOT hardcode URLs — use baseURL from config.
  • Do NOT test implementation details — test user-visible behavior.
  • Do NOT put assertions in Page Objects — assertions belong in test files.
  • Do NOT commit .only — enforce via forbidOnly: !!process.env.CI.

Anti-bruteforce — diagnose before retry

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

Compare before choosing