50 lines
2.9 KiB
TypeScript
50 lines
2.9 KiB
TypeScript
// The site (site/index.html) never scrolls sideways: at every viewport width from 320 to 1440 px (10 px steps), in the
|
|
// light and the dark theme, document.documentElement.scrollWidth stays within innerWidth. On a failure it names the
|
|
// elements whose right edge passes the viewport outside any scroll container (pseudo-elements show as their owner).
|
|
// Uses the bundled playwright-core with its Chromium (or Google Chrome); skips when neither is installed (a launch that
|
|
// times out on a busy machine fails instead). One launch, the context closed right after each test, capped closes
|
|
// (tests/helpers/browser.ts). SLOW on purpose: 113 widths x 2 themes, each a resize and a layout read.
|
|
import { afterAll, afterEach, describe, expect, test } from 'bun:test';
|
|
import { join } from 'node:path';
|
|
import { AFTER_ALL_MS, AFTER_EACH_MS, launchTestBrowser, testScope } from '../helpers/browser';
|
|
|
|
const page = 'file://' + join(import.meta.dir, '..', '..', 'site', 'index.html');
|
|
|
|
const shared = await launchTestBrowser('playwright-core');
|
|
const { browser, skipWhy } = shared;
|
|
if (!browser) console.warn(`site overflow test skipped: no Chromium installed (${skipWhy}). Run \`bunx playwright install chromium\`.`);
|
|
const scope = testScope(() => browser);
|
|
|
|
// bounded: one context per test, each close capped (bun's 5 s default hook timeout was too tight for Chrome's slow shutdown)
|
|
afterEach(() => scope.settle(), AFTER_EACH_MS);
|
|
afterAll(() => shared.close(), AFTER_ALL_MS);
|
|
|
|
describe.skipIf(!browser)('site: no horizontal overflow', () => {
|
|
for (const scheme of ['light', 'dark'] as const) {
|
|
test(`320-1440 px, ${scheme}`, async () => {
|
|
const p = await scope.newPage({ colorScheme: scheme, viewport: { width: 1440, height: 900 } });
|
|
await p.goto(page, { waitUntil: 'load' });
|
|
const bad: string[] = [];
|
|
for (let w = 320; w <= 1440; w += 10) {
|
|
await p.setViewportSize({ width: w, height: 900 });
|
|
const r = await p.evaluate(() => {
|
|
const iw = innerWidth, sw = document.documentElement.scrollWidth;
|
|
if (sw <= iw) return null;
|
|
const els: string[] = [];
|
|
for (const el of document.querySelectorAll('body *')) {
|
|
const rc = el.getBoundingClientRect();
|
|
if (rc.width === 0 || rc.right <= iw + 0.5) continue;
|
|
let clipped = false;
|
|
for (let a = el.parentElement; a && a !== document.body; a = a.parentElement) {
|
|
if (getComputedStyle(a).overflowX !== 'visible') { clipped = true; break; }
|
|
}
|
|
if (!clipped) els.push(`${el.tagName.toLowerCase()}${el.id ? '#' + el.id : ''}${[...el.classList].map(c => '.' + c).join('')} right=${Math.round(rc.right)}`);
|
|
}
|
|
return `${iw}px: page ${sw - iw}px too wide${els.length ? ' (' + els.slice(0, 5).join(', ') + ')' : ' (a pseudo-element or transform)'}`;
|
|
});
|
|
if (r) bad.push(r);
|
|
}
|
|
expect(bad).toEqual([]);
|
|
}, 120_000);
|
|
}
|
|
});
|