mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
test(desktop): await thread scroll anchor (#3174)
## Why The focus/split E2E test could capture the thread root before its programmatic middle-thread scroll had settled, then incorrectly report a scroll-restoration failure. ## What - Poll until the requested middle-thread scroll position is applied - Require the captured anchor to intersect the thread viewport and differ from the root - Preserve the existing focus-to-split-to-focus viewport assertions ## Risk Assessment Low — test-only synchronization change with no production behavior changes. ## References - Original failure: https://github.com/block/buzz/actions/runs/30231271427/job/89870533541 - Buzz thread: buzz://message?channel=12dd513d-45fd-48ff-80ac-8596d2fcc9d3&id=87ce6024b4bf74bfac2fa75d9f7bbbcc8f8fe2df460afe534152c495929f51ba - Reproduced confidence: 20 consecutive targeted passes, full spec pass, `just desktop-ci`, and `just ci` Generated with Codex Signed-off-by: npub1x4hk035p3p9q39a3fcrd2fe30lpkrhr5dwe0cqzzjphxyyh8m0gsq4vqap <356f67c681884a0897b14e06d527317fc361dc746bb2fc0042906e6212e7dbd1@buzz.block.builderlab.xyz> Co-authored-by: npub1x4hk035p3p9q39a3fcrd2fe30lpkrhr5dwe0cqzzjphxyyh8m0gsq4vqap <356f67c681884a0897b14e06d527317fc361dc746bb2fc0042906e6212e7dbd1@buzz.block.builderlab.xyz> Co-authored-by: Wes <wesbillman@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
480c41ebf1
commit
9213090f60
@@ -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<string> {
|
||||
return body.evaluate((element) => {
|
||||
const top = element.getBoundingClientRect().top;
|
||||
const row = Array.from(
|
||||
element.querySelectorAll<HTMLElement>("[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<HTMLElement>("[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",
|
||||
|
||||
Reference in New Issue
Block a user