6.0 KiB
QA & Test Vectors (Moderation)
Quick checklist
- F1 set cached and used for “trusted reports”.
- Automated coverage:
tests/moderation/trusted-report-count.test.mjs(run vianpm run test:unit).
- Automated coverage:
- Blur once trusted
nudityreports meetDEFAULT_BLUR_THRESHOLD; autoplay blocks when the count reachesDEFAULT_AUTOPLAY_BLOCK_THRESHOLD(checkconfig/instance-config.jsfor your instance’s baseline exports).- Automated coverage:
tests/visual/moderation.spec.tsblur and autoplay scenarios (run vianpm run test:visual).
- Automated coverage:
- Hide videos once trusted mute/spam thresholds are met.
- Automated coverage:
tests/visual/moderation.spec.tstrusted hide scenarios (run vianpm run test:visual). - Manual: adjust thresholds in the profile modal, simulate trusted mutes/reports, and verify cards disappear until "show anyway" is used.
- Automated coverage:
- “Show anyway” works for blurred and hidden cards, surfaces a “Restore default moderation” control, and records only local pref.
- Automated coverage:
tests/visual/moderation.spec.tsshow-anyway persistence and trusted hide scenarios (run vianpm run test:visual).
- Automated coverage:
- Mute list (10000) downranks/hides consistently.
- Manual: subscribe to fixture B and verify muted author disappears from feeds after refresh.
- Admin lists (30000) take effect only when subscribed.
- Manual: load fixture C, toggle subscription, and confirm the hard-hide only applies while subscribed.
- COUNT fallback shows placeholders and doesn’t crash UI.
- Manual: point the client at a relay without COUNT support and confirm placeholders render instead of errors.
- Comment threads render with NIP-10; moderation badges show in context.
- Manual: open a reported thread and confirm badges + reply ordering remain intact.
- Reports from muted reporters are ignored.
- Automated coverage:
tests/moderation/trusted-report-count.test.mjs(muted reporter case).
- Automated coverage:
Fixtures (create on test relays / served in /docs/moderation/fixtures/)
A) NIP-56 report events
Create three distinct F1 reporter keys; each sends:
{
"kind": 1984,
"tags": [
["e", "<VIDEO_EVENT_ID>", "nudity"],
["p", "<AUTHOR_PUBKEY>"]
],
"content": "test: thumbnail too revealing"
}
Expected:
- After 1 report → no blur; autoplay allowed.
- Once reports reach
DEFAULT_AUTOPLAY_BLOCK_THRESHOLD→ autoplay blocked (the upstream configuration currently sets this to 2, but rely on yourconfig/instance-config.jsvalue). - Once reports reach
DEFAULT_BLUR_THRESHOLD→ thumbnail blurred; reason chip shown (upstream example: 1). At the spam threshold (TRUSTED_SPAM_HIDE_THRESHOLDsourced fromDEFAULT_TRUSTED_SPAM_HIDE_THRESHOLDinconfig/instance-config.js) the card hides entirely and the badge copy switches to "Hidden · {count} trusted spam report(s)" until the viewer overrides it.
Exercises: ModerationService.ingestReportEvent() and ModerationService.getTrustedReportSummary() wire through createModerationStage() so bitvidApp.decorateVideoModeration() can hand the summary to VideoCard.refreshModerationUi().
B) Mute list (10000)
{
"kind": 10000,
"tags": [
["p", "<AUTHOR_PUBKEY>"]
]
}
Expected: author’s items are downranked/blurred for this viewer. When the mute threshold (TRUSTED_MUTE_HIDE_THRESHOLD, sourced from DEFAULT_TRUSTED_MUTE_HIDE_THRESHOLD in config/instance-config.js; upstream example: 20) is met, cards render with "Hidden · {count} trusted mute(s)" and require a "Show anyway" override to display content plus a "Restore default moderation" control to revert.
Exercises: ModerationService.ingestTrustedMuteEvent() updates ModerationService.isAuthorMutedByTrusted() / getTrustedMutersForAuthor(), which createModerationStage() propagates to the video item before VideoCard.refreshModerationUi() renders the mute state.
C) Admin blacklist (30000)
{
"kind": 30000,
"tags": [
["d", "bitvid:admin:blacklist"],
["p", "<AUTHOR_PUBKEY>"]
]
}
Expected: when viewer subscribes to this list, author is hard-hidden.
Exercises: accessControl hydration feeds ModerationService.getAdminListSnapshot() / getAccessControlStatus(), giving createModerationStage() the whitelist/blacklist flags that bitvidApp.decorateVideoModeration() and VideoCard.refreshModerationUi() respect.
D) COUNT fallback
- Use a relay that doesn’t support COUNT.
- Verify “—” placeholders; no spinner loops; no crashes.
Exercises: Missing COUNT data flows through ModerationService.setActiveEventIds() → ModerationService.getTrustedReportSummary() defaults, letting createModerationStage() emit neutral moderation metadata that VideoCard.refreshModerationUi() renders as placeholders.
Automated checks (suggested)
npm run test:unit— coverstests/moderation/trusted-report-count.test.mjsfor deduping and mute handling.npm run test:visual— runs Playwright fixtures intests/visual/moderation.spec.tsagainst/docs/moderation/fixtures/index.html, covering blur thresholds, autoplay blocks, trusted hide badges, and the override UX.- Integration test: emit events over a local relay; assert UI state.
- Regression test: ensure Home feed ignores reputation gating.