import { expect, test } from "bun:test"; import { defineEntitlements, defineMeter, definePacks } from "../src/index.ts"; test("resolves fallback entitlements and features", async () => { const entitlements = defineEntitlements({ plans: () => [ { code: "free", name: "Free", features: [], allowance: 10 }, { code: "pro", name: "Pro", features: ["schedule"], allowance: 100 }, ], subscriptionFor: async () => "pro", fallback: "free", }); expect(await entitlements.enabled("u1", "schedule")).toBe(true); expect(await entitlements.allowance("u1")).toBe(100); }); test("packs are immutable and selected only by code", () => { const packs = definePacks([{ code: "small", units: 100, label: "Small" }]); expect(packs.get("constructor")).toBeUndefined(); expect(packs.get("small")?.units).toBe(100); }); test("meter distinguishes refusals from storage faults", async () => { const meter = defineMeter({ store: { balance: async () => 5, reserve: async (_subject, units) => units <= 5, write: async () => { throw new Error("offline"); }, }, }); expect(await meter.reserve("u1", 6, "send")).toEqual({ ok: false, reason: "insufficient balance", }); expect(await meter.grant("u1", 5, "plan")).toEqual({ ok: false, reason: "offline", fault: true, }); }); test("adjust accepts signed non-zero amounts while other additions stay positive", async () => { const writes: number[] = []; const meter = defineMeter({ store: { balance: async () => 0, reserve: async () => true, write: async (_subject, units) => { writes.push(units); }, }, }); expect(await meter.adjust("u1", -25, "correction")).toEqual({ ok: true }); expect(await meter.adjust("u1", 10, "correction")).toEqual({ ok: true }); expect(await meter.adjust("u1", 0, "correction")).toEqual({ ok: false, reason: "units adjustment must be a non-zero whole number", }); expect(await meter.grant("u1", -1, "invalid")).toEqual({ ok: false, reason: "units must be a positive whole number", }); expect(writes).toEqual([-25, 10]); });