- Complete execution patterns for remaining 20 tasks - 6-section prompt templates for each task type - Troubleshooting guide for common issues - Verification checklists and best practices - Session learnings from Wave 2-3 completion
142 lines
4.7 KiB
Markdown
142 lines
4.7 KiB
Markdown
# Learnings — cts-herd-playwright
|
|
|
|
## Inherited from Phase 1 (cts-presenter-app)
|
|
|
|
### Vue Key Pattern
|
|
For repeating groups in arrangements, MUST use `${group.id}-${index}` NOT just `group.id`
|
|
|
|
### PDF Generation
|
|
Old-school CSS only (NO Tailwind) with DejaVu Sans font for German umlauts
|
|
|
|
### Auto-Save
|
|
500ms debounce for text, immediate for selects/checkboxes via `useDebounceFn`
|
|
|
|
### Line-Count Translation
|
|
Distribute translated text by matching original slide line counts
|
|
|
|
### SQLite date gotcha
|
|
Returns `YYYY-MM-DD 00:00:00` instead of `YYYY-MM-DD` — needs `substr($date, 0, 10)`
|
|
|
|
---
|
|
|
|
## Phase 2 Specific
|
|
|
|
|
|
## [2026-03-01 23:10] Wave 2-3 Completion Session
|
|
|
|
### Playwright Test Patterns Established
|
|
|
|
**Auth Setup Pattern** (auth.setup.ts):
|
|
- Navigate to /login to establish session cookies (XSRF-TOKEN)
|
|
- Extract XSRF token from cookies: `decodeURIComponent(xsrfCookie.value)`
|
|
- POST to /dev-login with XSRF token in headers
|
|
- Navigate to /dashboard to confirm login
|
|
- Save storageState to tests/e2e/.auth/user.json
|
|
- Pattern works reliably for all authenticated tests
|
|
|
|
**Test Structure Pattern**:
|
|
```typescript
|
|
test('description', async ({ page }) => {
|
|
await page.goto('/url');
|
|
await page.waitForLoadState('networkidle'); // CRITICAL for Inertia apps
|
|
await expect(page).toHaveURL(/pattern/);
|
|
await expect(page.getByTestId('testid')).toBeVisible();
|
|
});
|
|
```
|
|
|
|
**CSRF Protection Pattern** (for POST requests in tests):
|
|
```typescript
|
|
const cookies = await page.context().cookies();
|
|
const xsrfCookie = cookies.find((c) => c.name === 'XSRF-TOKEN');
|
|
const xsrfToken = xsrfCookie ? decodeURIComponent(xsrfCookie.value) : '';
|
|
|
|
await page.request.post('/endpoint', {
|
|
headers: { 'X-XSRF-TOKEN': xsrfToken }
|
|
});
|
|
```
|
|
|
|
### Session Timeout Handling
|
|
|
|
**Issue**: Long-running task() calls timeout after 10 minutes (600000ms)
|
|
|
|
**Solution**:
|
|
1. Check if file was created despite timeout: `ls -la tests/e2e/{filename}.spec.ts`
|
|
2. If created, verify tests: `npx playwright test {filename}.spec.ts`
|
|
3. If tests pass, proceed with verification and commit
|
|
4. If tests fail, resume session with session_id (saves 70%+ tokens)
|
|
|
|
**Pattern**: Timeouts don't mean failure — check actual output before retrying
|
|
|
|
### data-testid Naming Conventions
|
|
|
|
**Established Patterns**:
|
|
- Navigation: `auth-layout-nav-{page}` (e.g., `auth-layout-nav-services`)
|
|
- User controls: `auth-layout-user-dropdown-trigger`, `auth-layout-logout-link`
|
|
- Sync: `auth-layout-sync-button`, `auth-layout-sync-timestamp`
|
|
- Lists: `{feature}-list-table`, `{feature}-list-row-{id}`, `{feature}-list-empty`
|
|
- Actions: `{feature}-list-{action}-button` (e.g., `service-list-edit-button`)
|
|
- Blocks: `{block}-block-{element}-{id}` (e.g., `information-block-thumbnail-{id}`)
|
|
|
|
**Rule**: Always use kebab-case, always include component context, always be specific
|
|
|
|
### German UI Text Assertions
|
|
|
|
**Common Terms**:
|
|
- Navigation: "Gottesdienste", "Song-Datenbank"
|
|
- Actions: "Bearbeiten", "Finalisieren", "Wieder öffnen", "Herunterladen", "Löschen"
|
|
- Auth: "Mit ChurchTools anmelden", "Abmelden", "Test-Anmeldung"
|
|
- General: "Willkommen", "Ablaufdatum", "Vorschau", "Zuweisen", "Mit Übersetzung"
|
|
|
|
**Rule**: Always use exact German text from Vue components, never English
|
|
|
|
### Inertia.js + Playwright Gotchas
|
|
|
|
**Issue**: Inertia apps render client-side, so page.goto() returns before Vue renders
|
|
|
|
**Solution**: ALWAYS use `await page.waitForLoadState('networkidle')` after navigation
|
|
|
|
**Issue**: data-testid attributes don't appear in raw HTML (curl output)
|
|
|
|
**Solution**: Check compiled JS bundles: `grep -r 'data-testid' public/build/assets/*.js`
|
|
|
|
### Parallel Task Execution
|
|
|
|
**Wave 3 Pattern**: All 6 tasks (T8-T13) can run in parallel
|
|
- Each creates independent spec file
|
|
- No shared state between tests
|
|
- All use same storageState (auth.setup.ts)
|
|
- workers:1 in playwright.config.ts prevents SQLite conflicts
|
|
|
|
**Optimization**: Dispatch all 6 tasks in ONE message for maximum parallelism
|
|
|
|
### Verification Best Practices
|
|
|
|
**4-Phase Verification** (MANDATORY):
|
|
1. **Read Code**: Read EVERY changed file line-by-line
|
|
2. **Automated Checks**: Run tests, build, lsp_diagnostics
|
|
3. **Hands-On QA**: Actually run the tests and see them pass
|
|
4. **Gate Decision**: Can explain every line? Saw it work? Confident nothing broken?
|
|
|
|
**Evidence Files**: Save test output to `.sisyphus/evidence/task-{number}-{name}.txt`
|
|
|
|
**Commit Messages**: Use conventional commits format:
|
|
```
|
|
test(e2e): add {feature} E2E tests
|
|
|
|
- X tests: {list}
|
|
- German UI text assertions
|
|
- All tests passing
|
|
```
|
|
|
|
### Token Budget Management
|
|
|
|
**Session Stats**:
|
|
- Started: 200K tokens
|
|
- Used: ~124K tokens (62%)
|
|
- Remaining: ~76K tokens (38%)
|
|
- Tasks completed: 7/24 (29.2%)
|
|
|
|
**Optimization**: Use session_id for retries (saves 70%+ tokens vs new task)
|
|
|
|
**Strategy**: Focus on completing Wave 3 (6 tasks) before token exhaustion
|