From 791449161fef8d989e3b7bbe5408074519f73981 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 23 Jun 2026 16:44:43 +0800 Subject: [PATCH] =?UTF-8?q?test(ai-review=20=E4=BD=BF=E7=94=A8=E9=87=8F):?= =?UTF-8?q?=20=E8=A3=9C=20quota/rate=20=E4=B8=8A=E9=99=90=E7=82=BA=200/?= =?UTF-8?q?=E8=B2=A0=E6=95=B8/Infinity/NaN=20=E8=88=87=E5=89=A9=E9=A4=98?= =?UTF-8?q?=E9=9D=9E=E6=9C=89=E9=99=90=E7=9A=84=E9=82=8A=E7=95=8C=E6=B8=AC?= =?UTF-8?q?=E8=A9=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/usage.test.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/app/usage.test.js b/app/usage.test.js index aa79008..21655fc 100644 --- a/app/usage.test.js +++ b/app/usage.test.js @@ -196,6 +196,25 @@ describe('resolveRemainingPercent', () => { assert.match(pct.reason, /無上限/); }); + it('returns null percent for non-finite or non-positive quota limits', () => { + for (const limit of [0, -5, Infinity, NaN, undefined]) { + const pct = resolveRemainingPercent({ available: true, used: 0, limit, remaining: limit, currency: 'USD' }, null); + assert.equal(pct.percent, null, `quota.limit=${limit} 應算不出百分比`); + } + }); + + it('returns null percent for non-finite or non-positive rate limits', () => { + for (const limit of [0, -1, Infinity, NaN]) { + const pct = resolveRemainingPercent({ available: false, reason: 'x' }, { hasData: true, remaining: limit, limit, kind: 'tokens' }); + assert.equal(pct.percent, null, `rate.limit=${limit} 應算不出百分比`); + } + }); + + it('returns null percent when limit is finite but remaining is non-finite', () => { + const pct = resolveRemainingPercent({ available: true, used: 0, limit: 100, remaining: Infinity, currency: 'USD' }, null); + assert.equal(pct.percent, null); + }); + it('does not divide by zero when quota.limit is 0', () => { const pct = resolveRemainingPercent({ available: true, used: 5, limit: 0, currency: 'USD' }, { hasData: false }); assert.equal(pct.percent, null); // limit > 0 守衛擋掉除以零 @@ -253,4 +272,21 @@ describe('formatUsageStatsLine', () => { assert.doesNotMatch(line, /NaN/); assert.match(line, /剩餘可用: 無法計算/); }); + + it('does not output Infinity/NaN/negative percent for invalid quota numbers', () => { + const ownUsage = { calls: 1, promptTokens: 1, completionTokens: 1, totalTokens: 2 }; + for (const limit of [Infinity, 0, -5, NaN]) { + const line = formatUsageStatsLine('openai', 'm', ownUsage, { available: true, used: 0, limit, remaining: limit, currency: 'USD' }, null); + assert.doesNotMatch(line, /NaN|Infinity|-\d+%/); + assert.match(line, /剩餘可用: 無法計算/); + } + }); + + it('falls back to a valid rate percent when only the quota limit is invalid', () => { + const ownUsage = { calls: 1, promptTokens: 1, completionTokens: 1, totalTokens: 2 }; + const line = formatUsageStatsLine('openai', 'm', ownUsage, + { available: true, used: 0, limit: Infinity, currency: 'USD' }, // quota 無效 + { hasData: true, remaining: 150000, limit: 200000, kind: 'tokens' }); // rate 有效 → 75% + assert.match(line, /剩餘可用: 75%(速率配額/); + }); });