Skip to content

Commit

Permalink
fix: don't hang when reloading during a test run (#496)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va authored Oct 9, 2024
1 parent 741a03a commit 1f9f06d
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 24 deletions.
2 changes: 2 additions & 0 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ export class VitestFolderAPI {
}

async cancelRun() {
if (this.process.closed)
return
await this.meta.rpc.cancelRun()
}

Expand Down
7 changes: 7 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class VitestExtension {
private tagsManager: TagsManager
private api: VitestAPI | undefined

private runners: TestRunner[] = []

private disposables: vscode.Disposable[] = []

constructor() {
Expand Down Expand Up @@ -64,6 +66,8 @@ class VitestExtension {

private async _defineTestProfiles(showWarning: boolean, cancelToken?: vscode.CancellationToken) {
this.testTree.reset([])
this.runners.forEach(runner => runner.dispose())
this.runners = []

const vitest = await resolveVitestPackages(showWarning)

Expand Down Expand Up @@ -167,6 +171,7 @@ class VitestExtension {
this.testTree,
api,
)
this.runners.push(runner)

const prefix = api.prefix
let runProfile = previousRunProfiles.get(`${api.id}:run`)
Expand Down Expand Up @@ -368,5 +373,7 @@ class VitestExtension {
this.runProfiles.clear()
this.disposables.forEach(d => d.dispose())
this.disposables = []
this.runners.forEach(runner => runner.dispose())
this.runners = []
}
}
65 changes: 41 additions & 24 deletions src/runner/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export class TestRunner extends vscode.Disposable {
private testRun: vscode.TestRun | undefined
private testRunDefer: PromiseWithResolvers<void> | undefined

private disposables: vscode.Disposable[] = []

constructor(
private readonly controller: vscode.TestController,
private readonly tree: TestTree,
Expand All @@ -33,10 +35,10 @@ export class TestRunner extends vscode.Disposable {
this.endTestRun()
this.nonContinuousRequest = undefined
this.continuousRequests.clear()
if (!this.api.process.closed) {
this.api.cancelRun()
}
this.api.cancelRun()
this._onRequestsExhausted.dispose()
this.disposables.forEach(d => d.dispose())
this.disposables = []
})

api.onWatcherRerun((files, _trigger, collecting) => {
Expand Down Expand Up @@ -155,17 +157,19 @@ export class TestRunner extends vscode.Disposable {
private async watchContinuousTests(request: vscode.TestRunRequest, token: vscode.CancellationToken) {
this.continuousRequests.add(request)

token.onCancellationRequested(() => {
log.verbose?.('Continuous test run for', join(request.include), 'was cancelled')
this.disposables.push(
token.onCancellationRequested(() => {
log.verbose?.('Continuous test run for', join(request.include), 'was cancelled')

this.continuousRequests.delete(request)
if (!this.continuousRequests.size) {
log.verbose?.('Stopped watching test files')
this._onRequestsExhausted.fire()
this.api.unwatchTests()
this.endTestRun()
}
})
this.continuousRequests.delete(request)
if (!this.continuousRequests.size) {
log.verbose?.('Stopped watching test files')
this._onRequestsExhausted.fire()
this.api.unwatchTests()
this.endTestRun()
}
}),
)

if (!request.include?.length) {
log.info('[RUNNER]', 'Watching all test files')
Expand Down Expand Up @@ -202,10 +206,12 @@ export class TestRunner extends vscode.Disposable {
}
})

token.onCancellationRequested(() => {
log.verbose?.('Coverage for', join(request.include), 'was manually stopped')
this.api.disableCoverage()
})
this.disposables.push(
token.onCancellationRequested(() => {
log.verbose?.('Coverage for', join(request.include), 'was manually stopped')
this.api.disableCoverage()
}),
)

await this.runTests(request, token)
}
Expand All @@ -218,14 +224,25 @@ export class TestRunner extends vscode.Disposable {

this.nonContinuousRequest = request

token.onCancellationRequested(() => {
this.endTestRun()
this.nonContinuousRequest = undefined
this.api.cancelRun()
log.verbose?.('Test run was cancelled manually for', join(request.include))
})
this.disposables.push(
token.onCancellationRequested(() => {
this.endTestRun()
this.nonContinuousRequest = undefined
this.api.cancelRun()
log.verbose?.('Test run was cancelled manually for', join(request.include))
}),
)

await this.runTestItems(request)
try {
await this.runTestItems(request)
}
catch (err: any) {
// the rpc can be closed during the test run by clicking on reload
if (!err.message.startsWith('[birpc] rpc is closed')) {
log.error('Failed to run tests', err)
}
this.endTestRun()
}

this.nonContinuousRequest = undefined
this._onRequestsExhausted.fire()
Expand Down

0 comments on commit 1f9f06d

Please sign in to comment.