with one click
e2e
// End-to-end testing workflow for web applications using Playwright or Cypress. Covers user flow discovery, test design, implementation, execution, and flaky test management.
// End-to-end testing workflow for web applications using Playwright or Cypress. Covers user flow discovery, test design, implementation, execution, and flaky test management.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | e2e |
| description | End-to-end testing workflow for web applications using Playwright or Cypress. Covers user flow discovery, test design, implementation, execution, and flaky test management. |
| category | process |
| triggers | ["end to end test","browser test","user flow test","playwright test","cypress test"] |
Purpose: End-to-end testing for web applications Phases: Setup → Discover → Design → Implement → Run → Report Usage:
/e2e [scope flags] <description of what to test>
/test-coverage or /tdd/api-test/reviewdata-testid or role-based selectors. CSS classes change with styling; test anchors must be stable.waitForSelector, waitForNavigation, Cypress auto-retry). setTimeout in tests is a flakiness factory.See ai-assistant-protocol for valid approval terms and invalid responses.
| Flag | Description |
|---|---|
--framework=<name> | Testing framework: playwright or cypress |
--files=<paths> | Limit scope to specific test files or app files |
--flow=<name> | Target a specific user flow (e.g., login, checkout) |
Examples:
/e2e --framework=playwright login and signup flows
/e2e --flow=checkout verify the full purchase flow
/e2e --files=e2e/auth/ fix flaky authentication tests
Mode: Read-only investigation — verify testing infrastructure.
Detect the package manager from the project's lockfile. Check in this order:
| Lockfile | Package Manager | Run command |
|---|---|---|
pnpm-lock.yaml | pnpm | pnpm exec |
yarn.lock | yarn | yarn |
bun.lockb | bun | bun / bunx |
package-lock.json | npm | npx |
Use the detected package manager for all commands throughout this workflow (installs, running tests, starting dev server). Do not mix package managers.
cat package.json | grep -E "playwright|cypress"
ls playwright.config.* cypress.config.* 2>/dev/null
package.json for @playwright/test or cypressplaywright.config.ts, cypress.config.ts)Verify browser binaries are installed for the testing framework:
npx playwright install --dry-run or checking the Playwright cache. If missing, install the project's configured browsers (or chromium as a default):
# Using detected package manager (example: pnpm)
pnpm exec playwright install chromium
# Or install all configured browsers:
pnpm exec playwright install
npx cypress verify. If not verified, run npx cypress install.Do not skip this step. Browser binaries are often missing in fresh clones, CI environments, and containers.
Check if the dev server is needed and running:
webServer in playwright.config.tsbaseUrl in cypress.config.ts and any start scriptswebServer is configured in Playwright config — the framework handles starting/stopping the server automatically. Note this and proceed.webServer is NOT configured:
curl -s http://localhost:3000 > /dev/null or similar)webServer block to the Playwright/Cypress config so the framework manages it, or (b) start the server and document how to stop itbaseUrl: set baseUrl in the config to avoid hardcoded URLs in tests.Tests must not fail due to ECONNREFUSED because no server is listening.
## E2E Setup
| Check | Status |
|-------|--------|
| Package manager | [pnpm/yarn/bun/npm] |
| Framework | [Playwright/Cypress/None] |
| Config file | [Found/Missing] |
| Base URL | [configured/missing] |
| Test directory | [path or missing] |
| Browsers installed | [yes/no → installed] |
| Dev server | [webServer configured / running on port X / needs setup] |
If setup is incomplete, offer to scaffold before proceeding.
git branch --show-current
git status --porcelain
Identify target scope from flags and description.
Mode: Read-only — identify what needs testing.
Examine the application to map critical user flows:
# Find route definitions
grep -rn "path=" src/ --include="*.tsx" --include="*.ts"
grep -rn "Route" src/ --include="*.tsx" --include="*.ts"
# Find page components
find src -name "page.*" -o -name "Page.*" | head -20
# Check what is already covered
find e2e tests/e2e cypress/e2e -name "*.spec.*" -o -name "*.test.*" 2>/dev/null
## Flow Inventory
| Flow | Pages | Existing Tests | Priority |
|------|-------|----------------|----------|
| Login | /login → /dashboard | 0 | High |
| Signup | /signup → /verify → /dashboard | 0 | High |
| Checkout | /cart → /shipping → /payment → /confirm | 0 | Critical |
Confirm these flows? (yes / modify)
GATE: Wait for confirmation before designing tests.
Mode: Read-only — plan test scenarios for each flow.
For each approved flow, design scenarios covering:
For flows spanning multiple pages, outline Page Object Model structure:
## Page Objects
- `LoginPage` — email input, password input, submit button, error message
- `DashboardPage` — user greeting, navigation menu, logout button
## Test Design: [Flow Name]
### Happy Path
1. Navigate to /login
2. Fill email and password
3. Click Sign in
4. Verify redirect to /dashboard
5. Verify user greeting visible
### Error: Invalid Credentials
1. Navigate to /login
2. Fill invalid credentials
3. Click Sign in
4. Verify error message displayed
5. Verify still on /login
### Edge: Empty Form Submission
1. Navigate to /login
2. Click Sign in without filling fields
3. Verify validation messages
---
**Approve test design?** (yes / no / modify)
GATE: User must approve test design before implementing.
Mode: Full access — create test files.
Reference: See
references/e2e-patterns.mdfor page object patterns, selector strategies, and common flow templates. Seereferences/e2e-flaky-tests.mdfor flaky test prevention and mitigation.
Follow project conventions for file naming and directory structure. Use the approved test design as the blueprint.
Selector strategy (in priority order):
getByRole('button', { name: 'Sign in' })getByLabel('Email')getByTestId('submit-btn')getByText('Welcome')Use framework-native waiting, never setTimeout:
test.describe('User Authentication', () => {
test('should allow 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.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('wrongpassword');
await page.getByRole('button', { name: 'Sign in' }).click();
await expect(page.getByText('Invalid email or password')).toBeVisible();
});
});
// e2e/pages/login.page.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();
}
async expectError(message: string) {
await expect(this.page.getByRole('alert')).toContainText(message);
}
}
Ensure each test:
If the flow involves third-party iframes (OAuth providers like Google/GitHub, payment widgets like Stripe, CAPTCHAs):
/api/auth/callback) and return a valid session/token.// Example: mock OAuth callback for login flow
test('OAuth login redirects to dashboard', async ({ page }) => {
// Mock the OAuth callback to return a valid session
await page.route('**/api/auth/callback**', (route) => {
route.fulfill({
status: 302,
headers: { Location: '/dashboard' },
});
});
// Note: We cannot test the third-party OAuth provider's login page.
// This test verifies the app handles the callback correctly.
await page.goto('/api/auth/callback?code=mock-auth-code');
await expect(page).toHaveURL('/dashboard');
});
Mode: Execution — run tests and collect results.
# Playwright
npx playwright test [file]
# Cypress
npx cypress run --spec [file]
If tests fail:
# Playwright — headed with trace
npx playwright test [file] --headed --trace on
# Cypress — interactive
npx cypress open
| Attempt | Action |
|---|---|
| 1st failure | Review error, fix obvious issues (selectors, timing) |
| 2nd failure | Enable tracing/screenshots, inspect step-by-step |
| 3rd failure | STOP. Likely a flaky test or app bug, not a test bug. Present findings to user. |
Mode: Summary — present results and recommendations.
## E2E Test Results
| Flow | Tests | Passed | Failed | Skipped |
|------|-------|--------|--------|---------|
| Login | 4 | 4 | 0 | 0 |
| Signup | 3 | 2 | 1 | 0 |
| Checkout | 5 | 5 | 0 | 0 |
**Total:** 12 tests, 11 passed, 1 failed
For each failure, include:
## Coverage by Flow
| Flow | Happy Path | Errors | Edge Cases |
|------|------------|--------|------------|
| Login | Covered | Covered | Partial |
| Signup | Covered | Missing | Missing |
## Recommendations
- [ ] Add signup error handling tests
- [ ] Add edge case tests for login (special characters in email)
- [ ] Consider adding visual regression tests for critical pages
## Ready to Commit
**Files created/changed:**
- `e2e/auth/login.spec.ts` — Login flow tests
- `e2e/pages/login.page.ts` — Login page object
**Message:**
test(e2e): add login flow end-to-end tests
Covers happy path, invalid credentials, and empty form submission. Uses Page Object Model for maintainability.
**Commit?** (yes / no / edit)
GATE: User must approve before committing.
See references/e2e-flaky-tests.md for a deep guide on diagnosis, prevention patterns, and the flaky test decision tree.
A test is flaky if:
| Cause | Symptom | Fix |
|---|---|---|
| Timing issues | Element not found, timeout | Add proper waits (waitForSelector, expect().toBeVisible()) |
| Animation interference | Click on wrong element, element moving | Disable animations in test mode |
| Network dependency | Intermittent timeout, connection refused | Mock all external API calls |
| Test ordering | Passes alone, fails in suite | Isolate state, reset between tests |
| Shared state | Random data appearing in assertions | Each test creates its own data |
| Race condition | Inconsistent assertion failures | Wait for specific conditions, not time |
Fix or delete. Never ignore.
| ID | Type | Prompt / Condition | Expected |
|---|---|---|---|
| E2E-T1 | Positive | "Write end-to-end tests for the login flow" | Skill triggers |
| E2E-T2 | Positive | "Add Playwright tests for checkout" | Skill triggers |
| E2E-T3 | Positive | "Browser test the signup flow" | Skill triggers |
| E2E-T4 | Negative | "Write unit tests for this function" | Does NOT trigger (-> /test-coverage or /tdd) |
| E2E-T5 | Negative | "Test the API endpoints" | Does NOT trigger (-> /api-test) |
| E2E-T6 | Negative | "Fix the flaky test" | Does NOT trigger (-> /debug) |
| E2E-T7 | Boundary | "Test the full user flow" | Triggers if referring to browser-based user flow |
| Phase | Mode | Gate |
|---|---|---|
| 1. Setup | Read-only | Framework detected and configured |
| 2. Discover | Read-only | User confirms flow inventory |
| 3. Design | Read-only | User approves test design |
| 4. Implement | Full access | Tests written per approved design |
| 5. Run | Execution | All tests pass (or failures triaged) |
| 6. Report | Summary | User approves before commit |