Files
OSIT-AE-App-Svelte/tests/_helpers/idb_helpers.ts
Scott Idem af02e38528 test: badge E2E tests — fix __version wipe, extract idb_helpers, add render + workflow tests
Root cause fix: tests/_helpers/ae_defaults.ts was missing __version: 1, causing
store_versions.ts to wipe ae_loc from localStorage on every test page load. This
made trusted_access fall back to false, hiding the print button (can_print guard)
and failing all attendee workflow tests.

Changes:
- ae_defaults.ts: add __version: 1 with comment explaining the store_versions guard
- idb_helpers.ts: extract inject_badge_and_template() from print layout test into
  shared helper; now used by all three print/render test files
- event_badge_render.test.ts: new — 4 tests covering full_name_override priority,
  full_name fallback, duplex=0 hides badge back, duplex=1 shows badge back
- event_badge_attendee_workflow.test.ts: cleaned up (diagnostic code removed);
  all 3 tests now pass
- event_badge_print_layout.test.ts: renamed from badge_print_layout.test.ts;
  inline inject_idb() replaced with shared idb_helpers import
- event_badge_smoke.test.ts: renamed from event_badge.test.ts
- playwright.config.ts: use system /usr/bin/chromium on Arch Linux (avoids
  Playwright's bundled Chromium which requires Ubuntu libs not present on Arch)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 16:58:55 -04:00

57 lines
2.4 KiB
TypeScript

/**
* IndexedDB injection helpers for Playwright tests.
*
* These functions execute inside the browser via page.evaluate() — they must be
* self-contained and cannot close over test-scope variables (only the single
* argument passed to page.evaluate is available).
*
* Standard pattern for using inject_badge_and_template:
*
* await page.goto('/events/{event_id}/badges/{badge_id}/print');
* await page.waitForLoadState('domcontentloaded');
* await page.evaluate(inject_badge_and_template, { badge, template });
* await page.reload();
* await page.waitForLoadState('domcontentloaded');
*
* Why reload after injection: direct IDB writes bypass Dexie's internal
* change-notification system, so liveQuery subscribers don't re-fire.
* Reloading starts the page fresh against the already-populated IDB.
*/
/** Injects a badge and badge_template record into ae_events_db. */
export async function inject_badge_and_template(
{ badge, template }: { badge: object; template: object }
): Promise<void> {
// Wait for Dexie to have fully initialised ae_events_db with its stores.
// domcontentloaded fires before Dexie's version migration runs, so the DB
// may not have the 'badge' / 'badge_template' stores yet when we arrive here.
await new Promise<void>((resolve, reject) => {
const poll = () => {
const req = indexedDB.open('ae_events_db');
req.onsuccess = () => {
const db = req.result as IDBDatabase;
const ready = db.objectStoreNames.contains('badge') &&
db.objectStoreNames.contains('badge_template');
db.close();
if (ready) resolve();
else setTimeout(poll, 100);
};
req.onerror = () => reject((req as IDBRequest).error);
};
poll();
});
const db = await new Promise<IDBDatabase>((resolve, reject) => {
const req = indexedDB.open('ae_events_db');
req.onsuccess = () => resolve(req.result as IDBDatabase);
req.onerror = () => reject((req as IDBRequest).error);
});
await new Promise<void>((resolve, reject) => {
const tx = db.transaction(['badge', 'badge_template'], 'readwrite');
tx.objectStore('badge').put(badge);
tx.objectStore('badge_template').put(template);
tx.oncomplete = () => { db.close(); resolve(); };
tx.onerror = () => { db.close(); reject(tx.error); };
});
}