@@ -54,7 +54,7 @@ export class TestRunner extends vscode.Disposable {
5454 log . verbose ?.( 'Not starting the runner because tests are being collected for' , ...files . map ( f => this . relative ( f ) ) )
5555 }
5656 else {
57- log . verbose ?.( 'Starting a test run because' , ...files . map ( f => this . relative ( f ) ) , 'were started due to a file change ' )
57+ log . verbose ?.( 'Starting a test run because' , ...files . map ( f => this . relative ( f ) ) , 'triggered a watch rerun event ' )
5858 this . startTestRun ( files )
5959 }
6060 } )
@@ -248,19 +248,8 @@ export class TestRunner extends vscode.Disposable {
248248 if ( request . continuous )
249249 return await this . watchContinuousTests ( request , token )
250250
251- this . nonContinuousRequest = request
252-
253- this . disposables . push (
254- token . onCancellationRequested ( ( ) => {
255- this . endTestRun ( )
256- this . nonContinuousRequest = undefined
257- this . api . cancelRun ( )
258- log . verbose ?.( 'Test run was cancelled manually for' , join ( request . include ) )
259- } ) ,
260- )
261-
262251 try {
263- await this . runTestItems ( request )
252+ await this . scheduleTestItems ( request , token )
264253 }
265254 catch ( err : any ) {
266255 // the rpc can be closed during the test run by clicking on reload
@@ -269,19 +258,23 @@ export class TestRunner extends vscode.Disposable {
269258 }
270259 this . endTestRun ( )
271260 }
272-
273- this . nonContinuousRequest = undefined
274- this . _onRequestsExhausted . fire ( )
275261 }
276262
277- protected async runTestItems ( request : vscode . TestRunRequest ) {
278- if ( this . testRunDefer ) {
279- log . verbose ?.( 'Waiting for the previous test run to finish' )
280- await this . testRunDefer . promise
281- }
263+ protected scheduleTestRunsQueue : ( ( ) => Promise < void > ) [ ] = [ ]
282264
283- log . verbose ?.( 'Initiating deferred test run' )
284- this . testRunDefer = Promise . withResolvers ( )
265+ private async runTestItems ( request : vscode . TestRunRequest , token : vscode . CancellationToken ) {
266+ this . nonContinuousRequest = request
267+
268+ this . disposables . push (
269+ token . onCancellationRequested ( ( ) => {
270+ this . endTestRun ( )
271+ if ( request === this . nonContinuousRequest ) {
272+ this . nonContinuousRequest = undefined
273+ }
274+ this . api . cancelRun ( )
275+ log . verbose ?.( 'Test run was cancelled manually for' , join ( request . include ) )
276+ } ) ,
277+ )
285278
286279 const runTests = ( files ?: SerializedTestSpecification [ ] | string [ ] , testNamePatern ?: string ) =>
287280 'updateSnapshots' in request
@@ -303,6 +296,26 @@ export class TestRunner extends vscode.Disposable {
303296 log . info ( `Running ${ files . length } file(s):` , files . map ( f => this . relative ( f ) ) )
304297 await runTests ( files , testNamePatern )
305298 }
299+
300+ if ( request === this . nonContinuousRequest ) {
301+ this . nonContinuousRequest = undefined
302+ this . _onRequestsExhausted . fire ( )
303+ }
304+ }
305+
306+ protected async scheduleTestItems ( request : vscode . TestRunRequest , token : vscode . CancellationToken ) {
307+ if ( ! this . testRunDefer ) {
308+ await this . runTestItems ( request , token )
309+ }
310+ else {
311+ log . verbose ?.( 'Queueing a new test run to execute when the current one is finished.' )
312+ return new Promise ( ( resolve , reject ) => {
313+ this . scheduleTestRunsQueue . push ( ( ) => {
314+ log . verbose ?.( 'Scheduled test run is starting now.' )
315+ return this . runTestItems ( request , token ) . then ( resolve , reject )
316+ } )
317+ } )
318+ }
306319 }
307320
308321 private isTestIncluded ( test : vscode . TestItem , include : readonly vscode . TestItem [ ] | vscode . TestItemCollection ) {
@@ -373,7 +386,6 @@ export class TestRunner extends vscode.Disposable {
373386 if ( this . testRun ) {
374387 log . verbose ?.( 'Waiting for the previous test run to finish' )
375388 await this . testRunDefer ?. promise
376- this . endTestRun ( )
377389 }
378390
379391 const name = files . length > 1
@@ -382,6 +394,12 @@ export class TestRunner extends vscode.Disposable {
382394
383395 const run = this . testRun = this . controller . createTestRun ( request , name )
384396 this . testRunRequest = request
397+ this . testRunDefer = Promise . withResolvers ( )
398+ this . testRunDefer . promise = this . testRunDefer . promise . finally ( ( ) => {
399+ run . end ( )
400+ log . verbose ?.( `Test run promise is finished, the queue is ${ this . scheduleTestRunsQueue . length } ` )
401+ this . scheduleTestRunsQueue . shift ( ) ?.( )
402+ } )
385403
386404 for ( const file of files ) {
387405 if ( file [ file . length - 1 ] === '/' ) {
0 commit comments