import { expect, test } from "@playwright/test"; const FIXTURE_URL = "/docs/moderation/fixtures/index.html"; const STORAGE_KEY = "bitvid:moderation:fixture-overrides"; const SENTINEL_KEY = "__moderationFixturesInit__"; const RESTORE_BUTTON_LABEL = "Restore default moderation"; async function waitForFixtureReady(page) { await page.waitForSelector('body[data-ready="true"]'); } function setupStorageReset(page) { return page.addInitScript(({ storageKey, sentinelKey }) => { try { const session = window.sessionStorage; const local = window.localStorage; if (session && !session.getItem(sentinelKey)) { local?.removeItem(storageKey); session.setItem(sentinelKey, "1"); } } catch { /* ignore reset failures in tests */ } }, { storageKey: STORAGE_KEY, sentinelKey: SENTINEL_KEY }); } test.beforeEach(async ({ page }) => { page.on('console', msg => console.log('PAGE LOG:', msg.text())); page.on('pageerror', err => console.log('PAGE ERROR:', err.message)); await setupStorageReset(page); }); test.afterEach(async ({ page }) => { try { await page.evaluate(({ key, sentinel }) => { window.localStorage?.removeItem(key); window.sessionStorage?.removeItem(sentinel); }, { key: STORAGE_KEY, sentinel: SENTINEL_KEY }); } catch { // ignore cleanup errors when page already closed } }); test.describe("moderation fixtures", () => { test("blur fixture masks thumbnails and blocks autoplay", async ({ page }) => { await page.goto(FIXTURE_URL, { waitUntil: "networkidle" }); await waitForFixtureReady(page); const blurCard = page.locator('[data-test-id="blur-threshold"]'); const thumbnail = blurCard.locator('img[data-video-thumbnail]'); await expect(blurCard).toHaveAttribute("data-moderation-report-count", "3"); await expect(blurCard).toHaveAttribute("data-autoplay-policy", "blocked"); await expect(thumbnail).toHaveAttribute("data-thumbnail-state", "blurred"); await expect(blurCard).not.toHaveAttribute( "data-moderation-override", "show-anyway" ); }); test("autoplay fixture disables preview without blurring", async ({ page }) => { await page.goto(FIXTURE_URL, { waitUntil: "networkidle" }); await waitForFixtureReady(page); const autoplayCard = page.locator('[data-test-id="autoplay-threshold"]'); const thumbnail = autoplayCard.locator('img[data-video-thumbnail]'); await expect(autoplayCard).toHaveAttribute("data-moderation-report-count", "2"); await expect(autoplayCard).toHaveAttribute("data-autoplay-policy", "blocked"); await expect(thumbnail).not.toHaveAttribute("data-thumbnail-state", "blurred"); }); test("show anyway override persists across reloads", async ({ page }) => { await page.goto(FIXTURE_URL, { waitUntil: "networkidle" }); await waitForFixtureReady(page); const overrideCard = page.locator('[data-test-id="show-anyway"]'); const thumbnail = overrideCard.locator('img[data-video-thumbnail]'); await expect(overrideCard).toHaveAttribute( "data-moderation-override-available", "true" ); const showAnywayButton = overrideCard.getByRole("button", { name: "Show anyway" }); const restoreButtonQuery = overrideCard.getByRole("button", { name: RESTORE_BUTTON_LABEL, }); await expect(overrideCard).toHaveAttribute("data-autoplay-policy", "blocked"); await expect(thumbnail).toHaveAttribute("data-thumbnail-state", "blurred"); await expect(showAnywayButton).toBeVisible(); await expect(restoreButtonQuery).toHaveCount(0); await showAnywayButton.click(); await expect(overrideCard).toHaveAttribute( "data-moderation-override", "show-anyway" ); await expect(overrideCard).not.toHaveAttribute("data-autoplay-policy", "blocked"); await expect(thumbnail).not.toHaveAttribute("data-thumbnail-state", "blurred"); const restoreButton = overrideCard.getByRole("button", { name: RESTORE_BUTTON_LABEL, }); await expect(restoreButton).toBeVisible(); await expect(overrideCard.getByRole("button", { name: "Show anyway" })).toHaveCount(0); await page.reload({ waitUntil: "networkidle" }); await waitForFixtureReady(page); const reloadedCard = page.locator('[data-test-id="show-anyway"]'); const reloadedThumbnail = reloadedCard.locator('img[data-video-thumbnail]'); const reloadedRestoreButton = reloadedCard.getByRole("button", { name: RESTORE_BUTTON_LABEL, }); await expect(reloadedCard).toHaveAttribute( "data-moderation-override", "show-anyway" ); await expect(reloadedCard).not.toHaveAttribute("data-autoplay-policy", "blocked"); await expect(reloadedThumbnail).not.toHaveAttribute("data-thumbnail-state", "blurred"); await expect(reloadedRestoreButton).toBeVisible(); await expect( reloadedCard.getByRole("button", { name: "Show anyway" }) ).toHaveCount(0); await reloadedRestoreButton.click(); await expect(reloadedCard).not.toHaveAttribute( "data-moderation-override", "show-anyway" ); await expect(reloadedCard).toHaveAttribute("data-autoplay-policy", "blocked"); await expect(reloadedThumbnail).toHaveAttribute("data-thumbnail-state", "blurred"); await expect( reloadedCard.getByRole("button", { name: RESTORE_BUTTON_LABEL }) ).toHaveCount(0); await expect( reloadedCard.getByRole("button", { name: "Show anyway" }) ).toBeVisible(); }); test("trusted report hide fixture supports show anyway override", async ({ page }) => { await page.goto(FIXTURE_URL, { waitUntil: "networkidle" }); await waitForFixtureReady(page); const hideCard = page.locator('[data-test-id="trusted-report-hide"]'); const badge = hideCard.locator('[data-moderation-badge="true"]'); await expect(hideCard).toHaveAttribute( "data-moderation-override-available", "true" ); const showAnywayButton = hideCard.getByRole("button", { name: "Show anyway" }); const restoreButtonQuery = hideCard.getByRole("button", { name: RESTORE_BUTTON_LABEL, }); await expect(hideCard).toHaveAttribute("data-moderation-hidden", "true"); await expect(hideCard).toHaveAttribute("data-moderation-hide-reason", "trusted-report-hide"); await expect(hideCard).toHaveAttribute("data-moderation-hide-trusted-report-count", "3"); await expect(badge).toContainText("Hidden · 3 trusted spam reports"); await expect(showAnywayButton).toBeVisible(); await expect(restoreButtonQuery).toHaveCount(0); await showAnywayButton.click(); await expect(hideCard).not.toHaveAttribute("data-moderation-hidden", "true"); await expect(hideCard).toHaveAttribute("data-moderation-override", "show-anyway"); await expect(hideCard.locator('[data-moderation-badge="true"]')).toContainText( "Showing despite 3 trusted spam reports", ); const restoreButton = hideCard.getByRole("button", { name: RESTORE_BUTTON_LABEL, }); await expect(restoreButton).toBeVisible(); await restoreButton.click(); await expect(hideCard).toHaveAttribute("data-moderation-hidden", "true"); await expect(hideCard).not.toHaveAttribute("data-moderation-override", "show-anyway"); await expect(hideCard.getByRole("button", { name: "Show anyway" })).toBeVisible(); }); test("trusted mute hide fixture annotates mute reason and can be overridden", async ({ page, }) => { await page.goto(FIXTURE_URL, { waitUntil: "networkidle" }); await waitForFixtureReady(page); 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]'); await expect(muteCard).toHaveAttribute( "data-moderation-override-available", "true" ); const showAnywayButton = muteCard.getByRole("button", { name: "Show anyway" }); const restoreButtonQuery = muteCard.getByRole("button", { name: RESTORE_BUTTON_LABEL, }); await expect(muteCard).toHaveAttribute("data-moderation-hidden", "true"); await expect(muteCard).toHaveAttribute("data-moderation-hide-reason", "trusted-mute-hide"); await expect(muteCard).toHaveAttribute("data-moderation-hide-trusted-mute-count", "1"); 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(); const showAnywayLocator = muteCard.locator('button[data-moderation-action="override"]'); await expect(showAnywayLocator).toHaveCount(1); await expect(showAnywayLocator).toHaveAttribute("aria-label", "Show anyway"); await expect(restoreButtonQuery).toHaveCount(0); await showAnywayButton.click(); await expect(muteCard).not.toHaveAttribute("data-moderation-hidden", "true"); await expect(muteCard).toHaveAttribute("data-moderation-override", "show-anyway"); await expect(muteCard.locator('[data-moderation-badge="true"]')).toContainText( "Showing despite 1 trusted mute", ); await expect(thumbnail).not.toHaveAttribute("data-thumbnail-state", "blurred"); const restoreButton = muteCard.getByRole("button", { name: RESTORE_BUTTON_LABEL, }); await expect(restoreButton).toBeVisible(); await restoreButton.click(); await expect(muteCard).toHaveAttribute("data-moderation-hidden", "true"); await expect(muteCard).not.toHaveAttribute("data-moderation-override", "show-anyway"); await expect(thumbnail).toHaveAttribute("data-thumbnail-state", "blurred"); await expect(muteCard.getByRole("button", { name: "Show anyway" })).toBeVisible(); }); });