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