with one click
generate-e2e-tests
// Use Playwright MCP to explore a feature, analyze existing tests, and generate/update E2E tests. Prioritizes user journey scenarios over individual element tests.
// Use Playwright MCP to explore a feature, analyze existing tests, and generate/update E2E tests. Prioritizes user journey scenarios over individual element tests.
| name | generate-e2e-tests |
| description | Use Playwright MCP to explore a feature, analyze existing tests, and generate/update E2E tests. Prioritizes user journey scenarios over individual element tests. |
| user-invocable | true |
| allowed-tools | ["Read","Write","Edit","Grep","Glob","Bash","mcp__playwright__browser_navigate","mcp__playwright__browser_snapshot","mcp__playwright__browser_click","mcp__playwright__browser_type","mcp__playwright__browser_select_option","mcp__playwright__browser_close"] |
Convert manual Playwright MCP verification into automated Playwright tests. This skill explores the UI, analyzes existing test coverage, and proposes scenario-based tests.
Prioritize scenarios over individual element tests:
Tests should represent user journeys - sequences of actions a user would take to accomplish a goal. Multiple assertions within a single test scenario are preferred over separate tests for each assertion.
Understand the feature from conversation context or ask the user:
Start mock server and dev server if not running:
docker compose -f e2e/docker-compose.yml up -d
# Dev server should be started with mock config:
# DOT_AI_MCP_URL=http://localhost:3001 DOT_AI_AUTH_TOKEN=mock-token ./scripts/dev-start.sh
Navigate to the feature using mcp__playwright__browser_navigate
Capture snapshots using mcp__playwright__browser_snapshot to understand:
Interact with the feature using:
mcp__playwright__browser_click for buttons/linksmcp__playwright__browser_type for inputsmcp__playwright__browser_select_option for dropdownsDocument the user journey as you explore:
Read existing test files in e2e/ directory:
e2e/*.spec.ts
Identify coverage gaps:
## E2E Test Plan for [Feature Name]
### Existing Coverage
- [List what's already tested that relates to this feature]
### Proposed Changes
#### Option A: Extend Existing Test (Preferred if applicable)
**File:** `e2e/[existing].spec.ts`
**Test:** `[existing test name]`
**Add assertions for:**
- [New assertion 1]
- [New assertion 2]
#### Option B: New Test Scenario
**File:** `e2e/[new-or-existing].spec.ts`
**Scenario:** `[descriptive scenario name]`
**User Journey:**
1. [Action 1] → [Expected outcome]
2. [Action 2] → [Expected outcome]
3. [Action 3] → [Expected outcome]
### Recommendation
[Which option and why]
// GOOD: Scenario-based test with multiple assertions
test('user can browse resources and view details', async ({ page }) => {
// Navigate to starting point
await page.goto('/dashboard')
// Action 1: Select a resource type
await page.getByRole('button', { name: 'Pod' }).click()
await expect(page).toHaveURL(/kind=Pod/)
// Action 2: Verify list loads with expected data
await expect(page.getByRole('table')).toBeVisible()
// Use exact count when mock data is deterministic, or verify non-empty
await expect(page.getByRole('row')).toHaveCount(5)
// Action 3: Click on a specific resource
await page.getByRole('link', { name: 'nginx-pod' }).click()
// Action 4: Verify details page
await expect(page.getByRole('heading', { name: 'nginx-pod' })).toBeVisible()
})
// BAD: Separate tests for each element
test('sidebar has Pod button', ...)
test('clicking Pod updates URL', ...)
test('table is visible', ...)
test('rows exist', ...)
Use beforeEach for common setup (login, navigation to starting point)
Prefer extending existing test.describe blocks when the feature fits
npx playwright test e2e/[file].spec.ts --reporter=line
getByRole() - Most reliable, semanticgetByLabel() - For form fieldsgetByText() - For static textgetByTestId() - Last resort, requires code changestoBeVisible() for elements that should be seentoBeAttached() for elements in DOM but possibly hiddentoHaveURL() for navigation verificationtoHaveCount() for lists/tablestoContainText() for partial text matchingawait expect(page.getByRole('table')).toBeVisible()
// Now table is definitely visible before next action
User: "I just finished implementing the resource detail page. Can you generate tests for it?"
Claude would then:
e2e/dashboard.spec.ts