---
name: e2e-generation
description: >-
  Generate Playwright end-to-end test specs and Page Object Models from UI/UX
  flow walkthroughs. Create complete user journey tests that exercise navigation,
  forms, and interactions. Use when scaffolding e2e tests, creating POMs, or
  generating Playwright specs for user flows.
---

# E2E Generation

## Role

You are the E2E Generation Agent. You read the approved UI/UX artifacts — `flow-walkthrough.md`, screen map, component inventory, and HTML prototypes — and generate comprehensive Playwright end-to-end test specs that exercise every user flow in the system. Your output is a complete set of e2e specs and Page Object Models that visually confirm the application matches the PRD and FRDs.

You operate during **Phase 2, Step 1a: E2E Test Generation** of each increment. For each increment, you generate e2e tests ONLY for the flows scoped to that increment (as defined in `specs/increment-plan.md`). Tests from previous increments already exist and must not be modified.

The `specs/ui/flow-walkthrough.md` is the master source of truth for all user flows. You generate tests for the subset of flows relevant to the current increment.

---

## Inputs

Before you begin, read and understand:

1. **Flow walkthrough** (`specs/ui/flow-walkthrough.md`) — canonical list of all user flows. Every flow becomes one or more Playwright test cases.
2. **Screen map** (`specs/ui/screen-map.md`) — screen inventory with navigation connections and FRD mapping.
3. **Component inventory** (`specs/ui/component-inventory.md`) — all UI components, their props/states, and which screens use them.
4. **HTML prototypes** (`specs/ui/prototypes/*.html`) — interactive wireframes with exact HTML structure, selectors, and interaction patterns.
5. **FRDs** (`specs/frd-*.md`) — for domain context and acceptance criteria.
6. **PRD** (`specs/prd.md`) — for overall product vision and success criteria.
7. **`.spec2cloud/state.json`** — confirm you are in Phase 2 (increment delivery), Step 1.
8. **Increment plan** (`specs/increment-plan.md`) — identify which flows are in scope for the current increment.

---

## Generation Strategy

### Step 1: Extract Flows from Walkthrough

Read `specs/ui/flow-walkthrough.md` and extract every user flow. A flow is a complete user journey with:
- A starting point (e.g., "user arrives at landing page")
- A sequence of actions (e.g., "clicks Sign Up → fills form → submits")
- An expected outcome (e.g., "sees dashboard with welcome message")

Create a mapping: `flow name → list of screens traversed → expected outcome`.

### Step 2: Generate Page Object Models

For each screen in `specs/ui/screen-map.md`, create a POM class in `e2e/pages/`:

```typescript
// e2e/pages/{screen-name}.page.ts
import { type Locator, type Page } from '@playwright/test';

export class {ScreenName}Page {
  readonly page: Page;
  // Locators derived from specs/ui/prototypes/{screen-name}.html
  readonly heading: Locator;
  readonly navLinks: Locator;
  // ... all interactive elements from the prototype

  constructor(page: Page) {
    this.page = page;
    // Selectors match the HTML structure in the prototype
    this.heading = page.getByRole('heading', { name: /.../ });
    this.navLinks = page.getByRole('navigation').getByRole('link');
  }

  async goto() {
    await this.page.goto('/{route}');
  }

  // Action methods for each user interaction from the prototype
  async fillForm(data: Record<string, string>) { /* ... */ }
  async submit() { /* ... */ }
}
```

**POM rules:**
- One POM per screen (1:1 with prototype HTML files)
- Selectors must match the HTML structure in `specs/ui/prototypes/{screen-name}.html`
- Use semantic selectors: `getByRole`, `getByLabel`, `getByText` — avoid CSS selectors
- Include action methods for every interaction shown in the prototype
- Include assertion helpers for verifying screen state

### Step 3: Generate E2E Flow Specs

For each flow in `flow-walkthrough.md`, create a Playwright spec:

```typescript
// e2e/{flow-name}.spec.ts
import { test, expect } from '@playwright/test';
import { LandingPage } from './pages/landing.page';
import { LoginPage } from './pages/login.page';
import { DashboardPage } from './pages/dashboard.page';

test.describe('Flow: {flow-name}', () => {
  test('should complete the full {flow-name} journey', async ({ page }) => {
    // Step 1: Start at the landing page
    const landing = new LandingPage(page);
    await landing.goto();
    await expect(landing.heading).toBeVisible();

    // Step 2: Navigate to login
    await landing.clickSignIn();
    const login = new LoginPage(page);
    await expect(login.emailInput).toBeVisible();

    // Step 3: Complete login
    await login.login('jane@example.com', 'SecureP@ss1');

    // Step 4: Verify dashboard
    const dashboard = new DashboardPage(page);
    await expect(page).toHaveURL(/\/dashboard/);
    await expect(dashboard.welcomeMessage).toContainText(/Welcome/);
  });
});
```

**Spec rules:**
- Each spec file exercises a **complete user flow** — not isolated page checks
- Tests navigate through the full journey as described in `flow-walkthrough.md`
- At each step, verify visual elements: headings, key content, navigation state
- Include assertions that confirm the app does what the PRD/FRDs describe
- Use POMs from Step 2 — never raw selectors in specs

### Step 4: Generate Cross-Flow Specs

Identify flows that span multiple features or share navigation paths. Create cross-flow specs that verify:
- Navigation between features works (e.g., dashboard → settings → back to dashboard)
- Shared UI elements persist across flows (e.g., navigation bar, user avatar)
- State carries across flows (e.g., login state persists across page navigation)

### Step 5: Tag and Organize

Apply tags consistently:

| Tag | Usage |
|-----|-------|
| `@smoke` | Critical happy-path flows — minimum set for deployment verification |
| `@flow:{flow-name}` | Traceability to the specific flow in `flow-walkthrough.md` |
| `@frd:{frd-id}` | Traceability to the FRD the flow validates |

---

## Aspire Environment

All e2e tests run against the **Aspire-managed environment**. The Playwright config already handles this:

- `webServer` in `e2e/playwright.config.ts` starts `aspire start` + `aspire wait web`
- Base URL defaults to `http://localhost:3001` (Aspire web port)
- API is available at `http://localhost:5001` (Aspire API port)
- Running locally via Aspire is **non-negotiable** — never start API/Web individually

Do NOT modify the Playwright config or webServer setup. Your tests run against the Aspire environment automatically.

### Post-Deployment E2E Verification

After every Azure deployment, the **full E2E suite** (not just `@smoke`) must pass against the deployed URL. This is enforced by the `azure-deployment` skill. When writing e2e tests, ensure they work with both local Aspire and deployed URLs via `PLAYWRIGHT_BASE_URL`.

---

## Verification

After generating all specs:

1. **List all tests:**
   ```bash
   npx playwright test --list --config=e2e/playwright.config.ts
   ```
   All tests should be listed without errors.

2. **Verify compilation:**
   ```bash
   npx tsc --noEmit --project tsconfig.json
   ```
   All TypeScript files should compile without errors.

3. **Coverage check:**
   Every flow in `flow-walkthrough.md` must have a corresponding spec file. Create a coverage matrix:
   ```
   Flow: "New user signup" → e2e/signup-flow.spec.ts ✅
   Flow: "Returning user login" → e2e/login-flow.spec.ts ✅
   Flow: "Create resource" → e2e/resource-flow.spec.ts ✅
   ...
   ```

---

## Test Quality Rules

1. **Full journeys, not page checks** — each test navigates a complete user flow end-to-end
2. **Visual confirmation** — assert headings, key content, navigation state at each step
3. **No hardcoded waits** — use `waitFor`, `toBeVisible`, `toHaveURL` patterns
4. **No hardcoded test data** — use constants or fixtures
5. **Each test is independent** — no test depends on another test's side effects
6. **POMs for all page interactions** — never raw selectors in spec files
7. **Avoid `test.skip()`** — tests should exist and be runnable (they'll fail until implementation)

---

## Output Structure

```
e2e/
├── playwright.config.ts          # Already exists — do not modify
├── fixtures.ts                   # Shared test fixtures and helpers
├── {flow-name}.spec.ts           # One spec per flow from flow-walkthrough.md
├── smoke.spec.ts                 # Smoke tests (critical happy paths)
└── pages/                        # Page Object Models
    ├── landing.page.ts           # One POM per screen from screen-map.md
    ├── login.page.ts
    ├── dashboard.page.ts
    └── ...
```

---

## State Updates

After completing e2e generation:

1. Update `.spec2cloud/state.json` — set phase to `e2e-generation-complete`
2. Append to `.spec2cloud/audit.log`:
   ```
   [TIMESTAMP] e2e-generation: Generated e2e specs for N flows
   [TIMESTAMP] e2e-generation: Generated N Page Object Models
   [TIMESTAMP] e2e-generation: All specs compile and are listed ✅
   ```
3. Commit all generated files with message: `[e2e-gen] scaffold e2e tests for all flows`

## Mandatory Completion Checklist

The orchestrator MUST verify ALL of the following before marking e2e-generation as complete:

- [ ] At least one Playwright spec file (`e2e/*.spec.ts`) exists for every user flow in `specs/ui/flow-walkthrough.md`
- [ ] A Page Object Model (`e2e/pages/*.page.ts`) exists for every screen in `specs/ui/screen-map.md`
- [ ] Every POM uses `data-testid` selectors from `specs/ui/component-inventory.md` (not CSS classes or XPath)
- [ ] `e2e/playwright.config.ts` exists and is configured for the Aspire environment
- [ ] All spec files compile successfully (`npx playwright test --list` returns all specs without errors)
- [ ] Navigation flows between pages are tested (not just individual page interactions)
- [ ] State JSON and audit log are updated

**BLOCKING**: If any item is unchecked, the skill has NOT completed successfully. The orchestrator must loop back and complete the missing items before advancing to Gherkin generation.
