Accessing meta in Reporter onTestCaseResult
In a custom reporter, the `onTestCaseResult` method receives a TestCase object. The `meta` property can be accessed by calling `testCase.meta()` which returns the metadata object. Example: `const { custom } = testCase.meta()` accesses a custom property set during test execution.
Accessing meta in Reporter onTestRunEnd
In a custom reporter, the `onTestRunEnd` method receives a TestModule object. Meta properties can be accessed on the module itself via `testModule.meta()` and on child tasks via `testModule.children.at(0).meta()`. Example: `testModule.meta().done === true` and `testModule.children.at(0).meta().custom === 'some-custom-handler'`
onInit reporter method signature
onInit is a reporter method with signature: function onInit(vitest: Vitest): Awaitable<void>. It is called when Vitest was initiated or started, but before the tests were filtered. Internally this method is called inside vitest.start, vitest.standalone, or vitest.mergeReports. If using programmatic API, ensure to call one of those methods before calling vitest.runTestSpecifications.
onBrowserInit reporter method signature
onBrowserInit is a reporter method with signature: function onBrowserInit(project: TestProject): Awaitable<void>. It is called when the browser instance is initiated. It receives an instance of the project for which the browser is initiated. project.browser will always be defined when this method is called.
onTestRunStart reporter method signature
onTestRunStart is a reporter method with signature: function onTestRunStart(specifications: TestSpecification[]): Awaitable<void>. It is called when a new test run has started. It receives a readonly array of test specifications scheduled to run. If Vitest didn't find any test files to run, this event will be invoked with an empty array, and then onTestRunEnd will be called immediately after.
onTestRunEnd reporter method signature and parameters
onTestRunEnd is a reporter method with signature: function onTestRunEnd(testModules: ReadonlyArray<TestModule>, unhandledErrors: ReadonlyArray<SerializedError>, reason: TestRunEndReason): Awaitable<void>. It is called after all tests have finished running and coverage merged all reports if enabled. The second argument is a readonly list of unhandled errors that Vitest wasn't able to attribute to any test. The third argument indicates why the test run finished: 'passed' (normally finished with no errors), 'failed' (at least one error), or 'interrupted' (cancelled by vitest.cancelCurrentRun or Ctrl+C in terminal).
onCoverage reporter method signature
onCoverage is a reporter method with signature: function onCoverage(coverage: unknown): Awaitable<void>. It is called after coverage results have been processed. Coverage provider's reporters are called after this hook. The typings of coverage depends on the coverage.provider. For Vitest's default built-in providers, the type can be imported from istanbul-lib-coverage package: CoverageMap. If Vitest didn't perform any coverage, this hook is not called.
onTestModuleQueued reporter method signature
onTestModuleQueued is a reporter method with signature: function onTestModuleQueued(testModule: TestModule): Awaitable<void>. It is called right before Vitest imports the setup file and the test module itself. The testModule will have no children yet, but you can start reporting it as the next test to run.
onTestModuleCollected reporter method signature
onTestModuleCollected is a reporter method with signature: function onTestModuleCollected(testModule: TestModule): Awaitable<void>. It is called when all tests inside the file were collected, meaning testModule.children collection is populated, but tests don't have any results yet.
onTestModuleStart reporter method signature
onTestModuleStart is a reporter method with signature: function onTestModuleStart(testModule: TestModule): Awaitable<void>. It is called right after onTestModuleCollected unless Vitest runs in collection mode (vitest.collect() or vitest collect in CLI), in which case it will not be called at all because there are no tests to run.
onTestModuleEnd reporter method signature
onTestModuleEnd is a reporter method with signature: function onTestModuleEnd(testModule: TestModule): Awaitable<void>. It is called when every test in the module finished running. This means every test inside testModule.children will have a test.result() that is not equal to pending.
onHookStart reporter method signature
onHookStart is a reporter method with signature: function onHookStart(context: ReportedHookContext): Awaitable<void>. It is called when any of these hooks have started running: beforeAll, afterAll, beforeEach, afterEach. If beforeAll or afterAll are started, the entity will be either TestSuite or TestModule. If beforeEach or afterEach are started, the entity will always be TestCase. Note: onHookStart will not be called if the hook did not run during the test run.
onHookEnd reporter method signature
onHookEnd is a reporter method with signature: function onHookEnd(context: ReportedHookContext): Awaitable<void>. It is called when any of these hooks have finished running: beforeAll, afterAll, beforeEach, afterEach. If beforeAll or afterAll have finished, the entity will be either TestSuite or TestModule. If beforeEach or afterEach have finished, the entity will always be TestCase. Note: onHookEnd will not be called if the hook did not run during the test run.
onTestSuiteReady reporter method signature
onTestSuiteReady is a reporter method with signature: function onTestSuiteReady(testSuite: TestSuite): Awaitable<void>. It is called before the suite starts to run its tests. This method is also called if the suite was skipped. If the file doesn't have any suites, this method will not be called; consider using onTestModuleStart to cover this use case.
onTestSuiteResult reporter method signature
onTestSuiteResult is a reporter method with signature: function onTestSuiteResult(testSuite: TestSuite): Awaitable<void>. It is called after the suite has finished running tests. This method is also called if the suite was skipped. If the file doesn't have any suites, this method will not be called; consider using onTestModuleEnd to cover this use case.
onTestCaseReady reporter method signature
onTestCaseReady is a reporter method with signature: function onTestCaseReady(testCase: TestCase): Awaitable<void>. It is called before the test starts to run or it was skipped. beforeEach and afterEach hooks are considered part of the test because they can influence the result. Note that it's possible to have testCase.result() with passed or failed state already when onTestCaseReady is called, which can happen if test was running too fast and both onTestCaseReady and onTestCaseResult were scheduled to run in the same microtask.
onTestCaseResult reporter method signature
onTestCaseResult is a reporter method with signature: function onTestCaseResult(testCase: TestCase): Awaitable<void>. It is called when the test has finished running or was just skipped. This will be called after the afterEach hook is finished, if there are any. At this point, testCase.result() will have non-pending state.
onTestCaseAnnotate reporter method signature
onTestCaseAnnotate is a reporter method with signature: function onTestCaseAnnotate(testCase: TestCase, annotation: TestAnnotation): Awaitable<void>. Available since version 3.2.0. It is associated with the context.annotate method. When annotate is invoked, Vitest serialises it and sends the same attachment to the main thread where reporter can interact with it. If the path is specified, Vitest stores it in a separate directory configured by attachmentsDir and modifies the path property to reference it.
onTestCaseArtifactRecord reporter method signature
onTestCaseArtifactRecord is a reporter method with signature: function onTestCaseArtifactRecord(testCase: TestCase, artifact: TestArtifact): Awaitable<void>. Experimental, available since version 4.0.11. It is associated with the recordArtifact utility. When recordArtifact is invoked, Vitest serialises it and sends the same attachment to the main thread where reporter can interact with it. If the path is specified, Vitest stores it in a separate directory configured by attachmentsDir and modifies the path property to reference it. Note: annotations won't hit this hook and won't appear in task.artifacts array for backwards compatibility reasons.
Reporter test run lifecycle order
The reporter lifecycle follows this order: onInit, onTestRunStart, then for each test module: onTestModuleQueued, onTestModuleCollected, onTestModuleStart, onTestSuiteReady, onHookStart(beforeAll), onHookEnd(beforeAll), onTestCaseReady, onTestCaseAnnotate, onTestCaseArtifactRecord, onHookStart(beforeEach), onHookEnd(beforeEach), onHookStart(afterEach), onHookEnd(afterEach), onTestCaseResult, onHookStart(afterAll), onHookEnd(afterAll), onTestSuiteResult, onTestModuleEnd, onCoverage, and finally onTestRunEnd. Tests and suites within a single module are reported in order unless skipped. All skipped tests are reported at the end of suite/module. Test modules can run in parallel, so Vitest reports them in parallel.
Example custom reporter extending BaseReporter
import { BaseReporter } from 'vitest/node'
export default class CustomReporter extends BaseReporter {
onTestRunEnd(testModules, errors) {
console.log(testModule.length, 'tests finished running')
super.onTestRunEnd(testModules, errors)
}
}
This example shows how to extend BaseReporter to create a custom reporter that logs the number of tests after they finish running.
Example reporter storing Vitest instance in onInit
import type { Reporter, TestSpecification, Vitest } from 'vitest/node'
class MyReporter implements Reporter {
private vitest!: Vitest
onInit(vitest: Vitest) {
this.vitest = vitest
}
onTestRunStart(specifications: TestSpecification[]) {
console.log(
specifications.length,
'test files will run in',
this.vitest.config.root,
)
}
}
export default new MyReporter()
This example shows how to store a reference to the Vitest instance in onInit to access configuration in subsequent reporter methods.
Example reporter using onTestRunStart
import type { Reporter, TestSpecification } from 'vitest/node'
class MyReporter implements Reporter {
onTestRunStart(specifications: TestSpecification[]) {
console.log(specifications.length, 'test files will run')
}
}
export default new MyReporter()
This example shows a basic reporter that logs the number of test files scheduled to run.
Example reporter using onTestRunEnd with reason handling
import type {
Reporter,
SerializedError,
TestModule,
TestRunEndReason,
TestSpecification
} from 'vitest/node'
class MyReporter implements Reporter {
onTestRunEnd(
testModules: ReadonlyArray<TestModule>,
unhandledErrors: ReadonlyArray<SerializedError>,
reason: TestRunEndReason,
) {
if (reason === 'passed') {
testModules.forEach(module => console.log(module.moduleId, 'succeeded'))
}
else if (reason === 'failed') {
// note that this will skip possible errors in suites
// you can get them from testSuite.errors()
for (const testCase of testModules.children.allTests()) {
if (testCase.result().state === 'failed') {
console.log(testCase.fullName, 'in', testCase.module.moduleId, 'failed')
console.log(testCase.result().errors)
}
}
}
else {
console.log('test run was interrupted, skipping report')
}
}
}
export default new MyReporter()
This example shows how to handle different TestRunEndReason values in onTestRunEnd to report on test results and errors.
agent reporter reduces token usage for AI agents
The agent reporter is a minimal output mode designed to reduce token usage for AI coding agents. It only displays failed tests and their errors, suppressing passed test output and console logs from passing tests. Vitest automatically enables this reporter when it detects running inside an AI coding agent using std-env detection. Can be manually enabled by setting AI_AGENT environment variable (e.g., AI_AGENT=copilot).
github-actions reporter now generates Job Summary
The built-in github-actions reporter now automatically generates a GitHub Actions Job Summary with an overview of test results. The summary includes test file and test case statistics, highlights flaky tests requiring retries with permalink URLs linking test names directly to source lines on GitHub. Enabled by default when running in GitHub Actions. Can be disabled or customized with reporters configuration: ['github-actions', { jobSummary: { enabled: false } }].