Skip to content

Commit a6a2f28

Browse files
fix(a11y): use aria-expanded=false for collapsed compact tool row + add ChatRow compact tool tests
- Change aria-expanded={isExpanded} to aria-expanded={false} per edelauna review (button only renders when !isExpanded, so value is always false) - Add ChatRow.compact-tool.spec.tsx with 3 tests: 1. Renders compact row when compactToolUI=true and not expanded 2. Calls onToggleExpand when compact row is clicked 3. Has aria-expanded=false on the compact button Addresses review feedback on PR #327
1 parent 8f2079e commit a6a2f28

2 files changed

Lines changed: 109 additions & 1 deletion

File tree

webview-ui/src/components/chat/ChatRow.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1423,7 +1423,7 @@ export const ChatRowContent = ({
14231423
<button
14241424
type="button"
14251425
onClick={handleToggleExpand}
1426-
aria-expanded={isExpanded}
1426+
aria-expanded={false}
14271427
className="flex items-center gap-2 py-0.5 cursor-pointer text-vscode-descriptionForeground hover:text-vscode-foreground bg-transparent border-none text-inherit w-full text-left"
14281428
data-testid="compact-tool-row"
14291429
title={t("chat:compactTool.expandHint")}>
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import React from "react"
2+
import { fireEvent, render, screen } from "@/utils/test-utils"
3+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
4+
import type { ClineMessage } from "@roo-code/types"
5+
import { ChatRowContent } from "../ChatRow"
6+
7+
const mockPostMessage = vi.fn()
8+
const mockOnToggleExpand = vi.fn()
9+
10+
vi.mock("@src/utils/vscode", () => ({
11+
vscode: {
12+
postMessage: (...args: unknown[]) => mockPostMessage(...args),
13+
},
14+
}))
15+
16+
// Mock i18n
17+
vi.mock("react-i18next", () => ({
18+
useTranslation: () => ({
19+
t: (key: string, opts?: Record<string, string>) => {
20+
const map: Record<string, string> = {
21+
"chat:compactTool.expandHint": "Click to expand",
22+
"chat:compactTool.label": opts?.tool ? `tool: ${opts.tool}` : "tool",
23+
}
24+
return map[key] || key
25+
},
26+
}),
27+
Trans: ({ children }: { children?: React.ReactNode }) => <>{children}</>,
28+
initReactI18next: { type: "3rdParty", init: () => {} },
29+
}))
30+
31+
// Mock CodeBlock (avoid ESM/highlighter costs)
32+
vi.mock("@src/components/common/CodeBlock", () => ({
33+
default: () => null,
34+
}))
35+
36+
// Mock useExtensionState to enable compactToolUI
37+
vi.mock("@src/context/ExtensionStateContext", () => ({
38+
useExtensionState: () => ({
39+
mcpServers: [],
40+
alwaysAllowMcp: false,
41+
currentCheckpoint: undefined,
42+
mode: "code",
43+
apiConfiguration: {},
44+
clineMessages: [],
45+
currentTaskItem: undefined,
46+
compactToolUI: true,
47+
}),
48+
ExtensionStateContextProvider: ({ children }: { children: React.ReactNode }) => <>{children}</>,
49+
}))
50+
51+
const queryClient = new QueryClient()
52+
53+
function createSayToolMessage(toolPayload: Record<string, unknown>): ClineMessage {
54+
return {
55+
type: "say",
56+
say: "tool" as any,
57+
ts: Date.now(),
58+
text: JSON.stringify(toolPayload),
59+
}
60+
}
61+
62+
function renderChatRow(message: ClineMessage, isExpanded = false) {
63+
return render(
64+
<QueryClientProvider client={queryClient}>
65+
<ChatRowContent
66+
message={message}
67+
isExpanded={isExpanded}
68+
isLast={false}
69+
isStreaming={false}
70+
onToggleExpand={mockOnToggleExpand}
71+
onSuggestionClick={() => {}}
72+
onBatchFileResponse={() => {}}
73+
onFollowUpUnmount={() => {}}
74+
isFollowUpAnswered={false}
75+
/>
76+
</QueryClientProvider>,
77+
)
78+
}
79+
80+
describe("ChatRow - compact tool UI", () => {
81+
beforeEach(() => {
82+
vi.clearAllMocks()
83+
mockOnToggleExpand.mockClear()
84+
})
85+
86+
it("renders the compact row when compactToolUI is true and not expanded", () => {
87+
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
88+
renderChatRow(message, false)
89+
90+
expect(screen.getByTestId("compact-tool-row")).toBeInTheDocument()
91+
})
92+
93+
it("calls onToggleExpand when the compact row is clicked", () => {
94+
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
95+
renderChatRow(message, false)
96+
97+
fireEvent.click(screen.getByTestId("compact-tool-row"))
98+
99+
expect(mockOnToggleExpand).toHaveBeenCalledWith(message.ts)
100+
})
101+
102+
it("has aria-expanded=false on the compact button", () => {
103+
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
104+
renderChatRow(message, false)
105+
106+
expect(screen.getByTestId("compact-tool-row")).toHaveAttribute("aria-expanded", "false")
107+
})
108+
})

0 commit comments

Comments
 (0)