From ebc27423cc3e254805eb793c360dc6b807d24d98 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 27 Jan 2026 12:14:15 +0000 Subject: [PATCH] Add minimal reproducer for moderation UI visibility bug - Creates `examples/reproducers/issue-moderation-ui/` with a standalone Playwright script. - Includes `repro.spec.ts` which reproduces the "Show anyway" button visibility failure. - Adds `playwright.config.ts` for standalone execution of the reproducer. - Documents running instructions in `README.md`. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- .../reproducers/issue-moderation-ui/README.md | 31 +++++----- .../issue-moderation-ui/playwright.config.ts | 34 ++++++----- .../issue-moderation-ui/repro.spec.ts | 58 +++++-------------- 3 files changed, 54 insertions(+), 69 deletions(-) diff --git a/examples/reproducers/issue-moderation-ui/README.md b/examples/reproducers/issue-moderation-ui/README.md index 46c3bbdd..2269d7d7 100644 --- a/examples/reproducers/issue-moderation-ui/README.md +++ b/examples/reproducers/issue-moderation-ui/README.md @@ -1,19 +1,24 @@ -# Moderation UI "Show Anyway" Bug Reproducer +# Moderation UI "Show Anyway" Button Visibility Issue Reproducer -This reproducer demonstrates the failure of the "Show anyway" button visibility check and click action in the moderation UI fixtures. +This reproducer demonstrates the issue where the "Show anyway" button in the moderation UI is not visible (or not interactable) in the test environment, even though the logic seems correct. ## Issue Description +- **Known Issue**: `KNOWN_ISSUES.md`: Moderation UI (`tests/visual/moderation.spec.ts`): The "Show anyway" button and related moderation badges fail to render in the test environment, causing `toBeVisible()` assertions to fail. +- **Symptoms**: `Error: element(s) not found` when asserting visibility of the "Show anyway" button. -In the moderation UI tests, the "Show anyway" button fails to be visible or clickable in the test environment (headless mode), even though the logic seems correct. This prevents verifying the "show anyway" override functionality. +## How to Run -## Running the Reproducer +1. Navigate to the repository root. +2. Ensure dependencies are installed and the project is built: + ```bash + npm ci + npm run build + npx playwright install chromium + ``` +3. Run the reproducer script using the provided config: + ```bash + npx playwright test -c examples/reproducers/issue-moderation-ui/playwright.config.ts + ``` -To run the reproducer script: - -```bash -npx playwright test examples/reproducers/issue-moderation-ui/repro.spec.ts -``` - -## Expected Result - -The test should fail with a timeout waiting for the "Show anyway" button to be visible or clickable. +## Expected Output +The test `repro: show anyway override button visibility` should **fail** with a timeout or "element not found" error on the assertion `await expect(showAnywayButton).toBeVisible();`. diff --git a/examples/reproducers/issue-moderation-ui/playwright.config.ts b/examples/reproducers/issue-moderation-ui/playwright.config.ts index 513c3e22..bac743ba 100644 --- a/examples/reproducers/issue-moderation-ui/playwright.config.ts +++ b/examples/reproducers/issue-moderation-ui/playwright.config.ts @@ -1,23 +1,29 @@ -import baseConfig from '../../../playwright.config.ts'; -import { defineConfig } from '@playwright/test'; -import path from 'path'; -import { fileURLToPath } from 'url'; +import { defineConfig } from "@playwright/test"; -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const repoRoot = path.resolve(__dirname, '../../..'); +const HOST = process.env.PLAYWRIGHT_HOST ?? "127.0.0.1"; +const PORT = Number.parseInt(process.env.PLAYWRIGHT_PORT ?? "4173", 10); +const BASE_URL = process.env.PLAYWRIGHT_BASE_URL ?? `http://${HOST}:${PORT}`; export default defineConfig({ - ...baseConfig, - testDir: './', - webServer: { - ...baseConfig.webServer, - cwd: repoRoot, + testDir: ".", + outputDir: "../../../artifacts/test-results", + timeout: 60_000, + reporter: [["list"]], + use: { + baseURL: BASE_URL, + viewport: { width: 1280, height: 720 }, + ignoreHTTPSErrors: true, }, projects: [ { - name: 'repro', - testMatch: '**/*.spec.ts', - use: baseConfig.projects?.[0]?.use, + name: "repro", + testMatch: "**/*.spec.ts", }, ], + webServer: { + command: `npx http-server . -p ${PORT} -a ${HOST} -c-1 --silent`, + url: `${BASE_URL}/docs/kitchen-sink.html`, + reuseExistingServer: true, + timeout: 120_000, + }, }); diff --git a/examples/reproducers/issue-moderation-ui/repro.spec.ts b/examples/reproducers/issue-moderation-ui/repro.spec.ts index 57ced734..e6b5a912 100644 --- a/examples/reproducers/issue-moderation-ui/repro.spec.ts +++ b/examples/reproducers/issue-moderation-ui/repro.spec.ts @@ -1,69 +1,43 @@ 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 }) => { - 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 reproducer", () => { - test("show anyway override persists across reloads", async ({ page }) => { +test("repro: show anyway override button visibility", async ({ page }) => { + // 1. Navigate to fixture await page.goto(FIXTURE_URL, { waitUntil: "networkidle" }); await waitForFixtureReady(page); + // 2. Locate the card that should have the button const overrideCard = page.locator('[data-test-id="show-anyway"]'); - const thumbnail = overrideCard.locator('img[data-video-thumbnail]'); + // 3. Verify it has the override available attribute await expect(overrideCard).toHaveAttribute( "data-moderation-override-available", "true" ); + + // 4. Locate the button 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"); - - // Uncommenting the failing check to reproduce the bug + // 5. Assert visibility (this is expected to fail) + console.log("Checking visibility of 'Show anyway' button..."); await expect(showAnywayButton).toBeVisible(); - await expect(restoreButtonQuery).toHaveCount(0); - // Uncommenting the failing action to reproduce the bug + console.log("'Show anyway' button is visible. Attempting click..."); + // 6. Click (this is expected to fail/timeout if not visible) await showAnywayButton.click({ force: true }); - }); + + // 7. Verify state change + await expect(overrideCard).toHaveAttribute( + "data-moderation-override", + "show-anyway" + ); });