Skip to content

Commit 038007e

Browse files
authored
🤖 fix: resolve bash tool story flakiness (#1083)
The `expandAllBashTools` helper had a race condition where it would find and click expand icons before all messages had finished rendering. **Root cause:** `createStaticChatHandler` sends messages async (50ms delay), and `waitFor` succeeded as soon as *any* expand icons appeared, missing tools that rendered in later React commits. **Fix:** - Add `data-loaded` attribute to message-window in AIView.tsx that reflects the actual loading state (true when caught-up received) - Update `expandAllBashTools` to wait for `data-loaded="true"` before finding expand icons This is non-racy because `data-loaded` only becomes true after `caught-up` is processed, and all messages are sent before `caught-up`. _Generated with `mux`_
1 parent f4a1a82 commit 038007e

File tree

2 files changed

+15
-5
lines changed

2 files changed

+15
-5
lines changed

src/browser/components/AIView.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,7 @@ const AIViewInner: React.FC<AIViewProps> = ({
562562
aria-label="Conversation transcript"
563563
tabIndex={0}
564564
data-testid="message-window"
565+
data-loaded={!loading}
565566
className="h-full overflow-y-auto p-[15px] leading-[1.5] break-words whitespace-pre-wrap"
566567
>
567568
<div

src/browser/stories/App.bash.stories.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,29 @@ import { userEvent, waitFor } from "@storybook/test";
2121

2222
/**
2323
* Helper to expand all bash tool calls in a story.
24-
* Clicks on the ▶ expand icons to expand tool details.
24+
* Waits for messages to load, then clicks on the ▶ expand icons to expand tool details.
2525
*/
2626
async function expandAllBashTools(canvasElement: HTMLElement) {
27+
// Wait for messages to finish loading (non-racy: uses actual loading state)
28+
await waitFor(
29+
() => {
30+
const messageWindow = canvasElement.querySelector('[data-testid="message-window"]');
31+
if (!messageWindow || messageWindow.getAttribute("data-loaded") !== "true") {
32+
throw new Error("Messages not loaded yet");
33+
}
34+
},
35+
{ timeout: 5000 }
36+
);
37+
38+
// Now find and expand all tool icons
2739
await waitFor(
2840
async () => {
29-
// Find all ▶ expand icons (they contain the triangle character)
30-
// The icon parent div is clickable and triggers expansion
3141
const allSpans = canvasElement.querySelectorAll("span");
3242
const expandIcons = Array.from(allSpans).filter((span) => span.textContent?.trim() === "▶");
3343
if (expandIcons.length === 0) {
3444
throw new Error("No expand icons found");
3545
}
3646
for (const icon of expandIcons) {
37-
// Click the parent element (the tool header row)
3847
const header = icon.closest("[class*='cursor-pointer']");
3948
if (header) {
4049
await userEvent.click(header as HTMLElement);
@@ -44,7 +53,7 @@ async function expandAllBashTools(canvasElement: HTMLElement) {
4453
{ timeout: 5000 }
4554
);
4655

47-
// Wait for any auto-focus timers, then blur
56+
// Wait for focus auto-select timer, then blur
4857
await new Promise((resolve) => setTimeout(resolve, 150));
4958
(document.activeElement as HTMLElement)?.blur();
5059
}

0 commit comments

Comments
 (0)