diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 981a5366006b..287a605fd52b 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -85,6 +85,7 @@ export default withPwa(defineConfig({ { text: 'Guide', link: '/guide/' }, { text: 'API', link: '/api/' }, { text: 'Config', link: '/config/' }, + { text: 'Advanced', link: '/advanced/api' }, { text: `v${version}`, items: [ @@ -102,6 +103,21 @@ export default withPwa(defineConfig({ sidebar: { // TODO: bring sidebar of apis and config back + '/advanced': [ + { + text: 'Advanced', + items: [ + { + text: 'Vitest Node API', + link: '/advanced/api', + }, + { + text: 'Runner API', + link: '/advanced/runner', + }, + ], + }, + ], '/': [ { text: 'Guide', diff --git a/docs/advanced/api.md b/docs/advanced/api.md new file mode 100644 index 000000000000..ce36b7ae8fde --- /dev/null +++ b/docs/advanced/api.md @@ -0,0 +1,67 @@ +# Node API + +::: warning +Vitest exposes experimental private API. Breaking changes might not follow semver, please pin Vitest's version when using it. +::: + +## startVitest + +You can start running Vitest tests using its Node API: + +```js +import { startVitest } from 'vitest/node' + +const vitest = await startVitest('test', ['tests/run-only.test.ts']) + +await vitest?.close() +``` + +`startVitest` function returns `Vitest` instance if tests can be started. It returns `undefined`, if one of the following occurs: + +- Vitest didn't find "vite" package (usually installed with Vitest) +- If coverage is enabled and run mode is "test", but the coverage package is not installed (`@vitest/coverage-c8` or `@vitest/coverage-istanbul`) +- If the environment package is not installed (`jsdom`/`happy-dom`/`@edge-runtime/vm`) + +If `undefined` is returned or tests failed during the run, Vitest sets `process.exitCode` to `1`. + +If watch mode is not enabled, Vitest will call `close` method. + +If watch mode is enabled and the terminal supports TTY, Vitest will register console shortcuts. + +## createVitest + +You can create Vitest instance yourself using `createVitest` function. It returns the same `Vitest` instance as `startVitest`, but it doesn't start tests and doesn't validate installed packages. + +```js +import { createVitest } from 'vitest/node' + +const vitest = await createVitest('test', { + watch: false, +}) +``` + +## Vitest + +Vitest instance requires the current test mode. I can be either: + +- `test` when running runtime tests +- `benchmark` when running benchmarks +- `typecheck` when running type tests + +### mode + +#### test + +Test mode will only call functions inside `test` or `it`, and throws an error when `bench` is encountered. This mode uses `include` and `exclude` options in the config to find test files. + +#### benchmark + +Benchmark mode calls `bench` functions and throws an error, when it encounters `test` or `it`. This mode uses `benchmark.include` and `benchmark.exclude` options in the config to find benchmark files. + +#### typecheck + +Typecheck mode doesn't _run_ tests. It only analyses types and gives a summary. This mode uses `typecheck.include` and `typecheck.exclude` options in the config to find files to analyze. + +### start + +You can start running tests or benchmarks with `start` method. You can pass an array of strings to filter test files. diff --git a/docs/advanced/runner.md b/docs/advanced/runner.md new file mode 100644 index 000000000000..80fd7581a58b --- /dev/null +++ b/docs/advanced/runner.md @@ -0,0 +1,94 @@ +# Test Runner + +::: warning +This is advanced API. If you are just running tests, you probably don't need this. It is primarily used by library authors. +::: + +You can specify a path to your test runner with the `runner` option in your configuration file. This file should have a default export with a class implementing these methods: + +```ts +export interface VitestRunner { + /** + * First thing that's getting called before actually collecting and running tests. + */ + onBeforeCollect?(paths: string[]): unknown + /** + * Called after collecting tests and before "onBeforeRun". + */ + onCollected?(files: File[]): unknown + + /** + * Called before running a single test. Doesn't have "result" yet. + */ + onBeforeRunTest?(test: Test): unknown + /** + * Called before actually running the test function. Already has "result" with "state" and "startTime". + */ + onBeforeTryTest?(test: Test, retryCount: number): unknown + /** + * Called after result and state are set. + */ + onAfterRunTest?(test: Test): unknown + /** + * Called right after running the test function. Doesn't have new state yet. Will not be called, if the test function throws. + */ + onAfterTryTest?(test: Test, retryCount: number): unknown + + /** + * Called before running a single suite. Doesn't have "result" yet. + */ + onBeforeRunSuite?(suite: Suite): unknown + /** + * Called after running a single suite. Has state and result. + */ + onAfterRunSuite?(suite: Suite): unknown + + /** + * If defined, will be called instead of usual Vitest suite partition and handling. + * "before" and "after" hooks will not be ignored. + */ + runSuite?(suite: Suite): Promise + /** + * If defined, will be called instead of usual Vitest handling. Useful, if you have your custom test function. + * "before" and "after" hooks will not be ignored. + */ + runTest?(test: Test): Promise + + /** + * Called, when a task is updated. The same as "onTaskUpdate" in a reporter, but this is running in the same thread as tests. + */ + onTaskUpdate?(task: [string, TaskResult | undefined][]): Promise + + /** + * Called before running all tests in collected paths. + */ + onBeforeRun?(files: File[]): unknown + /** + * Called right after running all tests in collected paths. + */ + onAfterRun?(files: File[]): unknown + /** + * Called when new context for a test is defined. Useful, if you want to add custom properties to the context. + * If you only want to define custom context with a runner, consider using "beforeAll" in "setupFiles" instead. + */ + extendTestContext?(context: TestContext): TestContext + /** + * Called, when files are imported. Can be called in two situations: when collecting tests and when importing setup files. + */ + importFile(filepath: string, source: VitestRunnerImportSource): unknown + /** + * Publically available configuration. + */ + config: VitestRunnerConfig +} +``` + +When initiating this class, Vitest passes down Vitest config, - you should expose it as a `config` property. + +::: warning +`importFile` method in your custom runner must be inlined in `deps.inline` config option, if you call Node `import` inside. +::: + +::: tip +Snapshot support, C8 coverage, and some other features depend on the runner. If you don't want to lose it, you can extend your runner from `VitestTestRunner` imported from `vitest/runners`. It also exposes `BenchmarkNodeRunner`, if you want to extend its functionality. +::: \ No newline at end of file diff --git a/docs/guide/ui.md b/docs/guide/ui.md index 7b2646868fff..18f3595c5f84 100644 --- a/docs/guide/ui.md +++ b/docs/guide/ui.md @@ -22,7 +22,7 @@ Then you can visit the Vitest UI at Vitest UI -Since Vitest 0.26.0, UI can also be used as a reporter. Use `'html'` reporter in your Vitest configuration to generate HTML output and preview results of your tests: +Since Vitest 0.26.0, UI can also be used as a reporter. Use `'html'` reporter in your Vitest configuration to generate HTML output and preview the results of your tests: ```ts // vitest.config.ts