import { expect, test, type Page } from "@playwright/test"; import { API_HOST, apiPathPattern, mockApi, seedAuthenticatedState } from "./support/network.js"; import { isDesktopProject } from "./support/projects"; const json = (body: unknown, status = 200) => ({ status, contentType: "application/json", body: JSON.stringify(body), }); const departments = [ { id: 1, name: "Assigned Depot", description: "", visible: true, archived: false, custom_pricing_only: true }, { id: 2, name: "Remote Depot", description: "", visible: true, archived: false, custom_pricing_only: false }, ]; const role = { key: "department_admin", label: "Department admin", description: "Can manage department prices, customer pricing, and employee access.", permission_groups: [ { key: "limited_backoffice", capabilities: ["open_limited_backoffice", "manage_employee_access"], }, ], }; const roles = [ { key: "viewer", label: "Deactivated", description: "Keeps the employee registered without order, booking, or management permissions.", permission_groups: [{ key: "account", capabilities: ["sign_in", "view_own_permissions"] }], }, role, ]; const employees = [ { id: 501, user_id: 501, customer_number: 0, display_name: "Casey Clerk", email: "casey@example.com", phone_country_code: 45, phone: 12345678, active: true, role, departments, created_at: "2026-01-01 00:00:00", updated_at: "2026-01-01 00:00:00", }, { id: 502, user_id: 502, customer_number: 0, display_name: "Riley Remote", email: "riley@example.com", phone_country_code: null, phone: null, active: true, role: roles[0], departments: [departments[1]], created_at: "2026-01-01 00:00:00", updated_at: "2026-01-01 00:00:00", }, ]; async function seedSuperuser(page: Page) { await page.addInitScript(() => { window.localStorage.setItem("locale", "en"); }); await seedAuthenticatedState(page, "superuser-department-employees-token"); await mockApi(page, { authenticated: true, permissions: [ "superuser", "user", "limited_backoffice_access", "limited_backoffice_employees_manage", "superuser_fetch_department", ], }); } async function installRoutes(page: Page) { const calls: string[] = []; const createCalls: unknown[] = []; const updateCalls: unknown[] = []; const currentEmployees = { value: structuredClone(employees) }; await page.route(apiPathPattern("/superuser/department"), async (route) => { const departmentId = Number(new URL(route.request().url()).searchParams.get("department_id")); const department = departments.find((item) => item.id === departmentId) || departments[0]; await route.fulfill( json({ data: { ...department, branding: null, created_at: "2026-01-01 00:00:00", updated_at: "2026-07-06 09:30:00", }, }) ); }); await page.route(API_HOST, async (route) => { const request = route.request(); const url = new URL(request.url()); const pathname = url.pathname; const method = request.method().toUpperCase(); calls.push(`${method} ${pathname}`); if (pathname.endsWith("/limited-backoffice/departments") && method === "GET") { await route.fulfill(json({ data: departments })); return; } if (pathname.endsWith("/limited-backoffice/roles") && method === "GET") { await route.fulfill(json({ data: roles })); return; } if (pathname.endsWith("/limited-backoffice/employees") && method === "GET") { await route.fulfill(json({ data: currentEmployees.value })); return; } if (pathname.endsWith("/limited-backoffice/employees") && method === "POST") { const body = request.postDataJSON?.() || {}; createCalls.push(body); currentEmployees.value.unshift({ id: 900, user_id: 900, customer_number: 0, display_name: body.display_name, email: body.email, phone_country_code: body.phone_country_code, phone: body.phone, active: true, role, departments: departments.filter((department) => body.department_ids?.includes(department.id)), created_at: "2026-07-08 00:00:00", updated_at: "2026-07-08 00:00:00", }); await route.fulfill(json({ data: currentEmployees.value[0] })); return; } const employeeMatch = pathname.match(/\/limited-backoffice\/employees\/(\d+)$/); if (employeeMatch && method === "PUT") { const body = request.postDataJSON?.() || {}; updateCalls.push(body); await route.fulfill(json({ data: { ...currentEmployees.value[0], ...body } })); return; } await route.fallback(); }); return { calls, createCalls, updateCalls }; } test.describe("Superuser department employees", () => { test("renders department-scoped employees and keeps multi-department access editable", async ({ page }, testInfo) => { test.skip(!isDesktopProject(testInfo), "Desktop only"); await seedSuperuser(page); const api = await installRoutes(page); await page.goto("/superuser/departments/1/employees", { waitUntil: "domcontentloaded" }); await expect(page.getByRole("heading", { name: "Assigned Depot" })).toBeVisible(); await expect(page.getByTestId("limited-backoffice")).toHaveCount(0); await expect(page.getByRole("heading", { name: "Employees" })).toBeVisible(); await expect(page.getByTestId("limited-employee-row-501")).toContainText("Casey Clerk"); await expect(page.getByTestId("limited-employee-row-502")).toHaveCount(0); await expect(page.getByTestId("limited-employee-department-1")).toBeChecked(); await expect(page.getByTestId("limited-employee-department-2")).not.toBeChecked(); await page.getByTestId("limited-employee-department-2").check(); await page.getByTestId("limited-employee-name").fill("Morgan Manager"); await page.getByTestId("limited-employee-email").fill("morgan@example.com"); await page.getByTestId("limited-employee-password").fill("Secret123!"); await page.getByTestId("limited-employee-role").selectOption("department_admin"); await page.getByTestId("limited-employee-save").click(); expect(api.createCalls[0]).toMatchObject({ display_name: "Morgan Manager", email: "morgan@example.com", role_key: "department_admin", department_ids: [1, 2], }); await page.getByTestId("limited-employee-edit-501").click(); await expect(page.getByTestId("limited-employee-department-1")).toBeChecked(); await expect(page.getByTestId("limited-employee-department-2")).toBeChecked(); await page.getByTestId("limited-employee-name").fill("Casey Lead"); await page.getByTestId("limited-employee-save").click(); expect(api.updateCalls[0]).toMatchObject({ display_name: "Casey Lead", department_ids: [1, 2], }); await page.getByTestId("limited-employee-role-help").click(); await expect(page.getByTestId("limited-role-permissions-modal")).toBeVisible(); await expect(page.locator("body")).not.toContainText("department_access_1"); await expect(page.locator("body")).not.toContainText("limited_backoffice_employees_manage"); await expect(page.locator("body")).not.toContainText("raw_permissions"); }); test("does not fetch employees for unknown department tabs", async ({ page }, testInfo) => { test.skip(!isDesktopProject(testInfo), "Desktop only"); await seedSuperuser(page); const api = await installRoutes(page); await page.goto("/superuser/departments/3/employees", { waitUntil: "domcontentloaded" }); await expect(page.getByTestId("limited-employees-forbidden")).toBeVisible(); await expect(page.getByTestId("limited-employees-table")).toHaveCount(0); expect(api.calls.some((call) => call.includes("/limited-backoffice/employees"))).toBe(false); }); });