Files
diegosouzapw--omniroute/tests/unit/chatcore-codex-quota.test.ts
2026-07-13 13:39:12 +08:00

107 lines
4.5 KiB
TypeScript

// tests/unit/chatcore-codex-quota.test.ts
// Characterization of buildCodexQuotaPersistence — the pure core of handleChatCore's
// persistCodexQuotaState, extracted during the chatCore god-file decomposition (#3501). Locks the
// shape of the persisted providerSpecificData: the codexQuotaState snapshot, the existing-data
// passthrough, and the 429 dual-window exhaustion fields (codexScopeRateLimitedUntil /
// codexExhaustedWindow) plus the debug-log message. The handler keeps the DB write, the
// preflight-cache invalidation, and the log emission; this function only builds the data.
import { test } from "node:test";
import assert from "node:assert/strict";
import { buildCodexQuotaPersistence } from "../../open-sse/handlers/chatCore/codexQuota.ts";
import { getCodexModelScope } from "../../open-sse/executors/codex.ts";
const MODEL = "gpt-5-codex";
const ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
function quotaHeaders(over: Record<string, string> = {}) {
return {
"x-codex-5h-usage": "50",
"x-codex-5h-limit": "100",
"x-codex-5h-reset-at": "2999-01-01T00:00:00.000Z",
"x-codex-7d-usage": "10",
"x-codex-7d-limit": "100",
"x-codex-7d-reset-at": "2999-01-08T00:00:00.000Z",
...over,
};
}
test("returns null when the response carries no codex quota headers", () => {
assert.equal(
buildCodexQuotaPersistence({ headers: {}, existingProviderData: {}, modelForScope: MODEL, status: 200 }),
null
);
assert.equal(
buildCodexQuotaPersistence({ headers: { "content-type": "application/json" }, existingProviderData: {}, modelForScope: MODEL, status: 200 }),
null
);
});
test("builds codexQuotaState (parsed numbers + scope + updatedAt) and preserves existing provider data", () => {
const built = buildCodexQuotaPersistence({
headers: quotaHeaders(),
existingProviderData: { keepMe: "yes", apiKeyHealth: { primary: {} } },
modelForScope: MODEL,
status: 200,
});
assert.ok(built);
const qs = built.nextProviderData.codexQuotaState as Record<string, unknown>;
assert.equal(qs.usage5h, 50);
assert.equal(qs.limit5h, 100);
assert.equal(qs.usage7d, 10);
assert.equal(qs.limit7d, 100);
assert.equal(qs.scope, getCodexModelScope(MODEL));
assert.match(String(qs.updatedAt), ISO);
// existing keys passed through, not dropped
assert.equal(built.nextProviderData.keepMe, "yes");
assert.deepEqual(built.nextProviderData.apiKeyHealth, { primary: {} });
// non-429 → no exhaustion fields, no log
assert.equal(built.exhaustionLog, null);
assert.equal(built.nextProviderData.codexScopeRateLimitedUntil, undefined);
assert.equal(built.nextProviderData.codexExhaustedWindow, undefined);
});
test("429 with a near-exhausted 5h window records the per-scope cooldown + window + log", () => {
const built = buildCodexQuotaPersistence({
headers: quotaHeaders({ "x-codex-5h-usage": "100" }), // ratio 1.0 >= 0.95, reset far in the future
existingProviderData: {},
modelForScope: MODEL,
status: 429,
});
assert.ok(built);
assert.equal(built.nextProviderData.codexExhaustedWindow, "5h");
const scope = getCodexModelScope(MODEL);
const scopeMap = built.nextProviderData.codexScopeRateLimitedUntil as Record<string, string>;
assert.ok(scopeMap[scope]?.startsWith("2999-01-01T00:00:00"));
assert.match(
String(built.exhaustionLog),
/^Quota exhaustion on 5h window, cooldown until 2999-01-01T00:00:00/
);
});
test("429 merges into an existing codexScopeRateLimitedUntil map without dropping other scopes", () => {
const built = buildCodexQuotaPersistence({
headers: quotaHeaders({ "x-codex-5h-usage": "100" }),
existingProviderData: { codexScopeRateLimitedUntil: { "other-scope": "2999-12-31T00:00:00.000Z" } },
modelForScope: MODEL,
status: 429,
});
assert.ok(built);
const scopeMap = built.nextProviderData.codexScopeRateLimitedUntil as Record<string, string>;
assert.equal(scopeMap["other-scope"], "2999-12-31T00:00:00.000Z");
assert.ok(scopeMap[getCodexModelScope(MODEL)]);
});
test("429 below the exhaustion threshold builds the snapshot but no cooldown / no log", () => {
const built = buildCodexQuotaPersistence({
headers: quotaHeaders({ "x-codex-5h-usage": "1", "x-codex-7d-usage": "1" }), // ratios well under 0.95
existingProviderData: {},
modelForScope: MODEL,
status: 429,
});
assert.ok(built);
assert.ok(built.nextProviderData.codexQuotaState);
assert.equal(built.exhaustionLog, null);
assert.equal(built.nextProviderData.codexScopeRateLimitedUntil, undefined);
assert.equal(built.nextProviderData.codexExhaustedWindow, undefined);
});