# Prepare E2E Tests

You are tasked with analyzing code changes and preparing end-to-end (E2E) tests for the <% schema.slug %> project.

## Arguments

- `$ARGUMENTS` - Optional: specific features or areas to focus testing on. If not provided, analyze the git diff automatically.

## Overview

This command analyzes your recent code changes, determines what E2E test coverage is needed, writes the test specs following existing patterns, and runs them to verify they pass.

## Step 1: Analyze Changes

### 1.1 Get Changed Files

Determine what has changed by examining the git diff:

```bash
# If on a feature branch, diff against main
git diff main...HEAD --name-only

# Also check for any uncommitted changes
git diff --name-only
git diff --staged --name-only
```

If `$ARGUMENTS` was provided, focus analysis on the specified features or areas instead of the full diff.

### 1.2 Categorize Changes

Read each changed file and categorize it:

- **Frontend pages/routes**: Files in `<% frontendPath %>/src/routes/` — need navigation tests, content verification, and visual snapshots
- **Frontend components**: Files in `<% frontendPath %>/src/components/` or `<% frontendPath %>/src/pages/` — need interaction tests
- **Backend endpoints/routers**: Files in `<% backendPath %>/libs/router-trpc/` or `<% backendPath %>/libs/actions/` — need frontend integration tests verifying data display
- **Backend views**: Files in `<% backendPath %>/libs/view/` — need data display verification tests
- **Shared types**: Files in `<% backendPath %>/libs/types/` — may affect existing tests
- **Schema changes**: `postxl-schema.json` — affect models and may need comprehensive new tests
- **Forms**: Components containing form elements (TanStack Form, inputs, selects) — need form interaction tests
- **Tables/DataGrids**: Components using DataGrid — need data display, sorting, and filtering tests

### 1.3 Read Changed Files

For each changed file, read its content to understand:

- What routes/URLs are added or modified
- What data is displayed (model names, field names)
- What user interactions are possible (clicks, form fills, navigation)
- What test IDs are used (`data-test-id` attributes)

Also read these reference files for context:

```
e2e/support/model-test-ids.ts       # Available test IDs
e2e/fixtures/test-fixtures.ts       # Available test fixtures
e2e/support/wait-for-page-loaded.ts # Page loading utility
e2e/support/page-stability.ts       # API stability utility
```

### 1.4 Check Existing Test Coverage

Read all existing spec files in `e2e/specs/` to understand what is already covered. Do not duplicate existing tests.

## Step 2: Determine Test Coverage

Based on the analysis, determine which tests to write:

### For New Pages/Routes

- **Navigation test**: Verify the page is accessible at its URL
- **Content verification test**: Verify key content elements are visible
- **Visual regression snapshot**: Capture a baseline screenshot with `toHaveScreenshot()`

### For New Forms

- **Form display test**: Verify form fields are rendered correctly
- **Form interaction test**: Fill fields, submit, and verify success feedback
- **Form validation test**: Submit with invalid data and verify error messages

### For New Tables/Data Views

- **Data display test**: Verify table renders with expected columns and data
- **Sorting test**: Click column headers and verify sort order (if sortable)
- **Empty state test**: Verify empty state message when no data exists

### For API/Backend Changes

- **Data integration test**: Verify the frontend correctly displays API data
- **Error state test**: Verify error handling when API returns errors (if applicable)

### For UI Component Changes

- **Visual regression snapshot**: Capture screenshots of affected pages
- **Interaction test**: Verify component interactions work correctly

## Step 3: Write Tests

### 3.1 Test File Structure

Create new test files in `e2e/specs/` following the naming convention `<feature>.spec.ts`.

**CRITICAL**: Always use the project's custom test fixtures, NOT bare Playwright imports:

```typescript
import { expect, test } from '../fixtures/test-fixtures'
```

### 3.2 Test Patterns to Follow

**Reference the existing examples:**

- `e2e/specs/example.spec.ts` — basic navigation, visual snapshots, content verification
- `e2e/specs/example-backend-isolation.spec.ts` — backend isolation pattern

**Navigation and Snapshot Test Pattern:**

```typescript
import { expect, test } from '../fixtures/test-fixtures'

test.describe('<Feature Name>', () => {
  test('<Page name> page is accessible', async ({ page }) => {
    await page.goto('/<route>')
    await expect(page).toHaveURL(/.*\/<route>$/)
  })

  test('<Page name> page visual snapshot', async ({ page }) => {
    await page.goto('/<route>')
    await expect(page).toHaveScreenshot()
  })
})
```

**Content Verification Pattern:**

```typescript
test('<Page> displays expected content', async ({ page }) => {
  await page.goto('/<route>')
  await expect(page.getByText('Expected Heading')).toBeVisible()
  await expect(page.getByTestId('some-test-id')).toBeVisible()
})
```

**Form Interaction Pattern:**

```typescript
test.describe('<Form Name> Form', () => {
  test('can fill and submit form', async ({ page }) => {
    await page.goto('/<form-route>')

    // Fill form fields
    await page.getByLabel('Field Name').fill('Test Value')
    await page.getByRole('combobox').click()
    await page.getByRole('option', { name: 'Option' }).click()

    // Submit
    await page.getByRole('button', { name: 'Submit' }).click()

    // Verify success
    await expect(page.getByText('Success')).toBeVisible()
  })
})
```

**Table/DataGrid Verification Pattern:**

```typescript
test.describe('<Model> Table', () => {
  test('displays data in table', async ({ page }) => {
    await page.goto('/<admin-route>')

    // Verify table headers
    await expect(page.getByText('Column Header')).toBeVisible()

    // Verify data is loaded
    await expect(page.locator('table tbody tr').first()).toBeVisible()
  })
})
```

### 3.3 Available Utilities

Use these utilities from the `support/` and `fixtures/` directories:

- `waitForPageLoaded(page)` from `support/wait-for-page-loaded` — wait for DOM + images
- `waitForAppIdle(page)` from `support/page-stability` — wait for API requests to complete
- `resetData()` from `support/reset-data` — reset backend data (stateful mode only)
- `setData(data)` from `support/set-data` — set specific test data (stateful mode only)
- `maskToast(page)` from `support/mask-toast` — hide toast notifications for screenshots
- `clickCheckboxByName(page, name)` from `support/checkbox-click` — click checkboxes reliably
- `MODEL_TEST_IDS` from `support/model-test-ids` — generated test IDs for models
- `DataMocker` from `@mock-data/dataMocker.class` — create mock data

### 3.4 Best Practices

1. **Always use custom test fixtures**: `import { expect, test } from '../fixtures/test-fixtures'`
2. **Use descriptive test names**: Explain what the test verifies, not how
3. **Use `data-test-id` attributes**: Prefer `getByTestId()` for stable selectors
4. **Use role-based selectors**: `getByRole('button', { name: '...' })` for accessibility
5. **Avoid `waitForTimeout()`**: Use condition-based waits instead
6. **Group related tests**: Use `test.describe()` blocks
7. **Mask toasts for screenshots**: Use `maskToast(page)` before `toHaveScreenshot()` if toasts interfere
8. **Do not modify existing test files** unless the changes specifically affect those tests

## Step 4: Run and Verify

### 4.1 Run the Tests

Execute the E2E tests using the automated script:

```bash
<% cdProjectDir %>./scripts/e2e.sh
```

### 4.2 Handle First-Run Snapshot Baselines

New tests with `toHaveScreenshot()` will fail on the first run because no baseline snapshot exists yet. This is expected. Re-run the tests to create the baseline and confirm the snapshot is correct.

### 4.3 Investigate Failures

If tests fail for reasons other than missing baselines, follow the investigation workflow from the `run-e2e-tests` command:

1. **Parse test output** to identify which tests failed
2. **Read the last run status**: `cat e2e/test-results/.last-run.json`
3. **Read monocart report**: `cat e2e/monocart-report/index.json`
4. **Analyze failure type**: snapshot mismatch, element not found, timeout, assertion failure
5. **Read screenshots** from `e2e/test-results/` for visual context
6. **Fix and re-run** until all tests pass

### 4.4 Common Fixes

- **Element not found**: Add `waitForPageLoaded()` or check the selector matches the DOM
- **Timeout**: Add proper waits for API responses using `waitForAppIdle()`
- **Toast interfering with screenshot**: Add `maskToast(page)` before the screenshot assertion
- **Animation causing flaky snapshots**: The fixture auto-disables them, but custom CSS animations may need attention

## Step 5: Report Summary

After completing the process, provide:

- **Changes analyzed**: List of files categorized by type
- **Tests created**: List of new spec files with test names
- **Test results**: Pass/fail status
- **Coverage gaps**: Any areas that could not be automatically tested (e.g., require auth, complex multi-step workflows)

## Important Notes

- **Tests run in Docker** for consistent snapshots — never update snapshots outside Docker
- **Use stateless mode** as default for E2E tests
- **Follow existing patterns**: Match the coding style and structure of `example.spec.ts`
- **CRITICAL**: Always run tests in a NEW terminal separate from backend and frontend
