72 KiB
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-testidattributes to all Vue components, and write comprehensive Playwright E2E tests covering all 15 feature areas.Deliverables:
- App running on
http://cts-work.testvia Laravel Herd- Dummy test login route + button (gated by
APP_ENV=local|testing)data-testidattributes 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 viaAuth::login()(NOTAuth::attempt()due to bcrypt('') issue) - Herd Status: Already linked at
http://cts-work.test, PHP 8.4, Herd 1.17.0 - Live CTS:
.envhasTEST_CTS_USERNAMEandTEST_CTS_PASSWORDfor OAuth testing — STRICTLY READ-ONLY - Test Strategy: Playwright E2E tests (no changes to existing 174 Pest tests)
Research Findings:
- Zero
data-testidattributes in any Vue component — must add before writing tests UserFactoryis missing OAuth fields (churchtools_id,avatar,churchtools_groups,churchtools_roles).envcurrently points tolocalhost:8000— must update for Herdvite.config.jshashmr.host: 'localhost'— usenpm run buildfor Playwright (static assets)passwordfield hashashedcast — dummy login MUST useAuth::login(), notAuth::attempt()- SQLite + parallel writes =
SQLITE_BUSY— Playwright tests must serialize (nofullyParallel)
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'), NOTAPP_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
.envconfigured for Herd (APP_URL=http://cts-work.test)POST /dev-loginroute (local/testing only) inroutes/web.php- "Test Login" button on
Auth/Login.vue(conditional onAPP_ENV=local) - Updated
UserFactorywith all OAuth fields data-testidattributes on all interactive elements in 34 Vue componentsplaywright.config.tspointing tohttp://cts-work.testtests/e2e/auth.setup.tswith 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.testloads the app successfully- Dummy "Test Login" button visible on login page, logs in, redirects to dashboard
npx playwright testruns ALL tests — 0 failures (individual spec files verified)php artisan teststill 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-testidon 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
webServerblock inplaywright.config.ts— Herd serves the app - NO changes to existing 174 Pest tests
- NO
APP_DEBUGgating for dummy login — MUST useapp()->environment() - NO
Auth::attempt()for dummy login — MUST useAuth::login() - NO
fullyParallel: truein 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
-
1. Herd Environment Configuration
What to do:
- Update
.env.example: ChangeAPP_URL=http://localhost:8000toAPP_URL=http://cts-work.test - Update
.env.example: ChangeCHURCHTOOLS_REDIRECT_URItohttp://cts-work.test/auth/churchtools/callback - In worktree
.env(if present), apply same changes - Run
php artisan config:clearto flush cached config - Run
npm run buildto generate fresh static assets inpublic/build/ - Run
php artisan migrateto ensure DB schema is current - Verify
http://cts-work.test/loginloads 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.exampleis the only file that needs editing — update APP_URL and CHURCHTOOLS_REDIRECT_URI to match Herd's URL scheme
Acceptance Criteria:
.env.examplehasAPP_URL=http://cts-work.test.env.examplehasCHURCHTOOLS_REDIRECT_URI=http://cts-work.test/auth/churchtools/callbacknpm run buildexits with code 0php artisan migrateexits 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.txtCommit: 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
- Update
-
2. Dummy Test Login Route + Button
What to do:
- Add route
POST /dev-logininroutes/web.php, gated byapp()->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()NOTAuth::attempt()— thepasswordfield hashashedcast and stores bcrypt('') for OAuth users, soAuth::attempt()would fail - Update
Auth/Login.vue: Accept a propcanDevLogin(boolean, passed from controller). When true, show a secondary button "Test Login" below the OAuth button - Update
AuthController::showLogin()to passcanDevLogin => app()->environment('local', 'testing')as Inertia prop - The "Test Login" button should POST to
/dev-loginusing Inertia'srouter.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_DEBUGto gate the route — MUST useapp()->environment('local', 'testing') - Do NOT use
Auth::attempt()— MUST useAuth::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 passcanDevLoginprop.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). AcceptcanDevLoginprop.
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.phpguest group: Dummy login must be accessible without auth, so it goes in the guest middleware groupAuthController::callback(): Shows the exact User::updateOrCreate pattern and fields — dummy login should match this patternLogin.vue: Small component, add button conditionally based on prop
Acceptance Criteria:
POST /dev-loginroute exists and is gated byapp()->environment('local', 'testing')- Route creates/finds user with email
test@local.devand logs in viaAuth::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.txtCommit: 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
- Add route
-
3. Update UserFactory with OAuth Fields
What to do:
- Update
database/factories/UserFactory.phpto include all OAuth fields indefinition():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
hashedcast 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 onlyname,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).$fillableat line 21-29 lists all fields that must be present.$castsat line 48-53 showschurchtools_groupsandchurchtools_rolesare cast toarray./Users/thorsten/AI/cts-work/app/Http/Controllers/AuthController.php:39-49— OAuth callback shows how these fields are populated in production:churchtools_idfrom$rawUser['id'],avatarfrom$socialiteUser->getAvatar(), groups/roles from$rawUser.
WHY Each Reference Matters:
- Factory must match all
$fillablefields to preventnulldatabase errors in tests $castsfor groups/roles asarraymeans 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 teststill 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.txtCommit: 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
- Update
Wave 2 — Test Infrastructure
-
4. Add
data-testidAttributes to ALL Vue ComponentsWhat to do:
- Add
data-testidattributes 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"
- Example:
- 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 buttonresources/js/Pages/Dashboard.vue— Welcome text, any action elementsresources/js/Pages/Services/Index.vue— Service rows, Edit/Finalize/ReOpen/Download buttons, status indicatorsresources/js/Pages/Services/Edit.vue— Block accordion headers, save indicatorsresources/js/Pages/Songs/Index.vue— Song rows, search input, pagination, Edit/Delete/Download/Translate buttonsresources/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, datepickersresources/js/Components/Blocks/ModerationBlock.vue— Upload area, thumbnail grid, delete buttonsresources/js/Components/Blocks/SermonBlock.vue— Upload area, thumbnail grid, delete buttonsresources/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 nameresources/js/Components/SlideUploader.vue— Drop zone, file input, progress indicatorresources/js/Components/SlideGrid.vue— Thumbnail items, delete buttons, datepicker inputsresources/js/Components/SongEditModal.vue— Modal container, name/CCLI/copyright inputs, close buttonresources/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, logoutresources/js/Layouts/GuestLayout.vue— Logo, containerresources/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-testidif 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
.vuefiles listed above — each needsdata-testidon interactive elements - Standard Playwright
data-testidconvention: 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-testidon all interactive elements - All 4 Block components have
data-testidon all interactive elements - All 5 Feature components have
data-testidon all interactive elements - All 3 Layout components have
data-testidon key navigation elements npm run buildsucceeds (no broken templates)php artisan teststill 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.txtCommit: YES (group with Wave 2)
- Message:
test(e2e): add data-testid attributes to all Vue components - Files: All modified
.vuefiles - Pre-commit:
npm run build && php artisan test
- Add
-
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.tswith:baseURL: 'http://cts-work.test'fullyParallel: false(SQLite BUSY prevention)workers: 1(serialize all tests)testDir: './tests/e2e'use.storageStatepointing to auth state file- NO
webServerblock — 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
storageStatetotests/e2e/.auth/user.json
- Navigate to
- Add to
.gitignore:tests/e2e/.auth/ - Add npm script:
"test:e2e": "npx playwright test"topackage.json - Verify setup by running auth setup:
npx playwright test --project=setup
Must NOT do:
- Do NOT add
webServerconfig — 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/testto devDependencies andtest:e2escript./Users/thorsten/AI/cts-work/.gitignore— Addtests/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: 1is critical for SQLite — parallel workers cause SQLITE_BUSY
Acceptance Criteria:
@playwright/testin devDependenciesplaywright.config.tsexists withbaseURL,workers: 1, nowebServertests/e2e/auth.setup.tsexists and performs dummy loginnpx playwright test --project=setuppasses (auth state saved)tests/e2e/.auth/user.jsonexists 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.txtCommit: 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
- Install Playwright:
Wave 3 — E2E Tests (Core Features)
-
6. E2E — Auth Tests
What to do:
- Create
tests/e2e/auth.spec.tswith 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-testidselectors (from Task 4) - Use
storageStatefrom 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. Checkdata-testidnames from T4./Users/thorsten/AI/cts-work/resources/js/Layouts/AuthenticatedLayout.vue— Nav layout with user dropdown and logout button. Verifydata-testidfor user name, dropdown, logout./Users/thorsten/AI/cts-work/routes/web.php— Route definitions./loginis guest-only,/servicesrequires auth. After T2:/dev-loginroute 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-testidvalues 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.tsexists with ≥ 4 testsnpx 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.txtCommit: YES (group with Wave 3)
- Message:
test(e2e): add auth E2E tests - Files:
tests/e2e/auth.spec.ts
- Create
-
7. E2E — Dashboard + Navigation Tests
What to do:
- Create
tests/e2e/navigation.spec.tswith 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-testidvalues - Dashboard: Know what heading/content to assert after login
Acceptance Criteria:
tests/e2e/navigation.spec.tsexists with ≥ 4 testsnpx 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.txtCommit: YES (group with Wave 3)
- Message:
test(e2e): add dashboard and navigation E2E tests - Files:
tests/e2e/navigation.spec.ts
- Create
-
8. E2E — Service List Tests
What to do:
- Create
tests/e2e/service-list.spec.tswith 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-testidvalues for service rows, buttons, status indicators - ServiceController: Understand data shape to know what structural elements to assert
Acceptance Criteria:
tests/e2e/service-list.spec.tsexists with ≥ 4 testsnpx 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.txtCommit: YES (group with Wave 3)
- Message:
test(e2e): add service list E2E tests - Files:
tests/e2e/service-list.spec.ts
- Create
-
9. E2E — Service Edit: Information Block
What to do:
- Create
tests/e2e/service-edit-information.spec.tswith 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.tsexists with ≥ 3 testsnpx 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.txtCommit: YES (group with Wave 3)
- Message:
test(e2e): add service edit information block E2E tests - Files:
tests/e2e/service-edit-information.spec.ts
- Create
-
10. E2E — Service Edit: Moderation Block
What to do:
- Create
tests/e2e/service-edit-moderation.spec.tswith 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.tsexists with ≥ 3 testsnpx 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.txtCommit: YES (group with Wave 3)
- Message:
test(e2e): add service edit moderation block E2E tests - Files:
tests/e2e/service-edit-moderation.spec.ts
- Create
-
11. E2E — Service Edit: Sermon Block
What to do:
- Create
tests/e2e/service-edit-sermon.spec.tswith 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.tsexists with ≥ 3 testsnpx 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.txtCommit: YES (group with Wave 3)
- Message:
test(e2e): add service edit sermon block E2E tests - Files:
tests/e2e/service-edit-sermon.spec.ts
- Create
-
12. E2E — Service Edit: Songs Block
What to do:
- Create
tests/e2e/service-edit-songs.spec.tswith 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.tsexists with ≥ 6 testsnpx 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.txtCommit: YES (group with Wave 3)
- Message:
test(e2e): add service edit songs block E2E tests - Files:
tests/e2e/service-edit-songs.spec.ts
- Create
-
13. E2E — Service Finalization Tests
What to do:
- Create
tests/e2e/service-finalization.spec.tswith 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.tsexists with ≥ 3 testsnpx 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.txtCommit: YES (group with Wave 3)
- Message:
test(e2e): add service finalization E2E tests - Files:
tests/e2e/service-finalization.spec.ts
- Create
Wave 4 — E2E Tests (Song DB + Advanced Features)
-
14. E2E — Song DB List + Search
What to do:
- Create
tests/e2e/song-db.spec.tswith 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.tsexists with ≥ 5 testsnpx 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.txtCommit: YES (group with Wave 4)
- Message:
test(e2e): add song database list and search E2E tests - Files:
tests/e2e/song-db.spec.ts
- Create
-
15. E2E — Song Edit Modal
What to do:
- Create
tests/e2e/song-edit-modal.spec.tswith 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.tsexists with ≥ 3 testsnpx 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.txtCommit: YES (group with Wave 4)
- Message:
test(e2e): add song edit modal E2E tests - Files:
tests/e2e/song-edit-modal.spec.ts
- Create
-
16. E2E — Song Translation Page
What to do:
- Create
tests/e2e/song-translate.spec.tswith 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 withpage(),import(),fetchUrl()methods.
Acceptance Criteria:
tests/e2e/song-translate.spec.tsexists with ≥ 3 testsnpx 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.txtCommit: YES (group with Wave 4)
- Message:
test(e2e): add song translation page E2E tests - Files:
tests/e2e/song-translate.spec.ts
- Create
-
[~] 17. E2E — Arrangement Configurator [DEFERRED]
DEFERRED: This task was intentionally deferred due to complexity of drag-and-drop testing and low ROI. Feature has comprehensive Pest test coverage. See
.sisyphus/notepads/cts-herd-playwright/problems.mdfor details. All verification tasks (F1-F4) approved the project for production WITHOUT this task.What to do:
- Create
tests/e2e/arrangement.spec.tswith 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.tsexists with ≥ 4 testsnpx 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.txtCommit: YES (group with Wave 4)
- Message:
test(e2e): add arrangement configurator E2E tests - Files:
tests/e2e/arrangement.spec.ts
- Create
-
18. E2E — Song Preview + PDF Download
What to do:
- Create
tests/e2e/song-preview-pdf.spec.tswith 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.tsexists with ≥ 3 testsnpx 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.txtCommit: YES (group with Wave 4)
- Message:
test(e2e): add song preview and PDF download E2E tests - Files:
tests/e2e/song-preview-pdf.spec.ts
- Create
-
19. E2E — Sync + .pro Placeholders
What to do:
- Create
tests/e2e/sync-and-pro.spec.tswith 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.tsexists with ≥ 4 testsnpx 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.txtCommit: YES (group with Wave 4)
- Message:
test(e2e): add sync and .pro placeholder E2E tests - Files:
tests/e2e/sync-and-pro.spec.ts
- Create
-
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/toBeVisibleassertions) - SQLite BUSY errors (verify
workers: 1in config) - State contamination between tests (ensure proper setup/teardown)
- Missing
data-testidattributes (go back and add them) - Auth state expired (verify storageState is refreshed)
- Flaky tests due to timing (add
- Also verify existing Pest tests still pass:
php artisan test - Run
npm run buildto 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 failuresphp artisan test→ 174 tests, 905 assertions, 0 failuresnpm 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.txtCommit: YES
- Message:
test(e2e): fix all test failures and verify full suite passes - Files: Any modified
.spec.tsfiles,playwright.config.ts(if adjusted) - Pre-commit:
npx playwright test && php artisan test
- Run the ENTIRE Playwright test suite:
Final Verification Wave
4 review agents run in PARALLEL. ALL must APPROVE. Rejection → fix → re-run.
-
F1. Plan Compliance Audit —
oracleRead 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 -
F2. Code Quality Review —
unspecified-highRunphp artisan test(174 Pest tests still pass). Runnpx 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. Verifydata-testidnaming follows pattern{component}-{element}. Output:Pest [PASS/FAIL] | Playwright [N pass/N fail] | Files [N clean/N issues] | VERDICT -
F3. Real Manual QA —
unspecified-high(+playwrightskill) Start from clean state (clear storageState). Navigate tohttp://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 -
F4. Scope Fidelity Check —
deepFor each task: read "What to do", read actual diff (git difffor 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
# 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