diff --git a/artifacts/todos.txt b/artifacts/todos.txt index 27ec812e..d9bba68f 100644 --- a/artifacts/todos.txt +++ b/artifacts/todos.txt @@ -4,8 +4,8 @@ docs/agents/prompts/daily/bitvid-audit-agent.md:110: - If automated, add a fol docs/agents/prompts/daily/bitvid-const-refactor-agent.md:30:- `todo/TODO_.md` — List of duplicated constants to canonicalize and status for each. docs/agents/prompts/daily/bitvid-content-audit-agent.md:32:- `todo/TODO_.md` — checklist of pages and claims to verify, with statuses. docs/agents/prompts/daily/bitvid-decompose-agent.md:22:- `todo/TODO_.md` — checklist of extraction items (2–3 blocks) and status. -docs/agents/prompts/daily/bitvid-decompose-agent.md:65:Add these items to `todo/TODO_.md`. -docs/agents/prompts/daily/bitvid-decompose-agent.md:255:4. Read file, identify 2–3 cohesive blocks, document in `context/CONTEXT_.md` and `todo/TODO_.md`. +docs/agents/prompts/daily/bitvid-decompose-agent.md:66:Add these items to `todo/TODO_.md`. +docs/agents/prompts/daily/bitvid-decompose-agent.md:256:4. Read file, identify 2–3 cohesive blocks, document in `context/CONTEXT_.md` and `todo/TODO_.md`. docs/agents/prompts/daily/bitvid-deps-security-agent.md:33:- `todo/TODO_.md` — upgrade tasks and statuses. docs/agents/prompts/daily/bitvid-docs-code-investigator.md:12: - Focus on files > ~200 LOC, or files that contain `TODO|FIXME|XXX`. docs/agents/prompts/daily/bitvid-docs-code-investigator.md:13:- Priority: files containing `TODO|FIXME|XXX` or >200 lines. Nostr helpers and signaling modules are high-value places to document. @@ -14,7 +14,7 @@ docs/agents/prompts/daily/bitvid-docs-code-investigator.md:33:- Is large (> 200 docs/agents/prompts/daily/bitvid-docs-code-investigator.md:71:- Note unreachable code, TODOs, or suspicious `try/catch` with swallowing errors. docs/agents/prompts/daily/bitvid-docs-code-investigator.md:209:git grep -n -E "TODO|FIXME|XXX" -- js | sed -n '1,200p' docs/agents/prompts/daily/bitvid-innerhtml-migration-agent.md:20:- `todo/TODO_.md` — checklist of assignments in the file and status. -docs/agents/prompts/daily/bitvid-innerhtml-migration-agent.md:54: Add this list to `todo/TODO_.md` as items to migrate. +docs/agents/prompts/daily/bitvid-innerhtml-migration-agent.md:55: Add this list to `todo/TODO_.md` as items to migrate. docs/agents/prompts/daily/bitvid-nip-research-agent.md:34:- `todo/TODO_.md` — Checklist: NIPs/kinds to research and next actions (tests/PRs/issues). docs/agents/prompts/daily/bitvid-nip-research-agent.md:116: - Where client behavior diverges intentionally or by omission, update `docs/nips/*` or `/content` to reflect reality, cite spec, and add "TODO: Fix" notes if non-compliant. docs/agents/prompts/daily/bitvid-nip-research-agent.md:219:- Tests/PRs/Issues for remediation, with `context/CONTEXT_.md`, `todo/TODO_.md`, `decisions/DECISIONS_.md` and `test_logs/TEST_LOG_.md`. @@ -54,6 +54,14 @@ docs/agents/prompts/daily/bitvid-todo-triage-agent.md:161:- If multiple TODOs re docs/agents/prompts/daily/bitvid-todo-triage-agent.md:163:- Do not delete TODOs as “stale” unless you can prove the need is resolved. docs/agents/prompts/daily/bitvid-todo-triage-agent.md:178:- 0–N small PRs for trivial, safe TODOs docs/agents/prompts/daily/bitvid-todo-triage-agent.md:179:- 0–N GitHub issues for medium/large/sensitive TODOs +docs/agents/task-logs/daily/2026-02-14_00-00-00_content-audit-agent_completed.md:22:- `todo/TODO_2026-02-14.md` +docs/agents/task-logs/daily/2026-02-14_02-34-11_todo-triage-agent_completed.md:9:- Scanned codebase for `TODO`, `FIXME`, `XXX`. +docs/agents/task-logs/daily/2026-02-14_02-34-11_todo-triage-agent_completed.md:12: - `docs/agents/prompts/`: Agent prompts instructing others to manage TODOs. +docs/agents/task-logs/daily/2026-02-14_02-34-11_todo-triage-agent_completed.md:13: - `docs/agents/RESEARCH_LOG.md`: Mention of `TODO.md` file convention. +docs/agents/task-logs/daily/2026-02-14_02-34-11_todo-triage-agent_completed.md:14: - `js/ui/profileModalContract.js`: `npubXXXX…XXXX` string (false positive). +docs/agents/task-logs/daily/2026-02-14_02-34-11_todo-triage-agent_completed.md:16:- **Result:** No actionable TODOs found in source code. +docs/agents/task-logs/daily/2026-02-14_11-46-04_decompose-agent_completed.md:24:- `todo/TODO_1771068993.md` +docs/agents/task-logs/daily/2026-02-15_17-59-53_scheduler-update-agent_completed.md:14:- `todo/TODO_2026-02-15_17-56-50.md` js/ui/profileModalContract.js:146: "Formats npub strings for display using the canonical short representation (npubXXXX…XXXX).", vendor/highlight.min.js:62:begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", vendor/highlight.min.js:63:end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) 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/docs/agents/task-logs/daily/2026-02-15_21-03-07_todo-triage-agent_completed.md b/docs/agents/task-logs/daily/2026-02-15_21-03-07_todo-triage-agent_completed.md new file mode 100644 index 00000000..ce767615 --- /dev/null +++ b/docs/agents/task-logs/daily/2026-02-15_21-03-07_todo-triage-agent_completed.md @@ -0,0 +1,10 @@ +# Todo Triage Agent - Completed + +- **Date:** 2026-02-15 +- **Status:** Completed +- **Output:** artifacts/todo-triage-report.md +- **Summary:** + - Scanned codebase for TODO/FIXME/XXX. + - Found 0 actionable items. + - Verified false positive in js/ui/profileModalContract.js. + - No changes made to source code. 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/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