import { readFileSync } from "node:fs"; import { join } from "node:path"; import { beforeEach, describe, expect, it, vi } from "vitest"; const authenticatedRequestMock = vi.hoisted(() => vi.fn()); vi.mock("@/components/session/authenticatedRequest.vue", () => ({ authenticatedRequest: authenticatedRequestMock, })); import { EDGE_GATEWAY_WORKSPACE_CACHE_KEY, getEdgeGatewayDepartmentWorkspace, getEdgeGatewayInstallTokenStatus, getEdgeGatewayModuleConfig, listEdgeGatewayDepartmentWorkspaces, rotateNumberPlateScannerKey, setEdgeGatewayModuleConfig, updateNumberPlateScanner, } from "@/services/edgeGateways.js"; describe("edge gateway service", () => { beforeEach(() => { authenticatedRequestMock.mockReset(); }); it("loads module config entries and derives a keyed config object", async () => { authenticatedRequestMock.mockResolvedValue({ data: { data: [ { variable: "enabled", value: true }, { variable: "default_release_channel", value: "canary" }, ], }, }); const response = await getEdgeGatewayModuleConfig(); expect(authenticatedRequestMock).toHaveBeenCalledWith("/edgegateway/config", "GET", {}); expect(response.data.config).toEqual({ enabled: true, default_release_channel: "canary", }); }); it("persists module config updates as a single payload", async () => { authenticatedRequestMock.mockResolvedValue({ data: { data: [], }, }); await setEdgeGatewayModuleConfig({ enabled: false, default_release_channel: "canary", default_update_window: "03:00-05:00", }); expect(authenticatedRequestMock).toHaveBeenCalledTimes(1); expect(authenticatedRequestMock).toHaveBeenCalledWith("/edgegateway/config", "POST", { enabled: false, default_release_channel: "canary", default_update_window: "03:00-05:00", }); }); it("passes through installer session status requests unchanged", async () => { authenticatedRequestMock.mockResolvedValue({ data: { data: { claim_token_id: 9001, status: "RUNNING", }, }, }); await getEdgeGatewayInstallTokenStatus(9001); expect(authenticatedRequestMock).toHaveBeenCalledTimes(1); expect(authenticatedRequestMock).toHaveBeenCalledWith("/edge-gateways/install-token/9001/status", "GET", {}); }); it("loads department workspace summaries through the module workspace endpoint", async () => { authenticatedRequestMock.mockResolvedValue({ data: { data: [], }, }); await listEdgeGatewayDepartmentWorkspaces(); expect(authenticatedRequestMock).toHaveBeenCalledWith("/modules/edge-gateways/workspace/departments", "GET", {}); }); it("loads one department hardware workspace through the detail endpoint", async () => { authenticatedRequestMock.mockResolvedValue({ data: { data: { department: { id: 1 }, }, }, }); await getEdgeGatewayDepartmentWorkspace(1); expect(authenticatedRequestMock).toHaveBeenCalledWith("/modules/edge-gateways/workspace/departments/1", "GET", {}); }); it("updates scanner lane assignments through the shared scanner endpoint", async () => { authenticatedRequestMock.mockResolvedValue({ data: { data: { id: 8, }, }, }); await updateNumberPlateScanner(8, { department_id: 1, lane_id: 7, name: "North scanner", }); expect(authenticatedRequestMock).toHaveBeenCalledWith("/numberplatescanners", "PUT", { id: 8, department_id: 1, lane_id: 7, name: "North scanner", }); }); it("rotates scanner API keys through the dedicated rotate action", async () => { authenticatedRequestMock.mockResolvedValue({ data: { data: { api_key: "rotated-key", }, }, }); await rotateNumberPlateScannerKey(8); expect(authenticatedRequestMock).toHaveBeenCalledWith("/numberplatescanners/8/rotate-key", "POST", {}); }); it("keeps a stable browser cache namespace for workspace snapshots", () => { const source = readFileSync(join(process.cwd(), "src/services/edgeGateways.js"), "utf8"); expect(EDGE_GATEWAY_WORKSPACE_CACHE_KEY).toBe("truckwash.edgeGatewayWorkspace.cache.v1"); expect(source).toContain("localStorage"); expect(source).toContain("EDGE_GATEWAY_WORKSPACE_CACHE_KEY"); }); });