From 0f89a417759afd263c7d8ce0747b6547fb8aa2ef Mon Sep 17 00:00:00 2001 From: npub1x4hk035p3p9q39a3fcrd2fe30lpkrhr5dwe0cqzzjphxyyh8m0gsq4vqap <356f67c681884a0897b14e06d527317fc361dc746bb2fc0042906e6212e7dbd1@buzz.block.builderlab.xyz> Date: Mon, 27 Jul 2026 11:22:45 -0700 Subject: [PATCH] test(desktop): await thread scroll anchor Co-authored-by: npub1x4hk035p3p9q39a3fcrd2fe30lpkrhr5dwe0cqzzjphxyyh8m0gsq4vqap <356f67c681884a0897b14e06d527317fc361dc746bb2fc0042906e6212e7dbd1@buzz.block.builderlab.xyz> Signed-off-by: npub1x4hk035p3p9q39a3fcrd2fe30lpkrhr5dwe0cqzzjphxyyh8m0gsq4vqap <356f67c681884a0897b14e06d527317fc361dc746bb2fc0042906e6212e7dbd1@buzz.block.builderlab.xyz> --- desktop/tests/e2e/thread-focus-mode.spec.ts | 44 ++++++++++++++------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/desktop/tests/e2e/thread-focus-mode.spec.ts b/desktop/tests/e2e/thread-focus-mode.spec.ts index 8bb9a3b52b..36eb0630ba 100644 --- a/desktop/tests/e2e/thread-focus-mode.spec.ts +++ b/desktop/tests/e2e/thread-focus-mode.spec.ts @@ -30,17 +30,37 @@ async function seedLongThread(page: import("@playwright/test").Page) { }); } -async function topVisibleMessageId( +async function scrollToMiddleVisibleMessage( body: import("@playwright/test").Locator, + threadRootId: string, ): Promise { - return body.evaluate((element) => { - const top = element.getBoundingClientRect().top; - const row = Array.from( - element.querySelectorAll("[data-message-id]"), - ).find((candidate) => candidate.getBoundingClientRect().bottom > top); - if (!row?.dataset.messageId) throw new Error("No visible thread anchor"); - return row.dataset.messageId; - }); + let anchorId: string | null = null; + await expect + .poll(async () => { + anchorId = await body.evaluate((element) => { + const maxScrollTop = element.scrollHeight - element.clientHeight; + if (maxScrollTop <= 0) return null; + + const targetScrollTop = Math.floor(maxScrollTop * 0.4); + element.scrollTop = targetScrollTop; + element.dispatchEvent(new Event("scroll", { bubbles: true })); + + if (Math.abs(element.scrollTop - targetScrollTop) > 1) return null; + const bounds = element.getBoundingClientRect(); + const row = Array.from( + element.querySelectorAll("[data-message-id]"), + ).find((candidate) => { + const rect = candidate.getBoundingClientRect(); + return rect.bottom > bounds.top && rect.top < bounds.bottom; + }); + return row?.dataset.messageId ?? null; + }); + return anchorId !== null && anchorId !== threadRootId; + }) + .toBe(true); + + if (!anchorId) throw new Error("No visible middle-thread anchor"); + return anchorId; } /** @@ -181,11 +201,7 @@ test("focus and split preserve reading context and interaction ownership", async .toBe(true); await expect(channel).toHaveAttribute("inert", ""); - await body.evaluate((element) => { - element.scrollTop = element.scrollHeight * 0.4; - element.dispatchEvent(new Event("scroll", { bubbles: true })); - }); - const anchorId = await topVisibleMessageId(body); + const anchorId = await scrollToMiddleVisibleMessage(body, rootId); const focusModeToggle = page.getByRole("button", { name: "Show thread beside channel",