fix(test): stabilize tool call shimmer lifecycle gate in browser e2e

This commit is contained in:
Mohamed Boudra
2026-08-18 23:34:05 +02:00
parent 936fd4b6da
commit 60706feb34
@@ -1,6 +1,7 @@
import type { Locator, Page } from "@playwright/test"; import type { Locator, Page } from "@playwright/test";
import { test, expect } from "../support/fixtures"; import { test, expect } from "../support/fixtures";
import { daemonWsRoutePattern } from "../support/helpers/daemon-port"; import { daemonWsRoutePattern } from "../support/helpers/daemon-port";
import { expectComposerVisible } from "../support/helpers/composer";
import { openAgentRoute, seedMockAgentWorkspace } from "../support/helpers/mock-agent"; import { openAgentRoute, seedMockAgentWorkspace } from "../support/helpers/mock-agent";
type WebSocketMessage = string | Buffer; type WebSocketMessage = string | Buffer;
@@ -64,9 +65,8 @@ async function gateSecondToolCall(page: Page, agentId: string) {
let firstCallId: string | null = null; let firstCallId: string | null = null;
let secondCallId: string | null = null; let secondCallId: string | null = null;
let secondRunningMessage: WebSocketMessage | null = null; let secondRunningMessage: WebSocketMessage | null = null;
let pauseAfterSecondRunning = false;
let releaseSecondRequested = false; let releaseSecondRequested = false;
let pauseServerMessages = false;
let secondRunningForwarded = false;
let forwardSecondRunning: (() => void) | null = null; let forwardSecondRunning: (() => void) | null = null;
let resolveFirstCompleted!: () => void; let resolveFirstCompleted!: () => void;
let resolveSecondRunning!: () => void; let resolveSecondRunning!: () => void;
@@ -80,15 +80,14 @@ async function gateSecondToolCall(page: Page, agentId: string) {
await page.routeWebSocket(daemonWsRoutePattern(), (ws) => { await page.routeWebSocket(daemonWsRoutePattern(), (ws) => {
const server = ws.connectToServer(); const server = ws.connectToServer();
forwardSecondRunning = () => { forwardSecondRunning = () => {
if (!secondRunningMessage || secondRunningForwarded) { if (secondRunningMessage) {
return; ws.send(secondRunningMessage);
secondRunningMessage = null;
} }
ws.send(secondRunningMessage);
secondRunningForwarded = true;
}; };
ws.onMessage((message) => server.send(message)); ws.onMessage((message) => server.send(message));
server.onMessage((message) => { server.onMessage((message) => {
if (pauseServerMessages) { if (pauseAfterSecondRunning) {
return; return;
} }
@@ -97,6 +96,7 @@ async function gateSecondToolCall(page: Page, agentId: string) {
ws.send(message); ws.send(message);
return; return;
} }
if (!firstCallId) { if (!firstCallId) {
firstCallId = toolCall.callId; firstCallId = toolCall.callId;
} }
@@ -109,24 +109,11 @@ async function gateSecondToolCall(page: Page, agentId: string) {
} }
secondCallId ??= toolCall.callId; secondCallId ??= toolCall.callId;
if ( if (toolCall.callId === secondCallId) {
toolCall.callId === secondCallId && const transformedMessage =
(toolCall.status === "running" || toolCall.status === "executing") toolCall.status === "completed" ? replaceToolCallStatus(message, "running") : message;
) { secondRunningMessage = transformedMessage;
secondRunningMessage = message; pauseAfterSecondRunning = true;
pauseServerMessages = true;
resolveSecondRunning();
if (releaseSecondRequested) {
forwardSecondRunning?.();
}
return;
}
if (toolCall.callId === secondCallId && toolCall.status === "completed") {
// Keep the second real tool call inspectably active. Production providers
// send this same status shape while their work remains in flight.
secondRunningMessage = replaceToolCallStatus(message, "running");
pauseServerMessages = true;
resolveSecondRunning(); resolveSecondRunning();
if (releaseSecondRequested) { if (releaseSecondRequested) {
forwardSecondRunning?.(); forwardSecondRunning?.();
@@ -143,10 +130,7 @@ async function gateSecondToolCall(page: Page, agentId: string) {
waitForSecondRunning: () => secondRunning, waitForSecondRunning: () => secondRunning,
releaseSecondRunning() { releaseSecondRunning() {
releaseSecondRequested = true; releaseSecondRequested = true;
pauseServerMessages = false; forwardSecondRunning?.();
if (secondRunningMessage) {
forwardSecondRunning?.();
}
}, },
}; };
} }
@@ -192,10 +176,11 @@ test("measures an overview heading that becomes loading after its idle mount", a
workspaceId: agent.workspaceId, workspaceId: agent.workspaceId,
agentId: agent.agentId, agentId: agent.agentId,
}); });
await expectComposerVisible(page);
await agent.client.sendAgentMessage(agent.agentId, "Prove the overview shimmer lifecycle."); await agent.client.sendAgentMessage(agent.agentId, "Prove the overview shimmer lifecycle.");
await gate.waitForFirstCompleted(); await gate.waitForFirstCompleted();
const group = page.getByTestId("tool-call-group"); const group = page.getByTestId("tool-call-group").first();
await expect(group).toBeVisible(); await expect(group).toBeVisible();
const idleGroupHandle = await group.elementHandle(); const idleGroupHandle = await group.elementHandle();
if (!idleGroupHandle) { if (!idleGroupHandle) {