diff --git a/docs/plans/state.json b/docs/plans/state.json index 0a20a76..bb06294 100644 --- a/docs/plans/state.json +++ b/docs/plans/state.json @@ -832,6 +832,17 @@ ], "test_status": "pnpm test:run src/companion/runtimeClient.test.ts src/companion/platformClients.test.ts src/companion/heartbeatLoop.test.ts src/companion/platformClients.integration.test.ts + pnpm typecheck passing" }, + "companion-heartbeat-loop-restart-state-reset-coverage": { + "status": "completed", + "date": "2026-02-17", + "updated": "2026-02-17", + "summary": "Added restart regression coverage for `CompanionHeartbeatLoop` to verify success/failure counters and timestamps are reset deterministically on restart.", + "files_modified": [ + "src/companion/heartbeatLoop.test.ts", + "docs/plans/state.json" + ], + "test_status": "pnpm test:run src/companion/heartbeatLoop.test.ts src/companion/platformClients.test.ts src/companion/runtimeClient.test.ts src/companion/platformClients.integration.test.ts + pnpm typecheck passing" + }, "browser-tools-activation-clarity": { "status": "completed", "date": "2026-02-17", diff --git a/src/companion/heartbeatLoop.test.ts b/src/companion/heartbeatLoop.test.ts index 57741b6..bcaa06b 100644 --- a/src/companion/heartbeatLoop.test.ts +++ b/src/companion/heartbeatLoop.test.ts @@ -234,4 +234,36 @@ describe('CompanionHeartbeatLoop', () => { loop.stop(); }); + + it('resets success and failure state when restarted', async () => { + const publishHeartbeat = vi + .fn<() => Promise>() + .mockResolvedValueOnce(buildStatusResult()) + .mockRejectedValueOnce(new Error('transient')) + .mockResolvedValue(buildStatusResult()); + const loop = new CompanionHeartbeatLoop({ publishHeartbeat }, { intervalMs: 500 }); + + loop.start(); + await Promise.resolve(); + expect(loop.successCount).toBe(1); + expect(loop.failureCount).toBe(0); + + await vi.advanceTimersByTimeAsync(500); + expect(loop.failureCount).toBe(1); + expect(loop.lastFailure?.message).toBe('transient'); + + loop.stop(); + loop.start(false); + + expect(loop.successCount).toBe(0); + expect(loop.lastSuccessAt).toBeNull(); + expect(loop.failureCount).toBe(0); + expect(loop.lastFailure).toBeNull(); + + await vi.advanceTimersByTimeAsync(500); + expect(loop.successCount).toBe(1); + expect(loop.failureCount).toBe(0); + + loop.stop(); + }); });