1- import { describe , it , expect , vi , beforeEach , beforeAll } from "vitest"
1+ import { describe , it , expect , vi , beforeEach } from "vitest"
22import type { ClineProvider } from "../../webview/ClineProvider"
33import type { ProviderSettings , ModelInfo } from "@roo-code/types"
44
5+ // All vi.mock() calls are hoisted to the top of the file by Vitest
6+ // and are applied before any imports are resolved
7+
58// Mock vscode module before importing Task
69vi . mock ( "vscode" , ( ) => ( {
710 workspace : {
@@ -72,16 +75,92 @@ vi.mock("@roo-code/telemetry", () => ({
7275 } ,
7376} ) )
7477
78+ // Mock @roo -code/cloud to prevent socket.io-client initialization issues
79+ vi . mock ( "@roo-code/cloud" , ( ) => ( {
80+ CloudService : {
81+ isEnabled : ( ) => false ,
82+ } ,
83+ BridgeOrchestrator : {
84+ subscribeToTask : vi . fn ( ) ,
85+ } ,
86+ } ) )
87+
88+ // Mock delay to prevent actual delays
89+ vi . mock ( "delay" , ( ) => ( {
90+ __esModule : true ,
91+ default : vi . fn ( ) . mockResolvedValue ( undefined ) ,
92+ } ) )
93+
94+ // Mock p-wait-for to prevent hanging on async conditions
95+ vi . mock ( "p-wait-for" , ( ) => ( {
96+ default : vi . fn ( ) . mockResolvedValue ( undefined ) ,
97+ } ) )
98+
99+ // Mock execa
100+ vi . mock ( "execa" , ( ) => ( {
101+ execa : vi . fn ( ) ,
102+ } ) )
103+
104+ // Mock fs/promises
105+ vi . mock ( "fs/promises" , ( ) => ( {
106+ mkdir : vi . fn ( ) . mockResolvedValue ( undefined ) ,
107+ writeFile : vi . fn ( ) . mockResolvedValue ( undefined ) ,
108+ readFile : vi . fn ( ) . mockResolvedValue ( "[]" ) ,
109+ unlink : vi . fn ( ) . mockResolvedValue ( undefined ) ,
110+ rmdir : vi . fn ( ) . mockResolvedValue ( undefined ) ,
111+ } ) )
112+
113+ // Mock mentions
114+ vi . mock ( "../../mentions" , ( ) => ( {
115+ parseMentions : vi . fn ( ) . mockImplementation ( ( text ) => Promise . resolve ( text ) ) ,
116+ openMention : vi . fn ( ) ,
117+ getLatestTerminalOutput : vi . fn ( ) ,
118+ } ) )
119+
120+ // Mock extract-text
121+ vi . mock ( "../../../integrations/misc/extract-text" , ( ) => ( {
122+ extractTextFromFile : vi . fn ( ) . mockResolvedValue ( "Mock file content" ) ,
123+ } ) )
124+
125+ // Mock getEnvironmentDetails
126+ vi . mock ( "../../environment/getEnvironmentDetails" , ( ) => ( {
127+ getEnvironmentDetails : vi . fn ( ) . mockResolvedValue ( "" ) ,
128+ } ) )
129+
130+ // Mock RooIgnoreController
131+ vi . mock ( "../../ignore/RooIgnoreController" )
132+
133+ // Mock condense
134+ vi . mock ( "../../condense" , ( ) => ( {
135+ summarizeConversation : vi . fn ( ) . mockResolvedValue ( {
136+ messages : [ ] ,
137+ summary : "summary" ,
138+ cost : 0 ,
139+ newContextTokens : 1 ,
140+ } ) ,
141+ } ) )
142+
143+ // Mock storage utilities
144+ vi . mock ( "../../../utils/storage" , ( ) => ( {
145+ getTaskDirectoryPath : vi
146+ . fn ( )
147+ . mockImplementation ( ( globalStoragePath , taskId ) => Promise . resolve ( `${ globalStoragePath } /tasks/${ taskId } ` ) ) ,
148+ getSettingsDirectoryPath : vi
149+ . fn ( )
150+ . mockImplementation ( ( globalStoragePath ) => Promise . resolve ( `${ globalStoragePath } /settings` ) ) ,
151+ } ) )
152+
153+ // Mock fs utilities
154+ vi . mock ( "../../../utils/fs" , ( ) => ( {
155+ fileExistsAtPath : vi . fn ( ) . mockReturnValue ( false ) ,
156+ } ) )
157+
158+ // Import Task AFTER all vi.mock() calls - Vitest hoists mocks so this works
159+ import { Task } from "../Task"
160+
75161describe ( "Task reasoning preservation" , ( ) => {
76162 let mockProvider : Partial < ClineProvider >
77163 let mockApiConfiguration : ProviderSettings
78- let Task : any
79-
80- beforeAll ( async ( ) => {
81- // Import Task after mocks are set up
82- const taskModule = await import ( "../Task" )
83- Task = taskModule . Task
84- } )
85164
86165 beforeEach ( ( ) => {
87166 // Mock provider with necessary methods
@@ -127,7 +206,7 @@ describe("Task reasoning preservation", () => {
127206 id : "test-model" ,
128207 info : mockModelInfo ,
129208 } ) ,
130- }
209+ } as any
131210
132211 // Mock the API conversation history
133212 task . apiConversationHistory = [ ]
@@ -163,10 +242,12 @@ describe("Task reasoning preservation", () => {
163242
164243 // Verify the API conversation history contains the message with reasoning
165244 expect ( task . apiConversationHistory ) . toHaveLength ( 1 )
166- expect ( task . apiConversationHistory [ 0 ] . content [ 0 ] . text ) . toContain ( "<think>" )
167- expect ( task . apiConversationHistory [ 0 ] . content [ 0 ] . text ) . toContain ( "</think>" )
168- expect ( task . apiConversationHistory [ 0 ] . content [ 0 ] . text ) . toContain ( "Here is my response to your question." )
169- expect ( task . apiConversationHistory [ 0 ] . content [ 0 ] . text ) . toContain (
245+ expect ( ( task . apiConversationHistory [ 0 ] . content [ 0 ] as { text : string } ) . text ) . toContain ( "<think>" )
246+ expect ( ( task . apiConversationHistory [ 0 ] . content [ 0 ] as { text : string } ) . text ) . toContain ( "</think>" )
247+ expect ( ( task . apiConversationHistory [ 0 ] . content [ 0 ] as { text : string } ) . text ) . toContain (
248+ "Here is my response to your question." ,
249+ )
250+ expect ( ( task . apiConversationHistory [ 0 ] . content [ 0 ] as { text : string } ) . text ) . toContain (
170251 "Let me think about this step by step. First, I need to..." ,
171252 )
172253 } )
@@ -192,7 +273,7 @@ describe("Task reasoning preservation", () => {
192273 id : "test-model" ,
193274 info : mockModelInfo ,
194275 } ) ,
195- }
276+ } as any
196277
197278 // Mock the API conversation history
198279 task . apiConversationHistory = [ ]
@@ -223,8 +304,10 @@ describe("Task reasoning preservation", () => {
223304
224305 // Verify the API conversation history does NOT contain reasoning
225306 expect ( task . apiConversationHistory ) . toHaveLength ( 1 )
226- expect ( task . apiConversationHistory [ 0 ] . content [ 0 ] . text ) . toBe ( "Here is my response to your question." )
227- expect ( task . apiConversationHistory [ 0 ] . content [ 0 ] . text ) . not . toContain ( "<think>" )
307+ expect ( ( task . apiConversationHistory [ 0 ] . content [ 0 ] as { text : string } ) . text ) . toBe (
308+ "Here is my response to your question." ,
309+ )
310+ expect ( ( task . apiConversationHistory [ 0 ] . content [ 0 ] as { text : string } ) . text ) . not . toContain ( "<think>" )
228311 } )
229312
230313 it ( "should handle empty reasoning message gracefully when preserveReasoning is true" , async ( ) => {
@@ -248,7 +331,7 @@ describe("Task reasoning preservation", () => {
248331 id : "test-model" ,
249332 info : mockModelInfo ,
250333 } ) ,
251- }
334+ } as any
252335
253336 // Mock the API conversation history
254337 task . apiConversationHistory = [ ]
@@ -277,8 +360,8 @@ describe("Task reasoning preservation", () => {
277360 } )
278361
279362 // Verify the message doesn't contain reasoning tags
280- expect ( task . apiConversationHistory [ 0 ] . content [ 0 ] . text ) . toBe ( "Here is my response." )
281- expect ( task . apiConversationHistory [ 0 ] . content [ 0 ] . text ) . not . toContain ( "<think>" )
363+ expect ( ( task . apiConversationHistory [ 0 ] . content [ 0 ] as { text : string } ) . text ) . toBe ( "Here is my response." )
364+ expect ( ( task . apiConversationHistory [ 0 ] . content [ 0 ] as { text : string } ) . text ) . not . toContain ( "<think>" )
282365 } )
283366
284367 it ( "should handle undefined preserveReasoning (defaults to false)" , async ( ) => {
@@ -302,7 +385,7 @@ describe("Task reasoning preservation", () => {
302385 id : "test-model" ,
303386 info : mockModelInfo ,
304387 } ) ,
305- }
388+ } as any
306389
307390 // Mock the API conversation history
308391 task . apiConversationHistory = [ ]
@@ -322,8 +405,8 @@ describe("Task reasoning preservation", () => {
322405 } )
323406
324407 // Verify reasoning was NOT prepended (undefined defaults to false)
325- expect ( task . apiConversationHistory [ 0 ] . content [ 0 ] . text ) . toBe ( "Here is my response." )
326- expect ( task . apiConversationHistory [ 0 ] . content [ 0 ] . text ) . not . toContain ( "<think>" )
408+ expect ( ( task . apiConversationHistory [ 0 ] . content [ 0 ] as { text : string } ) . text ) . toBe ( "Here is my response." )
409+ expect ( ( task . apiConversationHistory [ 0 ] . content [ 0 ] as { text : string } ) . text ) . not . toContain ( "<think>" )
327410 } )
328411
329412 it ( "should embed encrypted reasoning as first assistant content block" , async ( ) => {
0 commit comments