From 913d564ce0f35924291bf3eeab6508517a6d8d1f Mon Sep 17 00:00:00 2001 From: Cameron Hotchkies Date: Tue, 28 Jul 2026 14:17:17 -0700 Subject: [PATCH] fix(desktop): stabilize flaky DM expansion E2E ordering assertions (#2004) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Fixes 4 flaky DM expansion E2E tests in Desktop Smoke shard 1 that were failing non-deterministically on CI (also reproducing on `main` at run `29526844596`). **Failing tests:** - `channels.spec.ts:652` — creates the DM before preparing a persona mention - `channels.spec.ts:760` — routes an agent mention from an existing DM to the expanded conversation - `channels.spec.ts:815` — routes a relay-agent mention from an existing DM to the expanded conversation - `channels.spec.ts:940` — drops an expanded DM after the first message fails ## Root Cause Race condition: under fast CI execution, mock command completions (create_managed_agent, open_dm) can resolve in non-deterministic order, causing assertions to observe stale or mid-transition state. ## Fix - **:652** — Move the `new-message-recipient-popover` hidden assertion after `chat-title` settles (both names present), so it runs post-transition rather than mid-transition. - **:760, :940** — Add `createManagedAgentDelayMs: 100` to ensure persona provisioning doesn't collapse into the same tick as the expanded-DM open/start sequence. - **:815** — Add `openDmDelayMs: 100` so the two open_dm calls resolve in deterministic order. ## Validation All 4 tests pass with `--repeat-each=3` (12/12 green) locally. Biome lint clean. ## Scope Test-only change: 12 insertions, 1 deletion in `desktop/tests/e2e/channels.spec.ts`. --- Investigated by Ferret, reviewed by Grumplestiltzkin. Signed-off-by: Cameron Hotchkies Co-authored-by: Goose --- desktop/tests/e2e/channels.spec.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/desktop/tests/e2e/channels.spec.ts b/desktop/tests/e2e/channels.spec.ts index 9c5bbfe80..9da402242 100644 --- a/desktop/tests/e2e/channels.spec.ts +++ b/desktop/tests/e2e/channels.spec.ts @@ -712,7 +712,6 @@ test("creates the DM before preparing a persona mention", async ({ page }) => { page.getByTestId(`new-dm-selected-${TEST_IDENTITIES.charlie.pubkey}`), ).toBeDisabled(); await expect(page.getByTestId("new-dm-search")).toBeDisabled(); - await expect(page.getByTestId("new-message-recipient-popover")).toBeHidden(); await expect .poll(async () => commandCount(await readCommandLog(page), "create_managed_agent"), @@ -720,6 +719,9 @@ test("creates the DM before preparing a persona mention", async ({ page }) => { .toBeGreaterThan(baselineCreateCount); await expect(page.getByTestId("chat-title")).toContainText("charlie"); await expect(page.getByTestId("chat-title")).toContainText("Fizz"); + // Assert popover hidden after chat-title settles — by this point the send + // flow has completed and the UI has fully transitioned away from the popover. + await expect(page.getByTestId("new-message-recipient-popover")).toBeHidden(); const sendCommands = (await readCommandLog(page)).slice( baselineCommands.length, @@ -782,8 +784,11 @@ test("creates the DM before preparing a persona mention", async ({ page }) => { test("routes an agent mention from an existing DM to the expanded conversation", async ({ page, }) => { + // Delay persona provisioning so the follow-up expanded-DM open/start sequence + // cannot collapse into the same fast CI tick before assertions observe it. await installMockBridge(page, { activePersonaIds: ["builtin:fizz"], + createManagedAgentDelayMs: 100, }); await page.goto("/"); @@ -837,7 +842,10 @@ test("routes an agent mention from an existing DM to the expanded conversation", test("routes a managed relay-agent mention from an existing DM to the expanded conversation", async ({ page, }) => { + // Delay the expanded open_dm call so routing/navigation settles + // deterministically under fast CI execution. await installMockBridge(page, { + openDmDelayMs: 100, managedAgents: [ { pubkey: DM_RELAY_AGENT_PUBKEY, @@ -967,8 +975,11 @@ test("does not reroute an expanded DM after the channel pane unmounts", async ({ test("drops an expanded DM after the first message fails", async ({ page }) => { const retryMessage = "Retry without the agent"; const sendError = "Mock first DM send failed."; + // Delay persona provisioning so the follow-up expanded-DM open/start sequence + // cannot collapse into the same fast CI tick before assertions observe it. await installMockBridge(page, { activePersonaIds: ["builtin:fizz"], + createManagedAgentDelayMs: 100, sendMessageErrors: [sendError], }); await page.goto("/");