import { expect, type Page } from "@playwright/test"; type AuthSeed = { token?: string; userId?: string; role?: string; username?: string; }; type HouseholdSeed = { id?: number; name?: string; role?: string; invite_code?: string; }; type StoreSeed = { id?: number; name?: string; location?: string; is_default?: boolean; }; const defaultConfig = { maxFileSizeMB: 20, maxImageDimension: 800, imageQuality: 85, }; export function seedAuthStorage(page: Page, seed: AuthSeed = {}) { return page.addInitScript((authSeed) => { localStorage.setItem("token", authSeed.token || "test-token"); localStorage.setItem("userId", authSeed.userId || "1"); localStorage.setItem("role", authSeed.role || "admin"); localStorage.setItem("username", authSeed.username || "test-user"); }, seed); } export async function mockConfig(page: Page, overrides = {}) { await page.route("**/config", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ ...defaultConfig, ...overrides }), }); }); } export async function mockHouseholdAndStoreShell( page: Page, options: { household?: HouseholdSeed; stores?: StoreSeed[] } = {} ) { const household = { id: 1, name: "Test Household", role: "admin", invite_code: "ABCD1234", ...options.household, }; const stores = options.stores || [ { id: 10, name: "Costco", location: "Warehouse", is_default: true }, ]; await page.route("**/households", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify([household]), }); }); await page.route(`**/stores/household/${household.id}`, async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify(stores), }); }); } export async function confirmSlide(page: Page) { const confirmModal = page.locator(".confirm-slide-modal"); await expect(confirmModal).toBeVisible(); const slider = confirmModal.locator(".confirm-slide-handle"); const track = confirmModal.locator(".confirm-slide-track"); const sliderBox = await slider.boundingBox(); const trackBox = await track.boundingBox(); if (!sliderBox || !trackBox) { throw new Error("Confirm slide control was not measurable"); } await page.mouse.move(sliderBox.x + sliderBox.width / 2, sliderBox.y + sliderBox.height / 2); await page.mouse.down(); await page.mouse.move(trackBox.x + trackBox.width - 4, sliderBox.y + sliderBox.height / 2, { steps: 8, }); await page.mouse.up(); } export function collectFailedApiRequests(page: Page) { const failedRequests: string[] = []; page.on("requestfailed", (request) => { const url = request.url(); if (!url.startsWith("http://localhost:5000")) { return; } const failure = request.failure()?.errorText || "unknown failure"; failedRequests.push(`${request.method()} ${url} :: ${failure}`); }); return failedRequests; } export function expectNoFailedApiRequests(failedRequests: string[]) { expect(failedRequests).toEqual([]); }