From 80656d522c49ece51668cb8ce95c0ad18462c2d5 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 23 Sep 2026 22:12:45 +0000 Subject: [PATCH] fix(web): stabilize message More menu Escape in hover E2E The desktop hover spec assumed Escape always closed the first page-level menu within one keypress. On self-hosted Chromium the Copy menu could stay open while the rail remained visible, failing getByRole('menu') count. Wait for the Copy item to prove the menu opened, then retry Escape until that item hides while asserting the More control stays on the hover rail. Co-authored-by: cynarAI --- apps/web/e2e/message-hover-actions.spec.ts | 28 ++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/apps/web/e2e/message-hover-actions.spec.ts b/apps/web/e2e/message-hover-actions.spec.ts index f19794e..47b5caf 100644 --- a/apps/web/e2e/message-hover-actions.spec.ts +++ b/apps/web/e2e/message-hover-actions.spec.ts @@ -10,6 +10,25 @@ async function sendComposerMessage(page: Page, composer: Locator, text: string) await expect(composer).toHaveValue(""); } +/** Copy is unique to the message More menu while it is open. */ +function messageMoreCopyItem(page: Page) { + return page.getByRole("menuitem", { name: "Copy" }); +} + +async function expectMessageMoreMenu(page: Page, open: boolean) { + const copyItem = messageMoreCopyItem(page); + if (open) { + await expect(copyItem).toBeVisible(); + return; + } + await expect(async () => { + if (await copyItem.isVisible()) { + await page.keyboard.press("Escape"); + } + await expect(copyItem).toBeHidden({ timeout: 500 }); + }).toPass({ timeout: 10_000 }); +} + async function revealHoverRail(row: Locator): Promise { const rail = row.getByTestId("message-hover-rail"); await expect @@ -180,12 +199,13 @@ test("message hover shows beside-bubble actions; reply links to parent", async ( expect(timeBox).not.toBeNull(); expect(rowBox).not.toBeNull(); expect(Math.abs(timeBox!.x - rowBox!.x)).toBeLessThan(2); - await toolbar.getByRole("button", { name: "More" }).click(); + const moreButton = toolbar.getByRole("button", { name: "More" }); + await moreButton.click(); + await expectMessageMoreMenu(page, true); await expect(page.getByRole("menu").locator("time")).toHaveCount(0); // Escape closes More; the hover rail stays visible for the pinned row. - await page.keyboard.press("Escape"); - await expect(page.getByRole("menu")).toHaveCount(0); - await expect(toolbar.getByRole("button", { name: "More" })).toBeVisible(); + await expectMessageMoreMenu(page, false); + await expect(moreButton).toBeVisible(); await captureScreenshot(page, testInfo, "message-user-actions-hover-desktop"); await page.getByRole("combobox", { name: "Message" }).focus(); // Default transcript shot: rail at rest (no hover pin, mouse clear).