Skip to content

test: cover usage-summary.mjs - #14

Merged
ZhenghuaBao merged 1 commit into
mainfrom
test/usage-summary-coverage
Aug 19, 2026
Merged

test: cover usage-summary.mjs#14
ZhenghuaBao merged 1 commit into
mainfrom
test/usage-summary-coverage

Conversation

@ZhenghuaBao

Copy link
Copy Markdown
Contributor

scripts/usage-summary.mjs shipped without any tests, so the metering and cost path had no coverage. This adds 27 tests.

What is covered

Aggregation - grouping by model, zero-defaults for missing fields, the (unknown) bucket, blocked counting only status >= 400, retry summing, and cache_hit_rate: null when there are no prompt tokens.

Best-effort I/O - blank lines are skipped without being counted as malformed; a malformed line is counted and skipped but still exits 0; an unreadable price list degrades to tokens-only; a missing file argument is the only exit-2 path.

Price-list resolution - exact key, vendor-prefix drop, case-insensitive basename, dated-snapshot (-YYYY-MM-DD) and release-channel (-preview/-latest/-stable) suffix stripping, and an ambiguous basename staying unpriced rather than guessed.

Cost math - ratio 1 == $2.00/1M input, completion_ratio applied to output only, the cache_ratio discount, and the case that costs real money to get wrong: a price entry with no cache_ratio bills cached tokens at the full input rate, so an identical token count costs double.

Notes

  • Uses spawnSync rather than the async spawn in report.test.mjs. That file needs an async spawn because its mock control plane runs in the test process; this script talks to no network, so the event loop does not need to stay live.
  • Tests pass the usage file before --pricing, which is the documented argument order.

Separate issue found while writing these

Argument order is not handled: the file is picked as the first argv entry not starting with --, so putting the flag first makes the pricing file get read as the usage file, silently and with no error.

node usage-summary.mjs --pricing pricing.json usage.jsonl --json
  -> prompt_tokens: 0

Not fixed here to keep this PR test-only.

🤖 Generated with Claude Code

usage-summary.mjs shipped without tests, so the metering/cost path had no
coverage at all. 27 tests across four areas:

- aggregation: grouping by model, zero-defaults for missing fields, the
  "(unknown)" model bucket, blocked = status >= 400, retry summing.
- best-effort I/O: blank vs malformed lines, unreadable price list degrading
  to tokens-only, and a missing file argument as the only exit-2 path.
- price-list resolution: exact key, vendor-prefix drop, case-insensitive
  basename, dated-snapshot and release-channel suffix stripping, and an
  ambiguous basename staying unpriced rather than guessed.
- cost math: ratio 1 == $2.00/1M input, completion_ratio on output only,
  cache_ratio discount, and the case that costs real money to get wrong --
  a price entry with no cache_ratio bills cached tokens at the FULL input
  rate, so identical token counts cost double.

Uses spawnSync rather than the async spawn in report.test.mjs: this script
talks to no network, so the test event loop does not need to stay live.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ZhenghuaBao
ZhenghuaBao merged commit 8e96c09 into main Aug 19, 2026
2 checks passed
@ZhenghuaBao
ZhenghuaBao deleted the test/usage-summary-coverage branch August 19, 2026 02:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant