From 09d86eddad54b52a154ca9e364551ecec183e27e Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Wed, 9 Sep 2026 15:01:15 +0200 Subject: [PATCH] Make the scroll-lock test able to fail, and name the tell a broken chain actually shows --- CHANGELOG.md | 4 ++-- e2e-tests/full-flow.spec.ts | 3 ++- e2e-tests/visual.spec.ts | 11 +++++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb5430f..9b97664 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,8 +39,8 @@ clip one nested any deeper. `data-table` takes `scrollRegion: true`, which puts 3. A page holding a region that filled the content column passes `fill: true` to the shell, puts `.scroll-region` on that region, and makes every wrapper between it and the content slot a flex column (`display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0`). Miss a wrapper and - the region grows instead of scrolling, so the frame scrolls in its place — a second scrollbar is - the tell. + the region grows instead of scrolling, so the frame scrolls in its place — the scrollbar moving off + the region onto the whole content column is the tell. 4. A table whose header must stay put passes `scrollRegion: true` to `data-table` on such a page. `examples/plugins/scheduling` shows the whole chain on its shifts list. diff --git a/e2e-tests/full-flow.spec.ts b/e2e-tests/full-flow.spec.ts index 1b2637a..302e2b5 100644 --- a/e2e-tests/full-flow.spec.ts +++ b/e2e-tests/full-flow.spec.ts @@ -207,6 +207,7 @@ test.describe.serial("authenticated admin journey", () => { test("plugin page: a filled page scrolls its table, not the document, and the header stays put", async () => { // The region is the viewport less ~185px of chrome, so this leaves ~75px: enough that the 3-row // fixture overflows it by half its height, and enough to hold the header a row scrolls under. + const original = page.viewportSize(); await page.setViewportSize({ width: 1280, height: 260 }); await page.goto("/scheduling/shifts"); @@ -235,7 +236,7 @@ test.describe.serial("authenticated admin journey", () => { await expect(page.locator("tbody tr").last()).toBeInViewport(); expect(await headTop(), "the header sticks to a scrollport that moves").toBe(before); // The journey shares one page; leaving it short would hand the next test a window it never chose. - await page.setViewportSize({ width: 1280, height: 800 }); + if (original) await page.setViewportSize(original); }); test("plugin settings: the screen names the variable that sets each declared key", async () => { diff --git a/e2e-tests/visual.spec.ts b/e2e-tests/visual.spec.ts index 91d5e00..558b0f1 100644 --- a/e2e-tests/visual.spec.ts +++ b/e2e-tests/visual.spec.ts @@ -57,9 +57,16 @@ for (const [name, path, tail] of [ if (width <= 860) { await page.locator(".hamburger").click(); // the label is the control; the checkbox takes no pointer await expect(page.locator("#nav-toggle")).toBeChecked(); + // The lock is one CSS rule, and whether a key press moves the page with the nav open turns + // out to differ by engine — so pin the rule itself, then the behaviour it buys. + expect(await page.evaluate(() => getComputedStyle(document.body).overflow)).toBe("hidden"); + // Both directions: opening the nav may leave the page at either end, and a key press toward + // the end it already sits at cannot move it whether the lock holds or not. const before = await page.evaluate(() => window.scrollY); - await page.keyboard.press("Home"); - expect(await page.evaluate(() => window.scrollY), "a key press cannot scroll the page while the nav is open").toBe(before); + for (const key of ["End", "Home"]) { + await page.keyboard.press(key); + expect(await page.evaluate(() => window.scrollY), key + " cannot scroll the page while the nav is open").toBe(before); + } } }); }