{"id":"playwright-expert","name":"playwright-expert","summary":"PlaywrightでE2Eテストを書いたり、テストインフラを構築したり、不安定なブラウザテストのデバッグをする際に使えます。","body":"# Playwright Expert\n\nE2E testing specialist with deep expertise in Playwright for robust, maintainable browser automation.\n\n## Core Workflow\n\n1. **Analyze requirements** - Identify user flows to test\n2. **Setup** - Configure Playwright with proper settings\n3. **Write tests** - Use POM pattern, proper selectors, auto-waiting\n4. **Debug** - Run test → check trace → identify issue → fix → verify fix\n5. **Integrate** - Add to CI/CD pipeline\n\n## Reference Guide\n\nLoad detailed guidance based on context:\n\n| Topic | Reference | Load When |\n|-------|-----------|-----------|\n| Selectors | `references/selectors-locators.md` | Writing selectors, locator priority |\n| Page Objects | `references/page-object-model.md` | POM patterns, fixtures |\n| API Mocking | `references/api-mocking.md` | Route interception, mocking |\n| Configuration | `references/configuration.md` | playwright.config.ts setup |\n| Debugging | `references/debugging-flaky.md` | Flaky tests, trace viewer |\n\n## Constraints\n\n### MUST DO\n- Use role-based selectors when possible\n- Leverage auto-waiting (don't add arbitrary timeouts)\n- Keep tests independent (no shared state)\n- Use Page Object Model for maintainability\n- Enable traces/screenshots for debugging\n- Run tests in parallel\n\n### MUST NOT DO\n- Use `waitForTimeout()` (use proper waits)\n- Rely on CSS class selectors (brittle)\n- Share state between tests\n- Ignore flaky tests\n- Use `first()`, `nth()` without good reason\n\n## Code Examples\n\n### Selector: Role-based (correct) vs CSS class (brittle)\n\n```typescript\n// ✅ Role-based selector — resilient to styling changes\nawait page.getByRole('button', { name: 'Submit' }).click();\nawait page.getByLabel('Email address').fill('user@example.com');\n\n// ❌ CSS class selector — breaks on refactor\nawait page.locator('.btn-primary.submit-btn').click();\nawait page.locator('.email-input').fill('user@example.com');\n```\n\n### Page Object Model + Test File\n\n```typescript\n// pages/LoginPage.ts\nimport { type Page, type Locator } from '@playwright/test';\n\nexport class LoginPage {\n  readonly page: Page;\n  readonly emailInput: Locator;\n  readonly passwordInput: Locator;\n  readonly submitButton: Locator;\n  readonly errorMessage: Locator;\n\n  constructor(page: Page) {\n    this.page = page;\n    this.emailInput = page.getByLabel('Email address');\n    this.passwordInput = page.getByLabel('Password');\n    this.submitButton = page.getByRole('button', { name: 'Sign in' });\n    this.errorMessage = page.getByRole('alert');\n  }\n\n  async goto() {\n    await this.page.goto('/login');\n  }\n\n  async login(email: string, password: string) {\n    await this.emailInput.fill(email);\n    await this.passwordInput.fill(password);\n    await this.submitButton.click();\n  }\n}\n```\n\n```typescript\n// tests/login.spec.ts\nimport { test, expect } from '@playwright/test';\nimport { LoginPage } from '../pages/LoginPage';\n\ntest.describe('Login', () => {\n  let loginPage: LoginPage;\n\n  test.beforeEach(async ({ page }) => {\n    loginPage = new LoginPage(page);\n    await loginPage.goto();\n  });\n\n  test('successful login redirects to dashboard', async ({ page }) => {\n    await loginPage.login('user@example.com', 'correct-password');\n    await expect(page).toHaveURL('/dashboard');\n  });\n\n  test('invalid credentials shows error', async () => {\n    await loginPage.login('user@example.com', 'wrong-password');\n    await expect(loginPage.errorMessage).toBeVisible();\n    await expect(loginPage.errorMessage).toContainText('Invalid credentials');\n  });\n});\n```\n\n### Debugging Workflow for Flaky Tests\n\n```typescript\n// 1. Run failing test with trace enabled\n// playwright.config.ts\nuse: {\n  trace: 'on-first-retry',\n  screenshot: 'only-on-failure',\n}\n\n// 2. Re-run with retries to capture trace\n// npx playwright test --retries=2\n\n// 3. Open trace viewer to inspect timeline\n// npx playwright show-trace test-results/.../trace.zip\n\n// 4. Common fix — replace arbitrary timeout with proper wait\n// ❌ Flaky\nawait page.waitForTimeout(2000);\nawait page.getByRole('button', { name: 'Save' }).click();\n\n// ✅ Reliable — waits for element state\nawait page.getByRole('button', { name: 'Save' }).waitFor({ state: 'visible' });\nawait page.getByRole('button', { name: 'Save' }).click();\n\n// 5. Verify fix — run test 10x to confirm stability\n// npx playwright test --repeat-each=10\n```\n\n## Output Templates\n\nWhen implementing Playwright tests, provide:\n1. Page Object classes\n2. Test files with proper assertions\n3. Fixture setup if needed\n4. Configuration recommendations\n\n## Knowledge Reference\n\nPlaywright, Page Object Model, auto-waiting, locators, fixtures, API mocking, trace viewer, visual comparisons, parallel execution, CI/CD integration\n\n[Documentation](https://jeffallan.github.io/claude-skills/skills/quality/playwright-expert/)","author":"@Jeffallan","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/Jeffallan/claude-skills/tree/main/skills/playwright-expert","license":"MIT","category":"writing","lang":"en","tokens":1140,"stars":0,"calls30d":1,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"references/api-mocking.md","size":3145,"sha256":"e4f788c6355a79c9baa21b232f55788cc80620d735d29d43dea62667120fde45"},{"path":"references/configuration.md","size":3286,"sha256":"f65f5eb5a91d3a13dafb845026ee07f41353e3b82bbb6def4fc7054e55b6f2aa"},{"path":"references/debugging-flaky.md","size":3207,"sha256":"e559423dad74e5c384ba3de0a1c0db8d7f7723bd1a19cdc46f25b0f7622d5627"},{"path":"references/page-object-model.md","size":3684,"sha256":"6df65f98c1ea3b954fee2ef68d2697e2ad3fe280809cd75c8f89873d38200be2"},{"path":"references/selectors-locators.md","size":2798,"sha256":"659941eebd0f53ecde7dba938ec035d76673b6b0bb7cba06441a06e46922e134"}],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":["jeffallan.github.io","staging.example.com"]}}