@@ -10,6 +10,22 @@ jest.mock("@src/utils/vscode", () => ({
1010 } ,
1111} ) )
1212
13+ // Mock all lucide-react icons with a proxy to handle any icon requested
14+ jest . mock ( "lucide-react" , ( ) => {
15+ return new Proxy (
16+ { } ,
17+ {
18+ get : function ( obj , prop ) {
19+ // Return a component factory for any icon that's requested
20+ if ( prop === "__esModule" ) {
21+ return true
22+ }
23+ return ( ) => < div data-testid = { `${ String ( prop ) } -icon` } > { String ( prop ) } </ div >
24+ } ,
25+ } ,
26+ )
27+ } )
28+
1329const mockExtensionState = {
1430 customModePrompts : { } ,
1531 listApiConfigMeta : [
@@ -19,6 +35,9 @@ const mockExtensionState = {
1935 enhancementApiConfigId : "" ,
2036 setEnhancementApiConfigId : jest . fn ( ) ,
2137 mode : "code" ,
38+ customModes : [ ] ,
39+ customSupportPrompts : [ ] ,
40+ currentApiConfigName : "" ,
2241 customInstructions : "Initial instructions" ,
2342 setCustomInstructions : jest . fn ( ) ,
2443}
@@ -32,69 +51,67 @@ const renderPromptsView = (props = {}) => {
3251 )
3352}
3453
54+ class MockResizeObserver {
55+ observe ( ) { }
56+ unobserve ( ) { }
57+ disconnect ( ) { }
58+ }
59+
60+ global . ResizeObserver = MockResizeObserver
61+
62+ Element . prototype . scrollIntoView = jest . fn ( )
63+
3564describe ( "PromptsView" , ( ) => {
3665 beforeEach ( ( ) => {
3766 jest . clearAllMocks ( )
3867 } )
3968
40- it ( "renders all mode tabs" , ( ) => {
41- renderPromptsView ( )
42- expect ( screen . getByTestId ( "code-tab" ) ) . toBeInTheDocument ( )
43- expect ( screen . getByTestId ( "ask-tab" ) ) . toBeInTheDocument ( )
44- expect ( screen . getByTestId ( "architect-tab" ) ) . toBeInTheDocument ( )
69+ it ( "displays the current mode name in the select trigger" , ( ) => {
70+ renderPromptsView ( { mode : "code" } )
71+ const selectTrigger = screen . getByTestId ( "mode-select-trigger" )
72+ expect ( selectTrigger ) . toHaveTextContent ( "Code" )
4573 } )
4674
47- it ( "defaults to current mode as active tab" , ( ) => {
48- renderPromptsView ( { mode : "ask" } )
49-
50- const codeTab = screen . getByTestId ( "code-tab" )
51- const askTab = screen . getByTestId ( "ask-tab" )
52- const architectTab = screen . getByTestId ( "architect-tab" )
53-
54- expect ( askTab ) . toHaveAttribute ( "data-active" , "true" )
55- expect ( codeTab ) . toHaveAttribute ( "data-active" , "false" )
56- expect ( architectTab ) . toHaveAttribute ( "data-active" , "false" )
75+ it ( "opens the mode selection popover when the trigger is clicked" , async ( ) => {
76+ renderPromptsView ( )
77+ const selectTrigger = screen . getByTestId ( "mode-select-trigger" )
78+ fireEvent . click ( selectTrigger )
79+ await waitFor ( ( ) => {
80+ expect ( selectTrigger ) . toHaveAttribute ( "aria-expanded" , "true" )
81+ } )
5782 } )
5883
59- it ( "switches between tabs correctly" , async ( ) => {
60- const { rerender } = render (
61- < ExtensionStateContext . Provider value = { { ...mockExtensionState , mode : "code" } as any } >
62- < PromptsView onDone = { jest . fn ( ) } />
63- </ ExtensionStateContext . Provider > ,
64- )
65-
66- const codeTab = screen . getByTestId ( "code-tab" )
67- const askTab = screen . getByTestId ( "ask-tab" )
68- const architectTab = screen . getByTestId ( "architect-tab" )
84+ it ( "filters mode options based on search input" , async ( ) => {
85+ renderPromptsView ( )
86+ const selectTrigger = screen . getByTestId ( "mode-select-trigger" )
87+ fireEvent . click ( selectTrigger )
6988
70- // Initial state matches current mode (code)
71- expect ( codeTab ) . toHaveAttribute ( "data-active" , "true" )
72- expect ( askTab ) . toHaveAttribute ( "data-active" , "false" )
73- expect ( architectTab ) . toHaveAttribute ( "data-active" , "false" )
89+ const searchInput = screen . getByTestId ( "mode-search-input" )
90+ fireEvent . change ( searchInput , { target : { value : "ask" } } )
7491
75- // Click Ask tab and update context
76- fireEvent . click ( askTab )
77- rerender (
78- < ExtensionStateContext . Provider value = { { ...mockExtensionState , mode : "ask" } as any } >
79- < PromptsView onDone = { jest . fn ( ) } />
80- </ ExtensionStateContext . Provider > ,
81- )
92+ await waitFor ( ( ) => {
93+ expect ( screen . getByTestId ( "mode-option-ask" ) ) . toBeInTheDocument ( )
94+ expect ( screen . queryByTestId ( "mode-option-code" ) ) . not . toBeInTheDocument ( )
95+ expect ( screen . queryByTestId ( "mode-option-architect" ) ) . not . toBeInTheDocument ( )
96+ } )
97+ } )
8298
83- expect ( askTab ) . toHaveAttribute ( "data-active" , "true" )
84- expect ( codeTab ) . toHaveAttribute ( "data-active" , "false" )
85- expect ( architectTab ) . toHaveAttribute ( "data-active" , "false" )
99+ it ( "selects a mode from the dropdown and sends update message" , async ( ) => {
100+ renderPromptsView ( )
101+ const selectTrigger = screen . getByTestId ( "mode-select-trigger" )
102+ fireEvent . click ( selectTrigger )
86103
87- // Click Architect tab and update context
88- fireEvent . click ( architectTab )
89- rerender (
90- < ExtensionStateContext . Provider value = { { ...mockExtensionState , mode : "architect" } as any } >
91- < PromptsView onDone = { jest . fn ( ) } />
92- </ ExtensionStateContext . Provider > ,
93- )
104+ const askOption = await waitFor ( ( ) => screen . getByTestId ( "mode-option-ask" ) )
105+ fireEvent . click ( askOption )
94106
95- expect ( architectTab ) . toHaveAttribute ( "data-active" , "true" )
96- expect ( askTab ) . toHaveAttribute ( "data-active" , "false" )
97- expect ( codeTab ) . toHaveAttribute ( "data-active" , "false" )
107+ expect ( mockExtensionState . setEnhancementApiConfigId ) . not . toHaveBeenCalled ( ) // Ensure this is not called by mode switch
108+ expect ( vscode . postMessage ) . toHaveBeenCalledWith ( {
109+ type : "mode" ,
110+ text : "ask" ,
111+ } )
112+ await waitFor ( ( ) => {
113+ expect ( selectTrigger ) . toHaveAttribute ( "aria-expanded" , "false" )
114+ } )
98115 } )
99116
100117 it ( "handles prompt changes correctly" , async ( ) => {
@@ -159,21 +176,19 @@ describe("PromptsView", () => {
159176 it ( "handles API configuration selection" , async ( ) => {
160177 renderPromptsView ( )
161178
162- // Click the ENHANCE tab first to show the API config dropdown
163- const enhanceTab = screen . getByTestId ( "ENHANCE-tab" )
164- fireEvent . click ( enhanceTab )
179+ const trigger = screen . getByTestId ( "support-prompt-select-trigger" )
180+ fireEvent . click ( trigger )
165181
166- // Wait for the ENHANCE tab click to take effect
167- const dropdown = await waitFor ( ( ) => screen . getByTestId ( "api-config-dropdown" ) )
168- fireEvent . change ( dropdown , {
169- target : { value : "config1" } ,
170- } )
182+ const enhanceOption = await waitFor ( ( ) => screen . getByTestId ( "ENHANCE-option" ) )
183+ fireEvent . click ( enhanceOption )
171184
172- expect ( mockExtensionState . setEnhancementApiConfigId ) . toHaveBeenCalledWith ( "config1" )
173- expect ( vscode . postMessage ) . toHaveBeenCalledWith ( {
174- type : "enhancementApiConfigId" ,
175- text : "config1" ,
176- } )
185+ const apiConfig = await waitFor ( ( ) => screen . getByTestId ( "api-config-select" ) )
186+ fireEvent . click ( apiConfig )
187+
188+ const config1 = await waitFor ( ( ) => screen . getByTestId ( "config1-option" ) )
189+ fireEvent . click ( config1 )
190+
191+ expect ( mockExtensionState . setEnhancementApiConfigId ) . toHaveBeenCalledWith ( "config1" ) // Ensure this is not called by mode switch
177192 } )
178193
179194 it ( "handles clearing custom instructions correctly" , async ( ) => {
0 commit comments