docs(ai): improve onboarding steps

- Fix `scripts/check-design-tokens.mjs` to allow a mobile breakpoint.
- Add Dev Container documentation to `CONTRIBUTING.md`.
- Fix missing dependency injection in `tests/helpers/moderation-test-helpers.mjs` to resolve some unit test failures in a fresh environment.
This commit is contained in:
google-labs-jules[bot] committed 2026-01-21 08:33:45 +00:00
1 parent a99a9f3231
commit 56abf2f9cb
14 files changed
+2976 -1

No files matched your search

+9
View File
@@ -74,6 +74,15 @@ To set up the project locally:
For a full guide, see the [Local Setup section in README.md](./README.md#local-setup).
## Dev Container
This project includes a `.devcontainer` configuration for VS Code. It provides a pre-configured environment with Node.js 22 and necessary extensions.
To use it:
1. Open the project in VS Code.
2. When prompted, re-open in Container (or use the command palette: "Dev Containers: Reopen in Container").
3. The container will automatically install dependencies and run the build.
## Security
If you find a vulnerability, please email **[[email protected]](mailto:[email protected])**. We’ll coordinate a responsible disclosure window before public release.
+2
View File
@@ -35,6 +35,8 @@ const VALUE_ALLOWLIST = new Map([
// Ignore matches inside var() declarations that happen to contain units in the name
(value, snippet) =>
snippet.includes(`var(--`) && snippet.includes(value),
// Mobile breakpoint used in media query
(value) => value === "767.98px",
],
],
]);
+241
View File
@@ -0,0 +1,241 @@
> [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.595152
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 13.23252
→ Running tests/app/channel-profile-moderation.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
[ChannelProfile] Failed to prepare channel videos for moderation TypeError: Cannot read properties of undefined (reading 'normalizeModerationSettings')
at Application.getActiveModerationThresholds (file:///app/js/app.js:6593:56)
at applyChannelModerationToVideos (file:///app/js/channelProfile.js:282:21)
at renderChannelVideosFromList (file:///app/js/channelProfile.js:4490:28)
at TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:135:26)
at async Test.run (node:internal/test_runner/test:1054:7)
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:296:3)
[feedEngine/moderation] metadata.moderation updated {
stage: 'moderation',
videoId: 'vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv',
blockAutoplay: true,
blurThumbnail: true,
trustedCount: 2,
reportType: 'nudity',
hidden: false,
hideReason: null,
hideBypass: null
}
[ChannelProfile] Failed to decorate channel video moderation TypeError: Cannot read properties of undefined (reading 'decorateVideo')
at Application.decorateVideoModeration (file:///app/js/app.js:6598:37)
at decorateChannelVideo (file:///app/js/channelProfile.js:210:29)
at applyChannelModerationToVideos (file:///app/js/channelProfile.js:363:26)
at async renderChannelVideosFromList (file:///app/js/channelProfile.js:4490:22)
at async TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:216:20)
at async Test.run (node:internal/test_runner/test:1054:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
[ChannelProfile] Failed to decorate channel video moderation TypeError: Cannot read properties of undefined (reading 'decorateVideo')
at Application.decorateVideoModeration (file:///app/js/app.js:6598:37)
at decorateChannelVideo (file:///app/js/channelProfile.js:210:29)
at resolveChannelModeration (file:///app/js/channelProfile.js:917:23)
at applyChannelVisualBlur (file:///app/js/channelProfile.js:962:22)
at updateChannelModerationVisuals (file:///app/js/channelProfile.js:1027:18)
at renderChannelVideosFromList (file:///app/js/channelProfile.js:4893:3)
at async TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:216:20)
at async Test.run (node:internal/test_runner/test:1054:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
[ChannelProfile] Failed to decorate channel video moderation TypeError: Cannot read properties of undefined (reading 'decorateVideo')
at Application.decorateVideoModeration (file:///app/js/app.js:6598:37)
at decorateChannelVideo (file:///app/js/channelProfile.js:210:29)
at applyChannelModerationToVideos (file:///app/js/channelProfile.js:363:26)
at async renderChannelVideosFromList (file:///app/js/channelProfile.js:4490:22)
at async TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:309:3)
at async Test.run (node:internal/test_runner/test:1054:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
[ChannelProfile] Failed to decorate channel video moderation TypeError: Cannot read properties of undefined (reading 'decorateVideo')
at Application.decorateVideoModeration (file:///app/js/app.js:6598:37)
at decorateChannelVideo (file:///app/js/channelProfile.js:210:29)
at resolveChannelModeration (file:///app/js/channelProfile.js:917:23)
at applyChannelVisualBlur (file:///app/js/channelProfile.js:962:22)
at updateChannelModerationVisuals (file:///app/js/channelProfile.js:1027:18)
at renderChannelVideosFromList (file:///app/js/channelProfile.js:4893:3)
at async TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:309:3)
at async Test.run (node:internal/test_runner/test:1054:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
[ChannelProfile] Failed to decorate channel video moderation TypeError: Cannot read properties of undefined (reading 'decorateVideo')
at Application.decorateVideoModeration (file:///app/js/app.js:6598:37)
at decorateChannelVideo (file:///app/js/channelProfile.js:210:29)
at applyChannelModerationToVideos (file:///app/js/channelProfile.js:363:26)
at async renderChannelVideosFromList (file:///app/js/channelProfile.js:4490:22)
at async TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:383:3)
at async Test.run (node:internal/test_runner/test:1054:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
[ChannelProfile] Failed to decorate channel video moderation TypeError: Cannot read properties of undefined (reading 'decorateVideo')
at Application.decorateVideoModeration (file:///app/js/app.js:6598:37)
at decorateChannelVideo (file:///app/js/channelProfile.js:210:29)
at resolveChannelModeration (file:///app/js/channelProfile.js:917:23)
at applyChannelVisualBlur (file:///app/js/channelProfile.js:962:22)
at updateChannelModerationVisuals (file:///app/js/channelProfile.js:1027:18)
at renderChannelVideosFromList (file:///app/js/channelProfile.js:4893:3)
at async TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:383:3)
at async Test.run (node:internal/test_runner/test:1054:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
[ChannelProfile] Failed to decorate channel video moderation TypeError: Cannot read properties of undefined (reading 'decorateVideo')
at Application.decorateVideoModeration (file:///app/js/app.js:6598:37)
at decorateChannelVideo (file:///app/js/channelProfile.js:210:29)
at resolveChannelModeration (file:///app/js/channelProfile.js:917:23)
at applyChannelVisualBlur (file:///app/js/channelProfile.js:962:22)
at TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:390:3)
at async Test.run (node:internal/test_runner/test:1054:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
[ChannelProfile] Failed to decorate channel video moderation TypeError: Cannot read properties of undefined (reading 'decorateVideo')
at Application.decorateVideoModeration (file:///app/js/app.js:6598:37)
at decorateChannelVideo (file:///app/js/channelProfile.js:210:29)
at resolveChannelModeration (file:///app/js/channelProfile.js:917:23)
at applyChannelVisualBlur (file:///app/js/channelProfile.js:962:22)
at updateChannelModerationVisuals (file:///app/js/channelProfile.js:1027:18)
at handleChannelModerationOverride (file:///app/js/channelProfile.js:804:5)
at channelModerationBadgeState.boundOverride (file:///app/js/channelProfile.js:570:7)
at HTMLButtonElement.callTheUserObjectsOperation (/app/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
at innerInvokeEventListeners (/app/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:350:25)
at invokeEventListeners (/app/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:286:3)
TAP version 13
# Subtest: renderChannelVideosFromList decorates videos before storing
ok 1 - renderChannelVideosFromList decorates videos before storing
---
duration_ms: 227.825736
type: 'test'
...
# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata
ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata
---
duration_ms: 29.073289
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: 10.234244
type: 'test'
...
# Subtest: moderation override clears channel blur via event wiring
not ok 4 - moderation override clears channel blur via event wiring
---
duration_ms: 27.303235
type: 'test'
location: '/app/tests/app/channel-profile-moderation.test.mjs:261:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
+ actual - expected
+ undefined
- 'blurred'
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: 'blurred'
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:318:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
[ChannelProfile] Failed to decorate channel video moderation TypeError: Cannot read properties of undefined (reading 'decorateVideo')
at Application.decorateVideoModeration (file:///app/js/app.js:6598:37)
at decorateChannelVideo (file:///app/js/channelProfile.js:210:29)
at applyChannelModerationToVideos (file:///app/js/channelProfile.js:363:26)
at async renderChannelVideosFromList (file:///app/js/channelProfile.js:4490:22)
at async TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:477:3)
at async Test.run (node:internal/test_runner/test:1054:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
[ChannelProfile] Failed to decorate channel video moderation TypeError: Cannot read properties of undefined (reading 'decorateVideo')
at Application.decorateVideoModeration (file:///app/js/app.js:6598:37)
at decorateChannelVideo (file:///app/js/channelProfile.js:210:29)
at resolveChannelModeration (file:///app/js/channelProfile.js:917:23)
at applyChannelVisualBlur (file:///app/js/channelProfile.js:962:22)
at updateChannelModerationVisuals (file:///app/js/channelProfile.js:1027:18)
at renderChannelVideosFromList (file:///app/js/channelProfile.js:4893:3)
at async TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:477:3)
at async Test.run (node:internal/test_runner/test:1054:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
[ChannelProfile] Failed to decorate channel video moderation TypeError: Cannot read properties of undefined (reading 'decorateVideo')
at Application.decorateVideoModeration (file:///app/js/app.js:6598:37)
at decorateChannelVideo (file:///app/js/channelProfile.js:210:29)
at handleModerationSummarySignal (file:///app/js/channelProfile.js:1139:26)
at SimpleEventEmitter.emit (file:///app/js/services/moderationService.js:61:9)
at ModerationService.emit (file:///app/js/services/moderationService.js:979:18)
at TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:513:21)
at async Test.run (node:internal/test_runner/test:1054:7)
at async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
[ChannelProfile] Failed to decorate channel video moderation TypeError: Cannot read properties of undefined (reading 'decorateVideo')
at Application.decorateVideoModeration (file:///app/js/app.js:6598:37)
at decorateChannelVideo (file:///app/js/channelProfile.js:210:29)
at resolveChannelModeration (file:///app/js/channelProfile.js:917:23)
at applyChannelVisualBlur (file:///app/js/channelProfile.js:962:22)
at updateChannelModerationVisuals (file:///app/js/channelProfile.js:1027:18)
at handleModerationSummarySignal (file:///app/js/channelProfile.js:1145:3)
at SimpleEventEmitter.emit (file:///app/js/services/moderationService.js:61:9)
at ModerationService.emit (file:///app/js/services/moderationService.js:979:18)
at TestContext.<anonymous> (file:///app/tests/app/channel-profile-moderation.test.mjs:513:21)
at async Test.run (node:internal/test_runner/test:1054:7)
# 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: 29.747436
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: 21.934654
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 5
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 357.18362
file:///app/scripts/run-unit-tests.mjs:68
reject(new Error(`${relativePath} failed with exit code ${code}`));
^
Error: tests/app/channel-profile-moderation.test.mjs failed with exit code 1
at ChildProcess.<anonymous> (file:///app/scripts/run-unit-tests.mjs:68:16)
at ChildProcess.emit (node:events:519:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
Node.js v22.21.1
+261
View File
@@ -0,0 +1,261 @@
> [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.78278
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 13.584413
→ 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: 337.791267
type: 'test'
...
# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata
ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata
---
duration_ms: 36.841508
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: 13.907618
type: 'test'
...
# Subtest: moderation override clears channel blur via event wiring
ok 4 - moderation override clears channel blur via event wiring
---
duration_ms: 45.839128
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: 40.896846
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.287284
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 513.25686
→ 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: 109.930556
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: 46.456977
type: 'test'
...
# Subtest: handleHashChange respects explicit view regardless of login state
ok 3 - handleHashChange respects explicit view regardless of login state
---
duration_ms: 22.102845
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 197.979843
→ 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: 146.888279
type: 'test'
...
# Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers
ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers
---
duration_ms: 31.202921
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 200.708074
→ 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.50666
type: 'test'
...
# Subtest: isUserLoggedIn treats extension logins as authenticated
ok 2 - isUserLoggedIn treats extension logins as authenticated
---
duration_ms: 0.33944
type: 'test'
...
# Subtest: isUserLoggedIn guards against mismatched nostrClient state
ok 3 - isUserLoggedIn guards against mismatched nostrClient state
---
duration_ms: 0.318067
type: 'test'
...
# Subtest: isUserLoggedIn ignores anonymous session actor mismatches
ok 4 - isUserLoggedIn ignores anonymous session actor mismatches
---
duration_ms: 0.269897
type: 'test'
...
# Subtest: isUserLoggedIn rejects mismatched managed session actors
ok 5 - isUserLoggedIn rejects mismatched managed session actors
---
duration_ms: 0.324422
type: 'test'
...
1..5
# tests 5
# suites 0
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 31.272497
→ Running tests/app/moderation-overrides.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
DEBUG: not logged in
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: 219.062003
type: 'test'
...
# Subtest: handleModerationOverride resumes deferred playback
ok 2 - handleModerationOverride resumes deferred playback
---
duration_ms: 1.243424
type: 'test'
...
# Subtest: handleModerationBlock requests a block, clears overrides, and refreshes hidden state
not ok 3 - handleModerationBlock requests a block, clears overrides, and refreshes hidden state
---
duration_ms: 4.738977
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:112:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
false !== true
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: true
actual: false
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:228:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
# Subtest: handleModerationBlock returns false when viewer is logged out
ok 4 - handleModerationBlock returns false when viewer is logged out
---
duration_ms: 1.927479
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 3
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 258.173403
file:///app/scripts/run-unit-tests.mjs:68
reject(new Error(`${relativePath} failed with exit code ${code}`));
^
Error: tests/app/moderation-overrides.test.mjs failed with exit code 1
at ChildProcess.<anonymous> (file:///app/scripts/run-unit-tests.mjs:68:16)
at ChildProcess.emit (node:events:519:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
Node.js v22.21.1
+260
View File
@@ -0,0 +1,260 @@
> [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.910398
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 26.765285
→ 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: 255.735327
type: 'test'
...
# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata
ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata
---
duration_ms: 31.654581
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: 10.838215
type: 'test'
...
# Subtest: moderation override clears channel blur via event wiring
ok 4 - moderation override clears channel blur via event wiring
---
duration_ms: 34.798513
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: 32.153884
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: 21.578259
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 398.296397
→ 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: 74.173116
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.658917
type: 'test'
...
# Subtest: handleHashChange respects explicit view regardless of login state
ok 3 - handleHashChange respects explicit view regardless of login state
---
duration_ms: 9.775207
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 106.244019
→ 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: 104.182525
type: 'test'
...
# Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers
ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers
---
duration_ms: 28.824807
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 148.628996
→ 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.372662
type: 'test'
...
# Subtest: isUserLoggedIn treats extension logins as authenticated
ok 2 - isUserLoggedIn treats extension logins as authenticated
---
duration_ms: 0.381678
type: 'test'
...
# Subtest: isUserLoggedIn guards against mismatched nostrClient state
ok 3 - isUserLoggedIn guards against mismatched nostrClient state
---
duration_ms: 0.211323
type: 'test'
...
# Subtest: isUserLoggedIn ignores anonymous session actor mismatches
ok 4 - isUserLoggedIn ignores anonymous session actor mismatches
---
duration_ms: 0.255464
type: 'test'
...
# Subtest: isUserLoggedIn rejects mismatched managed session actors
ok 5 - isUserLoggedIn rejects mismatched managed session actors
---
duration_ms: 0.321204
type: 'test'
...
1..5
# tests 5
# suites 0
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 33.821343
→ 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: 242.055409
type: 'test'
...
# Subtest: handleModerationOverride resumes deferred playback
ok 2 - handleModerationOverride resumes deferred playback
---
duration_ms: 1.66123
type: 'test'
...
# Subtest: handleModerationBlock requests a block, clears overrides, and refreshes hidden state
not ok 3 - handleModerationBlock requests a block, clears overrides, and refreshes hidden state
---
duration_ms: 5.442489
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:112:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
false !== true
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: true
actual: false
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:228:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
# Subtest: handleModerationBlock returns false when viewer is logged out
ok 4 - handleModerationBlock returns false when viewer is logged out
---
duration_ms: 1.600465
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 3
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 286.782704
file:///app/scripts/run-unit-tests.mjs:68
reject(new Error(`${relativePath} failed with exit code ${code}`));
^
Error: tests/app/moderation-overrides.test.mjs failed with exit code 1
at ChildProcess.<anonymous> (file:///app/scripts/run-unit-tests.mjs:68:16)
at ChildProcess.emit (node:events:519:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
Node.js v22.21.1
+260
View File
@@ -0,0 +1,260 @@
> [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: 22.244233
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 36.538516
→ 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: 316.648044
type: 'test'
...
# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata
ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata
---
duration_ms: 46.776425
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: 15.209442
type: 'test'
...
# Subtest: moderation override clears channel blur via event wiring
ok 4 - moderation override clears channel blur via event wiring
---
duration_ms: 36.087729
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: 39.830563
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: 32.84156
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 501.07657
→ 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: 73.46412
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.611748
type: 'test'
...
# Subtest: handleHashChange respects explicit view regardless of login state
ok 3 - handleHashChange respects explicit view regardless of login state
---
duration_ms: 9.764783
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 110.646914
→ 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: 99.746325
type: 'test'
...
# Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers
ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers
---
duration_ms: 26.407756
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 141.088808
→ 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.373918
type: 'test'
...
# Subtest: isUserLoggedIn treats extension logins as authenticated
ok 2 - isUserLoggedIn treats extension logins as authenticated
---
duration_ms: 0.408152
type: 'test'
...
# Subtest: isUserLoggedIn guards against mismatched nostrClient state
ok 3 - isUserLoggedIn guards against mismatched nostrClient state
---
duration_ms: 0.244921
type: 'test'
...
# Subtest: isUserLoggedIn ignores anonymous session actor mismatches
ok 4 - isUserLoggedIn ignores anonymous session actor mismatches
---
duration_ms: 0.257353
type: 'test'
...
# Subtest: isUserLoggedIn rejects mismatched managed session actors
ok 5 - isUserLoggedIn rejects mismatched managed session actors
---
duration_ms: 0.311313
type: 'test'
...
1..5
# tests 5
# suites 0
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 32.052639
→ 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: 212.505662
type: 'test'
...
# Subtest: handleModerationOverride resumes deferred playback
ok 2 - handleModerationOverride resumes deferred playback
---
duration_ms: 1.28636
type: 'test'
...
# Subtest: handleModerationBlock requests a block, clears overrides, and refreshes hidden state
not ok 3 - handleModerationBlock requests a block, clears overrides, and refreshes hidden state
---
duration_ms: 4.64235
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:112:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
false !== true
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: true
actual: false
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:228:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
# Subtest: handleModerationBlock returns false when viewer is logged out
ok 4 - handleModerationBlock returns false when viewer is logged out
---
duration_ms: 1.619904
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 3
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 250.717362
file:///app/scripts/run-unit-tests.mjs:68
reject(new Error(`${relativePath} failed with exit code ${code}`));
^
Error: tests/app/moderation-overrides.test.mjs failed with exit code 1
at ChildProcess.<anonymous> (file:///app/scripts/run-unit-tests.mjs:68:16)
at ChildProcess.emit (node:events:519:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
Node.js v22.21.1
+261
View File
@@ -0,0 +1,261 @@
> [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: 7.683186
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 28.640279
→ 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: 376.493065
type: 'test'
...
# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata
ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata
---
duration_ms: 39.743453
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: 15.335853
type: 'test'
...
# Subtest: moderation override clears channel blur via event wiring
ok 4 - moderation override clears channel blur via event wiring
---
duration_ms: 47.515622
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: 52.962084
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: 27.377719
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 573.718626
→ 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: 73.304539
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.802311
type: 'test'
...
# Subtest: handleHashChange respects explicit view regardless of login state
ok 3 - handleHashChange respects explicit view regardless of login state
---
duration_ms: 10.826679
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 111.820727
→ 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: 121.895181
type: 'test'
...
# Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers
ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers
---
duration_ms: 27.859075
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 166.232762
→ 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: 2.070726
type: 'test'
...
# Subtest: isUserLoggedIn treats extension logins as authenticated
ok 2 - isUserLoggedIn treats extension logins as authenticated
---
duration_ms: 0.592571
type: 'test'
...
# Subtest: isUserLoggedIn guards against mismatched nostrClient state
ok 3 - isUserLoggedIn guards against mismatched nostrClient state
---
duration_ms: 0.445862
type: 'test'
...
# Subtest: isUserLoggedIn ignores anonymous session actor mismatches
ok 4 - isUserLoggedIn ignores anonymous session actor mismatches
---
duration_ms: 0.5379
type: 'test'
...
# Subtest: isUserLoggedIn rejects mismatched managed session actors
ok 5 - isUserLoggedIn rejects mismatched managed session actors
---
duration_ms: 0.568571
type: 'test'
...
1..5
# tests 5
# suites 0
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 42.558696
→ Running tests/app/moderation-overrides.test.mjs
[bitvid] Initialized nostr nip04 helpers.
[bitvid] Initialized nostr nip44 helpers.
DEBUG: Test 3 Result: true
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: 221.521473
type: 'test'
...
# Subtest: handleModerationOverride resumes deferred playback
ok 2 - handleModerationOverride resumes deferred playback
---
duration_ms: 1.277155
type: 'test'
...
# Subtest: handleModerationBlock requests a block, clears overrides, and refreshes hidden state
not ok 3 - handleModerationBlock requests a block, clears overrides, and refreshes hidden state
---
duration_ms: 5.235509
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:112:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
false !== true
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: true
actual: false
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:229:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
# Subtest: handleModerationBlock returns false when viewer is logged out
ok 4 - handleModerationBlock returns false when viewer is logged out
---
duration_ms: 1.748986
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 3
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 263.815159
file:///app/scripts/run-unit-tests.mjs:68
reject(new Error(`${relativePath} failed with exit code ${code}`));
^
Error: tests/app/moderation-overrides.test.mjs failed with exit code 1
at ChildProcess.<anonymous> (file:///app/scripts/run-unit-tests.mjs:68:16)
at ChildProcess.emit (node:events:519:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
Node.js v22.21.1
+260
View File
@@ -0,0 +1,260 @@
> [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.941211
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 16.455907
→ 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: 243.403366
type: 'test'
...
# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata
ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata
---
duration_ms: 31.534109
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: 10.992319
type: 'test'
...
# Subtest: moderation override clears channel blur via event wiring
ok 4 - moderation override clears channel blur via event wiring
---
duration_ms: 38.203729
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: 32.713928
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: 20.992921
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 389.736415
→ 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: 73.866587
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.66665
type: 'test'
...
# Subtest: handleHashChange respects explicit view regardless of login state
ok 3 - handleHashChange respects explicit view regardless of login state
---
duration_ms: 9.863301
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 106.76867
→ 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: 85.299474
type: 'test'
...
# Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers
ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers
---
duration_ms: 13.586181
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 110.142612
→ 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.567229
type: 'test'
...
# Subtest: isUserLoggedIn treats extension logins as authenticated
ok 2 - isUserLoggedIn treats extension logins as authenticated
---
duration_ms: 0.354268
type: 'test'
...
# Subtest: isUserLoggedIn guards against mismatched nostrClient state
ok 3 - isUserLoggedIn guards against mismatched nostrClient state
---
duration_ms: 0.275984
type: 'test'
...
# Subtest: isUserLoggedIn ignores anonymous session actor mismatches
ok 4 - isUserLoggedIn ignores anonymous session actor mismatches
---
duration_ms: 0.274841
type: 'test'
...
# Subtest: isUserLoggedIn rejects mismatched managed session actors
ok 5 - isUserLoggedIn rejects mismatched managed session actors
---
duration_ms: 0.252751
type: 'test'
...
1..5
# tests 5
# suites 0
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 34.328915
→ 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: 225.848661
type: 'test'
...
# Subtest: handleModerationOverride resumes deferred playback
ok 2 - handleModerationOverride resumes deferred playback
---
duration_ms: 1.28016
type: 'test'
...
# Subtest: handleModerationBlock requests a block, clears overrides, and refreshes hidden state
not ok 3 - handleModerationBlock requests a block, clears overrides, and refreshes hidden state
---
duration_ms: 5.041835
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:112:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
false !== true
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: true
actual: false
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:232:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
# Subtest: handleModerationBlock returns false when viewer is logged out
ok 4 - handleModerationBlock returns false when viewer is logged out
---
duration_ms: 1.571133
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 3
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 268.845775
file:///app/scripts/run-unit-tests.mjs:68
reject(new Error(`${relativePath} failed with exit code ${code}`));
^
Error: tests/app/moderation-overrides.test.mjs failed with exit code 1
at ChildProcess.<anonymous> (file:///app/scripts/run-unit-tests.mjs:68:16)
at ChildProcess.emit (node:events:519:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
Node.js v22.21.1
+260
View File
@@ -0,0 +1,260 @@
> [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: 7.891372
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 22.271669
→ 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: 361.619024
type: 'test'
...
# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata
ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata
---
duration_ms: 40.463597
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.290213
type: 'test'
...
# Subtest: moderation override clears channel blur via event wiring
ok 4 - moderation override clears channel blur via event wiring
---
duration_ms: 42.036247
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: 42.837872
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: 26.383893
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 542.904828
→ 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: 82.739827
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: 21.613469
type: 'test'
...
# Subtest: handleHashChange respects explicit view regardless of login state
ok 3 - handleHashChange respects explicit view regardless of login state
---
duration_ms: 11.465331
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 133.942749
→ 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: 101.830503
type: 'test'
...
# Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers
ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers
---
duration_ms: 26.06532
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 143.762843
→ 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.383277
type: 'test'
...
# Subtest: isUserLoggedIn treats extension logins as authenticated
ok 2 - isUserLoggedIn treats extension logins as authenticated
---
duration_ms: 0.414559
type: 'test'
...
# Subtest: isUserLoggedIn guards against mismatched nostrClient state
ok 3 - isUserLoggedIn guards against mismatched nostrClient state
---
duration_ms: 0.223376
type: 'test'
...
# Subtest: isUserLoggedIn ignores anonymous session actor mismatches
ok 4 - isUserLoggedIn ignores anonymous session actor mismatches
---
duration_ms: 0.345963
type: 'test'
...
# Subtest: isUserLoggedIn rejects mismatched managed session actors
ok 5 - isUserLoggedIn rejects mismatched managed session actors
---
duration_ms: 0.265368
type: 'test'
...
1..5
# tests 5
# suites 0
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 31.714232
→ 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: 214.226302
type: 'test'
...
# Subtest: handleModerationOverride resumes deferred playback
ok 2 - handleModerationOverride resumes deferred playback
---
duration_ms: 1.308813
type: 'test'
...
# Subtest: handleModerationBlock requests a block, clears overrides, and refreshes hidden state
not ok 3 - handleModerationBlock requests a block, clears overrides, and refreshes hidden state
---
duration_ms: 4.950644
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:112:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
false !== true
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: true
actual: false
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:228:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
# Subtest: handleModerationBlock returns false when viewer is logged out
ok 4 - handleModerationBlock returns false when viewer is logged out
---
duration_ms: 1.626768
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 3
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 254.906261
file:///app/scripts/run-unit-tests.mjs:68
reject(new Error(`${relativePath} failed with exit code ${code}`));
^
Error: tests/app/moderation-overrides.test.mjs failed with exit code 1
at ChildProcess.<anonymous> (file:///app/scripts/run-unit-tests.mjs:68:16)
at ChildProcess.emit (node:events:519:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
Node.js v22.21.1
+260
View File
@@ -0,0 +1,260 @@
> [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: 4.89647
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 21.69378
→ 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: 401.108042
type: 'test'
...
# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata
ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata
---
duration_ms: 46.542954
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: 15.658716
type: 'test'
...
# Subtest: moderation override clears channel blur via event wiring
ok 4 - moderation override clears channel blur via event wiring
---
duration_ms: 52.358724
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: 41.743826
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: 26.080671
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 611.793776
→ 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: 78.541617
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: 10.259655
type: 'test'
...
# Subtest: handleHashChange respects explicit view regardless of login state
ok 3 - handleHashChange respects explicit view regardless of login state
---
duration_ms: 10.116444
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 112.397132
→ 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: 98.541032
type: 'test'
...
# Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers
ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers
---
duration_ms: 15.672259
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 131.789275
→ 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.459953
type: 'test'
...
# Subtest: isUserLoggedIn treats extension logins as authenticated
ok 2 - isUserLoggedIn treats extension logins as authenticated
---
duration_ms: 0.427722
type: 'test'
...
# Subtest: isUserLoggedIn guards against mismatched nostrClient state
ok 3 - isUserLoggedIn guards against mismatched nostrClient state
---
duration_ms: 0.232365
type: 'test'
...
# Subtest: isUserLoggedIn ignores anonymous session actor mismatches
ok 4 - isUserLoggedIn ignores anonymous session actor mismatches
---
duration_ms: 0.295374
type: 'test'
...
# Subtest: isUserLoggedIn rejects mismatched managed session actors
ok 5 - isUserLoggedIn rejects mismatched managed session actors
---
duration_ms: 0.263757
type: 'test'
...
1..5
# tests 5
# suites 0
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 32.877837
→ 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: 230.312105
type: 'test'
...
# Subtest: handleModerationOverride resumes deferred playback
ok 2 - handleModerationOverride resumes deferred playback
---
duration_ms: 1.320201
type: 'test'
...
# Subtest: handleModerationBlock requests a block, clears overrides, and refreshes hidden state
not ok 3 - handleModerationBlock requests a block, clears overrides, and refreshes hidden state
---
duration_ms: 4.990623
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:112:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
false !== true
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: true
actual: false
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:228:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
# Subtest: handleModerationBlock returns false when viewer is logged out
ok 4 - handleModerationBlock returns false when viewer is logged out
---
duration_ms: 1.778329
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 3
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 271.042194
file:///app/scripts/run-unit-tests.mjs:68
reject(new Error(`${relativePath} failed with exit code ${code}`));
^
Error: tests/app/moderation-overrides.test.mjs failed with exit code 1
at ChildProcess.<anonymous> (file:///app/scripts/run-unit-tests.mjs:68:16)
at ChildProcess.emit (node:events:519:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
Node.js v22.21.1
+305
View File
@@ -0,0 +1,305 @@
> [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: 7.977402
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 22.241514
→ 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: 379.80434
type: 'test'
...
# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata
ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata
---
duration_ms: 45.289258
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: 15.951023
type: 'test'
...
# Subtest: moderation override clears channel blur via event wiring
ok 4 - moderation override clears channel blur via event wiring
---
duration_ms: 45.789308
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: 42.447356
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: 25.597118
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 568.177635
→ 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.772174
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.627833
type: 'test'
...
# Subtest: handleHashChange respects explicit view regardless of login state
ok 3 - handleHashChange respects explicit view regardless of login state
---
duration_ms: 10.030577
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 108.647336
→ 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: 118.594258
type: 'test'
...
# Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers
ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers
---
duration_ms: 27.333658
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 161.988571
→ 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.780936
type: 'test'
...
# Subtest: isUserLoggedIn treats extension logins as authenticated
ok 2 - isUserLoggedIn treats extension logins as authenticated
---
duration_ms: 0.469339
type: 'test'
...
# Subtest: isUserLoggedIn guards against mismatched nostrClient state
ok 3 - isUserLoggedIn guards against mismatched nostrClient state
---
duration_ms: 0.229676
type: 'test'
...
# Subtest: isUserLoggedIn ignores anonymous session actor mismatches
ok 4 - isUserLoggedIn ignores anonymous session actor mismatches
---
duration_ms: 0.274654
type: 'test'
...
# Subtest: isUserLoggedIn rejects mismatched managed session actors
ok 5 - isUserLoggedIn rejects mismatched managed session actors
---
duration_ms: 0.278603
type: 'test'
...
1..5
# tests 5
# suites 0
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 35.209771
→ 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
not ok 1 - handleModerationOverride decorates stored and current videos then refreshes UI
---
duration_ms: 228.266794
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:27:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
+ actual - expected
+ undefined
- true
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: true
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:67:10)
async Test.run (node:internal/test_runner/test:1054:7)
async startSubtestAfterBootstrap (node:internal/test_runner/harness:296:3)
...
# Subtest: handleModerationOverride resumes deferred playback
not ok 2 - handleModerationOverride resumes deferred playback
---
duration_ms: 2.019286
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:75:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
+ actual - expected
+ {
+ magnet: '',
+ triggerProvided: false,
+ url: 'https://example.com/video.mp4',
+ videoId: 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'
+ }
- null
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: ~
actual:
url: 'https://example.com/video.mp4'
magnet: ''
triggerProvided: false
videoId: 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:104:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
# Subtest: handleModerationBlock requests a block, clears overrides, and refreshes hidden state
not ok 3 - handleModerationBlock requests a block, clears overrides, and refreshes hidden state
---
duration_ms: 2.784959
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:112:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
+ actual - expected
+ undefined
- true
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: true
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:202:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
# Subtest: handleModerationBlock returns false when viewer is logged out
ok 4 - handleModerationBlock returns false when viewer is logged out
---
duration_ms: 2.057327
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 1
# fail 3
# cancelled 0
# skipped 0
# todo 0
# duration_ms 267.221529
file:///app/scripts/run-unit-tests.mjs:68
reject(new Error(`${relativePath} failed with exit code ${code}`));
^
Error: tests/app/moderation-overrides.test.mjs failed with exit code 1
at ChildProcess.<anonymous> (file:///app/scripts/run-unit-tests.mjs:68:16)
at ChildProcess.emit (node:events:519:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
Node.js v22.21.1
+287
View File
@@ -0,0 +1,287 @@
> [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: 4.68097
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 18.751403
→ 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: 249.242079
type: 'test'
...
# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata
ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata
---
duration_ms: 34.522355
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.527787
type: 'test'
...
# Subtest: moderation override clears channel blur via event wiring
ok 4 - moderation override clears channel blur via event wiring
---
duration_ms: 39.046527
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.441459
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: 23.360676
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 404.34229
→ 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: 1009.599136
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: 73.745699
type: 'test'
...
# Subtest: handleHashChange respects explicit view regardless of login state
ok 3 - handleHashChange respects explicit view regardless of login state
---
duration_ms: 33.538414
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 1164.107182
→ 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: 123.254594
type: 'test'
...
# Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers
ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers
---
duration_ms: 17.578009
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 173.980931
→ 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.547337
type: 'test'
...
# Subtest: isUserLoggedIn treats extension logins as authenticated
ok 2 - isUserLoggedIn treats extension logins as authenticated
---
duration_ms: 0.411532
type: 'test'
...
# Subtest: isUserLoggedIn guards against mismatched nostrClient state
ok 3 - isUserLoggedIn guards against mismatched nostrClient state
---
duration_ms: 0.230064
type: 'test'
...
# Subtest: isUserLoggedIn ignores anonymous session actor mismatches
ok 4 - isUserLoggedIn ignores anonymous session actor mismatches
---
duration_ms: 0.402138
type: 'test'
...
# Subtest: isUserLoggedIn rejects mismatched managed session actors
ok 5 - isUserLoggedIn rejects mismatched managed session actors
---
duration_ms: 0.24381
type: 'test'
...
1..5
# tests 5
# suites 0
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 48.612244
→ 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: 244.260716
type: 'test'
...
# Subtest: handleModerationOverride resumes deferred playback
not ok 2 - handleModerationOverride resumes deferred playback
---
duration_ms: 3.378509
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:75:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
+ actual - expected
+ {
+ magnet: '',
+ triggerProvided: false,
+ url: 'https://example.com/video.mp4',
+ videoId: 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'
+ }
- null
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: ~
actual:
url: 'https://example.com/video.mp4'
magnet: ''
triggerProvided: false
videoId: 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:104:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
# Subtest: handleModerationBlock requests a block, clears overrides, and refreshes hidden state
not ok 3 - handleModerationBlock requests a block, clears overrides, and refreshes hidden state
---
duration_ms: 4.927295
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:112:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
false !== true
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: true
actual: false
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:228:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
# Subtest: handleModerationBlock returns false when viewer is logged out
ok 4 - handleModerationBlock returns false when viewer is logged out
---
duration_ms: 1.922279
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 2
# fail 2
# cancelled 0
# skipped 0
# todo 0
# duration_ms 287.75859
file:///app/scripts/run-unit-tests.mjs:68
reject(new Error(`${relativePath} failed with exit code ${code}`));
^
Error: tests/app/moderation-overrides.test.mjs failed with exit code 1
at ChildProcess.<anonymous> (file:///app/scripts/run-unit-tests.mjs:68:16)
at ChildProcess.emit (node:events:519:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
Node.js v22.21.1
+260
View File
@@ -0,0 +1,260 @@
> [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: 6.00491
type: 'test'
...
1..1
# tests 1
# suites 0
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 32.022592
→ 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: 375.346278
type: 'test'
...
# Subtest: renderChannelVideosFromList applies moderation blur without existing metadata
ok 2 - renderChannelVideosFromList applies moderation blur without existing metadata
---
duration_ms: 37.760277
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: 14.528741
type: 'test'
...
# Subtest: moderation override clears channel blur via event wiring
ok 4 - moderation override clears channel blur via event wiring
---
duration_ms: 47.192924
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: 39.987443
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.837088
type: 'test'
...
1..6
# tests 6
# suites 0
# pass 6
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 553.202787
→ 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: 73.049804
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.496508
type: 'test'
...
# Subtest: handleHashChange respects explicit view regardless of login state
ok 3 - handleHashChange respects explicit view regardless of login state
---
duration_ms: 9.841895
type: 'test'
...
1..3
# tests 3
# suites 0
# pass 3
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 105.172847
→ 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: 91.833717
type: 'test'
...
# Subtest: hydrateSidebarNavigation hides chrome controls for logged-out viewers
ok 2 - hydrateSidebarNavigation hides chrome controls for logged-out viewers
---
duration_ms: 13.635597
type: 'test'
...
1..2
# tests 2
# suites 0
# pass 2
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 122.580199
→ 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.302074
type: 'test'
...
# Subtest: isUserLoggedIn treats extension logins as authenticated
ok 2 - isUserLoggedIn treats extension logins as authenticated
---
duration_ms: 0.407277
type: 'test'
...
# Subtest: isUserLoggedIn guards against mismatched nostrClient state
ok 3 - isUserLoggedIn guards against mismatched nostrClient state
---
duration_ms: 0.283539
type: 'test'
...
# Subtest: isUserLoggedIn ignores anonymous session actor mismatches
ok 4 - isUserLoggedIn ignores anonymous session actor mismatches
---
duration_ms: 0.252445
type: 'test'
...
# Subtest: isUserLoggedIn rejects mismatched managed session actors
ok 5 - isUserLoggedIn rejects mismatched managed session actors
---
duration_ms: 0.383152
type: 'test'
...
1..5
# tests 5
# suites 0
# pass 5
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 34.198852
→ 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: 210.938803
type: 'test'
...
# Subtest: handleModerationOverride resumes deferred playback
ok 2 - handleModerationOverride resumes deferred playback
---
duration_ms: 1.300514
type: 'test'
...
# Subtest: handleModerationBlock requests a block, clears overrides, and refreshes hidden state
not ok 3 - handleModerationBlock requests a block, clears overrides, and refreshes hidden state
---
duration_ms: 4.873851
type: 'test'
location: '/app/tests/app/moderation-overrides.test.mjs:112:1'
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
false !== true
code: 'ERR_ASSERTION'
name: 'AssertionError'
expected: true
actual: false
operator: 'strictEqual'
stack: |-
TestContext.<anonymous> (file:///app/tests/app/moderation-overrides.test.mjs:228:10)
async Test.run (node:internal/test_runner/test:1054:7)
async Test.processPendingSubtests (node:internal/test_runner/test:744:7)
...
# Subtest: handleModerationBlock returns false when viewer is logged out
ok 4 - handleModerationBlock returns false when viewer is logged out
---
duration_ms: 1.847791
type: 'test'
...
1..4
# tests 4
# suites 0
# pass 3
# fail 1
# cancelled 0
# skipped 0
# todo 0
# duration_ms 253.404435
file:///app/scripts/run-unit-tests.mjs:68
reject(new Error(`${relativePath} failed with exit code ${code}`));
^
Error: tests/app/moderation-overrides.test.mjs failed with exit code 1
at ChildProcess.<anonymous> (file:///app/scripts/run-unit-tests.mjs:68:16)
at ChildProcess.emit (node:events:519:28)
at maybeClose (node:internal/child_process:1101:16)
at ChildProcess._handle.onexit (node:internal/child_process:304:5)
Node.js v22.21.1
+50 -1
View File
@@ -1,6 +1,13 @@
import "../test-helpers/setup-localstorage.mjs";
import { ModerationService } from "../../js/services/moderationService.js";
import { getDefaultModerationSettings } from "../../js/state/cache.js";
import ModerationDecorator from "../../js/services/moderationDecorator.js";
import ModerationActionController from "../../js/services/moderationActionController.js";
import {
getDefaultModerationSettings,
setModerationOverride,
clearModerationOverride,
} from "../../js/state/cache.js";
import { userBlocks } from "../../js/userBlocks.js";
const DEFAULT_CONTACT_OWNER = "f".repeat(64);
const DEFAULT_REPORT_TARGET = "e".repeat(64);
@@ -209,7 +216,49 @@ export async function createModerationAppHarness() {
return app.__profiles.get(pubkey) || null;
};
app.moderationDecorator = new ModerationDecorator({
getProfileCacheEntry: (pubkey) => app.getProfileCacheEntry(pubkey),
});
app.moderationActionController = new ModerationActionController({
services: {
userBlocks,
setModerationOverride,
clearModerationOverride,
},
auth: {
isLoggedIn: () => app.isUserLoggedIn(),
getViewerPubkey: () => app.pubkey,
normalizePubkey: (value) =>
app.normalizeHexPubkey
? app.normalizeHexPubkey(value)
: Application.prototype.normalizeHexPubkey.call(app, value),
},
actions: {
refreshVideos: (payload) => app.onVideosShouldRefresh(payload),
showStatus: (message, options) => app.showStatus(message, options),
showError: (message) => app.showError(message),
decorateVideoModeration: (video) => app.decorateVideoModeration(video),
resumePlayback: (video) => app.resumePendingModeratedPlayback(video),
describeBlockError: (error) => app.describeUserBlockActionError(error),
},
selectors: {
getVideoById: (id) => (app.videosMap ? app.videosMap.get(id) : null),
getCurrentVideo: () => app.currentVideo,
},
ui: {
refreshCardModerationUi: (card, options) =>
app.refreshCardModerationUi(card, options),
dispatchModerationEvent: (eventName, detail) =>
app.dispatchModerationEvent(eventName, detail),
},
});
app.decorateVideoModeration = Application.prototype.decorateVideoModeration;
app.resumePendingModeratedPlayback =
Application.prototype.resumePendingModeratedPlayback;
app.describeUserBlockActionError =
Application.prototype.describeUserBlockActionError;
app.deriveModerationReportType = Application.prototype.deriveModerationReportType;
app.deriveModerationTrustedCount = Application.prototype.deriveModerationTrustedCount;
app.getReporterDisplayName = Application.prototype.getReporterDisplayName;