import { expect, test, type APIRequestContext } from "@playwright/test"; async function resetDemoData(request: APIRequestContext) { await request.post("http://localhost:8128/api/v1/demo/login", { data: { role: "operations_manager" }, }); await request.post("http://localhost:8128/api/v1/demo/reset"); } test.describe.configure({ mode: "serial" }); test.beforeEach(async ({ page }) => { await page.goto("/login"); await page.getByRole("button", { name: "Open as Operations Manager" }).click(); await expect(page).toHaveURL(/\/dashboard$/); }); test("all seven nav items navigate correctly", async ({ page }) => { const items: [string, RegExp][] = [ ["Dashboard", /\/dashboard$/], ["Vehicles", /\/vehicles$/], ["Bookings", /\/bookings$/], ["Data Quality", /\/data-quality$/], ["Knowledge", /\/knowledge$/], ["Automation", /\/automation$/], ["Audit", /\/audit$/], ]; for (const [label, urlPattern] of items) { await page.getByRole("link", { name: label }).click(); await expect(page).toHaveURL(urlPattern); } }); test("vehicles page: status filter and attention-only checkbox both work", async ({ page }) => { await page.goto("/vehicles"); await expect(page.locator(".data-table")).toBeVisible(); await page.getByLabel("Status").selectOption("maintenance"); await expect(page.locator(".data-table tbody tr").first()).toBeVisible(); const statuses = await page.locator(".data-table tbody tr td:nth-child(4)").allTextContents(); expect(statuses.every((s) => s.includes("maintenance"))).toBeTruthy(); await page.getByLabel("Status").selectOption(""); await page.getByLabel("Attention only").check(); await expect(page.locator(".data-table tbody tr").first()).toBeVisible(); const attentionCells = await page.locator(".data-table tbody tr td:nth-child(6)").allTextContents(); expect(attentionCells.every((c) => c.includes("Needs attention"))).toBeTruthy(); }); test("vehicle detail: all tabs render distinct content", async ({ page }) => { await page.goto("/vehicles/MO-016"); await expect(page.getByRole("heading", { name: /MO-016/ })).toBeVisible(); for (const tab of ["Overview", "Bookings", "Inspections", "Maintenance", "Quality"]) { await page.getByRole("tab", { name: tab }).click(); await expect(page.getByRole("tab", { name: tab })).toHaveAttribute("aria-selected", "true"); } }); test("bookings page: status filter works", async ({ page }) => { await page.goto("/bookings"); await expect(page.locator(".data-table")).toBeVisible(); await page.getByLabel("Status").selectOption("returned"); await expect(page.locator(".data-table tbody tr").first()).toBeVisible(); const statuses = await page.locator(".data-table tbody tr td:nth-child(5)").allTextContents(); expect(statuses.every((s) => s.includes("returned"))).toBeTruthy(); }); test("data quality page: status and rule-type filters work", async ({ page }) => { await page.goto("/data-quality"); await expect(page.locator(".data-table")).toBeVisible(); await page.getByRole("combobox", { name: "Rule type", exact: true }).selectOption( "possible_duplicate_customer", ); await expect(page.locator(".data-table tbody tr").first()).toBeVisible(); const rules = await page.locator(".data-table tbody tr td:nth-child(2)").allTextContents(); expect(rules.every((r) => r.includes("possible duplicate customer"))).toBeTruthy(); await page.getByRole("combobox", { name: "Rule type", exact: true }).selectOption(""); await page.getByRole("combobox", { name: "Status", exact: true }).selectOption("resolved"); await expect(page.locator(".data-table tbody tr").first()).toBeVisible(); }); test("data quality issue detail: defer and reject buttons work", async ({ page, request }) => { await resetDemoData(request); await page.goto("/data-quality?status=open&rule_type=missing_required_field"); await page.goto("/data-quality"); await page .getByRole("combobox", { name: "Rule type", exact: true }) .selectOption("missing_required_field"); const firstLink = page.locator(".data-table tbody tr").first().locator("a"); const ref = await firstLink.textContent(); await firstLink.click(); await expect(page.getByRole("heading", { name: ref ?? "" })).toBeVisible(); await page.getByRole("button", { name: "Defer" }).click(); await expect(page.getByText("deferred", { exact: true })).toBeVisible(); }); test("automation page: status filter and retry button work", async ({ page, request }) => { await resetDemoData(request); await page.goto("/automation"); await expect(page.locator(".data-table")).toBeVisible(); await page.getByLabel("Status").selectOption("failed"); await expect(page.locator(".data-table tbody tr").first()).toBeVisible(); const failedRowCountBefore = await page.locator(".data-table tbody tr").count(); const retryButton = page.getByRole("button", { name: "Retry" }).first(); await expect(retryButton).toBeVisible(); await retryButton.click(); // Retrying a failed delivery moves it out of the "failed" status, so — while still // filtered to "failed" — the row correctly disappears from this view rather than // showing "pending" in place. Confirm the filtered list shrank by one. await expect(async () => { const count = await page.locator(".data-table tbody tr").count(); expect(count).toBe(failedRowCountBefore - 1); }).toPass({ timeout: 5000 }); }); test("audit page: action filter works", async ({ page }) => { await page.goto("/audit"); await expect(page.locator(".data-table")).toBeVisible(); await page.getByLabel("Action").fill("demo_login"); await expect(page.locator(".data-table tbody tr").first()).toBeVisible(); const actions = await page.locator(".data-table tbody tr td:nth-child(3)").allTextContents(); expect(actions.every((a) => a.includes("demo_login"))).toBeTruthy(); }); test("knowledge page: form submits and clears input", async ({ page }) => { await page.goto("/knowledge"); const input = page.getByPlaceholder(/What must I do when a vehicle returns with damage/); await input.fill("What must I do when a vehicle returns with damage?"); await page.getByRole("button", { name: "Ask" }).click(); await expect(page.getByText("Grounded in cited procedures")).toBeVisible(); await expect(input).toHaveValue(""); }); test("switch role button logs out and returns to login", async ({ page }) => { await page.getByRole("button", { name: "Switch role" }).click(); await expect(page).toHaveURL(/\/login$/); }); test("rental employee role sees restricted automation page and cannot access reset", async ({ page, }) => { await page.getByRole("button", { name: "Switch role" }).click(); await page.getByRole("button", { name: "Open as Rental Employee" }).click(); await expect(page).toHaveURL(/\/dashboard$/); await page.getByRole("link", { name: "Automation" }).click(); await expect( page.getByText("Automation delivery status is visible to Operations Managers only."), ).toBeVisible(); });