Skip to content

Commit c961c82

Browse files
committed
fix: run tests in a queue if "start test" is clicked multiple times
Fixes #589
1 parent fc07854 commit c961c82

File tree

1 file changed

+42
-24
lines changed

1 file changed

+42
-24
lines changed

src/runner/runner.ts

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)