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 }); });});
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 });
});
});