import { render, waitFor } from "@testing-library/react"; import { ProjectProvider } from "./ProjectContext"; const mockApiFetch = jest.fn(); const mockUseSession = jest.fn(); const mockSetCurrentProjectId = jest.fn(); jest.mock("next-auth/react", () => ({ useSession: () => mockUseSession(), })); jest.mock("next/navigation", () => ({ usePathname: () => "/login", useRouter: () => ({ push: jest.fn() }), })); jest.mock("@/components/project/ProjectSelector", () => ({ ProjectSelector: () =>
project selector
, })); jest.mock("@/config/config", () => ({ config: { BACKEND_URL: "http://backend.test", MAP_EXTENT: [1, 2, 3, 4], MAP_WORKSPACE: "default-workspace", }, NETWORK_NAME: "default-network", setMapExtent: jest.fn(), setMapWorkspace: jest.fn(), setNetworkName: jest.fn(), })); jest.mock("@/lib/apiFetch", () => ({ apiFetch: (...args: unknown[]) => mockApiFetch(...args), })); jest.mock("@/lib/permissions", () => ({ permissionCodes: { environmentManage: "environment:manage" }, })); jest.mock("@/store/accessStore", () => ({ useAccessStore: (selector: (state: { permissions: string[] }) => unknown) => selector({ permissions: [] }), })); jest.mock("@/store/projectStore", () => ({ useProjectStore: ( selector: (state: { setCurrentProjectId: typeof mockSetCurrentProjectId }) => unknown, ) => selector({ setCurrentProjectId: mockSetCurrentProjectId }), })); const seedSavedProject = () => { localStorage.setItem("MAP_WORKSPACE", "fengyang"); localStorage.setItem("NETWORK_NAME", "fengyang"); localStorage.setItem("MAP_EXTENT", "1,2,3,4"); localStorage.setItem( "active_project", "a2d67c84-fd9d-4feb-a500-c357244b2760", ); }; describe("ProjectProvider authentication boundary", () => { beforeEach(() => { localStorage.clear(); mockApiFetch.mockReset(); mockSetCurrentProjectId.mockReset(); mockApiFetch.mockResolvedValue({ ok: true, json: async () => ({}), }); }); it("does not restore or open a saved project while unauthenticated", () => { seedSavedProject(); mockUseSession.mockReturnValue({ status: "unauthenticated" }); render(
login page
, ); expect(mockSetCurrentProjectId).not.toHaveBeenCalled(); expect(mockApiFetch).not.toHaveBeenCalled(); }); it("restores a saved project and reads its current metadata", async () => { seedSavedProject(); mockUseSession.mockReturnValue({ status: "authenticated" }); render(
main page
, ); await waitFor(() => expect(mockApiFetch).toHaveBeenCalledTimes(1)); expect(mockApiFetch).toHaveBeenCalledWith( "http://backend.test/api/v1/projects/current", ); expect(mockSetCurrentProjectId).toHaveBeenCalledWith( "a2d67c84-fd9d-4feb-a500-c357244b2760", ); }); });