mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-19 21:32:20 +03:00
* feat(usage): redeem GLM Coding Plan Reset Cards from Provider Limits z.ai sells Reset Cards that clear an exhausted GLM coding-plan window (5-hour or weekly) ahead of its natural rollover, but OmniRoute only ever read the passive nextResetTime, so redeeming one meant leaving the dashboard. Add the wire layer for z.ai's two reset endpoints (/api/biz/customer-package-reset/list and /use), which authenticate with the same Bearer API key as /api/monitor/usage/quota/limit and report failures inside an HTTP-200 envelope, so callers must inspect success/code rather than the status line. The banked count rides along with the quota poll - only for keys that actually report a resettable window, and strictly best-effort so a card-less account or a transient failure still renders its quotas. The existing reset-credit card, picker and confirmation flow, until now gated to Codex, now also drive glm/glm-cn/glmt/zai through the new /api/usage/glm-reset-card route, reusing z.ai's requestId as the idempotency key so a retry cannot burn two cards. * test(usage): cover GLM reset-card edge cases * test(dashboard): require GLM reset-card copy * fix(usage): harden GLM reset-card redemption * fix(usage): treat missing GLM key as empty * fix(usage): fence GLM reset-card operations and coalesce lease-window duplicates - Acquire a synthetic 60s exclusive-connection lease around each list/use wire operation; release in finally so a competing lease can acquire immediately after success or failure. - Coalesce same-key duplicates that arrive after lease acquisition by checking the in-flight attempt before loading the connection. - Run the post-commit quota refresh outside the lease (redemption is already committed; the refresh is auxiliary and failure-tolerant). - Do not discard a retained ambiguous attempt on a lease-conflict 409. - Harden transport error mapping: static messages for proxy transport failures, keep explicit direct routing for unproxied connections through list, use, and refresh. * fix(i18n): sync GLM reset-card keys to pt-BR and vi locales --------- Co-authored-by: insoln <is@careerum.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
543 lines
20 KiB
TypeScript
543 lines
20 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import path from "node:path";
|
|
|
|
const providerLimitUtils =
|
|
await import("../../src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx");
|
|
const providerConstants = await import("../../src/shared/constants/providers.ts");
|
|
const settingsSchemas = await import("../../src/shared/validation/settingsSchemas.ts");
|
|
const resetCreditModal =
|
|
await import("../../src/app/(dashboard)/dashboard/usage/components/ProviderLimits/CodexResetCreditsModal.tsx");
|
|
const resetCreditRedemption =
|
|
await import("../../src/app/(dashboard)/dashboard/usage/components/ProviderLimits/useCodexResetCreditRedemption.ts");
|
|
|
|
type ParsedQuota = {
|
|
name?: string;
|
|
isResetCredits?: boolean;
|
|
isCredits?: boolean;
|
|
creditCount?: number;
|
|
};
|
|
|
|
test("provider plan fallbacks normalize to Unknown instead of repeating provider labels", () => {
|
|
const tier = providerLimitUtils.normalizePlanTier("Claude Code");
|
|
|
|
assert.equal(tier.key, "unknown");
|
|
assert.equal(tier.label, "Unknown");
|
|
});
|
|
|
|
test("tier token matching avoids substring false positives", () => {
|
|
assert.equal(providerLimitUtils.normalizePlanTier("MiniMax").key, "unknown");
|
|
assert.equal(providerLimitUtils.normalizePlanTier("APPROVE").key, "unknown");
|
|
assert.equal(providerLimitUtils.normalizePlanTier("Max").key, "ultra");
|
|
assert.equal(providerLimitUtils.normalizePlanTier("Pro").key, "pro");
|
|
});
|
|
|
|
test("paid individual tiers use non-gray badge variants", () => {
|
|
assert.equal(providerLimitUtils.normalizePlanTier("Plus").variant, "success");
|
|
assert.equal(providerLimitUtils.normalizePlanTier("Pro").variant, "success");
|
|
assert.equal(providerLimitUtils.normalizePlanTier("Student").variant, "success");
|
|
assert.equal(providerLimitUtils.normalizePlanTier("Lite").key, "lite");
|
|
assert.equal(providerLimitUtils.normalizePlanTier("Lite").label, "Lite");
|
|
assert.notEqual(providerLimitUtils.normalizePlanTier("Lite").variant, "default");
|
|
assert.equal(providerLimitUtils.normalizePlanTier("Free").variant, "default");
|
|
});
|
|
|
|
test("Codex workspacePlanType is used when live plan is missing or unknown", () => {
|
|
const resolvedPlan = providerLimitUtils.resolvePlanValue("unknown", {
|
|
workspacePlanType: "plus",
|
|
});
|
|
|
|
assert.equal(resolvedPlan, "plus");
|
|
const tier = providerLimitUtils.normalizePlanTier(resolvedPlan);
|
|
assert.equal(tier.key, "plus");
|
|
assert.equal(tier.variant, "success");
|
|
});
|
|
|
|
test("Claude providerSpecificData plan is used when live plan is missing", () => {
|
|
const resolvedPlan = providerLimitUtils.resolvePlanValue(null, {
|
|
plan: "Pro",
|
|
});
|
|
|
|
assert.equal(resolvedPlan, "Pro");
|
|
const tier = providerLimitUtils.normalizePlanTier(resolvedPlan);
|
|
assert.equal(tier.key, "pro");
|
|
assert.equal(tier.variant, "success");
|
|
});
|
|
|
|
test("Claude bootstrap rate_limit_tier maps default_claude_max_20x to Max 20x", () => {
|
|
const resolvedPlan = providerLimitUtils.resolvePlanValue(null, {
|
|
organizationType: "default_claude_ai",
|
|
organizationRateLimitTier: "default_claude_max_20x",
|
|
});
|
|
|
|
assert.equal(resolvedPlan, "default_claude_max_20x");
|
|
const tier = providerLimitUtils.normalizePlanTier(resolvedPlan);
|
|
assert.equal(tier.key, "ultra");
|
|
assert.equal(tier.label, "Max 20x");
|
|
});
|
|
|
|
test("Claude organization_type default_claude_ai is ignored without rate_limit_tier", () => {
|
|
const resolvedPlan = providerLimitUtils.resolvePlanValue("Claude Code", {
|
|
organizationType: "default_claude_ai",
|
|
});
|
|
|
|
assert.equal(resolvedPlan, null);
|
|
const tier = providerLimitUtils.normalizePlanTier(resolvedPlan);
|
|
assert.equal(tier.label, "Unknown");
|
|
});
|
|
|
|
test("MiniMax coding plan titles map to tier badges", () => {
|
|
const proTier = providerLimitUtils.normalizePlanTier("MiniMax Coding Plan Pro");
|
|
assert.equal(proTier.key, "pro");
|
|
assert.equal(proTier.label, "Pro");
|
|
|
|
const starterTier = providerLimitUtils.normalizePlanTier("Starter");
|
|
assert.equal(starterTier.key, "lite");
|
|
assert.equal(starterTier.label, "Starter");
|
|
|
|
const minimaxOnly = providerLimitUtils.normalizePlanTier("MiniMax Coding Plan");
|
|
assert.notEqual(minimaxOnly.key, "ultra");
|
|
});
|
|
|
|
test("tier token matching ignores embedded substrings", () => {
|
|
assert.equal(providerLimitUtils.normalizePlanTier("APPROVE").key, "unknown");
|
|
assert.equal(providerLimitUtils.normalizePlanTier("LITERAL").key, "unknown");
|
|
});
|
|
|
|
test("remaining percentage helpers reflect remaining quota and stale resets refill to 100", () => {
|
|
assert.equal(providerLimitUtils.calculatePercentage(0, 100), 100);
|
|
assert.equal(providerLimitUtils.calculatePercentage(17, 100), 83);
|
|
assert.equal(providerLimitUtils.calculatePercentage(60, 100), 40);
|
|
|
|
const past = new Date(Date.now() - 60_000).toISOString();
|
|
const parsed = providerLimitUtils.parseQuotaData("codex", {
|
|
quotas: {
|
|
session: { used: 83, total: 100, resetAt: past },
|
|
},
|
|
});
|
|
|
|
assert.equal(parsed.length, 1);
|
|
assert.equal(providerLimitUtils.calculatePercentage(parsed[0].used, parsed[0].total), 100);
|
|
});
|
|
|
|
test("Codex quota rows use stable OpenAI Codex order with banked reset credits last", () => {
|
|
const parsed = providerLimitUtils.parseQuotaData("codex", {
|
|
bankedResetCredits: 2,
|
|
quotas: {
|
|
gpt_5_3_codex_spark_weekly: { used: 100, total: 100, remainingPercentage: 0 },
|
|
weekly: { used: 2, total: 100, remainingPercentage: 98 },
|
|
gpt_5_3_codex_spark_session: { used: 0, total: 100, remainingPercentage: 100 },
|
|
session: { used: 10, total: 100, remainingPercentage: 90 },
|
|
},
|
|
});
|
|
|
|
assert.deepEqual(
|
|
parsed.map((quota) => quota.name),
|
|
[
|
|
"session",
|
|
"weekly",
|
|
"gpt_5_3_codex_spark_session",
|
|
"gpt_5_3_codex_spark_weekly",
|
|
"banked_reset_credits",
|
|
]
|
|
);
|
|
assert.equal(providerLimitUtils.formatQuotaLabel(parsed[2].name), "GPT-5.3-Codex-Spark Session");
|
|
assert.equal(providerLimitUtils.formatQuotaLabel(parsed[4].name), "Banked Reset Credits");
|
|
});
|
|
|
|
test("percentage-only quotas hide redundant usage counts while counted quotas keep them", () => {
|
|
const codex = providerLimitUtils.parseQuotaData("codex", {
|
|
quotas: {
|
|
session: { used: 7, total: 100, remainingPercentage: 93 },
|
|
weekly: { used: 28, total: 100, remainingPercentage: 72 },
|
|
},
|
|
});
|
|
|
|
assert.equal(codex.length, 2);
|
|
assert.equal(codex[0].isPercentageOnly, true);
|
|
assert.equal(providerLimitUtils.shouldShowQuotaUsageCount(codex[0]), false);
|
|
assert.equal(providerLimitUtils.shouldShowQuotaUsageCount(codex[1]), false);
|
|
|
|
const counted = providerLimitUtils.parseQuotaData("kimi-coding", {
|
|
quotas: {
|
|
Weekly: {
|
|
used: 28,
|
|
total: 100,
|
|
remaining: 72,
|
|
remainingPercentage: 72,
|
|
},
|
|
},
|
|
});
|
|
|
|
assert.equal(counted.length, 1);
|
|
assert.equal(counted[0].isPercentageOnly, undefined);
|
|
assert.equal(providerLimitUtils.shouldShowQuotaUsageCount(counted[0]), true);
|
|
});
|
|
|
|
test("Firecrawl over-plan quota displays remaining credits against the plan baseline", () => {
|
|
const parsed = providerLimitUtils.parseQuotaData("firecrawl", {
|
|
quotas: {
|
|
monthly: {
|
|
used: 0,
|
|
total: 1000,
|
|
remaining: 1450,
|
|
remainingPercentage: 145,
|
|
extraCreditsInferred: 450,
|
|
overPlan: true,
|
|
},
|
|
},
|
|
});
|
|
|
|
assert.equal(parsed.length, 1);
|
|
assert.equal(parsed[0].used, 0);
|
|
assert.equal(parsed[0].total, 1000);
|
|
assert.equal(parsed[0].remaining, 1450);
|
|
assert.equal(providerLimitUtils.getQuotaRemainingPercentage(parsed[0]), 145);
|
|
assert.equal(parsed[0].extraCreditsInferred, 450);
|
|
assert.equal(parsed[0].overPlan, true);
|
|
assert.equal(providerLimitUtils.shouldShowQuotaUsageCount(parsed[0]), true);
|
|
});
|
|
|
|
test("Codex banked reset credits parse as an integer reset-credit counter", () => {
|
|
const parsed = providerLimitUtils.parseQuotaData("codex", {
|
|
quotas: {
|
|
session: { used: 7, total: 100, remainingPercentage: 93 },
|
|
},
|
|
bankedResetCredits: 2,
|
|
});
|
|
|
|
const resetCredits = (parsed as ParsedQuota[]).find(
|
|
(quota) => quota.name === "banked_reset_credits"
|
|
);
|
|
assert.ok(resetCredits);
|
|
assert.equal(resetCredits.isResetCredits, true);
|
|
assert.equal(resetCredits.isCredits, undefined);
|
|
assert.equal(resetCredits.creditCount, 2);
|
|
});
|
|
|
|
test("reset-credit modal uses provider-specific titles and confirmations", () => {
|
|
const tr = (_key: string, fallback: string) => fallback;
|
|
const upstreamTitle = { selectionToken: "card-1", title: "Bonus card" };
|
|
|
|
assert.equal(
|
|
resetCreditModal.getResetCreditWindowTitle("codex", upstreamTitle, tr),
|
|
"Bonus card"
|
|
);
|
|
assert.equal(
|
|
resetCreditModal.getResetCreditWindowTitle("glm", upstreamTitle, tr),
|
|
"5-hour window reset · Bonus card"
|
|
);
|
|
assert.equal(
|
|
resetCreditModal.getResetCreditWindowTitle("zai", { ...upstreamTitle, resetType: "WEEK" }, tr),
|
|
"Weekly window reset · Bonus card"
|
|
);
|
|
assert.match(
|
|
resetCreditModal.getResetCreditConfirmation("codex", undefined, tr),
|
|
/Codex usage windows/
|
|
);
|
|
assert.match(resetCreditModal.getResetCreditConfirmation("glm", "FIVE_HOUR", tr), /5-hour/);
|
|
assert.match(resetCreditModal.getResetCreditConfirmation("glm-cn", "WEEK", tr), /weekly/);
|
|
});
|
|
|
|
test("committed refresh fallback preserves usage windows and decrements only reset cards", () => {
|
|
const session = { name: "session", used: 50, total: 100 };
|
|
const entry = {
|
|
quotas: [
|
|
session,
|
|
{
|
|
name: "banked_reset_credits",
|
|
isResetCredits: true,
|
|
remaining: 2,
|
|
creditCount: 2,
|
|
},
|
|
],
|
|
raw: { bankedResetCredits: 2, quotas: { session } },
|
|
plan: "pro",
|
|
};
|
|
|
|
const decremented = resetCreditRedemption.applyCommittedResetCreditFallback(entry);
|
|
assert.deepEqual(decremented.quotas, [
|
|
session,
|
|
{
|
|
name: "banked_reset_credits",
|
|
isResetCredits: true,
|
|
remaining: 1,
|
|
creditCount: 1,
|
|
},
|
|
]);
|
|
assert.equal(decremented.raw.bankedResetCredits, 1);
|
|
assert.deepEqual(decremented.raw.quotas, entry.raw.quotas);
|
|
assert.equal(decremented.plan, "pro");
|
|
|
|
const exhausted = resetCreditRedemption.applyCommittedResetCreditFallback({
|
|
...entry,
|
|
quotas: [{ isResetCredits: true, remaining: 1, creditCount: 1 }],
|
|
raw: { ...entry.raw, bankedResetCredits: 1 },
|
|
});
|
|
assert.deepEqual(exhausted.quotas, []);
|
|
assert.equal(exhausted.raw.bankedResetCredits, 0);
|
|
});
|
|
|
|
test("quota labels normalize session and weekly windows while preserving readable titles", () => {
|
|
assert.equal(providerLimitUtils.formatQuotaLabel("session"), "Session");
|
|
assert.equal(providerLimitUtils.formatQuotaLabel("session (5h)"), "Session");
|
|
assert.equal(providerLimitUtils.formatQuotaLabel("weekly"), "Weekly");
|
|
assert.equal(providerLimitUtils.formatQuotaLabel("weekly (7d)"), "Weekly");
|
|
assert.equal(providerLimitUtils.formatQuotaLabel("weekly sonnet (7d)"), "Weekly Sonnet");
|
|
assert.equal(providerLimitUtils.formatQuotaLabel("code_review"), "Code Review");
|
|
assert.equal(providerLimitUtils.formatQuotaLabel("code_review_weekly"), "Code Review Weekly");
|
|
assert.equal(providerLimitUtils.formatQuotaLabel("mcp_monthly"), "Monthly");
|
|
});
|
|
|
|
test("MiniMax providers are exposed to the limits dashboard support list", () => {
|
|
assert.ok(providerConstants.USAGE_SUPPORTED_PROVIDERS.includes("zai"));
|
|
assert.ok(providerConstants.USAGE_SUPPORTED_PROVIDERS.includes("minimax"));
|
|
assert.ok(providerConstants.USAGE_SUPPORTED_PROVIDERS.includes("minimax-cn"));
|
|
});
|
|
|
|
test("OpenRouter and Devin CLI are exposed to the limits dashboard support list", () => {
|
|
assert.ok(providerConstants.USAGE_SUPPORTED_PROVIDERS.includes("openrouter"));
|
|
assert.ok(providerConstants.USAGE_SUPPORTED_PROVIDERS.includes("devin-cli"));
|
|
});
|
|
|
|
test("MiniMax quota payloads use generic provider parsing and stale resets still refill", () => {
|
|
const future = new Date(Date.now() + 5 * 60_000).toISOString();
|
|
const past = new Date(Date.now() - 5 * 60_000).toISOString();
|
|
|
|
const parsed = providerLimitUtils.parseQuotaData("minimax", {
|
|
quotas: {
|
|
"session (5h)": {
|
|
used: 400,
|
|
total: 1500,
|
|
remaining: 1100,
|
|
remainingPercentage: 73.3,
|
|
resetAt: future,
|
|
},
|
|
"weekly (7d)": {
|
|
used: 1200,
|
|
total: 15000,
|
|
remaining: 13800,
|
|
remainingPercentage: 92,
|
|
resetAt: past,
|
|
},
|
|
},
|
|
});
|
|
|
|
assert.equal(parsed.length, 2);
|
|
assert.equal(parsed[0].name, "session (5h)");
|
|
assert.equal(parsed[0].used, 400);
|
|
assert.equal(parsed[0].total, 1500);
|
|
assert.equal(parsed[1].name, "weekly (7d)");
|
|
assert.equal(parsed[1].used, 0);
|
|
assert.equal(parsed[1].remainingPercentage, 100);
|
|
assert.equal(providerLimitUtils.formatQuotaLabel(parsed[0].name), "Session");
|
|
assert.equal(providerLimitUtils.formatQuotaLabel(parsed[1].name), "Weekly");
|
|
});
|
|
|
|
test("GLM quota rows are ordered by session, weekly, monthly, then reset cards", () => {
|
|
for (const provider of ["glm", "glm-cn", "glmt", "zai"]) {
|
|
const parsed = providerLimitUtils.parseQuotaData(provider, {
|
|
bankedResetCredits: 2,
|
|
quotas: {
|
|
mcp_monthly: { used: 10, total: 100, remainingPercentage: 90 },
|
|
weekly: { used: 20, total: 100, remainingPercentage: 80 },
|
|
session: { used: 30, total: 100, remainingPercentage: 70 },
|
|
},
|
|
});
|
|
|
|
assert.deepEqual(
|
|
parsed.map((quota) => quota.name),
|
|
["session", "weekly", "mcp_monthly", "banked_reset_credits"],
|
|
`${provider} should use GLM family parsing`
|
|
);
|
|
assert.equal(parsed[3].creditCount, 2);
|
|
assert.equal(parsed[3].isResetCredits, true);
|
|
}
|
|
});
|
|
|
|
test("OpenRouter credits render as a USD credit count, not a percentage row", () => {
|
|
const parsed = providerLimitUtils.parseQuotaData("openrouter", {
|
|
quotas: {
|
|
free_daily: { used: 0, total: 50, remaining: 50, remainingPercentage: 100 },
|
|
free_rpm: { used: 0, total: 20, remaining: 20, remainingPercentage: 100 },
|
|
credits: {
|
|
used: 0,
|
|
total: 0,
|
|
remaining: 231.0973698130001,
|
|
remainingPercentage: 100,
|
|
unlimited: true,
|
|
currency: "USD",
|
|
},
|
|
},
|
|
});
|
|
|
|
const credits = parsed.find((quota) => quota.name === "credits");
|
|
assert.ok(credits, "credits row must survive parsing");
|
|
assert.equal(credits.isCredits, true, "dollar renderer requires isCredits");
|
|
assert.equal(credits.creditCount, 231.0973698130001);
|
|
assert.equal(credits.remaining, 231.0973698130001);
|
|
assert.equal(credits.currency, "USD");
|
|
assert.equal(providerLimitUtils.formatQuotaLabel(credits.name), "AI Credits");
|
|
// Free-tier windows keep the generic percentage treatment.
|
|
const freeDaily = parsed.find((quota) => quota.name === "free_daily");
|
|
assert.ok(freeDaily);
|
|
assert.notEqual(freeDaily.isCredits, true);
|
|
assert.equal(freeDaily.total, 50);
|
|
});
|
|
|
|
test("hidden provider models are filtered from per-model quota rows", () => {
|
|
const quotas = providerLimitUtils.parseQuotaData("antigravity", {
|
|
quotas: {
|
|
"gpt-oss-120b-medium": { used: 2, total: 100, remainingPercentage: 98 },
|
|
"gemini-3.5-pro": { used: 10, total: 100, remainingPercentage: 90 },
|
|
credits: { remaining: 42 },
|
|
},
|
|
});
|
|
const hidden = providerLimitUtils.collectHiddenQuotaModelIds("antigravity", {
|
|
models: [{ id: "antigravity/gpt-oss-120b-medium", isHidden: true }],
|
|
modelCompatOverrides: [{ id: "gemini-3.7-flash", isHidden: true }],
|
|
});
|
|
const visible = providerLimitUtils.filterHiddenModelQuotas("antigravity", quotas, hidden);
|
|
|
|
assert.deepEqual(
|
|
visible.map((quota) => quota.modelKey || quota.name),
|
|
["gemini-3.5-pro", "credits"]
|
|
);
|
|
});
|
|
|
|
test("hidden quota filtering keeps non-model provider quota rows", () => {
|
|
const quotas = [
|
|
{ name: "weekly", used: 2, total: 100 },
|
|
{ name: "credits", isCredits: true, remaining: 10 },
|
|
];
|
|
const hidden = providerLimitUtils.collectHiddenQuotaModelIds("antigravity", {
|
|
modelCompatOverrides: [{ id: "weekly", isHidden: true }],
|
|
});
|
|
|
|
assert.deepEqual(
|
|
providerLimitUtils.filterHiddenModelQuotas("antigravity", quotas, hidden),
|
|
quotas
|
|
);
|
|
});
|
|
|
|
test("dashboard i18n keys used by OrFallback helpers exist in en.json", () => {
|
|
const enPath = path.resolve("src/i18n/messages/en.json");
|
|
const messages = JSON.parse(readFileSync(enPath, "utf8"));
|
|
|
|
const required: Array<[string, string]> = [
|
|
["combos", "emailVisibilityHint"],
|
|
["combos", "configOnlyStatus"],
|
|
["settings", "codexFastTierTierLabel"],
|
|
["providers", "antigravityClientProfileLabel"],
|
|
["providers", "codexFastTierActiveChip"],
|
|
["cache", "loadingCacheAria"],
|
|
["costs", "legacyFreeLabel"],
|
|
["contextCaveman", "inputCompressionTitle"],
|
|
["contextCaveman", "inputCompressionDesc"],
|
|
["providers", "tierFast"],
|
|
];
|
|
|
|
for (const [ns, key] of required) {
|
|
const value = messages[ns]?.[key];
|
|
assert.equal(typeof value, "string", `${ns}.${key} should be defined in en.json`);
|
|
assert.ok(!value.startsWith("__MISSING__:"), `${ns}.${key} should not be a placeholder`);
|
|
}
|
|
});
|
|
|
|
test("usage namespace includes Provider Limits UI translation keys", () => {
|
|
const enPath = path.resolve("src/i18n/messages/en.json");
|
|
const messages = JSON.parse(readFileSync(enPath, "utf8"));
|
|
const usage = messages.usage;
|
|
|
|
for (const key of [
|
|
"statTotal",
|
|
"statCritical",
|
|
"statAlert",
|
|
"statHealthy",
|
|
"filterPurchaseTypeLabel",
|
|
"filterTierLabel",
|
|
"purchaseAll",
|
|
"purchaseOauthSub",
|
|
"purchaseOauthFree",
|
|
"purchaseApiKey",
|
|
"tierLite",
|
|
"resetsIn",
|
|
"editCutoffs",
|
|
"forceRefresh",
|
|
"resetCreditsLabel",
|
|
"redeemResetCredit",
|
|
"manageResetCredits",
|
|
"viewResetCredits",
|
|
"resetCreditsModalTitle",
|
|
"resetCreditsModalExplainer",
|
|
"resetCreditsLoadFailed",
|
|
"resetCreditsDetailsUnavailable",
|
|
"noResetCreditsAvailable",
|
|
"resetCreditDefaultTitle",
|
|
"resetCreditExpiresFirst",
|
|
"resetCreditExpiresAt",
|
|
"resetCreditNoExpiry",
|
|
"redeemThisResetCredit",
|
|
"confirmRedeemResetCreditTitle",
|
|
"confirmRedeemResetCredit",
|
|
"confirmRedeemResetCreditButton",
|
|
"resetCreditRedeemed",
|
|
"resetCreditRedeemFailed",
|
|
"glmResetCreditsModalTitle",
|
|
"glmResetCreditsModalExplainer",
|
|
"glmResetCreditFiveHourTitle",
|
|
"glmResetCreditWeekTitle",
|
|
"glmConfirmRedeemResetCredit",
|
|
"glmConfirmRedeemFiveHourResetCredit",
|
|
"glmConfirmRedeemWeekResetCredit",
|
|
]) {
|
|
assert.equal(typeof usage[key], "string", `usage.${key} should be defined in en.json`);
|
|
assert.ok(!usage[key].startsWith("__MISSING__:"), `usage.${key} should not be a placeholder`);
|
|
}
|
|
});
|
|
|
|
test("provider quota auto-refresh settings are accepted by the settings schema", () => {
|
|
const result = settingsSchemas.updateSettingsSchema.safeParse({
|
|
autoRefreshProviderQuota: true,
|
|
autoRefreshProviderQuotaInterval: 180,
|
|
});
|
|
|
|
assert.equal(result.success, true);
|
|
});
|
|
|
|
test("grok-cli banked reset credits parse as an integer reset-credit counter including zero", () => {
|
|
const parsed = providerLimitUtils.parseQuotaData("grok-cli", {
|
|
quotas: {
|
|
weekly: { used: 37.25, total: 100, remainingPercentage: 62.75, isPercentageOnly: true },
|
|
},
|
|
bankedResetCredits: 0,
|
|
}) as ParsedQuota[];
|
|
const resetCredits = parsed.find((quota) => quota.name === "banked_reset_credits");
|
|
assert.ok(resetCredits);
|
|
assert.equal(resetCredits.isResetCredits, true);
|
|
assert.equal(resetCredits.creditCount, 0);
|
|
});
|
|
|
|
test("grok-cli omits the reset-credit row when bankedResetCredits is absent", () => {
|
|
const parsed = providerLimitUtils.parseQuotaData("grok-cli", {
|
|
quotas: {
|
|
weekly: { used: 37.25, total: 100, remainingPercentage: 62.75 },
|
|
},
|
|
}) as ParsedQuota[];
|
|
assert.equal(
|
|
parsed.some((quota) => quota.name === "banked_reset_credits"),
|
|
false
|
|
);
|
|
});
|
|
|
|
test("grok-cli exposes the redeem button when banked reset credits are present", () => {
|
|
const parsed = providerLimitUtils.parseQuotaData("grok-cli", {
|
|
quotas: { weekly: { used: 0, total: 100, remainingPercentage: 100 } },
|
|
bankedResetCredits: 2,
|
|
});
|
|
assert.equal(providerLimitUtils.computeCanRedeemResetCredit("grok-cli", parsed), true);
|
|
assert.equal(providerLimitUtils.computeCanRedeemResetCredit("codex", parsed), true);
|
|
assert.equal(providerLimitUtils.computeCanRedeemResetCredit("claude", parsed), false);
|
|
});
|