Files
CWC/tests/header-nav-overflow.spec.js
Keith Solomon ae8a80484f
Deploy to Dreamhost (dev) / build (push) Successful in 37s
Sync TODOs with Issues / sync_todos (push) Successful in 7s
🐞 fix: Update media query breakpoints for navigation styles and add responsive tests
2026-07-08 18:55:19 -05:00

122 lines
4.1 KiB
JavaScript

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();
});
}