mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-06 12:52:26 +00:00
Merge branch 'unstable' into codex/extend-tag-pill-rendering-and-add-menu-component
This commit is contained in:
14 files changed
+801
-39
No files matched your search
@@ -70,3 +70,77 @@ test("handleModerationOverride decorates stored and current videos then refreshe
|
||||
assert.equal(currentVideo.moderation.blockAutoplay, false);
|
||||
assert.equal(currentVideo.moderation.blurThumbnail, false);
|
||||
});
|
||||
|
||||
test("handleModerationHide clears overrides and re-applies hidden state", async (t) => {
|
||||
withMockedNostrTools(t);
|
||||
|
||||
const app = await createModerationAppHarness();
|
||||
app.getActiveModerationThresholds = () => ({
|
||||
autoplayBlockThreshold: Number.POSITIVE_INFINITY,
|
||||
blurThreshold: Number.POSITIVE_INFINITY,
|
||||
trustedMuteHideThreshold: 1,
|
||||
trustedSpamHideThreshold: Number.POSITIVE_INFINITY,
|
||||
});
|
||||
|
||||
const videoId = "b".repeat(64);
|
||||
const incomingVideo = {
|
||||
id: videoId,
|
||||
moderation: {
|
||||
trustedMuted: true,
|
||||
trustedMuteCount: 1,
|
||||
trustedMuters: [MUTER_HEX],
|
||||
trustedCount: 0,
|
||||
reportType: "nudity",
|
||||
},
|
||||
};
|
||||
|
||||
const storedVideo = {
|
||||
id: videoId,
|
||||
moderation: {
|
||||
trustedMuted: true,
|
||||
trustedMuteCount: 1,
|
||||
trustedMuters: [MUTER_HEX],
|
||||
trustedCount: 0,
|
||||
reportType: "nudity",
|
||||
},
|
||||
};
|
||||
|
||||
const currentVideo = {
|
||||
id: videoId,
|
||||
moderation: {
|
||||
trustedMuted: true,
|
||||
trustedMuteCount: 1,
|
||||
trustedMuters: [MUTER_HEX],
|
||||
trustedCount: 0,
|
||||
reportType: "nudity",
|
||||
},
|
||||
};
|
||||
|
||||
app.videosMap.set(videoId, storedVideo);
|
||||
app.currentVideo = currentVideo;
|
||||
|
||||
app.decorateVideoModeration(incomingVideo);
|
||||
app.decorateVideoModeration(storedVideo);
|
||||
app.decorateVideoModeration(currentVideo);
|
||||
|
||||
const card = {
|
||||
refreshModerationUi() {
|
||||
/* noop */
|
||||
},
|
||||
};
|
||||
|
||||
app.handleModerationOverride({ video: incomingVideo, card });
|
||||
|
||||
assert.equal(storedVideo.moderation.viewerOverride?.showAnyway, true);
|
||||
assert.equal(currentVideo.moderation.viewerOverride?.showAnyway, true);
|
||||
|
||||
const result = app.handleModerationHide({ video: incomingVideo, card });
|
||||
|
||||
assert.equal(result, true);
|
||||
assert.equal(incomingVideo.moderation.viewerOverride, undefined);
|
||||
assert.equal(storedVideo.moderation.viewerOverride, undefined);
|
||||
assert.equal(currentVideo.moderation.viewerOverride, undefined);
|
||||
assert.equal(incomingVideo.moderation.hidden, true);
|
||||
assert.equal(storedVideo.moderation.hidden, true);
|
||||
assert.equal(currentVideo.moderation.hidden, true);
|
||||
});
|
||||
@@ -197,6 +197,7 @@ export async function createModerationAppHarness() {
|
||||
app.deriveModerationTrustedCount = Application.prototype.deriveModerationTrustedCount;
|
||||
app.getReporterDisplayName = Application.prototype.getReporterDisplayName;
|
||||
app.handleModerationOverride = Application.prototype.handleModerationOverride;
|
||||
app.handleModerationHide = Application.prototype.handleModerationHide;
|
||||
|
||||
app.videosMap = new Map();
|
||||
app.currentVideo = null;
|
||||
|
||||
@@ -94,6 +94,8 @@ test("moderation stage enforces admin lists without whitelist bypass", async ()
|
||||
const whitelistedItem = result[0];
|
||||
assert.equal(whitelistedItem.video.moderation.blockAutoplay, true);
|
||||
assert.equal(whitelistedItem.video.moderation.blurThumbnail, true);
|
||||
assert.equal(whitelistedItem.video.moderation.blurReason, "trusted-report");
|
||||
assert.equal(whitelistedItem.metadata.moderation.blurReason, "trusted-report");
|
||||
assert.equal(whitelistedItem.video.moderation.adminWhitelist, true);
|
||||
assert.equal(whitelistedItem.video.moderation.adminWhitelistBypass, false);
|
||||
assert.equal(whitelistedItem.metadata.moderation.adminWhitelistBypass, false);
|
||||
@@ -101,6 +103,8 @@ test("moderation stage enforces admin lists without whitelist bypass", async ()
|
||||
const normalItem = result[1];
|
||||
assert.equal(normalItem.video.moderation.blockAutoplay, true);
|
||||
assert.equal(normalItem.video.moderation.blurThumbnail, true);
|
||||
assert.equal(normalItem.video.moderation.blurReason, "trusted-report");
|
||||
assert.equal(normalItem.metadata.moderation.blurReason, "trusted-report");
|
||||
|
||||
const reasons = why.map((entry) => entry.reason);
|
||||
assert(reasons.includes("viewer-block"));
|
||||
@@ -211,11 +215,14 @@ test("moderation stage applies provided thresholds", async () => {
|
||||
assert.equal(strictResult.length, 1);
|
||||
assert.equal(strictResult[0].video.moderation.blockAutoplay, false);
|
||||
assert.equal(strictResult[0].video.moderation.blurThumbnail, false);
|
||||
assert.equal(strictResult[0].video.moderation.blurReason, undefined);
|
||||
|
||||
const relaxedResult = await relaxedStage(items, {});
|
||||
assert.equal(relaxedResult.length, 1);
|
||||
assert.equal(relaxedResult[0].video.moderation.blockAutoplay, true);
|
||||
assert.equal(relaxedResult[0].video.moderation.blurThumbnail, true);
|
||||
assert.equal(relaxedResult[0].video.moderation.blurReason, "trusted-report");
|
||||
assert.equal(relaxedResult[0].metadata.moderation.blurReason, "trusted-report");
|
||||
});
|
||||
|
||||
test("moderation stage propagates whitelist, muters, and threshold updates", async () => {
|
||||
@@ -315,14 +322,18 @@ test("moderation stage propagates whitelist, muters, and threshold updates", asy
|
||||
assert.equal(whitelistedItem.metadata.moderation.adminWhitelist, true);
|
||||
assert.equal(whitelistedItem.metadata.moderation.blockAutoplay, true);
|
||||
assert.equal(whitelistedItem.metadata.moderation.blurThumbnail, true);
|
||||
assert.equal(whitelistedItem.metadata.moderation.blurReason, "trusted-report");
|
||||
assert.equal(whitelistedItem.video.moderation.adminWhitelistBypass, false);
|
||||
assert.equal(whitelistedItem.video.moderation.blurReason, "trusted-report");
|
||||
|
||||
assert.equal(mutedItem.metadata.moderation.trustedMuted, true);
|
||||
assert.deepEqual(mutedItem.metadata.moderation.trustedMuters, [muterHex]);
|
||||
assert.equal(mutedItem.metadata.moderation.blockAutoplay, true);
|
||||
assert.equal(mutedItem.metadata.moderation.blurThumbnail, true);
|
||||
assert.equal(mutedItem.metadata.moderation.blurReason, "trusted-report");
|
||||
assert.equal(mutedItem.video.moderation.trustedMuted, true);
|
||||
assert.deepEqual(mutedItem.video.moderation.trustedMuters, [muterHex]);
|
||||
assert.equal(mutedItem.video.moderation.blurReason, "trusted-report");
|
||||
|
||||
state.summaryById.set("muted-video", {
|
||||
eventId: "muted-video",
|
||||
@@ -342,9 +353,11 @@ test("moderation stage propagates whitelist, muters, and threshold updates", asy
|
||||
assert.deepEqual(updatedMuted.metadata.moderation.trustedMuters, []);
|
||||
assert.equal(updatedMuted.metadata.moderation.blockAutoplay, false);
|
||||
assert.equal(updatedMuted.metadata.moderation.blurThumbnail, false);
|
||||
assert.equal(updatedMuted.metadata.moderation.blurReason, undefined);
|
||||
assert.equal(updatedMuted.video.moderation.trustedMuted, false);
|
||||
assert.equal(updatedMuted.video.moderation.blockAutoplay, false);
|
||||
assert.equal(updatedMuted.video.moderation.blurThumbnail, false);
|
||||
assert.equal(updatedMuted.video.moderation.blurReason, undefined);
|
||||
});
|
||||
|
||||
test("moderation stage clears cached reporters and muters after service signals", async () => {
|
||||
|
||||
@@ -258,3 +258,135 @@ test(
|
||||
assert.ok(card.moderationBadgeEl.textContent.includes("Showing despite"));
|
||||
},
|
||||
);
|
||||
|
||||
test("VideoCard blurs thumbnails when trusted mute triggers without reports", async (t) => {
|
||||
const { document } = setupDom(t);
|
||||
withMockedNostrTools(t);
|
||||
|
||||
const app = await createModerationAppHarness();
|
||||
app.getActiveModerationThresholds = () => ({
|
||||
autoplayBlockThreshold: Number.POSITIVE_INFINITY,
|
||||
blurThreshold: Number.POSITIVE_INFINITY,
|
||||
trustedMuteHideThreshold: 2,
|
||||
trustedSpamHideThreshold: Number.POSITIVE_INFINITY,
|
||||
});
|
||||
const videoId = "c".repeat(64);
|
||||
|
||||
const video = {
|
||||
id: videoId,
|
||||
title: "Muted Clip",
|
||||
pubkey: "d".repeat(64),
|
||||
moderation: {
|
||||
trustedMuted: true,
|
||||
trustedMuteCount: 1,
|
||||
blockAutoplay: false,
|
||||
blurThumbnail: false,
|
||||
trustedCount: 0,
|
||||
reportType: "nudity",
|
||||
},
|
||||
};
|
||||
|
||||
app.videosMap.set(video.id, video);
|
||||
app.currentVideo = video;
|
||||
app.decorateVideoModeration(video);
|
||||
|
||||
const card = new VideoCard({
|
||||
document,
|
||||
video,
|
||||
formatters: {
|
||||
formatTimeAgo: () => "moments ago",
|
||||
},
|
||||
helpers: {
|
||||
isMagnetSupported: () => false,
|
||||
},
|
||||
});
|
||||
|
||||
document.body.appendChild(card.getRoot());
|
||||
|
||||
assert.equal(video.moderation.blurThumbnail, true);
|
||||
assert.equal(video.moderation.blurReason, "trusted-mute");
|
||||
assert.equal(card.getModerationContext().activeBlur, true);
|
||||
assert.equal(card.thumbnailEl.dataset.thumbnailState, "blurred");
|
||||
assert.equal(card.authorPicEl.dataset.visualState, "blurred");
|
||||
assert.equal(card.getRoot().dataset.autoplayPolicy, "blocked");
|
||||
assert.equal(card.moderationBadgeEl.dataset.moderationState, "trusted-mute");
|
||||
assert.equal(
|
||||
card.moderationBadgeTextEl.textContent,
|
||||
"Autoplay blocked · Muted by a trusted contact",
|
||||
);
|
||||
assert.ok(card.moderationHideButton);
|
||||
assert.equal(
|
||||
card.moderationHideButton?.dataset?.moderationAction,
|
||||
"hide",
|
||||
);
|
||||
});
|
||||
|
||||
test("VideoCard hide action restores trusted mute hide state after override", async (t) => {
|
||||
const { document } = setupDom(t);
|
||||
withMockedNostrTools(t);
|
||||
|
||||
const app = await createModerationAppHarness();
|
||||
app.getActiveModerationThresholds = () => ({
|
||||
autoplayBlockThreshold: Number.POSITIVE_INFINITY,
|
||||
blurThreshold: Number.POSITIVE_INFINITY,
|
||||
trustedMuteHideThreshold: 1,
|
||||
trustedSpamHideThreshold: Number.POSITIVE_INFINITY,
|
||||
});
|
||||
|
||||
const videoId = "d".repeat(64);
|
||||
const video = {
|
||||
id: videoId,
|
||||
title: "Muted Hide Clip",
|
||||
pubkey: "e".repeat(64),
|
||||
moderation: {
|
||||
trustedMuted: true,
|
||||
trustedMuteCount: 1,
|
||||
trustedMuters: ["f".repeat(64)],
|
||||
trustedCount: 0,
|
||||
reportType: "nudity",
|
||||
},
|
||||
};
|
||||
|
||||
app.videosMap.set(video.id, video);
|
||||
app.currentVideo = video;
|
||||
app.decorateVideoModeration(video);
|
||||
|
||||
const card = new VideoCard({
|
||||
document,
|
||||
video,
|
||||
formatters: {
|
||||
formatTimeAgo: () => "moments ago",
|
||||
},
|
||||
helpers: {
|
||||
isMagnetSupported: () => false,
|
||||
},
|
||||
});
|
||||
|
||||
document.body.appendChild(card.getRoot());
|
||||
|
||||
assert.equal(card.getModerationContext().activeHidden, true);
|
||||
assert.equal(card.getRoot().dataset.moderationHidden, "true");
|
||||
|
||||
card.onModerationOverride = ({ video: overrideVideo, card: overrideCard }) =>
|
||||
app.handleModerationOverride({ video: overrideVideo, card: overrideCard });
|
||||
|
||||
card.moderationActionButton.click();
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
const contextAfterOverride = card.getModerationContext();
|
||||
assert.equal(contextAfterOverride.overrideActive, true);
|
||||
assert.equal(contextAfterOverride.activeHidden, false);
|
||||
assert.ok(card.moderationHideButton);
|
||||
|
||||
card.onModerationHide = ({ video: targetVideo, card: targetCard }) =>
|
||||
app.handleModerationHide({ video: targetVideo, card: targetCard });
|
||||
|
||||
card.moderationHideButton.click();
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
const contextAfterHide = card.getModerationContext();
|
||||
assert.equal(contextAfterHide.overrideActive, false);
|
||||
assert.equal(contextAfterHide.activeHidden, true);
|
||||
assert.equal(card.getRoot().dataset.moderationHidden, "true");
|
||||
assert.equal(card.moderationHideButton, null);
|
||||
});
|
||||
@@ -127,6 +127,7 @@ test.describe("moderation fixtures", () => {
|
||||
|
||||
const muteCard = page.locator('[data-test-id="trusted-mute-hide"]');
|
||||
const badge = muteCard.locator('[data-moderation-badge="true"]');
|
||||
const thumbnail = muteCard.locator('img[data-video-thumbnail]');
|
||||
const showAnywayButton = muteCard.getByRole("button", { name: "Show anyway" });
|
||||
|
||||
await expect(muteCard).toHaveAttribute("data-moderation-hidden", "true");
|
||||
@@ -135,6 +136,7 @@ test.describe("moderation fixtures", () => {
|
||||
await expect(muteCard).toHaveAttribute("data-moderation-trusted-mute", "true");
|
||||
await expect(muteCard).toHaveAttribute("data-moderation-trusted-mute-count", "1");
|
||||
await expect(badge).toContainText("Hidden · 1 trusted mute");
|
||||
await expect(thumbnail).toHaveAttribute("data-thumbnail-state", "blurred");
|
||||
await expect(showAnywayButton).toBeVisible();
|
||||
|
||||
await showAnywayButton.click();
|
||||
@@ -144,5 +146,6 @@ test.describe("moderation fixtures", () => {
|
||||
await expect(muteCard.locator('[data-moderation-badge="true"]')).toContainText(
|
||||
"Showing despite 1 trusted mute",
|
||||
);
|
||||
await expect(thumbnail).not.toHaveAttribute("data-thumbnail-state", "blurred");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user