57 lines
2.3 KiB
TypeScript
57 lines
2.3 KiB
TypeScript
import { expect, type Page } from "@playwright/test";
|
|
|
|
export const narrowMobileViewport = { width: 390, height: 844 };
|
|
export const compactMobileViewport = { width: 320, height: 568 };
|
|
|
|
export async function expectNoHorizontalOverflow(page: Page): Promise<void> {
|
|
const metrics = await page.evaluate(() => {
|
|
const root = document.documentElement;
|
|
const body = document.body;
|
|
const viewportWidth = window.innerWidth;
|
|
const overflowingElements = Array.from(document.body.querySelectorAll<HTMLElement>("*"))
|
|
.flatMap((element) => {
|
|
const rect = element.getBoundingClientRect();
|
|
const overflowsViewport = rect.left < -1 || rect.right > viewportWidth + 1;
|
|
const overflowsOwnBox = element.scrollWidth > element.clientWidth + 1 && rect.width > 0;
|
|
if (!overflowsViewport && !overflowsOwnBox) return [];
|
|
|
|
const selector = [
|
|
element.tagName.toLowerCase(),
|
|
element.id ? `#${element.id}` : "",
|
|
element.dataset.uiId ? `[data-ui-id="${element.dataset.uiId}"]` : "",
|
|
element.className && typeof element.className === "string" ? `.${element.className.trim().split(/\s+/u).slice(0, 3).join(".")}` : "",
|
|
].join("");
|
|
|
|
return [
|
|
{
|
|
clientWidth: element.clientWidth,
|
|
left: Math.round(rect.left),
|
|
right: Math.round(rect.right),
|
|
scrollWidth: element.scrollWidth,
|
|
selector,
|
|
},
|
|
];
|
|
})
|
|
.slice(0, 5);
|
|
|
|
return {
|
|
bodyScrollWidth: body.scrollWidth,
|
|
clientWidth: root.clientWidth,
|
|
rootScrollWidth: root.scrollWidth,
|
|
overflowingElements,
|
|
viewportWidth,
|
|
};
|
|
});
|
|
const overflowDetails = metrics.overflowingElements.length > 0 ? `; overflowing elements: ${JSON.stringify(metrics.overflowingElements)}` : "";
|
|
|
|
expect(
|
|
metrics.rootScrollWidth,
|
|
`root scrollWidth ${metrics.rootScrollWidth} exceeds viewport ${metrics.viewportWidth}${overflowDetails}`
|
|
).toBeLessThanOrEqual(metrics.viewportWidth + 1);
|
|
expect(
|
|
metrics.bodyScrollWidth,
|
|
`body scrollWidth ${metrics.bodyScrollWidth} exceeds viewport ${metrics.viewportWidth}${overflowDetails}`
|
|
).toBeLessThanOrEqual(metrics.viewportWidth + 1);
|
|
expect(metrics.clientWidth).toBeLessThanOrEqual(metrics.viewportWidth);
|
|
}
|