import { expect, test } from "@playwright/test"; const pageUrl = process.env.TEST_PAGE_URL || "http://community-works-collaborative.test/sample-page/"; const getBox = async (locator) => { const box = await locator.boundingBox(); expect(box).not.toBeNull(); return box; }; const expectNear = (actual, expected, tolerance = 3) => { expect(Math.abs(actual - expected)).toBeLessThanOrEqual(tolerance); }; test.describe("inner page layout", () => { test("desktop: hero, intro, body render in order with the new media layers", async ({ page, }) => { const pageErrors = []; page.on("pageerror", (err) => pageErrors.push(err.message)); await page.setViewportSize({ width: 1280, height: 900 }); await page.goto(pageUrl); const hero = page.locator(".page-hero").first(); const intro = page.locator(".page-intro").first(); const content = page.locator(".entry-content").first(); await expect(hero).toBeVisible(); await expect(intro).toBeVisible(); await expect(content).toBeVisible(); // Order check: hero, then intro, then content. const heroBox = await getBox(hero); const introBox = await getBox(intro); const contentBox = await getBox(content); expect(heroBox.y).toBeLessThan(introBox.y); expect(introBox.y).toBeLessThan(contentBox.y); // Heading is rendered inside the hero. await expect(hero.locator("h1").first()).toBeVisible(); // Intro is centered and capped at the max-w-3xl width. const introInner = intro.locator(".content-wrapper").first(); const introInnerBox = await getBox(introInner); expect(introInnerBox.width).toBeLessThanOrEqual(768 + 3); // Page renders without JS errors. expect(pageErrors).toEqual([]); }); test("mobile 402: hero, intro, body order and intro width", async ({ page, }) => { const pageErrors = []; page.on("pageerror", (err) => pageErrors.push(err.message)); await page.setViewportSize({ width: 402, height: 874 }); await page.goto(pageUrl); const hero = page.locator(".page-hero").first(); const intro = page.locator(".page-intro").first(); const content = page.locator(".entry-content").first(); await expect(hero).toBeVisible(); await expect(intro).toBeVisible(); await expect(content).toBeVisible(); const heroBox = await getBox(hero); const introBox = await getBox(intro); const contentBox = await getBox(content); expect(heroBox.y).toBeLessThan(introBox.y); expect(introBox.y).toBeLessThan(contentBox.y); // Intro fits within the mobile viewport. const introInner = intro.locator(".content-wrapper").first(); const introInnerBox = await getBox(introInner); expect(introInnerBox.x + introInnerBox.width).toBeLessThanOrEqual( 402 + 3, ); // No JS errors. expect(pageErrors).toEqual([]); }); test("mobile 320: nothing clips horizontally", async ({ page }) => { await page.setViewportSize({ width: 320, height: 800 }); await page.goto(pageUrl); const hero = page.locator(".page-hero").first(); const intro = page.locator(".page-intro").first(); await expect(hero).toBeVisible(); await expect(intro).toBeVisible(); const heroBox = await getBox(hero); const introBox = await getBox(intro); expect(heroBox.x + heroBox.width).toBeLessThanOrEqual(320 + 3); expect(introBox.x + introBox.width).toBeLessThanOrEqual(320 + 3); }); test("mobile 767: layout still holds before the desktop breakpoint", async ({ page, }) => { await page.setViewportSize({ width: 767, height: 900 }); await page.goto(pageUrl); const hero = page.locator(".page-hero").first(); const intro = page.locator(".page-intro").first(); await expect(hero).toBeVisible(); await expect(intro).toBeVisible(); const heroBox = await getBox(hero); const introBox = await getBox(intro); expect(heroBox.x + heroBox.width).toBeLessThanOrEqual(767 + 3); expect(introBox.x + introBox.width).toBeLessThanOrEqual(767 + 3); }); });