docs: update tests/README and GUIDE__Development with current test patterns
tests/README.md:
- Add shared helpers table (_helpers/ files and purpose)
- Update "Writing / modifying tests" to reference setup_badge_test_page;
badge tests are now the canonical template
- Add "Hard-Won Lessons — Badge Print / IDB Tests" section covering:
- __version guard: why ae_defaults.ts must include __version: 1 or
store_versions.ts silently wipes ae_loc and loses trusted_access
- IDB inject-then-reload pattern: why reload is required (liveQuery
won't fire on raw IDB writes that bypass Dexie's notification system)
- Fix pre-existing lint warnings: bare URLs → code spans, trailing newline
GUIDE__Development.md:
- Add Required Check #5: run Playwright integration tests for auth/store
or badge print changes; badge tests are the canonical template
- Add tests/README.md to Key Documentation table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,11 @@
|
||||
2. **Type Safety:** Ensure interfaces in `src/lib/types/ae_types.ts` match backend schemas.
|
||||
3. **Reactivity Check:** Verify Svelte 5 runes (`$state`, `$derived`) are not creating race conditions with Dexie `liveQuery`.
|
||||
4. **Build Check:** For major changes, run `npm run build:staging` to ensure no SSR or build-time failures.
|
||||
5. **Integration Tests:** For changes to badge print, event layouts, or auth/store logic, run the relevant Playwright test file(s):
|
||||
```bash
|
||||
npx playwright test tests/event_badge_render.test.ts tests/event_badge_attendee_workflow.test.ts
|
||||
```
|
||||
Run the full suite with `npm run test:integration`. The badge tests (`event_badge_*.test.ts`) are the canonical integration test template.
|
||||
|
||||
## 2. Commit Policy
|
||||
- **Atomic Commits:** One component or one logic fix per commit. Do not batch unrelated changes.
|
||||
@@ -46,6 +51,7 @@ You are not working in a vacuum. Coordinate with the Backend Agent via MCP tools
|
||||
| `documentation/AE__Architecture.md` | System architecture overview |
|
||||
| `documentation/AE__Naming_Conventions.md` | Naming rules |
|
||||
| `documentation/PROJECT__AE_Events_Launcher_Native_integration.md` | Electron/Launcher reference |
|
||||
| `tests/README.md` | Playwright test guide — shared helpers, hard-won lessons, demo IDs |
|
||||
|
||||
## 6. URL Parameters
|
||||
|
||||
|
||||
@@ -25,20 +25,36 @@ Notes
|
||||
- Tests in `tests/disabled/` are ignored by default (see `playwright.config.ts`). Move flaky or environment-dependent tests there.
|
||||
- The runner starts a local dev server via `npm run dev` by default (see `playwright.config.ts:webServer`). Ensure the app can start on port `5173` or update the config.
|
||||
|
||||
Shared test helpers (`tests/_helpers/`)
|
||||
|
||||
| File | Purpose |
|
||||
| --- | --- |
|
||||
| `env.ts` | Constants: `testing_event_id`, `testing_account_id`, `mock_site_domain` |
|
||||
| `ae_defaults.ts` | `ae_app_local_data_defaults` — full localStorage seed object with `__version` |
|
||||
| `idb_helpers.ts` | `inject_badge_and_template()` — write badge + template records into IndexedDB |
|
||||
| `minimal_v3_mocks.ts` | `attach_minimal_v3_routes()`, `seed_trusted_session()`, `setup_badge_test_page()` |
|
||||
|
||||
**`setup_badge_test_page(page, event_id)`** is the one-call `beforeEach` for any badge/event print page test. It wires the pageerror listener, all V3 API mocks, and the trusted auth localStorage seed in one call.
|
||||
|
||||
Writing / modifying tests
|
||||
- Tests are TypeScript files under `tests/` and should export Playwright `test` blocks. Example header:
|
||||
- Tests are TypeScript files under `tests/` and should export Playwright `test` blocks.
|
||||
- The badge tests (`event_badge_*.test.ts`) are the **canonical template** — copy the pattern from there when adding tests for any new event module feature.
|
||||
- Minimal `beforeEach` using shared helpers:
|
||||
|
||||
```ts
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { testing_event_id } from './_helpers/env';
|
||||
import { inject_badge_and_template } from './_helpers/idb_helpers'; // only if IDB needed
|
||||
import { setup_badge_test_page } from './_helpers/minimal_v3_mocks';
|
||||
|
||||
test('example', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await expect(page).toHaveTitle(/OSIT/);
|
||||
const event_id = testing_event_id;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await setup_badge_test_page(page, event_id);
|
||||
});
|
||||
```
|
||||
|
||||
- Use `page.route('**/v3/**', handler)` to mock backend responses for deterministic tests.
|
||||
- Use `page.addInitScript` to inject `ae_loc` localStorage defaults when tests need authenticated/admin state.
|
||||
- If you need IDB data (badge, template), use the inject-then-reload pattern (see Hard-Won Lessons below).
|
||||
- Use `page.route('**/v3/**', handler)` to mock backend responses. `attach_minimal_v3_routes` covers the common cases; add inline `page.route()` calls only for test-specific overrides.
|
||||
|
||||
Adding new tests
|
||||
- Create a new file `tests/my_feature.test.ts`.
|
||||
@@ -58,6 +74,50 @@ Help
|
||||
|
||||
---
|
||||
|
||||
## Hard-Won Lessons — Badge Print / IDB Tests
|
||||
|
||||
These lessons came from debugging the badge attendee workflow tests. Document them here so the next person doesn't spend hours on the same issues.
|
||||
|
||||
### The `__version` Guard — Always Include It in `ae_app_local_data_defaults`
|
||||
|
||||
**Symptom:** Tests set `trusted_access: true` in `addInitScript`, but after `page.reload()` the print button is gone. Logging `$ae_loc.trusted_access` after reload shows `false`.
|
||||
|
||||
**Cause:** `src/lib/stores/store_versions.ts` is a module-level side-effect import that runs *before* `persisted()` hydrates the store. It reads `ae_loc` from localStorage and calls `localStorage.removeItem('ae_loc')` if `parsed.__version !== AE_LOC_VERSION`. After the wipe, `persisted()` falls back to its `initialValue` (app defaults where `trusted_access: false`), erasing the test's auth seed.
|
||||
|
||||
**Fix:** `ae_defaults.ts` must include `__version: 1` (matching `AE_LOC_VERSION` in `store_versions.ts`). This is already done — **do not remove it**.
|
||||
|
||||
```typescript
|
||||
export const ae_app_local_data_defaults = {
|
||||
__version: 1, // Must match AE_LOC_VERSION in store_versions.ts — store_versions.ts
|
||||
// wipes ae_loc if version doesn't match. Tests will silently lose auth.
|
||||
...
|
||||
};
|
||||
```
|
||||
|
||||
If `AE_LOC_VERSION` ever increments in `store_versions.ts`, update the value here too or every test that relies on `trusted_access` will silently break.
|
||||
|
||||
---
|
||||
|
||||
### The IDB Inject-Then-Reload Pattern
|
||||
|
||||
**Why reload?** Dexie's `liveQuery` subscribes to IDB change notifications. Writing directly to IDB via the raw `indexedDB` API (as `inject_badge_and_template` does) bypasses Dexie's notification system — `liveQuery` will not fire. Reloading the page forces Dexie to open fresh, query the now-populated IDB, and fire `liveQuery` with the seeded data.
|
||||
|
||||
**Correct pattern:**
|
||||
```typescript
|
||||
await page.goto(`/events/${event_id}/badges/${badge_id}/print`);
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
// First nav initializes the Dexie schema. Now inject data.
|
||||
await page.evaluate(inject_badge_and_template, { badge, template });
|
||||
// Reload so liveQuery starts fresh against populated IDB.
|
||||
await page.reload();
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
await page.waitForSelector('.event_badge_wrapper', { timeout: 8000 });
|
||||
```
|
||||
|
||||
**Do not** try to `waitForFunction` for IDB changes after `inject_badge_and_template` without reloading — it will time out because liveQuery will not re-fire.
|
||||
|
||||
---
|
||||
|
||||
## Deep Dive: Testing IDAA Edit Form Components
|
||||
|
||||
This section documents hard-won lessons from writing `idaa_recovery_meeting_edit.test.ts`. These issues are not obvious and cost significant debugging time — read this before writing tests for any Svelte 5 form component.
|
||||
@@ -231,8 +291,8 @@ await page.route(`**/v3/crud/event/${event_id}`, async (route) => {
|
||||
|
||||
## Development / Testing / Demo environment information
|
||||
* Use snake_case (or Snake_Case or Snake_case or test_NASA_example or test_API_key)
|
||||
* Aether test/demo base URL: 'http://demo.localhost:5173'
|
||||
* Aether development API: 'https://dev-api.oneskyit.com'
|
||||
* Aether test/demo base URL: `http://demo.localhost:5173`
|
||||
* Aether development API: `https://dev-api.oneskyit.com`
|
||||
|
||||
These are IDs for records that we can use for testing. Please do not delete them. They are also used for demo purposes with clients.
|
||||
|
||||
@@ -276,4 +336,4 @@ These are IDs for records that we can use for testing. Please do not delete them
|
||||
|
||||
### Events Module (IDAA Recovery Meetings)
|
||||
* Aether test/demo Event: '1Pkd025vvxU' (36) "IDAA Recovery Meeting Test"
|
||||
* Aether test/demo Event: 'gIZgAjISkf8' (43) "IDAA Recovery Meeting Test"
|
||||
* Aether test/demo Event: 'gIZgAjISkf8' (43) "IDAA Recovery Meeting Test"
|
||||
|
||||
Reference in New Issue
Block a user