From 16dc1827c94c0948809e90a350c439590732834f Mon Sep 17 00:00:00 2001 From: openhands Date: Wed, 25 Feb 2026 23:28:25 +0000 Subject: [PATCH] fix: Ponder: add test infrastructure + coverage for helpers (target 95%) (#287) - vitest.config.ts: add statements/functions/branches thresholds alongside lines so the coverage gate catches regressions in all four dimensions - tests/stats.test.ts: replace weak "> 0n" / "toBeDefined()" assertions with exact expected values derived from the ring buffer algebra: - hour-advanced path: mintedLastWeek=480n, mintedLastDay=220n, burnedLastWeek=240n, burnedLastDay=110n, mintNextHourProjected=68n, burnNextHourProjected=34n, netSupplyChangeDay=110n, netSupplyChangeWeek=240n - same-hour projection path: mintNextHourProjected=140n (elapsed-seconds scaling verified), burnNextHourProjected=0n (medium=0 fallback path) Co-Authored-By: Claude Sonnet 4.6 --- services/ponder/tests/stats.test.ts | 28 ++++++++++++++++++++-------- services/ponder/vitest.config.ts | 3 +++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/services/ponder/tests/stats.test.ts b/services/ponder/tests/stats.test.ts index 22009d5..4efa3dd 100644 --- a/services/ponder/tests/stats.test.ts +++ b/services/ponder/tests/stats.test.ts @@ -287,11 +287,20 @@ describe('updateHourlyData', () => { const dbMock = ctx as unknown as { db: { update: ReturnType } }; const setArg = (dbMock.db.update as ReturnType).mock.results[0].value.set.mock.calls[0][0]; - // mintedLastWeek and mintedLastDay should be positive - expect(setArg.mintedLastWeek).toBeGreaterThan(0n); - expect(setArg.mintedLastDay).toBeGreaterThan(0n); - expect(setArg.burnedLastWeek).toBeGreaterThan(0n); - expect(setArg.burnedLastDay).toBeGreaterThan(0n); + // After advancing 2 hours (new pointer=7), slots 6+7 are cleared (were already 0). + // Filled slots: i=2..49 from pointer=7 (48 slots × 10n minted / 5n burned). + // mintedLastDay: i<24 → i=2..23 = 22 slots × 10n = 220n + // mintedLastWeek: 48 × 10n = 480n + // mintNextHourProjected = mintedWeek / 7n = 480n / 7n = 68n (BigInt truncation) + // burnNextHourProjected = burnedWeek / 7n = 240n / 7n = 34n + expect(setArg.mintedLastWeek).toBe(480n); + expect(setArg.mintedLastDay).toBe(220n); + expect(setArg.burnedLastWeek).toBe(240n); + expect(setArg.burnedLastDay).toBe(110n); + expect(setArg.mintNextHourProjected).toBe(68n); + expect(setArg.burnNextHourProjected).toBe(34n); + expect(setArg.netSupplyChangeDay).toBe(110n); + expect(setArg.netSupplyChangeWeek).toBe(240n); }); it('carries forward holderCount into new ring buffer slots', async () => { @@ -333,9 +342,12 @@ describe('updateHourlyData', () => { const dbMock = ctx as unknown as { db: { update: ReturnType } }; expect(dbMock.db.update).toHaveBeenCalled(); const setArg = (dbMock.db.update as ReturnType).mock.results[0].value.set.mock.calls[0][0]; - // Projections should be computed - expect(setArg.mintNextHourProjected).toBeDefined(); - expect(setArg.burnNextHourProjected).toBeDefined(); + // elapsed = 1800s (30 min); current minted = 100n, prev minted = 80n + // projectedTotal = (100n * 3600n) / 1800n = 200n + // medium = (80n + 200n) / 2n = 140n → mintProjection = 140n + // burn: current=0n, prev=0n → medium=0n → fallback: mintedWeek/7 = 0n + expect(setArg.mintNextHourProjected).toBe(140n); + expect(setArg.burnNextHourProjected).toBe(0n); }); it('handles zero elapsedSeconds in projection (exact hour boundary)', async () => { diff --git a/services/ponder/vitest.config.ts b/services/ponder/vitest.config.ts index 7883db2..36c373c 100644 --- a/services/ponder/vitest.config.ts +++ b/services/ponder/vitest.config.ts @@ -14,6 +14,9 @@ export default defineConfig({ reporter: ['text', 'lcov'], thresholds: { lines: 95, + statements: 95, + functions: 95, + branches: 80, }, }, },