Skip to content

Commit fe33c25

Browse files
committed
🤖 refactor: dedupe Storybook autofocus waits
1 parent 9ac1da9 commit fe33c25

File tree

4 files changed

+35
-40
lines changed

4 files changed

+35
-40
lines changed

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

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
createBashBackgroundTerminateTool,
1818
} from "./mockFactory";
1919
import { setupSimpleChatStory } from "./storyHelpers";
20+
import { blurActiveElement, waitForChatInputAutofocusDone } from "./storyPlayHelpers.js";
2021
import { userEvent, waitFor } from "@storybook/test";
2122

2223
/**
@@ -64,20 +65,8 @@ async function expandAllBashTools(canvasElement: HTMLElement) {
6465
}
6566

6667
// Avoid leaving focus on a tool header.
67-
// Wait for ChatInput's auto-focus attempt to finish (no timing-based sleeps).
68-
await waitFor(
69-
() => {
70-
const state = canvasElement
71-
.querySelector('[data-component="ChatInputSection"]')
72-
?.getAttribute("data-autofocus-state");
73-
if (state !== "done") {
74-
throw new Error("ChatInput auto-focus not finished");
75-
}
76-
},
77-
{ timeout: 5000 }
78-
);
79-
80-
(document.activeElement as HTMLElement | null)?.blur?.();
68+
await waitForChatInputAutofocusDone(canvasElement);
69+
blurActiveElement();
8170
}
8271

8372
export default {

src/browser/stories/App.chat.stories.tsx

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
} from "./mockFactory";
1717
import { updatePersistedState } from "@/browser/hooks/usePersistedState";
1818
import { getModelKey } from "@/common/constants/storage";
19+
import { blurActiveElement, waitForChatInputAutofocusDone } from "./storyPlayHelpers.js";
1920
import { setupSimpleChatStory, setupStreamingChatStory } from "./storyHelpers";
2021
import { within, userEvent, waitFor } from "@storybook/test";
2122

@@ -330,19 +331,9 @@ export const GenericTool: AppStory = {
330331
},
331332
{ timeout: 5000 }
332333
);
333-
// Wait for ChatInput's auto-focus attempt to finish (no timing-based sleeps), then blur
334-
await waitFor(
335-
() => {
336-
const state = canvasElement
337-
.querySelector('[data-component="ChatInputSection"]')
338-
?.getAttribute("data-autofocus-state");
339-
if (state !== "done") {
340-
throw new Error("ChatInput auto-focus not finished");
341-
}
342-
},
343-
{ timeout: 5000 }
344-
);
345-
(document.activeElement as HTMLElement)?.blur();
334+
// Wait for ChatInput's auto-focus attempt to finish, then blur
335+
await waitForChatInputAutofocusDone(canvasElement);
336+
blurActiveElement();
346337
},
347338
};
348339

src/browser/stories/App.reviews.stories.tsx

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import { appMeta, AppWithMocks, type AppStory } from "./meta.js";
66
import { setupSimpleChatStory, setReviews, createReview } from "./storyHelpers";
7+
import { blurActiveElement, waitForChatInputAutofocusDone } from "./storyPlayHelpers.js";
78
import { createUserMessage, createAssistantMessage } from "./mockFactory";
89
import { within, userEvent, waitFor } from "@storybook/test";
910

@@ -273,18 +274,8 @@ export const BulkReviewActions: AppStory = {
273274
await userEvent.click(bannerButton);
274275
});
275276

276-
// Wait for ChatInput's auto-focus attempt to finish (no timing-based sleeps), then blur
277-
await waitFor(
278-
() => {
279-
const state = canvasElement
280-
.querySelector('[data-component="ChatInputSection"]')
281-
?.getAttribute("data-autofocus-state");
282-
if (state !== "done") {
283-
throw new Error("ChatInput auto-focus not finished");
284-
}
285-
},
286-
{ timeout: 5000 }
287-
);
288-
(document.activeElement as HTMLElement)?.blur();
277+
// Wait for ChatInput's auto-focus attempt to finish, then blur
278+
await waitForChatInputAutofocusDone(canvasElement);
279+
blurActiveElement();
289280
},
290281
};
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Helpers intended for Storybook play() functions only.
3+
* Keeping these separate avoids pulling @storybook/test into render-time story setup helpers.
4+
*/
5+
6+
import { waitFor } from "@storybook/test";
7+
8+
export async function waitForChatInputAutofocusDone(canvasElement: HTMLElement): Promise<void> {
9+
await waitFor(
10+
() => {
11+
const state = canvasElement
12+
.querySelector('[data-component="ChatInputSection"]')
13+
?.getAttribute("data-autofocus-state");
14+
if (state !== "done") {
15+
throw new Error("ChatInput auto-focus not finished");
16+
}
17+
},
18+
{ timeout: 5000 }
19+
);
20+
}
21+
22+
export function blurActiveElement(): void {
23+
(document.activeElement as HTMLElement | null)?.blur?.();
24+
}

0 commit comments

Comments
 (0)