import { expect, test } from "./helpers"; import type { Page } from "@playwright/test"; // THE OVERVIEW (release 22): the article's parts and their slides side by // side on one plane — tilted isometrically for a pointer, flat for reduced // motion, a narrow screen, a keyboard arrival or the reader's choice — over // the cited fixture site (stage.ts; its deck is listed in slides.spec.ts). const REPORT = "/reports/demo-factcheck/"; const switchIn = (page: Page) => page.locator("[data-report-views] [data-view-switch]"); const stage = (page: Page) => page.locator("[data-report-slides]"); const overview = (page: Page) => page.locator("[data-report-overview]"); test("overview: each part beside its slide; arrows walk the pairs; a card opens its slide, a block the article", async ({ page }) => { await page.goto(`${REPORT}#bridge`); await switchIn(page).getByRole("button", { name: "Overview" }).click(); await expect(page).toHaveURL(`${REPORT}?rv=iso#bridge`); const ov = overview(page); await expect(ov).toHaveAttribute("aria-roledescription", "overview"); await expect(ov.locator("[data-pair]")).toHaveCount(13); await expect(ov.locator('[data-pair="section:bridge"]')).toHaveAttribute("data-active", "true"); await ov.locator('[data-pair="section:bridge"] [data-ov-card]').focus(); await page.keyboard.press("ArrowDown"); await expect(page).toHaveURL(`${REPORT}?rv=iso#claim-1`); await expect(ov.locator('[data-pair="claim:claim-1"] [data-ov-card]')).toBeFocused(); await page.keyboard.press("ArrowLeft"); await expect(ov.locator('[data-pair="claim:claim-1"] [data-ov-block]')).toBeFocused(); await page.keyboard.press("ArrowDown"); await expect(ov.locator('[data-pair="claim:claim-2"] [data-ov-block]')).toBeFocused(); // Only the pair in force is in the tab order. await expect(ov.locator('[data-ov-block][tabindex="0"], [data-ov-card][tabindex="0"]')).toHaveCount(2); await page.keyboard.press("ArrowRight"); // The focus moves on the next frame; Enter opens what has it. await expect(ov.locator('[data-pair="claim:claim-2"] [data-ov-card]')).toBeFocused(); await page.keyboard.press("Enter"); await expect(page).toHaveURL(`${REPORT}?rv=slides#s-8`); await expect(stage(page).locator('[data-slide="claim:claim-2"]')).toBeVisible(); await page.goBack(); await expect(page).toHaveURL(`${REPORT}?rv=iso#claim-2`); await overview(page).locator('[data-pair="section:moving"] [data-ov-block]').focus(); await page.keyboard.press("Enter"); await expect(page).toHaveURL(`${REPORT}#moving`); await expect(page.locator("section#moving")).toBeInViewport(); }); test("overview: tilted for a pointer; flat for reduced motion; the Flat toggle lays it down", async ({ page, browser }) => { await page.goto(`${REPORT}?rv=iso#claim-1`); await expect(overview(page)).toHaveAttribute("data-report-overview", "iso"); const plane = page.locator(".rs-ov-plane"); expect(await plane.evaluate((el) => getComputedStyle(el).transform)).not.toBe("none"); await page.getByRole("button", { name: "Flat" }).click(); await expect(overview(page)).toHaveAttribute("data-report-overview", "flat"); expect(await plane.evaluate((el) => getComputedStyle(el).transform)).toBe("none"); await expect(page.getByRole("button", { name: "Flat" })).toHaveAttribute("aria-pressed", "true"); const reduced = await browser.newContext({ reducedMotion: "reduce" }); const p2 = await reduced.newPage(); await p2.goto(`${REPORT}?rv=iso#claim-1`); await expect(overview(p2)).toHaveAttribute("data-report-overview", "flat"); expect(await p2.locator(".rs-ov-plane").evaluate((el) => getComputedStyle(el).transform)).toBe("none"); // Flat, the pairs read as two columns: each block beside its card. const block = (await p2.locator('[data-pair="claim:claim-1"] .rs-ov-block').boundingBox())!; const card = (await p2.locator('[data-pair="claim:claim-1"] .rs-ov-card').boundingBox())!; expect(card.x).toBeGreaterThan(block.x + block.width); await reduced.close(); }); test("a phone: the overview lies flat, each part stacked over its slide; nothing scrolls sideways", async ({ page }) => { await page.setViewportSize({ width: 375, height: 800 }); await page.goto(`${REPORT}?rv=slides#s-7`); await page.locator("[data-reader-overlay] [data-view-switch]").getByRole("button", { name: "Overview" }).click(); await expect(page).toHaveURL(`${REPORT}?rv=iso#claim-1`); await expect(overview(page)).toHaveAttribute("data-report-overview", "flat"); // Both boxes in one frame: the overview smooth-scrolls the focused pair to // the middle, so two separate reads straddle the scroll. const [block, card] = await page.evaluate(() => [".rs-ov-block", ".rs-ov-card"].map((s) => { const r = document.querySelector(`[data-pair="claim:claim-1"] ${s}`)!.getBoundingClientRect(); return { x: r.x, y: r.y, width: r.width, height: r.height }; }), ); expect(card.y).toBeGreaterThanOrEqual(block.y + block.height); expect(card.x + card.width).toBeLessThanOrEqual(375); expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBeLessThanOrEqual(375); });