@@ -294,35 +294,52 @@ describe("ExtensionHost", () => {
294294 } )
295295
296296 describe ( "sendToExtension" , ( ) => {
297- it ( "should throw error when extension not ready" , ( ) => {
297+ it ( "should throw error when extension not ready" , async ( ) => {
298298 const host = createTestHost ( )
299299 const message : WebviewMessage = { type : "requestModes" }
300300
301- expect ( ( ) => {
302- host . sendToExtension ( message )
303- } ) . toThrow ( "You cannot send messages to the extension before it is ready" )
301+ await expect ( host . sendToExtension ( message ) ) . rejects . toThrow (
302+ "You cannot send messages to the extension before it is ready" ,
303+ )
304304 } )
305305
306- it ( "should emit webviewMessage event when webview is ready" , ( ) => {
306+ it ( "should emit webviewMessage event when webview is ready" , async ( ) => {
307307 const host = createTestHost ( )
308308 const emitSpy = vi . spyOn ( host , "emit" )
309309 const message : WebviewMessage = { type : "requestModes" }
310310
311311 host . markWebviewReady ( )
312312 emitSpy . mockClear ( ) // Clear the markWebviewReady calls
313- host . sendToExtension ( message )
313+ await host . sendToExtension ( message )
314314
315315 expect ( emitSpy ) . toHaveBeenCalledWith ( "webviewMessage" , message )
316316 } )
317317
318- it ( "should not throw when webview is ready" , ( ) => {
318+ it ( "should not throw when webview is ready" , async ( ) => {
319319 const host = createTestHost ( )
320320
321321 host . markWebviewReady ( )
322322
323- expect ( ( ) => {
324- host . sendToExtension ( { type : "requestModes" } )
325- } ) . not . toThrow ( )
323+ await expect ( host . sendToExtension ( { type : "requestModes" } ) ) . resolves . not . toThrow ( )
324+ } )
325+
326+ it ( "should await initialization before emitting message" , async ( ) => {
327+ const host = createTestHost ( )
328+ const emitSpy = vi . spyOn ( host , "emit" )
329+ const message : WebviewMessage = { type : "requestModes" }
330+
331+ host . markWebviewReady ( )
332+ emitSpy . mockClear ( )
333+
334+ // Send message immediately after marking ready
335+ const promise = host . sendToExtension ( message )
336+
337+ // Message should not be emitted yet if initialization is still pending
338+ // In this test, initialization completes synchronously, so this is just
339+ // ensuring the await happens
340+ await promise
341+
342+ expect ( emitSpy ) . toHaveBeenCalledWith ( "webviewMessage" , message )
326343 } )
327344 } )
328345
@@ -343,6 +360,49 @@ describe("ExtensionHost", () => {
343360 } )
344361 } )
345362
363+ describe ( "initialization ordering" , ( ) => {
364+ it ( "should ensure all messages await initialization promise" , async ( ) => {
365+ const host = createTestHost ( )
366+ let initializationResolved = false
367+ let resolveInit : ( ) => void
368+
369+ // Create a manually-resolved initialization promise
370+ const initPromise = new Promise < void > ( ( resolve ) => {
371+ resolveInit = ( ) => {
372+ initializationResolved = true
373+ resolve ( )
374+ }
375+ } )
376+
377+ // Override the initialization promise before marking ready
378+ const privateHost = host as unknown as { initializationPromise : Promise < void > ; isReady : boolean }
379+ privateHost . isReady = true
380+ privateHost . initializationPromise = initPromise
381+
382+ const emitSpy = vi . spyOn ( host , "emit" )
383+
384+ // Send a message - it should wait for initialization
385+ const sendPromise = host . sendToExtension ( { type : "requestModes" } )
386+
387+ // Give it a tick to start processing
388+ await new Promise ( ( resolve ) => setImmediate ( resolve ) )
389+
390+ // Message should not be emitted yet because initialization hasn't resolved
391+ expect ( initializationResolved ) . toBe ( false )
392+ expect ( emitSpy ) . not . toHaveBeenCalledWith ( "webviewMessage" , { type : "requestModes" } )
393+
394+ // Now resolve initialization
395+ resolveInit ! ( )
396+
397+ // Wait for the message to be sent
398+ await sendPromise
399+
400+ // Now initialization should be complete and message emitted
401+ expect ( initializationResolved ) . toBe ( true )
402+ expect ( emitSpy ) . toHaveBeenCalledWith ( "webviewMessage" , { type : "requestModes" } )
403+ } )
404+ } )
405+
346406 describe ( "public agent state API" , ( ) => {
347407 it ( "should return agent state from getAgentState()" , ( ) => {
348408 const host = createTestHost ( )
@@ -658,6 +718,8 @@ describe("ExtensionHost", () => {
658718 const taskPromise = host . runTask ( "delegate this" ) . then ( ( ) => {
659719 settled = true
660720 } )
721+ // Wait for newTask message to be emitted
722+ await new Promise ( ( resolve ) => setImmediate ( resolve ) )
661723 const rootId = ( messages . find ( ( message ) => message . type === "newTask" ) as { taskId : string } ) . taskId
662724
663725 api . emit ( RooCodeEventName . TaskModeSwitched , rootId , "architect" )
0 commit comments