@@ -367,4 +367,140 @@ describe("CodeIndexManager - handleSettingsChange regression", () => {
367367 expect ( mockServiceFactoryInstance . validateEmbedder ) . not . toHaveBeenCalled ( )
368368 } )
369369 } )
370+
371+ describe ( "recoverFromError" , ( ) => {
372+ let mockConfigManager : any
373+ let mockCacheManager : any
374+ let mockStateManager : any
375+
376+ beforeEach ( ( ) => {
377+ // Mock config manager
378+ mockConfigManager = {
379+ loadConfiguration : vi . fn ( ) . mockResolvedValue ( { requiresRestart : false } ) ,
380+ isFeatureConfigured : true ,
381+ isFeatureEnabled : true ,
382+ getConfig : vi . fn ( ) . mockReturnValue ( {
383+ isConfigured : true ,
384+ embedderProvider : "openai" ,
385+ modelId : "text-embedding-3-small" ,
386+ openAiOptions : { openAiNativeApiKey : "test-key" } ,
387+ qdrantUrl : "http://localhost:6333" ,
388+ qdrantApiKey : "test-key" ,
389+ searchMinScore : 0.4 ,
390+ } ) ,
391+ }
392+ ; ( manager as any ) . _configManager = mockConfigManager
393+
394+ // Mock cache manager
395+ mockCacheManager = {
396+ initialize : vi . fn ( ) ,
397+ clearCacheFile : vi . fn ( ) ,
398+ }
399+ ; ( manager as any ) . _cacheManager = mockCacheManager
400+
401+ // Mock state manager
402+ mockStateManager = ( manager as any ) . _stateManager
403+ mockStateManager . setSystemState = vi . fn ( )
404+ mockStateManager . getCurrentStatus = vi . fn ( ) . mockReturnValue ( {
405+ systemStatus : "Error" ,
406+ message : "Failed during initial scan: fetch failed" ,
407+ processedItems : 0 ,
408+ totalItems : 0 ,
409+ currentItemUnit : "items" ,
410+ } )
411+
412+ // Mock orchestrator and search service to simulate initialized state
413+ ; ( manager as any ) . _orchestrator = { stopWatcher : vi . fn ( ) , state : "Error" }
414+ ; ( manager as any ) . _searchService = { }
415+ ; ( manager as any ) . _serviceFactory = { }
416+ } )
417+
418+ it ( "should clear error state when recoverFromError is called" , async ( ) => {
419+ // Act
420+ await manager . recoverFromError ( )
421+
422+ // Assert
423+ expect ( mockStateManager . setSystemState ) . toHaveBeenCalledWith ( "Standby" , "" )
424+ } )
425+
426+ it ( "should reset internal service instances" , async ( ) => {
427+ // Verify initial state
428+ expect ( ( manager as any ) . _configManager ) . toBeDefined ( )
429+ expect ( ( manager as any ) . _serviceFactory ) . toBeDefined ( )
430+ expect ( ( manager as any ) . _orchestrator ) . toBeDefined ( )
431+ expect ( ( manager as any ) . _searchService ) . toBeDefined ( )
432+
433+ // Act
434+ await manager . recoverFromError ( )
435+
436+ // Assert - all service instances should be undefined
437+ expect ( ( manager as any ) . _configManager ) . toBeUndefined ( )
438+ expect ( ( manager as any ) . _serviceFactory ) . toBeUndefined ( )
439+ expect ( ( manager as any ) . _orchestrator ) . toBeUndefined ( )
440+ expect ( ( manager as any ) . _searchService ) . toBeUndefined ( )
441+ } )
442+
443+ it ( "should make manager report as not initialized after recovery" , async ( ) => {
444+ // Verify initial state
445+ expect ( manager . isInitialized ) . toBe ( true )
446+
447+ // Act
448+ await manager . recoverFromError ( )
449+
450+ // Assert
451+ expect ( manager . isInitialized ) . toBe ( false )
452+ } )
453+
454+ it ( "should allow re-initialization after recovery" , async ( ) => {
455+ // Setup mock for re-initialization
456+ const mockServiceFactoryInstance = {
457+ createServices : vi . fn ( ) . mockReturnValue ( {
458+ embedder : { embedderInfo : { name : "openai" } } ,
459+ vectorStore : { } ,
460+ scanner : { } ,
461+ fileWatcher : {
462+ onDidStartBatchProcessing : vi . fn ( ) ,
463+ onBatchProgressUpdate : vi . fn ( ) ,
464+ watch : vi . fn ( ) ,
465+ stopWatcher : vi . fn ( ) ,
466+ dispose : vi . fn ( ) ,
467+ } ,
468+ } ) ,
469+ validateEmbedder : vi . fn ( ) . mockResolvedValue ( { valid : true } ) ,
470+ }
471+ MockedCodeIndexServiceFactory . mockImplementation ( ( ) => mockServiceFactoryInstance as any )
472+
473+ // Act - recover from error
474+ await manager . recoverFromError ( )
475+
476+ // Verify manager is not initialized
477+ expect ( manager . isInitialized ) . toBe ( false )
478+
479+ // Mock context proxy for initialization
480+ const mockContextProxy = {
481+ getValue : vi . fn ( ) ,
482+ setValue : vi . fn ( ) ,
483+ storeSecret : vi . fn ( ) ,
484+ getSecret : vi . fn ( ) ,
485+ refreshSecrets : vi . fn ( ) . mockResolvedValue ( undefined ) ,
486+ getGlobalState : vi . fn ( ) . mockReturnValue ( {
487+ codebaseIndexEnabled : true ,
488+ codebaseIndexQdrantUrl : "http://localhost:6333" ,
489+ codebaseIndexEmbedderProvider : "openai" ,
490+ codebaseIndexEmbedderModelId : "text-embedding-3-small" ,
491+ codebaseIndexEmbedderModelDimension : 1536 ,
492+ codebaseIndexSearchMaxResults : 10 ,
493+ codebaseIndexSearchMinScore : 0.4 ,
494+ } ) ,
495+ }
496+
497+ // Re-initialize
498+ await manager . initialize ( mockContextProxy as any )
499+
500+ // Assert - manager should be initialized again
501+ expect ( manager . isInitialized ) . toBe ( true )
502+ expect ( mockServiceFactoryInstance . createServices ) . toHaveBeenCalled ( )
503+ expect ( mockServiceFactoryInstance . validateEmbedder ) . toHaveBeenCalled ( )
504+ } )
505+ } )
370506} )
0 commit comments