diff --git a/CONTEXT.md b/CONTEXT.md index 2f005345..4e1aabae 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -1,5 +1,20 @@ -# Context -This audit verifies the quality and coverage of the bitvid test suite. -Date: 2026-02-12 -Agent: bitvid-test-audit-agent +# Test Audit Context +## 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 +- **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. + +## 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 863ebe31..04309546 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -1,3 +1 @@ # Decisions -- Using built-in Node.js test runner as discovered in scripts. - diff --git a/TEST_LOG.md b/TEST_LOG.md index 9385258e..6be4e8f1 100644 --- a/TEST_LOG.md +++ b/TEST_LOG.md @@ -1,297 +1,10598 @@ +# Test Log + +> 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: 199.189275 + 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: 51.81465 + 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: 11.487824 + 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: 41.311943 + 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: 51.136496 + 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: 33.423774 + 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: 3.141801 + duration_ms: 2.55716 type: 'test' ... 1..1 -ok 7 - createFeedCoordinator - loadForYouVideos +ok 1 - createFeedCoordinator - loadForYouVideos --- - duration_ms: 5.234491 + 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 8 - handleHashChange defaults to for-you when logged in +ok 1 - handleHashChange defaults to for-you when logged in --- - duration_ms: 136.375706 + duration_ms: 90.299709 type: 'test' ... # Subtest: handleHashChange defaults to most-recent-videos when logged out -ok 9 - handleHashChange defaults to most-recent-videos when logged out +ok 2 - handleHashChange defaults to most-recent-videos when logged out --- - duration_ms: 65.884185 + duration_ms: 17.124794 type: 'test' ... # Subtest: handleHashChange respects explicit view regardless of login state -ok 10 - handleHashChange respects explicit view regardless of login state +ok 3 - handleHashChange respects explicit view regardless of login state --- - duration_ms: 10.129186 + 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 11 - hydrateSidebarNavigation reveals chrome controls for authenticated viewers +ok 1 - hydrateSidebarNavigation reveals chrome controls for authenticated viewers --- - duration_ms: 129.215341 + duration_ms: 103.796798 type: 'test' ... # Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers -ok 12 - hydrateSidebarNavigation hides chrome controls for logged-out viewers +ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers --- - duration_ms: 16.815718 + 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 13 - isUserLoggedIn returns false when no user pubkey is set +ok 1 - isUserLoggedIn returns false when no user pubkey is set --- - duration_ms: 3.461914 + duration_ms: 1.887904 type: 'test' ... # Subtest: isUserLoggedIn treats extension logins as authenticated -ok 14 - isUserLoggedIn treats extension logins as authenticated +ok 2 - isUserLoggedIn treats extension logins as authenticated --- - duration_ms: 0.727681 + duration_ms: 0.562774 type: 'test' ... # Subtest: isUserLoggedIn guards against mismatched nostrClient state -ok 15 - isUserLoggedIn guards against mismatched nostrClient state +ok 3 - isUserLoggedIn guards against mismatched nostrClient state --- - duration_ms: 0.40678 + duration_ms: 0.419478 type: 'test' ... # Subtest: isUserLoggedIn ignores anonymous session actor mismatches -ok 16 - isUserLoggedIn ignores anonymous session actor mismatches +ok 4 - isUserLoggedIn ignores anonymous session actor mismatches --- - duration_ms: 0.494294 + duration_ms: 0.338595 type: 'test' ... # Subtest: isUserLoggedIn rejects mismatched managed session actors -ok 17 - isUserLoggedIn rejects mismatched managed session actors +ok 5 - isUserLoggedIn rejects mismatched managed session actors --- - duration_ms: 0.520986 + 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 18 - handleModerationOverride decorates stored and current videos then refreshes UI +ok 1 - handleModerationOverride decorates stored and current videos then refreshes UI --- - duration_ms: 7.638841 + duration_ms: 5.945926 type: 'test' ... # Subtest: handleModerationOverride resumes deferred playback -ok 19 - handleModerationOverride resumes deferred playback +ok 2 - handleModerationOverride resumes deferred playback --- - duration_ms: 1.054371 + duration_ms: 1.227272 type: 'test' ... # Subtest: handleModerationBlock requests a block, clears overrides, and refreshes hidden state -ok 20 - 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.724481 + duration_ms: 3.605258 type: 'test' ... # Subtest: handleModerationBlock returns false when viewer is logged out -ok 21 - handleModerationBlock returns false when viewer is logged out +ok 4 - handleModerationBlock returns false when viewer is logged out --- - duration_ms: 0.754321 + 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 22 - handleModerationSettingsChange refreshes feeds with updated thresholds +ok 1 - handleModerationSettingsChange refreshes feeds with updated thresholds --- - duration_ms: 6.080419 + 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 23 - orders similar videos by shared tags then timestamp +ok 1 - orders similar videos by shared tags then timestamp --- - duration_ms: 4.342539 + duration_ms: 3.213169 type: 'test' ... # Subtest: returns no matches when the active video lacks tags -ok 24 - returns no matches when the active video lacks tags +ok 2 - returns no matches when the active video lacks tags --- - duration_ms: 0.548732 + duration_ms: 0.528101 type: 'test' ... # Subtest: skips candidates without tag metadata -ok 25 - skips candidates without tag metadata +ok 3 - skips candidates without tag metadata --- - duration_ms: 0.326721 + duration_ms: 0.405583 type: 'test' ... # Subtest: filters NSFW and private videos when NSFW content is disabled -ok 26 - 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.334698 + 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.095052 + 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.537814 + duration_ms: 0.702002 type: 'test' ... # Subtest: throws error if no extension available ok 3 - throws error if no extension available --- - duration_ms: 1.629492 + duration_ms: 1.349977 type: 'test' ... # Subtest: prioritizes explicit extension over window.nostr ok 4 - prioritizes explicit extension over window.nostr --- - duration_ms: 0.675012 + duration_ms: 0.791745 type: 'test' ... 1..4 -ok 27 - createNip07SigningAdapter +ok 1 - createNip07SigningAdapter --- - duration_ms: 7.965653 + 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: 27.566551 + 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: 12.274133 + duration_ms: 9.535353 type: 'test' ... 1..2 -ok 28 - NIP-04/44 Compliance: Encryption Preference +ok 1 - NIP-04/44 Compliance: Encryption Preference --- - duration_ms: 134.567681 + 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: 33.53945 + duration_ms: 25.870269 type: 'test' ... # Subtest: decryptNip46PayloadWithKeys handles nip04 payload ok 2 - decryptNip46PayloadWithKeys handles nip04 payload --- - duration_ms: 36.515407 + 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