@@ -936,6 +936,9 @@ describe("DiffViewProvider", () => {
936936 // Only the interactivity flag differs: the channel and the text are unchanged.
937937 expect ( mockTask . say . mock . calls [ 0 ] ?. [ 0 ] ) . toBe ( "error" )
938938 expect ( mockTask . say . mock . calls [ 0 ] ?. [ 1 ] ) . toContain ( "New problems detected after saving file: test.ts" )
939+ // The tail releases its controller when it completes - including the failing tail
940+ // below: without the finally cleanup, completed tails accumulate until disposal.
941+ expect ( diffViewProvider [ "postSaveTails" ] . size ) . toBe ( 0 )
939942 } )
940943
941944 it ( "does not start a tail when cancellation lands while the save is awaiting the write" , async ( ) => {
@@ -1078,7 +1081,43 @@ describe("DiffViewProvider", () => {
10781081
10791082 expect ( mockTask . say ) . toHaveBeenCalledTimes ( 1 )
10801083 expect ( mockTask . say . mock . calls [ 0 ] ?. [ 1 ] ) . toContain ( "own-problem" )
1081- expect ( mockTask . say . mock . calls [ 0 ] ?. [ 1 ] ) . not . toContain ( "other-file-problem" )
1084+ } )
1085+
1086+ it ( "narrows the tail payload to Error-severity diagnostics" , async ( ) => {
1087+ // The tail formats with an explicit Error-only severity list. Mixed fixtures
1088+ // are what make a widened severity list fail this test instead of passing silently.
1089+ const ownWarning : vscode . Diagnostic = {
1090+ severity : vscode . DiagnosticSeverity . Warning ,
1091+ range : new vscode . Range ( 0 , 0 , 0 , 1 ) ,
1092+ message : "own-warning" ,
1093+ }
1094+ const ownError : vscode . Diagnostic = {
1095+ severity : vscode . DiagnosticSeverity . Error ,
1096+ range : new vscode . Range ( 0 , 0 , 0 , 1 ) ,
1097+ message : "own-error" ,
1098+ }
1099+ const mixedDiagnostics : [ vscode . Uri , vscode . Diagnostic [ ] ] [ ] = [
1100+ [ makeUri ( `${ mockCwd } /test.ts` ) , [ ownWarning , ownError ] ] ,
1101+ ]
1102+ vi . mocked ( vscode . languages . getDiagnostics ) . mockReturnValueOnce ( [ ] ) . mockReturnValue ( mixedDiagnostics )
1103+
1104+ await diffViewProvider . saveDirectly ( "test.ts" , "new content" , true , true , 100 )
1105+ await new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) )
1106+
1107+ expect ( mockTask . say ) . toHaveBeenCalledTimes ( 1 )
1108+ expect ( mockTask . say . mock . calls [ 0 ] ?. [ 1 ] ) . toContain ( "own-error" )
1109+ expect ( mockTask . say . mock . calls [ 0 ] ?. [ 1 ] ) . not . toContain ( "own-warning" )
1110+ expect ( diffViewProvider [ "postSaveTails" ] . size ) . toBe ( 0 )
1111+
1112+ // Warning-only diagnostics must not emit at all.
1113+ mockTask . say . mockClear ( )
1114+ const warningOnly : [ vscode . Uri , vscode . Diagnostic [ ] ] [ ] = [ [ makeUri ( `${ mockCwd } /test.ts` ) , [ ownWarning ] ] ]
1115+ vi . mocked ( vscode . languages . getDiagnostics ) . mockReturnValueOnce ( [ ] ) . mockReturnValue ( warningOnly )
1116+
1117+ await diffViewProvider . saveDirectly ( "test.ts" , "more content" , true , true , 100 )
1118+ await new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) )
1119+
1120+ expect ( mockTask . say ) . not . toHaveBeenCalled ( )
10821121 } )
10831122
10841123 it ( "stops a post-save tail that is cancelled while the diagnostic settings are read" , async ( ) => {
@@ -1146,14 +1185,19 @@ describe("DiffViewProvider", () => {
11461185 const postDiagnostics : [ vscode . Uri , vscode . Diagnostic [ ] ] [ ] = [ [ makeUri ( `${ mockCwd } /Test.ts` ) , [ newDiag ] ] ]
11471186 vi . mocked ( vscode . languages . getDiagnostics ) . mockReturnValueOnce ( [ ] ) . mockReturnValue ( postDiagnostics )
11481187
1149- await diffViewProvider . saveDirectly ( "test.ts" , "new content" , true , true , 100 )
1188+ try {
1189+ await diffViewProvider . saveDirectly ( "test.ts" , "new content" , true , true , 100 )
11501190
1151- // Flush the fire-and-forget tail.
1152- await new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) )
1191+ // Flush the fire-and-forget tail.
1192+ await new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) )
11531193
1154- expect ( mockTask . say ) . toHaveBeenCalledTimes ( 1 )
1155- expect ( mockTask . say . mock . calls [ 0 ] ?. [ 1 ] ) . toContain ( "case-mismatch-problem" )
1156- platformSpy . mockRestore ( )
1194+ expect ( mockTask . say ) . toHaveBeenCalledTimes ( 1 )
1195+ expect ( mockTask . say . mock . calls [ 0 ] ?. [ 1 ] ) . toContain ( "case-mismatch-problem" )
1196+ } finally {
1197+ // Restore on assertion failure too: a leaked win32 override would apply Windows
1198+ // path rules to later tests' comparisons.
1199+ platformSpy . mockRestore ( )
1200+ }
11571201 } )
11581202
11591203 it ( "does not block the save on a diagnostics settle delay when diagnostics are disabled" , async ( ) => {
@@ -1214,14 +1258,21 @@ describe("DiffViewProvider", () => {
12141258 // The task is aborted while the diagnostics tail is emitting: say() rejects.
12151259 mockTask . say . mockRejectedValueOnce ( new Error ( "aborted" ) )
12161260
1217- await diffViewProvider . saveDirectly ( "test.ts" , "new content" , true , true , 0 )
1218- // Flush the fire-and-forget tail.
1219- await new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) )
1220-
1221- // The method's outer catch swallows the rejection with a warning.
1222- expect ( consoleWarnSpy ) . toHaveBeenCalledWith ( expect . stringContaining ( "Post-save diagnostics emit failed:" ) )
1261+ try {
1262+ await diffViewProvider . saveDirectly ( "test.ts" , "new content" , true , true , 0 )
1263+ // Flush the fire-and-forget tail.
1264+ await new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) )
12231265
1224- consoleWarnSpy . mockRestore ( )
1266+ // The method's outer catch swallows the rejection with a warning.
1267+ expect ( consoleWarnSpy ) . toHaveBeenCalledWith (
1268+ expect . stringContaining ( "Post-save diagnostics emit failed:" ) ,
1269+ )
1270+ // Even the failing tail releases its controller.
1271+ expect ( diffViewProvider [ "postSaveTails" ] . size ) . toBe ( 0 )
1272+ } finally {
1273+ // Restore on assertion failure too: a leaked spy would swallow later tests' warnings.
1274+ consoleWarnSpy . mockRestore ( )
1275+ }
12251276 } )
12261277 } )
12271278
0 commit comments