# Run E2E Tests

You are tasked with helping the user run end-to-end (E2E) tests in the Claude Code environment (VS Code with Claude assistance).

## Overview

The E2E tests use Playwright to verify that the application works as expected from the user's perspective. This command works for the <% schema.slug %> project.

**Tests always run inside a Docker container** to ensure snapshot consistency across different developer machines and CI. Docker guarantees identical rendering (fonts, DPI, browser version) so snapshot comparisons are deterministic regardless of the host OS.

> **⚠️ TERMINAL MANAGEMENT IN CLAUDE CODE**: When running commands through Claude, terminal reuse can cause background services to be interrupted. To avoid this, manually open separate terminal windows using the VS Code Terminal menu before starting each service (Backend, Frontend, Tests). This ensures each service runs in its own isolated terminal.

## E2E Test Modes

The project supports two types of E2E tests:

- **Stateful**: Tests that can change data. Each test runs a data reset before execution. Slower, uses limited seed data.
- **Stateless**: Tests that don't alter server data, only test views. Faster, can use larger/more complex seed data.

**For Claude Code environment, use stateless mode** as the default.

## Prerequisites

Before running E2E tests, ensure:

1. **Docker is running** on the host machine
2. **Backend is running** in E2E stateless mode (or let the script start it)
3. **Frontend is built and running** in E2E mode with Docker URLs (or let the script build it)

## Running E2E Tests

### Option 1: Automated Script (Recommended)

The easiest way to run E2E tests is using the automated script:

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

**What the script does:**

1. ✅ Auto-detects pnpm and activates Node.js 24+ (via nvm/fnm/volta)
2. ✅ Checks if backend/frontend are already running (reuses them if available)
3. 🚀 Starts backend in E2E stateless mode (if needed)
4. 🏗️ Builds frontend with Docker URLs and starts preview server (if needed)
5. 🧪 Runs E2E tests inside a Docker container
6. 🧹 Cleans up only script-started processes on exit (Ctrl+C safe)

**Benefits:**

- Single command to run everything
- Automatic service detection and reuse
- Only cleans up processes it started (your manually-started services are preserved)
- Detailed logs saved to `.e2e-backend.log` and `.e2e-frontend.log`
- Works great with Claude Code

```bash
# Run E2E tests (Docker mode)
<% cdProjectDir %>./scripts/e2e.sh

# Just build the Docker image
<% cdProjectDir %>./scripts/e2e.sh --build-image
```

### Option 2: Manual Step-by-Step Process

If you prefer to start services manually before running the script:

#### 1. Start Backend in E2E Stateless Mode

**Open a new terminal** and run:

```bash
cd <% backendPath %>
pnpm e2e:stateless
```

**Note**: Keep this terminal running.

#### 2. Build and Start Frontend in E2E Mode

**Open a new terminal** and run:

```bash
cd <% frontendPath %>
pnpm e2e:build
```

**Note**: This builds the production version with `host.docker.internal` URLs required for Docker-based testing. Keep this terminal running.

**Important**: Do NOT use `pnpm dev` for E2E tests — the Vite dev server uses `localhost` URLs which are not reachable from inside the Docker container.

#### 3. Run E2E Tests

**Open a new terminal** and run:

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

The script will detect the running backend and frontend, skip starting them, and run the Docker test container directly.

## Test Results and Reports

### View Test Results

- Detailed test results are saved in the `test-results/` directory
- HTML report available in `playwright-report/`
- Test coverage data in `monocart-report/`

## Investigating Test Failures

When tests fail, follow this investigation workflow **automatically** before asking the user for help.

### Step 1: Identify Failed Tests

1. Parse the test runner output to identify which tests failed and their error messages
2. Read the last run status file for a quick summary:
   ```bash
   cat e2e/test-results/.last-run.json
   ```
3. Read the monocart report for detailed structured results (flaky detection, retry info):
   ```bash
   cat e2e/monocart-report/index.json
   ```

### Step 2: Analyze Failure Type

Determine the failure category:

- **Snapshot mismatch**: Expected vs actual screenshot differs. Look for `toHaveScreenshot` errors and compare images in `e2e/test-results/` and `e2e/specs/*-snapshots/`
- **Element not found / Timeout**: A locator couldn't find an element or an action timed out. Usually indicates a selector change, missing wait, or race condition
- **Assertion failure**: A `toEqual`, `toContain`, `toBeVisible` etc. check failed. Check if the expected value or app behavior changed
- **Network/Connection error**: Backend or frontend unreachable. See Troubleshooting section below
- **Flaky test**: Test passed on retry (monocart marks these as `caseType: "flaky"`). Needs stabilization

### Step 3: Read Source Code and Artifacts

1. **Read the failing spec file** to understand what the test does:
   ```
   e2e/specs/<test-file>.spec.ts
   ```
2. **Check screenshots** for visual context — read any `.png` files in `e2e/test-results/` to see what the page actually looked like
3. **Check trace files** if available (captured on first retry): `e2e/test-results/*/trace.zip`
4. **Read related page/component code** if the test interacts with specific frontend components or backend endpoints

### Step 4: Fix and Re-run

Based on the failure type:

**For snapshot mismatches:**
- If the visual change is intentional (e.g., you modified a component), update the snapshot:
  ```bash
  <% cdProjectDir %>./scripts/e2e.sh  # re-run — snapshots update inside Docker for consistency
  ```
- If unintentional, investigate what caused the rendering difference

**For flaky tests (timing/race conditions):**
- Add explicit waits using the project's `waitForPageLoaded()` utility or `page.waitForSelector()`
- Replace `page.waitForTimeout()` with condition-based waits (e.g., `expect(locator).toBeVisible()`)
- Use the `pageStability` fixture to wait for API requests to complete
- Check if animations or transitions need to be disabled (the fixture auto-disables them, but custom CSS animations may need attention)

**For element not found errors:**
- Verify the selector matches the current DOM structure
- Check if a data-testid was renamed or removed
- Add a `waitForPageLoaded()` call before interacting with the element

**For assertion failures:**
- Check if the expected values need updating due to intentional code changes
- Verify test data setup (seed data, mocked data) is correct

### Step 5: Verify the Fix

After applying fixes, re-run the tests:
```bash
<% cdProjectDir %>./scripts/e2e.sh
```

If a test was flaky, consider running it multiple times to confirm stability. You can run a single test file:
```bash
# Inside the Docker container or via the script, target specific tests
<% cdProjectDir %>./scripts/e2e.sh  # full suite to confirm no regressions
```

## Troubleshooting

### Connection Refused Errors

If tests fail with connection errors like "connect ECONNREFUSED":

1. **Verify Docker is running**: The test container needs Docker to be available
2. **Verify backend is running**: Check that the backend is listening on port 4000 and E2E helper on port 3001
3. **Verify frontend is running**: Check that the frontend preview server is on port 3000
4. **Verify frontend was built with Docker URLs**: The frontend must be built with `VITE_PUBLIC_API_URL=http://host.docker.internal:3001`. If you started it with `pnpm dev`, restart with `pnpm e2e:build`

### Greeting Test Shows "Hi !" (Empty User)

This means the frontend cannot reach the backend API from inside the Docker container. The frontend was likely built with `localhost` URLs instead of `host.docker.internal`. Fix by:

1. Stopping the frontend
2. Rebuilding with `pnpm e2e:build` (uses Docker URLs)
3. Or let `./scripts/e2e.sh` handle everything automatically

### Database Connection Issues

If tests fail with database authentication errors:

1. Ensure your local database is running
2. Check database credentials in the backend configuration
3. Verify the database exists and migrations have been run

## Important Notes

- **Tests always run in Docker** for consistent snapshots and CI parity
- **The script preserves your services**: Cleanup only kills processes the script started
- **Frontend must use Docker URLs**: Built with `host.docker.internal` (via `pnpm e2e:build` or the script)
- **Keep backend and frontend running** while executing tests
- **Use stateless mode** as default for better performance
- **Test results** are saved in `test-results/` directory
- **CRITICAL**: Always run tests in a NEW terminal separate from backend and frontend terminals to avoid interrupting the servers
