Summary
The test suite has significant coverage gaps across multiple modules. While the 52 existing tests are well-written and cover the happy paths thoroughly, several important edge cases, feature paths, and rendering scenarios are untested. Additionally, CI never runs with code coverage instrumentation, so the actual coverage percentage is unknown.
CI Gap: No coverage reporting
The package.json defines a test:coverage script:
"test:coverage": "node --experimental-test-coverage --test"
But .github/workflows/ci.yml:29 only runs:
- name: Unit tests
run: node --test
Coverage is never collected in CI, so there's no way to track coverage drift across PRs.
Missing Test Coverage by Module
plugins/tps/config.js (7 existing tests)
| Missing test |
Why important |
OPENCODE_TPS_METER_DISABLE="true" |
Only "1" is tested; "true" is documented as valid |
OPENCODE_TPS_METER="0" / "no" / "" |
Only "off" tested; other falsy values should also disable |
showSparkline, showSession, showWaits |
No env override support exists, but if added, needs tests |
Env var precedence: OPENCODE_TPS_METER=1 + OPENCODE_TPS_METER_DISABLE=true |
Both set — which wins? Undefined behavior |
plugins/tps/view.js (8 existing tests)
| Missing test |
Why important |
showSparkline: false rendering |
Sparkline is a key UI feature; its absence should be tested |
showWaits: false rendering |
Wait exclusion info should be omitted when disabled |
Custom icon, label, unit |
README documents these config options but no test verifies they render |
showTotals: true |
The totals line (session TPS, tokens, cost) is completely untested |
showCost: true |
Cost formatting in rendered view has zero test coverage |
showCache: true |
Cache info in rendered view has zero test coverage |
| Minimal detail + live streaming |
Existing "minimal" test passes live: undefined so sparkline conditional is false |
plugins/tps/gen.js (6 existing tests)
| Missing test |
Why important |
GenerationTimer.snapshot() |
Exists in source (gen.js:133-149) but zero tests call it |
push() with repeated same-timestamp chunks (gap = 0) |
Common in bursty streams; zero-gap handling is untested |
setTokens() then snapshot() |
Exact provider token counts should reflect in snapshot |
plugins/tps/meter.js (10 existing tests)
| Missing test |
Why important |
smooth() ramp-up from 0 |
The EWMA cold-start (issue #2) behavior — test would validate the fix |
push() with out-of-order timestamps |
Meter assumes monotonic timestamps but doesn't enforce |
elapsedSec() edge cases |
Very small or very large durations |
plugins/tps/tps.js (9 existing tests)
| Missing test |
Why important |
messageStats with primeTokens on active window |
Prime-corrected decode TPS path is untested |
aggregate with decodeSource: "active" |
Only end-to-end decodeSource messages tested |
calibrateRatio with custom alpha |
The alpha parameter exists but is never tested with non-default values |
calibrateRatio boundary: near MIN_RATIO / MAX_RATIO |
Clamping behavior is untested |
tests/integration.test.mjs (2 existing tests)
| Missing test |
Why important |
End-to-end with metric: "output" |
Only "generated" metric is tested in full pipeline |
End-to-end with showTotals: true and showCost: true |
The cost/totals rendering path is completely uncovered by integration tests |
End-to-end involving calibrateRatio |
The chars→tokens calibration pipeline has no integration coverage |
tests/format.test.mjs (10 existing tests)
| Missing test |
Why important |
fmtRate(999) — boundary at >= 100 |
Tests cover < 10, >= 10, >= 100 and >= 1000 but not exactly the boundary |
sparkline with custom empty option |
The empty parameter exists but is never tested |
fmtMs(60000) — boundary at exactly one minute |
Should render "1m00s" — edge case |
Suggested Fix
- Enable coverage in CI. Change
node --test to npm run test:coverage in ci.yml.
- Add the missing tests prioritized by risk:
- High:
showTotals/showCost view rendering (untested render path that users see)
- High:
primeTokens in messageStats (math bug potential)
- High:
GenerationTimer.snapshot() (public API, untested)
- Medium: Integration tests with calibration pipeline
- Medium: Format boundary values
- Low: View custom icon/label/unit
Summary
The test suite has significant coverage gaps across multiple modules. While the 52 existing tests are well-written and cover the happy paths thoroughly, several important edge cases, feature paths, and rendering scenarios are untested. Additionally, CI never runs with code coverage instrumentation, so the actual coverage percentage is unknown.
CI Gap: No coverage reporting
The
package.jsondefines atest:coveragescript:But
.github/workflows/ci.yml:29only runs:Coverage is never collected in CI, so there's no way to track coverage drift across PRs.
Missing Test Coverage by Module
plugins/tps/config.js(7 existing tests)OPENCODE_TPS_METER_DISABLE="true""1"is tested;"true"is documented as validOPENCODE_TPS_METER="0"/"no"/"""off"tested; other falsy values should also disableshowSparkline,showSession,showWaitsOPENCODE_TPS_METER=1+OPENCODE_TPS_METER_DISABLE=trueplugins/tps/view.js(8 existing tests)showSparkline: falserenderingshowWaits: falserenderingicon,label,unitshowTotals: trueshowCost: trueshowCache: truelive: undefinedso sparkline conditional is falseplugins/tps/gen.js(6 existing tests)GenerationTimer.snapshot()gen.js:133-149) but zero tests call itpush()with repeated same-timestamp chunks (gap = 0)setTokens()thensnapshot()plugins/tps/meter.js(10 existing tests)smooth()ramp-up from 0push()with out-of-order timestampselapsedSec()edge casesplugins/tps/tps.js(9 existing tests)messageStatswithprimeTokenson active windowaggregatewithdecodeSource: "active"decodeSourcemessages testedcalibrateRatiowith customalphacalibrateRatioboundary: nearMIN_RATIO/MAX_RATIOtests/integration.test.mjs(2 existing tests)metric: "output""generated"metric is tested in full pipelineshowTotals: trueandshowCost: truecalibrateRatiotests/format.test.mjs(10 existing tests)fmtRate(999)— boundary at>= 100< 10,>= 10,>= 100and>= 1000but not exactly the boundarysparklinewith customemptyoptionemptyparameter exists but is never testedfmtMs(60000)— boundary at exactly one minute"1m00s"— edge caseSuggested Fix
node --testtonpm run test:coverageinci.yml.showTotals/showCostview rendering (untested render path that users see)primeTokensin messageStats (math bug potential)GenerationTimer.snapshot()(public API, untested)