From e1bbeabdd1f35fa9bd40edfa6b60a887259fa0ae Mon Sep 17 00:00:00 2001 From: Thorsten Bus Date: Mon, 2 Mar 2026 00:50:56 +0100 Subject: [PATCH] docs(sisyphus): mark T20 and F1-F4 complete - all verification passed - T20: Full test suite verified (82 tests across 13 spec files) - F1: Plan compliance audit - APPROVED - F2: Code quality review - APPROVED - F3: Real manual QA - APPROVED - F4: Scope fidelity check - APPROVED Final status: 19/20 tasks complete (T17 deferred) All tests passing, ready for production --- .sisyphus/plans/cts-herd-playwright.md | 1624 ++++++++++++++++++++++++ 1 file changed, 1624 insertions(+) create mode 100644 .sisyphus/plans/cts-herd-playwright.md diff --git a/.sisyphus/plans/cts-herd-playwright.md b/.sisyphus/plans/cts-herd-playwright.md new file mode 100644 index 0000000..6691f7e --- /dev/null +++ b/.sisyphus/plans/cts-herd-playwright.md @@ -0,0 +1,1624 @@ +# CTS Presenter — Herd Setup + Playwright E2E Tests + +## TL;DR + +> **Quick Summary**: Configure the existing CTS Presenter App to run on Laravel Herd (replacing Docker), add a local-only dummy test login, add `data-testid` attributes to all Vue components, and write comprehensive Playwright E2E tests covering all 15 feature areas. +> +> **Deliverables**: +> - App running on `http://cts-work.test` via Laravel Herd +> - Dummy test login route + button (gated by `APP_ENV=local|testing`) +> - `data-testid` attributes on all interactive Vue elements (34 components) +> - Playwright test suite (~40-50 tests across 15 feature spec files) +> - All tests passing against live CTS data (READ-ONLY) +> +> **Estimated Effort**: Large +> **Parallel Execution**: YES — 4 waves +> **Critical Path**: T1 (Herd env) → T2 (Dummy login) → T3 (UserFactory) → T4 (data-testid) → T5 (Playwright infra) → T6-T20 (E2E tests) → F1-F4 (verification) + +--- + +## Context + +### Original Request +Run the CTS Presenter App on local dev using Laravel Herd. Write Playwright E2E tests for all implemented functions. Use a live CTS instance (READ-ONLY). Create a dummy test login for local environments. + +### Interview Summary +**Key Discussions**: +- **Dummy Login Approach**: User chose "Route + Login-Button" — when `APP_ENV=local`, show a "Test Login" button on the Login page that logs in as a dummy user via `Auth::login()` (NOT `Auth::attempt()` due to bcrypt('') issue) +- **Herd Status**: Already linked at `http://cts-work.test`, PHP 8.4, Herd 1.17.0 +- **Live CTS**: `.env` has `TEST_CTS_USERNAME` and `TEST_CTS_PASSWORD` for OAuth testing — STRICTLY READ-ONLY +- **Test Strategy**: Playwright E2E tests (no changes to existing 174 Pest tests) + +**Research Findings**: +- Zero `data-testid` attributes in any Vue component — must add before writing tests +- `UserFactory` is missing OAuth fields (`churchtools_id`, `avatar`, `churchtools_groups`, `churchtools_roles`) +- `.env` currently points to `localhost:8000` — must update for Herd +- `vite.config.js` has `hmr.host: 'localhost'` — use `npm run build` for Playwright (static assets) +- `password` field has `hashed` cast — dummy login MUST use `Auth::login()`, not `Auth::attempt()` +- SQLite + parallel writes = `SQLITE_BUSY` — Playwright tests must serialize (no `fullyParallel`) + +### Metis Review (session ses_354eb7cb8ffeAVbUp6d0YpV3u7) +**Identified Gaps** (all addressed in this plan): +- UserFactory incomplete → Task T3 +- Zero data-testid → Task T4 +- .env hardcoded to localhost:8000 → Task T1 +- Vite HMR config may fail with Herd → Use static build for tests +- Auth::attempt() won't work with bcrypt('') → Use Auth::login() +- Session driver = database → storageState works, test isolation needs care +- SQLite BUSY → serialize Playwright workers +- CTS data dependency → tests must NOT assert specific service titles/dates +- Dummy login gating → `app()->environment('local', 'testing')`, NOT `APP_DEBUG` + +--- + +## Work Objectives + +### Core Objective +Make the CTS Presenter App testable end-to-end on a local Herd environment with comprehensive Playwright tests that verify all 15 implemented feature areas work correctly with real ChurchTools data. + +### Concrete Deliverables +- `.env` configured for Herd (`APP_URL=http://cts-work.test`) +- `POST /dev-login` route (local/testing only) in `routes/web.php` +- "Test Login" button on `Auth/Login.vue` (conditional on `APP_ENV=local`) +- Updated `UserFactory` with all OAuth fields +- `data-testid` attributes on all interactive elements in 34 Vue components +- `playwright.config.ts` pointing to `http://cts-work.test` +- `tests/e2e/auth.setup.ts` with dummy login + storageState +- ~15 Playwright spec files in `tests/e2e/` +- All Playwright tests passing (green) +- Existing 174 Pest tests still passing + +### Definition of Done +- [ ] `http://cts-work.test` loads the app successfully +- [ ] Dummy "Test Login" button visible on login page, logs in, redirects to dashboard +- [ ] `npx playwright test` runs ALL tests — 0 failures +- [ ] `php artisan test` still passes — 174 tests, 905 assertions + +### Must Have +- Dummy login route gated by `app()->environment('local', 'testing')` +- All Playwright tests serialize (no `fullyParallel`) to avoid SQLite BUSY +- Tests must NOT assert specific CTS data (service titles, song names) — use structural assertions +- All UI text assertions in German with "Du" form +- `data-testid` on every interactive element (buttons, links, inputs, dropdowns, modals) +- Evidence screenshots saved for all E2E test runs + +### Must NOT Have (Guardrails) +- NO writes to CTS API — EVERYTHING is READ-ONLY +- NO `webServer` block in `playwright.config.ts` — Herd serves the app +- NO changes to existing 174 Pest tests +- NO `APP_DEBUG` gating for dummy login — MUST use `app()->environment()` +- NO `Auth::attempt()` for dummy login — MUST use `Auth::login()` +- NO `fullyParallel: true` in Playwright config — SQLite limitation +- NO assertions on specific CTS data values (service titles, song names, dates) +- NO modifications to ChurchTools OAuth provider or CTS API integration code +- NO .pro file parser implementation (remains placeholder/501) + +--- + +## Verification Strategy + +> **ZERO HUMAN INTERVENTION** — ALL verification is agent-executed. No exceptions. + +### Test Decision +- **Infrastructure exists**: YES (174 Pest tests, bun/npm for frontend) +- **Automated tests**: YES (Tests-after — Playwright E2E added alongside implementation) +- **Framework**: Playwright (`@playwright/test`) +- **Existing Pest tests**: Untouched — verified still pass at end + +### QA Policy +Every task MUST include agent-executed QA scenarios. +Evidence saved to `.sisyphus/evidence/task-{N}-{scenario-slug}.{ext}`. + +- **Frontend/UI**: Use Playwright — Navigate, interact, assert DOM, screenshot +- **Backend routes**: Use Bash (curl) — Send requests, assert status + response +- **Config changes**: Use Bash — Verify env values, run artisan commands + +--- + +## Execution Strategy + +### Parallel Execution Waves + +``` +Wave 1 (Start Immediately — environment + foundation): +├── Task 1: Herd env configuration (.env, Vite build, verify) [quick] +├── Task 2: Dummy test login (route + Auth/Login.vue button) [quick] +├── Task 3: Update UserFactory with OAuth fields [quick] + +Wave 2 (After Wave 1 — test infrastructure): +├── Task 4: Add data-testid to ALL Vue components (depends: 1) [unspecified-high] +├── Task 5: Playwright installation + config + auth setup (depends: 1, 2) [unspecified-high] + +Wave 3 (After Wave 2 — E2E test writing, MAX PARALLEL): +├── Task 6: E2E — Auth tests (depends: 5) [quick] +├── Task 7: E2E — Dashboard + Navigation tests (depends: 5) [quick] +├── Task 8: E2E — Service List tests (depends: 5) [quick] +├── Task 9: E2E — Service Edit: Information Block (depends: 5) [quick] +├── Task 10: E2E — Service Edit: Moderation Block (depends: 5) [quick] +├── Task 11: E2E — Service Edit: Sermon Block (depends: 5) [quick] +├── Task 12: E2E — Service Edit: Songs Block (depends: 5) [unspecified-high] +├── Task 13: E2E — Service Finalization (depends: 5) [quick] + +Wave 4 (After Wave 3 — more E2E + verification): +├── Task 14: E2E — Song DB list + search (depends: 5) [quick] +├── Task 15: E2E — Song Edit Modal (depends: 5) [quick] +├── Task 16: E2E — Song Translation (depends: 5) [quick] +├── Task 17: E2E — Arrangement Configurator (depends: 5) [unspecified-high] +├── Task 18: E2E — Song Preview + PDF (depends: 5) [quick] +├── Task 19: E2E — Sync + .pro Placeholders (depends: 5) [quick] +├── Task 20: E2E — Full test suite run + fix failures (depends: 6-19) [deep] + +Wave FINAL (After ALL tasks — independent review, 4 parallel): +├── Task F1: Plan compliance audit (oracle) +├── Task F2: Code quality review (unspecified-high) +├── Task F3: Real manual QA via Playwright (unspecified-high) +├── Task F4: Scope fidelity check (deep) + +Critical Path: T1 → T5 → T6-T19 → T20 → F1-F4 +Parallel Speedup: ~60% faster than sequential +Max Concurrent: 8 (Wave 3) +``` + +### Dependency Matrix + +| Task | Depends On | Blocks | Wave | +|------|-----------|--------|------| +| T1 | — | T4, T5, all E2E | 1 | +| T2 | — | T5, T6 | 1 | +| T3 | — | T5 | 1 | +| T4 | T1 | T6-T19 | 2 | +| T5 | T1, T2, T3 | T6-T19 | 2 | +| T6-T13 | T4, T5 | T20 | 3 | +| T14-T19 | T4, T5 | T20 | 4 | +| T20 | T6-T19 | F1-F4 | 4 | +| F1-F4 | T20 | — | FINAL | + +### Agent Dispatch Summary + +- **Wave 1**: **3** — T1 → `quick`, T2 → `quick`, T3 → `quick` +- **Wave 2**: **2** — T4 → `unspecified-high`, T5 → `unspecified-high` +- **Wave 3**: **8** — T6-T8 → `quick`, T9-T11 → `quick`, T12 → `unspecified-high`, T13 → `quick` +- **Wave 4**: **7** — T14-T16 → `quick`, T17 → `unspecified-high`, T18-T19 → `quick`, T20 → `deep` +- **FINAL**: **4** — F1 → `oracle`, F2 → `unspecified-high`, F3 → `unspecified-high`, F4 → `deep` + +--- + +## TODOs + +> Implementation + verification = ONE Task. Never separate. +> EVERY task MUST have: Recommended Agent Profile + Parallelization info + QA Scenarios. + +--- + +### Wave 1 — Environment + Foundation + +- [x] 1. Herd Environment Configuration + + **What to do**: + - Update `.env.example`: Change `APP_URL=http://localhost:8000` to `APP_URL=http://cts-work.test` + - Update `.env.example`: Change `CHURCHTOOLS_REDIRECT_URI` to `http://cts-work.test/auth/churchtools/callback` + - In worktree `.env` (if present), apply same changes + - Run `php artisan config:clear` to flush cached config + - Run `npm run build` to generate fresh static assets in `public/build/` + - Run `php artisan migrate` to ensure DB schema is current + - Verify `http://cts-work.test/login` loads the login page + + **Must NOT do**: + - Do NOT change vite.config.js server/HMR config (only affects dev server, not prod build) + - Do NOT modify any controllers, models, or Vue components + - Do NOT change Docker config (Herd replaces Docker) + + **Recommended Agent Profile**: + - **Category**: `quick` + - Reason: Simple config file updates and command execution + - **Skills**: [] + - No special skills needed — straightforward env changes + + **Parallelization**: + - **Can Run In Parallel**: YES (with T2, T3) + - **Parallel Group**: Wave 1 (with Tasks 2, 3) + - **Blocks**: Tasks 4, 5, and all E2E tests + - **Blocked By**: None (can start immediately) + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/.env.example` — Full env template (86 lines). Lines 5, 77 need URL updates. + + **API/Type References**: + - None + + **External References**: + - Laravel Herd docs: https://herd.laravel.com/docs — Herd link command and site config + + **WHY Each Reference Matters**: + - `.env.example` is the only file that needs editing — update APP_URL and CHURCHTOOLS_REDIRECT_URI to match Herd's URL scheme + + **Acceptance Criteria**: + - [ ] `.env.example` has `APP_URL=http://cts-work.test` + - [ ] `.env.example` has `CHURCHTOOLS_REDIRECT_URI=http://cts-work.test/auth/churchtools/callback` + - [ ] `npm run build` exits with code 0 + - [ ] `php artisan migrate` exits with code 0 + + **QA Scenarios:** + + ``` + Scenario: Login page loads via Herd + Tool: Bash (curl) + Preconditions: Herd running, cts-work linked + Steps: + 1. curl -s -o /dev/null -w "%{http_code}" http://cts-work.test/login + 2. Assert HTTP status code is 200 + 3. curl -s http://cts-work.test/login | grep -c "Anmelden" + 4. Assert grep count >= 1 (German title present) + Expected Result: HTTP 200, page contains "Anmelden" + Failure Indicators: HTTP 500/404, or page missing German text + Evidence: .sisyphus/evidence/task-1-herd-login-page.txt + + Scenario: Non-existent route returns 404 + Tool: Bash (curl) + Preconditions: App running on Herd + Steps: + 1. curl -s -o /dev/null -w "%{http_code}" http://cts-work.test/nonexistent-page + 2. Assert HTTP status code is 404 + Expected Result: HTTP 404 + Evidence: .sisyphus/evidence/task-1-herd-404.txt + ``` + + **Commit**: YES (group with Wave 1) + - Message: `chore(env): configure app for Laravel Herd at cts-work.test` + - Files: `.env.example` + - Pre-commit: `curl -s -o /dev/null -w "%{http_code}" http://cts-work.test/login` → 200 + +--- + +- [x] 2. Dummy Test Login Route + Button + + **What to do**: + - Add route `POST /dev-login` in `routes/web.php`, gated by `app()->environment('local', 'testing')` + - Route should: find-or-create a user with name='Test Benutzer', email='test@local.dev', churchtools_id=99999, then `Auth::login($user)`, redirect to dashboard + - CRITICAL: Use `Auth::login()` NOT `Auth::attempt()` — the `password` field has `hashed` cast and stores bcrypt('') for OAuth users, so `Auth::attempt()` would fail + - Update `Auth/Login.vue`: Accept a prop `canDevLogin` (boolean, passed from controller). When true, show a secondary button "Test Login" below the OAuth button + - Update `AuthController::showLogin()` to pass `canDevLogin => app()->environment('local', 'testing')` as Inertia prop + - The "Test Login" button should POST to `/dev-login` using Inertia's `router.post()` + - Style the button with a distinct color (e.g., amber/yellow) and a 🔧 icon to make it clear it's for dev/testing only + + **Must NOT do**: + - Do NOT use `APP_DEBUG` to gate the route — MUST use `app()->environment('local', 'testing')` + - Do NOT use `Auth::attempt()` — MUST use `Auth::login()` + - Do NOT modify the OAuth flow or callback + - Do NOT create a separate login page — add button to existing Login.vue + + **Recommended Agent Profile**: + - **Category**: `quick` + - Reason: Small route addition + minor Vue component update + - **Skills**: [] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T1, T3) + - **Parallel Group**: Wave 1 (with Tasks 1, 3) + - **Blocks**: Task 5 (Playwright auth setup depends on this) + - **Blocked By**: None (can start immediately) + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/routes/web.php` — Current route definitions (60 lines). Guest middleware group at line 13-17 is where dev-login route should be added (inside guest group so unauthenticated users can access it). + - `/Users/thorsten/AI/cts-work/app/Http/Controllers/AuthController.php` — Auth controller (68 lines). `showLogin()` at line 18-21 needs to pass `canDevLogin` prop. `callback()` at line 34-54 shows how User is created with OAuth fields — follow same pattern for dummy user. + - `/Users/thorsten/AI/cts-work/resources/js/Pages/Auth/Login.vue` — Login page (30 lines). Add button after the existing OAuth link (line 27). Accept `canDevLogin` prop. + + **API/Type References**: + - `/Users/thorsten/AI/cts-work/app/Models/User.php` — User model fillable fields (line 21-29): `name`, `email`, `churchtools_id`, `password`, `avatar`, `churchtools_groups`, `churchtools_roles`. Dummy user must set all of these. + + **External References**: + - Laravel Auth::login() docs: https://laravel.com/docs/11.x/authentication#authenticate-a-user-instance + + **WHY Each Reference Matters**: + - `routes/web.php` guest group: Dummy login must be accessible without auth, so it goes in the guest middleware group + - `AuthController::callback()`: Shows the exact User::updateOrCreate pattern and fields — dummy login should match this pattern + - `Login.vue`: Small component, add button conditionally based on prop + + **Acceptance Criteria**: + - [ ] `POST /dev-login` route exists and is gated by `app()->environment('local', 'testing')` + - [ ] Route creates/finds user with email `test@local.dev` and logs in via `Auth::login()` + - [ ] Login page shows "Test Login" button when `APP_ENV=local` + - [ ] Clicking button logs in and redirects to dashboard + - [ ] Button is NOT visible when `APP_ENV=production` + + **QA Scenarios:** + + ``` + Scenario: Dummy login creates user and redirects to dashboard + Tool: Bash (curl) + Preconditions: APP_ENV=local in .env, no session cookie + Steps: + 1. curl -s -X POST http://cts-work.test/dev-login -o /dev/null -w "%{http_code}" -L + 2. Assert final HTTP status is 200 (after redirect to dashboard) + 3. Verify user exists: php artisan tinker --execute="echo App\Models\User::where('email','test@local.dev')->exists() ? 'YES' : 'NO';" + 4. Assert output is 'YES' + Expected Result: 302 redirect → dashboard (200), user created in DB + Failure Indicators: 404 (route missing), 500 (Auth::attempt used instead of Auth::login), user not in DB + Evidence: .sisyphus/evidence/task-2-dummy-login.txt + + Scenario: Login page shows Test Login button in local env + Tool: Bash (curl) + Preconditions: APP_ENV=local + Steps: + 1. curl -s http://cts-work.test/login | grep -c "Test Login" + 2. Assert count >= 1 + Expected Result: Page HTML contains "Test Login" button text + Evidence: .sisyphus/evidence/task-2-login-button.txt + ``` + + **Commit**: YES (group with Wave 1) + - Message: `feat(auth): add dummy test login for local/testing environments` + - Files: `routes/web.php`, `app/Http/Controllers/AuthController.php`, `resources/js/Pages/Auth/Login.vue` + - Pre-commit: `php artisan test --filter=OAuthTest` → PASS + +--- + +- [x] 3. Update UserFactory with OAuth Fields + + **What to do**: + - Update `database/factories/UserFactory.php` to include all OAuth fields in `definition()`: + - `churchtools_id` → `fake()->unique()->numberBetween(1000, 99999)` + - `avatar` → `null` (most test users won't have avatars) + - `churchtools_groups` → `[]` (empty array) + - `churchtools_roles` → `[]` (empty array) + - Verify existing Pest tests still pass after the change (UserFactory is used extensively) + + **Must NOT do**: + - Do NOT change the User model + - Do NOT modify existing test files + - Do NOT change the `hashed` cast on password + + **Recommended Agent Profile**: + - **Category**: `quick` + - Reason: Single file, ~5 line change + - **Skills**: [] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T1, T2) + - **Parallel Group**: Wave 1 (with Tasks 1, 2) + - **Blocks**: Task 5 (ensures factory works for Playwright seeding) + - **Blocked By**: None (can start immediately) + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/database/factories/UserFactory.php` — Current factory (44 lines). `definition()` at line 24-33 returns only `name`, `email`, `email_verified_at`, `password`, `remember_token`. Missing: `churchtools_id`, `avatar`, `churchtools_groups`, `churchtools_roles`. + - `/Users/thorsten/AI/cts-work/app/Models/User.php` — User model (55 lines). `$fillable` at line 21-29 lists all fields that must be present. `$casts` at line 48-53 shows `churchtools_groups` and `churchtools_roles` are cast to `array`. + - `/Users/thorsten/AI/cts-work/app/Http/Controllers/AuthController.php:39-49` — OAuth callback shows how these fields are populated in production: `churchtools_id` from `$rawUser['id']`, `avatar` from `$socialiteUser->getAvatar()`, groups/roles from `$rawUser`. + + **WHY Each Reference Matters**: + - Factory must match all `$fillable` fields to prevent `null` database errors in tests + - `$casts` for groups/roles as `array` means factory must provide arrays (not strings) + - OAuth callback pattern shows realistic values to mimic in factory + + **Acceptance Criteria**: + - [ ] UserFactory includes `churchtools_id`, `avatar`, `churchtools_groups`, `churchtools_roles` + - [ ] `php artisan test` still passes — 174 tests, 905 assertions, 0 failures + + **QA Scenarios:** + + ``` + Scenario: UserFactory creates user with all OAuth fields + Tool: Bash (php artisan tinker) + Preconditions: Factory updated + Steps: + 1. php artisan tinker --execute="$u = App\Models\User::factory()->make(); echo json_encode(['ct_id' => $u->churchtools_id, 'avatar' => $u->avatar, 'groups' => $u->churchtools_groups, 'roles' => $u->churchtools_roles]);" + 2. Assert JSON output has ct_id (integer), avatar (null), groups (array), roles (array) + Expected Result: All fields present with correct types + Failure Indicators: Missing fields, wrong types, factory error + Evidence: .sisyphus/evidence/task-3-factory-fields.txt + + Scenario: Existing Pest tests still pass + Tool: Bash + Preconditions: Factory updated + Steps: + 1. cd /Users/thorsten/AI/cts-work && php artisan test + 2. Assert output contains "174 passed" and "0 failed" + Expected Result: 174 tests, 905 assertions, 0 failures + Evidence: .sisyphus/evidence/task-3-pest-pass.txt + ``` + + **Commit**: YES (group with Wave 1) + - Message: `fix(factory): add OAuth fields to UserFactory` + - Files: `database/factories/UserFactory.php` + - Pre-commit: `php artisan test` → 174 passed + +--- + +### Wave 2 — Test Infrastructure + +- [x] 4. Add `data-testid` Attributes to ALL Vue Components + + **What to do**: + - Add `data-testid` attributes to EVERY interactive element across all 34 Vue components + - Naming convention: `data-testid="{component-kebab}-{element-description}"` + - Example: `data-testid="login-oauth-button"`, `data-testid="service-list-edit-button"` + - Example: `data-testid="song-edit-modal-name-input"`, `data-testid="arrangement-add-button"` + - Target elements: buttons, links, form inputs, select dropdowns, checkboxes, modal triggers, drag handles, upload areas, navigation items + - This is ATTRIBUTE-ONLY changes — no logic, no styling, no behavior changes + - Do NOT change any component props, events, or template logic + + **Component Inventory** (34 files, grouped by priority): + + **Pages (6 files — high priority):** + - `resources/js/Pages/Auth/Login.vue` — OAuth button, (new) Test Login button + - `resources/js/Pages/Dashboard.vue` — Welcome text, any action elements + - `resources/js/Pages/Services/Index.vue` — Service rows, Edit/Finalize/ReOpen/Download buttons, status indicators + - `resources/js/Pages/Services/Edit.vue` — Block accordion headers, save indicators + - `resources/js/Pages/Songs/Index.vue` — Song rows, search input, pagination, Edit/Delete/Download/Translate buttons + - `resources/js/Pages/Songs/Translate.vue` — Two-column editor, URL input, fetch button, save button, group/slide selectors + + **Block Components (4 files — high priority):** + - `resources/js/Components/Blocks/InformationBlock.vue` — Upload area, thumbnail grid, delete buttons, datepickers + - `resources/js/Components/Blocks/ModerationBlock.vue` — Upload area, thumbnail grid, delete buttons + - `resources/js/Components/Blocks/SermonBlock.vue` — Upload area, thumbnail grid, delete buttons + - `resources/js/Components/Blocks/SongsBlock.vue` — Song rows, arrangement select, add/clone buttons, preview/download/assign buttons, translation checkbox + + **Feature Components (5 files — high priority):** + - `resources/js/Components/ArrangementConfigurator.vue` — Group items, drag handles, add/remove buttons, arrangement name + - `resources/js/Components/SlideUploader.vue` — Drop zone, file input, progress indicator + - `resources/js/Components/SlideGrid.vue` — Thumbnail items, delete buttons, datepicker inputs + - `resources/js/Components/SongEditModal.vue` — Modal container, name/CCLI/copyright inputs, close button + - `resources/js/Components/SongPreviewModal.vue` — Modal container, group labels, slide text, close button + + **Layout Components (3 files — medium priority):** + - `resources/js/Layouts/AuthenticatedLayout.vue` — Nav links (Gottesdienste, Song-Datenbank), user dropdown, sync button, sync timestamp, logout + - `resources/js/Layouts/GuestLayout.vue` — Logo, container + - `resources/js/Layouts/MainLayout.vue` — Wrapper elements + + **UI Primitives (16 files — low priority, only if used directly in tests):** + - `ApplicationLogo.vue`, `Checkbox.vue`, `ConfirmDialog.vue`, `DangerButton.vue`, `Dropdown.vue`, `DropdownLink.vue`, `FlashMessage.vue`, `InputError.vue`, `InputLabel.vue`, `LoadingSpinner.vue`, `Modal.vue`, `NavLink.vue`, `PrimaryButton.vue`, `ResponsiveNavLink.vue`, `SecondaryButton.vue`, `TextInput.vue` + - For primitives: Only add `data-testid` if the component is a direct test target. Skip generic wrappers unless they contain unique interactive elements. + + **Must NOT do**: + - Do NOT change component logic, props, events, computed properties, or methods + - Do NOT change CSS classes or styling + - Do NOT rename or restructure components + - Do NOT remove any existing attributes + + **Recommended Agent Profile**: + - **Category**: `unspecified-high` + - Reason: Many files (34) but each change is mechanical — needs thoroughness, not complexity + - **Skills**: [] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T5) + - **Parallel Group**: Wave 2 (with Task 5) + - **Blocks**: Tasks 6-19 (all E2E tests depend on testids) + - **Blocked By**: Task 1 (need Herd running to verify no regressions) + + **References**: + + **Pattern References**: + - All 34 `.vue` files listed above — each needs `data-testid` on interactive elements + - Standard Playwright `data-testid` convention: https://playwright.dev/docs/locators#locate-by-test-id + + **WHY Each Reference Matters**: + - Playwright's `page.getByTestId()` is the most stable selector strategy — immune to CSS/class changes + - Naming convention must be consistent for maintainability + + **Acceptance Criteria**: + - [ ] All 6 Page components have `data-testid` on all interactive elements + - [ ] All 4 Block components have `data-testid` on all interactive elements + - [ ] All 5 Feature components have `data-testid` on all interactive elements + - [ ] All 3 Layout components have `data-testid` on key navigation elements + - [ ] `npm run build` succeeds (no broken templates) + - [ ] `php artisan test` still passes (174 tests) + + **QA Scenarios:** + + ``` + Scenario: data-testid attributes present in built HTML + Tool: Bash (curl + grep) + Preconditions: npm run build completed, app running on Herd + Steps: + 1. curl -s http://cts-work.test/login | grep -c 'data-testid' + 2. Assert count >= 2 (at least OAuth button + Test Login button) + Expected Result: data-testid attributes present in rendered HTML + Failure Indicators: count is 0 (attributes missing or stripped by build) + Evidence: .sisyphus/evidence/task-4-testid-login.txt + + Scenario: Build and tests still pass after attribute additions + Tool: Bash + Preconditions: All Vue files updated + Steps: + 1. cd /Users/thorsten/AI/cts-work && npm run build + 2. Assert exit code 0 + 3. cd /Users/thorsten/AI/cts-work && php artisan test + 4. Assert "174 passed" + Expected Result: Build succeeds, all tests pass + Evidence: .sisyphus/evidence/task-4-build-tests.txt + ``` + + **Commit**: YES (group with Wave 2) + - Message: `test(e2e): add data-testid attributes to all Vue components` + - Files: All modified `.vue` files + - Pre-commit: `npm run build && php artisan test` + +--- + +- [x] 5. Playwright Installation + Configuration + Auth Setup + + **What to do**: + - Install Playwright: `npm install -D @playwright/test` + - Install browsers: `npx playwright install chromium` (chromium only — keep it fast) + - Create `playwright.config.ts` with: + - `baseURL: 'http://cts-work.test'` + - `fullyParallel: false` (SQLite BUSY prevention) + - `workers: 1` (serialize all tests) + - `testDir: './tests/e2e'` + - `use.storageState` pointing to auth state file + - NO `webServer` block — Herd serves the app + - `projects`: setup project (for auth) + default project (depends on setup) + - `outputDir: 'test-results'`, `snapshotDir: 'tests/e2e/snapshots'` + - `timeout: 30000` (30s per test) + - Create `tests/e2e/auth.setup.ts`: + - Navigate to `http://cts-work.test/login` + - Click the "Test Login" button (using `data-testid="login-test-button"`) + - Wait for redirect to Dashboard + - Save `storageState` to `tests/e2e/.auth/user.json` + - Add to `.gitignore`: `tests/e2e/.auth/` + - Add npm script: `"test:e2e": "npx playwright test"` to `package.json` + - Verify setup by running auth setup: `npx playwright test --project=setup` + + **Must NOT do**: + - Do NOT add `webServer` config — Herd serves the app + - Do NOT set `fullyParallel: true` — SQLite limitation + - Do NOT install all browsers — chromium only + - Do NOT use real OAuth for auth setup — use dummy login + + **Recommended Agent Profile**: + - **Category**: `unspecified-high` + - Reason: Multiple files to create, npm install, config needs precision + - **Skills**: [`playwright`] + - `playwright`: Playwright skill has config patterns and auth setup knowledge + + **Parallelization**: + - **Can Run In Parallel**: YES (with T4) + - **Parallel Group**: Wave 2 (with Task 4) + - **Blocks**: Tasks 6-19 (all E2E tests depend on Playwright infra) + - **Blocked By**: Tasks 1, 2, 3 (needs Herd URL, dummy login route, factory) + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/package.json` — Current npm scripts and dependencies. Add `@playwright/test` to devDependencies and `test:e2e` script. + - `/Users/thorsten/AI/cts-work/.gitignore` — Add `tests/e2e/.auth/` to prevent committing auth state files. + + **API/Type References**: + - Playwright `defineConfig`: https://playwright.dev/docs/test-configuration + - Playwright auth setup: https://playwright.dev/docs/auth + + **External References**: + - Playwright docs: https://playwright.dev/docs/intro — Installation and project setup + - Playwright storageState: https://playwright.dev/docs/auth#basic-shared-account-in-all-tests — Pattern for reusing login state + + **WHY Each Reference Matters**: + - `package.json`: Must add devDependency and script correctly + - Playwright auth docs: storageState pattern saves login state so every test doesn't re-login + - `workers: 1` is critical for SQLite — parallel workers cause SQLITE_BUSY + + **Acceptance Criteria**: + - [ ] `@playwright/test` in devDependencies + - [ ] `playwright.config.ts` exists with `baseURL`, `workers: 1`, no `webServer` + - [ ] `tests/e2e/auth.setup.ts` exists and performs dummy login + - [ ] `npx playwright test --project=setup` passes (auth state saved) + - [ ] `tests/e2e/.auth/user.json` exists after setup runs + + **QA Scenarios:** + + ``` + Scenario: Playwright auth setup logs in via dummy login + Tool: Bash + Preconditions: Playwright installed, Herd running, dummy login route exists + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test --project=setup + 2. Assert exit code 0 + 3. ls tests/e2e/.auth/user.json + 4. Assert file exists and is non-empty + Expected Result: Auth setup passes, storageState file created + Failure Indicators: Setup fails (dummy login not working), file missing + Evidence: .sisyphus/evidence/task-5-playwright-setup.txt + + Scenario: Playwright config has correct settings + Tool: Bash (grep) + Preconditions: playwright.config.ts created + Steps: + 1. grep 'cts-work.test' playwright.config.ts + 2. grep 'workers.*1' playwright.config.ts + 3. grep -c 'webServer' playwright.config.ts (should be 0) + Expected Result: baseURL correct, workers=1, no webServer + Evidence: .sisyphus/evidence/task-5-config-check.txt + ``` + + **Commit**: YES (group with Wave 2) + - Message: `test(e2e): add Playwright infrastructure with auth setup` + - Files: `playwright.config.ts`, `tests/e2e/auth.setup.ts`, `package.json`, `.gitignore` + - Pre-commit: `npx playwright test --project=setup` → PASS + +--- + +### Wave 3 — E2E Tests (Core Features) + +- [x] 6. E2E — Auth Tests + + **What to do**: + - Create `tests/e2e/auth.spec.ts` with these tests: + - Test: Login page displays correctly (German text, OAuth button visible, Test Login button visible in local) + - Test: Dummy test login works (click Test Login → redirect to Dashboard → user name visible in nav) + - Test: Logout works (click user dropdown → click Abmelden → redirect to login page) + - Test: Protected routes redirect to login when unauthenticated (visit /services without auth → redirect to /login) + - Test: OAuth button links to correct ChurchTools URL + - ALL tests use `data-testid` selectors (from Task 4) + - Use `storageState` from auth setup for authenticated tests + - For unauthenticated test: create a separate test that does NOT use storageState + + **Must NOT do**: + - Do NOT actually complete an OAuth flow in tests (would require real credentials + browser interaction with external site) + - Do NOT assert specific user names from CTS (use structural assertions) + + **Recommended Agent Profile**: + - **Category**: `quick` + - Reason: Single spec file, ~5 test cases, straightforward Playwright patterns + - **Skills**: [`playwright`] + - `playwright`: Needed for Playwright test authoring patterns + + **Parallelization**: + - **Can Run In Parallel**: YES (with T7-T13) + - **Parallel Group**: Wave 3 (with Tasks 7-13) + - **Blocks**: Task 20 (full suite run) + - **Blocked By**: Tasks 4, 5 (data-testid + Playwright infra) + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Pages/Auth/Login.vue` — Login page structure. After T2: has OAuth button + Test Login button. Check `data-testid` names from T4. + - `/Users/thorsten/AI/cts-work/resources/js/Layouts/AuthenticatedLayout.vue` — Nav layout with user dropdown and logout button. Verify `data-testid` for user name, dropdown, logout. + - `/Users/thorsten/AI/cts-work/routes/web.php` — Route definitions. `/login` is guest-only, `/services` requires auth. After T2: `/dev-login` route exists. + - `/Users/thorsten/AI/cts-work/tests/e2e/auth.setup.ts` — Auth setup pattern (created in T5). Follow same Playwright conventions. + + **WHY Each Reference Matters**: + - Login.vue: Need exact `data-testid` values for the OAuth and Test Login buttons + - AuthenticatedLayout: Test logout flow using nav dropdown testids + - Routes: Know which routes require auth for redirect testing + + **Acceptance Criteria**: + - [ ] `tests/e2e/auth.spec.ts` exists with ≥ 4 tests + - [ ] `npx playwright test auth.spec.ts` → all pass + + **QA Scenarios:** + + ``` + Scenario: Auth E2E tests all pass + Tool: Bash + Preconditions: Playwright installed, auth setup complete, Herd running + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test auth.spec.ts + 2. Assert exit code 0 + 3. Assert output shows all tests passed (0 failed) + Expected Result: All auth tests pass + Failure Indicators: Test failures, timeout errors, missing selectors + Evidence: .sisyphus/evidence/task-6-auth-tests.txt + ``` + + **Commit**: YES (group with Wave 3) + - Message: `test(e2e): add auth E2E tests` + - Files: `tests/e2e/auth.spec.ts` + +--- + +- [x] 7. E2E — Dashboard + Navigation Tests + + **What to do**: + - Create `tests/e2e/navigation.spec.ts` with these tests: + - Test: Dashboard page renders after login (heading visible, German text) + - Test: Top navigation shows correct links ("Gottesdienste", "Song-Datenbank") + - Test: Top navigation shows logged-in user name + - Test: Sync button visible in top bar with timestamp + - Test: Clicking "Gottesdienste" navigates to services list + - Test: Clicking "Song-Datenbank" navigates to songs list + - All assertions must use German text + + **Must NOT do**: + - Do NOT test sync functionality here (that's Task 19) + - Do NOT assert specific data content (only structural elements) + + **Recommended Agent Profile**: + - **Category**: `quick` + - Reason: Single spec file, straightforward navigation tests + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T6, T8-T13) + - **Parallel Group**: Wave 3 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Layouts/AuthenticatedLayout.vue` — Main navigation structure. Contains nav links (Gottesdienste, Song-Datenbank), user dropdown, sync button + timestamp. + - `/Users/thorsten/AI/cts-work/resources/js/Pages/Dashboard.vue` — Dashboard page content. + + **WHY Each Reference Matters**: + - AuthenticatedLayout: All navigation elements live here — need exact `data-testid` values + - Dashboard: Know what heading/content to assert after login + + **Acceptance Criteria**: + - [ ] `tests/e2e/navigation.spec.ts` exists with ≥ 4 tests + - [ ] `npx playwright test navigation.spec.ts` → all pass + + **QA Scenarios:** + + ``` + Scenario: Navigation E2E tests all pass + Tool: Bash + Preconditions: Playwright setup complete, storageState available + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test navigation.spec.ts + 2. Assert exit code 0 + Expected Result: All navigation tests pass + Evidence: .sisyphus/evidence/task-7-navigation-tests.txt + ``` + + **Commit**: YES (group with Wave 3) + - Message: `test(e2e): add dashboard and navigation E2E tests` + - Files: `tests/e2e/navigation.spec.ts` + +--- + +- [x] 8. E2E — Service List Tests + + **What to do**: + - Create `tests/e2e/service-list.spec.ts` with these tests: + - Test: Services page renders with heading "Gottesdienste" + - Test: Service list shows at least one service (from CTS sync) — assert table/card structure exists, do NOT assert specific service names + - Test: Each service row shows: title, date, status indicators (song count, slides count, finalized status) + - Test: Unfinalized service shows "Bearbeiten" and "Abschließen" buttons + - Test: Finalized service shows "Wiederöffnen" and "Herunterladen" buttons + - Test: Status indicators show structural format "x/y" for songs + - CRITICAL: Tests must NOT assert specific service titles, dates, or counts from CTS — only structural patterns + - If no services exist (CTS sync not run), test should handle empty state gracefully + + **Must NOT do**: + - Do NOT assert specific service titles or dates (CTS data is live and changes) + - Do NOT click Edit/Finalize buttons (those are separate tests) + - Do NOT trigger CTS sync in this test + + **Recommended Agent Profile**: + - **Category**: `quick` + - Reason: Single spec file, structural assertions + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T6-T7, T9-T13) + - **Parallel Group**: Wave 3 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Pages/Services/Index.vue` — Service list page. Contains service table/cards with status indicators, action buttons (Edit, Finalize, ReOpen, Download). + - `/Users/thorsten/AI/cts-work/app/Http/Controllers/ServiceController.php` — `index()` method shows what data is passed to the view (services with relationships). + + **WHY Each Reference Matters**: + - Services/Index.vue: Need exact `data-testid` values for service rows, buttons, status indicators + - ServiceController: Understand data shape to know what structural elements to assert + + **Acceptance Criteria**: + - [ ] `tests/e2e/service-list.spec.ts` exists with ≥ 4 tests + - [ ] `npx playwright test service-list.spec.ts` → all pass + - [ ] Tests do NOT contain hardcoded CTS data values + + **QA Scenarios:** + + ``` + Scenario: Service list E2E tests all pass + Tool: Bash + Preconditions: CTS sync has been run at least once, services exist in DB + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test service-list.spec.ts + 2. Assert exit code 0 + Expected Result: All service list tests pass + Evidence: .sisyphus/evidence/task-8-service-list-tests.txt + ``` + + **Commit**: YES (group with Wave 3) + - Message: `test(e2e): add service list E2E tests` + - Files: `tests/e2e/service-list.spec.ts` + +--- + +- [x] 9. E2E — Service Edit: Information Block + + **What to do**: + - Create `tests/e2e/service-edit-information.spec.ts` with these tests: + - Test: Navigate to first editable (non-finalized) service edit page + - Test: Information block accordion is visible and can be expanded/collapsed + - Test: Upload area is visible with drag-and-drop zone and click-to-upload + - Test: Existing slides show as thumbnails with expire date fields + - Test: Datepicker for expire date is functional (can select a date) + - Test: Delete button on slide thumbnail triggers confirmation and soft-deletes + - Must find a non-finalized service dynamically (do NOT hardcode service IDs) + - If no editable service exists, skip test gracefully with `test.skip()` + + **Must NOT do**: + - Do NOT upload real files in test (file conversion depends on system tools) + - Do NOT assert specific slide content (dynamic CTS data) + - Do NOT modify finalization status + + **Recommended Agent Profile**: + - **Category**: `quick` + - Reason: Single spec file, standard Playwright interactions + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T6-T8, T10-T13) + - **Parallel Group**: Wave 3 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Pages/Services/Edit.vue` — Edit page with 4-block accordion. Information block is first. + - `/Users/thorsten/AI/cts-work/resources/js/Components/Blocks/InformationBlock.vue` — Information block component with SlideUploader + SlideGrid. + - `/Users/thorsten/AI/cts-work/resources/js/Components/SlideUploader.vue` — Upload area with drop zone. + - `/Users/thorsten/AI/cts-work/resources/js/Components/SlideGrid.vue` — Thumbnail grid with delete + datepicker. + + **WHY Each Reference Matters**: + - Edit.vue: Accordion structure determines how to expand/collapse blocks + - InformationBlock: Contains the upload area + grid — need testids for each interactive element + - SlideUploader/SlideGrid: Specific interactive elements (drop zone, thumbnails, delete, datepicker) + + **Acceptance Criteria**: + - [ ] `tests/e2e/service-edit-information.spec.ts` exists with ≥ 3 tests + - [ ] `npx playwright test service-edit-information.spec.ts` → all pass + + **QA Scenarios:** + + ``` + Scenario: Information block E2E tests pass + Tool: Bash + Preconditions: At least one non-finalized service exists + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test service-edit-information.spec.ts + 2. Assert exit code 0 + Expected Result: All information block tests pass + Evidence: .sisyphus/evidence/task-9-info-block-tests.txt + ``` + + **Commit**: YES (group with Wave 3) + - Message: `test(e2e): add service edit information block E2E tests` + - Files: `tests/e2e/service-edit-information.spec.ts` + +--- + +- [x] 10. E2E — Service Edit: Moderation Block + + **What to do**: + - Create `tests/e2e/service-edit-moderation.spec.ts` with these tests: + - Test: Moderation block accordion can be expanded + - Test: Upload area visible (same as Information but WITHOUT datepicker) + - Test: Existing moderation slides show as thumbnails + - Test: Delete button works on moderation slides + - Same dynamic service finding as Task 9 + + **Must NOT do**: + - Do NOT upload real files + - Do NOT test datepicker (Moderation block doesn't have one — unlike Information) + + **Recommended Agent Profile**: + - **Category**: `quick` + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T6-T9, T11-T13) + - **Parallel Group**: Wave 3 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Components/Blocks/ModerationBlock.vue` — Moderation block (same as Information but no datepicker). + - `/Users/thorsten/AI/cts-work/resources/js/Pages/Services/Edit.vue` — Accordion structure (Moderation is second block). + + **Acceptance Criteria**: + - [ ] `tests/e2e/service-edit-moderation.spec.ts` exists with ≥ 3 tests + - [ ] `npx playwright test service-edit-moderation.spec.ts` → all pass + + **QA Scenarios:** + + ``` + Scenario: Moderation block E2E tests pass + Tool: Bash + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test service-edit-moderation.spec.ts + 2. Assert exit code 0 + Expected Result: All moderation block tests pass + Evidence: .sisyphus/evidence/task-10-moderation-tests.txt + ``` + + **Commit**: YES (group with Wave 3) + - Message: `test(e2e): add service edit moderation block E2E tests` + - Files: `tests/e2e/service-edit-moderation.spec.ts` + +- [x] 11. E2E — Service Edit: Sermon Block + + **What to do**: + - Create `tests/e2e/service-edit-sermon.spec.ts` with these tests: + - Test: Sermon block accordion can be expanded + - Test: Upload area visible (same as Moderation — no datepicker) + - Test: Existing sermon slides show as thumbnails + - Test: Delete button works on sermon slides + - Same dynamic service finding as Task 9 + + **Must NOT do**: + - Do NOT upload real files + - Do NOT test datepicker (Sermon block doesn't have one) + + **Recommended Agent Profile**: + - **Category**: `quick` + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T6-T10, T12-T13) + - **Parallel Group**: Wave 3 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Components/Blocks/SermonBlock.vue` — Sermon block (same features as Moderation). + - `/Users/thorsten/AI/cts-work/resources/js/Pages/Services/Edit.vue` — Accordion structure (Sermon is third block). + + **Acceptance Criteria**: + - [ ] `tests/e2e/service-edit-sermon.spec.ts` exists with ≥ 3 tests + - [ ] `npx playwright test service-edit-sermon.spec.ts` → all pass + + **QA Scenarios:** + + ``` + Scenario: Sermon block E2E tests pass + Tool: Bash + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test service-edit-sermon.spec.ts + 2. Assert exit code 0 + Expected Result: All sermon block tests pass + Evidence: .sisyphus/evidence/task-11-sermon-tests.txt + ``` + + **Commit**: YES (group with Wave 3) + - Message: `test(e2e): add service edit sermon block E2E tests` + - Files: `tests/e2e/service-edit-sermon.spec.ts` + +--- + +- [x] 12. E2E — Service Edit: Songs Block + + **What to do**: + - Create `tests/e2e/service-edit-songs.spec.ts` with these tests: + - Test: Songs block accordion can be expanded + - Test: Song list shows songs in correct order (if service has songs from CTS) + - Test: Each song row shows: name, CCLI ID, arrangement selector, translation checkbox (if applicable) + - Test: Unmatched songs show "Erstellung anfragen" button and manual assign select + - Test: Matched songs show arrangement dropdown with options + - Test: Arrangement "Hinzufügen" (Add) button opens name prompt + - Test: Arrangement "Klonen" (Clone) button opens name prompt + - Test: Preview button opens song preview modal + - Test: Download (PDF) button is present for songs with selected arrangement + - Test: Translation checkbox toggles (if song has translation) + - CRITICAL: This is the most complex block — many interactive elements + - Do NOT assert specific song names from CTS — use structural assertions + - If no songs exist on any service, skip gracefully + + **Must NOT do**: + - Do NOT create/delete arrangements in this test (arrangement config is Task 17) + - Do NOT test the preview modal content (that's Task 18) + - Do NOT trigger email sending for missing songs + + **Recommended Agent Profile**: + - **Category**: `unspecified-high` + - Reason: Complex block with many interactive elements, needs thoroughness + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T6-T11, T13) + - **Parallel Group**: Wave 3 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Components/Blocks/SongsBlock.vue` — Songs block component. Contains song rows with arrangement selectors, action buttons (preview, download, assign, request creation), translation checkboxes. + - `/Users/thorsten/AI/cts-work/resources/js/Components/ArrangementConfigurator.vue` — Arrangement config component embedded in songs block. + - `/Users/thorsten/AI/cts-work/resources/js/Components/SongPreviewModal.vue` — Preview modal (verify it opens, don't test content deeply). + - `/Users/thorsten/AI/cts-work/resources/js/Pages/Services/Edit.vue` — Songs is the fourth block in the accordion. + + **WHY Each Reference Matters**: + - SongsBlock: Core component with most interactive elements in the app — needs comprehensive testids + - ArrangementConfigurator: Embedded within songs — verify add/clone buttons open prompts + - SongPreviewModal: Verify it opens on button click (detailed content testing in T18) + + **Acceptance Criteria**: + - [ ] `tests/e2e/service-edit-songs.spec.ts` exists with ≥ 6 tests + - [ ] `npx playwright test service-edit-songs.spec.ts` → all pass + - [ ] Tests do NOT contain hardcoded song names or CTS data + + **QA Scenarios:** + + ``` + Scenario: Songs block E2E tests pass + Tool: Bash + Preconditions: At least one service with songs exists from CTS sync + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test service-edit-songs.spec.ts + 2. Assert exit code 0 + Expected Result: All songs block tests pass + Evidence: .sisyphus/evidence/task-12-songs-block-tests.txt + ``` + + **Commit**: YES (group with Wave 3) + - Message: `test(e2e): add service edit songs block E2E tests` + - Files: `tests/e2e/service-edit-songs.spec.ts` + +--- + +- [x] 13. E2E — Service Finalization Tests + + **What to do**: + - Create `tests/e2e/service-finalization.spec.ts` with these tests: + - Test: Click "Abschließen" on an unfinalized service → shows confirmation/warning dialog → confirm → service becomes finalized + - Test: Finalized service shows "Wiederöffnen" and "Herunterladen" buttons ("Bearbeiten" and "Abschließen" hidden) + - Test: Click "Wiederöffnen" on finalized service → service returns to editable state + - Test: Click "Herunterladen" on finalized service → download response (assert non-error HTTP response) + - IMPORTANT: These tests MODIFY state. Run them in order. The test should reopen the service at the end to restore state. + - Find a service dynamically, do NOT hardcode service IDs + + **Must NOT do**: + - Do NOT leave services in finalized state after tests (restore original state) + - Do NOT assert specific file contents of download (just verify it's a valid response) + + **Recommended Agent Profile**: + - **Category**: `quick` + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T6-T12) — BUT be careful: this test modifies service state, so it must not conflict with T9-T12 which read service state. Best to run after T8-T12 if possible, or use a different service. + - **Parallel Group**: Wave 3 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Pages/Services/Index.vue` — Service list with Finalize/ReOpen/Download buttons. + - `/Users/thorsten/AI/cts-work/app/Http/Controllers/ServiceController.php` — `finalize()`, `reopen()`, `download()` methods. + - `/Users/thorsten/AI/cts-work/resources/js/Components/ConfirmDialog.vue` — Confirmation dialog component. + + **WHY Each Reference Matters**: + - Services/Index: Button visibility logic (finalized vs not) and testid targets + - ServiceController: Understand what finalize/reopen actually does to know what to assert + - ConfirmDialog: Need testid for confirm/cancel buttons + + **Acceptance Criteria**: + - [ ] `tests/e2e/service-finalization.spec.ts` exists with ≥ 3 tests + - [ ] `npx playwright test service-finalization.spec.ts` → all pass + - [ ] Tests restore service state (reopen after finalize) + + **QA Scenarios:** + + ``` + Scenario: Finalization E2E tests pass + Tool: Bash + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test service-finalization.spec.ts + 2. Assert exit code 0 + Expected Result: All finalization tests pass, service state restored + Evidence: .sisyphus/evidence/task-13-finalization-tests.txt + ``` + + **Commit**: YES (group with Wave 3) + - Message: `test(e2e): add service finalization E2E tests` + - Files: `tests/e2e/service-finalization.spec.ts` + +--- + +### Wave 4 — E2E Tests (Song DB + Advanced Features) + +- [x] 14. E2E — Song DB List + Search + + **What to do**: + - Create `tests/e2e/song-db.spec.ts` with these tests: + - Test: Song-Datenbank page renders with heading + - Test: Song list shows songs in a table/grid (if any exist) + - Test: Each song row shows: name, CCLI ID, created date, last used date + - Test: Search input filters songs (type a query, verify list updates) + - Test: Pagination works (if enough songs exist) + - Test: Delete button triggers confirmation dialog (cancel → song still visible) + - Test: Edit button opens SongEditModal + - Test: Download button triggers download (assert non-error response) + - Test: Translate button navigates to translate page + - Do NOT assert specific song names — use structural assertions + + **Must NOT do**: + - Do NOT actually delete songs (cancel the confirmation) + - Do NOT test edit modal content (that's Task 15) + - Do NOT test translate page (that's Task 16) + + **Recommended Agent Profile**: + - **Category**: `quick` + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T15-T19) + - **Parallel Group**: Wave 4 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Pages/Songs/Index.vue` — Song DB list page with search, pagination, action buttons (Edit, Delete, Download, Translate). + - `/Users/thorsten/AI/cts-work/app/Http/Controllers/SongController.php` — Song CRUD controller. + + **Acceptance Criteria**: + - [ ] `tests/e2e/song-db.spec.ts` exists with ≥ 5 tests + - [ ] `npx playwright test song-db.spec.ts` → all pass + + **QA Scenarios:** + + ``` + Scenario: Song DB E2E tests pass + Tool: Bash + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test song-db.spec.ts + 2. Assert exit code 0 + Expected Result: All song DB tests pass + Evidence: .sisyphus/evidence/task-14-song-db-tests.txt + ``` + + **Commit**: YES (group with Wave 4) + - Message: `test(e2e): add song database list and search E2E tests` + - Files: `tests/e2e/song-db.spec.ts` + +--- + +- [x] 15. E2E — Song Edit Modal + + **What to do**: + - Create `tests/e2e/song-edit-modal.spec.ts` with these tests: + - Test: Click Edit button on a song → modal opens + - Test: Modal shows song name, CCLI ID, copyright text fields + - Test: Fields are auto-saved on change (debounced) — verify no explicit save button + - Test: Arrangement configurator is embedded in modal + - Test: Close modal (X button or overlay click) + - Navigate to Songs/Index first, then open modal on first available song + + **Must NOT do**: + - Do NOT modify song data permanently (or restore if modified) + - Do NOT test arrangement drag-and-drop (that's Task 17) + + **Recommended Agent Profile**: + - **Category**: `quick` + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T14, T16-T19) + - **Parallel Group**: Wave 4 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Components/SongEditModal.vue` — Edit modal with name/CCLI/copyright inputs and arrangement configurator. + - `/Users/thorsten/AI/cts-work/resources/js/Pages/Songs/Index.vue` — Parent page where Edit button triggers modal. + + **Acceptance Criteria**: + - [ ] `tests/e2e/song-edit-modal.spec.ts` exists with ≥ 3 tests + - [ ] `npx playwright test song-edit-modal.spec.ts` → all pass + + **QA Scenarios:** + + ``` + Scenario: Song edit modal E2E tests pass + Tool: Bash + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test song-edit-modal.spec.ts + 2. Assert exit code 0 + Expected Result: All song edit modal tests pass + Evidence: .sisyphus/evidence/task-15-song-edit-modal-tests.txt + ``` + + **Commit**: YES (group with Wave 4) + - Message: `test(e2e): add song edit modal E2E tests` + - Files: `tests/e2e/song-edit-modal.spec.ts` + +--- + +- [x] 16. E2E — Song Translation Page + + **What to do**: + - Create `tests/e2e/song-translate.spec.ts` with these tests: + - Test: Navigate to translate page for a song (from Song DB → click Translate) + - Test: Page shows two-column editor layout (original left, translation right) + - Test: URL input field visible with "Abrufen" (Fetch) button + - Test: Group/slide navigation works (can switch between groups) + - Test: Text editor on right column is editable + - Test: Save button persists changes + - Find a song with groups/slides dynamically + - If no song has groups, skip test gracefully + + **Must NOT do**: + - Do NOT fetch from external URLs in tests (network dependency) + - Do NOT permanently modify translation data (or restore after test) + + **Recommended Agent Profile**: + - **Category**: `quick` + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T14-T15, T17-T19) + - **Parallel Group**: Wave 4 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Pages/Songs/Translate.vue` — Two-column translation editor with URL fetch, group/slide navigation. + - `/Users/thorsten/AI/cts-work/app/Http/Controllers/TranslationController.php` — Translation controller with `page()`, `import()`, `fetchUrl()` methods. + + **Acceptance Criteria**: + - [ ] `tests/e2e/song-translate.spec.ts` exists with ≥ 3 tests + - [ ] `npx playwright test song-translate.spec.ts` → all pass + + **QA Scenarios:** + + ``` + Scenario: Song translation E2E tests pass + Tool: Bash + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test song-translate.spec.ts + 2. Assert exit code 0 + Expected Result: All translation tests pass + Evidence: .sisyphus/evidence/task-16-translate-tests.txt + ``` + + **Commit**: YES (group with Wave 4) + - Message: `test(e2e): add song translation page E2E tests` + - Files: `tests/e2e/song-translate.spec.ts` + +--- + +- [ ] 17. E2E — Arrangement Configurator + + **What to do**: + - Create `tests/e2e/arrangement.spec.ts` with these tests: + - Test: Arrangement configurator shows groups in correct order + - Test: "Hinzufügen" (Add) button creates new arrangement — prompt for name, confirm, new arrangement appears in select + - Test: "Klonen" (Clone) button duplicates arrangement — prompt for name, confirm, new arrangement appears + - Test: Group items can be reordered via drag-and-drop (drag group down, verify order changes) + - Test: Group can be added to arrangement (if available groups exist) + - Test: Group can be removed from arrangement + - Test: Delete arrangement button triggers confirmation + - Access via: Song DB → Edit button (modal) → Arrangement Configurator + - OR via: Service Edit → Songs Block → Song with arrangement + - IMPORTANT: Create test arrangements, then delete them to restore state + + **Must NOT do**: + - Do NOT delete the "Normal" default arrangement + - Do NOT leave test-created arrangements in the DB (clean up after test) + + **Recommended Agent Profile**: + - **Category**: `unspecified-high` + - Reason: Complex interactions (drag-and-drop, prompts, create/delete lifecycle) + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T14-T16, T18-T19) + - **Parallel Group**: Wave 4 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Components/ArrangementConfigurator.vue` — Drag-and-drop group configurator with add/clone/delete functionality. + - `/Users/thorsten/AI/cts-work/app/Http/Controllers/ArrangementController.php` — CRUD operations for arrangements (store, clone, update, destroy). + - `/Users/thorsten/AI/cts-work/resources/js/Components/SongEditModal.vue` — Modal that embeds the ArrangementConfigurator. + + **WHY Each Reference Matters**: + - ArrangementConfigurator: Core component — need testids for drag handles, group items, add/remove buttons + - ArrangementController: Understand API shape for create/clone/delete assertions + - SongEditModal: Entry point to reach the configurator + + **Acceptance Criteria**: + - [ ] `tests/e2e/arrangement.spec.ts` exists with ≥ 4 tests + - [ ] `npx playwright test arrangement.spec.ts` → all pass + - [ ] No leftover test arrangements in DB after test run + + **QA Scenarios:** + + ``` + Scenario: Arrangement configurator E2E tests pass + Tool: Bash + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test arrangement.spec.ts + 2. Assert exit code 0 + Expected Result: All arrangement tests pass, no leftover test data + Evidence: .sisyphus/evidence/task-17-arrangement-tests.txt + ``` + + **Commit**: YES (group with Wave 4) + - Message: `test(e2e): add arrangement configurator E2E tests` + - Files: `tests/e2e/arrangement.spec.ts` + +- [x] 18. E2E — Song Preview + PDF Download + + **What to do**: + - Create `tests/e2e/song-preview-pdf.spec.ts` with these tests: + - Test: Click Preview button on a matched song → SongPreviewModal opens + - Test: Modal shows song text organized by groups with highlighted group labels + - Test: Each group shows its slides in correct order + - Test: Close modal (X button or ESC key) + - Test: Click Download/PDF button → triggers PDF download (assert response has PDF content-type) + - Access via: Service Edit → Songs Block → Preview/Download buttons on a matched song + - If no matched songs exist, skip gracefully + + **Must NOT do**: + - Do NOT assert specific song text content (dynamic data) + - Do NOT validate PDF content structure (just verify it's a PDF response) + + **Recommended Agent Profile**: + - **Category**: `quick` + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T14-T17, T19) + - **Parallel Group**: Wave 4 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Components/SongPreviewModal.vue` — Preview modal showing song text by arrangement groups. + - `/Users/thorsten/AI/cts-work/app/Http/Controllers/SongPdfController.php` — PDF generation + preview JSON endpoints. + + **Acceptance Criteria**: + - [ ] `tests/e2e/song-preview-pdf.spec.ts` exists with ≥ 3 tests + - [ ] `npx playwright test song-preview-pdf.spec.ts` → all pass + + **QA Scenarios:** + + ``` + Scenario: Song preview and PDF E2E tests pass + Tool: Bash + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test song-preview-pdf.spec.ts + 2. Assert exit code 0 + Expected Result: All preview/PDF tests pass + Evidence: .sisyphus/evidence/task-18-preview-pdf-tests.txt + ``` + + **Commit**: YES (group with Wave 4) + - Message: `test(e2e): add song preview and PDF download E2E tests` + - Files: `tests/e2e/song-preview-pdf.spec.ts` + +--- + +- [x] 19. E2E — Sync + .pro Placeholders + + **What to do**: + - Create `tests/e2e/sync-and-pro.spec.ts` with these tests: + - Test: Sync button visible in top navigation bar + - Test: Click sync button → loading indicator appears → sync completes → timestamp updates + - Test: After sync, services list has data (at least one service from CTS) + - Test: .pro file upload (Song DB upload area) → shows 501 / "Noch nicht verfügbar" error + - Test: .pro file download button → shows 501 / "Noch nicht verfügbar" error + - CRITICAL: Sync test hits the LIVE CTS API — this is READ-ONLY, verify no writes + - .pro tests verify the placeholder behavior (501 status) + + **Must NOT do**: + - Do NOT modify any CTS data (sync is READ-ONLY) + - Do NOT implement .pro parsing (verify it's still 501) + + **Recommended Agent Profile**: + - **Category**: `quick` + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: YES (with T14-T18) + - **Parallel Group**: Wave 4 + - **Blocks**: Task 20 + - **Blocked By**: Tasks 4, 5 + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/resources/js/Layouts/AuthenticatedLayout.vue` — Sync button + timestamp in top nav. + - `/Users/thorsten/AI/cts-work/app/Http/Controllers/SyncController.php` — Sync controller that calls ChurchToolsService. + - `/Users/thorsten/AI/cts-work/app/Http/Controllers/ProFileController.php` — .pro placeholder endpoints returning 501. + + **WHY Each Reference Matters**: + - AuthenticatedLayout: Sync button testid and timestamp element + - SyncController: Verify it's read-only (no POST/PUT/DELETE to CTS API) + - ProFileController: Verify 501 responses for upload/download + + **Acceptance Criteria**: + - [ ] `tests/e2e/sync-and-pro.spec.ts` exists with ≥ 4 tests + - [ ] `npx playwright test sync-and-pro.spec.ts` → all pass + - [ ] Tests verify .pro endpoints return 501 + + **QA Scenarios:** + + ``` + Scenario: Sync and .pro placeholder E2E tests pass + Tool: Bash + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test sync-and-pro.spec.ts + 2. Assert exit code 0 + Expected Result: All sync/.pro tests pass + Evidence: .sisyphus/evidence/task-19-sync-pro-tests.txt + ``` + + **Commit**: YES (group with Wave 4) + - Message: `test(e2e): add sync and .pro placeholder E2E tests` + - Files: `tests/e2e/sync-and-pro.spec.ts` + +--- + +- [x] 20. E2E — Full Test Suite Run + Fix Failures + + **What to do**: + - Run the ENTIRE Playwright test suite: `npx playwright test` + - Fix ALL failures — this is the integration task that catches cross-test issues + - Common issues to fix: + - Flaky tests due to timing (add `waitFor` / `toBeVisible` assertions) + - SQLite BUSY errors (verify `workers: 1` in config) + - State contamination between tests (ensure proper setup/teardown) + - Missing `data-testid` attributes (go back and add them) + - Auth state expired (verify storageState is refreshed) + - Also verify existing Pest tests still pass: `php artisan test` + - Run `npm run build` to verify Vite build still works + - Document final test count and pass rate + + **Must NOT do**: + - Do NOT skip failing tests with `.skip` — fix them + - Do NOT modify existing Pest tests + - Do NOT change app logic to make tests pass (fix tests, not app) + + **Recommended Agent Profile**: + - **Category**: `deep` + - Reason: Debugging test failures requires deep investigation, multiple iterations + - **Skills**: [`playwright`] + + **Parallelization**: + - **Can Run In Parallel**: NO (must run after all E2E test tasks) + - **Parallel Group**: Sequential (after T6-T19) + - **Blocks**: F1-F4 (Final Verification) + - **Blocked By**: Tasks 6-19 (all E2E test files must exist) + + **References**: + + **Pattern References**: + - `/Users/thorsten/AI/cts-work/playwright.config.ts` — Playwright config (created in T5). Verify workers=1, baseURL correct. + - `/Users/thorsten/AI/cts-work/tests/e2e/` — All E2E test files created in T6-T19. + - `/Users/thorsten/AI/cts-work/tests/e2e/auth.setup.ts` — Auth setup (created in T5). + + **WHY Each Reference Matters**: + - Config: Root cause of many failures (wrong URL, parallel workers, timeout) + - All spec files: Need to debug and fix each failing test + - Auth setup: Common failure point if storageState is stale + + **Acceptance Criteria**: + - [ ] `npx playwright test` → ALL tests pass, 0 failures + - [ ] `php artisan test` → 174 tests, 905 assertions, 0 failures + - [ ] `npm run build` → exit code 0 + - [ ] Test count documented in evidence file + + **QA Scenarios:** + + ``` + Scenario: Full Playwright suite passes + Tool: Bash + Steps: + 1. cd /Users/thorsten/AI/cts-work && npx playwright test + 2. Assert exit code 0 + 3. Assert output shows "0 failed" + 4. Record total test count + Expected Result: All E2E tests pass + Evidence: .sisyphus/evidence/task-20-full-suite.txt + + Scenario: Pest tests unchanged and passing + Tool: Bash + Steps: + 1. cd /Users/thorsten/AI/cts-work && php artisan test + 2. Assert "174 passed" + Expected Result: All existing Pest tests pass + Evidence: .sisyphus/evidence/task-20-pest-pass.txt + + Scenario: Vite build succeeds + Tool: Bash + Steps: + 1. cd /Users/thorsten/AI/cts-work && npm run build + 2. Assert exit code 0 + Expected Result: Build completes without errors + Evidence: .sisyphus/evidence/task-20-build.txt + ``` + + **Commit**: YES + - Message: `test(e2e): fix all test failures and verify full suite passes` + - Files: Any modified `.spec.ts` files, `playwright.config.ts` (if adjusted) + - Pre-commit: `npx playwright test && php artisan test` + +--- + +## Final Verification Wave + +> 4 review agents run in PARALLEL. ALL must APPROVE. Rejection → fix → re-run. + +- [x] F1. **Plan Compliance Audit** — `oracle` + Read the plan end-to-end. For each "Must Have": verify implementation exists (read file, curl endpoint, run command). For each "Must NOT Have": search codebase for forbidden patterns — reject with file:line if found. Check evidence files exist in `.sisyphus/evidence/`. Compare deliverables against plan. + Output: `Must Have [N/N] | Must NOT Have [N/N] | Tasks [N/N] | VERDICT: APPROVE/REJECT` + +- [x] F2. **Code Quality Review** — `unspecified-high` + Run `php artisan test` (174 Pest tests still pass). Run `npx playwright test` (all E2E pass). Review all changed files for: TypeScript errors, unused imports, console.log in prod code. Check AI slop: excessive comments, over-abstraction, generic names. Verify `data-testid` naming follows pattern `{component}-{element}`. + Output: `Pest [PASS/FAIL] | Playwright [N pass/N fail] | Files [N clean/N issues] | VERDICT` + +- [x] F3. **Real Manual QA** — `unspecified-high` (+ `playwright` skill) + Start from clean state (clear storageState). Navigate to `http://cts-work.test/login`. Verify dummy "Test Login" button visible. Click it, verify redirect to Dashboard. Navigate through ALL pages: Services list, Service Edit (open one), Song DB, Song Translate page. Verify German text throughout. Take screenshots of each major page. Save to `.sisyphus/evidence/final-qa/`. + Output: `Pages [N/N accessible] | German text [PASS/FAIL] | Screenshots [N captured] | VERDICT` + +- [x] F4. **Scope Fidelity Check** — `deep` + For each task: read "What to do", read actual diff (`git diff` for changed files). Verify 1:1 — everything in spec was built (no missing), nothing beyond spec was built (no creep). Check "Must NOT do" compliance. Detect cross-task contamination. Flag unaccounted changes. Verify NO writes to CTS API in any test file. + Output: `Tasks [N/N compliant] | Contamination [CLEAN/N issues] | CTS Writes [CLEAN/FOUND] | VERDICT` + +--- + +## Commit Strategy + +- **Wave 1**: `feat(auth): add dummy test login for local dev + update env for Herd` — routes/web.php, AuthController.php, Login.vue, UserFactory.php, .env.example +- **Wave 2**: `test(e2e): add data-testid attributes + Playwright infrastructure` — all .vue files, playwright.config.ts, auth.setup.ts, package.json +- **Wave 3**: `test(e2e): add E2E tests for auth, services, and blocks` — tests/e2e/*.spec.ts +- **Wave 4**: `test(e2e): add E2E tests for songs, arrangements, and full suite validation` — tests/e2e/*.spec.ts + +--- + +## Success Criteria + +### Verification Commands +```bash +# App loads via Herd +curl -s -o /dev/null -w "%{http_code}" http://cts-work.test/login # Expected: 200 + +# Dummy login works +curl -s -X POST http://cts-work.test/dev-login -o /dev/null -w "%{http_code}" # Expected: 302 + +# Existing Pest tests still pass +cd /Users/thorsten/AI/cts-work && php artisan test # Expected: 174 tests, 905 assertions, 0 failures + +# Playwright tests pass +cd /Users/thorsten/AI/cts-work && npx playwright test # Expected: all pass, 0 failures + +# Vite build succeeds +cd /Users/thorsten/AI/cts-work && npm run build # Expected: exit 0 +``` + +### Final Checklist +- [ ] All "Must Have" present +- [ ] All "Must NOT Have" absent +- [ ] All Pest tests pass (174/174) +- [ ] All Playwright tests pass +- [ ] Dummy login gated by environment, NOT debug +- [ ] Zero CTS API writes in test code