diff --git a/e2e/helpers/playwright.ts b/e2e/helpers/playwright.ts index 09afdc184..6ae95a8b6 100644 --- a/e2e/helpers/playwright.ts +++ b/e2e/helpers/playwright.ts @@ -29,6 +29,7 @@ interface RouterProbe { declare global { interface Window { __routerProbe?: RouterProbe; + __scrollYAtPress?: number; } } @@ -503,6 +504,34 @@ export async function waitForDropToSettle(page: Page) { await page.waitForTimeout(2 * DND_KIT_CLICK_SUPPRESSION_MS); } +/** + * The scroll position the page was at when it was last pressed, for asserting that + * an action did not move the viewer. Playwright scrolls a click target into view + * itself, and a retried click force-scrolls it again, so a reading taken before the + * press can be stale by the time the press lands. + */ +export async function trackScrollYAtPress(page: Page) { + await page.evaluate(() => { + window.__scrollYAtPress = undefined; + document.addEventListener( + "pointerdown", + () => { + window.__scrollYAtPress = window.scrollY; + }, + { capture: true }, + ); + }); + + return async () => { + const scrollY = await page.evaluate(() => window.__scrollYAtPress); + if (typeof scrollY !== "number") { + throw new Error("The page was never pressed"); + } + + return scrollY; + }; +} + /** Asserts the page rendered rather than the error boundary catching something. */ export async function expectNoErrorPage(page: Page) { await expect(page.getByTestId("error-page")).toHaveCount(0); diff --git a/e2e/sendouq.spec.ts b/e2e/sendouq.spec.ts index 3d6cde298..249bb6efc 100644 --- a/e2e/sendouq.spec.ts +++ b/e2e/sendouq.spec.ts @@ -19,6 +19,7 @@ import { isNotVisible, runRoutine, test, + trackScrollYAtPress, } from "./helpers/playwright"; import { NotificationPopover } from "./pages/layout/notification-popover"; import { SendouQLookingPage } from "./pages/sendouq/sendouq-looking-page"; @@ -237,13 +238,15 @@ test.describe("SendouQ", () => { const lastCard = looking.groupCard(otherUsers.length - 1); await lastCard.root.scrollIntoViewIfNeeded(); - const scrollBefore = await page.evaluate(() => window.scrollY); - expect(scrollBefore).toBeGreaterThan(0); + expect(await page.evaluate(() => window.scrollY)).toBeGreaterThan(0); + const scrollYAtPress = await trackScrollYAtPress(page); await lastCard.pressSuggest(); await expect(looking.groupCard(0).trail).toBeVisible(); - expect(await page.evaluate(() => window.scrollY)).toBe(scrollBefore); + expect(await page.evaluate(() => window.scrollY)).toBe( + await scrollYAtPress(), + ); }); });