diff --git a/CONTEXT.md b/CONTEXT.md index 8f8d6464..4e1aabae 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -1,14 +1,20 @@ -# Context: bitvid-perf-agent +# Test Audit Context -## Mission -Daily, measurable improvement of app responsiveness and documentation accuracy. +## Purpose +This audit aims to verify the integrity and effectiveness of the bitvid test suite. The goal is to ensure tests actually test the behaviors they claim to, find fragile or missing tests, and propose small, high-confidence fixes to raise test quality and coverage. ## Scope -- **Repo:** `PR0M3TH3AN/bitvid` (unstable) -- **Focus:** - - P0: Fix unbounded concurrency in background tasks. - - Docs: Ensure `/content` upload guides match runtime behavior. +- **Focus Areas**: UX- and security-critical code paths including: + - Login/Auth (`js/services/authService.js`) + - Relay Management (`js/relayManager.js`) + - Decryption (`js/nostr/dmDecryptWorker.js`) + - Watch History (`js/nostr/watchHistory.js`) + - Moderation (`js/userBlocks.js`) +- **Exclusions**: Non-critical UI components, deprecated code. -## Current Task (Run 1) -- Fix unbounded concurrency in `js/nostr/commentEvents.js`. -- Fix outdated CORS port in `content/docs/guides/upload-content.md`. +## Definition of Done +- A daily audit report (`test-audit-report-YYYY-MM-DD.md`) is generated. +- Failing and flaky tests are identified. +- Coverage gaps for critical files are mapped. +- At least one P0 test problem is fixed or tracked as an actionable issue. +- All artifacts are committed. diff --git a/DECISIONS.md b/DECISIONS.md index dd0da7a0..04309546 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -1,9 +1 @@ -# Decisions Log - -## Performance -- **2026-02-xx:** Use `pMap` with `RELAY_BACKGROUND_CONCURRENCY` (3) for comment publishing and fetching. - - **Rationale:** `Promise.all` floods the network when users have many relays. Bounding concurrency prevents resource exhaustion. - -## Documentation -- **2026-02-xx:** Standardize local dev port to 3000 in docs. - - **Rationale:** Matches `npm start` default and `README.md`. +# Decisions diff --git a/TEST_LOG.md b/TEST_LOG.md index 7d10d0fb..6be4e8f1 100644 --- a/TEST_LOG.md +++ b/TEST_LOG.md @@ -1,5 +1,35661 @@ # Test Log -## Run 1 (Performance & Docs) -- **Baseline:** Found unbounded `Promise.all` in `js/nostr/commentEvents.js`. -- **Verification:** (Pending) +> bitvid@1.0.0 test:unit +> node scripts/run-unit-tests.mjs + + +→ Running tests/app-batch-fetch-profiles.test.mjs +TAP version 13 +# Subtest: batchFetchProfiles handles fast and failing relays +ok 1 - batchFetchProfiles handles fast and failing relays + --- + duration_ms: 11.347752 + type: 'test' + ... +# Subtest: batchFetchProfiles respects forceRefresh +ok 2 - batchFetchProfiles respects forceRefresh + --- + duration_ms: 1.432216 + type: 'test' + ... +1..2 +# tests 2 +# suites 0 +# pass 2 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 28.923616 + +→ Running tests/app-state.test.mjs +TAP version 13 +# Subtest: AppState + # Subtest: Initial state is clean + ok 1 - Initial state is clean + --- + duration_ms: 2.458562 + type: 'test' + ... + # Subtest: setPubkey() updates state and notifies subscribers + ok 2 - setPubkey() updates state and notifies subscribers + --- + duration_ms: 1.001744 + type: 'test' + ... + # Subtest: setCurrentUserNpub() updates state + ok 3 - setCurrentUserNpub() updates state + --- + duration_ms: 0.408267 + type: 'test' + ... + # Subtest: setCurrentVideo() updates state + ok 4 - setCurrentVideo() updates state + --- + duration_ms: 0.640847 + type: 'test' + ... + # Subtest: setVideosMap() updates state + ok 5 - setVideosMap() updates state + --- + duration_ms: 0.58406 + type: 'test' + ... + # Subtest: setVideoSubscription() updates state + ok 6 - setVideoSubscription() updates state + --- + duration_ms: 0.365106 + type: 'test' + ... + # Subtest: setModalState() updates state and notifies modal subscribers + ok 7 - setModalState() updates state and notifies modal subscribers + --- + duration_ms: 0.80965 + type: 'test' + ... + # Subtest: Global subscriber receives updates + ok 8 - Global subscriber receives updates + --- + duration_ms: 0.634669 + type: 'test' + ... + # Subtest: resetAppState() clears all state and notifies + ok 9 - resetAppState() clears all state and notifies + --- + duration_ms: 0.593409 + type: 'test' + ... + 1..9 +ok 1 - AppState + --- + duration_ms: 9.575579 + type: 'suite' + ... +1..1 +# tests 9 +# suites 1 +# pass 9 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 25.93184 + +→ Running tests/app/channel-profile-moderation.test.mjs +node:internal/modules/package_json_reader:314 + throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null); + ^ + +Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'jsdom' imported from /app/tests/app/channel-profile-moderation.test.mjs + at Object.getPackageJSONURL (node:internal/modules/package_json_reader:314:9) + at packageResolve (node:internal/modules/esm/resolve:767:81) + at moduleResolve (node:internal/modules/esm/resolve:853:18) + at defaultResolve (node:internal/modules/esm/resolve:983:11) + at #cachedDefaultResolve (node:internal/modules/esm/loader:731:20) + at ModuleLoader.resolve (node:internal/modules/esm/loader:708:38) + at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:310:38) + at ModuleJob._link (node:internal/modules/esm/module_job:182:49) { + code: 'ERR_MODULE_NOT_FOUND' +} + +Node.js v22.22.0 + +✖ tests/app/channel-profile-moderation.test.mjs failed with exit code 1 +npm notice +npm notice New minor version of npm available! 11.7.0 -> 11.10.0 +npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.10.0 +npm notice To update run: npm install -g npm@11.10.0 +npm notice + +> bitvid@1.0.0 test:unit +> node scripts/run-unit-tests.mjs + + +→ Running tests/app-batch-fetch-profiles.test.mjs +TAP version 13 +# Subtest: batchFetchProfiles handles fast and failing relays +ok 1 - batchFetchProfiles handles fast and failing relays + --- + duration_ms: 3.873016 + type: 'test' + ... +# Subtest: batchFetchProfiles respects forceRefresh +ok 2 - batchFetchProfiles respects forceRefresh + --- + duration_ms: 0.972463 + type: 'test' + ... +1..2 +# tests 2 +# suites 0 +# pass 2 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 15.926111 + +→ Running tests/app-state.test.mjs +TAP version 13 +# Subtest: AppState + # Subtest: Initial state is clean + ok 1 - Initial state is clean + --- + duration_ms: 2.399172 + type: 'test' + ... + # Subtest: setPubkey() updates state and notifies subscribers + ok 2 - setPubkey() updates state and notifies subscribers + --- + duration_ms: 0.988354 + type: 'test' + ... + # Subtest: setCurrentUserNpub() updates state + ok 3 - setCurrentUserNpub() updates state + --- + duration_ms: 0.582713 + type: 'test' + ... + # Subtest: setCurrentVideo() updates state + ok 4 - setCurrentVideo() updates state + --- + duration_ms: 0.518129 + type: 'test' + ... + # Subtest: setVideosMap() updates state + ok 5 - setVideosMap() updates state + --- + duration_ms: 0.60507 + type: 'test' + ... + # Subtest: setVideoSubscription() updates state + ok 6 - setVideoSubscription() updates state + --- + duration_ms: 0.323639 + type: 'test' + ... + # Subtest: setModalState() updates state and notifies modal subscribers + ok 7 - setModalState() updates state and notifies modal subscribers + --- + duration_ms: 0.742334 + type: 'test' + ... + # Subtest: Global subscriber receives updates + ok 8 - Global subscriber receives updates + --- + duration_ms: 0.641097 + type: 'test' + ... + # Subtest: resetAppState() clears all state and notifies + ok 9 - resetAppState() clears all state and notifies + --- + duration_ms: 0.696579 + type: 'test' + ... + 1..9 +ok 1 - AppState + --- + duration_ms: 9.42967 + type: 'suite' + ... +1..1 +# tests 9 +# suites 1 +# pass 9 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 28.268057 + +→ Running tests/app/channel-profile-moderation.test.mjs +TAP version 13 +# Subtest: renderChannelVideosFromList decorates videos before storing +ok 1 - renderChannelVideosFromList decorates videos before storing + --- + duration_ms: 136.597794 + type: 'test' + ... +# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata +ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata + --- + duration_ms: 36.712026 + type: 'test' + ... +# Subtest: applyChannelVisualBlur blurs banner and avatar when viewer mutes author +ok 3 - applyChannelVisualBlur blurs banner and avatar when viewer mutes author + --- + duration_ms: 16.869787 + type: 'test' + ... +# Subtest: moderation override clears channel blur via event wiring +ok 4 - moderation override clears channel blur via event wiring + --- + duration_ms: 29.730034 + type: 'test' + ... +# Subtest: channel header moderation badge reflects blur state and override actions +ok 5 - channel header moderation badge reflects blur state and override actions + --- + duration_ms: 34.349005 + type: 'test' + ... +# Subtest: channel video cards update moderation state in place when summary changes +ok 6 - channel video cards update moderation state in place when summary changes + --- + duration_ms: 29.14083 + type: 'test' + ... +1..6 +# tests 6 +# suites 0 +# pass 6 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 305.05826 + +→ Running tests/app/feedCoordinator.test.mjs +TAP version 13 +# Subtest: createFeedCoordinator - loadForYouVideos + # Subtest: loadForYouVideos executes successfully + ok 1 - loadForYouVideos executes successfully + --- + duration_ms: 2.55716 + type: 'test' + ... + 1..1 +ok 1 - createFeedCoordinator - loadForYouVideos + --- + duration_ms: 4.379186 + type: 'test' + ... +1..1 +# tests 2 +# suites 0 +# pass 2 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 15.941918 + +→ Running tests/app/hash-change-handler.test.mjs +TAP version 13 +# Subtest: handleHashChange defaults to for-you when logged in +ok 1 - handleHashChange defaults to for-you when logged in + --- + duration_ms: 90.299709 + type: 'test' + ... +# Subtest: handleHashChange defaults to most-recent-videos when logged out +ok 2 - handleHashChange defaults to most-recent-videos when logged out + --- + duration_ms: 17.124794 + type: 'test' + ... +# Subtest: handleHashChange respects explicit view regardless of login state +ok 3 - handleHashChange respects explicit view regardless of login state + --- + duration_ms: 18.10759 + type: 'test' + ... +1..3 +# tests 3 +# suites 0 +# pass 3 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 138.368793 + +→ Running tests/app/hydrate-sidebar-navigation.test.mjs +TAP version 13 +# Subtest: hydrateSidebarNavigation reveals chrome controls for authenticated viewers +ok 1 - hydrateSidebarNavigation reveals chrome controls for authenticated viewers + --- + duration_ms: 103.796798 + type: 'test' + ... +# Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers +ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers + --- + duration_ms: 19.114249 + type: 'test' + ... +1..2 +# tests 2 +# suites 0 +# pass 2 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 136.684131 + +→ Running tests/app/is-user-logged-in.test.mjs +TAP version 13 +# Subtest: isUserLoggedIn returns false when no user pubkey is set +ok 1 - isUserLoggedIn returns false when no user pubkey is set + --- + duration_ms: 1.887904 + type: 'test' + ... +# Subtest: isUserLoggedIn treats extension logins as authenticated +ok 2 - isUserLoggedIn treats extension logins as authenticated + --- + duration_ms: 0.562774 + type: 'test' + ... +# Subtest: isUserLoggedIn guards against mismatched nostrClient state +ok 3 - isUserLoggedIn guards against mismatched nostrClient state + --- + duration_ms: 0.419478 + type: 'test' + ... +# Subtest: isUserLoggedIn ignores anonymous session actor mismatches +ok 4 - isUserLoggedIn ignores anonymous session actor mismatches + --- + duration_ms: 0.338595 + type: 'test' + ... +# Subtest: isUserLoggedIn rejects mismatched managed session actors +ok 5 - isUserLoggedIn rejects mismatched managed session actors + --- + duration_ms: 0.537694 + type: 'test' + ... +1..5 +# tests 5 +# suites 0 +# pass 5 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 40.684375 + +→ Running tests/app/moderation-overrides.test.mjs +TAP version 13 +# Subtest: handleModerationOverride decorates stored and current videos then refreshes UI +ok 1 - handleModerationOverride decorates stored and current videos then refreshes UI + --- + duration_ms: 5.945926 + type: 'test' + ... +# Subtest: handleModerationOverride resumes deferred playback +ok 2 - handleModerationOverride resumes deferred playback + --- + duration_ms: 1.227272 + type: 'test' + ... +# Subtest: handleModerationBlock requests a block, clears overrides, and refreshes hidden state +ok 3 - handleModerationBlock requests a block, clears overrides, and refreshes hidden state + --- + duration_ms: 3.605258 + type: 'test' + ... +# Subtest: handleModerationBlock returns false when viewer is logged out +ok 4 - handleModerationBlock returns false when viewer is logged out + --- + duration_ms: 1.006912 + type: 'test' + ... +1..4 +# tests 4 +# suites 0 +# pass 4 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 28.169184 + +→ Running tests/app/moderation-settings-refresh.test.mjs +TAP version 13 +# Subtest: handleModerationSettingsChange refreshes feeds with updated thresholds +ok 1 - handleModerationSettingsChange refreshes feeds with updated thresholds + --- + duration_ms: 4.491854 + type: 'test' + ... +1..1 +# tests 1 +# suites 0 +# pass 1 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 17.180422 + +→ Running tests/app/similar-content.test.mjs +TAP version 13 +# Subtest: orders similar videos by shared tags then timestamp +ok 1 - orders similar videos by shared tags then timestamp + --- + duration_ms: 3.213169 + type: 'test' + ... +# Subtest: returns no matches when the active video lacks tags +ok 2 - returns no matches when the active video lacks tags + --- + duration_ms: 0.528101 + type: 'test' + ... +# Subtest: skips candidates without tag metadata +ok 3 - skips candidates without tag metadata + --- + duration_ms: 0.405583 + type: 'test' + ... +# Subtest: filters NSFW and private videos when NSFW content is disabled +ok 4 - filters NSFW and private videos when NSFW content is disabled + --- + duration_ms: 0.538725 + type: 'test' + ... +1..4 +# tests 4 +# suites 0 +# pass 4 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 17.144684 + +→ Running tests/auth/signingAdapter.test.mjs +TAP version 13 +# Subtest: createNip07SigningAdapter + # Subtest: uses explicit extension if provided + ok 1 - uses explicit extension if provided + --- + duration_ms: 3.90752 + type: 'test' + ... + # Subtest: falls back to window.nostr if no extension provided + ok 2 - falls back to window.nostr if no extension provided + --- + duration_ms: 0.702002 + type: 'test' + ... + # Subtest: throws error if no extension available + ok 3 - throws error if no extension available + --- + duration_ms: 1.349977 + type: 'test' + ... + # Subtest: prioritizes explicit extension over window.nostr + ok 4 - prioritizes explicit extension over window.nostr + --- + duration_ms: 0.791745 + type: 'test' + ... + 1..4 +ok 1 - createNip07SigningAdapter + --- + duration_ms: 8.438813 + type: 'suite' + ... +1..1 +# tests 4 +# suites 1 +# pass 4 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 25.27363 + +→ Running tests/comment-event-builder.test.mjs +TAP version 13 +# Subtest: buildCommentEvent emits NIP-22 root metadata while keeping legacy fallbacks +ok 1 - buildCommentEvent emits NIP-22 root metadata while keeping legacy fallbacks + --- + duration_ms: 2.88372 + type: 'test' + ... +# Subtest: buildCommentEvent includes parent pointers, kinds, and authors for replies +ok 2 - buildCommentEvent includes parent pointers, kinds, and authors for replies + --- + duration_ms: 0.54315 + type: 'test' + ... +# Subtest: buildCommentEvent normalizes relays and preserves explicit overrides +ok 3 - buildCommentEvent normalizes relays and preserves explicit overrides + --- + duration_ms: 0.814022 + type: 'test' + ... +# Subtest: buildCommentEvent falls back to event pointers when no address is supplied +ok 4 - buildCommentEvent falls back to event pointers when no address is supplied + --- + duration_ms: 0.270816 + type: 'test' + ... +# Subtest: buildCommentEvent accepts partial metadata for parent overrides +ok 5 - buildCommentEvent accepts partial metadata for parent overrides + --- + duration_ms: 0.507199 + type: 'test' + ... +# Subtest: buildCommentEvent sanitizes additional tags before signing +ok 6 - buildCommentEvent sanitizes additional tags before signing + --- + duration_ms: 0.91122 + type: 'test' + ... +1..6 +# tests 6 +# suites 0 +# pass 6 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 21.523829 + +→ Running tests/comment-thread-service.test.mjs +TAP version 13 +# Subtest: CommentThreadService caches mixed-case video ids consistently +ok 1 - CommentThreadService caches mixed-case video ids consistently + --- + duration_ms: 3.643543 + type: 'test' + ... +# Subtest: CommentThreadService surfaces cache read failures +ok 2 - CommentThreadService surfaces cache read failures + --- + duration_ms: 0.707246 + type: 'test' + ... +# Subtest: CommentThreadService surfaces cache write failures +ok 3 - CommentThreadService surfaces cache write failures + --- + duration_ms: 0.539127 + type: 'test' + ... +# Subtest: CommentThreadService persists caches safely during teardown failures +ok 4 - CommentThreadService persists caches safely during teardown failures + --- + duration_ms: 1.976216 + type: 'test' + ... +# Subtest: CommentThreadService logs cache usage and fallback decisions +ok 5 - CommentThreadService logs cache usage and fallback decisions + --- + duration_ms: 1.405525 + type: 'test' + ... +# Subtest: CommentThreadService normalizes mixed-case event ids in thread state +ok 6 - CommentThreadService normalizes mixed-case event ids in thread state + --- + duration_ms: 2.341791 + type: 'test' + ... +# Subtest: CommentThreadService normalizes mixed-case pubkeys during hydration +ok 7 - CommentThreadService normalizes mixed-case pubkeys during hydration + --- + duration_ms: 0.98349 + type: 'test' + ... +# Subtest: CommentThreadService deduplicates mixed-case event ids and pubkeys +ok 8 - CommentThreadService deduplicates mixed-case event ids and pubkeys + --- + duration_ms: 1.045611 + type: 'test' + ... +# Subtest: CommentThreadService retries profile hydration before succeeding +ok 9 - CommentThreadService retries profile hydration before succeeding + --- + duration_ms: 76.746748 + type: 'test' + ... +# Subtest: CommentThreadService surfaces profile hydration failures after retries +ok 10 - CommentThreadService surfaces profile hydration failures after retries + --- + duration_ms: 202.180916 + type: 'test' + ... +# Subtest: listVideoComments accepts builder events without parent ids and filters replies +ok 11 - listVideoComments accepts builder events without parent ids and filters replies + --- + duration_ms: 5.90168 + type: 'test' + ... +# Subtest: CommentThreadService hydrates, subscribes, and dedupes incoming comment events +ok 12 - CommentThreadService hydrates, subscribes, and dedupes incoming comment events + --- + duration_ms: 33.974583 + type: 'test' + ... +# Subtest: CommentThreadService loadThread falls back to event id when address is missing +ok 13 - CommentThreadService loadThread falls back to event id when address is missing + --- + duration_ms: 0.819653 + type: 'test' + ... +# Subtest: CommentThreadService requests and snapshots comments by root identifier +ok 14 - CommentThreadService requests and snapshots comments by root identifier + --- + duration_ms: 0.745666 + type: 'test' + ... +# Subtest: CommentThreadService falls back to pointerIdentifiers root id +ok 15 - CommentThreadService falls back to pointerIdentifiers root id + --- + duration_ms: 0.790199 + type: 'test' + ... +# Subtest: CommentThreadService preserves raw video author pubkeys during hydration fetches +ok 16 - CommentThreadService preserves raw video author pubkeys during hydration fetches + --- + duration_ms: 5.216459 + type: 'test' + ... +# Subtest: CommentThreadService teardown cancels hydration timers +ok 17 - CommentThreadService teardown cancels hydration timers + --- + duration_ms: 81.181975 + type: 'test' + ... +1..17 +# tests 17 +# suites 0 +# pass 17 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 430.874374 + +→ Running tests/compliance/nip04_44_compliance.test.mjs +TAP version 13 +# Subtest: NIP-04/44 Compliance: Encryption Preference + # Subtest: createNip46Cipher prefers nip44.v2 when available + ok 1 - createNip46Cipher prefers nip44.v2 when available + --- + duration_ms: 21.560216 + type: 'test' + ... + # Subtest: createNip46Cipher falls back to nip04 if nip44 is missing + ok 2 - createNip46Cipher falls back to nip04 if nip44 is missing + --- + duration_ms: 9.535353 + type: 'test' + ... + 1..2 +ok 1 - NIP-04/44 Compliance: Encryption Preference + --- + duration_ms: 122.610928 + type: 'test' + ... +# Subtest: NIP-04/44 Compliance: Decryption Fallback + # Subtest: decryptNip46PayloadWithKeys handles nip44 (v2) payload + ok 1 - decryptNip46PayloadWithKeys handles nip44 (v2) payload + --- + duration_ms: 25.870269 + type: 'test' + ... + # Subtest: decryptNip46PayloadWithKeys handles nip04 payload + ok 2 - decryptNip46PayloadWithKeys handles nip04 payload + --- + duration_ms: 36.581415 + type: 'test' + ... + 1..2 +ok 2 - NIP-04/44 Compliance: Decryption Fallback + --- + duration_ms: 64.71237 + type: 'test' + ... +1..2 +# tests 6 +# suites 0 +# pass 6 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 206.652054 + +→ Running tests/compliance/nip07_compliance.test.mjs +TAP version 13 +# Subtest: NIP-07 Compliance: Retry Logic + # Subtest: runNip07WithRetry succeeds on first try + ok 1 - runNip07WithRetry succeeds on first try + --- + duration_ms: 2.021351 + type: 'test' + ... + # Subtest: runNip07WithRetry retries on timeout error + ok 2 - runNip07WithRetry retries on timeout error + --- + duration_ms: 20.804337 + type: 'test' + ... + # Subtest: runNip07WithRetry fails after max retries or if error is not timeout + ok 3 - runNip07WithRetry fails after max retries or if error is not timeout + --- + duration_ms: 1.209118 + type: 'test' + ... + 1..3 +ok 1 - NIP-07 Compliance: Retry Logic + --- + duration_ms: 25.648444 + type: 'test' + ... +1..1 +# tests 4 +# suites 0 +# pass 4 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 59.274839 + +→ Running tests/compliance/nip65_compliance.test.mjs +TAP version 13 +# Subtest: NIP-65 Compliance: Relay List Loading + # Subtest: loadRelayList requests Kind 10002 + ok 1 - loadRelayList requests Kind 10002 + --- + duration_ms: 6.934884 + type: 'test' + ... + # Subtest: loadRelayList parses r tags correctly + ok 2 - loadRelayList parses r tags correctly + --- + duration_ms: 0.329896 + type: 'test' + ... + 1..2 +ok 1 - NIP-65 Compliance: Relay List Loading + --- + duration_ms: 158.312117 + type: 'test' + ... +1..1 +# tests 3 +# suites 0 +# pass 3 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 172.028991 + +→ Running tests/compliance/video_note_compliance.test.mjs +TAP version 13 +# Subtest: Video Note Compliance (Kind 30078 & NIP-71) + # Subtest: prepareVideoPublishPayload creates Kind 30078 event + ok 1 - prepareVideoPublishPayload creates Kind 30078 event + --- + duration_ms: 2.674873 + type: 'test' + ... + # Subtest: prepareVideoPublishPayload includes NIP-71 tags when provided + ok 2 - prepareVideoPublishPayload includes NIP-71 tags when provided + --- + duration_ms: 0.957472 + type: 'test' + ... + 1..2 +ok 1 - Video Note Compliance (Kind 30078 & NIP-71) + --- + duration_ms: 39.709423 + type: 'test' + ... +1..1 +# tests 3 +# suites 0 +# pass 3 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 54.047089 + +→ Running tests/design-system-metrics.test.mjs +TAP version 13 +# Subtest: metric probe falls back to numeric parsing when measurement fails +ok 1 - metric probe falls back to numeric parsing when measurement fails + --- + duration_ms: 258.83015 + type: 'test' + ... +1..1 +# tests 1 +# suites 0 +# pass 1 +# fail 0 +# cancelled 0 +# skipped 0 +# todo 0 +# duration_ms 275.066096 + +→ Running tests/designSystem/dynamicStyles.test.mjs +TAP version 13 +# Subtest: js/designSystem/dynamicStyles.js + # Subtest: registerScope + # Subtest: should register a scope and return a string ID + ok 1 - should register a scope and return a string ID + --- + duration_ms: 118.742464 + type: 'test' + ... + # Subtest: should create a style element or use adoptedStyleSheets + ok 2 - should create a style element or use adoptedStyleSheets + --- + duration_ms: 15.288436 + type: 'test' + ... + # Subtest: should insert rules with the correct selector + ok 3 - should insert rules with the correct selector + --- + duration_ms: 13.14124 + type: 'test' + ... + # Subtest: should handle "&" in selectors + ok 4 - should handle "&" in selectors + --- + duration_ms: 11.58199 + type: 'test' + ... + 1..4 + ok 1 - registerScope + --- + duration_ms: 160.248423 + type: 'suite' + ... + # Subtest: setVariables + # Subtest: should update CSS variables on the scope + ok 1 - should update CSS variables on the scope + --- + duration_ms: 11.622113 + type: 'test' + ... + # Subtest: should handle removing variables + ok 2 - should handle removing variables + --- + duration_ms: 10.689878 + type: 'test' + ... + 1..2 + ok 2 - setVariables + --- + duration_ms: 22.794895 + type: 'suite' + ... + # Subtest: releaseScope + # Subtest: should remove rules and clean up + ok 1 - should remove rules and clean up + --- + duration_ms: 9.432565 + type: 'test' + ... + # Subtest: should return false for non-existent scope + ok 2 - should return false for non-existent scope + --- + duration_ms: 8.485024 + type: 'test' + ... + 1..2 + ok 3 - releaseScope + --- + duration_ms: 18.297913 + type: 'suite' + ... + # Subtest: Isolation + # Subtest: should manage scopes independently for different documents + ok 1 - should manage scopes independently for different documents + --- + duration_ms: 33.53914 + type: 'test' + ... + 1..1 + ok 4 - Isolation + --- + duration_ms: 33.695457 + type: 'suite' + ... + # Subtest: Edge cases + # Subtest: should handle invalid selectors gracefully + ok 1 - should handle invalid selectors gracefully + --- + duration_ms: 9.917057 + type: 'test' + ... + # Subtest: should handle missing document gracefully + ok 2 - should handle missing document gracefully + --- + duration_ms: 7.360211 + type: 'test' + ... + # Subtest: should fallback to