Created
August 1, 2025 14:39
-
-
Save keegancsmith/9a3422ea1dc7c490ad8b4bf303a00b0b to your computer and use it in GitHub Desktop.
Vitest Reporter which dumps what test was running on SIGTERM (useful for bazel)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import type { TestCase, TestSuite, Vitest } from 'vitest/node' | |
| import type { Reporter } from 'vitest/reporters' | |
| /** | |
| * Catches SIGTERM from Bazel so we can report what tests are currently | |
| * running. Vitest currently does not support reporting this information nor | |
| * configuring a global timeout. | |
| */ | |
| class TimeoutReporter implements Reporter { | |
| private runningTests = new Set<{ id: string; name: string; file: string; startTime: number }>() | |
| private runningSuites = new Set<{ name: string; startTime: number }>() | |
| public onInit(_: Vitest): void { | |
| this.runningTests.clear() | |
| this.runningSuites.clear() | |
| // Vitest registers a SIGTERM listener in logger.ts which calls | |
| // process.exit(). So we need to make sure we run before it. | |
| process.prependOnceListener('SIGTERM', () => { | |
| const now = Date.now() | |
| process.stderr.write('\n\nSIGTERM received!\n') | |
| for (const test of this.runningTests) { | |
| const duration = now - test.startTime | |
| process.stderr.write(`Currently running test ${test.name} (${test.file}) - running for ${duration}ms\n`) | |
| } | |
| for (const suite of this.runningSuites) { | |
| const duration = now - suite.startTime | |
| process.stderr.write(`Currently running suite ${suite.name} - running for ${duration}ms\n`) | |
| } | |
| process.stderr.write('Vitest was terminated by Bazel due to timeout\n') | |
| }) | |
| } | |
| public onTestCaseReady(testCase: TestCase): void { | |
| this.runningTests.add({ | |
| id: testCase.id, | |
| name: testCase.fullName, | |
| file: testCase.module.moduleId, | |
| startTime: Date.now(), | |
| }) | |
| } | |
| public onTestCaseResult(testCase: TestCase): void { | |
| for (const test of this.runningTests) { | |
| if (test.id === testCase.id) { | |
| this.runningTests.delete(test) | |
| break | |
| } | |
| } | |
| } | |
| public onTestSuiteReady(testSuite: TestSuite): void { | |
| this.runningSuites.add({ name: testSuite.fullName, startTime: Date.now() }) | |
| } | |
| public onTestSuiteResult(testSuite: TestSuite): void { | |
| for (const suite of this.runningSuites) { | |
| if (suite.name === testSuite.fullName) { | |
| this.runningSuites.delete(suite) | |
| break | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment