import { beforeEach, describe, expect, it, vi } from "vitest"; import { createPinia, setActivePinia } from "pinia"; const fetchStudies = vi.fn(); vi.mock("../api/studies", () => ({ fetchStudies, })); type StorageLike = { getItem: (key: string) => string | null; setItem: (key: string, value: string) => void; removeItem: (key: string) => void; clear: () => void; }; const createStorage = (): StorageLike => { const data = new Map(); return { getItem: (key) => data.get(key) ?? null, setItem: (key, value) => { data.set(key, String(value)); }, removeItem: (key) => { data.delete(key); }, clear: () => { data.clear(); }, }; }; describe("study store startup rehydration", () => { beforeEach(() => { setActivePinia(createPinia()); fetchStudies.mockReset(); Object.defineProperty(window, "localStorage", { value: createStorage(), configurable: true, }); }); it("clears a stale persisted study when the backend no longer has any studies", async () => { window.localStorage.setItem("ctms_last_login_email", "admin@example.com"); window.localStorage.setItem( "ctms_current_study", JSON.stringify({ id: "deleted-study", code: "ARCHIVED-CTMS", name: "已删除项目", }) ); fetchStudies.mockResolvedValue({ data: { items: [], }, }); const { useStudyStore } = await import("./study"); const study = useStudyStore(); study.loadCurrentStudy(); expect(study.currentStudy?.id).toBe("deleted-study"); await study.rehydrateStudyForLastUser(); expect(study.currentStudy).toBeNull(); expect(window.localStorage.getItem("ctms_current_study")).toBeNull(); }); it("does not treat a study role field as the current project role", async () => { const { useStudyStore } = await import("./study"); const study = useStudyStore(); study.setCurrentStudy({ id: "study-with-system-role", code: "SYS-ROLE", name: "系统字段项目", status: "ACTIVE", role: "PM", } as any); expect(study.currentStudyRole).toBeNull(); expect(window.localStorage.getItem("ctms_current_study_role")).toBeNull(); }); });