Files
bitvid/test_output.log
T
google-labs-jules[bot] fc9ce6916d docs(ai): improve onboarding steps and fix lint/test issues
\n- Fixed CSS linting errors by replacing raw values with design tokens in `css/tailwind.source.css`.
- Updated `scripts/check-design-tokens.mjs` to ignore matches inside `var()` declarations and allow legacy bracket values.
- Fixed a failing unit test in `tests/ui/similar-content-card.test.mjs` to match current component behavior.
- Updated `CONTRIBUTING.md` to include `npm run build:css` and clarify linting requirements.
- Enhanced `.devcontainer/devcontainer.json` to include `npm run build:css` in `postCreateCommand`.
2026-01-19 19:35:17 +00:00

1894 lines
59 KiB
Plaintext

> [email protected] test:unit
> node scripts/run-unit-tests.mjs
→ Running tests/app-batch-fetch-profiles.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
[batchFetchProfiles] Failed to fetch profiles from relay wss://fail.example: Error: relay timed out
at Object.list (file:///app/tests/app-batch-fetch-profiles.test.mjs:80:31)
at file:///app/js/utils/profileBatchFetcher.js:115:10
at Array.map (<anonymous>)
at batchFetchProfilesFromRelays (file:///app/js/utils/profileBatchFetcher.js:112:75)
at TestContext.<anonymous> (file:///app/tests/app-batch-fetch-profiles.test.mjs:87:11)
at Test.runInAsyncScope (node:async_hooks:214:14)
at Test.run (node:internal/test_runner/test:1047:25)
at Test.start (node:internal/test_runner/test:944:17)
at startSubtestAfterBootstrap (node:internal/test_runner/harness:296:17)
TAP version 13
# Subtest: batchFetchProfiles handles fast and failing relays
ok 1 - batchFetchProfiles handles fast and failing relays
---
duration_ms: 3.847532
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 15.85785
→ Running tests/app/channel-profile-moderation.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 2,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
TAP version 13
# Subtest: renderChannelVideosFromList decorates videos before storing
ok 1 - renderChannelVideosFromList decorates videos before storing
---
duration_ms: 232.522956
type: 'test'
...
# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata
ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata
---
duration_ms: 31.783442
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.23191
type: 'test'
...
# Subtest: moderation override clears channel blur via event wiring
ok 4 - moderation override clears channel blur via event wiring
---
duration_ms: 36.970563
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: 31.280065
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: 24.2117
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 380.211556
→ 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: 75.128603
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: 9.840989
type: 'test'
...
# Subtest: handleHashChange respects explicit view regardless of login state
ok 3 - handleHashChange respects explicit view regardless of login state
---
duration_ms: 9.951321
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 108.26157
→ Running tests/app/hydrate-sidebar-navigation.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: hydrateSidebarNavigation reveals chrome controls for authenticated viewers
ok 1 - hydrateSidebarNavigation reveals chrome controls for authenticated viewers
---
duration_ms: 86.167066
type: 'test'
...
# Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers
ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers
---
duration_ms: 12.849406
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 110.435512
→ Running tests/app/is-user-logged-in.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
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.824922
type: 'test'
...
# Subtest: isUserLoggedIn treats extension logins as authenticated
ok 2 - isUserLoggedIn treats extension logins as authenticated
---
duration_ms: 0.463582
type: 'test'
...
# Subtest: isUserLoggedIn guards against mismatched nostrClient state
ok 3 - isUserLoggedIn guards against mismatched nostrClient state
---
duration_ms: 0.273019
type: 'test'
...
# Subtest: isUserLoggedIn ignores anonymous session actor mismatches
ok 4 - isUserLoggedIn ignores anonymous session actor mismatches
---
duration_ms: 0.257852
type: 'test'
...
# Subtest: isUserLoggedIn rejects mismatched managed session actors
ok 5 - isUserLoggedIn rejects mismatched managed session actors
---
duration_ms: 0.432518
type: 'test'
...
1..5
# tests 5
# suites 0
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 33.654661
→ Running tests/app/moderation-overrides.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
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: 206.383606
type: 'test'
...
# Subtest: handleModerationOverride resumes deferred playback
ok 2 - handleModerationOverride resumes deferred playback
---
duration_ms: 1.336124
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.85506
type: 'test'
...
# Subtest: handleModerationBlock returns false when viewer is logged out
ok 4 - handleModerationBlock returns false when viewer is logged out
---
duration_ms: 1.71659
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 4
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 241.804569
→ Running tests/app/moderation-settings-refresh.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: handleModerationSettingsChange refreshes feeds with updated thresholds
ok 1 - handleModerationSettingsChange refreshes feeds with updated thresholds
---
duration_ms: 211.966355
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 240.518204
→ Running tests/app/similar-content.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: orders similar videos by shared tags then timestamp
ok 1 - orders similar videos by shared tags then timestamp
---
duration_ms: 2.926753
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.555046
type: 'test'
...
# Subtest: skips candidates without tag metadata
ok 3 - skips candidates without tag metadata
---
duration_ms: 0.476961
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.591487
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 4
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 34.404353
→ Running tests/comment-event-builder.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
[nostrEventSchemas] Dropping unmatched surrogate characters from event content
[nostrEventSchemas] Dropping unmatched surrogate characters from event content
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: 3.004895
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.46031
type: 'test'
...
# Subtest: buildCommentEvent normalizes relays and preserves explicit overrides
ok 3 - buildCommentEvent normalizes relays and preserves explicit overrides
---
duration_ms: 0.957929
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.337432
type: 'test'
...
# Subtest: buildCommentEvent accepts partial metadata for parent overrides
ok 5 - buildCommentEvent accepts partial metadata for parent overrides
---
duration_ms: 0.408436
type: 'test'
...
# Subtest: buildCommentEvent sanitizes additional tags before signing
ok 6 - buildCommentEvent sanitizes additional tags before signing
---
duration_ms: 0.901309
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 20.064818
→ Running tests/comment-thread-service.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
[commentThread] Cached 1 comments for AABBCC11223344556677889900aabbcc11223344556677889900aabbcc112233.
[commentThread] Loaded 1 cached comments for aabbcc11223344556677889900aabbcc11223344556677889900aabbcc112233.
[commentThread] Improved fetching fallback: feature disabled.
[commentThread] Improved fetching fallback: feature disabled.
[commentThread] Improved fetching fallback: feature disabled.
TAP version 13
# Subtest: CommentThreadService caches mixed-case video ids consistently
ok 1 - CommentThreadService caches mixed-case video ids consistently
---
duration_ms: 4.0376
type: 'test'
...
# Subtest: CommentThreadService surfaces cache read failures
ok 2 - CommentThreadService surfaces cache read failures
---
duration_ms: 0.831567
type: 'test'
...
# Subtest: CommentThreadService surfaces cache write failures
ok 3 - CommentThreadService surfaces cache write failures
---
duration_ms: 0.514611
type: 'test'
...
# Subtest: CommentThreadService persists caches safely during teardown failures
ok 4 - CommentThreadService persists caches safely during teardown failures
---
duration_ms: 1.896511
type: 'test'
...
# Subtest: CommentThreadService logs cache usage and fallback decisions
ok 5 - CommentThreadService logs cache usage and fallback decisions
---
duration_ms: 1.426893
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.482674
type: 'test'
...
# Subtest: CommentThreadService normalizes mixed-case pubkeys during hydration
ok 7 - CommentThreadService normalizes mixed-case pubkeys during hydration
---
duration_ms: 1.26822
type: 'test'
...
# Subtest: CommentThreadService deduplicates mixed-case event ids and pubkeys
ok 8 - CommentThreadService deduplicates mixed-case event ids and pubkeys
---
duration_ms: 1.158473
type: 'test'
...
[commentThread] Profile hydration attempt 1/3 failed for pubkeys: cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc, dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd. Error: temporary hydration failure
at CommentThreadService.batchFetchProfiles (file:///app/tests/comment-thread-service.test.mjs:545:15)
at file:///app/js/services/commentThreadService.js:908:40
at CommentThreadService.flushProfileQueue (file:///app/js/services/commentThreadService.js:955:7)
at Timeout._onTimeout (file:///app/js/services/commentThreadService.js:884:12)
at listOnTimeout (node:internal/timers:588:17)
at process.processTimers (node:internal/timers:523:7)
[commentThread] Retrying profile hydration in 50ms for pubkeys: cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc, dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd.
# Subtest: CommentThreadService retries profile hydration before succeeding
ok 9 - CommentThreadService retries profile hydration before succeeding
---
duration_ms: 77.501448
type: 'test'
...
[nostr] Comments cache miss for ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
[nostr] Comments cache hit for ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
[commentThread] Improved fetching fallback: feature disabled.
# Subtest: CommentThreadService surfaces profile hydration failures after retries
ok 10 - CommentThreadService surfaces profile hydration failures after retries
---
duration_ms: 201.319632
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.593448
type: 'test'
...
[commentThread] Improved fetching fallback: feature disabled.
[commentThread] Improved fetching fallback: feature disabled.
[commentThread] Improved fetching fallback: feature disabled.
[commentThread] Improved fetching fallback: feature disabled.
# Subtest: CommentThreadService hydrates, subscribes, and dedupes incoming comment events
ok 12 - CommentThreadService hydrates, subscribes, and dedupes incoming comment events
---
duration_ms: 35.214518
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: 1.181554
type: 'test'
...
# Subtest: CommentThreadService requests and snapshots comments by root identifier
ok 14 - CommentThreadService requests and snapshots comments by root identifier
---
duration_ms: 1.087917
type: 'test'
...
# Subtest: CommentThreadService falls back to pointerIdentifiers root id
ok 15 - CommentThreadService falls back to pointerIdentifiers root id
---
duration_ms: 0.741488
type: 'test'
...
[commentThread] Comment cache miss for aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: no entry present.
[commentThread] Cached 0 comments for aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
[commentThread] Loaded 0 cached comments for aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
[commentThread] Cached 0 comments for aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
[commentThread] Cached 1 comments for aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
[commentThread] Cached 1 comments for aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.
# Subtest: CommentThreadService preserves raw video author pubkeys during hydration fetches
ok 16 - CommentThreadService preserves raw video author pubkeys during hydration fetches
---
duration_ms: 6.258213
type: 'test'
...
# Subtest: CommentThreadService teardown cancels hydration timers
ok 17 - CommentThreadService teardown cancels hydration timers
---
duration_ms: 80.86304
type: 'test'
...
1..17
# tests 17
# suites 0
# pass 17
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 434.051498
→ 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: 146.293963
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 161.992063
→ Running tests/dm-decryptor.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: decryptDM handles kind 4 events with nip04 ciphertext
ok 1 - decryptDM handles kind 4 events with nip04 ciphertext
---
duration_ms: 73.003385
type: 'test'
...
# Subtest: decryptDM prefers recipient pubkeys when actor is the sender
ok 2 - decryptDM prefers recipient pubkeys when actor is the sender
---
duration_ms: 18.283135
type: 'test'
...
# Subtest: decryptDM unwraps kind 1059 gift wraps with nip44
ok 3 - decryptDM unwraps kind 1059 gift wraps with nip44
---
duration_ms: 60.105189
type: 'test'
...
# Subtest: decryptDM returns failure when decryptors are unavailable
ok 4 - decryptDM returns failure when decryptors are unavailable
---
duration_ms: 0.382312
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 4
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 164.999578
→ Running tests/edit-modal-submit-state.test.mjs
TAP version 13
# Subtest: ignores additional submissions while pending without spurious errors
ok 1 - ignores additional submissions while pending without spurious errors
---
duration_ms: 266.78321
type: 'test'
...
# Subtest: editing the magnet refreshes torrent hints when ws/xs remain locked
ok 2 - editing the magnet refreshes torrent hints when ws/xs remain locked
---
duration_ms: 107.787782
type: 'test'
...
# Subtest: does not show missing video error after modal closes
ok 3 - does not show missing video error after modal closes
---
duration_ms: 83.991975
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 472.427029
→ Running tests/feed-engine/tag-preference-filter.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: tag preference stage filters by interests and excludes disinterests
ok 1 - tag preference stage filters by interests and excludes disinterests
---
duration_ms: 2.754511
type: 'test'
...
# Subtest: tag preference stage accepts interests from nip71 hashtags
ok 2 - tag preference stage accepts interests from nip71 hashtags
---
duration_ms: 0.444436
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 13.857379
→ Running tests/hashtag-preferences.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: load decrypts nip44 payloads and normalizes tags
ok 1 - load decrypts nip44 payloads and normalizes tags
---
duration_ms: 19.403426
type: 'test'
...
# Subtest: load falls back to nip04 decryption
ok 2 - load falls back to nip04 decryption
---
duration_ms: 1.250005
type: 'test'
...
# Subtest: load retries decryptors when hinted scheme fails
ok 3 - load retries decryptors when hinted scheme fails
---
duration_ms: 1.544729
type: 'test'
...
# Subtest: interest and disinterest lists remain exclusive
ok 4 - interest and disinterest lists remain exclusive
---
duration_ms: 0.67708
type: 'test'
...
# Subtest: publish encrypts payload and builds event via builder
ok 5 - publish encrypts payload and builds event via builder
---
duration_ms: 8.610979
type: 'test'
...
# Subtest: publish falls back to window nostr encryptors
ok 6 - publish falls back to window nostr encryptors
---
duration_ms: 2.455851
type: 'test'
...
# Subtest: load prefers canonical kind when timestamps match while accepting legacy payload
ok 7 - load prefers canonical kind when timestamps match while accepting legacy payload
---
duration_ms: 1.569546
type: 'test'
...
1..7
# tests 7
# suites 0
# pass 7
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 44.547963
→ Running tests/magnet-utils.test.mjs
TAP version 13
# Subtest: safeDecodeMagnet handles encoded values
ok 1 - safeDecodeMagnet handles encoded values
---
duration_ms: 1.499096
type: 'test'
...
# Subtest: safeDecodeMagnet leaves plain strings untouched
ok 2 - safeDecodeMagnet leaves plain strings untouched
---
duration_ms: 0.270485
type: 'test'
...
# Subtest: bare hashes normalize consistently across helpers
ok 3 - bare hashes normalize consistently across helpers
---
duration_ms: 3.303802
type: 'test'
...
# Subtest: legacy %3A payloads decode across helpers
ok 4 - legacy %3A payloads decode across helpers
---
duration_ms: 0.587992
type: 'test'
...
# Subtest: duplicate trackers and hints stay in sync
ok 5 - duplicate trackers and hints stay in sync
---
duration_ms: 1.194348
type: 'test'
...
# Subtest: object helper enforces HTTPS web seeds when on HTTPS
ok 6 - object helper enforces HTTPS web seeds when on HTTPS
---
duration_ms: 0.541729
type: 'test'
...
# Subtest: object helper allows HTTP seeds on HTTP origins
ok 7 - object helper allows HTTP seeds on HTTP origins
---
duration_ms: 0.318126
type: 'test'
...
# Subtest: extractMagnetHints returns first ws/xs pair
ok 8 - extractMagnetHints returns first ws/xs pair
---
duration_ms: 0.409157
type: 'test'
...
# Subtest: string helper skips insecure ws hints on HTTPS origins
ok 9 - string helper skips insecure ws hints on HTTPS origins
---
duration_ms: 0.865413
type: 'test'
...
# Subtest: object helper reports didChange when output differs
ok 10 - object helper reports didChange when output differs
---
duration_ms: 0.74896
type: 'test'
...
# Subtest: helpers trim fragments from non-magnet values
ok 11 - helpers trim fragments from non-magnet values
---
duration_ms: 0.283338
type: 'test'
...
1..11
# tests 11
# suites 0
# pass 11
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 29.76196
→ Running tests/media-loader.test.mjs
TAP version 13
# Subtest: MediaLoader assigns image sources once intersecting
ok 1 - MediaLoader assigns image sources once intersecting
---
duration_ms: 83.853192
type: 'test'
...
# Subtest: MediaLoader loads video sources and poster fallbacks
ok 2 - MediaLoader loads video sources and poster fallbacks
---
duration_ms: 23.340945
type: 'test'
...
# Subtest: MediaLoader clears unsupported lazy targets without inline styles
ok 3 - MediaLoader clears unsupported lazy targets without inline styles
---
duration_ms: 10.753205
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 131.319846
→ Running tests/modal-accessibility.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: UploadModal closes on Escape and restores trigger focus
ok 1 - UploadModal closes on Escape and restores trigger focus
---
duration_ms: 241.185669
type: 'test'
...
# Subtest: UploadModal backdrop click closes and restores trigger focus
ok 2 - UploadModal backdrop click closes and restores trigger focus
---
duration_ms: 83.8338
type: 'test'
...
# Subtest: UploadModal mode toggle updates button states
ok 3 - UploadModal mode toggle updates button states
---
duration_ms: 61.389447
type: 'test'
...
# Subtest: EditModal Escape closes and restores trigger focus
ok 4 - EditModal Escape closes and restores trigger focus
---
duration_ms: 97.270416
type: 'test'
...
# Subtest: EditModal backdrop click closes and restores trigger focus
ok 5 - EditModal backdrop click closes and restores trigger focus
---
duration_ms: 81.214373
type: 'test'
...
# Subtest: EditModal visibility toggle updates button state
ok 6 - EditModal visibility toggle updates button state
---
duration_ms: 72.668177
type: 'test'
...
# Subtest: RevertModal Escape closes and restores trigger focus
ok 7 - RevertModal Escape closes and restores trigger focus
---
duration_ms: 57.157734
type: 'test'
...
# Subtest: static modal helper toggles accessibility hooks
ok 8 - static modal helper toggles accessibility hooks
---
duration_ms: 12.423016
type: 'test'
...
1..8
# tests 8
# suites 0
# pass 8
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 716.147671
→ Running tests/moderation-service.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: trusted report summaries respect personal blocks and admin lists
ok 1 - trusted report summaries respect personal blocks and admin lists
---
duration_ms: 5.136779
type: 'test'
...
# Subtest: user block updates recompute summaries and emit notifications
ok 2 - user block updates recompute summaries and emit notifications
---
duration_ms: 4.31839
type: 'test'
...
# Subtest: moderation thresholds emit logger hooks only when crossing
ok 3 - moderation thresholds emit logger hooks only when crossing
---
duration_ms: 1.617488
type: 'test'
...
# Subtest: trusted mute aggregation tracks F1 mute lists
ok 4 - trusted mute aggregation tracks F1 mute lists
---
duration_ms: 1.869098
type: 'test'
...
# Subtest: viewer mute list publishes and updates aggregation
ok 5 - viewer mute list publishes and updates aggregation
---
duration_ms: 4.351462
type: 'test'
...
1..5
# tests 5
# suites 0
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 31.242407
→ Running tests/moderation-stage.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'c',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 5,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'd',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 3,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'muted',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 0,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'normal',
blockAutoplay: false,
blurThumbnail: false,
trustedCount: 0,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'custom-threshold',
blockAutoplay: false,
blurThumbnail: false,
trustedCount: 4,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'custom-threshold',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 4,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'runtime-threshold',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 3,
reportType: 'nudity',
hidden: true,
hideReason: 'trusted-report-hide',
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'runtime-threshold',
blockAutoplay: false,
blurThumbnail: false,
trustedCount: 3,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'resolver-threshold',
blockAutoplay: false,
blurThumbnail: false,
trustedCount: 2,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'resolver-threshold',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 2,
reportType: 'nudity',
hidden: true,
hideReason: 'trusted-report-hide',
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'whitelisted-video',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 4,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'muted-video',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 3,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'whitelisted-video',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 4,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'muted-video',
blockAutoplay: false,
blurThumbnail: false,
trustedCount: 0,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'viewer-muted',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 0,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: '9999999999999999999999999999999999999999999999999999999999999999',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 1,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: '9999999999999999999999999999999999999999999999999999999999999999',
blockAutoplay: false,
blurThumbnail: false,
trustedCount: 0,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
TAP version 13
# Subtest: moderation stage enforces admin lists without whitelist bypass
ok 1 - moderation stage enforces admin lists without whitelist bypass
---
duration_ms: 5.472572
type: 'test'
...
# Subtest: moderation stage annotates trusted mute metadata
ok 2 - moderation stage annotates trusted mute metadata
---
duration_ms: 1.412272
type: 'test'
...
# Subtest: moderation stage applies provided thresholds
ok 3 - moderation stage applies provided thresholds
---
duration_ms: 1.49677
type: 'test'
...
# Subtest: moderation stage respects runtime threshold changes
ok 4 - moderation stage respects runtime threshold changes
---
duration_ms: 1.667688
type: 'test'
...
# Subtest: moderation stage supports function-based threshold resolvers
ok 5 - moderation stage supports function-based threshold resolvers
---
duration_ms: 1.15711
type: 'test'
...
# Subtest: moderation stage propagates whitelist, muters, and threshold updates
ok 6 - moderation stage propagates whitelist, muters, and threshold updates
---
duration_ms: 1.818141
type: 'test'
...
# Subtest: moderation stage blurs viewer-muted authors
ok 7 - moderation stage blurs viewer-muted authors
---
duration_ms: 0.777393
type: 'test'
...
# Subtest: moderation stage clears cached reporters and muters after service signals
ok 8 - moderation stage clears cached reporters and muters after service signals
---
duration_ms: 1.162641
type: 'test'
...
1..8
# tests 8
# suites 0
# pass 8
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 29.810449
→ Running tests/moderation/hide-thresholds.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: '1111111111111111111111111111111111111111111111111111111111111111',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 0,
reportType: 'nudity',
hidden: true,
hideReason: 'trusted-mute-hide',
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: '2222222222222222222222222222222222222222222222222222222222222222',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 5,
reportType: 'nudity',
hidden: true,
hideReason: 'trusted-report-hide',
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: '6666666666666666666666666666666666666666666666666666666666666666',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 4,
reportType: 'nudity',
hidden: true,
hideReason: 'trusted-mute-hide',
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: '6666666666666666666666666666666666666666666666666666666666666666',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 4,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: '9999999999999999999999999999999999999999999999999999999999999999',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 0,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: '9999999999999999999999999999999999999999999999999999999999999999',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 0,
reportType: 'nudity',
hidden: true,
hideReason: 'trusted-mute-hide',
hideBypass: null
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: '3333333333333333333333333333333333333333333333333333333333333333',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 4,
reportType: 'nudity',
hidden: false,
hideReason: 'trusted-report-hide',
hideBypass: 'feed-policy'
}
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: '4444444444444444444444444444444444444444444444444444444444444444',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 6,
reportType: 'nudity',
hidden: true,
hideReason: 'trusted-report-hide',
hideBypass: null
}
TAP version 13
# Subtest: moderation stage hides videos muted by trusted when threshold met
ok 1 - moderation stage hides videos muted by trusted when threshold met
---
duration_ms: 5.000103
type: 'test'
...
# Subtest: moderation stage hides videos when trusted reports exceed threshold
ok 2 - moderation stage hides videos when trusted reports exceed threshold
---
duration_ms: 1.059393
type: 'test'
...
# Subtest: moderation stage respects runtime hide threshold changes
ok 3 - moderation stage respects runtime hide threshold changes
---
duration_ms: 1.453776
type: 'test'
...
# Subtest: moderation stage supports trusted mute hide resolver functions
ok 4 - moderation stage supports trusted mute hide resolver functions
---
duration_ms: 1.673764
type: 'test'
...
# Subtest: moderation stage bypasses hard hides on home feed
ok 5 - moderation stage bypasses hard hides on home feed
---
duration_ms: 1.304653
type: 'test'
...
# Subtest: moderation stage hides admin-whitelisted videos once thresholds fire
ok 6 - moderation stage hides admin-whitelisted videos once thresholds fire
---
duration_ms: 1.067946
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 25.239371
→ Running tests/moderation/submit-report.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: submitReport emits NIP-56 compliant report tags
ok 1 - submitReport emits NIP-56 compliant report tags
---
duration_ms: 11.293163
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 19.169334
→ Running tests/moderation/trust-seeds.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
TAP version 13
# Subtest: default trust seeds derive from config
ok 1 - default trust seeds derive from config
---
duration_ms: 2.525753
type: 'test'
...
# Subtest: trusted seeds contribute to trusted mute counts
ok 2 - trusted seeds contribute to trusted mute counts
---
duration_ms: 4.961509
type: 'test'
...
# Subtest: trusted seeds contribute to trusted report counts
ok 3 - trusted seeds contribute to trusted report counts
---
duration_ms: 3.041467
type: 'test'
...
# Subtest: trusted seed updates recompute guest report summaries
ok 4 - trusted seed updates recompute guest report summaries
---
duration_ms: 1.395334
type: 'test'
...
# Subtest: moderator seeds populate trusted contacts
ok 5 - moderator seeds populate trusted contacts
---
duration_ms: 0.961815
type: 'test'
...
[trustBootstrap] bootstrapTrustedSeeds called
[trustBootstrap] waitForAccessControl result { ok: true, timedOut: false }
[trustBootstrap] Applying 2 trusted seeds [
'npub15jnttpymeytm80hatjqcvhhqhzrhx6gxp8pq0wn93rhnu8s9h9dsha32lx',
'npub1moderatorexamplemoderatorexamplemoderatorexample1'
]
[trustBootstrap] Applying 2 trusted seeds [
'npub15jnttpymeytm80hatjqcvhhqhzrhx6gxp8pq0wn93rhnu8s9h9dsha32lx',
'npub1moderatorexamplemoderatorexamplemoderatorexample1'
]
[trustBootstrap] Applying 3 trusted seeds [
'npub15jnttpymeytm80hatjqcvhhqhzrhx6gxp8pq0wn93rhnu8s9h9dsha32lx',
'npub1newmoderatorexamplemoderatorexamplemoderator',
'npub1secondmoderatorexamplemoderatorexamplemod'
]
# Subtest: bootstrap seeds track editor roster and ignore whitelist-only changes
ok 6 - bootstrap seeds track editor roster and ignore whitelist-only changes
---
duration_ms: 87.400034
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 3609.738811
→ Running tests/moderation/trusted-mute-lists.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'video-muted',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 0,
reportType: 'nudity',
hidden: true,
hideReason: 'trusted-mute-hide',
hideBypass: null
}
# Subtest: trusted mute lists from seeds hide authors for anonymous viewers
ok 1 - trusted mute lists from seeds hide authors for anonymous viewers
---
duration_ms: 14.641151
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 22.66779
→ Running tests/moderation/trusted-report-count.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
[bitvid] [moderationService] moderation threshold crossed
TAP version 13
# Subtest: trustedReportCount dedupes multiple reports from the same trusted reporter
ok 1 - trustedReportCount dedupes multiple reports from the same trusted reporter
---
duration_ms: 5.900588
type: 'test'
...
# Subtest: trustedReportCount ignores reports from muted or blocked reporters
ok 2 - trustedReportCount ignores reports from muted or blocked reporters
---
duration_ms: 2.910961
type: 'test'
...
# Subtest: blocking and unblocking reporters recomputes trusted summaries
ok 3 - blocking and unblocking reporters recomputes trusted summaries
---
duration_ms: 3.648077
type: 'test'
...
# Subtest: trustedReportCount only counts eligible F1 reporters and admin whitelist
ok 4 - trustedReportCount only counts eligible F1 reporters and admin whitelist
---
duration_ms: 2.56259
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 4
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 29.648246
→ Running tests/moderation/video-card.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: VideoCard renders moderation badges and respects viewer override
ok 1 - VideoCard renders moderation badges and respects viewer override
---
duration_ms: 329.036268
type: 'test'
...
# Subtest: VideoCard hides content when hide metadata is present and override unmasks it
ok 2 - VideoCard hides content when hide metadata is present and override unmasks it
---
duration_ms: 39.040999
type: 'test'
...
# Subtest: VideoCard blurs viewer-muted creators
ok 3 - VideoCard blurs viewer-muted creators
---
duration_ms: 18.340051
type: 'test'
...
# Subtest: VideoCard blurs thumbnails when trusted mute triggers without reports
ok 4 - VideoCard blurs thumbnails when trusted mute triggers without reports
---
duration_ms: 17.192959
type: 'test'
...
# Subtest: VideoCard block action restores trusted mute hide state after override
ok 5 - VideoCard block action restores trusted mute hide state after override
---
duration_ms: 29.059796
type: 'test'
...
# Subtest: applyModerationContextDatasets clears blur when overrides are active
ok 6 - applyModerationContextDatasets clears blur when overrides are active
---
duration_ms: 8.641352
type: 'test'
...
# Subtest: buildModerationBadgeText returns trusted contact block copy when autoplay block and trusted mute combine
ok 7 - buildModerationBadgeText returns trusted contact block copy when autoplay block and trusted mute combine
---
duration_ms: 0.28807
type: 'test'
...
1..7
# tests 7
# suites 0
# pass 7
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 449.805331
→ Running tests/more-menu-controller.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: copy-link action writes to clipboard and shows success
ok 1 - copy-link action writes to clipboard and shows success
---
duration_ms: 3.352528
type: 'test'
...
# Subtest: blacklist-author requires moderator access and refreshes subscriptions
ok 2 - blacklist-author requires moderator access and refreshes subscriptions
---
duration_ms: 0.694916
type: 'test'
...
# Subtest: blacklist-author shows error when no moderator session is available
ok 3 - blacklist-author shows error when no moderator session is available
---
duration_ms: 0.324585
type: 'test'
...
# Subtest: block-author updates user blocks, reloads videos, and refreshes feeds
ok 4 - block-author updates user blocks, reloads videos, and refreshes feeds
---
duration_ms: 0.723132
type: 'test'
...
# Subtest: mute-author updates viewer mute list and refreshes feeds
ok 5 - mute-author updates viewer mute list and refreshes feeds
---
duration_ms: 0.796094
type: 'test'
...
# Subtest: unmute-author removes creators from viewer mute list
ok 6 - unmute-author removes creators from viewer mute list
---
duration_ms: 0.658273
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 19.973263
→ Running tests/nip71-base-event-tags.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: 30078 events carry nip71 metadata tags and hydrate fallback metadata
ok 1 - 30078 events carry nip71 metadata tags and hydrate fallback metadata
---
duration_ms: 5.767242
type: 'test'
...
# Subtest: imeta tags lower-case mime values
ok 2 - imeta tags lower-case mime values
---
duration_ms: 0.620549
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 18.672745
→ Running tests/nip71-builder.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: buildNip71VideoEvent assembles rich metadata
ok 1 - buildNip71VideoEvent assembles rich metadata
---
duration_ms: 5.511834
type: 'test'
...
# Subtest: buildNip71VideoEvent falls back to summary and selects kind
ok 2 - buildNip71VideoEvent falls back to summary and selects kind
---
duration_ms: 0.404613
type: 'test'
...
# Subtest: buildNip71VideoEvent attaches pointer tags
ok 3 - buildNip71VideoEvent attaches pointer tags
---
duration_ms: 0.596327
type: 'test'
...
# Subtest: extractNip71MetadataFromTags parses metadata and pointers
ok 4 - extractNip71MetadataFromTags parses metadata and pointers
---
duration_ms: 1.356091
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 4
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 21.66105
→ Running tests/nip71-form-manager.test.mjs
TAP version 13
# Subtest: collectSection sanitizes and deduplicates hashtags
ok 1 - collectSection sanitizes and deduplicates hashtags
---
duration_ms: 103.866471
type: 'test'
...
# Subtest: hydrateSection renders sanitized hashtags with prefix
ok 2 - hydrateSection renders sanitized hashtags with prefix
---
duration_ms: 22.040454
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 138.250466
→ Running tests/nostr-login-permissions.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
Got pubkey: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
Converted to npub: npub1lllllllllllllllllllllllllllllllllllllllllllllllllllsq7lrjw
Whitelist: []
Blacklist: []
Logged in with extension. Pubkey: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
User logged out.
Got pubkey: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
Converted to npub: npub1lllllllllllllllllllllllllllllllllllllllllllllllllllsq7lrjw
Whitelist: []
Blacklist: []
Logged in with extension. Pubkey: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
User logged out.
[bitvid] [nostr] extension.enable request with explicit permissions failed: Error: object permissions unsupported
at enableImpl (file:///app/tests/nostr-login-permissions.test.mjs:299:31)
at Object.enable (file:///app/tests/nostr-login-permissions.test.mjs:60:32)
at runNip07WithRetry.label (file:///app/js/nostr/nip07Permissions.js:282:36)
at getOrStartOperation (file:///app/js/nostr/nip07Permissions.js:202:41)
at withNip07Timeout (file:///app/js/nostr/nip07Permissions.js:170:23)
at runNip07WithRetry (file:///app/js/nostr/nip07Permissions.js:214:18)
at requestEnablePermissions (file:///app/js/nostr/nip07Permissions.js:281:13)
at NostrClient.ensureExtensionPermissions (file:///app/js/nostr/client.js:2488:32)
at NostrClient.login (file:///app/js/nostr/client.js:3799:43)
at TestContext.<anonymous> (file:///app/tests/nostr-login-permissions.test.mjs:309:38)
Got pubkey: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
Converted to npub: npub1lllllllllllllllllllllllllllllllllllllllllllllllllllsq7lrjw
Whitelist: []
Blacklist: []
Logged in with extension. Pubkey: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
User logged out.
[bitvid] [nostr] extension.enable request with explicit permissions failed: Error: payloads not supported
at enableImpl (file:///app/tests/nostr-login-permissions.test.mjs:342:31)
at Object.enable (file:///app/tests/nostr-login-permissions.test.mjs:60:32)
at runNip07WithRetry.label (file:///app/js/nostr/nip07Permissions.js:282:36)
at getOrStartOperation (file:///app/js/nostr/nip07Permissions.js:202:41)
at withNip07Timeout (file:///app/js/nostr/nip07Permissions.js:170:23)
at runNip07WithRetry (file:///app/js/nostr/nip07Permissions.js:214:18)
at requestEnablePermissions (file:///app/js/nostr/nip07Permissions.js:281:13)
at NostrClient.ensureExtensionPermissions (file:///app/js/nostr/client.js:2488:32)
at NostrClient.login (file:///app/js/nostr/client.js:3799:43)
at TestContext.<anonymous> (file:///app/tests/nostr-login-permissions.test.mjs:349:38)
[bitvid] [nostr] extension.enable request with explicit permissions failed: Error: payloads not supported
at enableImpl (file:///app/tests/nostr-login-permissions.test.mjs:342:31)
at Object.enable (file:///app/tests/nostr-login-permissions.test.mjs:60:32)
at runNip07WithRetry.label (file:///app/js/nostr/nip07Permissions.js:282:36)
at getOrStartOperation (file:///app/js/nostr/nip07Permissions.js:202:41)
at withNip07Timeout (file:///app/js/nostr/nip07Permissions.js:170:23)
at runNip07WithRetry (file:///app/js/nostr/nip07Permissions.js:214:18)
at requestEnablePermissions (file:///app/js/nostr/nip07Permissions.js:281:13)
at async NostrClient.ensureExtensionPermissions (file:///app/js/nostr/client.js:2488:26)
at async NostrClient.login (file:///app/js/nostr/client.js:3799:32)
at async TestContext.<anonymous> (file:///app/tests/nostr-login-permissions.test.mjs:349:20)
Got pubkey: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
Converted to npub: npub1lllllllllllllllllllllllllllllllllllllllllllllllllllsq7lrjw
Whitelist: []
Blacklist: []
Logged in with extension. Pubkey: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
User logged out.
TAP version 13
# Subtest: NIP-07 login requests decrypt permissions upfront
ok 1 - NIP-07 login requests decrypt permissions upfront
---
duration_ms: 8.958341
type: 'test'
...
# Subtest: NIP-07 decrypt reuses cached extension permissions
ok 2 - NIP-07 decrypt reuses cached extension permissions
---
duration_ms: 2.74935
type: 'test'
...
# Subtest: NIP-07 login falls back when structured permissions fail
ok 3 - NIP-07 login falls back when structured permissions fail
---
duration_ms: 2.865024
type: 'test'
...
# Subtest: NIP-07 login supports extensions that only allow enable() without payload
ok 4 - NIP-07 login supports extensions that only allow enable() without payload
---
duration_ms: 2.399392
type: 'test'
...
[bitvid] [nostr] extension.enable request with explicit permissions failed: Error: Timed out waiting for the NIP-07 extension. Confirm the extension prompt in your browser toolbar and try again.
at Timeout.<anonymous> (file:///app/js/nostr/nip07Permissions.js:164:14)
at listOnTimeout (node:internal/timers:588:17)
at process.processTimers (node:internal/timers:523:7)
Got pubkey: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
Converted to npub: npub1lllllllllllllllllllllllllllllllllllllllllllllllllllsq7lrjw
Whitelist: []
Blacklist: []
Logged in with extension. Pubkey: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
User logged out.
[bitvid] [nostr] extension.enable request with explicit permissions failed: Error: permission denied
at enableImpl (file:///app/tests/nostr-login-permissions.test.mjs:430:29)
at Object.enable (file:///app/tests/nostr-login-permissions.test.mjs:60:32)
at runNip07WithRetry.label (file:///app/js/nostr/nip07Permissions.js:282:36)
at getOrStartOperation (file:///app/js/nostr/nip07Permissions.js:202:41)
at withNip07Timeout (file:///app/js/nostr/nip07Permissions.js:170:23)
at runNip07WithRetry (file:///app/js/nostr/nip07Permissions.js:214:18)
at requestEnablePermissions (file:///app/js/nostr/nip07Permissions.js:281:13)
at NostrClient.ensureExtensionPermissions (file:///app/js/nostr/client.js:2488:32)
at NostrClient.login (file:///app/js/nostr/client.js:3799:43)
at file:///app/tests/nostr-login-permissions.test.mjs:435:44
[bitvid] [nostr] extension.enable request with explicit permissions failed: Error: permission denied
at enableImpl (file:///app/tests/nostr-login-permissions.test.mjs:430:29)
at Object.enable (file:///app/tests/nostr-login-permissions.test.mjs:60:32)
at runNip07WithRetry.label (file:///app/js/nostr/nip07Permissions.js:282:36)
at getOrStartOperation (file:///app/js/nostr/nip07Permissions.js:202:41)
at withNip07Timeout (file:///app/js/nostr/nip07Permissions.js:170:23)
at runNip07WithRetry (file:///app/js/nostr/nip07Permissions.js:214:18)
at requestEnablePermissions (file:///app/js/nostr/nip07Permissions.js:281:13)
at async NostrClient.ensureExtensionPermissions (file:///app/js/nostr/client.js:2488:26)
at async NostrClient.login (file:///app/js/nostr/client.js:3799:32)
at async waitForActual (node:assert:644:5)
[bitvid] Login error: Error: The NIP-07 extension reported "permission denied". Please approve the prompt and try again.
at NostrClient.login (file:///app/js/nostr/client.js:3805:29)
at async waitForActual (node:assert:644:5)
at async Function.rejects (node:assert:767:25)
at async TestContext.<anonymous> (file:///app/tests/nostr-login-permissions.test.mjs:435:5)
at async Test.run (node:internal/test_runner/test:1054:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:744:7) {
cause: Error: permission denied
at enableImpl (file:///app/tests/nostr-login-permissions.test.mjs:430:29)
at Object.enable (file:///app/tests/nostr-login-permissions.test.mjs:60:32)
at runNip07WithRetry.label (file:///app/js/nostr/nip07Permissions.js:282:64)
at getOrStartOperation (file:///app/js/nostr/nip07Permissions.js:202:41)
at withNip07Timeout (file:///app/js/nostr/nip07Permissions.js:170:23)
at runNip07WithRetry (file:///app/js/nostr/nip07Permissions.js:214:18)
at requestEnablePermissions (file:///app/js/nostr/nip07Permissions.js:281:13)
at async NostrClient.ensureExtensionPermissions (file:///app/js/nostr/client.js:2488:26)
at async NostrClient.login (file:///app/js/nostr/client.js:3799:32)
at async waitForActual (node:assert:644:5)
}
User logged out.
# Subtest: NIP-07 login quickly retries when a permission payload stalls
ok 5 - NIP-07 login quickly retries when a permission payload stalls
---
duration_ms: 82.359752
type: 'test'
...
# Subtest: NIP-07 login surfaces enable permission errors
ok 6 - NIP-07 login surfaces enable permission errors
---
duration_ms: 2.871493
type: 'test'
...
# Subtest: runNip07WithRetry respects timeout without retry multiplier
ok 7 - runNip07WithRetry respects timeout without retry multiplier
---
duration_ms: 61.183634
type: 'test'
...
1..7
# tests 7
# suites 0
# pass 7
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 172.793518
→ Running tests/nostr-private-key-signer.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: registerPrivateKeySigner exposes nip04 helpers
ok 1 - registerPrivateKeySigner exposes nip04 helpers
---
duration_ms: 213.347804
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 236.30689
→ Running tests/nostr-send-direct-message.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
TAP version 13
# Subtest: sendDirectMessage succeeds with private key signer and no extension
ok 1 - sendDirectMessage succeeds with private key signer and no extension
---
duration_ms: 224.825469
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 246.791889
→ Running tests/nostr-service-access-control.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
[moderationService] reconcileTrustedMuteSubscriptions { previous: 0, next: 0 }
[moderationService] subscribing to trusted mute list for 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
(moderationService) ensurePool failed while subscribing to trusted mute list for 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef Error: nostr-client-unavailable
at ModerationService.ensurePool (file:///app/js/services/moderationService.js:1842:13)
at file:///app/js/services/moderationService.js:1128:20
at ModerationService.subscribeToTrustedMuteList (file:///app/js/services/moderationService.js:1195:7)
at ModerationService.reconcileTrustedMuteSubscriptions (file:///app/js/services/moderationService.js:1076:12)
at ModerationService.rebuildTrustedContacts (file:///app/js/services/moderationService.js:655:10)
at ModerationService.clearTrustedMuteTracking (file:///app/js/services/moderationService.js:1039:10)
at ModerationService.setViewerPubkey (file:///app/js/services/moderationService.js:1887:10)
at ModerationService.refreshViewerFromClient (file:///app/js/services/moderationService.js:1861:17)
at NostrService.getModerationService (file:///app/js/services/nostrService.js:870:32)
at NostrService.isViewerVideoAuthor (file:///app/js/services/nostrService.js:1706:12)
[moderationService] ensurePool failed while fetching contacts Error: nostr-client-unavailable
at ModerationService.ensurePool (file:///app/js/services/moderationService.js:1842:13)
at ModerationService.fetchTrustedContacts (file:///app/js/services/moderationService.js:1937:18)
at ModerationService.setViewerPubkey (file:///app/js/services/moderationService.js:1903:36)
at ModerationService.refreshViewerFromClient (file:///app/js/services/moderationService.js:1861:17)
at NostrService.getModerationService (file:///app/js/services/nostrService.js:870:32)
at NostrService.isViewerVideoAuthor (file:///app/js/services/nostrService.js:1706:12)
at NostrService.shouldIncludeVideo (file:///app/js/services/nostrService.js:1002:33)
at TestContext.<anonymous> (file:///app/tests/nostr-service-access-control.test.mjs:143:13)
at Test.runInAsyncScope (node:async_hooks:214:14)
at Test.run (node:internal/test_runner/test:1047:25)
[moderationService] ensurePool failed while subscribing to contacts Error: nostr-client-unavailable
at ModerationService.ensurePool (file:///app/js/services/moderationService.js:1842:13)
at ModerationService.subscribeToContactList (file:///app/js/services/moderationService.js:2011:18)
at ModerationService.setViewerPubkey (file:///app/js/services/moderationService.js:1918:10)
TAP version 13
# Subtest: shouldIncludeVideo returns true for whitelist author when npubEncode throws
ok 1 - shouldIncludeVideo returns true for whitelist author when npubEncode throws
---
duration_ms: 1.95596
type: 'test'
...
# Subtest: shouldIncludeVideo rejects blacklisted authors provided as npub
ok 2 - shouldIncludeVideo rejects blacklisted authors provided as npub
---
duration_ms: 0.455841
type: 'test'
...
# Subtest: shouldIncludeVideo rejects blacklisted authors provided as hex when npubEncode throws
ok 3 - shouldIncludeVideo rejects blacklisted authors provided as hex when npubEncode throws
---
duration_ms: 0.482175
type: 'test'
...
# Subtest: shouldIncludeVideo always returns true for the viewer's own video
ok 4 - shouldIncludeVideo always returns true for the viewer's own video
---
duration_ms: 5.13633
type: 'test'
...
# Subtest: shouldIncludeVideo allows access when access control would deny the author
ok 5 - shouldIncludeVideo allows access when access control would deny the author
---
duration_ms: 49.238852
type: 'test'
...
[moderationService] subscribing to trusted mute list for 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
(moderationService) ensurePool failed while subscribing to trusted mute list for 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef Error: nostr-client-unavailable
at ModerationService.ensurePool (file:///app/js/services/moderationService.js:1842:13)
at file:///app/js/services/moderationService.js:1128:20
at ModerationService.subscribeToTrustedMuteList (file:///app/js/services/moderationService.js:1195:7)
at ModerationService.ensureViewerMuteListLoaded (file:///app/js/services/moderationService.js:1516:35)
at ModerationService.setViewerPubkey (file:///app/js/services/moderationService.js:1923:16)