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 { test, expect } from "../support/fixtures";
import { daemonWsRoutePattern } from "../support/helpers/daemon-port";
import { expectComposerVisible } from "../support/helpers/composer";
import { openAgentRoute, seedMockAgentWorkspace } from "../support/helpers/mock-agent";
type WebSocketMessage = string | Buffer;
@@ -64,9 +65,8 @@ async function gateSecondToolCall(page: Page, agentId: string) {
let firstCallId: string | null = null;
let secondCallId: string | null = null;
let secondRunningMessage: WebSocketMessage | null = null;
let pauseAfterSecondRunning = false;
let releaseSecondRequested = false;
let pauseServerMessages = false;
let secondRunningForwarded = false;
let forwardSecondRunning: (() => void) | null = null;
let resolveFirstCompleted!: () => void;
let resolveSecondRunning!: () => void;
@@ -80,15 +80,14 @@ async function gateSecondToolCall(page: Page, agentId: string) {
await page.routeWebSocket(daemonWsRoutePattern(), (ws) => {
const server = ws.connectToServer();
forwardSecondRunning = () => {
if (!secondRunningMessage || secondRunningForwarded) {
return;
}
if (secondRunningMessage) {
ws.send(secondRunningMessage);
secondRunningForwarded = true;
secondRunningMessage = null;
}
};
ws.onMessage((message) => server.send(message));
server.onMessage((message) => {
if (pauseServerMessages) {
if (pauseAfterSecondRunning) {
return;
}
@@ -97,6 +96,7 @@ async function gateSecondToolCall(page: Page, agentId: string) {
ws.send(message);
return;
}
if (!firstCallId) {
firstCallId = toolCall.callId;
}
@@ -109,24 +109,11 @@ async function gateSecondToolCall(page: Page, agentId: string) {
}
secondCallId ??= toolCall.callId;
if (
toolCall.callId === secondCallId &&
(toolCall.status === "running" || toolCall.status === "executing")
) {
secondRunningMessage = message;
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;
if (toolCall.callId === secondCallId) {
const transformedMessage =
toolCall.status === "completed" ? replaceToolCallStatus(message, "running") : message;
secondRunningMessage = transformedMessage;
pauseAfterSecondRunning = true;
resolveSecondRunning();
if (releaseSecondRequested) {
forwardSecondRunning?.();
@@ -143,10 +130,7 @@ async function gateSecondToolCall(page: Page, agentId: string) {
waitForSecondRunning: () => secondRunning,
releaseSecondRunning() {
releaseSecondRequested = true;
pauseServerMessages = false;
if (secondRunningMessage) {
forwardSecondRunning?.();
}
},
};
}
@@ -192,10 +176,11 @@ test("measures an overview heading that becomes loading after its idle mount", a
workspaceId: agent.workspaceId,
agentId: agent.agentId,
});
await expectComposerVisible(page);
await agent.client.sendAgentMessage(agent.agentId, "Prove the overview shimmer lifecycle.");
await gate.waitForFirstCompleted();
const group = page.getByTestId("tool-call-group");
const group = page.getByTestId("tool-call-group").first();
await expect(group).toBeVisible();
const idleGroupHandle = await group.elementHandle();
if (!idleGroupHandle) {