import { beforeEach, describe, expect, it, vi } from "vitest"; const save = vi.fn(); const load = vi.fn(); const list = vi.fn(); const restart = vi.fn(); vi.mock("@/lib/storage/providers/server-http.js", () => ({ saveInvestigation: (...args) => save(...args), loadInvestigation: (...args) => load(...args), listInvestigations: (...args) => list(...args), restartInvestigation: (...args) => restart(...args), })); function deferred() { let resolve; const promise = new Promise((next) => { resolve = next; }); return { promise, resolve }; } describe("server-authoritative investigation storage seam", () => { beforeEach(() => { vi.clearAllMocks(); save.mockResolvedValue(null); }); it("uses only the server provider for async load and list", async () => { const storage = await import("@/lib/storage/investigation-storage.js"); load.mockResolvedValue({ id: "inv-1" }); list.mockResolvedValue([{ id: "inv-1" }]); await expect(storage.loadInvestigation("inv-1")).resolves.toEqual({ id: "inv-1" }); await expect(storage.listInvestigations()).resolves.toEqual([{ id: "inv-1" }]); expect(load).toHaveBeenCalledWith("inv-1"); expect(list).toHaveBeenCalledTimes(1); }); it("allows only one in-flight save per investigation and coalesces rapid pending saves to the latest snapshot", async () => { const storage = await import("@/lib/storage/investigation-storage.js"); const first = deferred(); const second = deferred(); save.mockReturnValueOnce(first.promise).mockReturnValueOnce(second.promise); const one = storage.saveInvestigation({ id: "inv-1", revision: 1 }); const two = storage.saveInvestigation({ id: "inv-1", revision: 2 }); const three = storage.saveInvestigation({ id: "inv-1", revision: 3 }); expect(save).toHaveBeenCalledTimes(1); expect(save).toHaveBeenCalledWith({ id: "inv-1", revision: 1 }, "inv-1"); first.resolve({ id: "inv-1", revision: 1 }); await Promise.resolve(); expect(save).toHaveBeenCalledTimes(2); expect(save).toHaveBeenLastCalledWith({ id: "inv-1", revision: 3 }, "inv-1"); second.resolve({ id: "inv-1", revision: 3 }); await expect(Promise.all([one, two, three])).resolves.toEqual([ { id: "inv-1", revision: 1 }, { id: "inv-1", revision: 3 }, { id: "inv-1", revision: 3 }, ]); }); it("does not permit an older request to complete after a newer request becomes durable", async () => { const storage = await import("@/lib/storage/investigation-storage.js"); const first = deferred(); const second = deferred(); save.mockReturnValueOnce(first.promise).mockReturnValueOnce(second.promise); const older = storage.saveInvestigation({ id: "inv-2", revision: 2 }); const newer = storage.saveInvestigation({ id: "inv-2", revision: 3 }); expect(save).toHaveBeenCalledTimes(1); first.resolve({ id: "inv-2", revision: 2 }); await Promise.resolve(); expect(save).toHaveBeenLastCalledWith({ id: "inv-2", revision: 3 }, "inv-2"); second.resolve({ id: "inv-2", revision: 3 }); await Promise.all([older, newer]); expect(save).toHaveBeenCalledTimes(2); }); });