kammer/e2e/support/seed.ts
Christopher Mühl 307ef24b78 test: E2E test suite + handoff documentation
50 Playwright E2E tests across 13 spec files covering all routes and
user flows (items CRUD, check-out/in, locations, labels, scanning,
search/filter). Uses vitest as runner with playwright-core for browser
automation (bun-compatible alternative to @playwright/test).

Includes Gherkin .feature files as living documentation, test support
infrastructure (IDB seeding, item factories, assertion helpers, layout
measurement), and HANDOFF.md covering project state, deployment, and
open design decisions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 20:53:08 +01:00

78 lines
2.4 KiB
TypeScript

import type { Page } from 'playwright-core';
import type { Item } from '../../src/lib/types';
/**
* Wait for the app to finish loading (IDB initialized, default locations seeded).
*/
export async function waitForAppReady(page: Page) {
// Wait for SvelteKit to render (nav bar is always present in the layout)
await page.waitForSelector('nav', { timeout: 15000 });
// Then wait for the loading state to finish
await page.waitForFunction(() => {
return !document.body.textContent?.includes('Loading...');
}, { timeout: 15000 });
}
/**
* Seed items into IndexedDB via page.evaluate().
*/
export async function seedItems(page: Page, items: Item[]) {
await page.evaluate(async (itemsToSeed) => {
const request = indexedDB.open('solidhaus');
const db = await new Promise<IDBDatabase>((resolve, reject) => {
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
const tx = db.transaction('items', 'readwrite');
const store = tx.objectStore('items');
for (const item of itemsToSeed) {
store.put(item);
}
await new Promise<void>((resolve, reject) => {
tx.oncomplete = () => resolve();
tx.onerror = () => reject(tx.error);
});
db.close();
}, items);
}
/**
* Clear all items from IDB.
* Must be called after the app has loaded (IDB schema exists).
*/
export async function clearItems(page: Page) {
await page.evaluate(async () => {
const request = indexedDB.open('solidhaus');
const db = await new Promise<IDBDatabase>((resolve, reject) => {
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
// Check if the store exists before trying to clear it
if (db.objectStoreNames.contains('items')) {
const tx = db.transaction('items', 'readwrite');
tx.objectStore('items').clear();
await new Promise<void>((resolve, reject) => {
tx.oncomplete = () => resolve();
tx.onerror = () => reject(tx.error);
});
}
db.close();
});
}
/**
* Navigate, seed data, reload so store picks up changes.
*/
export async function seedAndNavigate(page: Page, items: Item[], targetPath: string) {
await page.goto('/');
await waitForAppReady(page);
if (items.length > 0) {
await seedItems(page, items);
}
await page.goto(targetPath);
await waitForAppReady(page);
}