From 50ded6b4dcbecd4420e147f6596d4842c35276e9 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 15 Feb 2026 20:18:30 +0000 Subject: [PATCH] feat(test-audit): run daily test audit and fix zero-assertion test - Run daily test audit using `test-audit-agent`. - Generate `test-audit-report-2026-02-15.md` with coverage and static analysis findings. - Fix zero-assertion test in `tests/minimal-channel-profile.test.mjs`. - Add audit scripts `scripts/agent/audit-coverage-map.js` and `scripts/agent/audit-static-analysis.sh`. - Log execution details in `test_logs/TEST_LOG_2026-02-15_20-00-00.md`. - Create completion log in `docs/agents/task-logs/daily/`. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- context/CONTEXT_2026-02-15_20-00-00.md | 14 ++ decisions/DECISIONS_2026-02-15_20-00-00.md | 3 + ...-15_20-19-15_test-audit-agent_completed.md | 24 ++ scripts/agent/audit-coverage-map.js | 35 +++ scripts/agent/audit-static-analysis.sh | 30 +++ test-audit-report-2026-02-15.md | 51 ++++ test-audit/coverage-gaps.json | 10 + test-audit/suspicious-tests.txt | 231 ++++++++++++++++++ test_logs/TEST_LOG_2026-02-15_20-00-00.md | 29 +++ tests/minimal-channel-profile.test.mjs | 6 +- todo/TODO_2026-02-15_20-00-00.md | 5 + 11 files changed, 435 insertions(+), 3 deletions(-) create mode 100644 context/CONTEXT_2026-02-15_20-00-00.md create mode 100644 decisions/DECISIONS_2026-02-15_20-00-00.md create mode 100644 docs/agents/task-logs/daily/2026-02-15_20-19-15_test-audit-agent_completed.md create mode 100644 scripts/agent/audit-coverage-map.js create mode 100644 scripts/agent/audit-static-analysis.sh create mode 100644 test-audit-report-2026-02-15.md create mode 100644 test-audit/coverage-gaps.json create mode 100644 test-audit/suspicious-tests.txt create mode 100644 test_logs/TEST_LOG_2026-02-15_20-00-00.md create mode 100644 todo/TODO_2026-02-15_20-00-00.md diff --git a/context/CONTEXT_2026-02-15_20-00-00.md b/context/CONTEXT_2026-02-15_20-00-00.md new file mode 100644 index 00000000..17326f69 --- /dev/null +++ b/context/CONTEXT_2026-02-15_20-00-00.md @@ -0,0 +1,14 @@ +# Context: Daily Test Audit + +**Goal**: Run a daily audit of the test suite to verify test quality, identify flakiness, and ensure critical paths are covered. + +**Scope**: +- Run unit tests with coverage. +- Detect flaky tests by re-running. +- Static analysis for anti-patterns. +- Generate a report. + +**Definition of Done**: +- `test-audit-report-YYYY-MM-DD.md` created. +- Logs saved in `test_logs/`. +- Artifacts in `test-audit/`. diff --git a/decisions/DECISIONS_2026-02-15_20-00-00.md b/decisions/DECISIONS_2026-02-15_20-00-00.md new file mode 100644 index 00000000..0bc954c6 --- /dev/null +++ b/decisions/DECISIONS_2026-02-15_20-00-00.md @@ -0,0 +1,3 @@ +# Decisions + +- Using `test-audit/` directory for temporary artifacts. diff --git a/docs/agents/task-logs/daily/2026-02-15_20-19-15_test-audit-agent_completed.md b/docs/agents/task-logs/daily/2026-02-15_20-19-15_test-audit-agent_completed.md new file mode 100644 index 00000000..9c8a6bab --- /dev/null +++ b/docs/agents/task-logs/daily/2026-02-15_20-19-15_test-audit-agent_completed.md @@ -0,0 +1,24 @@ +# Agent Completion Report: test-audit-agent + +**Date**: 2026-02-15 +**Agent**: test-audit-agent +**Status**: Success + +## Summary +Executed the daily test audit workflow. +- Discovered test runner: `node:test` via `scripts/run-unit-tests.mjs`. +- Ran tests with coverage (c8). +- Detected 0 failing or flaky tests (based on 3 runs). +- Performed static analysis and identified suspicious tests. +- Generated `test-audit-report-2026-02-15.md`. +- Applied a quick fix to `tests/minimal-channel-profile.test.mjs` (zero assertions). + +## Outputs +- `test-audit-report-2026-02-15.md` +- `test_logs/TEST_LOG_2026-02-15_20-00-00.md` +- `tests/minimal-channel-profile.test.mjs` (modified) +- `test-audit/` (artifacts) + +## Next Steps +- Implement coverage improvements for `js/userBlocks.js`. +- Refactor `setTimeout` usage in tests. diff --git a/scripts/agent/audit-coverage-map.js b/scripts/agent/audit-coverage-map.js new file mode 100644 index 00000000..86e39b59 --- /dev/null +++ b/scripts/agent/audit-coverage-map.js @@ -0,0 +1,35 @@ +import fs from 'fs'; +import path from 'path'; + +const criticalFiles = [ + 'js/services/authService.js', + 'js/relayManager.js', + 'js/nostr/dmDecryptWorker.js', + 'js/nostr/dmDecryptWorkerClient.js', + 'js/nostr/watchHistory.js', + 'js/userBlocks.js', + 'js/ui/ambientBackground.js', + 'torrent/app.js' +]; + +try { + const summary = JSON.parse(fs.readFileSync('test-audit/coverage/coverage-summary.json', 'utf8')); + const report = {}; + + for (const file of criticalFiles) { + // Find the file in the coverage summary keys (might be absolute paths) + const key = Object.keys(summary).find(k => k.endsWith(file)); + if (key) { + report[file] = summary[key].lines.pct; + } else { + report[file] = 0; // Not covered + } + } + + console.log("Critical Coverage Report:"); + console.log(JSON.stringify(report, null, 2)); + + fs.writeFileSync('test-audit/coverage-gaps.json', JSON.stringify(report, null, 2)); +} catch (e) { + console.error("Error processing coverage summary:", e); +} diff --git a/scripts/agent/audit-static-analysis.sh b/scripts/agent/audit-static-analysis.sh new file mode 100644 index 00000000..70683cfa --- /dev/null +++ b/scripts/agent/audit-static-analysis.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +OUTPUT="test-audit/suspicious-tests.txt" +echo "Suspicious Tests Report" > "$OUTPUT" +echo "=======================" >> "$OUTPUT" + +echo "" >> "$OUTPUT" +echo "## Tests with zero assertions (heuristic)" >> "$OUTPUT" +# Find test files +find tests -name "*.test.mjs" -o -name "*.test.js" | while read f; do + if ! grep -qE "assert\.|expect\(|t\.is" "$f"; then + echo " - $f" >> "$OUTPUT" + fi +done + +echo "" >> "$OUTPUT" +echo "## Tests using .only or .skip" >> "$OUTPUT" +grep -rE "\.(only|skip)\(" tests >> "$OUTPUT" + +echo "" >> "$OUTPUT" +echo "## Tests using setTimeout/sleep" >> "$OUTPUT" +grep -rE "setTimeout\(|sleep\(|await delay\(" tests >> "$OUTPUT" + +echo "" >> "$OUTPUT" +echo "## Tests using console logs" >> "$OUTPUT" +grep -rE "console\.(log|warn|error)" tests >> "$OUTPUT" + +echo "" >> "$OUTPUT" +echo "## Tests using real network (fetch/axios/WebSocket)" >> "$OUTPUT" +grep -rE "fetch\(|axios\.|new WebSocket" tests >> "$OUTPUT" diff --git a/test-audit-report-2026-02-15.md b/test-audit-report-2026-02-15.md new file mode 100644 index 00000000..cda5372a --- /dev/null +++ b/test-audit-report-2026-02-15.md @@ -0,0 +1,51 @@ +# Test Audit Report: 2026-02-15 + +## Summary +- **Date**: 2026-02-15 +- **Test Runner**: Node.js built-in runner (`node:test`) +- **Total Tests**: ~370 +- **Pass Rate**: 100% (based on available runs) +- **Coverage**: Mixed. Core services like `authService` are well covered (77%), but `userBlocks.js` (26%) and `relayManager.js` (50%) need attention. + +## Findings + +### 1. Suspicious Tests +The following tests were identified as suspicious due to having zero assertions or relying on anti-patterns: +- `tests/minimal-channel-profile.test.mjs`: Zero assertions (smoke test). +- `tests/ui/components/debug_hashtag_strip_helper.test.mjs`: Zero assertions. +- `tests/minimal-webtorrent.test.mjs`: Zero assertions. +- Heavy reliance on `setTimeout` and `sleep` in many tests (e.g., `tests/webtorrent-regression.test.mjs`, `tests/video-card-source-visibility.test.mjs`), which can lead to flakiness. + +### 2. Coverage Gaps (Critical Files) +| File | Coverage | Status | +|------|----------|--------| +| `js/userBlocks.js` | 25.86% | **CRITICAL** | +| `js/ui/ambientBackground.js` | 33.02% | High | +| `js/relayManager.js` | 49.93% | Medium | +| `js/nostr/watchHistory.js` | 58.14% | Medium | +| `js/services/authService.js` | 77.34% | Good | +| `js/nostr/dmDecryptWorkerClient.js` | 96.85% | Excellent | + +`js/userBlocks.js` implements critical moderation logic (blocking/muting) and its low coverage is a significant risk. It includes a custom Bech32 decoder which appears to be largely untested (or testing relies on `NostrTools` which bypasses it). + +### 3. Flakiness +No flaky tests were definitively identified in the sample runs, though the `setTimeout` usage suggests potential for future flakiness. + +## Remediation Plan + +### Immediate Actions +1. **Fix Zero Assertions**: Update `tests/minimal-channel-profile.test.mjs` to include explicit assertions. +2. **Coverage Improvements**: Plan to add tests for `js/userBlocks.js`, specifically targeting the internal Bech32 implementation and error handling paths. + +### Tickets / Issues +- **ISSUE-001**: Increase test coverage for `js/userBlocks.js`. + - **Context**: Current coverage is 25%. + - **Action**: Add tests for internal Bech32 decoder (by simulating missing `NostrTools`) and edge cases in encryption/decryption ordering. +- **ISSUE-002**: Refactor `setTimeout` usage in tests. + - **Context**: 50+ instances of `setTimeout` found. + - **Action**: Replace with deterministic `waitFor` helpers or mock timers. + +## Logs +- `test_logs/TEST_LOG_2026-02-15_20-00-00.md` +- `test-audit/suspicious-tests.txt` +- `test-audit/coverage-gaps.json` diff --git a/test-audit/coverage-gaps.json b/test-audit/coverage-gaps.json new file mode 100644 index 00000000..adb2f169 --- /dev/null +++ b/test-audit/coverage-gaps.json @@ -0,0 +1,10 @@ +{ + "js/services/authService.js": 77.34, + "js/relayManager.js": 49.93, + "js/nostr/dmDecryptWorker.js": 71.8, + "js/nostr/dmDecryptWorkerClient.js": 96.85, + "js/nostr/watchHistory.js": 58.14, + "js/userBlocks.js": 25.86, + "js/ui/ambientBackground.js": 33.02, + "torrent/app.js": 0 +} \ No newline at end of file diff --git a/test-audit/suspicious-tests.txt b/test-audit/suspicious-tests.txt new file mode 100644 index 00000000..9fef3bd4 --- /dev/null +++ b/test-audit/suspicious-tests.txt @@ -0,0 +1,231 @@ +Suspicious Tests Report +======================= + +## Tests with zero assertions (heuristic) + - tests/minimal-channel-profile.test.mjs + - tests/ui/components/debug_hashtag_strip_helper.test.mjs + - tests/minimal-webtorrent.test.mjs + +## Tests using .only or .skip +tests/nostr/sessionActor.test.mjs: t.skip("WebCrypto not available in this environment"); + +## Tests using setTimeout/sleep +tests/webtorrent-regression.test.mjs: setTimeout(() => { +tests/webtorrent-regression.test.mjs: setTimeout(() => { +tests/video-card-source-visibility.test.mjs: window.requestAnimationFrame = (cb) => setTimeout(() => cb(Date.now()), 16); +tests/video-card-source-visibility.test.mjs: window.requestAnimationFrame = (cb) => setTimeout(() => cb(Date.now()), 16); +tests/nostr-send-direct-message.test.mjs: setTimeout(() => process.exit(0), 100); +tests/nostr-send-direct-message.test.mjs: setTimeout(() => handler(), 0); +tests/view-counter.test.mjs:const flushPromises = () => new Promise((resolve) => setTimeout(resolve, 0)); +tests/view-counter.test.mjs: setTimeout(() => handler(), 0); +tests/subscriptions-manager.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/nostr/toolkit.test.mjs: setTimeout(() => { +tests/nostr/sign-request-queue.test.mjs:const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); +tests/nostr/sign-request-queue.test.mjs: await delay(50); +tests/nostr/sign-request-queue.test.mjs: await delay(100); +tests/nostr/integration-remote-flow.test.mjs: setTimeout(() => handler(), 0); +tests/nostr/dm-direct-message-flow.test.mjs: await new Promise((r) => setTimeout(r, intervalMs)); +tests/nostr/dm-direct-message-flow.test.mjs: await new Promise((resolve) => setTimeout(resolve, 100)); // Still wait to ensure no duplication appears +tests/nostr/dmSignalEvents.test.mjs: if (event === 'ok') setTimeout(cb, 0); +tests/nostr/client.test.mjs: await new Promise(r => setTimeout(r, 300)); +tests/nostr/client.test.mjs: if (evt === "eose") setTimeout(handler, 0); +tests/nostr/client.test.mjs: if (evt === "eose") setTimeout(handler, 0); +tests/nostr/nip07Permissions.test.js: setTimeout(() => { +tests/nostr/watchHistory.test.js: setTimeout(handler, 0); +tests/nostr/comment-events.test.mjs: await new Promise(resolve => setTimeout(resolve, 0)); +tests/torrent/toast-service.test.mjs: await new Promise((resolve) => setTimeout(resolve, 250)); +tests/hashtag-preferences.test.mjs: setTimeout(() => handler(), 0); +tests/hashtag-preferences.test.mjs: setTimeout(() => process.exit(0), 100); +tests/nostr-private-key-signer.test.mjs: setTimeout(() => process.exit(0), 100); +tests/e2e/webseed-playback.spec.ts: test.setTimeout(90000); // Increase timeout for fallback logic +tests/nwc-client.test.mjs: setTimeout(() => { +tests/nwc-client.test.mjs: setTimeout(() => { +tests/watchHistory/watch-history-telemetry.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/feed-engine.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/profile-cache.test.mjs: await new Promise((resolve) => setTimeout(resolve, 20)); +tests/profile-cache.test.mjs: await new Promise((resolve) => setTimeout(resolve, 20)); +tests/dm-normalization.test.mjs: await new Promise((resolve) => setTimeout(resolve, 50)); +tests/dm-normalization.test.mjs: setTimeout(() => process.exit(0), 100); +tests/webtorrent-handlers.test.mjs: setTimeout(() => { +tests/webtorrent-handlers.test.mjs: await new Promise(r => setTimeout(r, 20)); +tests/webtorrent-handlers.test.mjs: await new Promise(r => setTimeout(r, 20)); +tests/sign-request-queue.test.mjs: await new Promise((resolve) => setTimeout(resolve, 50)); +tests/sign-request-queue.test.mjs: await new Promise((resolve) => setTimeout(resolve, 50)); +tests/sign-request-queue.test.mjs: await new Promise((resolve) => setTimeout(resolve, 200)); +tests/moderation/video-card.test.mjs: window.requestAnimationFrame = (cb) => setTimeout(() => cb(Date.now()), 16); +tests/moderation/video-card.test.mjs: window.requestAnimationFrame = (cb) => setTimeout(() => cb(Date.now()), 16); +tests/moderation/video-card.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/moderation/video-card.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/moderation/video-card.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/moderation/video-card.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/moderation/submit-report.test.mjs: setTimeout(() => handler(), 0); +tests/race/nostr-client-init-race.test.mjs: await new Promise(resolve => setTimeout(resolve, 50)); +tests/modal-accessibility.test.mjs: setTimeout(() => callback(Date.now()), 0); +tests/zap-split.test.mjs: setTimeout(() => { +tests/profile-modal-controller.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/profile-modal-controller.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/profile-modal-controller.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/auth-service.test.mjs: await new Promise((resolve) => setTimeout(resolve, 10)); +tests/auth-service.test.mjs: await new Promise((resolve) => setTimeout(resolve, 10)); +tests/test-helpers/wait-for.mjs: await new Promise((resolve) => setTimeout(resolve, interval)); +tests/watch-history.test.mjs: setTimeout(() => { +tests/watch-history.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/watch-history.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/watch-history.test.mjs: await new Promise((resolve) => setTimeout(resolve, 0)); +tests/user-blocks.test.mjs:await new Promise((resolve) => setTimeout(resolve, 100)); +tests/user-blocks.test.mjs:await new Promise((resolve) => setTimeout(resolve, 100)); +tests/nostr-service-access-control.test.mjs: setTimeout(() => process.exit(0), 100); +tests/nostr-login-permissions.test.mjs: setTimeout(() => reject(new Error("permission denied")), 300); +tests/admin-list-store.test.mjs: setTimeout(fn, delay); +tests/admin-list-store.test.mjs:await new Promise((resolve) => setTimeout(resolve, slowRelayDelayMs + 20)); +tests/visual/overlay-layers.spec.ts: test.setTimeout(120_000); +tests/state/cache.test.mjs: await new Promise((resolve) => setTimeout(resolve, 10)); +tests/nip07-concurrency.test.mjs: await new Promise(resolve => setTimeout(resolve, delay)); +tests/nip07-concurrency.test.mjs: await new Promise(resolve => setTimeout(resolve, delay)); +tests/nostr-nip46-queue.test.mjs: await new Promise(r => setTimeout(r, 10)); +tests/nostr-nip46-queue.test.mjs: await new Promise(r => setTimeout(r, 50)); +tests/nostr-nip46-queue.test.mjs: await new Promise(r => setTimeout(r, 100)); +tests/ui/uploadModal-integration.test.mjs: await new Promise(r => setTimeout(r, 10)); +tests/ui/url-health-controller.test.mjs: await new Promise(resolve => setTimeout(resolve, 100)); +tests/ui/url-health-controller.test.mjs: setTimeout(handler, 10); +tests/ui/url-health-controller.test.mjs: setTimeout(handler, 10); +tests/ui/url-health-controller.test.mjs: setTimeout(handler, 0); +tests/ui/url-health-controller.test.mjs: await new Promise(resolve => setTimeout(resolve, 50)); +tests/compliance/nip07_compliance.test.mjs: await new Promise(resolve => setTimeout(resolve, 50)); +tests/unit/notificationController.test.mjs: setTimeout: mock.fn((cb, ms) => setTimeout(cb, ms)), +tests/unit/client-count-resilience.test.mjs: await new Promise(r => setTimeout(r, 100)); +tests/unit/ui/videoModalController.test.mjs: await new Promise(resolve => setTimeout(resolve, 0)); +tests/unit/ui/videoModalController.test.mjs: await new Promise(resolve => setTimeout(resolve, 0)); +tests/nostr-signer-race.test.mjs: await new Promise(resolve => setTimeout(resolve, 50)); +tests/embed_playback_check.spec.mjs: await new Promise(resolve => setTimeout(resolve, 2000)); +tests/comment-thread-service.test.mjs:const tick = (ms = 0) => new Promise((resolve) => setTimeout(resolve, ms)); +tests/services/link-preview-service.test.mjs: await new Promise((r) => setTimeout(r, 10)); +tests/services/trustBootstrap.test.mjs: setTimeout(() => { +tests/services/trustBootstrap.test.mjs: await new Promise(resolve => setTimeout(resolve, 300)); +tests/services/profileMetadataService.test.mjs: await new Promise(r => setTimeout(r, 0)); +tests/services/relay-health-service.test.mjs: setTimeout(() => relay.emit("connect"), 10); +tests/services/playbackService_forcedSource.test.mjs: await new Promise(resolve => setTimeout(resolve, 200)); +tests/services/playbackService_forcedSource.test.mjs: await new Promise(resolve => setTimeout(resolve, 200)); +tests/services/playbackService_forcedSource.test.mjs: await new Promise(resolve => setTimeout(resolve, 200)); + +## Tests using console logs +tests/subscriptions-feed.test.mjs:console.log("subscriptions-feed tests passed"); +tests/webtorrent-regression.test.mjs: console.log("Failed result:", result); +tests/video-modal-accessibility.test.mjs: console.warn("[tests] failed to reset runtime flags", error); +tests/video-modal-accessibility.test.mjs: console.warn( +tests/video-modal-accessibility.test.mjs: console.warn("[tests] app.destroy failed", error); +tests/video-modal-accessibility.test.mjs: console.warn("[tests] failed to reset runtime flags", error); +tests/nostr-publish-rejection.test.mjs: console.log("nostr publish rejection tests passed"); +tests/zap-shared-state.test.mjs:console.log("zap-shared-state tests passed"); +tests/view-counter.test.mjs: const originalWarn = console.warn; +tests/view-counter.test.mjs: console.warn = (...args) => { +tests/view-counter.test.mjs: console.warn = originalWarn; +tests/view-counter.test.mjs:console.log("View counter tests completed successfully."); +tests/nostr/countDiagnostics.test.mjs: // Mock console.warn +tests/nostr/countDiagnostics.test.mjs: originalConsoleWarn = console.warn; +tests/nostr/countDiagnostics.test.mjs: console.warn = (...args) => { +tests/nostr/countDiagnostics.test.mjs: console.warn = originalConsoleWarn; +tests/nostr/dmDecryptWorkerClient.test.mjs: originalConsoleWarn = console.warn; +tests/nostr/dmDecryptWorkerClient.test.mjs: // Set dev mode to true to ensure logger calls console.warn +tests/nostr/dmDecryptWorkerClient.test.mjs: console.warn = originalConsoleWarn; +tests/nostr/dmDecryptWorkerClient.test.mjs: console.warn = warnMock; +tests/nostr/nip04WorkerClient.test.mjs: if (console.warn.mock) console.warn.mock.restore(); +tests/watch-history-feed.test.mjs:console.log("watch-history-feed.test.mjs completed successfully."); +tests/e2e/repro_issue.spec.ts: console.log('PAGE ERROR:', err.message); +tests/e2e/repro_issue.spec.ts: console.log('Timeout waiting for status change. Current status:', await page.locator('#embedStatus').textContent()); +tests/e2e/repro_issue.spec.ts: console.error('Reproduced TypeError:', typeError); +tests/e2e/repro_issue.spec.ts: console.log('No TypeError found.'); +tests/e2e/repro_issue.spec.ts: console.log('Console output:', consoleMessages.join('\n')); +tests/e2e/video-modal-share-bug.spec.ts: console.log(\`setGlobalModalState: \${name} = \${isOpen}\`); +tests/e2e/webseed-playback.spec.ts: console.error('Test failed to load video list. Body content:', body.substring(0, 500)); +tests/app-batch-fetch-profiles.test.mjs: // console.log("pool.list called with relays:", relays); +tests/app-batch-fetch-profiles.test.mjs: // console.log("poolListCalls.length:", poolListCalls.length); +tests/app-batch-fetch-profiles.test.mjs: // console.log("nostrClient.relays:", nostrClient.relays); +tests/feed-engine.test.mjs:console.log("All feed engine tests passed"); +tests/utils/domUtils.test.mjs: inlineScript.textContent = "console.log('hello')"; +tests/utils/domUtils.test.mjs: assert.equal(container.querySelector("script").textContent, "console.log('hello')"); +tests/event-schemas.test.mjs: originalWarn = console.warn; +tests/event-schemas.test.mjs: console.warn = (...args) => { +tests/event-schemas.test.mjs: console.warn = originalWarn; +tests/nostr-rebroadcast-guard.test.mjs:console.log("nostr rebroadcast guard tests passed"); +tests/nostr-boost-actions.test.mjs:console.log("nostr boost action tests passed"); +tests/check_resize_observer.mjs: console.log("globalThis.ResizeObserver:", typeof globalThis.ResizeObserver); +tests/nostr-ephemeral-dm-tester.html: console.log(`[${type.toUpperCase()}] ${msg}`); +tests/nostr-ephemeral-dm-tester.html: console.error(err); +tests/zap-split.test.mjs:console.log("zap-split tests passed"); +tests/watch-history.test.mjs: console.log("Running normalizeActorKey short-circuit test..."); +tests/watch-history.test.mjs: const originalWarn = console.warn; +tests/watch-history.test.mjs: console.warn = (...args) => { +tests/watch-history.test.mjs: console.warn = originalWarn; +tests/watch-history.test.mjs: console.log("Running normalizeActorKey manual fallback test..."); +tests/watch-history.test.mjs: const originalWarn = console.warn; +tests/watch-history.test.mjs: console.warn = (...args) => { +tests/watch-history.test.mjs: console.warn = originalWarn; +tests/watch-history.test.mjs: console.warn("WARN: novEvent content is not JSON (likely encrypted), skipping payload assertions"); +tests/watch-history.test.mjs: console.log("Running watch history snapshot inflight queue retention test..."); +tests/watch-history.test.mjs: console.log("Running watch history snapshot merge test..."); +tests/watch-history.test.mjs: console.log("Running watch history card playback metadata test..."); +tests/watch-history.test.mjs: console.log("Running watch history stale cache refresh test..."); +tests/watch-history.test.mjs: console.log("Running watch history local fallback test..."); +tests/watch-history.test.mjs: console.log("Running watch history renderer feed registration fallback test..."); +tests/watch-history.test.mjs: console.log("Running watch history logged-in sync override test..."); +tests/watch-history.test.mjs: console.log("Running watch history app login fallback test..."); +tests/watch-history.test.mjs: console.log("Running watch history feed hydration test..."); +tests/watch-history.test.mjs:console.log("watch-history.test.mjs completed successfully"); +tests/discussion-count-service.test.mjs:console.log("discussion-count-service tests passed"); +tests/nostr-view-events.test.mjs:console.log("nostr view events tests passed"); +tests/admin-list-store.test.mjs:const originalConsoleWarn = console.warn; +tests/admin-list-store.test.mjs:console.warn = (...args) => { +tests/admin-list-store.test.mjs: console.warn = originalConsoleWarn; +tests/admin-list-store.test.mjs:console.log("admin-list-store tests passed"); +tests/nostr-count-fallback.test.mjs: const originalWarn = console.warn; +tests/nostr-count-fallback.test.mjs: console.warn = (...args) => { +tests/nostr-count-fallback.test.mjs: console.warn = originalWarn; +tests/nostr-count-fallback.test.mjs:console.log("nostr COUNT fallback tests completed successfully."); +tests/visual/moderation.spec.ts: page.on('console', msg => console.log('PAGE LOG:', msg.text())); +tests/visual/moderation.spec.ts: page.on('pageerror', err => console.log('PAGE ERROR:', err.message)); +tests/benchmark-explore-data.spec.mjs: console.log(`[Benchmark] buildWatchHistoryTagCounts: ${result.countsTime.toFixed(2)}ms`); +tests/benchmark-explore-data.spec.mjs: console.log(`[Benchmark] buildTagIdf: ${result.idfTime.toFixed(2)}ms`); +tests/benchmark-explore-data.spec.mjs: console.log(`[Benchmark] Counts Size: ${result.countsSize}`); +tests/benchmark-explore-data.spec.mjs: console.log(`[Benchmark] IDF Size: ${result.idfSize}`); +tests/nostr-view-event-bindings.test.mjs:console.log("nostr-view-event-bindings tests passed"); +tests/ui/components/debug_hashtag_strip_helper.test.mjs: console.log(`DEBUG: window.addEventListener('${event}') called`); +tests/ui/components/debug_hashtag_strip_helper.test.mjs: console.log("Global ResizeObserver type:", typeof globalThis.ResizeObserver); +tests/ui/components/debug_hashtag_strip_helper.test.mjs: console.log("Helper window ResizeObserver:", typeof helper.window.ResizeObserver); +tests/ui/uploadModal-reset.test.mjs: global.alert = (msg) => { console.log("ALERT CALLED:", msg); }; +tests/ui/profileModalController-addProfile.test.mjs: showSuccess: (msg) => { console.log("Success:", msg); }, +tests/ui/profileModalController-addProfile.test.mjs: showError: (msg) => { console.error("Error:", msg); }, +tests/performance/resolvePostedAt.test.mjs: console.log(`pool.list calls: ${listCalls}`); +tests/performance/resolvePostedAt.test.mjs: console.log(`pool.get calls: ${getCalls}`); +tests/embed_playback_check.spec.mjs: console.log('Starting reproduction script...'); +tests/embed_playback_check.spec.mjs: console.log(`Starting local relay on port ${relayPort}...`); +tests/embed_playback_check.spec.mjs: console.log(`Starting web server on port ${serverPort}...`); +tests/embed_playback_check.spec.mjs: console.log('Launching headless browser...'); +tests/embed_playback_check.spec.mjs: console.log(`[BROWSER CONSOLE] ${msg.type()}: ${msg.text()}`); +tests/embed_playback_check.spec.mjs: console.log('!!! CAUGHT EXPECTED ERROR IN CONSOLE !!!'); +tests/embed_playback_check.spec.mjs: console.log(`[BROWSER PAGEERROR] ${err.message}`); +tests/embed_playback_check.spec.mjs: console.log('!!! CAUGHT EXPECTED ERROR IN PAGEERROR !!!'); +tests/embed_playback_check.spec.mjs: console.log(`Navigating to ${baseUrl} to setup...`); +tests/embed_playback_check.spec.mjs: console.log(`Published video event: ${eventId}`); +tests/embed_playback_check.spec.mjs: console.log(`Navigating to embed: ${embedUrl}`); +tests/embed_playback_check.spec.mjs: console.log(`Response status: ${response.status()} ${response.statusText()}`); +tests/embed_playback_check.spec.mjs: console.log(`Response url: ${response.url()}`); +tests/embed_playback_check.spec.mjs: console.log(`Current Location: ${locationHref}`); +tests/embed_playback_check.spec.mjs: console.log('Waiting for error...'); +tests/embed_playback_check.spec.mjs: console.log(`Current Embed Status: "${statusText}"`); +tests/embed_playback_check.spec.mjs: console.error('FAILURE: TypeError still present.'); +tests/embed_playback_check.spec.mjs: console.log('SUCCESS: TypeError fixed (not found).'); +tests/embed_playback_check.spec.mjs: console.error('Test script error:', err); +tests/nostr-delete-flow.test.mjs:console.log("nostr delete flow tests passed"); +tests/comment-thread-service.test.mjs: console.error("Test encountered errors:", errorPayloads); +tests/services/link-preview-service.test.mjs: console.warn("[LinkPreviewService Test] Database deletion blocked"); +tests/services/exploreDataService.test.mjs: // Mock console.warn BEFORE import so logger.js captures the mock +tests/services/exploreDataService.test.mjs: // if console.warn is already mocked (e.g. by other tests? unlikely in isolated process), restore it first +tests/services/exploreDataService.test.mjs: if (console.warn.mock) console.warn.mock.restore(); + +## Tests using real network (fetch/axios/WebSocket) +tests/e2e/repro_issue.spec.ts: const ws = new WebSocket(RELAY_URL); +tests/e2e/agent-testability.spec.ts: const resp = await fetch(`${httpUrl}/events`); +tests/e2e/agent-testability.spec.ts: const resp = await fetch(`${httpUrl}/health`); +tests/e2e/helpers/bitvidTestFixture.ts: const resp = await fetch(`${httpUrl}/seed`, { +tests/e2e/helpers/bitvidTestFixture.ts: const resp = await fetch(`${httpUrl}/events`, { method: "DELETE" }); diff --git a/test_logs/TEST_LOG_2026-02-15_20-00-00.md b/test_logs/TEST_LOG_2026-02-15_20-00-00.md new file mode 100644 index 00000000..5c0cbe9b --- /dev/null +++ b/test_logs/TEST_LOG_2026-02-15_20-00-00.md @@ -0,0 +1,29 @@ +# Test Log: 2026-02-15 + +## Setup +- Created directories: `context`, `todo`, `decisions`, `test_logs`, `test-audit`. +- Detected test runner: `node:test` via `scripts/run-unit-tests.mjs`. + +## Execution +1. **Coverage Run**: + - Command: `npx c8 --reporter=text --reporter=json-summary --report-dir=test-audit/coverage node scripts/run-unit-tests.mjs` + - Output: `test-audit/coverage-run.log` + - Artifacts: `test-audit/coverage/coverage-summary.json` + +2. **Flakiness Check**: + - Command: `node scripts/run-unit-tests.mjs` (x2) + - Logs: `test-audit/flakiness-run-1.log`, `test-audit/flakiness-run-2.log` + - Result: No failures observed. + +3. **Static Analysis**: + - Script: `scripts/agent/audit-static-analysis.sh` + - Output: `test-audit/suspicious-tests.txt` + +4. **Coverage Mapping**: + - Script: `scripts/agent/audit-coverage-map.js` + - Output: `test-audit/coverage-gaps.json` + +## Results +- **Pass Rate**: 100% +- **Critical Gaps**: `js/userBlocks.js` (25%). +- **Suspicious**: 3 tests with zero assertions. diff --git a/tests/minimal-channel-profile.test.mjs b/tests/minimal-channel-profile.test.mjs index 7833c69b..9a10e19c 100644 --- a/tests/minimal-channel-profile.test.mjs +++ b/tests/minimal-channel-profile.test.mjs @@ -1,8 +1,8 @@ +import "./test-helpers/setup-localstorage.mjs"; import test from "node:test"; +import assert from "node:assert/strict"; import { renderChannelVideosFromList } from "../js/channelProfile.js"; test("can import channelProfile", () => { - if (typeof renderChannelVideosFromList !== "function") { - throw new Error("Import failed"); - } + assert.equal(typeof renderChannelVideosFromList, "function", "Import failed"); }); diff --git a/todo/TODO_2026-02-15_20-00-00.md b/todo/TODO_2026-02-15_20-00-00.md new file mode 100644 index 00000000..e156f20b --- /dev/null +++ b/todo/TODO_2026-02-15_20-00-00.md @@ -0,0 +1,5 @@ +- [ ] Discover test runner +- [ ] Run tests with coverage +- [ ] Run flakiness check (5x) +- [ ] Run static analysis +- [ ] Generate report