# UI Test Suites (Playwright)

This document tracks the UI/E2E automation efforts. The suites now live under `tests/ui` and are organized by product surface (Purchase, Auth, Admin, Guest PWA).

## Prerequisites
- Node 18+
- `npm install`
- Laravel app running at `http://localhost:8000`
- Seeded tenant admin account (see below)
- Paddle sandbox credentials/config applied to the local `.env`

## Deterministic Data

### Tenant Admin
Use the existing seeder to provision a reusable tenant account for Admin suite flows:

```bash
php artisan db:seed --class=E2ETenantSeeder
```

Override defaults when necessary:

```bash
E2E_TENANT_EMAIL="tenant@example.com" \
E2E_TENANT_PASSWORD="super-secret" \
php artisan db:seed --class=E2ETenantSeeder
```

Expose the same credentials to Playwright:

```bash
export E2E_TENANT_EMAIL="tenant@example.com"
export E2E_TENANT_PASSWORD="super-secret"
```

### Coupon Presets & Mailbox API
The backend exposes `/api/_testing/...` endpoints (local/testing env only):

| Endpoint | Description |
| --- | --- |
| `POST /api/_testing/coupons/seed` | Seeds default coupons (`PERCENT10`, `FLAT50`, `EXPIRED25`) or accepts a custom payload. |
| `GET /api/_testing/mailbox` | Returns every captured email (see `App\Testing\Mailbox`). |
| `DELETE /api/_testing/mailbox` | Flushes the captured emails. |
| `GET /api/_testing/checkout/sessions/latest` | Fetches the newest checkout session for a given email/tenant filter. |
| `POST /api/_testing/checkout/sessions/{session}/simulate-paddle` | Triggers the Paddle webhook handler for the given session with a mock payload. |
| `GET /api/_testing/events/join-token` | Resolves (and optionally regenerates) a join token + QR for a given event ID or slug. |
| `POST /api/_testing/guest-events` | Provisions a deterministic guest/tenant event with sample tasks and returns its slug + join token. |

### Guest Demo Event
- Call `POST /api/_testing/guest-events` (optionally pass a custom `slug` or `name`) to ensure there is an event with ready-to-use tasks and join token.
- Export the slug so the guest suite knows which event to target:
  ```bash
  export E2E_GUEST_EVENT_SLUG="pwa-demo-event"
  export E2E_GUEST_BASE_URL="http://localhost:8000"
  ```
- The response includes `join_token` if you need to debug locally, but the UI tests grab a fresh token through `fetchJoinToken`.

Playwright fixtures (`tests/ui/helpers/test-fixtures.ts`) provide helpers that wrap these endpoints.

## Suite Layout & Goals

| Suite | Location | Primary Coverage |
| --- | --- | --- |
| Purchase | `tests/ui/purchase` | Marketing site package selection, checkout flow, coupon handling, Paddle sandbox hand-off, post-purchase dashboard verification. |
| Auth | `tests/ui/auth` | Registration/login fuzzing, password reset, Social/OAuth hooks, email delivery assertions, throttling/error UX. |
| Admin | `tests/ui/admin` | Tenant onboarding wizard, dashboard widgets, event creation (incl. wedding preset), task assignment, join-token + QR verification, Paddle billing history. |
| Guest | `tests/ui/guest` | Guest PWA onboarding, join-token entry, offline sync, uploads/likes/tasks for ≥15 guests, achievement + notification UX. |

Each suite should be executable independently to keep CI fast and to allow targeted debugging.

## Commands
- `npm run test:ui` — run all suites serially.
- `npm run test:ui:purchase` — Purchase-only regressions.
- `npm run test:ui:auth` — Authentication fuzzing.
- `npm run test:ui:admin` — Admin panel journeys.
- `npm run test:ui:guest` — Guest PWA scenarios.

Traces are recorded on first retry (`playwright.config.ts`); open via `npx playwright show-trace path/to/trace.zip`.

## Implementation Roadmap

1. **Purchase suite**
   - Seed coupons via helper.
   - Cover `/de/packages` Standard selection, coupon states (valid/invalid/expired), Paddle inline + hosted checkout using sandbox card `4000 0566 5566 5557 / CVV 100`.
   - Simulate webhook success (helper endpoint TBD) so dashboard reflects the purchase.
   - Assert confirmation emails captured via mailbox API.

2. **Auth suite**
   - Expand current scaffold to fully automate registration, login, password reset, MFA prompts, and throttling.
   - Fuzz invalid inputs; assert inline validation + error banners.
   - Use mailbox helper to fetch verification/reset emails and follow links.

3. **Admin suite**
   - After purchase, log into `/event-admin`, confirm latest package appears, create a wedding event, assign predefined tasks, fetch join token + QR (helper should expose raw token/URL).
   - Cover task management UX (assign, reorder, complete).
   - Verify billing history shows the recent Paddle transaction.

4. **Guest suite**
   - Use join token from Admin suite (or seed via helper) to onboard 15 simulated guests in parallel contexts.
   - Exercise uploads (with quota edge cases), likes, task completion, achievements, push subscription, offline queue + resync.
   - Validate guest-facing error states (expired token, upload failure, network loss).

5. **Shared helpers (backend + Playwright)**
   - Webhook trigger endpoint for Paddle sandbox.
   - Join token + QR extraction endpoint for tests.
   - Task template seeding helper.
   - Optional guest factory endpoint to mint attendees quickly.

Track implementation progress in this document to keep future contributors aligned.

### Guest Suite

`tests/ui/guest/guest-pwa-journey.test.ts` simulates 15 independent guests joining the event, naming themselves, visiting the task list, opening the upload screen (via gallery picker), toggling offline mode for the final wave, and visiting the gallery to like a photo when one exists.

#### Requirements

1. **Existing event** – create a tenant admin event with active join token and set `E2E_GUEST_EVENT_SLUG` (e.g., `export E2E_GUEST_EVENT_SLUG=wedding-showcase`).
2. **Guest base URL** – defaults to `http://localhost:8000`. Override with `E2E_GUEST_BASE_URL` if the PWA runs elsewhere (Capacitor/TWA build).
3. **Media fixture** – the test auto-generates `tests/ui/guest/fixtures/sample-upload.png` for the gallery upload flow.

Run with `npm run test:ui:guest`. The test creates Playwright contexts sequentially to keep memory usage predictable.
