# 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: 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