import { describe, expect, it } from "vitest"; import { CHIP_PER_XP, CHIP_TOP_UP_COOLDOWN_MS, CHIP_TOP_UP_THRESHOLD, chipTopUpState, chipsForXp, } from "@/lib/minigames/chips"; describe("chipsForXp", () => { it("converts XP to chips at the fixed rate", () => { expect(CHIP_PER_XP).toBe(10); expect(chipsForXp(1)).toBe(10); expect(chipsForXp(5)).toBe(50); expect(chipsForXp(50)).toBe(500); }); it("rounds fractional XP to whole chips", () => { expect(chipsForXp(0.5)).toBe(5); expect(chipsForXp(1.25)).toBe(13); }); it("never returns negative chips", () => { expect(chipsForXp(0)).toBe(0); expect(chipsForXp(-3)).toBe(0); expect(chipsForXp(Number.NaN)).toBe(0); expect(chipsForXp(Number.POSITIVE_INFINITY)).toBe(0); }); }); describe("chipTopUpState", () => { const NOW = 1_700_000_000_000; it("is claimable for a first-time broke player (no refill timestamp)", () => { const state = chipTopUpState(0, null, NOW); expect(state.topUpAvailable).toBe(true); expect(state.nextTopUpAt).toBeNull(); }); it("is not claimable while the pool holds the threshold or more", () => { expect(chipTopUpState(CHIP_TOP_UP_THRESHOLD, null, NOW).topUpAvailable).toBe(false); expect(chipTopUpState(1500, null, NOW).topUpAvailable).toBe(false); }); it("is claimable below the threshold even with a stale refill", () => { const stale = new Date(NOW - CHIP_TOP_UP_COOLDOWN_MS - 1).toISOString(); const state = chipTopUpState(499, stale, NOW); expect(state.topUpAvailable).toBe(true); expect(state.nextTopUpAt).toBeNull(); }); it("is locked during the cooldown window and reports when it unlocks", () => { const recent = new Date(NOW - 60_000).toISOString(); const state = chipTopUpState(0, recent, NOW); expect(state.topUpAvailable).toBe(false); expect(state.nextTopUpAt).toBe(new Date(NOW - 60_000 + CHIP_TOP_UP_COOLDOWN_MS).toISOString()); }); it("unlocks the moment the cooldown expires", () => { const boundary = new Date(NOW - CHIP_TOP_UP_COOLDOWN_MS).toISOString(); expect(chipTopUpState(0, boundary, NOW).topUpAvailable).toBe(true); }); it("treats an unparseable refill timestamp as never refilled", () => { const state = chipTopUpState(0, "not-a-date", NOW); expect(state.topUpAvailable).toBe(true); expect(state.nextTopUpAt).toBeNull(); }); });