一键导入
playwright-e2e-patterns
Playwright E2E testing patterns. Use when playwright, E2E test, toBeVisible, route mock, modal, flaky test, or selector issues.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Playwright E2E testing patterns. Use when playwright, E2E test, toBeVisible, route mock, modal, flaky test, or selector issues.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Make Codex CLI behave more like Claude Code for Kookr by preserving the known fork, branch, build, deploy, daily upstream sync, and live-verification workflow for Claude-compatible skills, agents, settings, hooks, and related UX.
Kookr-internal extension to rfc-iterative-review that captures append-only critic traces for later meta-analysis of RFC reviewer subagents.
Analyze an open question by casting 3-5 deliberately conflicting expert roles, running them in parallel and blind to each other, sharpening them in a debate round, attacking their consensus with a devil's advocate, then synthesizing a verdict that preserves disagreement instead of averaging it. Use for decisions, strategy, idea generation, hypothesis triage, experiment post-mortems, or any question where a single lens would return "it depends".
Iterative RFC drafting workflow — draft in worktree, run parallel critic subagents, incorporate feedback over N rounds, present to user before any action
How to create, structure, and launch Kookr playbook tasks — reusable agent task templates with dynamic sources and project identity
Build a Ralph-like sequential Kookr task chain where each task completes one independent unit, records durable state, and spawns the next task with the same continuation contract. Use for issue batches, queue drains, staged migrations, or other long runs that should proceed one task at a time without relying on conversation memory.
| name | playwright-e2e-patterns |
| description | Playwright E2E testing patterns. Use when playwright, E2E test, toBeVisible, route mock, modal, flaky test, or selector issues. |
| keywords | playwright, e2e, toBeVisible, route-mock, modal, flaky-test, firefox, selector, data-testid, storageState, serial |
| related | testing-patterns |
E2E testing patterns for the Kookr dashboard.
npx playwright test # All tests (config at repo root, testDir ./e2e)
npx playwright test e2e/canary.spec.ts # Specific file
npx playwright test --headed # See browser
npx playwright test --debug # Inspector
| Problem | Cause | Fix |
|---|---|---|
| Clicks wrong modal | Generic .modal selector | Use [data-modal="name"] or data-testid |
| Mock doesn't work | Set up after navigation | Mock BEFORE page.goto() |
| Broad mock catches specific routes | Pattern too wide | Register specific routes first |
| Assertion fails on async content | Content loads after render | Use toBeVisible({ timeout }) or waitForResponse() |
| Welcome modal blocks clicks | First-visit modal | Set localStorage via addInitScript() |
| Firefox-only failures | Timing differences | Use specific selectors + explicit waits |
| Serial tests conflict | Browser projects run parallel | Use workers: 1 |
| Count is 0 but elements exist | Feature changed DOM structure | Inspect actual DOM with innerHTML() |
| WS message silently dropped | WS not connected when sent | Wait for connection indicator before sending |
| State leaks between tests | Reset endpoint incomplete | Clear ALL stateful subsystems in reset |
Prefer data-testid, role-based (getByRole('button', { name: 'Submit' })). Avoid CSS classes (.modal, .button). Be specific: [data-modal="delete-confirmation"] not .modal.
Mock BEFORE navigation:
await page.route('**/api/v1/tasks', route => route.fulfill({ json: mockTasks }));
await page.goto('http://localhost:30080');
Specific routes first:
await page.route('**/api/v1/tasks/123', route => route.fulfill({ json: specificTask }));
await page.route('**/api/v1/tasks', route => route.fulfill({ json: taskList }));
Fallthrough pattern:
await page.route('**/api/v1/**', route => {
const url = route.request().url();
if (url.includes('/tasks')) route.fulfill({ json: mockTasks });
else if (url.includes('/workflows')) route.fulfill({ json: mockWorkflows });
else route.continue();
});
// Set localStorage before navigation
await page.addInitScript(() => localStorage.setItem('aegis_welcome_dismissed', 'true'));
await page.goto('/');
// Or use storageState
test.use({
storageState: { cookies: [], origins: [{ origin: 'http://localhost:30080', localStorage: [{ name: 'aegis_welcome_dismissed', value: 'true' }] }] }
});
// Or dismiss if present
const modal = page.locator('[data-modal="welcome"]');
if (await modal.isVisible({ timeout: 1000 })) await modal.getByRole('button', { name: 'Close' }).click();
await page.goto('http://localhost:30080');
await page.waitForResponse('**/api/v1/tasks');
await expect(page.locator('.task-item')).toHaveCount(5);
await expect(page.locator('.task-item').first()).toBeVisible({ timeout: 10000 });
When a DOM assertion (toHaveCount, toBeVisible) fails, don't increase the timeout first. Follow this sequence:
await page.locator('.parent').innerHTML() or page.evaluate(() => document.body.innerHTML). A count of 0 could mean "not arrived yet" OR "rendered as a different element."await request.get('/api/state') to confirm the data exists server-side. If the server has the data but the DOM doesn't, it's a client delivery or rendering issue.When tests trigger server actions via REST and then assert on DOM that updates via WebSocket:
.health-dot-connected)page.goto('/')), the WS reconnects asynchronously — wait for the connection indicator, not just the page contentinjectEvent returning { ok: true } means the server processed it and called ws.send(), but the browser may not have received/rendered it yetReset endpoints must clear ALL stateful subsystems, not just the obvious ones:
Missing any subsystem causes state leakage between tests — symptoms appear as unexpected counts, stale data, or "impossible" states.
workers: 1 if tests modify shared statepage.on('console', msg => console.log(msg.text()))testInfo.status !== 'passed' && page.screenshot()await page.pause()vitest-bun-mocking, e2e-test-troubleshooting, api-route-patterns