import * as CodexErrors from "effect-codex-app-server/errors"; import { describe, expect, it } from "vite-plus/test"; import { codexRateLimitsFailureMessage, codexRateLimitsToLimits, codexRateLimitsToUpdate, codexResetCreditsToContract, } from "./codexUsageLimits.ts"; const checkedAt = "2026-07-18T10:00:00.000Z"; describe("codexRateLimitsToLimits", () => { it("maps primary and secondary onto the session and weekly windows", () => { expect( codexRateLimitsToLimits({ checkedAt, snapshot: { planType: "plus", primary: { usedPercent: 12, resetsAt: 1_784_000_000, windowDurationMins: 300 }, secondary: { usedPercent: 47, resetsAt: 1_784_500_000, windowDurationMins: 10080 }, }, }), ).toEqual({ checkedAt, windows: [ { id: "primary", kind: "session", label: "Session", usedPercent: 12, windowDurationMins: 300, resetsAt: "2026-07-14T03:33:20.000Z", }, { id: "secondary", kind: "weekly", label: "Weekly", usedPercent: 47, windowDurationMins: 10080, resetsAt: "2026-07-19T22:26:40.000Z", }, ], }); }); it("treats a lone duration-less primary as monthly on Free and Go", () => { expect( codexRateLimitsToLimits({ checkedAt, snapshot: { planType: "free", primary: { usedPercent: 80, resetsAt: null } }, }).windows, ).toEqual([ { id: "primary", kind: "monthly", label: "Monthly", usedPercent: 80, windowDurationMins: 43_200, }, ]); }); }); describe("codexRateLimitsToUpdate", () => { it("carries only the windows the notification names", () => { expect( codexRateLimitsToUpdate({ secondary: { usedPercent: 51, windowDurationMins: 10080 }, }), ).toEqual({ windows: [ { id: "secondary", kind: "weekly", label: "Weekly", usedPercent: 51, windowDurationMins: 10080, }, ], }); expect(codexRateLimitsToUpdate({ planType: "plus" })).toBeUndefined(); }); }); describe("codexRateLimitsFailureMessage", () => { it("keeps the JSON-RPC code and nothing else from a request failure", () => { expect( codexRateLimitsFailureMessage( new CodexErrors.CodexAppServerRequestError({ code: -32603, errorMessage: "failed to fetch codex rate limits: GET https://chatgpt.com/backend-api/wham/usage failed: 401 Unauthorized", }), ), ).toBe("Codex could not read usage (JSON-RPC -32603)."); }); it("phrases a dead process differently from a bad answer", () => { expect( codexRateLimitsFailureMessage(new CodexErrors.CodexAppServerProcessExitedError({ code: 1 })), ).toBe("Codex exited before it could report usage."); }); }); describe("codexResetCreditsToContract", () => { it("counts available credits and reports the soonest expiry", () => { expect( codexResetCreditsToContract({ availableCount: 2, credits: [ { status: "available", expiresAt: 1_784_500_000 }, { status: "redeemed", expiresAt: 1_700_000_000 }, { status: "available", expiresAt: 1_784_000_000 }, ], }), ).toEqual({ availableCount: 2, nextExpiresAt: "2026-07-14T03:33:20.000Z" }); expect(codexResetCreditsToContract({ availableCount: 0 })).toEqual({ availableCount: 0 }); expect(codexResetCreditsToContract(null)).toBeUndefined(); }); it("rides along on the probe's limits", () => { expect( codexRateLimitsToLimits({ checkedAt, snapshot: { primary: { usedPercent: 5, windowDurationMins: 300 } }, resetCredits: { availableCount: 1 }, }).resetCredits, ).toEqual({ availableCount: 1 }); }); });