From e0918e8fc289bdfd45fd95d5d0b21bd56358a650 Mon Sep 17 00:00:00 2001 From: Thomas Petersen Date: Sat, 15 Aug 2026 19:43:21 -0400 Subject: [PATCH] test(desktop): stabilize flaky smoke interactions Allow relay initialization polling to wait for its seam and drive section reordering with deterministic pointer events. Signed-off-by: Thomas Petersen --- desktop/tests/e2e/relay-reconnect.spec.ts | 3 +- desktop/tests/e2e/virtualization.spec.ts | 76 ++++++++++++++++++++--- 2 files changed, 68 insertions(+), 11 deletions(-) diff --git a/desktop/tests/e2e/relay-reconnect.spec.ts b/desktop/tests/e2e/relay-reconnect.spec.ts index 74f819cc5..2c54522f4 100644 --- a/desktop/tests/e2e/relay-reconnect.spec.ts +++ b/desktop/tests/e2e/relay-reconnect.spec.ts @@ -186,8 +186,7 @@ test("failed initial relay dial retries automatically", async ({ page }) => { __BUZZ_E2E_GET_RELAY_CONNECTION_STATE__?: () => string; } ).__BUZZ_E2E_GET_RELAY_CONNECTION_STATE__; - if (!getState) throw new Error("Relay state seam is not installed."); - return getState(); + return getState?.() ?? null; }), { timeout: 10_000 }, ) diff --git a/desktop/tests/e2e/virtualization.spec.ts b/desktop/tests/e2e/virtualization.spec.ts index 61a2753ba..f7a44f05c 100644 --- a/desktop/tests/e2e/virtualization.spec.ts +++ b/desktop/tests/e2e/virtualization.spec.ts @@ -32,15 +32,69 @@ async function seedChannelSections(page: Page) { // the sequence dnd-kit needs to fire onDragEnd and commit the reorder. async function dragOver(page: Page, source: Locator, target: Locator) { const from = await source.boundingBox(); - const to = await target.boundingBox(); - if (!from || !to) throw new Error("drag handles not laid out"); - await page.mouse.move(from.x + from.width / 2, from.y + from.height / 2); - await page.mouse.down(); - await page.mouse.move(from.x + from.width / 2, from.y + from.height / 2 + 10); - await page.mouse.move(to.x + to.width / 2, to.y + to.height / 2, { - steps: 10, + if (!from) throw new Error("drag source not laid out"); + const pointer = { + x: from.x + from.width / 2, + y: from.y + from.height / 2, + }; + await source.dispatchEvent("pointerdown", { + button: 0, + buttons: 1, + clientX: pointer.x, + clientY: pointer.y, + isPrimary: true, + pointerId: 1, + pointerType: "mouse", }); - await page.mouse.up(); + await page.evaluate(({ x, y }) => { + document.dispatchEvent( + new PointerEvent("pointermove", { + bubbles: true, + buttons: 1, + clientX: x, + clientY: y + 8, + isPrimary: true, + pointerId: 1, + pointerType: "mouse", + }), + ); + }, pointer); + await expect(page.getByTestId("sidebar-section-drag-overlay")).toBeVisible(); + + const to = await target.boundingBox(); + if (!to) throw new Error("drag target not laid out"); + const destination = { + x: to.x + to.width / 2, + y: to.y + to.height - 2, + }; + await page.evaluate(async ({ x, y }) => { + document.dispatchEvent( + new PointerEvent("pointermove", { + bubbles: true, + buttons: 1, + clientX: x, + clientY: y, + isPrimary: true, + pointerId: 1, + pointerType: "mouse", + }), + ); + await new Promise((resolve) => { + requestAnimationFrame(() => requestAnimationFrame(() => resolve())); + }); + document.dispatchEvent( + new PointerEvent("pointerup", { + bubbles: true, + button: 0, + buttons: 0, + clientX: x, + clientY: y, + isPrimary: true, + pointerId: 1, + pointerType: "mouse", + }), + ); + }, destination); } test.describe("list virtualization", () => { @@ -160,6 +214,10 @@ test.describe("list virtualization", () => { const headers = page.locator('[aria-roledescription="sortable"]'); const topHeader = headers.filter({ hasText: "Priority" }); const bottomHeader = headers.filter({ hasText: "Archive" }); + const topHeaderButton = topHeader.getByRole("button", { + name: "Priority", + exact: true, + }); await expect(topHeader).toBeVisible(); await expect(bottomHeader).toBeVisible(); await expect(headers).toHaveCount(2); @@ -176,7 +234,7 @@ test.describe("list virtualization", () => { // Drag "Priority" past "Archive" — onDragEnd commits arrayMove and persists // the new order. The drop must land for the order to flip. - await dragOver(page, topHeader, bottomHeader); + await dragOver(page, topHeaderButton, bottomHeader); // The drop landed: order flipped. A no-op drag would leave it unchanged. await expect.poll(sectionOrder).toEqual(["Archive", "Priority"]);