import { test, expect } from "./fixtures.js"; /** * E2E tests for customer portal impersonation flow. */ const MOCK_SESSION = { id: "session-1", staffId: "staff-1", clientId: "client-1", reason: "Testing customer booking flow", status: "active", startedAt: new Date().toISOString(), endedAt: null, expiresAt: new Date(Date.now() + 30 * 60 * 1000).toISOString(), createdAt: new Date().toISOString(), }; test.describe("ImpersonationBanner", () => { test.beforeEach(async ({ page }) => { // Only mock impersonation endpoints - portal/me is NOT called in impersonation flow await page.route("**/api/impersonation/sessions/session-1", (route) => route.fulfill({ json: MOCK_SESSION }) ); await page.route("**/api/impersonation/sessions/session-1/end", (route) => route.fulfill({ json: { status: "ended" } }) ); await page.route("**/api/impersonation/sessions/session-1/extend", (route) => route.fulfill({ json: { ...MOCK_SESSION, expiresAt: new Date(Date.now() + 60 * 60 * 1000).toISOString() } }) ); await page.route("**/api/impersonation/sessions/session-1/audit-log", (route) => route.fulfill({ json: { logs: [] } }) ); // NOTE: NOT mocking portal/me - this endpoint is only called in the CLIENT // dev user flow (devUser.type === "client"), NOT in the impersonation flow }); test("banner displays when session is active", async ({ page }) => { await page.goto("/?sessionId=session-1"); await expect(page.locator("[data-testid=\"impersonation-banner\"]")).toBeVisible(); await expect(page.getByTestId("impersonation-banner").getByText("STAFF VIEW")).toBeVisible(); }); test("banner shows reason when session has reason", async ({ page }) => { await page.goto("/?sessionId=session-1"); await expect(page.getByText(/Reason: Testing customer booking flow/)).toBeVisible(); }); test("banner shows started time", async ({ page }) => { await page.goto("/?sessionId=session-1"); await expect(page.getByText(/Started/)).toBeVisible(); }); test("End Session button is visible", async ({ page }) => { await page.goto("/?sessionId=session-1"); await expect(page.getByRole("button", { name: /End Session/ })).toBeVisible(); }); test("Audit button is visible", async ({ page }) => { await page.goto("/?sessionId=session-1"); await expect(page.getByRole("button", { name: /Audit/ })).toBeVisible(); }); test("clicking End Session calls API and redirects", async ({ page }) => { await page.goto("/?sessionId=session-1"); await page.getByRole("button", { name: /End Session/ }).click(); await expect(page.getByTestId("impersonation-banner")).not.toBeVisible(); }); test("Extend button appears when time is low and not extended", async ({ page }) => { const lowTimeSession = { ...MOCK_SESSION, expiresAt: new Date(Date.now() + 3 * 60 * 1000).toISOString(), }; await page.route("**/api/impersonation/sessions/session-1", (route) => route.fulfill({ json: lowTimeSession }) ); await page.goto("/?sessionId=session-1"); await expect(page.getByRole("button", { name: /Extend/ })).toBeVisible(); }); test("URL is cleaned when session ends", async ({ page }) => { await page.goto("/?sessionId=session-1"); await page.getByRole("button", { name: /End Session/ }).click(); await expect(page).not.toHaveURL(/sessionId=session-1/); }); });