import { expect, test, type Page, type Route } from "@playwright/test"; const FROZEN_NOW = "2026-08-19T15:00:00.000Z"; const WEEK_START = "2026-08-17"; const WEEK_END = "2026-08-21"; const TEST_USER = { token: "wo-visual-token", expiration: "2030-01-01T00:00:00.000Z", email: "admin@seahavenind.com", userRoles: "Admin", phoneNumber: "5551234567", fullname: "Work Order Visual Admin", id: "1", }; const DISPATCHERS = [{ id: "1", name: "Pat Dispatcher" }]; const LOCATIONS = [ { id: 10, name: "STL-01 ยท St. Louis, MO", siteCode: "STL-01", city: "St. Louis", state: "MO", code: "STL-01", }, ]; const VENDORS = [ { id: 101, companyName: "Gateway Plumbing", contactName: "Adam Whyte", tradeSpecialties: "Plumbing", address: "1 Market St", }, ]; const scheduledRow = { id: 1, woNumber: "WO-501", workOrderType: 2, siteCode: "STL-01", locationName: "St. Louis HQ", locationId: 10, lifecycleStatusLabel: "Scheduled", scheduledDate: "2026-08-19", dispatcherId: "1", dispatcherName: "Pat Dispatcher", pm: "HVAC", vendorId: 101, vendorName: "Gateway Plumbing", techName: "Adam Whyte", title: "Quarterly HVAC PM", dueDate: "2026-08-21", rowVersion: "rv-visual", }; const unassignedRow = { ...scheduledRow, id: 2, woNumber: "WO-502", scheduledDate: null, lifecycleStatusLabel: "Pending", title: "Boiler leak follow-up", }; async function fulfillJson(route: Route, body: unknown, status = 200) { await route.fulfill({ status, contentType: "application/json", body: JSON.stringify(body) }); } function isBoardList(pathname: string) { return pathname.endsWith("/workorders/board") || pathname.endsWith("/api/workorders/board"); } function isBoardSearch(pathname: string) { return pathname.includes("/workorders/board/search"); } function isBoardDetail(pathname: string) { return /\/workorders\/\d+\/detail$/.test(pathname); } function isAccountList(pathname: string) { return pathname.includes("/Account/GetAccountList"); } async function mockWorkOrderApi(page: Page, mode: "default" | "empty" | "error" = "default") { await page.clock.setFixedTime(new Date(FROZEN_NOW)); await page.addInitScript((user) => localStorage.setItem("auth", JSON.stringify(user)), TEST_USER); await page.route("**/api/**", async (route) => { const url = new URL(route.request().url()); const pathname = url.pathname; if (!pathname.startsWith("/api/")) { await route.continue(); return; } if (isBoardSearch(pathname)) { const items = mode === "default" ? [unassignedRow] : []; await fulfillJson(route, { items, totalCount: items.length, page: 0, pageSize: 50 }); return; } if (isBoardList(pathname)) { if (mode === "error") { await fulfillJson(route, { message: "Work order board unavailable" }, 500); return; } const scheduled = mode === "empty" ? [] : [scheduledRow]; const unscheduled = mode === "empty" ? [] : [unassignedRow]; await fulfillJson(route, { weekStart: WEEK_START, weekEnd: WEEK_END, counts: { returned: scheduled.length + unscheduled.length, total: scheduled.length + 1 }, unscheduled, scheduled, }); return; } if (isBoardDetail(pathname)) { await fulfillJson(route, { data: { info: scheduledRow, comments: [], audit: [], media: [], completion: {}, }, }); return; } if (pathname.includes("/workorders/lookups/dispatchers")) { await fulfillJson(route, { data: DISPATCHERS }); return; } if (pathname.includes("/Contact/GetLocations") || pathname.includes("/locations/sites")) { await fulfillJson(route, { data: LOCATIONS }); return; } if (pathname.includes("/vendors/Dropdown") || pathname.endsWith("/vendors/dropdown")) { await fulfillJson(route, { data: VENDORS }); return; } if (pathname.includes("/DropdownOptions/ByCategory/Problem")) { await fulfillJson(route, { data: [ { id: 1, value: "HVAC", category: "Problem" }, { id: 2, value: "Plumbing", category: "Problem" }, ], }); return; } if (pathname.includes("/api/User")) { await fulfillJson(route, { data: DISPATCHERS }); return; } if (isAccountList(pathname)) { await fulfillJson(route, { items: [ { id: 1, name: "Amazon", number: "AMZ-1", industry: "Retail", website: "", primaryContact: "", phoneNumber: "", owner: "", }, ], totalCount: 1, page: 1, pageSize: 50, }); return; } await fulfillJson(route, { data: [] }); }); } async function openWorkOrderPage(page: Page, mode: "default" | "empty" | "error" = "default") { await mockWorkOrderApi(page, mode); await page.goto("/workorders"); await page.evaluate(() => document.fonts.ready); await page.addStyleTag({ content: ` *, *::before, *::after { transition: none !important; animation: none !important; } .MuiDrawer-paper { transform: none !important; } .Toastify__toast-container { display: none !important; } .tsqd-parent-container { display: none !important; } `, }); } async function expectStableScreenshot(page: Page, name: string) { await page.waitForTimeout(250); await page.evaluate( () => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(() => resolve())), ), ); await page.screenshot({ animations: "disabled", caret: "hide" }); await expect(page).toHaveScreenshot(name); } test.describe("Work Orders deterministic pixel regression", () => { test("list", async ({ page }) => { await openWorkOrderPage(page); await expect(page.getByRole("heading", { name: "Work Orders" })).toBeVisible(); await expect(page.getByText("WO-501").first()).toBeVisible(); await expectStableScreenshot(page, "wo-list.png"); }); test("filters", async ({ page }) => { await openWorkOrderPage(page); await page.getByRole("button", { name: "Advanced Filters" }).click(); await expect(page.getByRole("dialog", { name: "Advanced Filters" })).toBeVisible(); await expectStableScreenshot(page, "wo-filters.png"); }); test("new", async ({ page }) => { await openWorkOrderPage(page); await page.getByRole("button", { name: "New WO" }).click(); await expect(page.getByRole("heading", { name: "Type & schedule" })).toBeVisible(); await expectStableScreenshot(page, "wo-new.png"); }); test("detail", async ({ page }) => { await openWorkOrderPage(page); const row = page.locator("#wo-row-1"); await row.hover(); await row.getByRole("button", { name: "View details" }).click(); await expect(page.getByRole("heading", { name: "#WO-501" })).toBeVisible(); await expectStableScreenshot(page, "wo-detail.png"); }); test("empty", async ({ page }) => { await openWorkOrderPage(page, "empty"); await expect(page.getByRole("heading", { name: "Work Orders" })).toBeVisible(); await page.getByLabel("Search work orders").fill("zz"); await expect(page.getByText("No work orders match your search")).toBeVisible(); await expectStableScreenshot(page, "wo-empty.png"); }); test("error", async ({ page }) => { await openWorkOrderPage(page, "error"); await expect(page.getByRole("heading", { name: "Work Orders" })).toBeVisible(); const alert = page.getByRole("main").getByRole("alert"); await expect(alert).toBeVisible(); await expect(alert).toContainText(/server error/i); await expectStableScreenshot(page, "wo-error.png"); }); test("mobile", async ({ page }) => { await page.setViewportSize({ width: 390, height: 844 }); await openWorkOrderPage(page); await expect(page.getByText("WO-501").first()).toBeVisible(); await expectStableScreenshot(page, "wo-mobile.png"); await page.getByRole("button", { name: "Toggle navigation" }).click(); await expect(page.getByRole("navigation", { name: "Primary navigation" })).toBeVisible(); await expectStableScreenshot(page, "wo-mobile-navigation.png"); }); });