diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 532ceb4c467b..c4c5a3a6fd16 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -1,5 +1,6 @@ import { transformerTwoslash } from '@shikijs/vitepress-twoslash' import { withPwa } from '@vite-pwa/vitepress' +import type { DefaultTheme } from 'vitepress' import { defineConfig } from 'vitepress' import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs' import { version } from '../../package.json' @@ -19,6 +20,10 @@ import { } from './meta' import { pwa } from './scripts/pwa' import { transformHead } from './scripts/transformHead' +import { + groupIconMdPlugin, + groupIconVitePlugin, +} from 'vitepress-plugin-group-icons' export default ({ mode }: { mode: string }) => { return withPwa(defineConfig({ @@ -56,9 +61,26 @@ export default ({ mode }: { mode: string }) => { ['link', { rel: 'apple-touch-icon', href: '/apple-touch-icon.png', sizes: '180x180' }], ], lastUpdated: true, + vite: { + plugins: [ + groupIconVitePlugin({ + customIcon: { + 'CLI': 'vscode-icons:file-type-shell', + 'vitest.workspace': 'vscode-icons:file-type-vitest', + 'vitest.config': 'vscode-icons:file-type-vitest', + '.spec.ts': 'vscode-icons:file-type-testts', + '.test.ts': 'vscode-icons:file-type-testts', + '.spec.js': 'vscode-icons:file-type-testjs', + '.test.js': 'vscode-icons:file-type-testjs', + 'marko': 'vscode-icons:file-type-marko', + }, + }), + ], + }, markdown: { config(md) { md.use(tabsMarkdownPlugin) + md.use(groupIconMdPlugin) }, theme: { light: 'github-light', @@ -116,8 +138,7 @@ export default ({ mode }: { mode: string }) => { }, nav: [ - { text: 'Guide', link: '/guide/', activeMatch: '^/guide/(?!browser)' }, - { text: 'API', link: '/api/', activeMatch: '^/api/' }, + { text: 'Guide & API', link: '/guide/', activeMatch: '^/(guide|api)/(?!browser)' }, { text: 'Config', link: '/config/', activeMatch: '^/config/' }, { text: 'Browser Mode', link: '/guide/browser', activeMatch: '^/guide/browser/' }, { @@ -176,225 +197,119 @@ export default ({ mode }: { mode: string }) => { sidebar: { '/guide/browser': [ { - text: 'Why Browser Mode?', - link: '/guide/browser/why', - docFooterText: 'Why Browser Mode? | Browser Mode', - }, - { - text: 'Getting Started', - link: '/guide/browser/', - docFooterText: 'Getting Started | Browser Mode', - }, - { - text: 'Context API', - link: '/guide/browser/context', - docFooterText: 'Context API | Browser Mode', - }, - { - text: 'Interactivity API', - link: '/guide/browser/interactivity-api', - docFooterText: 'Interactivity API | Browser Mode', - }, - { - text: 'Locators', - link: '/guide/browser/locators', - docFooterText: 'Locators | Browser Mode', - }, - { - text: 'Assertion API', - link: '/guide/browser/assertion-api', - docFooterText: 'Assertion API | Browser Mode', - }, - { - text: 'Commands API', - link: '/guide/browser/commands', - docFooterText: 'Commands | Browser Mode', - }, - ], - // TODO: bring sidebar of apis and config back - '/advanced': [ - { + text: 'Introduction', + collapsed: false, items: [ { - text: 'API', - items: [ - - { - text: 'Vitest Node API', - link: '/advanced/api', - }, - { - text: 'Runner API', - link: '/advanced/runner', - }, - { - text: 'Task Metadata', - link: '/advanced/metadata', - }, - ], + text: 'Why Browser Mode', + link: '/guide/browser/why', + docFooterText: 'Why Browser Mode | Browser Mode', }, { - text: 'Guides', - items: [ - { - text: 'Running Tests', - link: '/advanced/guide/tests', - }, - { - text: 'Extending Reporters', - link: '/advanced/reporters', - }, - { - text: 'Custom Pool', - link: '/advanced/pool', - }, - ], + text: 'Getting Started', + link: '/guide/browser/', + docFooterText: 'Getting Started | Browser Mode', }, ], }, - ], - '/guide/': [ { + text: 'API', + collapsed: false, items: [ { - text: 'Why Vitest', - link: '/guide/why', - }, - { - text: 'Getting Started', - link: '/guide/', - }, - { - text: 'Features', - link: '/guide/features', - }, - { - text: 'Workspace', - link: '/guide/workspace', - }, - { - text: 'CLI', - link: '/guide/cli', - }, - { - text: 'Test Filtering', - link: '/guide/filtering', - }, - { - text: 'Reporters', - link: '/guide/reporters', - }, - { - text: 'Coverage', - link: '/guide/coverage', - }, - { - text: 'Snapshot', - link: '/guide/snapshot', - }, - { - text: 'Mocking', - link: '/guide/mocking', - }, - { - text: 'Testing Types', - link: '/guide/testing-types', - }, - { - text: 'Vitest UI', - link: '/guide/ui', - }, - { - text: 'In-Source Testing', - link: '/guide/in-source', - }, - { - text: 'Test Context', - link: '/guide/test-context', - }, - { - text: 'Environment', - link: '/guide/environment', - }, - { - text: 'Extending Matchers', - link: '/guide/extending-matchers', - }, - { - text: 'IDE Integration', - link: '/guide/ide', - }, - { - text: 'Debugging', - link: '/guide/debugging', + text: 'Context API', + link: '/guide/browser/context', + docFooterText: 'Context API | Browser Mode', }, { - text: 'Comparisons', - link: '/guide/comparisons', + text: 'Interactivity API', + link: '/guide/browser/interactivity-api', + docFooterText: 'Interactivity API | Browser Mode', }, { - text: 'Migration Guide', - link: '/guide/migration', + text: 'Locators', + link: '/guide/browser/locators', + docFooterText: 'Locators | Browser Mode', }, { - text: 'Common Errors', - link: '/guide/common-errors', + text: 'Assertion API', + link: '/guide/browser/assertion-api', + docFooterText: 'Assertion API | Browser Mode', }, { - text: 'Profiling Test Performance', - link: '/guide/profiling-test-performance', - }, - { - text: 'Improving Performance', - link: '/guide/improving-performance', + text: 'Commands API', + link: '/guide/browser/commands', + docFooterText: 'Commands | Browser Mode', }, ], }, + footer(), ], - '/api/': [ + '/advanced': [ { + text: 'API', + collapsed: false, items: [ { - text: 'Test API Reference', - link: '/api/', - }, - { - text: 'Mock Functions', - link: '/api/mock', + text: 'Vitest Node API', + link: '/advanced/api', }, { - text: 'Vi Utility', - link: '/api/vi', + text: 'Runner API', + link: '/advanced/runner', }, { - text: 'Expect', - link: '/api/expect', + text: 'Task Metadata', + link: '/advanced/metadata', }, + ], + }, + { + text: 'Guides', + collapsed: false, + items: [ { - text: 'ExpectTypeOf', - link: '/api/expect-typeof', + text: 'Running Tests', + link: '/advanced/guide/tests', }, { - text: 'Assert', - link: '/api/assert', + text: 'Extending Reporters', + link: '/advanced/reporters', }, { - text: 'AssertType', - link: '/api/assert-type', + text: 'Custom Pool', + link: '/advanced/pool', }, ], }, + footer(), ], - '/config/': [ + '/team': [], + '/': [ + { + text: 'Introduction', + collapsed: false, + items: introduction(), + }, + { + text: 'API', + collapsed: false, + items: api(), + }, + { + text: 'Guides', + collapsed: false, + items: guide(), + }, { items: [ { - text: 'Config File', - link: '/config/file', + text: 'Browser Mode', + link: '/guide/browser', }, { - text: 'Config Reference', - link: '/config/', + text: 'Advanced API', + link: '/advanced/api', }, ], }, @@ -405,3 +320,157 @@ export default ({ mode }: { mode: string }) => { transformHead, })) } + +function footer(): DefaultTheme.SidebarItem { + return { + items: [ + { + text: 'Config Reference', + link: '/config/', + }, + { + text: 'Test API Reference', + link: '/api/', + }, + ], + } +} + +function introduction(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Why Vitest', + link: '/guide/why', + }, + { + text: 'Getting Started', + link: '/guide/', + }, + { + text: 'Features', + link: '/guide/features', + }, + { + text: 'Config Reference', + link: '/config/', + }, + ] +} + +function guide(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Workspace', + link: '/guide/workspace', + }, + { + text: 'CLI', + link: '/guide/cli', + }, + { + text: 'Test Filtering', + link: '/guide/filtering', + }, + { + text: 'Reporters', + link: '/guide/reporters', + }, + { + text: 'Coverage', + link: '/guide/coverage', + }, + { + text: 'Snapshot', + link: '/guide/snapshot', + }, + { + text: 'Mocking', + link: '/guide/mocking', + }, + { + text: 'Testing Types', + link: '/guide/testing-types', + }, + { + text: 'Vitest UI', + link: '/guide/ui', + }, + { + text: 'In-Source Testing', + link: '/guide/in-source', + }, + { + text: 'Test Context', + link: '/guide/test-context', + }, + { + text: 'Environment', + link: '/guide/environment', + }, + { + text: 'Extending Matchers', + link: '/guide/extending-matchers', + }, + { + text: 'IDE Integration', + link: '/guide/ide', + }, + { + text: 'Debugging', + link: '/guide/debugging', + }, + { + text: 'Comparisons', + link: '/guide/comparisons', + }, + { + text: 'Migration Guide', + link: '/guide/migration', + }, + { + text: 'Common Errors', + link: '/guide/common-errors', + }, + { + text: 'Profiling Test Performance', + link: '/guide/profiling-test-performance', + }, + { + text: 'Improving Performance', + link: '/guide/improving-performance', + }, + ] +} + +function api(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'Test API Reference', + link: '/api/', + }, + { + text: 'Mock Functions', + link: '/api/mock', + }, + { + text: 'Vi Utility', + link: '/api/vi', + }, + { + text: 'Expect', + link: '/api/expect', + }, + { + text: 'ExpectTypeOf', + link: '/api/expect-typeof', + }, + { + text: 'Assert', + link: '/api/assert', + }, + { + text: 'AssertType', + link: '/api/assert-type', + }, + ] +} diff --git a/docs/.vitepress/style/main.css b/docs/.vitepress/style/main.css index 87c08069f97e..735f705c9940 100644 --- a/docs/.vitepress/style/main.css +++ b/docs/.vitepress/style/main.css @@ -6,6 +6,10 @@ html:not(.dark) [img-dark] { display: none; } +details summary { + cursor: pointer; +} + /* Overrides */ .sp .sp-link.link:hover, diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index d684d9dc1fad..c3e91f7db522 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -10,6 +10,7 @@ import '../style/main.css' import '../style/vars.css' import 'uno.css' import '@shikijs/vitepress-twoslash/style.css' +import 'virtual:group-icons.css' if (inBrowser) { import('./pwa') diff --git a/docs/advanced/metadata.md b/docs/advanced/metadata.md index 2f493d3f0943..6efd276269f2 100644 --- a/docs/advanced/metadata.md +++ b/docs/advanced/metadata.md @@ -22,8 +22,7 @@ test('custom', ({ task }) => { Once a test is completed, Vitest will send a task including the result and `meta` to the Node.js process using RPC. To intercept and process this task, you can utilize the `onTaskUpdate` method available in your reporter implementation: -```ts -// custom-reporter.js +```ts [custom-reporter.js] export default { // you can intercept packs if needed onTaskUpdate(packs) { diff --git a/docs/advanced/reporters.md b/docs/advanced/reporters.md index 6f3236632cd0..49586526003c 100644 --- a/docs/advanced/reporters.md +++ b/docs/advanced/reporters.md @@ -18,8 +18,7 @@ Of course, you can create your reporter from scratch. Just extend the `BaseRepor And here is an example of a custom reporter: -```ts -// ./custom-reporter.js +```ts [custom-reporter.js] import { BaseReporter } from 'vitest/reporters' export default class CustomReporter extends BaseReporter { @@ -32,8 +31,7 @@ export default class CustomReporter extends BaseReporter { Or implement the `Reporter` interface: -```ts -// ./custom-reporter.js +```ts [custom-reporter.js] import { Reporter } from 'vitest/reporters' export default class CustomReporter implements Reporter { @@ -45,7 +43,7 @@ export default class CustomReporter implements Reporter { Then you can use your custom reporter in the `vitest.config.ts` file: -```ts +```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' import CustomReporter from './custom-reporter.js' diff --git a/docs/advanced/runner.md b/docs/advanced/runner.md index 0e969cde0e0b..ab5fb77e510b 100644 --- a/docs/advanced/runner.md +++ b/docs/advanced/runner.md @@ -246,8 +246,7 @@ Vitest exposes a `Custom` task type that allows users to reuse built-int reporte A task is an object that is part of a suite. It is automatically added to the current suite with a `suite.task` method: -```js -// ./utils/custom.js +```js [custom.js] import { createTaskCollector, getCurrentSuite, setFn } from 'vitest/suite' export { afterAll, beforeAll, describe } from 'vitest' @@ -270,9 +269,8 @@ export const myCustomTask = createTaskCollector( ) ``` -```js -// ./garden/tasks.test.js -import { afterAll, beforeAll, describe, myCustomTask } from '../custom.js' +```js [tasks.test.js] +import { afterAll, beforeAll, describe, myCustomTask } from './custom.js' import { gardener } from './gardener.js' describe('take care of the garden', () => { diff --git a/docs/api/vi.md b/docs/api/vi.md index 2aed59bc98ec..759ddf975c37 100644 --- a/docs/api/vi.md +++ b/docs/api/vi.md @@ -136,8 +136,7 @@ For example, you have this file structure: If you call `vi.mock` in a test file without a factory or options provided, it will find a file in the `__mocks__` folder to use as a module: -```ts -// increment.test.js +```ts [increment.test.js] import { vi } from 'vitest' // axios is a default export from `__mocks__/axios.js` @@ -175,14 +174,13 @@ import { increment } from './increment.js' ``` ::: -```ts -// ./increment.js +```ts [increment.js] export function increment(number) { return number + 1 } ``` -```ts +```ts [increment.test.js] import { beforeEach, test } from 'vitest' import { increment } from './increment.js' @@ -216,8 +214,7 @@ Type helper for TypeScript. Just returns the object that was passed. When `partial` is `true` it will expect a `Partial` as a return value. By default, this will only make TypeScript believe that the first level values are mocked. You can pass down `{ deep: true }` as a second argument to tell TypeScript that the whole object is mocked, if it actually is. -```ts -// example.ts +```ts [example.ts] export function add(x: number, y: number): number { return x + y } @@ -227,8 +224,7 @@ export function fetchSomething(): Promise { } ``` -```ts -// example.test.ts +```ts [example.test.ts] import * as example from './example' vi.mock('./example') @@ -277,14 +273,13 @@ Removes module from the mocked registry. All calls to import will return the ori The same as [`vi.unmock`](#vi-unmock), but is not hoisted to the top of the file. The next import of the module will import the original module instead of the mock. This will not unmock previously imported modules. -```ts -// ./increment.js +```ts [increment.js] export function increment(number) { return number + 1 } ``` -```ts +```ts [increment.test.js] import { increment } from './increment.js' // increment is already mocked, because vi.mock is hoisted diff --git a/docs/config/file.md b/docs/config/file.md deleted file mode 100644 index 3b6dfe2b5b52..000000000000 --- a/docs/config/file.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -outline: deep ---- - -# Managing Vitest config file - -If you are using Vite and have a `vite.config` file, Vitest will read it to match with the plugins and setup as your Vite app. If you want to have a different configuration for testing or your main app doesn't rely on Vite specifically, you could either: - -- Create `vitest.config.ts`, which will have the higher priority and will **override** the configuration from `vite.config.ts` (Vitest supports all conventional JS and TS extensions, but doesn't support `json`) - it means all options in your `vite.config` will be **ignored** -- Pass `--config` option to CLI, e.g. `vitest --config ./path/to/vitest.config.ts` -- Use `process.env.VITEST` or `mode` property on `defineConfig` (will be set to `test`/`benchmark` if not overridden with `--mode`) to conditionally apply different configuration in `vite.config.ts` - -To configure `vitest` itself, add `test` property in your Vite config. You'll also need to add a reference to Vitest types using a [triple slash command](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-) at the top of your config file, if you are importing `defineConfig` from `vite` itself. - -Using `defineConfig` from `vite` you should follow this: - -```ts -/// -import { defineConfig } from 'vite' - -export default defineConfig({ - test: { - // ... Specify options here. - }, -}) -``` - -The `` will stop working in Vitest 3, but you can start migrating to `vitest/config` in Vitest 2.1: - -```ts -/// -import { defineConfig } from 'vite' - -export default defineConfig({ - test: { - // ... Specify options here. - }, -}) -``` - -Using `defineConfig` from `vitest/config` you should follow this: - -```ts -import { defineConfig } from 'vitest/config' - -export default defineConfig({ - test: { - // ... Specify options here. - }, -}) -``` - -You can retrieve Vitest's default options to expand them if needed: - -```ts -import { configDefaults, defineConfig } from 'vitest/config' - -export default defineConfig({ - test: { - exclude: [...configDefaults.exclude, 'packages/template/*'], - }, -}) -``` - -When using a separate `vitest.config.js`, you can also extend Vite's options from another config file if needed: - -```ts -import { defineConfig, mergeConfig } from 'vitest/config' -import viteConfig from './vite.config' - -export default mergeConfig(viteConfig, defineConfig({ - test: { - exclude: ['packages/template/*'], - }, -})) -``` - -If your Vite config is defined as a function, you can define the config like this: - -```ts -import { defineConfig, mergeConfig } from 'vitest/config' -import viteConfig from './vite.config' - -export default defineConfig(configEnv => mergeConfig( - viteConfig(configEnv), - defineConfig({ - test: { - exclude: ['packages/template/*'], - }, - }) -)) -``` diff --git a/docs/config/index.md b/docs/config/index.md index ca613da7dd84..ffff54277ada 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -4,24 +4,111 @@ outline: deep # Configuring Vitest -To create a Vitest configuration file, follow [the guide](/config/file). Make sure you understand how Vitest config resolution works before proceeding. +If you are using Vite and have a `vite.config` file, Vitest will read it to match with the plugins and setup as your Vite app. If you want to have a different configuration for testing or your main app doesn't rely on Vite specifically, you could either: + +- Create `vitest.config.ts`, which will have the higher priority and will **override** the configuration from `vite.config.ts` (Vitest supports all conventional JS and TS extensions, but doesn't support `json`) - it means all options in your `vite.config` will be **ignored** +- Pass `--config` option to CLI, e.g. `vitest --config ./path/to/vitest.config.ts` +- Use `process.env.VITEST` or `mode` property on `defineConfig` (will be set to `test`/`benchmark` if not overridden with `--mode`) to conditionally apply different configuration in `vite.config.ts` + +To configure `vitest` itself, add `test` property in your Vite config. You'll also need to add a reference to Vitest types using a [triple slash command](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-) at the top of your config file, if you are importing `defineConfig` from `vite` itself. + +
+ Open Config Examples + +Using `defineConfig` from `vite` you should follow this: + +```ts [vite.config.js] +/// +import { defineConfig } from 'vite' + +export default defineConfig({ + test: { + // ... Specify options here. + }, +}) +``` + +The `` will stop working in Vitest 3, but you can start migrating to `vitest/config` in Vitest 2.1: + +```ts [vite.config.js] +/// +import { defineConfig } from 'vite' + +export default defineConfig({ + test: { + // ... Specify options here. + }, +}) +``` + +Using `defineConfig` from `vitest/config` you should follow this: + +```ts [vitest.config.js] +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + // ... Specify options here. + }, +}) +``` + +You can retrieve Vitest's default options to expand them if needed: + +```ts [vitest.config.js] +import { configDefaults, defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + exclude: [...configDefaults.exclude, 'packages/template/*'], + }, +}) +``` + +When using a separate `vitest.config.js`, you can also extend Vite's options from another config file if needed: + +```ts [vitest.config.js] +import { defineConfig, mergeConfig } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig(viteConfig, defineConfig({ + test: { + exclude: ['packages/template/*'], + }, +})) +``` + +If your Vite config is defined as a function, you can define the config like this: + +```ts [vitest.config.js] +import { defineConfig, mergeConfig } from 'vitest/config' +import viteConfig from './vite.config' + +export default defineConfig(configEnv => mergeConfig( + viteConfig(configEnv), + defineConfig({ + test: { + exclude: ['packages/template/*'], + }, + }) +)) +``` +
::: warning -_All_ listed options here are located on a `test` property inside the config: +_All listed options_ on this page are located within a `test` property inside the configuration: -```ts +```ts [vitest.config.js] export default defineConfig({ test: { exclude: [], }, }) ``` -::: -::: tip -In addition to the following options, you can also use any configuration option from [Vite](https://vitejs.dev/config/). For example, `define` to define global variables, or `resolve.alias` to define aliases. +Since Vitest uses Vite config, you can also use any configuration option from [Vite](https://vitejs.dev/config/). For example, `define` to define global variables, or `resolve.alias` to define aliases - these options should be defined on the top level, _not_ within a `test` property. -All configuration options that are not supported inside a [workspace](/guide/workspace) project config have sign next to them. +Configuration options that are not supported inside a [workspace](/guide/workspace) project config have sign next to them. ::: ### include @@ -248,7 +335,7 @@ This option will also affect if a file should be treated as a module when extern Setting this option will _override_ the default, if you wish to still search `node_modules` for packages include it along with any other options: -```ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -355,8 +442,7 @@ Vitest uses Vite SSR primitives to run tests which has [certain pitfalls](https: By default, `vitest` does not provide global APIs for explicitness. If you prefer to use the APIs globally like Jest, you can pass the `--globals` option to CLI or add `globals: true` in the config. -```ts -// vitest.config.ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -368,8 +454,7 @@ export default defineConfig({ To get TypeScript working with the global APIs, add `vitest/globals` to the `types` field in your `tsconfig.json` -```json -// tsconfig.json +```json [tsconfig.json] { "compilerOptions": { "types": ["vitest/globals"] @@ -379,8 +464,7 @@ To get TypeScript working with the global APIs, add `vitest/globals` to the `typ If you are already using [`unplugin-auto-import`](https://github.com/antfu/unplugin-auto-import) in your project, you can also use it directly for auto importing those APIs. -```ts -// vitest.config.ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' import AutoImport from 'unplugin-auto-import/vite' @@ -454,7 +538,7 @@ If you are running Vitest with [`--isolate=false`](#isolate) flag, your tests wi Starting from 0.23.0, you can also define custom environment. When non-builtin environment is used, Vitest will try to load package `vitest-environment-${name}`. That package should export an object with the shape of `Environment`: -```ts +```ts [environment.js] import type { Environment } from 'vitest' export default { @@ -476,7 +560,7 @@ Vitest also exposes `builtinEnvironments` through `vitest/environments` entry, i ::: tip jsdom environment exposes `jsdom` global variable equal to the current [JSDOM](https://github.com/jsdom/jsdom) instance. If you want TypeScript to recognize it, you can add `vitest/jsdom` to your `tsconfig.json` when you use this environment: -```json +```json [tsconfig.json] { "compilerOptions": { "types": ["vitest/jsdom"] @@ -501,7 +585,7 @@ Automatically assign environment based on globs. The first match will be used. For example: -```ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -526,7 +610,7 @@ Automatically assign pool in which tests will run based on globs. The first matc For example: -```ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -645,7 +729,7 @@ Similar as `vmThreads` pool but uses `child_process` instead of `worker_threads` Options for `threads` pool. -```ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -717,7 +801,7 @@ Be careful when using, it as some options may crash worker, e.g. --prof, --title Options for `forks` pool. -```ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -780,7 +864,7 @@ Be careful when using, it as some options may crash worker, e.g. --prof, --title Options for `vmThreads` pool. -```ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -861,7 +945,7 @@ Be careful when using, it as some options may crash worker, e.g. --prof, --title Options for `vmForks` pool. -```ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -1032,9 +1116,7 @@ Properties have to be strings and values need to be [serializable](https://devel ::: tip If you are using TypeScript, you will need to augment `ProvidedContext` type for type safe access: -```ts -// vitest.shims.d.ts - +```ts [vitest.shims.d.ts] declare module 'vitest' { export interface ProvidedContext { API_KEY: string @@ -1064,16 +1146,16 @@ Global setup runs only if there is at least one running test. This means that gl Beware that the global setup is running in a different global scope, so your tests don't have access to variables defined here. However, you can pass down serializable data to tests via [`provide`](#provide) method: :::code-group -```js [globalSetup.js] -export default function setup(project) { - project.provide('wsPort', 3000) -} +```ts [example.test.js] +import { inject } from 'vitest' + +inject('wsPort') === 3000 ``` -```ts [globalSetup.ts 2.0.0] -import type { GlobalSetupContext } from 'vitest/node' +```ts [globalSetup.ts 2.2.0] +import type { TestProject } from 'vitest/node' -export default function setup({ provide }: GlobalSetupContext) { - provide('wsPort', 3000) +export default function setup(project: TestProject) { + project.provide('wsPort', 3000) } declare module 'vitest' { @@ -1082,11 +1164,11 @@ declare module 'vitest' { } } ``` -```ts [globalSetup.ts 2.2.0] -import type { TestProject } from 'vitest/node' +```ts [globalSetup.ts 2.0.0] +import type { GlobalSetupContext } from 'vitest/node' -export default function setup(project: TestProject) { - project.provide('wsPort', 3000) +export default function setup({ provide }: GlobalSetupContext) { + provide('wsPort', 3000) } declare module 'vitest' { @@ -1095,16 +1177,11 @@ declare module 'vitest' { } } ``` -```ts [example.test.js] -import { inject } from 'vitest' - -inject('wsPort') === 3000 -``` ::: Since Vitest 2.2.0, you can define a custom callback function to be called when Vitest reruns tests. If the function is asynchronous, the runner will wait for it to complete before executing tests. Note that you cannot destruct the `project` like `{ onTestsRerun }` because it relies on the context. -```ts +```ts [globalSetup.ts] import type { TestProject } from 'vitest/node' export default function setup(project: TestProject) { @@ -1213,7 +1290,7 @@ List of files excluded from coverage as glob patterns. This option overrides all default options. Extend the default options when adding new patterns to ignore: -```ts +```ts [vitest.config.js] import { coverageConfigDefaults, defineConfig } from 'vitest/config' export default defineConfig({ @@ -1502,7 +1579,7 @@ By default Vite uses ESBuild which removes comments and Typescript types from `. If you want to apply ESBuild to other files as well, define them in [`esbuild` options](https://vitejs.dev/config/shared-options.html#esbuild): -```ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -1665,11 +1742,10 @@ Run the browser in a `headless` mode. If you are running Vitest in CI, it will b Run every test in a separate iframe. -#### browser.testerHtmlPath +#### browser.testerHtmlPath 2.1.4 {#browser-testerhtmlpath} - **Type:** `string` - **Default:** `@vitest/browser/tester.html` -- **Version:** Since Vitest 2.1.4 A path to the HTML entry point. Can be relative to the root of the project. This file will be processed with [`transformIndexHtml`](https://vite.dev/guide/api-plugin#transformindexhtml) hook. @@ -1709,8 +1785,8 @@ This is an advanced API for library authors. If you just need to run tests in a Options that will be passed down to provider when calling `provider.initialize`. -```ts -export default defineConfig({ +```ts [vitest.config.js] +export default { test: { browser: { providerOptions: { @@ -1720,11 +1796,11 @@ export default defineConfig({ } } } -}) +} ``` ::: tip -To have a better type safety when using built-in providers, you should reference one of these types (for provider that you are using) in your [config file](/config/file): +To have a better type safety when using built-in providers, you should reference one of these types (for provider that you are using) in your [config file](/config/): ```ts /// @@ -1911,7 +1987,7 @@ A list of paths to snapshot serializer modules for snapshot testing, useful if y Overrides default snapshot path. For example, to store snapshots next to test files: -```ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -2016,7 +2092,7 @@ Use this option if you want to disable the cache feature. At the moment Vitest s The cache directory is controlled by the Vite's [`cacheDir`](https://vitejs.dev/config/shared-options.html#cachedir) option: -```ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -2026,7 +2102,7 @@ export default defineConfig({ You can limit the directory only for Vitest by using `process.env.VITEST`: -```ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -2259,7 +2335,7 @@ Custom handler for `console.log` in tests. If you return `false`, Vitest will no Can be useful for filtering out logs from third-party libraries. -```ts +```ts [vitest.config.js] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -2279,7 +2355,7 @@ Apply a filtering function to each frame of each stack trace when handling error Can be useful for filtering out stack trace frames from third-party libraries. -```ts +```ts [vitest.config.ts] import type { ParsedStack } from 'vitest' import { defineConfig } from 'vitest/config' diff --git a/docs/guide/browser/assertion-api.md b/docs/guide/browser/assertion-api.md index c768cc10c1d8..2126fe110e22 100644 --- a/docs/guide/browser/assertion-api.md +++ b/docs/guide/browser/assertion-api.md @@ -32,7 +32,7 @@ Vitest bundles the [`@testing-library/jest-dom`](https://github.com/testing-libr - [`toHaveRole`](https://github.com/testing-library/jest-dom#toHaveRole) - [`toHaveErrorMessage`](https://github.com/testing-library/jest-dom#toHaveErrorMessage) -If you are using [TypeScript](/guide/browser/#typescript) or want to have correct type hints in `expect`, make sure you have either `@vitest/browser/providers/playwright` or `@vitest/browser/providers/webdriverio` referenced in your [setup file](/config/#setupfile) or a [config file](/config/file) depending on the provider you use. If you use the default `preview` provider, you can specify `@vitest/browser/matchers` instead. +If you are using [TypeScript](/guide/browser/#typescript) or want to have correct type hints in `expect`, make sure you have either `@vitest/browser/providers/playwright` or `@vitest/browser/providers/webdriverio` referenced in your [setup file](/config/#setupfile) or a [config file](/config/) depending on the provider you use. If you use the default `preview` provider, you can specify `@vitest/browser/matchers` instead. ::: code-group ```ts [preview] diff --git a/docs/guide/browser/commands.md b/docs/guide/browser/commands.md index 064ec47f418d..419cd0b04e4a 100644 --- a/docs/guide/browser/commands.md +++ b/docs/guide/browser/commands.md @@ -149,7 +149,7 @@ export const myCommand: BrowserCommand<[string, number]> = async ( ``` ::: tip -If you are using TypeScript, don't forget to reference `@vitest/browser/providers/playwright` in your [setup file](/config/#setupfile) or a [config file](/config/file) to get autocompletion in the config and in `userEvent` and `page` options: +If you are using TypeScript, don't forget to reference `@vitest/browser/providers/playwright` in your [setup file](/config/#setupfile) or a [config file](/config/) to get autocompletion in the config and in `userEvent` and `page` options: ```ts /// @@ -165,7 +165,7 @@ Vitest exposes some `webdriverio` specific properties on the context object. Vitest automatically switches the `webdriver` context to the test iframe by calling `browser.switchToFrame` before the command is called, so `$` and `$$` methods refer to the elements inside the iframe, not in the orchestrator, but non-webdriver APIs will still refer to the parent frame context. ::: tip -If you are using TypeScript, don't forget to reference `@vitest/browser/providers/webdriverio` in your [setup file](/config/#setupfile) or a [config file](/config/file) to get autocompletion: +If you are using TypeScript, don't forget to reference `@vitest/browser/providers/webdriverio` in your [setup file](/config/#setupfile) or a [config file](/config/) to get autocompletion: ```ts /// diff --git a/docs/guide/browser/index.md b/docs/guide/browser/index.md index a09efb8c0169..ff525f786844 100644 --- a/docs/guide/browser/index.md +++ b/docs/guide/browser/index.md @@ -7,6 +7,10 @@ outline: deep This page provides information about the experimental browser mode feature in the Vitest API, which allows you to run your tests in the browser natively, providing access to browser globals like window and document. This feature is currently under development, and APIs may change in the future. +::: tip +If you are looking for documentation for `expect`, `vi` or any general API like workspaces or type testing, refer to the ["Getting Started" guide](/guide/). +::: + Vitest UI Vitest UI @@ -51,7 +55,7 @@ bun add -D vitest @vitest/browser ::: warning However, to run tests in CI you need to install either [`playwright`](https://npmjs.com/package/playwright) or [`webdriverio`](https://www.npmjs.com/package/webdriverio). We also recommend switching to either one of them for testing locally instead of using the default `preview` provider since it relies on simulating events instead of using Chrome DevTools Protocol. -If you don't already use one of these tools, we recommend starting with Playwright because it supports parallel execution, which makes your tests run faster. Additionally, the Chrome DevTools Protocol that Playwright uses is generally faster than WebDriver. +If you don't already use one of these tools, we recommend starting with Playwright because it supports parallel execution, which makes your tests run faster. Additionally, Playwright uses [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/) which is generally faster than WebDriver. ::: tabs key:provider == Playwright @@ -93,7 +97,8 @@ bun add -D vitest @vitest/browser webdriverio To activate browser mode in your Vitest configuration, you can use the `--browser` flag or set the `browser.enabled` field to `true` in your Vitest configuration file. Here is an example configuration using the browser field: -```ts +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' export default defineConfig({ test: { browser: { @@ -114,6 +119,21 @@ Since Vitest 2.1.5, the CLI no longer prints the Vite URL automatically. You can If you have not used Vite before, make sure you have your framework's plugin installed and specified in the config. Some frameworks might require extra configuration to work - check their Vite related documentation to be sure. ::: code-group +```ts [react] +import { defineConfig } from 'vitest/config' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()], + test: { + browser: { + enabled: true, + provider: 'playwright', + name: 'chromium', + } + } +}) +``` ```ts [vue] import { defineConfig } from 'vitest/config' import vue from '@vitejs/plugin-vue' @@ -176,16 +196,11 @@ export default defineConfig({ ``` ::: -::: tip -`react` doesn't require a plugin to work, but `preact` requires [extra configuration](https://preactjs.com/guide/v10/getting-started/#create-a-vite-powered-preact-app) to make aliases work. -::: - If you need to run some tests using Node-based runner, you can define a [workspace](/guide/workspace) file with separate configurations for different testing strategies: {#workspace-config} -```ts -// vitest.workspace.ts +```ts [vitest.workspace.ts] import { defineWorkspace } from 'vitest/config' export default defineWorkspace([ @@ -225,7 +240,7 @@ export default defineWorkspace([ == Playwright You can configure how Vitest [launches the browser](https://playwright.dev/docs/api/class-browsertype#browser-type-launch) and creates the [page context](https://playwright.dev/docs/api/class-browsercontext) via [`providerOptions`](/config/#browser-provideroptions) field: -```ts +```ts [vitest.config.ts] export default defineConfig({ test: { browser: { @@ -282,9 +297,9 @@ The browser option in Vitest depends on the provider. Vitest will fail, if you p ## TypeScript -By default, TypeScript doesn't recognize providers options and extra `expect` properties. If you don't use any providers, make sure the `@vitest/browser/matchers` is referenced somewhere in your tests, [setup file](/config/#setupfile) or a [config file](/config/file) to pick up the extra `expect` definitions. If you are using custom providers, make sure to add `@vitest/browser/providers/playwright` or `@vitest/browser/providers/webdriverio` to the same file so TypeScript can pick up definitions for custom options: +By default, TypeScript doesn't recognize providers options and extra `expect` properties. If you don't use any providers, make sure the `@vitest/browser/matchers` is referenced somewhere in your tests, [setup file](/config/#setupfile) or a [config file](/config/) to pick up the extra `expect` definitions. If you are using custom providers, make sure to add `@vitest/browser/providers/playwright` or `@vitest/browser/providers/webdriverio` to the same file so TypeScript can pick up definitions for custom options: -::: code-block +::: code-group ```ts [default] /// ``` @@ -294,10 +309,11 @@ By default, TypeScript doesn't recognize providers options and extra `expect` pr ```ts [webdriverio] /// ``` +::: Alternatively, you can also add them to `compilerOptions.types` field in your `tsconfig.json` file. Note that specifying anything in this field will disable [auto loading](https://www.typescriptlang.org/tsconfig/#types) of `@types/*` packages. -::: code-block +::: code-group ```json [default] { "compilerOptions": { @@ -354,11 +370,12 @@ By default, Vitest will automatically open the browser UI for development. Your Headless mode is another option available in the browser mode. In headless mode, the browser runs in the background without a user interface, which makes it useful for running automated tests. The headless option in Vitest can be set to a boolean value to enable or disable headless mode. -When using headless mode, Vitest won't open the UI automatically. If you want to continue using the UI but have tests run headlessly, you can install the [`@vitest/ui`](/guide/ui) package and pass the --ui flag when running Vitest. +When using headless mode, Vitest won't open the UI automatically. If you want to continue using the UI but have tests run headlessly, you can install the [`@vitest/ui`](/guide/ui) package and pass the `--ui` flag when running Vitest. Here's an example configuration enabling headless mode: -```ts +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' export default defineConfig({ test: { browser: { diff --git a/docs/guide/browser/interactivity-api.md b/docs/guide/browser/interactivity-api.md index db7576d788a5..c41610c26dbc 100644 --- a/docs/guide/browser/interactivity-api.md +++ b/docs/guide/browser/interactivity-api.md @@ -12,7 +12,7 @@ import { userEvent } from '@vitest/browser/context' await userEvent.click(document.querySelector('.button')) ``` -Almost every `userEvent` method inherits its provider options. To see all available options in your IDE, add `webdriver` or `playwright` types (depending on your provider) to your [setup file](/config/#setupfile) or a [config file](/config/file) (depending on what is in `included` in your `tsconfig.json`): +Almost every `userEvent` method inherits its provider options. To see all available options in your IDE, add `webdriver` or `playwright` types (depending on your provider) to your [setup file](/config/#setupfile) or a [config file](/config/) (depending on what is in `included` in your `tsconfig.json`): ::: code-group ```ts [playwright] diff --git a/docs/guide/browser/why.md b/docs/guide/browser/why.md index b7cbc3e95d9d..73201e7c6bbb 100644 --- a/docs/guide/browser/why.md +++ b/docs/guide/browser/why.md @@ -1,9 +1,9 @@ --- -title: Why Browser Mode? | Browser Mode +title: Why Browser Mode | Browser Mode outline: deep --- -# Why Browser Mode? +# Why Browser Mode ## Motivation diff --git a/docs/guide/cli-generated.md b/docs/guide/cli-generated.md index 27d7d0160e3b..59ad0d904a9b 100644 --- a/docs/guide/cli-generated.md +++ b/docs/guide/cli-generated.md @@ -677,12 +677,96 @@ Stop test execution when given number of tests have failed (default: `0`) Retry the test specific number of times if it fails (default: `0`) -### diff +### diff.aAnnotation -- **CLI:** `--diff ` -- **Config:** [diff](/config/#diff) +- **CLI:** `--diff.aAnnotation ` +- **Config:** [diff.aAnnotation](/config/#diff-aannotation) -Path to a diff config that will be used to generate diff interface +Annotation for expected lines (default: `Expected`) + +### diff.aIndicator + +- **CLI:** `--diff.aIndicator ` +- **Config:** [diff.aIndicator](/config/#diff-aindicator) + +Indicator for expected lines (default: `-`) + +### diff.bAnnotation + +- **CLI:** `--diff.bAnnotation ` +- **Config:** [diff.bAnnotation](/config/#diff-bannotation) + +Annotation for received lines (default: `Received`) + +### diff.bIndicator + +- **CLI:** `--diff.bIndicator ` +- **Config:** [diff.bIndicator](/config/#diff-bindicator) + +Indicator for received lines (default: `+`) + +### diff.commonIndicator + +- **CLI:** `--diff.commonIndicator ` +- **Config:** [diff.commonIndicator](/config/#diff-commonindicator) + +Indicator for common lines (default: ` `) + +### diff.contextLines + +- **CLI:** `--diff.contextLines ` +- **Config:** [diff.contextLines](/config/#diff-contextlines) + +Number of lines of context to show around each change (default: `5`) + +### diff.emptyFirstOrLastLinePlaceholder + +- **CLI:** `--diff.emptyFirstOrLastLinePlaceholder ` +- **Config:** [diff.emptyFirstOrLastLinePlaceholder](/config/#diff-emptyfirstorlastlineplaceholder) + +Placeholder for an empty first or last line (default: `""`) + +### diff.expand + +- **CLI:** `--diff.expand` +- **Config:** [diff.expand](/config/#diff-expand) + +Expand all common lines (default: `true`) + +### diff.includeChangeCounts + +- **CLI:** `--diff.includeChangeCounts` +- **Config:** [diff.includeChangeCounts](/config/#diff-includechangecounts) + +Include comparison counts in diff output (default: `false`) + +### diff.omitAnnotationLines + +- **CLI:** `--diff.omitAnnotationLines` +- **Config:** [diff.omitAnnotationLines](/config/#diff-omitannotationlines) + +Omit annotation lines from the output (default: `false`) + +### diff.printBasicPrototype + +- **CLI:** `--diff.printBasicPrototype` +- **Config:** [diff.printBasicPrototype](/config/#diff-printbasicprototype) + +Print basic prototype Object and Array (default: `true`) + +### diff.truncateThreshold + +- **CLI:** `--diff.truncateThreshold ` +- **Config:** [diff.truncateThreshold](/config/#diff-truncatethreshold) + +Number of lines to show before and after each change (default: `0`) + +### diff.truncateAnnotation + +- **CLI:** `--diff.truncateAnnotation ` +- **Config:** [diff.truncateAnnotation](/config/#diff-truncateannotation) + +Annotation for truncated lines (default: `... Diff result is truncated`) ### exclude @@ -759,7 +843,7 @@ The name of the project to run if you are using Vitest workspace feature. This c - **CLI:** `--slowTestThreshold ` - **Config:** [slowTestThreshold](/config/#slowtestthreshold) -Threshold in milliseconds for a test to be considered slow (default: `300`) +Threshold in milliseconds for a test or suite to be considered slow (default: `300`) ### teardownTimeout diff --git a/docs/guide/cli.md b/docs/guide/cli.md index ba46c7b1270f..b4ac323c2187 100644 --- a/docs/guide/cli.md +++ b/docs/guide/cli.md @@ -44,8 +44,7 @@ vitest related /src/index.ts /src/hello-world.js ::: tip Don't forget that Vitest runs with enabled watch mode by default. If you are using tools like `lint-staged`, you should also pass `--run` option, so that command can exit normally. -```js -// .lintstagedrc.js +```js [.lintstagedrc.js] export default { '*.{js,ts}': 'vitest related --run', } diff --git a/docs/guide/common-errors.md b/docs/guide/common-errors.md index a5f5044af6a9..47f40e9fbbea 100644 --- a/docs/guide/common-errors.md +++ b/docs/guide/common-errors.md @@ -49,8 +49,7 @@ This error happens when `vi.mock` method is called on a module that was already Remember that `vi.mock` is always hoisted - it means that the module was loaded before the test file started executing - most likely in a setup file. To fix the error, remove the import or clear the cache at the end of a setup file - beware that setup file and your test file will reference different modules in that case. -```ts -// setupFile.js +```ts [setupFile.js] import { vi } from 'vitest' import { sideEffect } from './mocked-file.js' diff --git a/docs/guide/coverage.md b/docs/guide/coverage.md index d29c77f5d893..6ad6d19e4ec9 100644 --- a/docs/guide/coverage.md +++ b/docs/guide/coverage.md @@ -12,8 +12,7 @@ Both `v8` and `istanbul` support are optional. By default, `v8` will be used. You can select the coverage tool by setting `test.coverage.provider` to `v8` or `istanbul`: -```ts -// vitest.config.ts +```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -29,13 +28,14 @@ When you start the Vitest process, it will prompt you to install the correspondi Or if you prefer to install them manually: -```bash -# For v8 +::: code-group +```bash [v8] npm i -D @vitest/coverage-v8 - -# For istanbul +``` +```bash [istanbul] npm i -D @vitest/coverage-istanbul ``` +::: ## Coverage Setup @@ -47,7 +47,7 @@ This helps Vitest to reduce the amount of files picked by [`coverage.all`](https To test with coverage enabled, you can pass the `--coverage` flag in CLI. By default, reporter `['text', 'html', 'clover', 'json']` will be used. -```json +```json [package.json] { "scripts": { "test": "vitest", @@ -58,8 +58,7 @@ By default, reporter `['text', 'html', 'clover', 'json']` will be used. To configure it, set `test.coverage` options in your config file: -```ts -// vitest.config.ts +```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -75,7 +74,7 @@ export default defineConfig({ You can use custom coverage reporters by passing either the name of the package or absolute path in `test.coverage.reporter`: -```ts +```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -95,8 +94,7 @@ export default defineConfig({ Custom reporters are loaded by Istanbul and must match its reporter interface. See [built-in reporters' implementation](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-reports/lib) for reference. -```js -// custom-reporter.cjs +```js [custom-reporter.cjs] const { ReportBase } = require('istanbul-lib-report') module.exports = class CustomReporter extends ReportBase { @@ -123,8 +121,7 @@ module.exports = class CustomReporter extends ReportBase { It's also possible to provide your custom coverage provider by passing `'custom'` in `test.coverage.provider`: -```ts -// vitest.config.ts +```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -139,8 +136,7 @@ export default defineConfig({ The custom providers require a `customProviderModule` option which is a module name or path where to load the `CoverageProviderModule` from. It must export an object that implements `CoverageProviderModule` as default export: -```ts -// my-custom-coverage-provider.ts +```ts [my-custom-coverage-provider.ts] import type { CoverageProvider, CoverageProviderModule, @@ -176,7 +172,7 @@ Please refer to the type definition for more details. When running a coverage report, a `coverage` folder is created in the root directory of your project. If you want to move it to a different directory, use the `test.coverage.reportsDirectory` property in the `vite.config.js` file. -```js +```js [vitest.config.js] import { defineConfig } from 'vite' export default defineConfig({ diff --git a/docs/guide/features.md b/docs/guide/features.md index 4fbe414eeedc..b67e2f2ace58 100644 --- a/docs/guide/features.md +++ b/docs/guide/features.md @@ -124,16 +124,18 @@ expect(fn.mock.results[1].value).toBe('world') Vitest supports both [happy-dom](https://github.com/capricorn86/happy-dom) or [jsdom](https://github.com/jsdom/jsdom) for mocking DOM and browser APIs. They don't come with Vitest, you will need to install them separately: -```bash +::: code-group +```bash [happy-dom] $ npm i -D happy-dom -# or +``` +```bash [jsdom] $ npm i -D jsdom ``` +::: After that, change the `environment` option in your config file: -```ts -// vitest.config.ts +```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -149,7 +151,7 @@ Learn more at [Mocking](/guide/mocking). Vitest supports Native code coverage via [`v8`](https://v8.dev/blog/javascript-code-coverage) and instrumented code coverage via [`istanbul`](https://istanbul.js.org/). -```json +```json [package.json] { "scripts": { "test": "vitest", @@ -166,9 +168,7 @@ Vitest also provides a way to run tests within your source code along with the i This makes the tests share the same closure as the implementations and able to test against private states without exporting. Meanwhile, it also brings the feedback loop closer for development. -```ts -// src/index.ts - +```ts [src/index.ts] // the implementation export function add(...args: number[]): number { return args.reduce((a, b) => a + b, 0) @@ -191,7 +191,7 @@ Learn more at [In-source testing](/guide/in-source). You can run benchmark tests with [`bench`](/api/#bench) function via [Tinybench](https://github.com/tinylibs/tinybench) to compare performance results. -```ts +```ts [sort.bench.ts] import { bench, describe } from 'vitest' describe('sort', () => { @@ -218,7 +218,7 @@ describe('sort', () => { You can [write tests](/guide/testing-types) to catch type regressions. Vitest comes with [`expect-type`](https://github.com/mmkal/expect-type) package to provide you with a similar and easy to understand API. -```ts +```ts [types.test-d.ts] import { assertType, expectTypeOf, test } from 'vitest' import { mount } from './mount.js' @@ -248,7 +248,7 @@ See [`Improving Performance | Sharding`](/guide/improving-performance#sharding) Vitest exclusively autoloads environment variables prefixed with `VITE_` from `.env` files to maintain compatibility with frontend-related tests, adhering to [Vite's established convention](https://vitejs.dev/guide/env-and-mode.html#env-files). To load every environmental variable from `.env` files anyway, you can use `loadEnv` method imported from `vite`: -```ts +```ts [vitest.config.ts] import { loadEnv } from 'vite' import { defineConfig } from 'vitest/config' diff --git a/docs/guide/in-source.md b/docs/guide/in-source.md index 29822f177841..9a9c2507fbf0 100644 --- a/docs/guide/in-source.md +++ b/docs/guide/in-source.md @@ -16,9 +16,7 @@ This guide explains how to write tests inside your source code. If you need to w To get started, put a `if (import.meta.vitest)` block at the end of your source file and write some tests inside it. For example: -```ts -// src/index.ts - +```ts [src/index.ts] // the implementation export function add(...args: number[]) { return args.reduce((a, b) => a + b, 0) @@ -37,8 +35,7 @@ if (import.meta.vitest) { Update the `includeSource` config for Vitest to grab the files under `src/`: -```ts -// vitest.config.ts +```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -58,8 +55,7 @@ $ npx vitest For the production build, you will need to set the `define` options in your config file, letting the bundler do the dead code elimination. For example, in Vite -```ts -// vitest.config.ts +```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -77,8 +73,7 @@ export default defineConfig({
unbuild -```ts -// build.config.ts +```ts [build.config.ts] import { defineBuildConfig } from 'unbuild' export default defineBuildConfig({ @@ -96,8 +91,7 @@ Learn more: [unbuild](https://github.com/unjs/unbuild)
Rollup -```ts -// rollup.config.js +```ts [rollup.config.js] import replace from '@rollup/plugin-replace' // [!code ++] export default { @@ -118,8 +112,7 @@ Learn more: [Rollup](https://rollupjs.org/) To get TypeScript support for `import.meta.vitest`, add `vitest/importMeta` to your `tsconfig.json`: -```json -// tsconfig.json +```json [tsconfig.json] { "compilerOptions": { "types": [ diff --git a/docs/guide/index.md b/docs/guide/index.md index 23df99383a9d..e0e4fac1ed72 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -47,15 +47,13 @@ The `npx` tool will execute the specified command. By default, `npx` will first As an example, we will write a simple test that verifies the output of a function that adds two numbers. -``` js -// sum.js +``` js [sum.js] export function sum(a, b) { return a + b } ``` -``` js -// sum.test.js +``` js [sum.test.js] import { expect, test } from 'vitest' import { sum } from './sum.js' @@ -65,12 +63,12 @@ test('adds 1 + 2 to equal 3', () => { ``` ::: tip -By default, tests must contain ".test." or ".spec." in their file name. +By default, tests must contain `.test.` or `.spec.` in their file name. ::: Next, in order to execute the test, add the following section to your `package.json`: -```json +```json [package.json] { "scripts": { "test": "vitest" @@ -108,7 +106,7 @@ Vitest supports the same extensions for your configuration file as Vite does: `. If you are not using Vite as your build tool, you can configure Vitest using the `test` property in your config file: -```ts +```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -124,7 +122,7 @@ Even if you do not use Vite yourself, Vitest relies heavily on it for its transf If you are already using Vite, add `test` property in your Vite config. You'll also need to add a reference to Vitest types using a [triple slash directive](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types-) at the top of your config file. -```ts +```ts [vite.config.ts] /// import { defineConfig } from 'vite' @@ -137,7 +135,7 @@ export default defineConfig({ The `` will stop working in Vitest 3, but you can start migrating to `vitest/config` in Vitest 2.1: -```ts +```ts [vite.config.ts] /// import { defineConfig } from 'vite' @@ -181,7 +179,7 @@ However, we recommend using the same file for both Vite and Vitest, instead of c Run different project configurations inside the same project with [Vitest Workspaces](/guide/workspace). You can define a list of files and folders that define your workspace in `vitest.workspace` file. The file supports `js`/`ts`/`json` extensions. This feature works great with monorepo setups. -```ts +```ts [vitest.workspace.ts] import { defineWorkspace } from 'vitest/config' export default defineWorkspace([ @@ -216,7 +214,7 @@ export default defineWorkspace([ In a project where Vitest is installed, you can use the `vitest` binary in your npm scripts, or run it directly with `npx vitest`. Here are the default npm scripts in a scaffolded Vitest project: -```json +```json [package.json] { "scripts": { "test": "vitest", diff --git a/docs/guide/mocking.md b/docs/guide/mocking.md index 9afefe9706ac..db60491ac11e 100644 --- a/docs/guide/mocking.md +++ b/docs/guide/mocking.md @@ -175,22 +175,22 @@ Vitest supports mocking Vite [virtual modules](https://vitejs.dev/guide/api-plug 1. Provide an alias -```ts -// vitest.config.js -export default { +```ts [vitest.config.js] +import { defineConfig } from 'vitest/config' +export default defineConfig({ test: { alias: { - '$app/forms': resolve('./mocks/forms.js') - } - } -} + '$app/forms': resolve('./mocks/forms.js'), + }, + }, +}) ``` 2. Provide a plugin that resolves a virtual module -```ts -// vitest.config.js -export default { +```ts [vitest.config.js] +import { defineConfig } from 'vitest/config' +export default defineConfig({ plugins: [ { name: 'virtual-modules', @@ -198,10 +198,10 @@ export default { if (id === '$app/forms') { return 'virtual:$app/forms' } - } - } - ] -} + }, + }, + ], +}) ``` The benefit of the second approach is that you can dynamically create different virtual entrypoints. If you redirect several virtual modules into a single file, then all of them will be affected by `vi.mock`, so make sure to use unique identifiers. @@ -210,7 +210,7 @@ The benefit of the second approach is that you can dynamically create different Beware that it is not possible to mock calls to methods that are called inside other methods of the same file. For example, in this code: -```ts +```ts [foobar.js] export function foo() { return 'foo' } @@ -222,7 +222,7 @@ export function foobar() { It is not possible to mock the `foo` method from the outside because it is referenced directly. So this code will have no effect on the `foo` call inside `foobar` (but it will affect the `foo` call in other modules): -```ts +```ts [foobar.test.ts] import { vi } from 'vitest' import * as mod from './foobar.js' @@ -239,8 +239,7 @@ vi.mock('./foobar.js', async (importOriginal) => { You can confirm this behaviour by providing the implementation to the `foobar` method directly: -```ts -// foobar.test.js +```ts [foobar.test.js] import * as mod from './foobar.js' vi.spyOn(mod, 'foo') @@ -249,8 +248,7 @@ vi.spyOn(mod, 'foo') mod.foobar(mod.foo) ``` -```ts -// foobar.js +```ts [foobar.js] export function foo() { return 'foo' } @@ -382,8 +380,7 @@ module.exports = fs.promises ``` ::: -```ts -// read-hello-world.js +```ts [read-hello-world.js] import { readFileSync } from 'node:fs' export function readHelloWorld(path) { @@ -391,8 +388,7 @@ export function readHelloWorld(path) { } ``` -```ts -// hello-world.test.js +```ts [hello-world.test.js] import { beforeEach, expect, it, vi } from 'vitest' import { fs, vol } from 'memfs' import { readHelloWorld } from './read-hello-world.js' @@ -595,13 +591,12 @@ vi.mock(import('./dog.js'), () => { This method can also be used to pass an instance of a class to a function that accepts the same interface: -```ts -// ./src/feed.ts +```ts [src/feed.ts] function feed(dog: Dog) { // ... } - -// ./tests/dog.test.ts +``` +```ts [tests/dog.test.ts] import { expect, test, vi } from 'vitest' import { feed } from '../src/feed.js' @@ -667,13 +662,11 @@ You can also spy on getters and setters using the same method. I want to… ### Mock exported variables -```js -// some-path.js +```js [example.js] export const getter = 'variable' ``` -```ts -// some-path.test.ts -import * as exports from './some-path.js' +```ts [example.test.ts] +import * as exports from './example.js' vi.spyOn(exports, 'getter', 'get').mockReturnValue('mocked') ``` @@ -686,21 +679,20 @@ vi.spyOn(exports, 'getter', 'get').mockReturnValue('mocked') Don't forget that a `vi.mock` call is hoisted to top of the file. It will always be executed before all imports. ::: -```ts -// ./some-path.js +```ts [example.js] export function method() {} ``` ```ts -import { method } from './some-path.js' +import { method } from './example.js' -vi.mock('./some-path.js', () => ({ +vi.mock('./example.js', () => ({ method: vi.fn() })) ``` 2. Example with `vi.spyOn`: ```ts -import * as exports from './some-path.js' +import * as exports from './example.js' vi.spyOn(exports, 'method').mockImplementation(() => {}) ``` @@ -708,14 +700,13 @@ vi.spyOn(exports, 'method').mockImplementation(() => {}) ### Mock an exported class implementation 1. Example with `vi.mock` and `.prototype`: -```ts -// ./some-path.ts +```ts [example.js] export class SomeClass {} ``` ```ts -import { SomeClass } from './some-path.js' +import { SomeClass } from './example.js' -vi.mock(import('./some-path.js'), () => { +vi.mock(import('./example.js'), () => { const SomeClass = vi.fn() SomeClass.prototype.someMethod = vi.fn() return { SomeClass } @@ -726,7 +717,7 @@ vi.mock(import('./some-path.js'), () => { 2. Example with `vi.spyOn`: ```ts -import * as mod from './some-path.js' +import * as mod from './example.js' const SomeClass = vi.fn() SomeClass.prototype.someMethod = vi.fn() @@ -738,26 +729,23 @@ vi.spyOn(mod, 'SomeClass').mockImplementation(SomeClass) 1. Example using cache: -```ts -// some-path.ts +```ts [example.js] export function useObject() { return { method: () => true } } ``` -```ts -// useObject.js -import { useObject } from './some-path.js' +```ts [useObject.js] +import { useObject } from './example.js' const obj = useObject() obj.method() ``` -```ts -// useObject.test.js -import { useObject } from './some-path.js' +```ts [useObject.test.js] +import { useObject } from './example.js' -vi.mock(import('./some-path.js'), () => { +vi.mock(import('./example.js'), () => { let _cache const useObject = () => { if (!_cache) { @@ -863,8 +851,7 @@ it('the value is restored before running an other test', () => { }) ``` -```ts -// vitest.config.ts +```ts [vitest.config.ts] export default defineConfig({ test: { unstubEnvs: true, diff --git a/docs/guide/snapshot.md b/docs/guide/snapshot.md index 906cd231d979..a7e33498ee4e 100644 --- a/docs/guide/snapshot.md +++ b/docs/guide/snapshot.md @@ -137,7 +137,7 @@ expect.addSnapshotSerializer({ We also support [snapshotSerializers](/config/#snapshotserializers) option to implicitly add custom serializers. -```ts +```ts [path/to/custom-serializer.ts] import { SnapshotSerializer } from 'vitest' export default { @@ -157,12 +157,12 @@ export default { } satisfies SnapshotSerializer ``` -```ts -import { defineConfig } from 'vite' +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' export default defineConfig({ test: { - snapshotSerializers: ['path/to/custom-serializer.ts'] + snapshotSerializers: ['path/to/custom-serializer.ts'], }, }) ``` @@ -242,14 +242,15 @@ test('snapshot', () => { We believe this is a more reasonable default for readability and overall DX. If you still prefer Jest's behavior, you can change your config: -```ts -// vitest.config.js +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' + export default defineConfig({ test: { snapshotFormat: { - printBasicPrototype: true - } - } + printBasicPrototype: true, + }, + }, }) ``` diff --git a/docs/guide/test-context.md b/docs/guide/test-context.md index 9d0473107425..373f662204e4 100644 --- a/docs/guide/test-context.md +++ b/docs/guide/test-context.md @@ -74,8 +74,7 @@ Like [Playwright](https://playwright.dev/docs/api/class-test#test-extend), you c For example, we first create `myTest` with two fixtures, `todos` and `archive`. -```ts -// my-test.ts +```ts [my-test.ts] import { test } from 'vitest' const todos = [] @@ -98,7 +97,7 @@ export const myTest = test.extend({ Then we can import and use it. -```ts +```ts [my-test.test.ts] import { expect } from 'vitest' import { myTest } from './my-test.js' diff --git a/docs/guide/testing-types.md b/docs/guide/testing-types.md index e26abc1e86e1..49e74ba35f93 100644 --- a/docs/guide/testing-types.md +++ b/docs/guide/testing-types.md @@ -117,7 +117,7 @@ This will pass, because it expects an error, but the word “answer” has a typ ```ts // @ts-expect-error answer is not a string -assertType(answr) // +assertType(answr) ``` ::: @@ -125,7 +125,7 @@ assertType(answr) // To enable typechecking, just add [`--typecheck`](/config/#typecheck) flag to your Vitest command in `package.json`: -```json +```json [package.json] { "scripts": { "test": "vitest --typecheck" diff --git a/docs/guide/ui.md b/docs/guide/ui.md index d3a1881b2c94..156588dea6b0 100644 --- a/docs/guide/ui.md +++ b/docs/guide/ui.md @@ -23,14 +23,14 @@ Then you can visit the Vitest UI at =20.0.0} peerDependencies: vite: ^5.4.0 @@ -8935,6 +8941,10 @@ packages: resolution: {integrity: sha512-HR3W/bMGPSr90i8AAp2C4DM3wChFdJPLrWYpIS++LxS8K+W535qftjt+4MyjNYHeWabMj1nvtmLIi7l++iq91A==} engines: {node: '>=18.17'} + undici@6.21.0: + resolution: {integrity: sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==} + engines: {node: '>=18.17'} + unicode-canonical-property-names-ecmascript@2.0.1: resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} engines: {node: '>=4'} @@ -9201,6 +9211,9 @@ packages: vite: optional: true + vitepress-plugin-group-icons@1.3.0: + resolution: {integrity: sha512-E6Up5HyWh0gxmy2v1v1VVzQpL9UOZuHgoqOmSNBMTRv2rSwg6nk8MeIiJD0tJ0xtWrY5dwG69ENZPyFoD+fVoA==} + vitepress-plugin-tabs@0.5.0: resolution: {integrity: sha512-SIhFWwGsUkTByfc2b279ray/E0Jt8vDTsM1LiHxmCOBAEMmvzIBZSuYYT1DpdDTiS3SuJieBheJkYnwCq/yD9A==} peerDependencies: @@ -9349,8 +9362,8 @@ packages: resolution: {integrity: sha512-jkslwUvOmqhFfc1E21Tz48NgYD8ykiR+09iWZlVLtx3P43k4jOfS+CfasvQ+6hJiVck+N5dXjYfg6zDjpkIFRw==} engines: {node: ^16.13 || >=18} - webdriver@9.2.8: - resolution: {integrity: sha512-40NtUC1zME9tPHNfZv6ETSE3+aE75qZuKjbVAA0gj02AkO1Nl3yJmf5RLdaLLfIQ2WlrbRP1g8KXlkiiVCmakg==} + webdriver@9.4.0: + resolution: {integrity: sha512-DTwAF2t10wxLI6xgWo6KgMdSefCtZT/uJGjhDAaEfs/XB7WwIfHk8SU177f6Rco3+/KEwrIutt1/y8pNhHOn8w==} engines: {node: '>=18.20.0'} webdriverio@8.32.2: @@ -9371,8 +9384,8 @@ packages: devtools: optional: true - webdriverio@9.2.14: - resolution: {integrity: sha512-85yEbwN3MwdrGzKZoGkLUf1J5cpfnc7knL4u/Y6XWd0gGwYjv60I5ZPsgSnXzNXAkq2kmtkammf1AM3ihqFM3A==} + webdriverio@9.4.0: + resolution: {integrity: sha512-qsQv61sebj0pxyFm5ZbRTh4HqF8szWwRrMsTXIVP4GOYgLi9rVD/GwkJqk60QoyTLPI1XJnFf0AxpK+mGJz1rg==} engines: {node: '>=18.20.0'} peerDependencies: puppeteer-core: ^22.3.0 @@ -11252,6 +11265,10 @@ snapshots: dependencies: '@iconify/types': 2.0.0 + '@iconify-json/vscode-icons@1.2.2': + dependencies: + '@iconify/types': 2.0.0 + '@iconify/types@2.0.0': {} '@iconify/utils@2.1.33': @@ -12456,7 +12473,7 @@ snapshots: vite: 5.4.0(@types/node@22.9.0)(terser@5.36.0) vue: 3.5.12(typescript@5.6.3) - '@vitejs/plugin-vue@5.2.0(vite@5.4.0(@types/node@22.9.0)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3))': + '@vitejs/plugin-vue@5.2.1(vite@5.4.0(@types/node@22.9.0)(terser@5.36.0))(vue@3.5.12(typescript@5.6.3))': dependencies: vite: 5.4.0(@types/node@22.9.0)(terser@5.36.0) vue: 3.5.12(typescript@5.6.3) @@ -18313,6 +18330,8 @@ snapshots: undici@6.19.7: {} + undici@6.21.0: {} + unicode-canonical-property-names-ecmascript@2.0.1: {} unicode-match-property-ecmascript@2.0.0: @@ -18623,6 +18642,14 @@ snapshots: optionalDependencies: vite: 5.4.0(@types/node@22.9.0)(terser@5.36.0) + vitepress-plugin-group-icons@1.3.0: + dependencies: + '@iconify-json/logos': 1.2.3 + '@iconify-json/vscode-icons': 1.2.2 + '@iconify/utils': 2.1.33 + transitivePeerDependencies: + - supports-color + vitepress-plugin-tabs@0.5.0(vitepress@1.5.0(@algolia/client-search@4.20.0)(@types/node@22.9.0)(@types/react@18.2.79)(postcss@8.4.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.9.0)(terser@5.36.0)(typescript@5.6.3))(vue@3.5.12(typescript@5.6.3)): dependencies: vitepress: 1.5.0(@algolia/client-search@4.20.0)(@types/node@22.9.0)(@types/react@18.2.79)(postcss@8.4.47)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.9.0)(terser@5.36.0)(typescript@5.6.3) @@ -18829,7 +18856,7 @@ snapshots: - supports-color - utf-8-validate - webdriver@9.2.8: + webdriver@9.4.0: dependencies: '@types/node': 20.14.15 '@types/ws': 8.5.13 @@ -18839,6 +18866,7 @@ snapshots: '@wdio/types': 9.2.2 '@wdio/utils': 9.2.8 deepmerge-ts: 7.1.0 + undici: 6.21.0 ws: 8.18.0 transitivePeerDependencies: - bufferutil @@ -18911,7 +18939,7 @@ snapshots: - supports-color - utf-8-validate - webdriverio@9.2.14: + webdriverio@9.4.0: dependencies: '@types/node': 20.14.15 '@types/sinonjs__fake-timers': 8.1.5(patch_hash=ggdsr7nrdrzokhhihsihc2hdja) @@ -18939,7 +18967,7 @@ snapshots: rgb2hex: 0.2.5 serialize-error: 11.0.3 urlpattern-polyfill: 10.0.0 - webdriver: 9.2.8 + webdriver: 9.4.0 transitivePeerDependencies: - bufferutil - supports-color