From 7a9a5233d9d755e715be0c585cf7850e935d28cf Mon Sep 17 00:00:00 2001 From: Will Pfleger Date: Thu, 3 Sep 2026 08:59:49 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20fix(desktop):=20harden=20smoke?= =?UTF-8?q?=20E2E=20tests=20against=20Bestie=20overlay=20and=20toast=20tim?= =?UTF-8?q?ing=20(#7270)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What Two remaining E2E hardening fixes from the Desktop Smoke flake pattern introduced by `ac5a18697` (Bestie — added `VITE_BUZZ_BESTIE=1` to `.env.e2e` and mounted `BestieGlobalOverlay` globally). The toast/DM-retry fix landed independently in main via #7127 (`input.hover()` + bounded `toHaveCount` wait); that hunk is dropped from this PR. ## Fixes ### `agent-control-regressions.spec.ts:240` — Stop does not accept an unconfirmed or foreign-channel result **Cause:** Playwright 1.60.0's `page.clock.install()` fakes all timers including `requestAnimationFrame`. The test called it before opening the settings menu. With RAF frozen, the `DropdownMenuContent`'s `zoom-in-95 duration-150` CSS enter-animation never advances — Playwright's stability check observes a continuously-changing bounding box until the 30s test timeout. **Fix:** Re-sequence so the menu is opened on real time first. After `openAgentActivity`, open the trigger, assert visibility/enabled, call `waitForAnimations(page)` to settle the enter-animation (real `setTimeout`, no fake clock installed yet), then install the clock. The `fastForward(8_001)` correlation timeout still works because it's scheduled after the clock is active. Pointer actionability preserved — normal `stop.click()` (no `force`) fails with pointer-interception under a covering surface. ### `message-feedback-snapshots.spec.ts:97` — profile hover uses the channel hover surface **Cause:** `channel.hover()` triggers a CSS `transition-colors` animation. With the Bestie `LayoutGroup` mounted, `evaluate()` captures a mid-transition background value that never matches the profile card's settled token. **Fix:** `waitForAnimations(page)` after `channel.hover()` and before reading `channelHoverColor`. ## Evidence - Target specs pass: stop-turn 8/8, profile-hover passes. - Full `agent-control-regressions.spec.ts` (7 tests) green. - `just desktop-typecheck` clean at pushed head `0fbfe2a9f`. - No production code changed. Signed-off-by: Will Pfleger Co-authored-by: Hayt <9e1c23a3fd83f61da34420e4e88ff1b16e45cafcc0cd9019eb07d4ecfa8ca9b0@buzz.block.builderlab.xyz> --- .../e2e/agent-control-regressions.spec.ts | 21 +++++++++++++++++-- .../e2e/message-feedback-snapshots.spec.ts | 4 ++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/desktop/tests/e2e/agent-control-regressions.spec.ts b/desktop/tests/e2e/agent-control-regressions.spec.ts index 07ec00d74c..4c0bb08fae 100644 --- a/desktop/tests/e2e/agent-control-regressions.spec.ts +++ b/desktop/tests/e2e/agent-control-regressions.spec.ts @@ -1,6 +1,7 @@ import { expect, test, type Page } from "@playwright/test"; import { installMockBridge, TEST_IDENTITIES } from "../helpers/bridge"; +import { waitForAnimations } from "../helpers/animations"; const AGENT_PUBKEY = TEST_IDENTITIES.charlie.pubkey; const RESTORED_UNSCOPED_AGENT_PUBKEY = TEST_IDENTITIES.outsider.pubkey; @@ -258,10 +259,26 @@ test.describe("agent control browser regressions", () => { }, ], }); - await page.clock.install({ time: new Date("2026-08-30T17:00:00.000Z") }); await openAgentActivity(page, CHANNEL_AGENTS); - await clickStop(page); + // Open the settings menu on real time so the DropdownMenuContent's 150ms + // CSS enter-animation (zoom-in-95) can complete before the fake clock is + // installed. Once the clock is active, every setTimeout — including those + // used by the correlation timeout the test exercises — is fake-controlled. + await page.getByTestId("agent-session-settings-menu-trigger").click(); + const stop = page.getByTestId("agent-session-stop-turn"); + await expect(stop).toBeVisible(); + await expect(stop).toBeEnabled(); + // Settle the enter-animation before installing the fake clock. Real + // setTimeout here; waitForAnimations works normally with no fake clock. + await waitForAnimations(page); + + // Install the fake clock NOW — after the menu is open and stable. Any + // setTimeout scheduled from this point forward (e.g. the 8-second + // correlation timeout) will be fake-clock-controlled. + await page.clock.install({ time: new Date("2026-08-30T17:00:00.000Z") }); + + await stop.click(); await expect .poll(() => readControlRequests(page)) .toEqual( diff --git a/desktop/tests/e2e/message-feedback-snapshots.spec.ts b/desktop/tests/e2e/message-feedback-snapshots.spec.ts index 18776d7f25..5bdcade359 100644 --- a/desktop/tests/e2e/message-feedback-snapshots.spec.ts +++ b/desktop/tests/e2e/message-feedback-snapshots.spec.ts @@ -101,6 +101,10 @@ test("profile hover uses the channel hover surface", async ({ page }) => { const profile = page.getByTestId("sidebar-profile-card"); const channel = page.getByTestId("channel-random"); await channel.hover(); + // Wait for the CSS transition to settle before capturing the hover color so + // a mid-transition sample does not produce a value the profile card (which + // uses the same token) can never match. + await waitForAnimations(page); const channelHoverColor = await channel.evaluate( (element) => getComputedStyle(element).backgroundColor, );