import { expect, test } from "@playwright/test"; /** * Regression coverage for the 1024-1200px header-nav overflow. * * Bug: at viewport widths between 1000 and ~1200, the inline main-navigation * was wider than the header container, pushing doc.scrollWidth past * window.innerWidth and producing a horizontal scrollbar. * * Fix: the desktop-nav breakpoint moved from 62.5rem (1000px) to 80rem * (1280px), so the hamburger now covers 1000-1279 and the inline nav * appears at 1280+. * * These tests assert: * - no horizontal overflow at any of the previously-broken widths * - the hamburger toggle is visible below 1280 * - the inline nav is visible at 1280+ * * Tests run against the local Herd site where the rebuilt theme.css is * served. The live deployment (solowebdesigns.net) will pick up the * rebuilt CSS when the user deploys. */ const site = "http://community-works-collaborative.test/"; const widths = [1000, 1023, 1024, 1100, 1200, 1279, 1280, 1366, 1440]; for (const w of widths) { test(`no horizontal overflow at width ${w}`, async ({ browser }) => { const ctx = await browser.newContext({ viewport: { width: w, height: 800 }, }); const page = await ctx.newPage(); await page.goto(site, { waitUntil: "networkidle" }); const { docW, winW } = await page.evaluate(() => ({ docW: document.documentElement.scrollWidth, winW: window.innerWidth, })); expect( docW, `viewport ${w}: docW=${docW} exceeds winW=${winW} by ${docW - winW}px`, ).toBeLessThanOrEqual(winW + 1); await ctx.close(); }); } for (const w of [1000, 1023, 1024, 1100, 1200, 1279]) { test(`hamburger visible below 1280 at width ${w}`, async ({ browser }) => { const ctx = await browser.newContext({ viewport: { width: w, height: 800 }, }); const page = await ctx.newPage(); await page.goto(site, { waitUntil: "networkidle" }); const toggleVisible = await page.evaluate(() => { const t = document.querySelector(".nav-main__toggle"); if (!t) return false; const cs = getComputedStyle(t); const r = t.getBoundingClientRect(); return ( cs.display !== "none" && cs.visibility !== "hidden" && r.width > 0 && r.height > 0 ); }); expect( toggleVisible, `width ${w}: hamburger should be visible`, ).toBe(true); await ctx.close(); }); } for (const w of [1280, 1366, 1440, 1920]) { test(`inline nav visible at 1280+ at width ${w}`, async ({ browser }) => { const ctx = await browser.newContext({ viewport: { width: w, height: 800 }, }); const page = await ctx.newPage(); await page.goto(site, { waitUntil: "networkidle" }); const result = await page.evaluate(() => { const toggle = document.querySelector(".nav-main__toggle"); const menu = document.querySelector(".nav-main .menu-vdi"); const nav = document.querySelector(".nav-main"); return { toggleDisplay: toggle ? getComputedStyle(toggle).display : null, menuDisplay: menu ? getComputedStyle(menu).display : null, navRight: nav ? Math.round(nav.getBoundingClientRect().right) : null, docW: document.documentElement.scrollWidth, winW: window.innerWidth, }; }); // Hamburger hidden expect( result.toggleDisplay, `width ${w}: hamburger should be hidden at 1280+`, ).toBe("none"); // Inline menu visible (display: flex from the @apply) expect( result.menuDisplay, `width ${w}: inline menu should be visible at 1280+`, ).toBe("flex"); // Nav stays inside the viewport expect( result.docW, `width ${w}: docW=${result.docW} exceeds winW=${result.winW}`, ).toBeLessThanOrEqual(result.winW + 1); await ctx.close(); }); }