mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
75 lines
2.9 KiB
TypeScript
75 lines
2.9 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|||
|
|
import { waitForHydration } from "./helpers";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* VitePress switches to the desktop nav at 768px. Several locales carry
|
||
|
|
* top-level labels far longer than English (es 55 characters, pt-BR 54, th 53,
|
||
|
|
* ru 52, de 48 against en 33), so between 768px and the 960px sidebar
|
||
|
|
* breakpoint the navbar's right edge landed outside the viewport and the page
|
||
|
|
* scrolled sideways. apps/docs/.vitepress/theme/vars.css moves that one switch
|
||
|
|
* to 960px.
|
||
|
|
*
|
||
|
|
* English fits at every width, so an English-only check would have stayed green
|
||
|
|
* through the whole regression. The long-label locales are the point.
|
||
|
|
*/
|
||
|
|
|
||
|
|
const WIDTHS = [375, 767, 768, 900, 959, 960, 1280];
|
||
|
|
|
||
|
|
// The five longest nav-label locales plus English as the control.
|
||
|
|
const PAGES = [
|
||
|
|
"/guide/getting-started",
|
||
|
|
"/de/guide/getting-started",
|
||
|
|
"/es/guide/getting-started",
|
||
|
|
"/pt-BR/guide/getting-started",
|
||
|
|
"/th/guide/getting-started",
|
||
|
|
"/ru/guide/getting-started",
|
||
|
|
];
|
||
|
|
|
||
|
|
test.describe("Docs responsive layout", () => {
|
||
|
|
for (const path of PAGES) {
|
||
|
|
for (const width of WIDTHS) {
|
||
|
|
test(`${path} does not scroll sideways at ${width}px`, async ({ page }) => {
|
||
|
|
await page.setViewportSize({ width, height: 900 });
|
||
|
|
await page.goto(path);
|
||
|
|
await waitForHydration(page);
|
||
|
|
const { scrollWidth, clientWidth } = await page.evaluate(() => ({
|
||
|
|
scrollWidth: document.documentElement.scrollWidth,
|
||
|
|
clientWidth: document.documentElement.clientWidth,
|
||
|
|
}));
|
||
|
|
expect(
|
||
|
|
scrollWidth,
|
||
|
|
`${path} overflows by ${scrollWidth - clientWidth}px at ${width}px`,
|
||
|
|
).toBeLessThanOrEqual(clientWidth);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Hiding the desktop menu is only safe if the overlay replaces it, so this
|
||
|
|
// pins the replacement rather than trusting the CSS to have both halves.
|
||
|
|
for (const width of [768, 900, 959]) {
|
||
|
|
test(`the hamburger overlay carries the top-level nav at ${width}px`, async ({ page }) => {
|
||
|
|
await page.setViewportSize({ width, height: 900 });
|
||
|
|
await page.goto("/de/guide/getting-started");
|
||
|
|
await waitForHydration(page);
|
||
|
|
|
||
|
|
await expect(page.locator(".VPNavBarMenu")).toBeHidden();
|
||
|
|
const hamburger = page.locator(".VPNavBarHamburger");
|
||
|
|
await expect(hamburger).toBeVisible();
|
||
|
|
|
||
|
|
await hamburger.click();
|
||
|
|
const screen = page.locator(".VPNavScreen");
|
||
|
|
await expect(screen).toBeVisible();
|
||
|
|
await expect(screen.locator(".VPNavScreenMenu")).toContainText("Anleitung");
|
||
|
|
await expect(screen.locator(".translations")).toBeVisible();
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
test("the desktop nav returns at the sidebar breakpoint", async ({ page }) => {
|
||
|
|
await page.setViewportSize({ width: 960, height: 900 });
|
||
|
|
await page.goto("/de/guide/getting-started");
|
||
|
|
await waitForHydration(page);
|
||
|
|
await expect(page.locator(".VPNavBarMenu")).toBeVisible();
|
||
|
|
await expect(page.locator(".VPNavBarHamburger")).toBeHidden();
|
||
|
|
});
|
||
|
|
});
|