From 664b27ec1ff058d25d5b0ce6057a199c248e96e9 Mon Sep 17 00:00:00 2001 From: Thomas Petersen Date: Mon, 21 Sep 2026 15:46:50 -0400 Subject: [PATCH] test(browser): scroll past tall rows before asserting a new reading row Since the reading fixture shrank to 20 tall messages (#83), the row above the anchored one can be taller than a single 300px wheel step, so the first wholly visible paragraph stayed the same message and "panel restoration yields to a new wheel reading position" failed on main in both engines. Keep making bounded, verified wheel progress until the visible reading row belongs to another message, reusing the shared anchor reader. Signed-off-by: Thomas Petersen --- tests/browser/layout.spec.mjs | 47 +++++++++++++++-------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/tests/browser/layout.spec.mjs b/tests/browser/layout.spec.mjs index f9869719e..b010eb82f 100644 --- a/tests/browser/layout.spec.mjs +++ b/tests/browser/layout.spec.mjs @@ -1,5 +1,5 @@ import { test, expect } from "./fixture.mjs"; -import { settle, upper, expectAnchor } from "./timeline.mjs"; +import { anchor, settle, upper, expectAnchor } from "./timeline.mjs"; const scroll = test.extend({ historyCounts: { alpha: 20, beta: 1 } }); // Resize tests must not enter the fixture’s deliberately held paging path. @@ -606,33 +606,26 @@ readingTest( const history = page.getByRole("region", { name: "Channel message history", }); - const before = await history.evaluate((el) => el.scrollTop); await history.hover(); - await page.mouse.wheel(0, -300); - await expect - .poll(() => history.evaluate((el) => el.scrollTop)) - .toBeLessThan(before); - await settle(page); - // A tall paragraph need not fit wholly in the narrowed viewport. Capture - // the visible reading row, including the production clipped-row fallback. - const reading = await history.evaluate((el) => { - const bounds = el.getBoundingClientRect(); - const rows = Array.from(el.querySelectorAll("[data-message-id]")); - const row = - rows.find((row) => { - const p = row.querySelector("p").getBoundingClientRect(); - return p.top >= bounds.top && p.bottom <= bounds.bottom; - }) ?? - rows.find((row) => { - const rect = row.getBoundingClientRect(); - return rect.bottom > bounds.top && rect.top < bounds.bottom; - }); - if (!row) throw new Error("No visible post-gesture reading row"); - return { - id: row.dataset.messageId, - y: row.querySelector("p").getBoundingClientRect().top - bounds.top, - }; - }); + // A tall row above the anchor can exceed one wheel step, and a tall + // paragraph need not fit wholly in the narrowed viewport. Keep making real + // progress until the visible reading row (including the production + // clipped-row fallback) belongs to another message; never repeat a read + // until an immobile timeline happens to pass. + let reading = original; + for ( + let gesture = 0; + gesture < 6 && reading.id === original.id; + gesture++ + ) { + const before = await history.evaluate((el) => el.scrollTop); + await page.mouse.wheel(0, -300); + await expect + .poll(() => history.evaluate((el) => el.scrollTop)) + .toBeLessThan(before); + await settle(page); + reading = await anchor(page); + } expect(reading.id).not.toBe(original.id); await button(page, "Close Bestie panel").click(); await settle(page);