@@ -126,9 +126,12 @@ describe("migrateTaskHistoryWithContextProxy", () => {
126126 // Act
127127 await migrateTaskHistoryWithContextProxy ( mockContext , mockContextProxy , mockWorkspaceFolder )
128128
129- // Assert
129+ // Assert - migration flag should be set even with undefined task history
130130 expect ( mockContextProxy . updateWorkspaceState ) . not . toHaveBeenCalled ( )
131- expect ( mockContext . globalState . update ) . not . toHaveBeenCalled ( )
131+ expect ( mockContext . globalState . update ) . toHaveBeenCalledWith (
132+ "taskHistoryMigratedToWorkspace_/test/workspace" ,
133+ true ,
134+ )
132135 } )
133136
134137 it ( "should handle undefined task history in global state" , async ( ) => {
@@ -147,9 +150,12 @@ describe("migrateTaskHistoryWithContextProxy", () => {
147150 // Act
148151 await migrateTaskHistoryWithContextProxy ( mockContext , mockContextProxy , mockWorkspaceFolder )
149152
150- // Assert
153+ // Assert - migration flag should be set even with empty task history
151154 expect ( mockContextProxy . updateWorkspaceState ) . not . toHaveBeenCalled ( )
152- expect ( mockContext . globalState . update ) . not . toHaveBeenCalled ( )
155+ expect ( mockContext . globalState . update ) . toHaveBeenCalledWith (
156+ "taskHistoryMigratedToWorkspace_/test/workspace" ,
157+ true ,
158+ )
153159 } )
154160
155161 it ( "should merge with existing workspace task history" , async ( ) => {
@@ -205,7 +211,7 @@ describe("migrateTaskHistoryWithContextProxy", () => {
205211 expect ( mockContext . globalState . update ) . toHaveBeenCalledWith ( "globalSettings" , { } )
206212 } )
207213
208- it ( "should handle tasks without workspacePath" , async ( ) => {
214+ it ( "should migrate tasks without workspacePath to current workspace " , async ( ) => {
209215 // Arrange
210216 const taskWithoutPath : HistoryItem = {
211217 id : "task1" ,
@@ -224,7 +230,7 @@ describe("migrateTaskHistoryWithContextProxy", () => {
224230 if ( key === "globalSettings" ) {
225231 return { taskHistory : [ taskWithoutPath ] }
226232 }
227- if ( key === "taskHistoryMigratedToWorkspace" ) {
233+ if ( key . startsWith ( "taskHistoryMigratedToWorkspace" ) ) {
228234 return false
229235 }
230236 return undefined
@@ -235,12 +241,10 @@ describe("migrateTaskHistoryWithContextProxy", () => {
235241 await migrateTaskHistoryWithContextProxy ( mockContext , mockContextProxy , mockWorkspaceFolder )
236242
237243 // Assert
238- // Should not migrate tasks without workspace path
239- expect ( mockContextProxy . updateWorkspaceState ) . not . toHaveBeenCalled ( )
240- // Should keep the task in global state
241- expect ( mockContext . globalState . update ) . toHaveBeenCalledWith ( "globalSettings" , {
242- taskHistory : [ taskWithoutPath ] ,
243- } )
244+ // Should migrate tasks without workspace path to current workspace
245+ expect ( mockContextProxy . updateWorkspaceState ) . toHaveBeenCalledWith ( "taskHistory" , [ taskWithoutPath ] )
246+ // Should remove the task from global state
247+ expect ( mockContext . globalState . update ) . toHaveBeenCalledWith ( "globalSettings" , { } )
244248 } )
245249
246250 it ( "should handle no workspace folder" , async ( ) => {
@@ -264,7 +268,7 @@ describe("migrateTaskHistoryWithContextProxy", () => {
264268 ] ,
265269 }
266270 }
267- if ( key === "taskHistoryMigratedToWorkspace" ) {
271+ if ( key . startsWith ( "taskHistoryMigratedToWorkspace" ) ) {
268272 return false
269273 }
270274 return undefined
@@ -297,10 +301,10 @@ describe("migrateTaskHistoryWithContextProxy", () => {
297301 consoleSpy . mockRestore ( )
298302 } )
299303
300- it ( "should skip migration if already migrated" , async ( ) => {
304+ it ( "should skip migration if already migrated for workspace " , async ( ) => {
301305 // Arrange
302306 vi . mocked ( mockContext . globalState . get ) . mockImplementation ( ( key : string ) => {
303- if ( key === "taskHistoryMigratedToWorkspace" ) {
307+ if ( key === `taskHistoryMigratedToWorkspace_ ${ mockWorkspaceFolder . uri . fsPath } ` ) {
304308 return true // Already migrated
305309 }
306310 if ( key === "globalSettings" ) {
@@ -354,7 +358,7 @@ describe("migrateTaskHistoryWithContextProxy", () => {
354358 if ( key === "globalSettings" ) {
355359 return { taskHistory : mockTaskHistory }
356360 }
357- if ( key === "taskHistoryMigratedToWorkspace" ) {
361+ if ( key . startsWith ( "taskHistoryMigratedToWorkspace" ) ) {
358362 return false
359363 }
360364 return undefined
@@ -365,7 +369,78 @@ describe("migrateTaskHistoryWithContextProxy", () => {
365369 await migrateTaskHistoryWithContextProxy ( mockContext , mockContextProxy , mockWorkspaceFolder )
366370
367371 // Assert
368- // Should set the migration flag
369- expect ( mockContext . globalState . update ) . toHaveBeenCalledWith ( "taskHistoryMigratedToWorkspace" , true )
372+ // Should set the migration flag for the workspace
373+ expect ( mockContext . globalState . update ) . toHaveBeenCalledWith (
374+ `taskHistoryMigratedToWorkspace_${ mockWorkspaceFolder . uri . fsPath } ` ,
375+ true ,
376+ )
377+ } )
378+
379+ it ( "should handle workspace state update errors gracefully" , async ( ) => {
380+ // Arrange
381+ const mockTaskHistory : HistoryItem [ ] = [
382+ {
383+ id : "task1" ,
384+ number : 1 ,
385+ ts : Date . now ( ) ,
386+ task : "Test task" ,
387+ tokensIn : 100 ,
388+ tokensOut : 50 ,
389+ cacheWrites : 0 ,
390+ cacheReads : 0 ,
391+ totalCost : 0.01 ,
392+ workspace : "/test/workspace" ,
393+ } ,
394+ ]
395+
396+ vi . mocked ( mockContext . globalState . get ) . mockImplementation ( ( key : string ) => {
397+ if ( key === "globalSettings" ) {
398+ return { taskHistory : mockTaskHistory }
399+ }
400+ if ( key . startsWith ( "taskHistoryMigratedToWorkspace" ) ) {
401+ return false
402+ }
403+ return undefined
404+ } )
405+ vi . mocked ( mockContextProxy . getWorkspaceSettings ) . mockReturnValue ( { } )
406+
407+ // Mock workspace state update to throw error
408+ vi . mocked ( mockContextProxy . updateWorkspaceState ) . mockRejectedValue ( new Error ( "Workspace state update failed" ) )
409+
410+ // Act
411+ await migrateTaskHistoryWithContextProxy ( mockContext , mockContextProxy , mockWorkspaceFolder )
412+
413+ // Assert
414+ // Should still update global state even if workspace update fails
415+ expect ( mockContext . globalState . update ) . toHaveBeenCalledWith ( "globalSettings" , { } )
416+ // Should set migration flag
417+ expect ( mockContext . globalState . update ) . toHaveBeenCalledWith (
418+ `taskHistoryMigratedToWorkspace_${ mockWorkspaceFolder . uri . fsPath } ` ,
419+ true ,
420+ )
421+ } )
422+
423+ it ( "should set migration flag even when no tasks to migrate" , async ( ) => {
424+ // Arrange
425+ vi . mocked ( mockContext . globalState . get ) . mockImplementation ( ( key : string ) => {
426+ if ( key === "globalSettings" ) {
427+ return { taskHistory : [ ] }
428+ }
429+ if ( key . startsWith ( "taskHistoryMigratedToWorkspace" ) ) {
430+ return false
431+ }
432+ return undefined
433+ } )
434+
435+ // Act
436+ await migrateTaskHistoryWithContextProxy ( mockContext , mockContextProxy , mockWorkspaceFolder )
437+
438+ // Assert
439+ // Should set migration flag even with empty task history
440+ expect ( mockContext . globalState . update ) . toHaveBeenCalledWith (
441+ `taskHistoryMigratedToWorkspace_${ mockWorkspaceFolder . uri . fsPath } ` ,
442+ true ,
443+ )
444+ expect ( mockContextProxy . updateWorkspaceState ) . not . toHaveBeenCalled ( )
370445 } )
371446} )
0 commit comments