import { describe, expect, it, vi } from "vitest"; import { createPiWebReleaseLookupCache } from "./piWebReleaseLookupCache.js"; describe("createPiWebReleaseLookupCache", () => { it("serves a fresh cached release lookup", async () => { let now = 1_000; const load = vi.fn(() => Promise.resolve("1.0.0")); const cache = createPiWebReleaseLookupCache(load, { ttlMs: 100, now: () => now }); await expect(cache.get("0.9.0")).resolves.toMatchObject({ latestVersion: "1.0.0", checkedAtMs: 1_000 }); now = 1_050; await expect(cache.get("0.9.1")).resolves.toMatchObject({ latestVersion: "1.0.0", checkedAtMs: 1_000 }); expect(load).toHaveBeenCalledOnce(); expect(load).toHaveBeenCalledWith("0.9.0"); }); it("bypasses a fresh lookup when forced", async () => { let now = 1_000; const load = vi.fn() .mockResolvedValueOnce("1.0.0") .mockResolvedValueOnce("1.1.0"); const cache = createPiWebReleaseLookupCache(load, { ttlMs: 100, now: () => now }); await cache.get("0.9.0"); now = 1_050; await expect(cache.get("0.9.0", { force: true })).resolves.toMatchObject({ latestVersion: "1.1.0", checkedAtMs: 1_050 }); await expect(cache.get("0.9.0")).resolves.toMatchObject({ latestVersion: "1.1.0", checkedAtMs: 1_050 }); expect(load).toHaveBeenCalledTimes(2); }); it.each(["forced-first", "regular-first"] as const)("does not let an older regular lookup replace a forced result when %s completes", async (completionOrder) => { const regular = createDeferred(); const forced = createDeferred(); const load = vi.fn() .mockImplementationOnce(() => regular.promise) .mockImplementationOnce(() => forced.promise); const cache = createPiWebReleaseLookupCache(load); const regularLookup = cache.get("0.9.0"); const forcedLookup = cache.get("0.9.0", { force: true }); if (completionOrder === "forced-first") { forced.resolve("2.0.0"); await expect(forcedLookup).resolves.toMatchObject({ latestVersion: "2.0.0" }); regular.resolve("1.0.0"); await expect(regularLookup).resolves.toMatchObject({ latestVersion: "1.0.0" }); } else { regular.resolve("1.0.0"); await expect(regularLookup).resolves.toMatchObject({ latestVersion: "1.0.0" }); forced.resolve("2.0.0"); await expect(forcedLookup).resolves.toMatchObject({ latestVersion: "2.0.0" }); } await expect(cache.get("0.9.0")).resolves.toMatchObject({ latestVersion: "2.0.0" }); expect(load).toHaveBeenCalledTimes(2); }); it("makes regular callers join a pending forced lookup", async () => { const forced = createDeferred(); const load = vi.fn(() => forced.promise); const cache = createPiWebReleaseLookupCache(load); const forcedLookup = cache.get("0.9.0", { force: true }); const regularLookup = cache.get("0.9.0"); expect(regularLookup).toBe(forcedLookup); forced.resolve("2.0.0"); await expect(regularLookup).resolves.toMatchObject({ latestVersion: "2.0.0" }); expect(load).toHaveBeenCalledOnce(); }); }); function createDeferred(): { promise: Promise; resolve: (value: T) => void } { let resolve: (value: T) => void = () => undefined; const promise = new Promise((innerResolve) => { resolve = innerResolve; }); return { promise, resolve }; }