story-kit: merge 140_bug_activity_status_indicator_never_visible_due_to_display_condition
This commit is contained in:
@@ -18,6 +18,7 @@ type WsHandlers = {
|
||||
onUpdate: (history: Message[]) => void;
|
||||
onSessionId: (sessionId: string) => void;
|
||||
onError: (message: string) => void;
|
||||
onActivity: (toolName: string) => void;
|
||||
onReconciliationProgress: (
|
||||
storyId: string,
|
||||
status: string,
|
||||
@@ -393,3 +394,83 @@ describe("Chat reconciliation banner", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Chat activity status indicator (Bug 140)", () => {
|
||||
beforeEach(() => {
|
||||
capturedWsHandlers = null;
|
||||
setupMocks();
|
||||
});
|
||||
|
||||
it("shows activity label when tool activity fires during streaming content", async () => {
|
||||
render(<Chat projectPath="/tmp/project" onCloseProject={vi.fn()} />);
|
||||
|
||||
await waitFor(() => expect(capturedWsHandlers).not.toBeNull());
|
||||
|
||||
// Simulate sending a message to set loading=true
|
||||
const input = screen.getByPlaceholderText("Send a message...");
|
||||
await act(async () => {
|
||||
fireEvent.change(input, { target: { value: "Read my file" } });
|
||||
});
|
||||
await act(async () => {
|
||||
fireEvent.keyDown(input, { key: "Enter", shiftKey: false });
|
||||
});
|
||||
|
||||
// Simulate tokens arriving (streamingContent becomes non-empty)
|
||||
act(() => {
|
||||
capturedWsHandlers?.onToken("I'll read that file for you.");
|
||||
});
|
||||
|
||||
// Now simulate a tool activity event while streamingContent is non-empty
|
||||
act(() => {
|
||||
capturedWsHandlers?.onActivity("read_file");
|
||||
});
|
||||
|
||||
// The activity indicator should be visible with the tool activity label
|
||||
const indicator = await screen.findByTestId("activity-indicator");
|
||||
expect(indicator).toBeInTheDocument();
|
||||
expect(indicator).toHaveTextContent("Reading file...");
|
||||
});
|
||||
|
||||
it("shows Thinking... fallback when loading with no streaming and no activity", async () => {
|
||||
render(<Chat projectPath="/tmp/project" onCloseProject={vi.fn()} />);
|
||||
|
||||
await waitFor(() => expect(capturedWsHandlers).not.toBeNull());
|
||||
|
||||
// Simulate sending a message to set loading=true
|
||||
const input = screen.getByPlaceholderText("Send a message...");
|
||||
await act(async () => {
|
||||
fireEvent.change(input, { target: { value: "Hello" } });
|
||||
});
|
||||
await act(async () => {
|
||||
fireEvent.keyDown(input, { key: "Enter", shiftKey: false });
|
||||
});
|
||||
|
||||
// No tokens, no activity — should show "Thinking..."
|
||||
const indicator = await screen.findByTestId("activity-indicator");
|
||||
expect(indicator).toBeInTheDocument();
|
||||
expect(indicator).toHaveTextContent("Thinking...");
|
||||
});
|
||||
|
||||
it("hides Thinking... when streaming content is present but no tool activity", async () => {
|
||||
render(<Chat projectPath="/tmp/project" onCloseProject={vi.fn()} />);
|
||||
|
||||
await waitFor(() => expect(capturedWsHandlers).not.toBeNull());
|
||||
|
||||
// Simulate sending a message to set loading=true
|
||||
const input = screen.getByPlaceholderText("Send a message...");
|
||||
await act(async () => {
|
||||
fireEvent.change(input, { target: { value: "Hello" } });
|
||||
});
|
||||
await act(async () => {
|
||||
fireEvent.keyDown(input, { key: "Enter", shiftKey: false });
|
||||
});
|
||||
|
||||
// Tokens arrive — streamingContent is non-empty, no activity
|
||||
act(() => {
|
||||
capturedWsHandlers?.onToken("Here is my response...");
|
||||
});
|
||||
|
||||
// The activity indicator should NOT be visible (just streaming bubble)
|
||||
expect(screen.queryByTestId("activity-indicator")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -683,8 +683,9 @@ export function Chat({ projectPath, onCloseProject }: ChatProps) {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{loading && !streamingContent && (
|
||||
{loading && (activityStatus != null || !streamingContent) && (
|
||||
<div
|
||||
data-testid="activity-indicator"
|
||||
style={{
|
||||
alignSelf: "flex-start",
|
||||
color: "#888",
|
||||
|
||||
Reference in New Issue
Block a user