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>
57 lines
2.4 KiB
TypeScript
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); };
|
|
});
|
|
}
|