import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; describe("cache", () => { beforeEach(() => { vi.resetModules(); }); afterEach(() => { vi.useRealTimers(); }); it("bypasses cache when not in browser", async () => { vi.doMock("$app/environment", () => ({ browser: false })); const { cached } = await import("./cache"); const fn = vi.fn().mockResolvedValue("result-1"); const res1 = await cached("test-key", 30_000, fn); const res2 = await cached("test-key", 30_000, fn); expect(res1).toBe("result-1"); expect(res2).toBe("result-1"); expect(fn).toHaveBeenCalledTimes(2); }); it("caches value in browser and serves from cache before ttl expires", async () => { vi.doMock("$app/environment", () => ({ browser: true })); const { cached } = await import("./cache"); const fn = vi.fn().mockResolvedValue({ hello: "world" }); const res1 = await cached("test-key", 30_000, fn); const res2 = await cached("test-key", 30_000, fn); expect(res1).toEqual({ hello: "world" }); expect(res2).toEqual({ hello: "world" }); expect(fn).toHaveBeenCalledTimes(1); }); it("refetches after ttl expires", async () => { vi.useFakeTimers(); vi.doMock("$app/environment", () => ({ browser: true })); const { cached } = await import("./cache"); let count = 0; const fn = vi.fn().mockImplementation(async () => ++count); const res1 = await cached("test-key", 30_000, fn); expect(res1).toBe(1); vi.advanceTimersByTime(29_999); const res2 = await cached("test-key", 30_000, fn); expect(res2).toBe(1); expect(fn).toHaveBeenCalledTimes(1); vi.advanceTimersByTime(2); const res3 = await cached("test-key", 30_000, fn); expect(res3).toBe(2); expect(fn).toHaveBeenCalledTimes(2); }); it("cleans up cache and rethrows when loader rejects", async () => { vi.doMock("$app/environment", () => ({ browser: true })); const { cached } = await import("./cache"); const err = new Error("network error"); const fn = vi.fn().mockRejectedValue(err); await expect(cached("err-key", 30_000, fn)).rejects.toThrow("network error"); fn.mockResolvedValueOnce("recovered"); const res = await cached("err-key", 30_000, fn); expect(res).toBe("recovered"); }); it("clears every key", async () => { vi.doMock("$app/environment", () => ({ browser: true })); const { cached, clear } = await import("./cache"); const fnIssues = vi.fn().mockResolvedValue("issues-data"); const fnPulls = vi.fn().mockResolvedValue("pulls-data"); await cached("issues:did:plc:repo:open:", 30_000, fnIssues); await cached("pulls:did:plc:repo:open:", 30_000, fnPulls); clear(); await cached("issues:did:plc:repo:open:", 30_000, fnIssues); await cached("pulls:did:plc:repo:open:", 30_000, fnPulls); expect(fnIssues).toHaveBeenCalledTimes(2); expect(fnPulls).toHaveBeenCalledTimes(2); }); });