-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat: introduce the new reporter API #7069
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
sheremet-va
merged 89 commits into
vitest-dev:main
from
sheremet-va:feat/new-reporter-api
Jan 14, 2025
Merged
Changes from 74 commits
Commits
Show all changes
89 commits
Select commit
Hold shift + click to select a range
38b967c
feat: introduce the new reporter API
sheremet-va 25bae18
chore: cleanup
sheremet-va 0998e4f
feat: introduce the new reporter API
sheremet-va 6f0da08
chore: cleanup
sheremet-va 64abbda
feat(reporters): add first 5/7 test run life cycles
AriPerkkio f3686b0
test: add initial test setup
AriPerkkio 9cd58e9
fix: report skipped tests, prevent duplicate queued
AriPerkkio 3f6edd5
fix: review
AriPerkkio 1b8264a
Merge branch 'feat/new-reporter-api' of github.com:sheremet-va/vitest…
sheremet-va 506cec5
refactor: don't allow undefined in getReportedEntity
sheremet-va 2624054
refactor: move collecton/enqueued to the test runner
sheremet-va ef9a086
refactor: remove test.skipped()
sheremet-va 10f3890
fix: correct skipped state
sheremet-va ebf3454
docs: cleanup
sheremet-va 5d2bd70
docs: remove skipped from suite methods
sheremet-va cd291db
feat: add onTestModuleCollected
sheremet-va 0ef6608
refactor: add events to TaskResultPack
sheremet-va d515785
docs: update result() docs
sheremet-va 87d313b
docs: add state() docs
sheremet-va 934087b
docs: fix result description
sheremet-va 6567412
docs: update metadata docs
sheremet-va 5e3b7cb
refactor: add event
sheremet-va 20696a5
chore: fix ts error
sheremet-va ed1332e
fix: set event in typechecking
sheremet-va 89baf8e
refactor: move log to test run
sheremet-va 4afce13
refactor: move onFinished
sheremet-va 4557b4b
fix: report skipped tests of suites
AriPerkkio 3e0990e
Merge remote-tracking branch 'upstream/main' into feat/new-reporter-api
AriPerkkio 1a74b1b
feat(reporter): `'dot'` to use new reporter API
AriPerkkio 84ddc2f
refactor: mark readonly properties
sheremet-va 1f03389
refactor: rename spec.module to spec.testModule
sheremet-va 19fd301
docs: update options type, remove "reporter api" warning
sheremet-va be5b429
feat(reporter): summary to use new reporter API, except before & afte…
AriPerkkio 02c0279
refactor: add comments and clarifications
sheremet-va 1c8fb37
chore: cleanup
sheremet-va f6c3571
refactor: remove `TaskParser`, use new reporter API completely
AriPerkkio eb36354
refactor: rename new APIs
AriPerkkio 0cef2b5
fix: resolve reporter life cycle from `onTaskUpdate` event field
AriPerkkio b5b962f
fix: report hooks only when they actually exist
AriPerkkio dd6ebc5
chore: add some test run docs and make arrays readonly
sheremet-va 44ad507
docs: fix link
sheremet-va 23730ae
Merge branch 'main' of github.com:vitest-dev/vitest into feat/new-rep…
sheremet-va c62f22b
refactor: add more docs, export TestRunEndReason and SerializedError
sheremet-va 409c401
fix: attempt to get order right
AriPerkkio 41985f3
fix: correct order for `TestCase`
AriPerkkio 208466b
docs: document more hooks
sheremet-va 2852271
refactor: rename hooks option
sheremet-va f8b657a
refactor: return diagnostic if test was retried
sheremet-va 44f588d
fix: single `beforeEach/afterEach` working
AriPerkkio d98e4eb
fix: multiple `beforeEach/afterEach` working
AriPerkkio d9d652a
refactor: rename test-case's Start/End -> Ready/Result
sheremet-va 97e51bd
test: refactor and add more tests
AriPerkkio c812be8
fix: report `beforeAll/afterAll` of `TestModule`
AriPerkkio a1b2051
refactor: don't parse events, keep the order in the runner (#3)
sheremet-va afe9935
chore: cleanup
sheremet-va 8d1abdd
docs: add onTestSuiteReady/onTestSuiteResult
sheremet-va 6a48858
chore: cleanup
sheremet-va 3b087fe
Merge branch 'main' of github.com:vitest-dev/vitest into feat/new-rep…
sheremet-va 8592c09
test: enable tests for suites
sheremet-va e56ffad
fix: don't report ctx.skip tests twice
sheremet-va 328594d
chore: events
sheremet-va 5c44c17
test: fix test
sheremet-va 06669e7
docs: cleanup
sheremet-va 330deee
fix: remove coverage from merge-reports
sheremet-va cb0110a
chore: always report onCoverage
sheremet-va db86137
fix: remove error with sharding
sheremet-va 0fd1b76
test: fix snapshot
sheremet-va 503cae0
refactor: cleanup
sheremet-va 9947672
test: add tests with delay to not check sync updates only
AriPerkkio 101a542
Merge remote-tracking branch 'upstream/main' into feat/new-reporter-api
AriPerkkio 7dc23e6
fix: dot reporter to check suite tests too
AriPerkkio 7a4dbff
chore: review fixes
AriPerkkio bcb6e71
docs: broken link
AriPerkkio 6bc4f8d
docs: correct onCoverage
AriPerkkio bef1eee
chore: review fixes
AriPerkkio 306a5cd
refactor: remove unused statistics from reported tasks
AriPerkkio 50cf790
refactor: remove unused statistics from reported tasks
AriPerkkio cf0e14f
Merge remote-tracking branch 'upstream/main' into feat/new-reporter-api
AriPerkkio e5e9638
build: fix paths
AriPerkkio 1a155c4
doc: jsdoc for reporter hooks
AriPerkkio 1fd9697
chore: review, typos, revert formatting-only changes
AriPerkkio 6d3b228
fix: report skipped tests in merge-reports
AriPerkkio ebff697
fix: add events to typechecker
AriPerkkio 3e93fb3
Merge branch 'main' of github.com:vitest-dev/vitest into feat/new-rep…
sheremet-va b46340d
chore: merge reporters types
sheremet-va 077f230
fix: call onTestRunStart/onTestRunEnd even if there are no files to run
sheremet-va 33c8544
fix: don't call `onCoverage` hook if there is no coverage to report
sheremet-va 59808e7
fix: correctly report merged reports
sheremet-va b4cb350
fix: correctly parse typecheck events and print TS icon in summary
sheremet-va File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,306 @@ | ||
| # Reporters | ||
|
|
||
| ::: warning | ||
| This is an advanced API. If you just want to configure built-in reporters, read the ["Reporters"](/guide/reporters) guide. | ||
| ::: | ||
|
|
||
| Vitest has its own test run lifecycle. These are represented by reporter's methods: | ||
|
|
||
| - [`onInit`](#oninit) | ||
| - [`onTestRunStart`](#ontestrunstart) | ||
| - [`onTestModuleQueued`](#ontestmodulequeued) | ||
| - [`onTestModuleCollected`](#ontestmodulecollected) | ||
| - [`onTestModuleStart`](#ontestmodulestart) | ||
| - [`onTestSuiteReady`](#ontestsuiteready) | ||
| - [`onHookStart(beforeAll)`](#onhookstart) | ||
| - [`onHookEnd(beforeAll)`](#onhookend) | ||
| - [`onTestCaseReady`](#ontestcaseready) | ||
| - [`onHookStart(beforeEach)`](#onhookstart) | ||
| - [`onHookEnd(beforeEach)`](#onhookend) | ||
| - [`onHookStart(afterEach)`](#onhookstart) | ||
| - [`onHookEnd(afterEach)`](#onhookend) | ||
| - [`onTestCaseResult`](#ontestcaseresult) | ||
| - [`onHookStart(afterAll)`](#onhookstart) | ||
| - [`onHookEnd(afterAll)`](#onhookend) | ||
| - [`onTestSuiteResult`](#ontestsuiteresult) | ||
| - [`onTestModuleEnd`](#ontestmoduleend) | ||
| - [`onTestRunEnd`](#ontestrunend) | ||
|
|
||
| Tests and suites within a single module will be reported in order unless they were skipped. All skipped tests are reported at the end of suite/module. | ||
|
|
||
| Note that since test modules can run in parallel, Vitest will report them in parallel. | ||
|
|
||
| This guide lists all supported reporter methods. However, don't forget that instead of creating your own reporter, you can [extend existing one](/advanced/reporters) instead: | ||
|
|
||
| ```ts [custom-reporter.js] | ||
| import { BaseReporter } from 'vitest/reporters' | ||
|
|
||
| export default class CustomReporter extends BaseReporter { | ||
| onTestRunEnd(testModules, errors) { | ||
| console.log(testModule.length, 'tests finished running') | ||
| super.onTestRunEnd(testModules, errors) | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## onInit | ||
|
|
||
| ```ts | ||
| function onInit(vitest: Vitest): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method is called when [Vitest](/advanced/api/vitest) was initiated or started, but before the tests were filtered. | ||
|
|
||
| ::: info | ||
| Internally this method is called inside [`vitest.start`](/advanced/api/vitest#start), [`vitest.init`](/advanced/api/vitest#init) or [`vitest.mergeReports`](/advanced/api/vitest#mergereports). If you are using programmatic API, make sure to call either one dependning on your needs before calling [`vitest.runTestSpecifications`](/advanced/api/vitest#runtestspecifications), for example. Built-in CLI will always run methods in correct order. | ||
| ::: | ||
|
|
||
| Note that you can also get access to `vitest` instance from test cases, suites and test modules via a [`project`](/advanced/api/test-project) property, but it might also be useful to store a reference to `vitest` in this method. | ||
|
|
||
| ::: details Example | ||
| ```ts | ||
| import type { Reporter, TestSpecification } from 'vitest/reporters' | ||
| import type { 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() | ||
| ``` | ||
| ::: | ||
|
|
||
| ## onTestRunStart | ||
|
|
||
| ```ts | ||
| function onTestRunStart( | ||
| specifications: TestSpecification[] | ||
| ): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method is called when a new test run has started. It receives an array of [test specifications](/advanced/api/test-specification) scheduled to run. This array is readonly and available only for information purposes. | ||
|
|
||
| ::: details Example | ||
| ```ts | ||
| import type { Reporter, TestSpecification } from 'vitest/reporters' | ||
|
|
||
| class MyReporter implements Reporter { | ||
| onTestRunStart(specifications: TestSpecification[]) { | ||
| console.log(specifications.length, 'test files will run') | ||
| } | ||
| } | ||
|
|
||
| export default new MyReporter() | ||
| ``` | ||
| ::: | ||
|
|
||
| ::: tip DEPRECATION NOTICE | ||
| This method was added in Vitest 3, replacing `onPathsCollected` and `onSpecsCollected`, both of which are now deprecated. | ||
| ::: | ||
|
|
||
| ## onTestRunEnd | ||
|
|
||
| ```ts | ||
| function onTestRunEnd( | ||
| testModules: ReadonlyArray<TestModule>, | ||
| unhandledErrors: ReadonlyArray<SerializedError>, | ||
| reason: TestRunEndReason | ||
| ): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method is called after all tests have finished running and the coverage merged all reports, if it's enabled. Note that you can get the coverage information in [`onCoverage`](#oncoverage) hook. | ||
|
|
||
| It receives a readonly list of test modules. You can iterate over it via a [`testModule.children`](/advanced/api/test-collection) property to report the state and errors, if any. | ||
|
|
||
| The second argument is a readonly list of unhandled errors that Vitest wasn't able to attribute to any test. These can happen outside of the test run because of an error in a plugin, or inside the test run as a side-effect of a non-awaited function (for example, a timeout that threw an error after the test has finished running). | ||
|
|
||
| The third argument indicated why the test run was finished: | ||
|
|
||
| - `passed`: test run was finished normally and there are no errors | ||
| - `failed`: test run has at least one error (due to a syntax error during collection or an actual error during test execution) | ||
| - `interrupted`: test was interruped by [`vitest.cancelCurrentRun`](/advanced/api/vitest#cancelcurrentrun) call or `Ctrl+C` was pressed in the terminal (note that it's still possible to have failed tests in this case) | ||
|
|
||
| ::: details Example | ||
| ```ts | ||
| import type { | ||
| Reporter, | ||
| SerializedError, | ||
| TestModule, | ||
| TestRunEndReason, | ||
| TestSpecification | ||
| } from 'vitest/reporters' | ||
|
|
||
| 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() | ||
| ``` | ||
| ::: | ||
|
|
||
| ::: tip DEPRECATION NOTICE | ||
| This method was added in Vitest 3, replacing `onFinished`, which is now deprecated. | ||
| ::: | ||
|
|
||
| ## onCoverage | ||
|
|
||
| ```ts | ||
| function onCoverage(coverage: unknown): Awaitable<void> | ||
| ``` | ||
|
|
||
| This hook 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 you can import the types from `istanbul-lib-coverage` package: | ||
|
|
||
| ```ts | ||
| import type { CoverageMap } from 'istanbul-lib-coverage' | ||
|
|
||
| declare function onCoverage(coverage: CoverageMap): Awaitable<void> | ||
| ``` | ||
|
|
||
| ## onTestModuleQueued | ||
|
|
||
| ```ts | ||
| function onTestModuleQueued(testModule: TestModule): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method is called right before Vitest imports the setup file and the test module itself. This means that `testModule` will have no [`children`](/advanced/api/test-suite#children) yet, but you can start reporting it as the next test to run. | ||
|
|
||
| ## onTestModuleCollected | ||
|
|
||
| ```ts | ||
| function onTestModuleCollected(testModule: TestModule): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method is called when all tests inside the file were collected, meaning [`testModule.children`](/advanced/api/test-suite#children) collection is populated, but tests don't have any results yet. | ||
|
|
||
| ## onTestModuleStart | ||
|
|
||
| ```ts | ||
| function onTestModuleStart(testModule: TestModule): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method is called right after [`onTestModuleCollected`](#ontestmodulecollected) unless Vitest runs in collection mode ([`vitest.collect()`](/advanced/api/vitest#collect) or `vitest collect` in the CLI), in this case it will not be called at all because there are no tests to run. | ||
|
|
||
| ## onTestModuleEnd | ||
|
|
||
| ```ts | ||
| function onTestModuleEnd(testModule: TestModule): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method is called when every test in the module finished running. This means, every test inside [`testModule.children`](/advanced/api/test-suite#children) will have a `test.result()` that is not equal to `pending`. | ||
|
|
||
| ## onHookStart | ||
|
|
||
| ```ts | ||
| function onHookStart(context: ReportedHookContext): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method 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`](/advanced/api/test-suite) or [`TestModule`](/advanced/api/test-module). | ||
|
|
||
| If `beforeEach` or `afterEach` are started, the `entity` will always be [`TestCase`](/advanced/api/test-case). | ||
|
|
||
| ::: warning | ||
| `onHookStart` method will not be called if the hook did not run during the test run. | ||
| ::: | ||
|
|
||
| ## onHookEnd | ||
|
|
||
| ```ts | ||
| function onHookEnd(context: ReportedHookContext): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method 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`](/advanced/api/test-suite) or [`TestModule`](/advanced/api/test-module). | ||
|
|
||
| If `beforeEach` or `afterEach` have finished, the `entity` will always be [`TestCase`](/advanced/api/test-case). | ||
|
|
||
| ::: warning | ||
| `onHookEnd` method will not be called if the hook did not run during the test run. | ||
| ::: | ||
|
|
||
| ## onTestSuiteReady | ||
|
|
||
| ```ts | ||
| function onTestSuiteReady(testSuite: TestSuite): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method 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 | ||
|
|
||
| ```ts | ||
| function onTestSuiteResult(testSuite: TestSuite): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method 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 | ||
|
|
||
| ```ts | ||
| function onTestCaseReady(testCase: TestCase): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method is called before the test starts to run or it was skipped. Note that `beforeEach` and `afterEach` hooks are considered part of the test because they can influence the result. | ||
|
|
||
| ::: warning | ||
| Notice that it's possible to have [`testCase.result()`](/advanced/api/test-case#result) with `passed` or `failed` state already when `onTestCaseReady` is called. This can happen if test was running too fast and both `onTestCaseReady` and `onTestCaseResult` were scheduled to run in the same microtask. | ||
| ::: | ||
|
|
||
| ## onTestCaseResult | ||
|
|
||
| ```ts | ||
| function onTestCaseResult(testCase: TestCase): Awaitable<void> | ||
| ``` | ||
|
|
||
| This method is called when the test has finished running or was just skipped. Note that this will be called after the `afterEach` hook is finished, if there are any. | ||
|
|
||
| At this point, [`testCase.result()`](/advanced/api/test-case#result) will have non-pending state. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.