Skip to content

Commit 1c29772

Browse files
committed
fix: prevent auto-approve menu overflow with scrollable container
- Add max-h-[400px] and overflow-y-auto Tailwind classes to expanded content - Ensures menu remains usable when all 10 toggles are displayed - Add tests to verify overflow behavior
1 parent 6fa918c commit 1c29772

File tree

2 files changed

+134
-1
lines changed

2 files changed

+134
-1
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import { render, screen, fireEvent } from "@/utils/test-utils"
2+
import { describe, it, expect, vi, beforeEach } from "vitest"
3+
import AutoApproveMenu from "../components/chat/AutoApproveMenu"
4+
5+
// Mock vscode API
6+
vi.mock("@src/utils/vscode", () => ({
7+
vscode: {
8+
postMessage: vi.fn(),
9+
},
10+
}))
11+
12+
// Mock window.postMessage
13+
const mockPostMessage = vi.fn()
14+
window.postMessage = mockPostMessage
15+
16+
// Mock useExtensionState
17+
const mockUseExtensionState = vi.fn()
18+
19+
vi.mock("@src/context/ExtensionStateContext", () => ({
20+
useExtensionState: () => mockUseExtensionState(),
21+
ExtensionStateContextProvider: ({ children }: { children: React.ReactNode }) => <>{children}</>,
22+
}))
23+
24+
// Mock translation hook
25+
vi.mock("@src/i18n/TranslationContext", () => ({
26+
useAppTranslation: () => ({
27+
t: (key: string) => key,
28+
}),
29+
}))
30+
31+
const createMockExtensionState = (overrides = {}) => ({
32+
autoApprovalEnabled: false,
33+
setAutoApprovalEnabled: vi.fn(),
34+
alwaysAllowReadOnly: false,
35+
alwaysAllowWrite: false,
36+
alwaysAllowExecute: false,
37+
alwaysAllowBrowser: false,
38+
alwaysAllowMcp: false,
39+
alwaysAllowModeSwitch: false,
40+
alwaysAllowSubtasks: false,
41+
alwaysApproveResubmit: false,
42+
alwaysAllowFollowupQuestions: false,
43+
alwaysAllowUpdateTodoList: false,
44+
allowedMaxRequests: undefined,
45+
setAlwaysAllowReadOnly: vi.fn(),
46+
setAlwaysAllowWrite: vi.fn(),
47+
setAlwaysAllowExecute: vi.fn(),
48+
setAlwaysAllowBrowser: vi.fn(),
49+
setAlwaysAllowMcp: vi.fn(),
50+
setAlwaysAllowModeSwitch: vi.fn(),
51+
setAlwaysAllowSubtasks: vi.fn(),
52+
setAlwaysApproveResubmit: vi.fn(),
53+
setAlwaysAllowFollowupQuestions: vi.fn(),
54+
setAlwaysAllowUpdateTodoList: vi.fn(),
55+
setAllowedMaxRequests: vi.fn(),
56+
...overrides,
57+
})
58+
59+
describe("AutoApproveMenu", () => {
60+
beforeEach(() => {
61+
vi.clearAllMocks()
62+
mockUseExtensionState.mockReturnValue(createMockExtensionState())
63+
})
64+
65+
it("renders without crashing", () => {
66+
render(<AutoApproveMenu />)
67+
expect(screen.getByText("chat:autoApprove.title")).toBeInTheDocument()
68+
})
69+
70+
it("expands when clicked", () => {
71+
render(<AutoApproveMenu />)
72+
73+
// Initially, the expanded content should not be visible
74+
const expandedContainer = document.querySelector(".flex.flex-col.gap-2.max-h-\\[400px\\].overflow-y-auto")
75+
expect(expandedContainer).not.toBeInTheDocument()
76+
77+
// Click to expand
78+
const titleArea = screen.getByText("chat:autoApprove.title").parentElement?.parentElement
79+
fireEvent.click(titleArea!)
80+
81+
// Now the expanded content should be visible
82+
const expandedContent = document.querySelector(".flex.flex-col.gap-2.max-h-\\[400px\\].overflow-y-auto")
83+
expect(expandedContent).toBeInTheDocument()
84+
})
85+
86+
it("expanded content has max-height and overflow-y auto to prevent overflow", () => {
87+
render(<AutoApproveMenu />)
88+
89+
// Click to expand
90+
const titleArea = screen.getByText("chat:autoApprove.title").parentElement?.parentElement
91+
fireEvent.click(titleArea!)
92+
93+
// Find the expanded content container
94+
const expandedContent = document.querySelector(".flex.flex-col.gap-2.max-h-\\[400px\\].overflow-y-auto")
95+
96+
// Check that it exists and has the correct classes
97+
expect(expandedContent).toBeInTheDocument()
98+
expect(expandedContent).toHaveClass("max-h-[400px]", "overflow-y-auto")
99+
})
100+
101+
it("collapses when clicked again", () => {
102+
render(<AutoApproveMenu />)
103+
104+
// Click to expand
105+
const titleArea = screen.getByText("chat:autoApprove.title").parentElement?.parentElement
106+
fireEvent.click(titleArea!)
107+
108+
// Verify expanded
109+
const expandedContent = document.querySelector(".flex.flex-col.gap-2.max-h-\\[400px\\].overflow-y-auto")
110+
expect(expandedContent).toBeInTheDocument()
111+
112+
// Click to collapse
113+
fireEvent.click(titleArea!)
114+
115+
// Verify collapsed
116+
const collapsedContent = document.querySelector(".flex.flex-col.gap-2.max-h-\\[400px\\].overflow-y-auto")
117+
expect(collapsedContent).not.toBeInTheDocument()
118+
})
119+
120+
it("displays enabled actions list when toggles are enabled", () => {
121+
mockUseExtensionState.mockReturnValue(
122+
createMockExtensionState({
123+
alwaysAllowReadOnly: true,
124+
alwaysAllowWrite: true,
125+
}),
126+
)
127+
128+
render(<AutoApproveMenu />)
129+
130+
// Should show the enabled actions instead of "none"
131+
expect(screen.queryByText("chat:autoApprove.none")).not.toBeInTheDocument()
132+
})
133+
})

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
201201
</div>
202202

203203
{isExpanded && (
204-
<div className="flex flex-col gap-2">
204+
<div className="flex flex-col gap-2 max-h-[400px] overflow-y-auto">
205205
<div
206206
style={{
207207
color: "var(--vscode-descriptionForeground)",

0 commit comments

Comments
 (0)