diff --git a/docs/agents/task-logs/daily/2026-02-14_04-49-55_ci-health-agent_completed.md b/docs/agents/task-logs/daily/2026-02-14_04-49-55_ci-health-agent_completed.md new file mode 100644 index 00000000..12a48fe1 --- /dev/null +++ b/docs/agents/task-logs/daily/2026-02-14_04-49-55_ci-health-agent_completed.md @@ -0,0 +1,25 @@ +# CI Health Agent - Daily Run + +**Date:** 2026-02-14 +**Agent:** ci-health-agent +**Status:** Completed + +## Summary + +Identified and fixed test pollution risks in unit tests that mocked global objects (`global.document` and `global.window`) without guaranteed cleanup. + +## Changes + +1. **Refactored `tests/nostr/videoEventBuffer.test.mjs`**: Wrapped `global.document` mocking in a `try...finally` block to ensure restoration even if assertions fail. +2. **Refactored `tests/ui/engagement-controller.test.mjs`**: Wrapped `global.window` mocking in a `try...finally` block to ensure deletion even if assertions fail. + +## Verification + +Ran the affected tests locally to ensure they pass: +- `tests/nostr/videoEventBuffer.test.mjs`: Passed +- `tests/ui/engagement-controller.test.mjs`: Passed + +## Learnings + +- Tests running in the same process (even sequentially) can pollute global state (`window`, `document`) if not cleaned up properly. +- `try...finally` is crucial when mocking globals in tests. diff --git a/tests/nostr/videoEventBuffer.test.mjs b/tests/nostr/videoEventBuffer.test.mjs index 0cbe0000..638ee820 100644 --- a/tests/nostr/videoEventBuffer.test.mjs +++ b/tests/nostr/videoEventBuffer.test.mjs @@ -156,38 +156,40 @@ test('VideoEventBuffer', async (t) => { // Mock document const originalDocument = global.document; let visibilityHandler = null; - global.document = { - hidden: true, - addEventListener: (type, handler) => { - if (type === 'visibilitychange') visibilityHandler = handler; - }, - removeEventListener: () => {} - }; + try { + global.document = { + hidden: true, + addEventListener: (type, handler) => { + if (type === 'visibilitychange') visibilityHandler = handler; + }, + removeEventListener: () => {} + }; - const client = new MockClient(); - let onVideoCalls = []; - const onVideo = (videos) => onVideoCalls.push(videos); - const buffer = new VideoEventBuffer(client, onVideo); + const client = new MockClient(); + let onVideoCalls = []; + const onVideo = (videos) => onVideoCalls.push(videos); + const buffer = new VideoEventBuffer(client, onVideo); - // Push event while hidden - buffer.push(validEvent); - buffer.scheduleFlush(true); + // Push event while hidden + buffer.push(validEvent); + buffer.scheduleFlush(true); - // Should NOT have called onVideo yet - assert.equal(onVideoCalls.length, 0); - // Should have buffered pending videos - assert.equal(buffer.pendingVideos.length, 1); + // Should NOT have called onVideo yet + assert.equal(onVideoCalls.length, 0); + // Should have buffered pending videos + assert.equal(buffer.pendingVideos.length, 1); - // Simulate visibility change - global.document.hidden = false; - assert.ok(visibilityHandler, "Listener attached"); - visibilityHandler(); + // Simulate visibility change + global.document.hidden = false; + assert.ok(visibilityHandler, "Listener attached"); + visibilityHandler(); - // Should flush now - assert.equal(onVideoCalls.length, 1); - assert.equal(buffer.pendingVideos.length, 0); - - // Cleanup mock - global.document = originalDocument; + // Should flush now + assert.equal(onVideoCalls.length, 1); + assert.equal(buffer.pendingVideos.length, 0); + } finally { + // Cleanup mock + global.document = originalDocument; + } }); }); diff --git a/tests/ui/engagement-controller.test.mjs b/tests/ui/engagement-controller.test.mjs index ca825fe2..7cbb1a39 100644 --- a/tests/ui/engagement-controller.test.mjs +++ b/tests/ui/engagement-controller.test.mjs @@ -127,14 +127,16 @@ test("EngagementController", async (t) => { const eventId = "test-event-id"; mockNostrClient.rebroadcastEvent.mock.mockImplementation(async () => ({ throttled: true, cooldown: { remainingMs: 5000 } })); - global.window = { setTimeout: t.mock.fn() }; + try { + global.window = { setTimeout: t.mock.fn() }; - await controller.handleEnsurePresenceAction({ eventId }); + await controller.handleEnsurePresenceAction({ eventId }); - assert.equal(mockShowStatus.mock.calls.length, 1); - assert.match(mockShowStatus.mock.calls[0].arguments[0], /Rebroadcast is cooling down/); - - delete global.window; + assert.equal(mockShowStatus.mock.calls.length, 1); + assert.match(mockShowStatus.mock.calls[0].arguments[0], /Rebroadcast is cooling down/); + } finally { + delete global.window; + } }); await t.test("handleEnsurePresenceAction - should show success on successful rebroadcast", async () => {