import { describe, it, expect, beforeEach, vi } from "vitest"; const store: Record = {}; vi.stubGlobal("chrome", { storage: { local: { get: vi.fn(async (key: string) => ({ [key]: store[key] })), set: vi.fn(async (entries: Record) => { Object.assign(store, entries); }), }, }, }); const { claimProNudge, snoozeProNudge, silenceProNudge } = await import("./pro-nudge"); const DAY = 24 * 60 * 60 * 1000; const T0 = 1_800_000_000_000; describe("pro-nudge", () => { beforeEach(() => { Object.keys(store).forEach((k) => delete store[k]); }); it("does not show on first sight, only after a grace period", async () => { expect(await claimProNudge(T0)).toBe(false); expect(await claimProNudge(T0 + 13 * DAY)).toBe(false); expect(await claimProNudge(T0 + 14 * DAY)).toBe(true); }); it("shows at most once per cadence window even if never dismissed", async () => { await claimProNudge(T0); expect(await claimProNudge(T0 + 14 * DAY)).toBe(true); expect(await claimProNudge(T0 + 15 * DAY)).toBe(false); expect(await claimProNudge(T0 + 44 * DAY)).toBe(true); }); it("stays hidden for 90 days after snoozing", async () => { await claimProNudge(T0); await claimProNudge(T0 + 14 * DAY); await snoozeProNudge(T0 + 14 * DAY); expect(await claimProNudge(T0 + 103 * DAY)).toBe(false); expect(await claimProNudge(T0 + 104 * DAY)).toBe(true); }); it("never shows again after silencing", async () => { await claimProNudge(T0); await silenceProNudge(); expect(await claimProNudge(T0 + 10_000 * DAY)).toBe(false); }); it("treats unreadable storage as not due", async () => { vi.mocked(chrome.storage.local.get).mockRejectedValueOnce(new Error("unavailable")); expect(await claimProNudge(T0 + 1_000 * DAY)).toBe(false); }); });