diff --git a/.vitepress/config.ts b/.vitepress/config.ts index c7752f02..3b05b7ed 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -136,6 +136,12 @@ export default ({ mode }: { mode: string }) => { }, }, + banner: { + id: 'viteplus-alpha', + text: 'Announcing Vite+ Alpha: Open source. Unified. Next-gen.', + url: 'https://voidzero.dev/posts/announcing-vite-plus-alpha?utm_source=vitest&utm_content=top_banner', + }, + carbonAds: { code: 'CW7DVKJE', placement: 'vitestdev', diff --git a/.vitepress/sponsors.ts b/.vitepress/sponsors.ts index daa87ab5..720845f7 100644 --- a/.vitepress/sponsors.ts +++ b/.vitepress/sponsors.ts @@ -6,14 +6,14 @@ export const sponsors: SponsorTier[] = [ size: 'big', items: [ { - name: 'NuxtLabs', - url: 'https://nuxtlabs.com', - img: '/nuxtlabs.svg', + name: 'Vercel', + url: 'https://vercel.com', + img: '/vercel.svg', }, { - name: 'Bolt', - url: 'https://bolt.new', - img: '/bolt.svg', + name: 'Chromatic', + url: 'https://www.chromatic.com/?utm_source=vitest&utm_medium=sponsorship&utm_campaign=vitestSponsorship', + img: '/chromatic.svg', }, { name: 'Zammad', @@ -26,10 +26,11 @@ export const sponsors: SponsorTier[] = [ tier: '铂金赞助商', size: 'big', items: [ + { - name: 'Chromatic', - url: 'https://www.chromatic.com/?utm_source=vitest&utm_medium=sponsorship&utm_campaign=vitestSponsorship', - img: '/chromatic.svg', + name: 'Bolt', + url: 'https://bolt.new', + img: '/bolt.svg', }, ], }, @@ -57,6 +58,11 @@ export const sponsors: SponsorTier[] = [ url: 'https://www.liminity.se/', img: '/liminity.svg', }, + { + name: 'Aerius Ventilation', + url: 'https://aerius.se/', + img: '/aerius.png', + }, ], }, ] diff --git a/.vitepress/theme/Intro.vue b/.vitepress/theme/Intro.vue index 2ee9ce8f..92f6f03c 100644 --- a/.vitepress/theme/Intro.vue +++ b/.vitepress/theme/Intro.vue @@ -21,7 +21,12 @@ 应用测试变得轻而易举。Vitest 基于 Vite 构建,原生支持 Vite 配置,并复用相同的解析和转换。

+<<<<<<< HEAD 即使不使用 Vite,也同样可以使用 Vitest。它兼容 Jest,也同样适用于后端代码。 +======= + You can also use Vitest even if you are not using Vite. It is Jest-compatible + and works for backend code too. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532

了解更多 diff --git a/api/advanced/metadata.md b/api/advanced/metadata.md index 5dd96a0b..84006c88 100644 --- a/api/advanced/metadata.md +++ b/api/advanced/metadata.md @@ -36,9 +36,15 @@ export default { ::: danger BEWARE Vitest 使用不同的方法与 Node.js 进程进行通信。 +<<<<<<< HEAD - 如果 Vitest 在工作线程内运行测试,它将通过[消息端口](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort)发送数据 - 如果 Vitest 使用子进程,数据将通过 [`process.send`](https://nodejs.org/api/process.html#processsendmessage-sendhandle-options-callback) API 作为序列化缓冲区发送 - 如果 Vitest 在浏览器中运行测试,数据将使用 [flatted](https://www.npmjs.com/package/flatted) 包进行字符串化 +======= +- If Vitest runs tests inside worker threads, it will send data via [message port](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) +- If Vitest uses child process, the data will be send as a serialized Buffer via [`process.send`](https://nodejs.org/api/process.html#processsendmessage-sendhandle-options-callback) API +- If Vitest runs tests in the browser, the data will be stringified using [flatted](https://npmx.dev/package/flatted) package +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 该属性也会出现在每个测试的 `json` 报告中,因此请确保数据可以序列化为 JSON。 diff --git a/api/advanced/plugin.md b/api/advanced/plugin.md index 3f94f4b7..9595c9bc 100644 --- a/api/advanced/plugin.md +++ b/api/advanced/plugin.md @@ -11,7 +11,11 @@ outline: deep 本指南假设我们知道如何使用 [Vite 插件](https://vite.dev/guide/api-plugin.html)。 ::: +<<<<<<< HEAD Vitest 自 3.1 版起支持实验性的 `configureVitest` [插件](https://cn.vite.dev/guide/api-plugin) hook。 +======= +Vitest supports a `configureVitest` [plugin](https://vite.dev/guide/api-plugin.html) hook since version 3.1. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ::: code-group ```ts [only vitest] diff --git a/api/advanced/test-project.md b/api/advanced/test-project.md index 23a36920..1dfd4526 100644 --- a/api/advanced/test-project.md +++ b/api/advanced/test-project.md @@ -51,7 +51,11 @@ export default defineConfig({ ::: ::: info +<<<<<<< HEAD 如果 [根项目](/api/advanced/vitest#getroottestproject) 不是用户工作区的一部分,则不会解析其 `name`。 +======= +If the [root project](/api/advanced/vitest#getrootproject) is not part of user projects, its `name` will not be resolved. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ::: ## vitest @@ -78,7 +82,11 @@ project.serializedConfig === project.serializedConfig // ❌ ## globalConfig +<<<<<<< HEAD [`Vitest`](/api/advanced/vitest) 初始化时的测试配置。如果这是 [根项目](/api/advanced/vitest#getroottestproject),`globalConfig` 和 `config` 将引用同一个对象。此配置对于无法在项目级别设置的值非常有用,例如 `coverage` 或 `reporters`。 +======= +The test config that [`Vitest`](/api/advanced/vitest) was initialized with. If this is the [root project](/api/advanced/vitest#getrootproject), `globalConfig` and `config` will reference the same object. This config is useful for values that cannot be set on the project level, like `coverage` or `reporters`. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```ts import type { ResolvedConfig } from 'vitest/node' @@ -206,7 +214,11 @@ await vitest.runTestSpecifications([specification]) function isRootProject(): boolean ``` +<<<<<<< HEAD 检查当前项目是否为根项目。我们也可以通过调用 [`vitest.getRootProject()`](#getrootproject) 获取根项目。 +======= +Checks if the current project is the root project. You can also get the root project by calling [`vitest.getRootProject()`](/api/advanced/vitest#getrootproject). +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ## globTestFiles @@ -233,7 +245,11 @@ project.globTestFiles(['basic/foo.js:10']) // ❌ ``` ::: tip +<<<<<<< HEAD Vitest 使用 [fast-glob](https://www.npmjs.com/package/fast-glob) 来查找测试文件。`test.dir`、`test.root`、`root` 或 `process.cwd()` 定义了 `cwd` 选项。 +======= +Vitest uses [fast-glob](https://npmx.dev/package/fast-glob) to find test files. `test.dir`, `test.root`, `root` or `process.cwd()` define the `cwd` option. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 此方法查看多个配置选项: diff --git a/api/advanced/vitest.md b/api/advanced/vitest.md index 749be3a3..1fb1491f 100644 --- a/api/advanced/vitest.md +++ b/api/advanced/vitest.md @@ -351,7 +351,11 @@ function collectTests( function cancelCurrentRun(reason: CancelReason): Promise ``` +<<<<<<< HEAD 此方法将优雅地取消所有正在进行的测试。它将等待已启动的测试完成运行,并且不会运行已计划运行但尚未启动的测试。 +======= +This method will gracefully cancel all ongoing tests. It will stop the on-going tests and will not run tests that were scheduled to run but haven't started yet. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ## setGlobalTestNamePattern diff --git a/api/browser/assertions.md b/api/browser/assertions.md index af28e165..1db6fd12 100644 --- a/api/browser/assertions.md +++ b/api/browser/assertions.md @@ -370,7 +370,11 @@ await expect.element(getByTestId('parent')).toContainHTML('') ::: warning 你可能不需要使用这个匹配器。我们鼓励从用户在浏览器中感知应用程序的角度进行测试。这就是为什么不建议针对特定的 DOM 结构进行测试。 +<<<<<<< HEAD 在某些情况下,被测试的代码会渲染从外部来源获取的 HTML,而你希望验证该 HTML 代码是否按预期使用。 +======= +It could be useful in situations where the code being tested renders html that was obtained from an external source, and you want to validate that html code was used as intended. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 不应使用它来检查你控制的 DOM 结构。请改用 [`toContainElement`](#tocontainelement)。 ::: @@ -1077,9 +1081,15 @@ await expect.element(getByTestId('button')).toMatchScreenshot('fancy-button', { - `comparatorName: "pixelmatch" = "pixelmatch"` +<<<<<<< HEAD 用于比较图像的算法/库名称。 目前,仅支持 [“pixelmatch”](https://github.com/mapbox/pixelmatch)。 +======= + The algorithm/library used for comparing images. + + `"pixelmatch"` is the only built-in comparator, but you can use custom ones by [registering them in the config file](/config/browser/expect#browser-expect-tomatchscreenshot-comparators). +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 - `comparatorOptions: object` @@ -1130,7 +1140,11 @@ await expect.element(getByTestId('button')).toMatchScreenshot('fancy-button', { #### `"pixelmatch"` comparator options +<<<<<<< HEAD 使用 `"pixelmatch"` 比较器时,以下选项可用: +======= +The `"pixelmatch"` comparator uses [`@blazediff/core`](https://blazediff.dev/docs/core) under the hood. The following options are available when using it: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 - `allowedMismatchedPixelRatio: number | undefined = undefined` diff --git a/api/browser/context.md b/api/browser/context.md index 65e8e2d7..b7ed52cf 100644 --- a/api/browser/context.md +++ b/api/browser/context.md @@ -78,7 +78,19 @@ export const page: { base64: string }>) & ((options?: ScreenshotOptions) => Promise) /** +<<<<<<< HEAD * 使用自定义方法扩展默认的 `page` 对象。 +======= + * Add a trace marker when browser tracing is enabled. + */ + mark(name: string, options?: { stack?: string }): Promise + /** + * Group multiple operations under a trace marker when browser tracing is enabled. + */ + mark(name: string, body: () => T | Promise, options?: { stack?: string }): Promise + /** + * Extend default `page` object with custom methods. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 */ extend: (methods: Partial) => BrowserPage /** @@ -114,6 +126,40 @@ export const page: { 在这种情况下,`path` 也会被忽略。 ::: +### mark + +```ts +function mark(name: string, options?: { stack?: string }): Promise +function mark( + name: string, + body: () => T | Promise, + options?: { stack?: string }, +): Promise +``` + +Adds a named marker to the trace timeline for the current test. + +Pass `options.stack` to override the callsite location in trace metadata. This is useful for wrapper libraries that need to preserve the end-user source location. + +If you pass a callback, Vitest creates a trace group with this name, runs the callback, and closes the group automatically. + +```ts +import { page } from 'vitest/browser' + +await page.mark('before submit') +await page.getByRole('button', { name: 'Submit' }).click() +await page.mark('after submit') + +await page.mark('submit flow', async () => { + await page.getByRole('textbox', { name: 'Email' }).fill('john@example.com') + await page.getByRole('button', { name: 'Submit' }).click() +}) +``` + +::: tip +This method is useful only when [`browser.trace`](/config/browser/trace) is enabled. +::: + ### frameLocator ```ts @@ -246,7 +292,7 @@ utils.configurePrettyDOM({ - **`maxLength`** - Maximum length of the output string (default: `7000`) - **`filterNode`** - A CSS selector string or function to filter out nodes from the output. When a string is provided, elements matching the selector will be excluded. When a function is provided, it should return `false` to exclude a node. - **`highlight`** - Enable syntax highlighting (default: `true`) -- And other options from [`pretty-format`](https://www.npmjs.com/package/@vitest/pretty-format) +- And other options from [`pretty-format`](https://npmx.dev/package/@vitest/pretty-format) #### Filtering with CSS Selectors 4.1.0 {#filtering-with-css-selectors} diff --git a/api/browser/locators.md b/api/browser/locators.md index aef07a49..a255eea8 100644 --- a/api/browser/locators.md +++ b/api/browser/locators.md @@ -7,7 +7,11 @@ outline: [2, 3] 定位器是表示一个或多个元素的方式。每个定位器都由一个称为选择器的字符串定义。Vitest 通过提供方便的方法在后台生成这些选择器,从而抽象了选择器。 +<<<<<<< HEAD 定位器 API 使用了 [Playwright 的定位器](https://playwright.dev/docs/api/class-locator) 的一个分支,称为 [Ivya](https://npmjs.com/ivya)。然而,Vitest 将此 API 提供给每个 [provider](/config/browser/provider)。 +======= +The locator API uses a fork of [Playwright's locators](https://playwright.dev/docs/api/class-locator) called [Ivya](https://npmx.dev/ivya). However, Vitest provides this API to every [provider](/config/browser/provider), not just playwright. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ::: tip 本页介绍了 API 的使用。为了更好地了解定位器及其用法,请阅读 [Playwright 的“定位器”文档](https://playwright.dev/docs/locators)。 @@ -65,7 +69,7 @@ await page.getByRole('button', { name: /submit/i }).click() 根据 ARIA 指南,**强烈不建议** 通过 `role` 或 `aria-*` 属性为已经具有隐式角色的内置元素提供角色。 ::: -##### Options +**Options** - `exact: boolean` @@ -189,7 +193,11 @@ await page.getByRole('button', { name: /submit/i }).click() page.getByRole('button', { selected: false }) // ❌ ``` +<<<<<<< HEAD ##### 更多内容请参阅 {#see-also} +======= +**See also** +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 - [MDN 上的 ARIA 角色列表](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles) - [w3.org 上的 ARIA 角色列表](https://www.w3.org/TR/wai-aria-1.2/#role_definitions) @@ -213,13 +221,17 @@ page.getByAltText(/incredibles.*? poster/i) // ✅ page.getByAltText('non existing alt text') // ❌ ``` -#### Options +**Options** - `exact: boolean` `text` 是否精确匹配:区分大小写且完全匹配字符串。默认情况下禁用此选项。如果 `text` 是正则表达式,则忽略此选项。请注意,精确匹配仍然会修剪空白字符。 +<<<<<<< HEAD #### 更多内容请参阅 {#see-also-1} +======= +**See also** +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 - [testing-library's `ByAltText`](https://testing-library.com/docs/queries/byalttext/) @@ -260,13 +272,17 @@ function getByLabelText( ``` -#### Options +**Options** - `exact: boolean` `text` 是否精确匹配:区分大小写且完全匹配字符串。默认情况下禁用此选项。如果 `text` 是正则表达式,则忽略此选项。请注意,精确匹配仍然会修剪空白字符。 +<<<<<<< HEAD #### 更多内容请参阅 {#see-also-2} +======= +**See also** +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 - [testing-library's `ByLabelText`](https://testing-library.com/docs/queries/bylabeltext/) @@ -292,13 +308,17 @@ page.getByPlaceholder('not found') // ❌ 通常情况下,使用 [`getByLabelText`](#getbylabeltext) 依赖标签比依赖占位符更好。 ::: -#### Options +**Options** - `exact: boolean` `text` 是否精确匹配:区分大小写且完全匹配字符串。默认情况下禁用此选项。如果 `text` 是正则表达式,则忽略此选项。请注意,精确匹配仍然会修剪空白字符。 +<<<<<<< HEAD #### 更多内容请参阅 {#see-also-3} +======= +**See also** +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 - [testing-library's `ByPlaceholderText`](https://testing-library.com/docs/queries/byplaceholdertext/) @@ -324,13 +344,17 @@ page.getByText('about', { exact: true }) // ❌ 此定位器适用于定位非交互式元素。如果你需要定位交互式元素,比如按钮或输入框,建议使用 [`getByRole`](#getbyrole)。 ::: -#### Options +**Options** - `exact: boolean` `text` 是否精确匹配:区分大小写且完全匹配字符串。默认情况下禁用此选项。如果 `text` 是正则表达式,则忽略此选项。请注意,精确匹配仍然会修剪空白字符。 +<<<<<<< HEAD #### 更多内容请参阅 {#see-also-4} +======= +**See also** +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 - [testing-library's `ByText`](https://testing-library.com/docs/queries/bytext/) @@ -352,13 +376,17 @@ page.getByTitle('Delete') // ✅ page.getByTitle('Create') // ❌ ``` -#### Options +**Options** - `exact: boolean` `text` 是否精确匹配:区分大小写且完全匹配字符串。默认情况下禁用此选项。如果 `text` 是正则表达式,则忽略此选项。请注意,精确匹配仍然会修剪空白字符。 +<<<<<<< HEAD #### 更多内容请参阅 {#see-also-5} +======= +**See also** +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 - [testing-library's `ByTitle`](https://testing-library.com/docs/queries/bytitle/) @@ -381,13 +409,17 @@ page.getByTestId('non-existing-element') // ❌ 建议仅在其他定位器不适用于你的使用场景时才使用此方法。使用 `data-testid` 属性并不符合用户实际使用软件的方式,因此如果可能应避免使用。 ::: -#### Options +**Options** - `exact: boolean` `text` 是否精确匹配:区分大小写和整个字符串。默认情况下禁用此选项。如果 `text` 是正则表达式,则忽略此选项。请注意,精确匹配仍然会修剪空格。 +<<<<<<< HEAD #### 更多内容请参阅 {#see-also-6} +======= +**See also** +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 - [testing-library's `ByTestId`](https://testing-library.com/docs/queries/bytestid/) @@ -821,6 +853,30 @@ const { path, base64 } = await button.screenshot({ 注意,当 `save` 设置为 `false` 时,`screenshot` 将始终返回 base64 字符串。在此情况下,路径参数也会被忽略。 ::: +### mark + +```ts +function mark(name: string, options?: { stack?: string }): Promise +``` + +Adds a named marker to the trace timeline and uses the current locator as marker context. + +Pass `options.stack` to override the callsite location in trace metadata. This is useful for wrapper libraries that need to preserve the end-user source location. + +```ts +import { page } from 'vitest/browser' + +const submitButton = page.getByRole('button', { name: 'Submit' }) + +await submitButton.mark('before submit') +await submitButton.click() +await submitButton.mark('after submit') +``` + +::: tip +This method is useful only when [`browser.trace`](/config/browser/trace) is enabled. +::: + ### query ```ts @@ -940,6 +996,63 @@ page.getByText('Hello').elements() // ✅ [HTMLElement, HTMLElement] page.getByText('Hello USA').elements() // ✅ [] ``` +### findElement 4.1.0 {#findelement} + +```ts +function findElement( + options?: SelectorOptions +): Promise +``` + +::: danger WARNING +This is an escape hatch for cases where you need the raw DOM element — for example, to pass it to a third-party library like FormKit that doesn't accept Vitest locators. If you are interacting with the element yourself, use other [builtin methods](#methods) instead. +::: + +This method returns an element matching the locator. Unlike [`.element()`](#element), this method will wait and retry until a matching element appears in the DOM, using increasing intervals (0, 20, 50, 100, 100, 500ms). + +If _no element_ is found before the timeout, an error is thrown. By default, the timeout matches the test timeout. + +If _multiple elements_ match the selector and `strict` is `true` (the default), an error is thrown immediately without retrying. Set `strict` to `false` to return the first matching element instead. + +It accepts options: + +- `timeout: number` - How long to wait in milliseconds until at least one element is found. By default, this shares timeout with the test. +- `strict: boolean` - When `true` (default), throws an error if multiple elements match the locator. When `false`, returns the first matching element. + +Consider the following DOM structure: + +```html +
Hello World
+
Hello Germany
+
Hello
+``` + +These locators will resolve successfully: + +```ts +await page.getByText('Hello World').findElement() // ✅ HTMLDivElement +await page.getByText('World').findElement() // ✅ HTMLSpanElement +await page.getByText('Hello Germany').findElement() // ✅ HTMLDivElement +``` + +These locators will throw an error: + +```ts +// multiple elements match, strict mode rejects +await page.getByText('Hello').findElement() // ❌ +await page.getByText(/^Hello/).findElement() // ❌ + +// no matching element before timeout +await page.getByText('Hello USA').findElement() // ❌ +``` + +Using `strict: false` to allow multiple matches: + +```ts +// returns the first matching element instead of throwing +await page.getByText('Hello').findElement({ strict: false }) // ✅ HTMLDivElement +``` + ### all ```ts diff --git a/api/browser/react.md b/api/browser/react.md index fa0b4301..e3bd4baa 100644 --- a/api/browser/react.md +++ b/api/browser/react.md @@ -4,7 +4,11 @@ outline: deep # vitest-browser-react +<<<<<<< HEAD 由社区提供的 [`vitest-browser-react`](https://www.npmjs.com/package/vitest-browser-react) 包可在 [浏览器模式](/guide/browser/) 中渲染 [React](https://zh-hans.react.dev/) 组件。 +======= +The community [`vitest-browser-react`](https://npmx.dev/package/vitest-browser-react) package renders [React](https://react.dev/) components in [Browser Mode](/guide/browser/). +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```jsx import { render } from 'vitest-browser-react' @@ -39,6 +43,8 @@ export function render( ): Promise ``` +The `render` function records a `react.render` trace mark, visible in the [Trace View](/guide/browser/trace-view). + :::warning 请注意,与其他包不同,为了支持 [`Suspense`](https://react.dev/reference/react/Suspense) 功能,此处的 `render` 是异步方法。 @@ -154,7 +160,13 @@ function debug( function rerender(ui: React.ReactNode): Promise ``` +<<<<<<< HEAD 其最佳实践是测试负责更新属性的组件本身,以确保属性更新逻辑正确,从而避免测试代码依赖于实现细节。如果需要在测试过程中更新已渲染组件的属性,当前函数可用于实现该需求。 +======= +Also records a `react.rerender` trace mark in the [Trace View](/guide/browser/trace-view). + +It is better if you test the component that's doing the prop updating to ensure that the props are being updated correctly to avoid relying on implementation details in your tests. That said, if you'd prefer to update the props of a rendered component in your test, this function can be used to update props of the rendered component. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```jsx import { render } from 'vitest-browser-react' @@ -171,7 +183,13 @@ await rerender() function unmount(): Promise ``` +<<<<<<< HEAD 此操作将会把已渲染的组件卸载。该特性适用于测试组件从页面移除时的行为(例如验证是否残留未清除的事件处理器,避免引发内存泄漏)。 +======= +Also records a `react.unmount` trace mark in the [Trace View](/guide/browser/trace-view). + +This will cause the rendered component to be unmounted. This is useful for testing what happens when your component is removed from the page (like testing that you don't leave event handlers hanging around causing memory leaks). +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```jsx import { render } from 'vitest-browser-react' diff --git a/api/browser/svelte.md b/api/browser/svelte.md index 3f71a69a..16fdef27 100644 --- a/api/browser/svelte.md +++ b/api/browser/svelte.md @@ -4,7 +4,11 @@ outline: deep # vitest-browser-svelte +<<<<<<< HEAD 由社区提供的 [`vitest-browser-svelte`](https://www.npmjs.com/package/vitest-browser-svelte) 包可在 [浏览器模式](/guide/browser/) 中渲染 [Svelte](https://svelte.dev/) 组件。 +======= +The community [`vitest-browser-svelte`](https://npmx.dev/package/vitest-browser-svelte) package renders [Svelte](https://svelte.dev/) components in [Browser Mode](/guide/browser/). +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```ts import { render } from 'vitest-browser-svelte' @@ -12,7 +16,7 @@ import { expect, test } from 'vitest' import Component from './Component.svelte' test('counter button increments the count', async () => { - const screen = render(Component, { + const screen = await render(Component, { initialCount: 1, }) @@ -39,15 +43,30 @@ export function render( Component: ComponentImport, options?: ComponentOptions, renderOptions?: SetupOptions -): RenderResult +): RenderResult & PromiseLike> ``` +<<<<<<< HEAD ### 选项 {#options} +======= +The `render` function records a `svelte.render` trace mark, visible in the [Trace View](/guide/browser/trace-view). + +::: warning +Synchronous usage of `render` is deprecated and will be removed in the next major version. Please always `await` the result: + +```ts +const screen = render(Component) // [!code --] +const screen = await render(Component) // [!code ++] +``` +::: + +### Options +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 `render` 函数支持两种传参方式,一种是向 [`mount`](https://svelte.dev/docs/svelte/imperative-component-api#mount) 传入配置选项,另一种则是直接向组件传入属性: ```ts -const screen = render(Component, { +const screen = await render(Component, { props: { // [!code --] initialCount: 1, // [!code --] }, // [!code --] @@ -68,7 +87,7 @@ const screen = render(Component, { ```ts const table = document.createElement('table') -const screen = render(TableBody, { +const screen = await render(TableBody, { props, // ⚠️ 渲染前需手动将元素添加到 `body` target: document.body.appendChild(table), @@ -86,7 +105,7 @@ const screen = render(TableBody, { 除文档记载的返回值外,`render` 函数还会返回相对于 [`baseElement`](#baseelement) 的所有可用 [定位器](/api/browser/locators),包括 [自定义定位器](/api/browser/locators#custom-locators)。 ```ts -const screen = render(TableBody, props) +const screen = await render(TableBody, props) await screen.getByRole('link', { name: 'Expand' }).click() ``` @@ -104,7 +123,7 @@ Svelte 组件将被渲染到 `container` 这个 DOM 容器中。这是一个常 已挂载的 Svelte 组件实例。如需访问组件方法和属性,可通过此实例进行操作。 ```ts -const { component } = render(Counter, { +const { component } = await render(Counter, { initialCount: 0, }) @@ -118,7 +137,7 @@ const { component } = render(Counter, { ```ts import { render } from 'vitest-browser-svelte' -const { locator } = render(NumberDisplay, { +const { locator } = await render(NumberDisplay, { number: 2, }) @@ -139,15 +158,19 @@ function debug( #### rerender ```ts -function rerender(props: Partial>): void +function rerender(props: Partial>): Promise ``` +<<<<<<< HEAD 更新组件属性并等待 Svelte 变更被应用。适用于测试组件属性变化的响应。 +======= +Updates the component's props and waits for Svelte to apply the changes. Use this to test how your component responds to prop changes. Also records a `svelte.rerender` trace mark in the [Trace View](/guide/browser/trace-view). +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```ts import { render } from 'vitest-browser-svelte' -const { rerender } = render(NumberDisplay, { +const { rerender } = await render(NumberDisplay, { number: 1, }) @@ -158,17 +181,31 @@ await rerender({ number: 2 }) #### unmount ```ts -function unmount(): void +function unmount(): Promise ``` +<<<<<<< HEAD 卸载并销毁 Svelte 组件。该特性适用于测试组件从页面移除时的行为(例如验证是否残留未清除的事件处理器,避免引发内存泄漏)。 +======= +Unmount and destroy the Svelte component. Also records a `svelte.unmount` trace mark in the [Trace View](/guide/browser/trace-view). This is useful for testing what happens when your component is removed from the page (like testing that you don't leave event handlers hanging around causing memory leaks). + +::: warning +Synchronous usage of `unmount` is deprecated and will be removed in the next major version. Please always `await` the result. +::: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```ts import { render } from 'vitest-browser-svelte' +<<<<<<< HEAD const { container, unmount } = render(Component) unmount() // 组件已被卸载,此时:container.innerHTML === '' +======= +const { container, unmount } = await render(Component) +await unmount() +// your component has been unmounted and now: container.innerHTML === '' +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ``` ## cleanup @@ -193,7 +230,7 @@ locators.extend({ }, }) -const screen = render(Component) +const screen = await render(Component) await expect.element( screen.getByArticleTitle('Hello World') ).toBeVisible() @@ -211,7 +248,7 @@ import { expect, test } from 'vitest' import SubjectTest from './basic-snippet.test.svelte' test('basic snippet', async () => { - const screen = render(SubjectTest) + const screen = await render(SubjectTest) const heading = screen.getByRole('heading') const child = heading.getByTestId('child') @@ -250,7 +287,7 @@ import { expect, test } from 'vitest' import Subject from './complex-snippet.svelte' test('renders greeting in message snippet', async () => { - const screen = render(Subject, { + const screen = await render(Subject, { name: 'Alice', message: createRawSnippet(greeting => ({ render: () => `${greeting()}`, diff --git a/api/browser/vue.md b/api/browser/vue.md index 49fdc207..c8e79370 100644 --- a/api/browser/vue.md +++ b/api/browser/vue.md @@ -4,7 +4,11 @@ outline: deep # vitest-browser-vue +<<<<<<< HEAD 由社区提供的 [`vitest-browser-vue`](https://www.npmjs.com/package/vitest-browser-vue) 包可在 [浏览器模式](/guide/browser/) 中渲染 [Vue](https://cn.vuejs.org/) 组件。 +======= +The community [`vitest-browser-vue`](https://npmx.dev/package/vitest-browser-vue) package renders [Vue](https://vuejs.org/) components in [Browser Mode](/guide/browser/). +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```ts import { render } from 'vitest-browser-vue' @@ -12,7 +16,7 @@ import { expect, test } from 'vitest' import Component from './Component.vue' test('counter button increments the count', async () => { - const screen = render(Component, { + const screen = await render(Component, { props: { initialCount: 1, } @@ -40,10 +44,25 @@ test('counter button increments the count', async () => { export function render( component: Component, options?: ComponentRenderOptions, -): RenderResult +): RenderResult & PromiseLike ``` +<<<<<<< HEAD ### 选项 {#options} +======= +The `render` function records a `vue.render` trace mark, visible in the [Trace View](/guide/browser/trace-view). + +::: warning +Synchronous usage of `render` is deprecated and will be removed in the next major version. Please always `await` the result: + +```ts +const screen = render(Component) // [!code --] +const screen = await render(Component) // [!code ++] +``` +::: + +### Options +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 `render` 函数支持 `@vue/test-utils` 中 [`mount` 选项](https://test-utils.vuejs.org/api/#mount) 的全部参数(除 `attachTo` 外,需改用 `container`)。此外还额外支持 `container` 和 `baseElement` 参数。 @@ -56,7 +75,7 @@ export function render( ```js const table = document.createElement('table') -const { container } = render(TableBody, { +const { container } = await render(TableBody, { props, // ⚠️ 渲染前需手动将元素添加到 `body` container: document.body.appendChild(table), @@ -72,7 +91,7 @@ const { container } = render(TableBody, { 除文档记载的返回值外,`render` 函数还会返回相对于 [`baseElement`](#baseelement) 的所有可用 [定位器](/api/browser/locators),包括 [自定义定位器](/api/browser/locators#custom-locators)。 ```ts -const screen = render(TableBody, { props }) +const screen = await render(TableBody, { props }) await screen.getByRole('link', { name: 'Expand' }).click() ``` @@ -102,7 +121,7 @@ Vue 组件将被渲染到 `container` 这个 DOM 容器中。如果在调用 ren ```js import { render } from 'vitest-browser-vue' -const { locator } = render(NumberDisplay, { +const { locator } = await render(NumberDisplay, { props: { number: 2 } }) @@ -125,27 +144,50 @@ function debug( #### rerender ```ts -function rerender(props: Partial): void +function rerender(props: Partial): void & PromiseLike ``` +<<<<<<< HEAD 其最佳实践是测试负责更新属性的组件本身,以确保属性更新逻辑正确,从而避免测试代码依赖于实现细节。如果需要在测试过程中更新已渲染组件的属性,当前函数可用于实现该需求。 +======= +Also records a `vue.rerender` trace mark in the [Trace View](/guide/browser/trace-view). + +It is better if you test the component that's doing the prop updating to ensure that the props are being updated correctly to avoid relying on implementation details in your tests. That said, if you'd prefer to update the props of a rendered component in your test, this function can be used to update props of the rendered component. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 + +::: warning +Synchronous usage of `rerender` is deprecated and will be removed in the next major version. Please always `await` the result. +::: ```js import { render } from 'vitest-browser-vue' -const { rerender } = render(NumberDisplay, { props: { number: 1 } }) +const { rerender } = await render(NumberDisplay, { props: { number: 1 } }) +<<<<<<< HEAD // 使用新属性重新渲染同一个组件 rerender({ number: 2 }) +======= +// re-render the same component with different props +await rerender({ number: 2 }) +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ``` #### unmount ```ts -function unmount(): void +function unmount(): void & PromiseLike ``` +<<<<<<< HEAD 此操作将会把已渲染的组件卸载。该特性适用于测试组件从页面移除时的行为(例如验证是否残留未清除的事件处理器,避免引发内存泄漏)。 +======= +This will cause the rendered component to be unmounted. Also records a `vue.unmount` trace mark in the [Trace View](/guide/browser/trace-view). This is useful for testing what happens when your component is removed from the page (like testing that you don't leave event handlers hanging around causing memory leaks). + +::: warning +Synchronous usage of `unmount` is deprecated and will be removed in the next major version. Please always `await` the result. +::: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 #### emitted @@ -182,7 +224,7 @@ locators.extend({ }, }) -const screen = render(Component) +const screen = await render(Component) await expect.element( screen.getByArticleTitle('Hello World') ).toBeVisible() diff --git a/api/expect.md b/api/expect.md index f5da0000..576399d8 100644 --- a/api/expect.md +++ b/api/expect.md @@ -6,7 +6,7 @@ type Awaitable = T | PromiseLike ``` -`expect` 用于创建断言。在此上下文中,`断言` 是可以被调用来验证一个语句的函数。Vitest 默认提供 `chai` 断言,同时也提供基于 chai 构建的兼容 `Jest` 的断言。自 Vitest 4.1 起,在进行 spy/mock 测试时,Vitest 还额外提供了 [Chai 风格断言](#chai-style-spy-assertions)(如 `expect(spy).to.have.been.called()`),与 Jest 风格断言(如 `expect(spy).toHaveBeenCalled()`)并存。与 `Jest` 不同,Vitest 支持将一条消息作为第二个参数传入,如果断言失败,错误信息将等于该消息。 +`expect` is used to create assertions. In this context `assertions` are functions that can be called to assert a statement. Vitest provides `chai` assertions by default and also `Jest` compatible assertions built on top of `chai`. Since Vitest 4.1, for spy/mock testing, Vitest also provides Chai-style assertions (e.g., [`expect(spy).to.have.been.called()`](#called)) alongside Jest-style assertions (e.g., `expect(spy).toHaveBeenCalled()`). Unlike `Jest`, Vitest supports a message as the second argument - if the assertion fails, the error message will be equal to it. ```ts export interface ExpectStatic extends Chai.ExpectStatic, AsymmetricMatchersContaining { @@ -2107,7 +2107,7 @@ test('email validation', () => { 如果需要添加自定义序列化程序,应该在 [`setupFiles`](/config/setupfiles) 中调用此方法。这将影响每个快照。 :::tip -如果以前将 Vue CLI 与 Jest 一起使用,需要安装 [jest-serializer-vue](https://www.npmjs.com/package/jest-serializer-vue)。 否则,快照将被包裹在一个字符串中,其中 `"` 是要转义的。 +如果以前将 Vue CLI 与 Jest 一起使用,需要安装 [jest-serializer-vue](https://npmx.dev/package/jest-serializer-vue)。 否则,的快照将被包裹在一个字符串中,其中 `"` 是要转义的。 ::: ## expect.extend diff --git a/api/test.md b/api/test.md index 9fa7336f..e5983b2e 100644 --- a/api/test.md +++ b/api/test.md @@ -199,7 +199,11 @@ describe( }, ({ task }) => { // task.meta === { nested: { object: false } } +<<<<<<< HEAD // 注意 array 丢失了,因为 "nested" 对象被整体覆盖 +======= + // notice array got lost because "nested" object was overridden +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 } ) } diff --git a/api/vi.md b/api/vi.md index 6ca3d37e..2a77fcea 100644 --- a/api/vi.md +++ b/api/vi.md @@ -1089,7 +1089,7 @@ import { vi } from 'vitest' vi.useFakeTimers() // Manual mode (default) -vi.setTimerTickMode({ mode: 'manual' }) +vi.setTimerTickMode('manual') let i = 0 setInterval(() => console.log(++i), 50) @@ -1097,13 +1097,13 @@ setInterval(() => console.log(++i), 50) vi.advanceTimersByTime(150) // logs 1, 2, 3 // nextTimerAsync mode -vi.setTimerTickMode({ mode: 'nextTimerAsync' }) +vi.setTimerTickMode('nextTimerAsync') // Timers will advance automatically after each macrotask await new Promise(resolve => setTimeout(resolve, 150)) // logs 4, 5, 6 // interval mode (default when 'fakeTimers.shouldAdvanceTime' is `true`) -vi.setTimerTickMode({ mode: 'interval', interval: 50 }) +vi.setTimerTickMode('interval', 50) // Timers will advance automatically every 50ms await new Promise(resolve => setTimeout(resolve, 150)) // logs 7, 8, 9 diff --git a/blog/vitest-3-2.md b/blog/vitest-3-2.md index c26c6d96..cd9019da 100644 --- a/blog/vitest-3-2.md +++ b/blog/vitest-3-2.md @@ -47,7 +47,7 @@ Vitest 3.2 专注于改进浏览器模式和 TypeScript 支持。此版本还包 新的 [注释 API](/guide/test-annotations) 允许你为任何测试添加自定义消息和附件。这些注释在 UI、HTML、junit、tap 和 GitHub Actions 报告器中可见。如果测试失败,Vitest 还会在 CLI 中打印相关注释。 - +an example of annotation with a cute puppy ## 作用域固定装置 {#scoped-fixtures} @@ -106,7 +106,7 @@ export default defineConfig({ ``` ::: - +an example of project names with custom backgrounds ## 自定义浏览器定位器 API {#custom-browser-locators-api} diff --git a/blog/vitest-3.md b/blog/vitest-3.md index 921e55d4..5c829c9d 100644 --- a/blog/vitest-3.md +++ b/blog/vitest-3.md @@ -67,7 +67,7 @@ _2025 年 1 月 17 日_ 你可以在 [#7069](https://github.com/vitest-dev/vitest/pull/7069) PR 中关注设计过程。为了逆向工程之前的 onTaskUpdate API 并实现这个新的优雅生命周期,我们经历了一番艰难的努力。
- + a gif from it's always sunny with a drawing board
## 内联工作区 {#inline-workspace} diff --git a/blog/vitest-4-1.md b/blog/vitest-4-1.md new file mode 100644 index 00000000..ae2b6452 --- /dev/null +++ b/blog/vitest-4-1.md @@ -0,0 +1,483 @@ +--- +title: Vitest 4.1 is out! +author: + name: The Vitest Team +date: 2026-03-12 +sidebar: false +head: + - - meta + - property: og:type + content: website + - - meta + - property: og:title + content: Announcing Vitest 4.1 + - - meta + - property: og:image + content: https://vitest.dev/og-vitest-4-1.jpg + - - meta + - property: og:url + content: https://vitest.dev/blog/vitest-4-1 + - - meta + - property: og:description + content: Vitest 4.1 Release Announcement + - - meta + - name: twitter:card + content: summary_large_image +--- + +# Vitest 4.1 is out! + +_March 12, 2026_ + +![Vitest 4.1 Announcement Cover Image](/og-vitest-4-1.jpg) + +## The next Vitest minor is here + +Today, we are thrilled to announce Vitest 4.1 packed with new exciting features! + +Quick links: + +- [Docs](/) +- Translations: [简体中文](https://cn.vitest.dev/) +- [GitHub Changelog](https://github.com/vitest-dev/vitest/releases/tag/v4.1.0) + +If you've not used Vitest before, we suggest reading the [Getting Started](/guide/) and [Features](/guide/features) guides first. + +We extend our gratitude to the over [713 contributors to Vitest Core](https://github.com/vitest-dev/vitest/graphs/contributors) and to the maintainers and contributors of Vitest integrations, tools, and translations who have helped us develop this new release. We encourage you to get involved and help us improve Vitest for the entire ecosystem. Learn more at our [Contributing Guide](https://github.com/vitest-dev/vitest/blob/main/CONTRIBUTING.md). + +To get started, we suggest helping [triage issues](https://github.com/vitest-dev/vitest/issues), [review PRs](https://github.com/vitest-dev/vitest/pulls), send failing tests PRs based on open issues, and support others in [Discussions](https://github.com/vitest-dev/vitest/discussions) and Vitest Land's [help forum](https://discord.com/channels/917386801235247114/1057959614160851024). If you'd like to talk to us, join our [Discord community](http://chat.vitest.dev/) and say hi on the [#contributing channel](https://discord.com/channels/917386801235247114/1057959614160851024). + +For the latest news about the Vitest ecosystem and Vitest core, follow us on [Bluesky](https://bsky.app/profile/vitest.dev) or [Mastodon](https://webtoo.ls/@vitest). + +To stay updated, keep an eye on the [VoidZero blog](https://voidzero.dev/blog) and subscribe to the [newsletter](https://voidzero.dev/newsletter). + +## Vite 8 Support + +This release adds support for the new Vite 8 version. Additionally, Vitest now uses the installed `vite` version instead of downloading a separate dependency, if possible. This makes issues like type inconsistencies in your config file obsolete. + +## Test Tags + +[Tags](/guide/test-tags) let you label tests to organize them into groups. Once tagged, you can filter tests by tag or apply shared options — like a longer timeout or automatic retries — to every test with a given tag. + +To use tags, define them in your configuration file. Each tag requires a `name` and can optionally include test options that apply to every test marked with that tag. For the full list of available options, see [`tags`](/config/tags). + +```ts [vitest.config.js] +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + tags: [ + { + name: 'db', + description: 'Tests for database queries.', + timeout: 60_000, + }, + { + name: 'flaky', + description: 'Flaky CI tests.', + retry: process.env.CI ? 3 : 0, + }, + ], + }, +}) +``` + +With this configuration, you can apply `flaky` and `db` tags to your tests: + +```ts +test('flaky database test', { tags: ['flaky', 'db'] }, () => { + // ... +}) +``` + +The test has a timeout of 60 seconds and will be retried 3 times on CI because these options were specified in the configuration file for `db` and `flaky` tags. + +Inspired by [pytest](https://docs.pytest.org/en/stable/reference/reference.html#cmdoption-m), Vitest supports a custom syntax for filtering tags: + +- `and` or `&&` to include both expressions +- `or` or `||` to include at least one expression +- `not` or `!` to exclude the expression +- `*` to match any number of characters (0 or more) +- `()` to group expressions and override precedence + +Here are some common filtering patterns: + +```shell +# Run only unit tests +vitest --tags-filter="unit" + +# Run tests that are both frontend AND fast +vitest --tags-filter="frontend and fast" + +# Run frontend tests that are not flaky +vitest --tags-filter="frontend && !flaky" + +# Run tests matching a wildcard pattern +vitest --tags-filter="api/*" +``` + +## Experimental `viteModuleRunner: false` + +By default, Vitest runs all code inside Vite's [module runner](https://vite.dev/guide/api-environment-runtimes#modulerunner) — a permissive sandbox that provides `import.meta.env`, `require`, `__dirname`, `__filename`, and applies Vite plugins and aliases. While this makes getting started easy, it can hide real issues: your tests may pass in the sandbox but fail in production because the runtime behavior differs from native Node.js. + +Vitest 4.1 introduces [`experimental.viteModuleRunner`](/config/experimental#experimental-vitemodulerunner), which lets you disable the module runner entirely and run tests with native `import` instead: + +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + experimental: { + viteModuleRunner: false, + }, + }, +}) +``` + +With this flag, **no file transforms are applied** — your test files, source code, and setup files are executed by Node.js directly. This means faster startup, closer-to-production behavior, and issues like incorrect `__dirname` injection or silently passing imports of nonexistent exports are caught early. + +If you are using Node.js 22.18+ or 23.6+, TypeScript is [stripped natively](https://nodejs.org/en/learn/typescript/run-natively) — no extra configuration needed. + +Mocking with `vi.mock` and `vi.hoisted` is supported via the Node.js [Module Loader API](https://nodejs.org/api/module.html#customization-hooks) (requires Node.js 22.15+). Note that `import.meta.env`, Vite plugins, aliases, and the `istanbul` coverage provider are not available in this mode. + +Consider this option if you run server-side or script-like tests that don't need Vite transforms. For `jsdom`/`happy-dom` tests, we still recommend the default module runner or [browser mode](/guide/browser/). + +Read more in the [`experimental.viteModuleRunner` docs](/config/experimental#experimental-vitemodulerunner). + +## Configure UI Browser Window + +Vitest 4.1 introduces [`browser.detailsPanelPosition`](/config/browser/detailspanelposition), letting you choose where the details panel appears in Browser UI. + +
+ Vitest UI with details at the bottom + Vitest UI with details at the bottom + + An example of UI with the details panel at the bottom. +
+ +This is especially useful on smaller screens, where switching to a bottom panel leaves more horizontal space for your app: + +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + browser: { + enabled: true, + detailsPanelPosition: 'bottom', // or 'right' + }, + }, +}) +``` + +You can also switch this directly from the UI via the new layout toggle button. + +## Enhanced Browser Trace View + +Vitest 4.1 brings major improvements to the [Playwright Trace Viewer](/guide/browser/trace-view) integration in browser mode. Browser interactions like `click`, `fill`, and `expect.element` are now automatically grouped in the trace timeline and linked back to the exact line in your test file. + +
+ Trace Viewer showing the trace timeline and rendered component + Trace Viewer showing the trace timeline and rendered component + + An example of trace view with `expect.element` assertion failure highlighted. +
+ +Framework libraries are also integrating with the trace. For example, [`vitest-browser-react`](https://github.com/vitest-community/vitest-browser-react)'s `render()` utility now automatically appears in the trace with rendered element highlighted. + +For custom annotations, the new [`page.mark`](/api/browser/context#mark) and [`locator.mark`](/api/browser/locators#mark) APIs let you add your own markers to the trace: + +```ts +import { page } from 'vitest/browser' + +await page.mark('before sign in') +await page.getByRole('button', { name: 'Sign in' }).click() +await page.mark('after sign in') +``` + +You can also group a whole flow under one named entry: + +```ts +await page.mark('sign in flow', async () => { + await page.getByRole('textbox', { name: 'Email' }).fill('john@example.com') + await page.getByRole('textbox', { name: 'Password' }).fill('secret') + await page.getByRole('button', { name: 'Sign in' }).click() +}) +``` + +Read more in the [Trace View guide](/guide/browser/trace-view). + +## Type-Inference in `test.extend` - New Builder Pattern + +Vitest 4.1 introduces a new [`test.extend`](/guide/test-context) pattern that supports type inference. You can return a value from the factory instead of calling the `use` function — TypeScript infers the type of each fixture from its return value, so you don't need to declare types manually. + +```ts +import { test as baseTest } from 'vitest' + +export const test = baseTest + // Simple value - type is inferred as { port: number; host: string } + .extend('config', { port: 3000, host: 'localhost' }) + // Function fixture - type is inferred from return value + .extend('server', async ({ config }) => { + // TypeScript knows config is { port: number; host: string } + return `http://${config.host}:${config.port}` + }) +``` + +For fixtures that need setup or cleanup logic, use a function. The `onCleanup` callback registers teardown logic that runs after the fixture's scope ends: + +```ts +import { test as baseTest } from 'vitest' + +export const test = baseTest + .extend('tempFile', async ({}, { onCleanup }) => { + const filePath = `/tmp/test-${Date.now()}.txt` + await fs.writeFile(filePath, 'test data') + + // Register cleanup - runs after test completes + onCleanup(() => fs.unlink(filePath)) + + return filePath + }) +``` + +In addition to this, Vitest now passes down `file` and `worker` contexts to `beforeAll`, `afterAll` and `aroundAll` hooks: + +```ts +import { test as baseTest } from 'vitest' + +const test = baseTest + .extend('config', { scope: 'file' }, () => loadConfig()) + .extend('db', { scope: 'file' }, ({ config }) => createDatabase(config.port)) + +test.beforeAll(async ({ db }) => { + await db.migrateUsers() +}) + +test.afterAll(async ({ db }) => { + await db.deleteUsers() +}) +``` + +::: warning +This change could be considered breaking. Previously Vitest passed down undocumented `Suite` as the first argument. The team decided that the usage was small enough to not disrupt the ecosystem. +::: + +## New `aroundAll` and `aroundEach` Hooks + +The new `aroundEach` hook registers a callback function that wraps around each test within the current suite. The callback receives a `runTest` function that **must** be called to run the test. The `aroundAll` hook works similarly, but is called for every suite, not every test. + +You should use `aroundEach` when your test needs to run **inside a context** that wraps around it, such as: +- Wrapping tests in [AsyncLocalStorage](https://nodejs.org/api/async_context.html#class-asynclocalstorage) context +- Wrapping tests with tracing spans +- Database transactions + +```ts +import { test as baseTest } from 'vitest' + +const test = baseTest + .extend('db', async ({}, { onCleanup }) => { + // db is created before `aroundEach` hook + const db = await createTestDatabase() + onCleanup(() => db.close()) + return db + }) + +test.aroundEach(async (runTest, { db }) => { + await db.transaction(runTest) +}) + +test('insert user', async ({ db }) => { + // called inside a transaction + await db.insert({ name: 'Alice' }) +}) +``` + +## Helper for Better Stack Traces + +When a test fails inside a shared utility function, the stack trace usually points to the line inside that helper — not where it was called. This makes it harder to find which test actually failed, especially when the same helper is used across many tests. + +[`vi.defineHelper`](/api/vi#vi-definehelper) wraps a function so that Vitest removes its internals from the stack trace and points the error back to the call site instead: + +```ts +import { expect, test, vi } from 'vitest' + +const assertPair = vi.defineHelper((a, b) => { + expect(a).toEqual(b) // 🙅‍♂️ error code block will NOT point to here +}) + +test('example', () => { + assertPair('left', 'right') // 🙆 but point to here +}) +``` + +This is especially useful for custom assertion libraries and reusable test utilities where the call site is more meaningful than the implementation. + +## `--detect-async-leaks` to Catch Leaks + +Leaked timers, handles, and unresolved async resources can make test suites flaky and hard to debug. Vitest 4.1 adds [`detectAsyncLeaks`](/config/detectasyncleaks) to help track these issues. + +You can enable it via CLI: + +```sh +vitest --detect-async-leaks +``` + +Or in config: + +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + detectAsyncLeaks: true, + }, +}) +``` + +When enabled, Vitest uses `node:async_hooks` to report leaked async resources with source locations. Since this adds runtime overhead, it is best used while debugging. + +## `vscode` Improvements + +The official [vscode extension](https://vitest.dev/vscode) received a large number of fixes and new features: + +- The extension no longer keeps a running process in the background unless you explicitly enable continuous run manually or via a new config option `watchOnStartup`. This reduces memory usage and eliminates the `maximumConfigs` config option. +- The new "Run Related Tests" command runs tests that import the currently open file. +- The new "Toggle Continuous Run" action is now available when clicking on the gutter icon. +- The extension now supports [Deno runtime](https://deno.com/). +- The extension cancels the test run sooner after clicking "Stop", when possible. +- The extension displays the module load time inline next to each import statement, if you are using Vitest 4.1. + +
+ An example of import breakdown in vscode + An example of import breakdown in vscode. +
+ +## GitHub Actions Job Summary + +The built-in [`github-actions` reporter](/guide/reporters#github-actions-reporter) now automatically generates a [Job Summary](https://github.blog/news-insights/product-news/supercharging-github-actions-with-job-summaries/) with an overview of your test results. The summary includes test file and test case statistics, and highlights flaky tests that required retries — with permalink URLs linking test names directly to the relevant source lines on GitHub. + +
+ GitHub Actions Job Summary + GitHub Actions Job Summary + + An example of the job summary with flaky test details. +
+ +The summary is enabled by default when running in GitHub Actions and writes to the path specified by `$GITHUB_STEP_SUMMARY`. No configuration is needed in most cases. To disable it or customize the output path: + +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + reporters: [ + ['github-actions', { + jobSummary: { + enabled: false, // or set `outputPath` to customize where the summary is written + }, + }], + ], + }, +}) +``` + +## New `agent` Reporter to Reduce Token Usage + +As AI coding agents become a common way to run tests, Vitest 4.1 introduces the [`agent` reporter](/guide/reporters#agent-reporter) — a minimal output mode designed to reduce token usage. It only displays failed tests and their errors, suppressing passed test output and console logs from passing tests. + +Vitest automatically enables this reporter when it detects it's running inside an AI coding agent. The detection is powered by [`std-env`](https://github.com/unjs/std-env), which recognizes popular agent environments out of the box. You can also set the `AI_AGENT=copilot` (or any name) environment variable explicitly. No configuration needed — just run Vitest as usual: + +```sh +AI_AGENT=copilot vitest +``` + +If you configure custom reporters, the automatic detection is skipped, so add `'agent'` to the list manually if you want both. + +## New `mockThrow` API + +Previously, making a mock throw required wrapping the error in a function: `mockImplementation(() => { throw new Error(...) })`. The new [`mockThrow`](/api/mock#mockthrow) and [`mockThrowOnce`](/api/mock#mockthrowonce) methods make this more concise and readable: + +```ts +const myMockFn = vi.fn() +myMockFn.mockThrow(new Error('error message')) +myMockFn() // throws Error<'error message'> +``` + +## Strict Mode in WebdriverIO and Preview + +Locating elements is now strict by default in `webdriverio` and `preview`, matching Playwright behavior. + +If a locator resolves to multiple elements, Vitest throws a "strict mode violation" instead of silently picking one. This helps catch ambiguous queries early: + +```ts +const button = page.getByRole('button') + +await button.click() // throws if multiple buttons match +await button.click({ strict: false }) // opt out and return first match +``` + +## Chai-style Mocking Assertions + +Vitest already supports chai-style assertions like `eql`, `throw`, and `be`. This release extends that support to mock assertions, making it easier to migrate from Sinon-based test suites without rewriting every expectation: + +```ts +import { expect, vi } from 'vitest' + +const fn = vi.fn() + +fn('example') + +expect(fn).to.have.been.called // expect(fn).toHaveBeenCalled() +expect(fn).to.have.been.calledWith('example') // expect(fn).toHaveBeenCalledWith('example') +expect(fn).to.have.returned // expect(fn).toHaveReturned() +expect(fn).to.have.callCount(1) // expect(fn).toHaveBeenCalledTimes(1) +``` + +## Coverage `ignore start/stop` Ignore Hints + +You can now completely ignore specific lines from code coverage using `ignore start/stop` comments. +In Vitest v3, this was supported by the `v8` provider, but not in v4.0 due to underlying dependency changes. + +Due to the community's request, we've now implemented it back ourselves and extended the support to both `v8` and `istanbul` providers. + +```ts +/* istanbul ignore start -- @preserve */ +if (parameter) { // [!code error] + console.log('Ignored') // [!code error] +} // [!code error] +else { // [!code error] + console.log('Ignored') // [!code error] +} // [!code error] +/* istanbul ignore stop -- @preserve */ + +console.log('Included') + +/* v8 ignore start -- @preserve */ +if (parameter) { // [!code error] + console.log('Ignored') // [!code error] +} // [!code error] +else { // [!code error] + console.log('Ignored') // [!code error] +} // [!code error] +/* v8 ignore stop -- @preserve */ + +console.log('Included') +``` + +See [Coverage | Ignoring Code](/guide/coverage.html#ignoring-code) for more examples. + +## Coverage For Changed Files Only + +If you want to get code coverage only for the modified files, you can use [`coverage.changed`](/config/coverage.html#coverage-changed) to limit the file inclusion. + +Compared to the regular [`--changed`](/guide/cli.html#changed) flag, `--coverage.changed` allows you to still run all test files, but limit the coverage reporting only to the changed files. +This allows you to exclude unchanged files from coverage that `--changed` would otherwise include. + +## Coverage in HTML Reporter and Subpath Deployments + +Coverage HTML viewing now works reliably across UI mode, HTML reporter, and browser mode — including when deployed under a subpath. For custom coverage reporters, the new [`coverage.htmlDir`](/config/coverage#coverage-htmldir) option can be used to integrate their HTML output. + +## Acknowledgments + +Vitest 4.1 is the result of countless hours by the [Vitest team](/team) and our contributors. We appreciate the individuals and companies sponsoring Vitest development. [Vladimir](https://github.com/sheremet-va) and [Hiroshi](https://github.com/hi-ogawa) are part of the [VoidZero](https://voidzero.dev) Team and are able to work on Vite and Vitest full-time, and [Ari](https://github.com/ariperkkio) can invest more time in Vitest thanks to support from [Chromatic](https://www.chromatic.com/). A big shout-out to [Zammad](https://zammad.com), and sponsors on [Vitest's GitHub Sponsors](https://github.com/sponsors/vitest-dev) and [Vitest's Open Collective](https://opencollective.com/vitest). diff --git a/blog/vitest-4.md b/blog/vitest-4.md index 219d1967..26c08656 100644 --- a/blog/vitest-4.md +++ b/blog/vitest-4.md @@ -56,7 +56,7 @@ To stay updated, keep an eye on the [VoidZero blog](https://voidzero.dev/blog) a With this release we are removing the `experimental` tag from [Browser Mode](/guide/browser/). To make it possible, we had to introduce some changes to the public API. -To define a provider, you now need to install a separate package: [`@vitest/browser-playwright`](https://www.npmjs.com/package/@vitest/browser-playwright), [`@vitest/browser-webdriverio`](https://www.npmjs.com/package/@vitest/browser-webdriverio), or [`@vitest/browser-preview`](https://www.npmjs.com/package/@vitest/browser-preview). This makes it simpler to work with custom options and doesn't require adding `/// `preact`), you may want to alias the actual `node_modules` packages instead to make it work for externalized dependencies. Both [Yarn](https://classic.yarnpkg.com/en/docs/cli/add/#toc-yarn-add-alias) and [pnpm](https://pnpm.io/aliases/) support aliasing via the `npm:` prefix. ::: diff --git a/config/allowonly.md b/config/allowonly.md index 2716ced2..44ff47bf 100644 --- a/config/allowonly.md +++ b/config/allowonly.md @@ -14,7 +14,7 @@ outline: deep By default, Vitest does not permit tests marked with the [`only`](/api/test#test-only) flag in Continuous Integration (CI) environments. Conversely, in local development environments, Vitest allows these tests to run. ::: info -Vitest uses [`std-env`](https://www.npmjs.com/package/std-env) package to detect the environment. +Vitest uses [`std-env`](https://npmx.dev/package/std-env) package to detect the environment. ::: You can customize this behavior by explicitly setting the `allowOnly` option to either `true` or `false`. diff --git a/config/api.md b/config/api.md index 91e99717..b20c5408 100644 --- a/config/api.md +++ b/config/api.md @@ -18,7 +18,7 @@ Listen to port and serve API for [the UI](/guide/ui) or [browser server](/guide/ - **Type:** `boolean` - **Default:** `true` if not exposed to the network, `false` otherwise -Vitest server can save test files or snapshot files via the API. This allows anyone who can connect to the API the ability to run any arbitary code on your machine. +Vitest server can save test files or snapshot files via the API. This allows anyone who can connect to the API the ability to run any arbitrary code on your machine. ::: danger SECURITY ADVICE Vitest does not expose the API to the internet by default and only listens on `localhost`. However if `host` is manually exposed to the network, anyone who connects to it can run arbitrary code on your machine, unless `api.allowWrite` and `api.allowExec` are set to `false`. diff --git a/config/benchmark.md b/config/benchmark.md index db5690a7..a6926140 100644 --- a/config/benchmark.md +++ b/config/benchmark.md @@ -28,7 +28,11 @@ outline: deep - **类型:** `string[]` - **默认值:** `[]` +<<<<<<< HEAD 匹配包含内联基准测试文件的 glob 规则。此选项类似于 [`includeSource`](#includesource)。 +======= +Include globs for in-source benchmark test files. This option is similar to [`includeSource`](/config/include-source). +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 定义后,Vitest 将运行所有匹配的文件,其中包含 `import.meta.vitest`。 diff --git a/config/browser/api.md b/config/browser/api.md index 71a48261..f45353ea 100644 --- a/config/browser/api.md +++ b/config/browser/api.md @@ -11,7 +11,7 @@ outline: deep - **Default:** `63315` - **CLI:** `--browser.api=63315`, `--browser.api.port=1234, --browser.api.host=example.com` -Configure options for Vite server that serves code in the browser. Does not affect [`test.api`](#api) option. By default, Vitest assigns port `63315` to avoid conflicts with the development server, allowing you to run both in parallel. +Configure options for Vite server that serves code in the browser. Does not affect [`test.api`](/config/api) option. By default, Vitest assigns port `63315` to avoid conflicts with the development server, allowing you to run both in parallel. ## api.allowWrite 4.1.0 {#api-allowwrite} diff --git a/config/browser/detailspanelposition.md b/config/browser/detailspanelposition.md index 70811aa3..e71ca3fa 100644 --- a/config/browser/detailspanelposition.md +++ b/config/browser/detailspanelposition.md @@ -28,3 +28,18 @@ export default defineConfig({ }, }) ``` + +## Example + +::: tabs +== bottom +
+ Vitest UI with details at the bottom + Vitest UI with details at the bottom +
+== right +
+ Vitest UI with details at the right side + Vitest UI with details at the right side +
+::: diff --git a/config/browser/playwright.md b/config/browser/playwright.md index 3715851a..306c9245 100644 --- a/config/browser/playwright.md +++ b/config/browser/playwright.md @@ -1,6 +1,10 @@ # 配置 Playwright {#configuring-playwright} +<<<<<<< HEAD 要使用 playwright 运行测试,你需要安装 [`@vitest/browser-playwright`](https://www.npmjs.com/package/@vitest/browser-playwright) npm 包,并在配置中的 `test.browser.provider` 属性中指定其 `playwright` 导出: +======= +To run tests using playwright, you need to install the [`@vitest/browser-playwright`](https://npmx.dev/package/@vitest/browser-playwright) npm package and specify its `playwright` export in the `test.browser.provider` property of your config: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```ts [vitest.config.js] import { playwright } from '@vitest/browser-playwright' @@ -74,7 +78,13 @@ Vitest 将忽略 `launch.headless` 选项。请改用 [`test.browser.headless`]( Use `connectOptions.wsEndpoint` to connect to an existing Playwright server instead of launching browsers locally. This is useful for running browsers in Docker, in CI, or on a remote machine. ::: warning +<<<<<<< HEAD 由于此命令连接到现有的 Playwright 服务器,任何 `launch` 选项都将被忽略。 +======= + +Vitest forwards `launchOptions` to Playwright server via the `x-playwright-launch-options` header. This works only if the remote Playwright server supports this header, for example when using the `playwright run-server` CLI. + +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ::: ::: details Example: Running a Playwright Server in Docker diff --git a/config/browser/preview.md b/config/browser/preview.md index eb608a04..9fde3430 100644 --- a/config/browser/preview.md +++ b/config/browser/preview.md @@ -4,7 +4,11 @@ `preview` 提供程序的主要功能是在真实浏览器环境中显示测试。不过,它不支持高级浏览器自动化功能,如多个浏览器实例或无头模式。对于更复杂的场景,请考虑使用 [Playwright](/config/browser/playwright) 或 [WebdriverIO](/config/browser/webdriverio)。 ::: +<<<<<<< HEAD 要让你的测试运行在真实浏览器中,需要安装 [`@vitest/browser-preview`](https://www.npmjs.com/package/@vitest/browser-preview) npm 软件包,并在配置的 `test.browser.provider` 属性中指定其 `preview` 导出: +======= +To see your tests running in a real browser, you need to install the [`@vitest/browser-preview`](https://npmx.dev/package/@vitest/browser-preview) npm package and specify its `preview` export in the `test.browser.provider` property of your config: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```ts [vitest.config.js] import { preview } from '@vitest/browser-preview' @@ -26,7 +30,14 @@ export default defineConfig({ 与 [Playwright](/config/browser/playwright) 或 [WebdriverIO](/config/browser/webdriverio) 等其他 Providers 相比,预览服务存在一些限制: +<<<<<<< HEAD - 它不支持无头模式; 浏览器窗口始终可见. - 它不支持同一浏览器的多个实例; 每个实例必须使用不同的浏览器. - 它不支持高级浏览器功能或选项; 你只能指定浏览器名称. - 它不支持 CDP(Chrome DevTools 协议)命令或其他低层浏览器交互. 与 Playwright 或 WebdriverIO 不同, [`userEvent`](/api/browser/interactivity) API 只是从 [`@testing-library/user-event`](https://www.npmjs.com/package/@testing-library/user-event) 重新导出, 没有与浏览器的特殊集成. +======= +- It does not support headless mode; the browser window will always be visible. +- It does not support multiple instances of the same browser; each instance must use a different browser. +- It does not support advanced browser capabilities or options; you can only specify the browser name. +- It does not support CDP (Chrome DevTools Protocol) commands or other low-level browser interactions. Unlike Playwright or WebdriverIO, the [`userEvent`](/api/browser/interactivity) API is just re-exported from [`@testing-library/user-event`](https://npmx.dev/package/@testing-library/user-event) and does not have any special integration with the browser. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 diff --git a/config/browser/provider.md b/config/browser/provider.md index 366c07e0..c5995fbf 100644 --- a/config/browser/provider.md +++ b/config/browser/provider.md @@ -64,7 +64,7 @@ export default defineConfig({ ## Custom Provider advanced ::: danger ADVANCED API -The custom provider API is highly experimental and can change between patches. If you just need to run tests in a browser, use the [`browser.instances`](#browser-instances) option instead. +The custom provider API is highly experimental and can change between patches. If you just need to run tests in a browser, use the [`browser.instances`](/config/browser/instances) option instead. ::: ```ts diff --git a/config/browser/webdriverio.md b/config/browser/webdriverio.md index 11ba70cf..272181b7 100644 --- a/config/browser/webdriverio.md +++ b/config/browser/webdriverio.md @@ -4,7 +4,11 @@ 如果我们的项目尚未使用 WebdriverIO,我们建议从 [Playwright](/config/browser/playwright) 开始,因为它更易于配置且 API 更灵活。 ::: +<<<<<<< HEAD 要使用 WebdriverIO 运行测试,你需要安装 [`@vitest/browser-webdriverio`](https://www.npmjs.com/package/@vitest/browser-webdriverio) npm 包,并在配置中的 `test.browser.provider` 属性中指定其 `webdriverio` 导出: +======= +To run tests using WebdriverIO, you need to install the [`@vitest/browser-webdriverio`](https://npmx.dev/package/@vitest/browser-webdriverio) npm package and specify its `webdriverio` export in the `test.browser.provider` property of your config: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```ts [vitest.config.js] import { webdriverio } from '@vitest/browser-webdriverio' diff --git a/config/clearmocks.md b/config/clearmocks.md index fff1dbfd..c2bde0b8 100644 --- a/config/clearmocks.md +++ b/config/clearmocks.md @@ -21,3 +21,7 @@ export default defineConfig({ }, }) ``` + +::: warning +Be aware that this option may cause problems with async [concurrent tests](/api/test#test-concurrent). If enabled, the completion of one test will clear the mock history for all mocks, including those currently being used by other tests in progress. +::: diff --git a/config/coverage.md b/config/coverage.md index a50ea6f6..79b546b0 100644 --- a/config/coverage.md +++ b/config/coverage.md @@ -149,7 +149,7 @@ Generate coverage report even when tests fail. - **Available for providers:** `'v8' | 'istanbul'` - **CLI:** `--coverage.allowExternal`, `--coverage.allowExternal=false` -Collect coverage of files outside the [project `root`](#root). +Collect coverage of files outside the [project `root`](/config/root). ## coverage.excludeAfterRemap diff --git a/config/deps.md b/config/deps.md index b49b8fdd..579544e9 100644 --- a/config/deps.md +++ b/config/deps.md @@ -44,7 +44,7 @@ Enable dependency optimization. Options that are applied to external files when the environment is set to `client`. By default, `jsdom` and `happy-dom` use `client` environment, while `node` and `edge` environments use `ssr`, so these options will have no affect on files inside those environments. -Usually, files inside `node_modules` are externalized, but these options also affect files in [`server.deps.external`](#server-deps-external). +Usually, files inside `node_modules` are externalized, but these options also affect files in [`server.deps.external`](/config/server#server-deps-external). ### deps.client.transformAssets @@ -56,7 +56,7 @@ Should Vitest process assets (.png, .svg, .jpg, etc) files and resolve them like This module will have a default export equal to the path to the asset, if no query is specified. ::: warning -At the moment, this option only works with [`vmThreads`](#vmthreads) and [`vmForks`](#vmforks) pools. +At the moment, this option only works with [`vmThreads`](/config/pool#vmthreads) and [`vmForks`](/config/pool#vmforks) pools. ::: ### deps.client.transformCss @@ -66,10 +66,10 @@ At the moment, this option only works with [`vmThreads`](#vmthreads) and [`vmFor Should Vitest process CSS (.css, .scss, .sass, etc) files and resolve them like Vite does in the browser. -If CSS files are disabled with [`css`](#css) options, this option will just silence `ERR_UNKNOWN_FILE_EXTENSION` errors. +If CSS files are disabled with [`css`](/config/css) options, this option will just silence `ERR_UNKNOWN_FILE_EXTENSION` errors. ::: warning -At the moment, this option only works with [`vmThreads`](#vmthreads) and [`vmForks`](#vmforks) pools. +At the moment, this option only works with [`vmThreads`](/config/pool#vmthreads) and [`vmForks`](/config/pool#vmforks) pools. ::: ### deps.client.transformGlobPattern @@ -82,7 +82,7 @@ Regexp pattern to match external files that should be transformed. By default, files inside `node_modules` are externalized and not transformed, unless it's CSS or an asset, and corresponding option is not disabled. ::: warning -At the moment, this option only works with [`vmThreads`](#vmthreads) and [`vmForks`](#vmforks) pools. +At the moment, this option only works with [`vmThreads`](/config/pool#vmthreads) and [`vmForks`](/config/pool#vmforks) pools. ::: ## deps.interopDefault @@ -113,7 +113,7 @@ By default, Vitest assumes you are using a bundler to bypass this and will not f - **Type:** `string[]` - **Default**: `['node_modules']` -A list of directories that should be treated as module directories. This config option affects the behavior of [`vi.mock`](/api/vi#vi-mock): when no factory is provided and the path of what you are mocking matches one of the `moduleDirectories` values, Vitest will try to resolve the mock by looking for a `__mocks__` folder in the [root](#root) of the project. +A list of directories that should be treated as module directories. This config option affects the behavior of [`vi.mock`](/api/vi#vi-mock): when no factory is provided and the path of what you are mocking matches one of the `moduleDirectories` values, Vitest will try to resolve the mock by looking for a `__mocks__` folder in the [root](/config/root) of the project. This option will also affect if a file should be treated as a module when externalizing dependencies. By default, Vitest imports external modules with native Node.js bypassing Vite transformation step. diff --git a/config/detectasyncleaks.md b/config/detectasyncleaks.md index 88c326de..c9c49a4e 100644 --- a/config/detectasyncleaks.md +++ b/config/detectasyncleaks.md @@ -19,7 +19,7 @@ Uses [`node:async_hooks`](https://nodejs.org/api/async_hooks.html) to track crea For example if your code has `setTimeout` calls that execute the callback after tests have finished, you will see following error: ```sh -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Async Leaks 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ +⎯⎯⎯⎯⎯⎯⎯⎯ Async Leaks 1 ⎯⎯⎯⎯⎯⎯⎯⎯ Timeout leaking in test/checkout-screen.test.tsx 26| diff --git a/config/exclude.md b/config/exclude.md index 7116ce6b..7e44ee52 100644 --- a/config/exclude.md +++ b/config/exclude.md @@ -10,7 +10,7 @@ title: exclude | Config A list of [glob patterns](https://superchupu.dev/tinyglobby/comparison) that should be excluded from your test files. These patterns are resolved relative to the [`root`](/config/root) ([`process.cwd()`](https://nodejs.org/api/process.html#processcwd) by default). -Vitest uses the [`tinyglobby`](https://www.npmjs.com/package/tinyglobby) package to resolve the globs. +Vitest uses the [`tinyglobby`](https://npmx.dev/package/tinyglobby) package to resolve the globs. ::: warning This option does not affect coverage. If you need to remove certain files from the coverage report, use [`coverage.exclude`](/config/coverage#exclude). diff --git a/config/experimental.md b/config/experimental.md index 4e79d019..164c1346 100644 --- a/config/experimental.md +++ b/config/experimental.md @@ -279,6 +279,10 @@ Duration thresholds in milliseconds for coloring and warnings: ## experimental.viteModuleRunner 4.1.0 {#experimental-vitemodulerunner} +::: tip FEEDBACK +Please leave feedback regarding this feature in a [GitHub Discussion](https://github.com/vitest-dev/vitest/discussions/9501). +::: + - **Type:** `boolean` - **Default:** `true` diff --git a/config/faketimers.md b/config/faketimers.md index a389b451..68b43e1c 100644 --- a/config/faketimers.md +++ b/config/faketimers.md @@ -7,7 +7,7 @@ outline: deep - **Type:** `FakeTimerInstallOpts` -Options that Vitest will pass down to [`@sinon/fake-timers`](https://www.npmjs.com/package/@sinonjs/fake-timers) when using [`vi.useFakeTimers()`](/api/vi#vi-usefaketimers). +Options that Vitest will pass down to [`@sinon/fake-timers`](https://npmx.dev/package/@sinonjs/fake-timers) when using [`vi.useFakeTimers()`](/api/vi#vi-usefaketimers). ## fakeTimers.now diff --git a/config/fileparallelism.md b/config/fileparallelism.md index c39fcc93..7b9a232d 100644 --- a/config/fileparallelism.md +++ b/config/fileparallelism.md @@ -12,5 +12,9 @@ outline: deep 所有测试文件应该并行运行。 将其设置为 `false` 将覆盖 `maxWorkers` 选项为 `1`。 ::: tip +<<<<<<< HEAD 此选项不会影响在同一文件中运行的测试。如果你想并行运行这些程序,使用 `concurrent` 选项 [describe](/api/describe#describe-concurrent) 或通过 [配置](#sequence-concurrent)。 +======= +This option doesn't affect tests running in the same file. If you want to run those in parallel, use `concurrent` option on [describe](/api/describe#describe-concurrent) or via [a config](/config/sequence#sequence-concurrent). +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ::: diff --git a/config/globalsetup.md b/config/globalsetup.md index 549d2aad..279d3d39 100644 --- a/config/globalsetup.md +++ b/config/globalsetup.md @@ -62,7 +62,7 @@ declare module 'vitest' { If you need to execute code in the same process as tests, use [`setupFiles`](/config/setupfiles) instead, but note that it runs before every test file. ::: -### Handling Test Reruns +## Handling Test Reruns You can define a custom callback function to be called when Vitest reruns tests. The test 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. diff --git a/config/include-source.md b/config/include-source.md index e1ee0ce8..abe287c6 100644 --- a/config/include-source.md +++ b/config/include-source.md @@ -15,7 +15,7 @@ When defined, Vitest will run all matched files that have `import.meta.vitest` i Vitest performs a simple text-based inclusion check on source files. If a file contains `import.meta.vitest`, even in a comment, it will be matched as an in-source test file. ::: -Vitest uses the [`tinyglobby`](https://www.npmjs.com/package/tinyglobby) package to resolve the globs. +Vitest uses the [`tinyglobby`](https://npmx.dev/package/tinyglobby) package to resolve the globs. ## Example diff --git a/config/include.md b/config/include.md index 86c6fa7e..ac0b8b76 100644 --- a/config/include.md +++ b/config/include.md @@ -10,7 +10,7 @@ title: include | Config A list of [glob patterns](https://superchupu.dev/tinyglobby/comparison) that match your test files. These patterns are resolved relative to the [`root`](/config/root) ([`process.cwd()`](https://nodejs.org/api/process.html#processcwd) by default). -Vitest uses the [`tinyglobby`](https://www.npmjs.com/package/tinyglobby) package to resolve the globs. +Vitest uses the [`tinyglobby`](https://npmx.dev/package/tinyglobby) package to resolve the globs. ::: tip NOTE When using coverage, Vitest automatically adds test files `include` patterns to coverage's default `exclude` patterns. See [`coverage.exclude`](/config/coverage#exclude). diff --git a/config/includetasklocation.md b/config/includetasklocation.md index 312c6bb1..e830028c 100644 --- a/config/includetasklocation.md +++ b/config/includetasklocation.md @@ -8,7 +8,7 @@ outline: deep - **Type:** `boolean` - **Default:** `false` -Should `location` property be included when Vitest API receives tasks in [reporters](#reporters). If you have a lot of tests, this might cause a small performance regression. +Should `location` property be included when Vitest API receives tasks in [reporters](/config/reporters). If you have a lot of tests, this might cause a small performance regression. The `location` property has `column` and `line` values that correspond to the `test` or `describe` position in the original file. diff --git a/config/mockreset.md b/config/mockreset.md index fac9b6b7..15259293 100644 --- a/config/mockreset.md +++ b/config/mockreset.md @@ -21,3 +21,7 @@ export default defineConfig({ }, }) ``` + +::: warning +Be aware that this option may cause problems with async [concurrent tests](/api/test#test-concurrent). If enabled, the completion of one test will clear the mock history and implementation for all mocks, including those currently being used by other tests in progress. +::: diff --git a/config/reporters.md b/config/reporters.md index d79ae59c..6c9b3335 100644 --- a/config/reporters.md +++ b/config/reporters.md @@ -14,7 +14,7 @@ interface UserConfig { type ConfigReporter = string | Reporter | [string, object?] ``` -- **Default:** [`'default'`](/guide/reporters#default-reporter) +- **Default:** [`'default'`](/guide/reporters#default-reporter) (or [['default'](/guide/reporters#default-reporter), ['github-actions'](/guide/reporters#github-actions-reporter)] when `process.env.GITHUB_ACTIONS === 'true'`) - **CLI:** - `--reporter=tap` for a single reporter - `--reporter=verbose --reporter=github-actions` for multiple reporters @@ -42,6 +42,7 @@ Note that the [coverage](/guide/coverage) feature uses a different [`coverage.re - [`tap-flat`](/guide/reporters#tap-flat-reporter) - [`hanging-process`](/guide/reporters#hanging-process-reporter) - [`github-actions`](/guide/reporters#github-actions-reporter) +- [`agent`](/guide/reporters#agent-reporter) - [`blob`](/guide/reporters#blob-reporter) ## Example diff --git a/config/restoremocks.md b/config/restoremocks.md index 00638008..818942c1 100644 --- a/config/restoremocks.md +++ b/config/restoremocks.md @@ -21,3 +21,7 @@ export default defineConfig({ }, }) ``` + +::: warning +Be aware that this option may cause problems with async [concurrent tests](/api/test#test-concurrent). If enabled, the completion of one test will restore the implementation for all spies, including those currently being used by other tests in progress. +::: diff --git a/config/sequence.md b/config/sequence.md index 9fc65fb7..51c7276b 100644 --- a/config/sequence.md +++ b/config/sequence.md @@ -24,7 +24,7 @@ A custom class that defines methods for sharding and sorting. You can extend `Ba Sharding is happening before sorting, and only if `--shard` option is provided. -If [`sequencer.groupOrder`](#grouporder) is specified, the sequencer will be called once for each group and pool. +If [`sequence.groupOrder`](#sequence-grouporder) is specified, the sequencer will be called once for each group and pool. ## sequence.groupOrder @@ -38,7 +38,7 @@ Controls the order in which this project runs its tests when using multiple [pro - If several projects use the same group order, they will run at the same time. This setting only affects the order in which projects run, not the order of tests within a project. -To control test isolation or the order of tests inside a project, use the [`isolate`](#isolate) and [`sequence.sequencer`](#sequence-sequencer) options. +To control test isolation or the order of tests inside a project, use the [`isolate`](/config/isolate) and [`sequence.sequencer`](/config/sequence#sequence-sequencer) options. ::: details Example Consider this example: diff --git a/config/server.md b/config/server.md index 94a986a2..e7c3623e 100644 --- a/config/server.md +++ b/config/server.md @@ -15,9 +15,9 @@ These options should be used only as the last resort to improve performance by e Normally, Vitest should do this automatically. ::: -## deps +## server.deps -### external +### server.deps.external - **Type:** `(string | RegExp)[]` - **Default:** files inside [`moduleDirectories`](/config/deps#moduledirectories) @@ -48,7 +48,7 @@ If a string is provided, it is first normalized by prefixing the `/node_modules/ If a `RegExp` is provided, it is matched against the full file path. ::: -### inline +### server.deps.inline - **Type:** `(string | RegExp)[] | true` - **Default:** everything that is not externalized @@ -63,7 +63,7 @@ If a string is provided, it is first normalized by prefixing the `/node_modules/ If a `RegExp` is provided, it is matched against the full file path. ::: -### fallbackCJS +### server.deps.fallbackCJS - **Type:** `boolean` - **Default:** `false` diff --git a/config/snapshotenvironment.md b/config/snapshotenvironment.md index 889b5684..b6a550cf 100644 --- a/config/snapshotenvironment.md +++ b/config/snapshotenvironment.md @@ -28,5 +28,5 @@ You can extend default `VitestSnapshotEnvironment` from `vitest/snapshot` entry ::: warning This is a low-level option and should be used only for advanced cases where you don't have access to default Node.js APIs. -If you just need to configure snapshots feature, use [`snapshotFormat`](#snapshotformat) or [`resolveSnapshotPath`](#resolvesnapshotpath) options. +If you just need to configure snapshots feature, use [`snapshotFormat`](/config/snapshotformat) or [`resolveSnapshotPath`](/config/resolvesnapshotpath) options. ::: diff --git a/config/snapshotformat.md b/config/snapshotformat.md index d0e00fc3..e161c236 100644 --- a/config/snapshotformat.md +++ b/config/snapshotformat.md @@ -7,10 +7,10 @@ outline: deep - **Type:** `PrettyFormatOptions` -Format options for snapshot testing. These options are passed down to our fork of [`pretty-format`](https://www.npmjs.com/package/pretty-format). In addition to the `pretty-format` options we support `printShadowRoot: boolean`. +Format options for snapshot testing. These options are passed down to our fork of [`pretty-format`](https://npmx.dev/package/pretty-format). In addition to the `pretty-format` options we support `printShadowRoot: boolean`. ::: tip Beware that `plugins` field on this object will be ignored. -If you need to extend snapshot serializer via pretty-format plugins, please, use [`expect.addSnapshotSerializer`](/api/expect#expect-addsnapshotserializer) API or [snapshotSerializers](#snapshotserializers) option. +If you need to extend snapshot serializer via pretty-format plugins, please, use [`expect.addSnapshotSerializer`](/api/expect#expect-addsnapshotserializer) API or [snapshotSerializers](/config/snapshotserializers) option. ::: diff --git a/config/ui.md b/config/ui.md index 97be22eb..9581d659 100644 --- a/config/ui.md +++ b/config/ui.md @@ -14,7 +14,7 @@ outline: deep Enable [Vitest UI](/guide/ui). ::: warning -This features requires a [`@vitest/ui`](https://www.npmjs.com/package/@vitest/ui) package to be installed. If you do not have it already, Vitest will install it when you run the test command for the first time. +This features requires a [`@vitest/ui`](https://npmx.dev/package/@vitest/ui) package to be installed. If you do not have it already, Vitest will install it when you run the test command for the first time. ::: ::: danger SECURITY ADVICE diff --git a/config/unstubenvs.md b/config/unstubenvs.md index 7afa9dbc..0d309437 100644 --- a/config/unstubenvs.md +++ b/config/unstubenvs.md @@ -19,3 +19,7 @@ export default defineConfig({ }, }) ``` + +::: warning +Be aware that this option may cause problems with async [concurrent tests](/api/test#test-concurrent). If enabled, the completion of one test will restore all the values changed with [`vi.stubEnv`](/api/vi#vi-stubenv), including those currently being used by other tests in progress. +::: diff --git a/config/unstubglobals.md b/config/unstubglobals.md index 6c0d984b..47c8e8ea 100644 --- a/config/unstubglobals.md +++ b/config/unstubglobals.md @@ -19,3 +19,7 @@ export default defineConfig({ }, }) ``` + +::: warning +Be aware that this option may cause problems with async [concurrent tests](/api/test#test-concurrent). If enabled, the completion of one test will restore all global values that were changed with [`vi.stubGlobal`](/api/vi#vi-stubglobal), including those currently being used by other tests in progress. +::: diff --git a/config/update.md b/config/update.md index 78512712..29f2b602 100644 --- a/config/update.md +++ b/config/update.md @@ -7,11 +7,17 @@ outline: deep # update {#update} -- **Type:** `boolean | 'new' | 'all'` +- **Type:** `boolean | 'new' | 'all' | 'none'` - **Default:** `false` -- **CLI:** `-u`, `--update`, `--update=false`, `--update=new` +- **CLI:** `-u`, `--update`, `--update=false`, `--update=new`, `--update=none` -Update snapshot files. The behaviour depends on the value: +Define snapshot update behavior. -- `true` or `'all'`: updates all changed snapshots and delete obsolete ones +- `true` or `'all'`: updates all changed snapshots and deletes obsolete ones - `new`: generates new snapshots without changing or deleting obsolete ones +- `none`: does not write snapshots and fails on snapshot mismatches, missing snapshots, and obsolete snapshots + +When `update` is `false` (the default), Vitest resolves snapshot update mode by environment: + +- Local runs (non-CI): works same as `new` +- CI runs (`process.env.CI` is truthy): works same as `none` diff --git a/guide/advanced/pool.md b/guide/advanced/pool.md index 635d04e3..cebe4aea 100644 --- a/guide/advanced/pool.md +++ b/guide/advanced/pool.md @@ -13,7 +13,7 @@ Vitest runs tests in a pool. By default, there are several pool runners: - `typescript` to run typechecking on tests ::: tip -See [`vitest-pool-example`](https://www.npmjs.com/package/vitest-pool-example) for example of a custom pool runner implementation. +See [`vitest-pool-example`](https://npmx.dev/package/vitest-pool-example) for example of a custom pool runner implementation. ::: ## Usage diff --git a/guide/browser/component-testing.md b/guide/browser/component-testing.md index f8f81243..0492546c 100644 --- a/guide/browser/component-testing.md +++ b/guide/browser/component-testing.md @@ -123,7 +123,11 @@ test('ProductList filters and displays products correctly', async () => { ## Testing Library 集成 {#testing-library-integration} +<<<<<<< HEAD 虽然 Vitest 为流行的框架提供了官方依赖包 ([`vitest-browser-vue`](https://www.npmjs.com/package/vitest-browser-vue)、[`vitest-browser-react`](https://www.npmjs.com/package/vitest-browser-react)、[`vitest-browser-svelte`](https://www.npmjs.com/package/vitest-browser-svelte)),但对于尚未官方支持的框架,你可以通过 [Testing Library](https://testing-library.com/) 进行继承。 +======= +While Vitest provides official packages for popular frameworks ([`vitest-browser-vue`](https://npmx.dev/package/vitest-browser-vue), [`vitest-browser-react`](https://npmx.dev/package/vitest-browser-react), [`vitest-browser-svelte`](https://npmx.dev/package/vitest-browser-svelte)), you can integrate with [Testing Library](https://testing-library.com/) for frameworks not yet officially supported. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ### 何时使用 Testing Library {#when-to-use-testing-library} @@ -166,10 +170,17 @@ test('Solid component handles user interaction', async () => { 与 Vitest 配合使用效果良好的流行 Testing Library 包: +<<<<<<< HEAD - [`@testing-library/solid`](https://github.com/solidjs/solid-testing-library) - 用于Solid.js - [`@marko/testing-library`](https://testing-library.com/docs/marko-testing-library/intro) - 用于Marko - [`@testing-library/svelte`](https://testing-library.com/docs/svelte-testing-library/intro) - [`vitest-browser-svelte`](https://www.npmjs.com/package/vitest-browser-svelte) 的替代方案 - [`@testing-library/vue`](https://testing-library.com/docs/vue-testing-library/intro) - [`vitest-browser-vue`](https://www.npmjs.com/package/vitest-browser-vue) 的替代方案 +======= +- [`@testing-library/solid`](https://github.com/solidjs/solid-testing-library) - For Solid.js +- [`@marko/testing-library`](https://testing-library.com/docs/marko-testing-library/intro) - For Marko +- [`@testing-library/svelte`](https://testing-library.com/docs/svelte-testing-library/intro) - Alternative to [`vitest-browser-svelte`](https://npmx.dev/package/vitest-browser-svelte) +- [`@testing-library/vue`](https://testing-library.com/docs/vue-testing-library/intro) - Alternative to [`vitest-browser-vue`](https://npmx.dev/package/vitest-browser-vue) +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ::: tip 迁移路径 当你使用的框架后续获得 Vitest 官方支持时,可以通过替换 Testing Library 的 `render` 函数来逐步迁移,同时保持大部分测试逻辑不变。 diff --git a/guide/browser/index.md b/guide/browser/index.md index 83f662aa..ff31d643 100644 --- a/guide/browser/index.md +++ b/guide/browser/index.md @@ -55,13 +55,21 @@ bun add -D vitest @vitest/browser-preview ::: ::: warning +<<<<<<< HEAD 不过,要在 CI 中运行测试,我们需要安装 [`playwright`](https://npmjs.com/package/playwright) 或 [`webdriverio`](https://www.npmjs.com/package/webdriverio) 。我们还建议在本地测试时切换到这两个选项中的一个,而不是使用默认的 `preview` 提供程序,因为它依赖于模拟事件而不是使用 Chrome DevTools 协议。 +======= +However, to run tests in CI you need to install either [`playwright`](https://npmx.dev/package/playwright) or [`webdriverio`](https://npmx.dev/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. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 如果你还没有使用这些工具中的任何一个,我们建议从 Playwright 开始,因为它支持并行执行,可显著提升测试速度。 ::: tabs key:provider == Playwright +<<<<<<< HEAD [Playwright](https://npmjs.com/package/playwright) 是一个用于网络测试和自动化的框架。 +======= +[Playwright](https://npmx.dev/package/playwright) is a framework for Web Testing and Automation. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ::: code-group ```bash [npm] @@ -78,7 +86,11 @@ bun add -D vitest @vitest/browser-playwright ``` == WebdriverIO +<<<<<<< HEAD [WebdriverIO](https://www.npmjs.com/package/webdriverio) 允许我们使用 WebDriver 协议在本地运行测试。 +======= +[WebdriverIO](https://npmx.dev/package/webdriverio) allows you to run tests locally using the WebDriver protocol. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ::: code-group ```bash [npm] @@ -356,7 +368,11 @@ npx vitest --browser.headless 在这种情况下,Vitest 将使用 Chrome 浏览器以无头模式运行。 ::: warning +<<<<<<< HEAD 默认情况下Headless模式不可用。我们需要使用 [`playwright`](https://npmjs.com/package/playwright) 或 [`webdriverio`](https://www.npmjs.com/package/webdriverio) 提供程序来启用此功能。 +======= +Headless mode is not available by default. You need to use either [`playwright`](https://npmx.dev/package/playwright) or [`webdriverio`](https://npmx.dev/package/webdriverio) providers to enable this feature. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ::: ## 示例 {#examples} @@ -394,9 +410,15 @@ test('properly handles form inputs', async () => { 其他框架也有社区提供的软件包: +<<<<<<< HEAD - [`vitest-browser-lit`](https://github.com/EskiMojo14/vitest-browser-lit) 渲染 [lit](https://lit.dev) 组件 - [`vitest-browser-preact`](https://github.com/JoviDeCroock/vitest-browser-preact) 渲染 [preact](https://preactjs.com) 组件 - [`vitest-browser-qwik`](https://github.com/kunai-consulting/vitest-browser-qwik) 渲染 [qwik](https://qwik.dev) 组件 +======= +- [`vitest-browser-lit`](https://github.com/EskiMojo14/vitest-browser-lit) to render [lit](https://lit.dev) components +- [`vitest-browser-preact`](https://github.com/JoviDeCroock/vitest-browser-preact) to render [preact](https://preactjs.com) components +- [`vitest-browser-qwik`](https://github.com/QwikDev/vitest-browser-qwik) to render [qwik](https://qwik.dev) components +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 如果你的框架没有被包含在内,请随时创建你自己的软件包——它是一个简单的封装,围绕着框架渲染器和 `page.elementLocator` API。我们会在本页面添加指向它的链接。请确保其名称以 `vitest-browser-` 开头。 diff --git a/guide/browser/trace-view.md b/guide/browser/trace-view.md index 5f6ce258..8ea28137 100644 --- a/guide/browser/trace-view.md +++ b/guide/browser/trace-view.md @@ -57,7 +57,53 @@ export default defineConfig({ 追踪文件在报告器中作为 [注释](/guide/test-annotations) 形式呈现。例如,在 HTML 报告器中,你可以在测试详情页中找到追踪文件的链接。 +<<<<<<< HEAD ## 预览 {#preview} +======= +## Trace markers + +You can add explicit named markers to make the trace timeline easier to read: + +```ts +import { page } from 'vitest/browser' + +document.body.innerHTML = ` + +` + +await page.getByRole('button', { name: 'Sign in' }).mark('sign in button rendered') +``` + +Both `page.mark(name)` and `locator.mark(name)` are available. + +You can also group multiple operations under one marker with `page.mark(name, callback)`: + +```ts +await page.mark('sign in flow', async () => { + await page.getByRole('textbox', { name: 'Email' }).fill('john@example.com') + await page.getByRole('textbox', { name: 'Password' }).fill('secret') + await page.getByRole('button', { name: 'Sign in' }).click() +}) +``` + +You can also wrap reusable helpers with [`vi.defineHelper()`](/api/vi#vi-defineHelper) so trace entries point to where the helper is called, not its internals: + +```ts +import { vi } from 'vitest' +import { page } from 'vitest/browser' + +const myRender = vi.defineHelper(async (content: string) => { + document.body.innerHTML = content + await page.elementLocator(document.body).mark('render helper') +}) + +test('renders content', async () => { + await myRender('') // trace points to this line +}) +``` + +## Preview +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 要打开追踪文件,可以使用 Playwright Trace Viewer。在终端中运行以下命令: @@ -69,6 +115,30 @@ npx playwright show-trace "path-to-trace-file" 或者,你可以在浏览器中打开 https://trace.playwright.dev 并在那里上传追踪文件。 +<<<<<<< HEAD ## 局限性 {#limitations} 目前,Vitest 无法填充 Trace Viewer 中的 "Sources" 标签页。这意味着虽然你可以看到测试期间捕获的操作和截图,但无法直接在 Trace Viewer 中查看测试的源代码。你需要返回代码编辑器查看测试实现。 +======= +Trace Viewer showing the trace timeline and rendered component +Trace Viewer showing the trace timeline and rendered component + +## Source Location + +When you open a trace, you'll notice that Vitest groups browser interactions and links them back to the exact line in your test that triggered them. This happens automatically for: + +- `expect.element(...)` assertions +- Interactive actions like `click`, `fill`, `type`, `hover`, `selectOptions`, `upload`, `dragAndDrop`, `tab`, `keyboard`, `wheel`, and screenshots + +Under the hood, Playwright still records its own low-level action events as usual. Vitest wraps them with source-location groups so you can jump straight from the trace timeline to the relevant line in your test. + +Keep in mind that plain assertions like `expect(value).toBe(...)` run in Node, not the browser, so they won't show up in the trace. + +For anything not covered automatically, you can use `page.mark()` or `locator.mark()` to add your own trace groups — see [Trace markers](#trace-markers) above. + +::: warning + +Currently a source view of a trace can be only displayed properly when viewing it on the machine generated a trace with `playwright show-trace` CLI. This is expected to be fixed soon (see https://github.com/microsoft/playwright/pull/39307). + +::: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 diff --git a/guide/browser/visual-regression-testing.md b/guide/browser/visual-regression-testing.md index bdf31633..761383a6 100644 --- a/guide/browser/visual-regression-testing.md +++ b/guide/browser/visual-regression-testing.md @@ -356,7 +356,11 @@ Diff image: 要点在于,将视觉回归测试与常规测试分离运行。 否则,你可能会因截图差异引发的失败日志而浪费数小时进行排查。 +<<<<<<< HEAD #### 测试组织建议 {#organizing-your-tests} +======= +### Organizing Your Tests +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 首先,应将视觉回归测试与其他测试隔离管理。 建议单独建立一个 `visual` 文件夹(或根据项目结构选择更合适的目录名称)来存放这些测试用例,以便维护与执行。 @@ -380,15 +384,24 @@ Diff image: - `vitest --project visual` ::: +<<<<<<< HEAD #### 持续集成( CI )环境配置 {#ci-setup} +======= +### CI Setup +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 在 CI 环境中运行视觉回归测试时,需要确保浏览器已正确安装。至于如何安装,则取决于你所使用的 CI 服务提供商及其运行环境。 ::: tabs key:provider == Playwright +<<<<<<< HEAD [Playwright](https://npmjs.com/package/playwright) 能让浏览器安装与管理变得非常简单。 你只需固定所用的 Playwright 版本,并在运行测试之前加入以下命令或脚本: +======= +[Playwright](https://npmx.dev/package/playwright) makes this easy. Just pin +your version and add this before running tests: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```yaml [.github/workflows/ci.yml] # ...the rest of the workflow @@ -398,9 +411,15 @@ Diff image: == WebdriverIO +<<<<<<< HEAD [WebdriverIO](https://www.npmjs.com/package/webdriverio) 要求用户自行准备浏览器环境。不过, [ @browser-actions ](https://github.com/browser-actions) 团队已经为此提供了方便的解决方案, 帮你轻松完成浏览器的安装与配置。 +======= +[WebdriverIO](https://npmx.dev/package/webdriverio) expects you to bring +your own browsers. The folks at +[@browser-actions](https://github.com/browser-actions) have your back: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```yaml [.github/workflows/ci.yml] # ...the rest of the workflow @@ -420,7 +439,11 @@ Diff image: run: npm run test:visual ``` +<<<<<<< HEAD #### 更新工作流程 {#the-update-workflow} +======= +### The Update Workflow +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 关键点来了——切勿在每一次 Pull Request 中都自动更新截图, *(那只会带来混乱)*。更稳妥的方式,是建立一个手动触发的工作流程, @@ -567,14 +590,17 @@ jobs: 你的测试依旧在本地运行,只是将浏览器托管到云端执行。 这基于 Playwright 的远程浏览器功能,但所有云端基础设施均由 Microsoft 负责维护与管理。 +<<<<<<< HEAD #### 测试组织建议 +======= +### Organizing Your Tests +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 为控制成本,应将视觉回归测试与其他测试分离管理, 并确保只有那些实际需要截取页面截图的用例才会调用该服务。 最为简洁高效的做法,是使用 [Test Projects](/guide/projects) 功能来隔离这些测试。 - ```ts [vitest.config.ts] import { env } from 'node:process' import { defineConfig } from 'vitest/config' @@ -605,9 +631,9 @@ export default defineConfig({ connectOptions: { wsEndpoint: `${env.PLAYWRIGHT_SERVICE_URL}?${new URLSearchParams({ 'api-version': '2025-09-01', - os: 'linux', // always use Linux for consistency + 'os': 'linux', // always use Linux for consistency // helps identifying runs in the service's dashboard - runName: `Vitest ${env.CI ? 'CI' : 'local'} run @${new Date().toISOString()}`, + 'runName': `Vitest ${env.CI ? 'CI' : 'local'} run @${new Date().toISOString()}`, })}`, exposeNetwork: '', headers: { @@ -630,6 +656,7 @@ export default defineConfig({ }, }) ``` +<<<<<<< HEAD 该服务会提供两个关键环境变量: @@ -637,6 +664,8 @@ export default defineConfig({ - `PLAYWRIGHT_SERVICE_ACCESS_TOKEN`:你的身份认证令牌 +======= +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 按照 [官方指南创建 Playwright 工作区](https://learn.microsoft.com/en-us/azure/app-testing/playwright-workspaces/quickstart-run-end-to-end-tests?tabs=playwrightcli&pivots=playwright-test-runner#create-a-workspace)。 @@ -662,7 +691,11 @@ export default defineConfig({ } ``` +<<<<<<< HEAD #### 运行测试 +======= +### Running Tests +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```bash # Local development @@ -680,7 +713,11 @@ npm run test:visual -- --update - **按量计费**:仅有视觉测试会消耗服务分钟数,成本可控; - **零运维负担**:无需配置 Docker 或复杂的工作流,几乎不需额外维护。 +<<<<<<< HEAD #### 持续集成( CI )环境配置 +======= +### CI Setup +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 在 CI 平台中,将所需的密钥添加到环境变量或机密配置中: diff --git a/guide/browser/why.md b/guide/browser/why.md index b82db58e..47897aba 100644 --- a/guide/browser/why.md +++ b/guide/browser/why.md @@ -12,7 +12,11 @@ outline: deep 有不同的方法来测试 JavaScript 代码。一些测试框架在 Node.js 中模拟浏览器环境,而其他框架则在真实浏览器中运行测试。在这种情况下,[jsdom](https://www.npmjs.com/package/jsdom) 是一个模拟浏览器环境的规范实现,可以与 Jest 或 Vitest 等测试运行器一起使用,而其他测试工具,如 [WebdriverIO](https://webdriver.io/) 或 [Cypress](https://www.cypress.io/) 则允许开发者在真实浏览器中测试他们的应用,或者在 [Playwright](https://playwright.dev/) 的情况下提供一个浏览器引擎。 +<<<<<<< HEAD ### 模拟警告 {#the-simulation-caveat} +======= +There are different ways to test JavaScript code. Some testing frameworks simulate browser environments in Node.js, while others run tests in real browsers. In this context, [jsdom](https://npmx.dev/package/jsdom) is an example of a spec implementation that simulates a browser environment by being used with a test runner like Jest or Vitest, while other testing tools such as [WebdriverIO](https://webdriver.io/) or [Cypress](https://www.cypress.io/) allow developers to test their applications in a real browser or in case of [Playwright](https://playwright.dev/) provide you a browser engine. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 在模拟环境(如 jsdom 或 happy-dom)中测试 JavaScript 程序简化了测试设置并提供了易于使用的 API,使它们适用于许多项目并增加了对测试结果的信心。然而,需要牢记的是,这些工具仅模拟浏览器环境而不是实际浏览器,这可能导致模拟环境和真实环境之间存在一些差异。因此,测试结果可能会出现误报或漏报。 diff --git a/guide/cli-generated.md b/guide/cli-generated.md index df12abb4..c624092b 100644 --- a/guide/cli-generated.md +++ b/guide/cli-generated.md @@ -16,7 +16,11 @@ - **命令行终端:** `-u, --update [type]` - **配置:** [update](/config/update) +<<<<<<< HEAD 更新快照(接受 boolean, "new" 或 "all") +======= +Update snapshot (accepts boolean, "new", "all" or "none") +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ### watch @@ -102,7 +106,11 @@ - **命令行终端:** `--reporter ` - **配置:** [reporters](/config/reporters) +<<<<<<< HEAD 指定报告器(default、blob、verbose、dot、json、tap、tap-flat、junit、tree、hanging-process、github-actions) +======= +Specify reporters (default, agent, blob, verbose, dot, json, tap, tap-flat, junit, tree, hanging-process, github-actions) +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ### outputFile diff --git a/guide/cli.md b/guide/cli.md index cc3cba79..cd8b8d4d 100644 --- a/guide/cli.md +++ b/guide/cli.md @@ -171,7 +171,11 @@ bun vitest ## 选项 {#options} ::: tip +<<<<<<< HEAD Vitest 支持 CLI 参数的 both camel case 和 kebab case 。例如,`--passWithNoTests` 和 `--pass-with-no-tests` 都有效(`--no-color` 和 `--inspect-brk` 是例外)。 +======= +Vitest supports both camel case and kebab case for [CLI arguments](https://github.com/cacjs/cac#dot-nested-options). For example, `--passWithNoTests` and `--pass-with-no-tests` will both work (`--no-color` and `--inspect-brk` are the exceptions). +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 Vitest 还支持不同的指定值的方式:`--reporter dot` 和 `--reporter=dot` 都是有效的。 @@ -242,5 +246,3 @@ vitest run --shard=3/3 ```sh vitest --merge-reports --reporter=junit ``` - -[cac's dot notation]: https://github.com/cacjs/cac#dot-nested-options diff --git a/guide/common-errors.md b/guide/common-errors.md index 2d10d756..3ac79594 100644 --- a/guide/common-errors.md +++ b/guide/common-errors.md @@ -8,8 +8,14 @@ title: 常见错误 | 指南 如果你收到一个 **module cannot be found** 的报错,则可能意味着几种不同情况: +<<<<<<< HEAD 1. 你拼错了路径。确保路径正确。 2. 你可能依赖于 `tsconfig.json` 中的 `baseUrl`。默认情况下,Vite 不考虑 `tsconfig.json`,因此如果你依赖此行为,你可能需要自己安装 [`vite-tsconfig-paths`](https://www.npmjs.com/package/vite-tsconfig-paths)。 +======= +1. You misspelled the path. Make sure the path is correct. + +2. It's possible that you rely on `baseUrl` in your `tsconfig.json`. Vite doesn't take into account `tsconfig.json` by default, so you might need to install [`vite-tsconfig-paths`](https://npmx.dev/package/vite-tsconfig-paths) yourself, if you rely on this behavior. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```ts import tsconfigPaths from 'vite-tsconfig-paths' diff --git a/guide/environment.md b/guide/environment.md index 07472577..7f1e5248 100644 --- a/guide/environment.md +++ b/guide/environment.md @@ -8,10 +8,17 @@ Vitest 提供 [`environment`](/config/environment) 选项以在特定环境中 默认情况下,你可以使用这些环境: +<<<<<<< HEAD - `node` 为默认环境 - `jsdom` 通过提供 Browser API 模拟浏览器环境,使用 [`jsdom`](https://github.com/jsdom/jsdom) 包 - `happy-dom` 通过提供 Browser API 模拟浏览器环境,被认为比 jsdom 更快,但缺少一些 API,使用 [`happy-dom`](https://github.com/capricorn86/happy-dom) 包 - `edge-runtime` 模拟 Vercel 的 [edge-runtime](https://edge-runtime.vercel.app/),使用 [`@edge-runtime/vm`](https://www.npmjs.com/package/@edge-runtime/vm) 包 +======= +- `node` is default environment +- `jsdom` emulates browser environment by providing Browser API, uses [`jsdom`](https://github.com/jsdom/jsdom) package +- `happy-dom` emulates browser environment by providing Browser API, and considered to be faster than jsdom, but lacks some API, uses [`happy-dom`](https://github.com/capricorn86/happy-dom) package +- `edge-runtime` emulates Vercel's [edge-runtime](https://edge-runtime.vercel.app/), uses [`@edge-runtime/vm`](https://npmx.dev/package/@edge-runtime/vm) package +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ::: info 当使用 `jsdom` 或 `happy-dom` 环境时,Vitest 在导入 [CSS](https://vitejs.dev/guide/features.html#css) 和 [资源文件](https://vitejs.dev/guide/features.html#static-assets) 时遵循与 Vite 相同的规则。如果在导入外部依赖时出现 `unknown extension .css` 错误,则需要通过将所有相关包添加到 [`server.deps.inline`](/config/server#inline) 中,手动内联整个导入链。例如,在以下导入链中:`源代码 -> package-1 -> package-2 -> package-3`,如果错误发生在 `package-3`,你需要将这三个包都添加到 `server.deps.inline` 中。 diff --git a/guide/extending-matchers.md b/guide/extending-matchers.md index f9ccef12..06300420 100644 --- a/guide/extending-matchers.md +++ b/guide/extending-matchers.md @@ -110,29 +110,29 @@ expect.extend({ customMatcher }) 断言方法可以访问上下文 `this` 对象中的这些属性: -### `isNot` +## `isNot` 如果断言是在 `not` 方法上调用的( `expect(received).not.toBeFoo()` ),则返回 true。你无需手动处理该逻辑,Vitest 会自动反转 `pass` 的值。 -### `promise` +## `promise` 如果断言是在 `resolved/rejected` 中调用的,它的值将包含此断言的名称。否则,它将是一个空字符串。 -### `equals` +## `equals` 这是一个工具函数,他可以帮助你比较两个值。如果是相同的则返回 true,反之返回 false。这个方法几乎在每个断言内部都有使用。默认情况下,它支持非对称的断言。 -### `utils` +## `utils` 它包含了一系列工具函数,你可以使用它们来显示信息。 `this` 上下文也包含了当前测试的信息,你可以通过调用 `expect.getState()` 来获取它,其中最有用的属性是: -### `currentTestName` +## `currentTestName` 当前测试的全称(包括 describe 块)。 -### `task` 4.1.0 {#task} +## `task` 4.1.0 {#task} Contains a reference to [the `Test` runner task](/api/advanced/runner#tasks) when available. @@ -140,15 +140,15 @@ Contains a reference to [the `Test` runner task](/api/advanced/runner#tasks) whe When using the global `expect` with concurrent tests, `this.task` is `undefined`. Use `context.expect` instead to ensure `task` is available in custom matchers. ::: -### `testPath` +## `testPath` 当前正在执行的测试文件路径。 -### `environment` +## `environment` 当前 [`environment`](/config/environment) 的名称(例如 `jsdom`)。 -### `soft` +## `soft` 断言是否以 [`soft`](/api/expect#soft) 方式调用。您无需手动处理该逻辑,Vitest 始终会捕获错误。 diff --git a/guide/ide.md b/guide/ide.md index 0b52b684..c3d03990 100644 --- a/guide/ide.md +++ b/guide/ide.md @@ -12,19 +12,19 @@ const { isDark } = useData() ## VS Code Official {#vs-code}

- +vscode logo

[GitHub](https://github.com/vitest-dev/vscode) | [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=vitest.explorer) -![](https://i.ibb.co/bJCbCf2/202203292020.gif) +![A gif of vscode extension in vscode](https://i.ibb.co/bJCbCf2/202203292020.gif) ## JetBrains IDE WebStorm、PhpStorm、IntelliJ IDEA Ultimate 和其他 JetBrains IDE 内置了对 Vitest 的支持。

- +webstorm logo

[WebStorm Help](https://www.jetbrains.com/help/webstorm/vitest.html) | [IntelliJ IDEA Ultimate Help](https://www.jetbrains.com/help/idea/vitest.html) | [PhpStorm Help](https://www.jetbrains.com/help/phpstorm/vitest.html) diff --git a/guide/improving-performance.md b/guide/improving-performance.md index 3177979a..f6e5e39b 100644 --- a/guide/improving-performance.md +++ b/guide/improving-performance.md @@ -87,7 +87,25 @@ export default defineConfig({ 你可以通过 [`test.dir`](/config/dir) 选项限制 Vitest 搜索文件的工作目录。如果根目录中存在不相关的文件夹和文件,这将加快搜索速度。 +<<<<<<< HEAD ## 运行池 {#pool} +======= +## Caching Between Reruns + +In watch mode, Vitest caches all transformed files in memory, which makes reruns fast. However, this cache is discarded once the test run finishes. By enabling [`experimental.fsModuleCache`](/config/experimental#experimental-fsmodulecache), Vitest persists this cache to the file system so it can be reused across reruns. + +This improvement is most noticeable when rerunning a small number of tests that depend on a large module graph. For full test suites, parallelization already mitigates the cost because other tests populate the in-memory cache while earlier tests are still running. For example, running one test file with a huge module graph (>900 modules): + +```shell +# the first run +Duration 8.75s (transform 4.02s, setup 629ms, import 5.52s, tests 2.52s, environment 0ms, prepare 3ms) + +# the second run +Duration 5.90s (transform 842ms, setup 543ms, import 2.35s, tests 2.94s, environment 0ms, prepare 3ms) +``` + +## Pool +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 默认情况下,Vitest 在 `pool: 'forks'` 中运行测试。虽然 `'forks'` 池更适合解决兼容性问题([hanging process](/guide/common-errors.html#failed-to-terminate-worker) 和[segfaults](/guide/common-errors.html#segfaults-and-native-code-errors)),但在较大的项目中,它可能比 `pool: 'threads'` 稍慢。 diff --git a/guide/migration.md b/guide/migration.md index 0c37e49d..1a136766 100644 --- a/guide/migration.md +++ b/guide/migration.md @@ -5,9 +5,24 @@ outline: deep # 迁移指南 {#migration-guide} +<<<<<<< HEAD ## 迁移到 Vitest 4.0 {#vitest-4} ### V8 Code Coverage Major Changes {#v8-code-coverage-major-changes} +======= +[Migrating to Vitest 3.0](https://v3.vitest.dev/guide/migration) | [Migrating to Vitest 2.0](https://v2.vitest.dev/guide/migration) + +## Migrating to Vitest 4.0 {#vitest-4} + +::: warning Prerequisites +Vitest 4.0 requires **Vite >= 6.0.0** and **Node.js >= 20.0.0**. Before proceeding +with any other migration steps, ensure your environment meets these requirements. +Running Vitest 4.0 on older versions of Vite or Node.js is not supported and may +result in unexpected errors. +::: + +### V8 Code Coverage Major Changes +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 Vitest 的 V8 覆盖率提供器现在使用了更精准的结果映射逻辑,从 Vitest v3 升级后,你可能会看到覆盖率报告的内容有变化。 diff --git a/guide/mocking.md b/guide/mocking.md index 57e6d805..01c0d226 100644 --- a/guide/mocking.md +++ b/guide/mocking.md @@ -162,7 +162,11 @@ mocked() // 是一个 spy 函数 ``` ::: warning +<<<<<<< HEAD 别忘了,这只是 [mocks _external_ access](#mocking-pitfalls)。在本例中,如果 `original` 在内部调用 `mocked`,它将始终调用模块中定义的函数,而不是 mock 工厂中的函数。 +======= +Don't forget that this only [mocks _external_ access](/guide/mocking/modules#mocking-modules-pitfalls). In this example, if `original` calls `mocked` internally, it will always call the function defined in the module, not in the mock factory. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ::: ### 模拟当前日期 {#mock-the-current-date} diff --git a/guide/mocking/file-system.md b/guide/mocking/file-system.md index f7ab1c6a..8cb33486 100644 --- a/guide/mocking/file-system.md +++ b/guide/mocking/file-system.md @@ -2,7 +2,11 @@ 模拟文件系统可以确保测试不依赖于实际的文件系统,从而使测试更加可靠和可预测。这种隔离有助于避免之前测试产生的副作用。它允许测试错误条件和边缘情况,而这些情况在实际文件系统中可能难以或无法复制,例如权限问题、磁盘满场景或读写错误。 +<<<<<<< HEAD Vitest 没有开箱即用地提供任何文件系统模拟 API。你可以使用 `vi.mock` 手动模拟 `fs` 模块,但这很难维护。相反,我们推荐使用 [`memfs`](https://www.npmjs.com/package/memfs) 来为你完成这项工作。`memfs` 创建一个内存中的文件系统,它模拟文件系统操作而不触及实际磁盘。这种方法快速且安全,避免了对真实文件系统的任何潜在副作用。 +======= +Vitest doesn't provide any file system mocking API out of the box. You can use `vi.mock` to mock the `fs` module manually, but it's hard to maintain. Instead, we recommend using [`memfs`](https://npmx.dev/package/memfs) to do that for you. `memfs` creates an in-memory file system, which simulates file system operations without touching the actual disk. This approach is fast and safe, avoiding any potential side effects on the real file system. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ## 示例 {#example} diff --git a/guide/open-telemetry.md b/guide/open-telemetry.md index 371a47b0..011882cf 100644 --- a/guide/open-telemetry.md +++ b/guide/open-telemetry.md @@ -143,7 +143,7 @@ export default defineConfig({ 你可以使用任何支持 OpenTelemetry API 的开源或商业产品来查看追踪。如果是初次接触 OpenTelemetry,我们推荐从 [Jaeger](https://www.jaegertracing.io/docs/2.11/getting-started/#all-in-one) 开始,因为它真的很容易设置。 - +an example of open telemetry result in jaeger ## `@opentelemetry/api` {#opentelemetry-api} diff --git a/guide/profiling-test-performance.md b/guide/profiling-test-performance.md index 7696ff20..aa028107 100644 --- a/guide/profiling-test-performance.md +++ b/guide/profiling-test-performance.md @@ -112,21 +112,106 @@ test('formatter works', () => { Vitest UI demonstrating barrel file issues -To see how files are transformed, you can use `VITEST_DEBUG_DUMP` environment variable to write transformed files in the file system: +To see how files are transformed, you can open the "Module Info" view in the UI: -```bash -$ VITEST_DEBUG_DUMP=true vitest --run +The module info view for an inlined module +The module info view for an inlined module + +## File Import + +Some modules just take a long time to load. To identify which modules are the slowest, enable [`experimental.importDurations`](/config/experimental#experimental-importdurations) in your configuration: + +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + experimental: { + importDurations: { + print: true, + }, + }, + }, +}) +``` - RUN v2.1.1 /x/vitest/examples/profiling -... +This will print a breakdown of the slowest imports after your tests finish: -$ ls .vitest-dump/ -_x_examples_profiling_global-setup_ts-1292904907.js -_x_examples_profiling_test_prime-number_test_ts-1413378098.js -_src_prime-number_ts-525172412.js +```bash +Import Duration Breakdown (Top 10) + +Module Self Total +my-test.test.ts 5ms 620ms [████████████████████] +date-fns/index.js 500ms 500ms [████████████████░░░░] # [!code error] +src/utils/helpers.ts 10ms 120ms [████████░░░░░░░░░░░░] ``` +<<<<<<< HEAD ## 代码覆盖率 {#code-coverage} +======= +You can also use `--experimental.importDurations.print` from the CLI without changing your configuration: + +```bash +vitest --experimental.importDurations.print +``` + +Once you've identified the slow modules, there are several strategies to speed up imports: + +### Use Specific Entry Points + +Many libraries ship multiple entry points. Importing the main entry point (which is often a [barrel file](https://vitejs.dev/guide/performance.html#avoid-barrel-files)) can pull in far more code than you need. + +For example, `date-fns` re-exports hundreds of functions from its main entry point. Instead of importing from the top-level module, import directly from the specific function: + +```ts +import { format } from 'date-fns' // [!code --] +import { format } from 'date-fns/format' // [!code ++] +``` + +### Use `resolve.alias` to Redirect Imports + +If a dependency doesn't provide granular entry points, or if third-party code imports the heavy entry point, you can use [`resolve.alias`](https://vite.dev/config/shared-options#resolve-alias) to redirect imports to a lighter alternative: + +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + resolve: { + alias: [ + { + find: /^date-fns$/, + replacement: join(dirname(require.resolve('date-fns/package.json')), 'index.cjs'), + }, + ] + }, +}) +``` + +### Use the Dependency Optimizer + +Vitest can bundle external libraries into a single file using [`deps.optimizer`](/config/deps#deps-optimizer), which reduces the overhead of importing packages with many internal modules: + +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + deps: { + optimizer: { + ssr: { + enabled: true, + include: ['date-fns'], + }, + }, + }, + }, +}) +``` + +This is especially effective for UI libraries and packages with deep import trees. Use `optimizer.ssr` for `node`/`edge` environments and `optimizer.client` for `jsdom`/`happy-dom` environments. + +## Code Coverage +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 如果你的项目中代码覆盖率生成较慢,您可以使用 `DEBUG=vitest:coverage` 环境变量来启用性能日志记录。 diff --git a/guide/projects.md b/guide/projects.md index 4cc8e860..c64b1994 100644 --- a/guide/projects.md +++ b/guide/projects.md @@ -42,11 +42,21 @@ export default defineConfig({ }) ``` +<<<<<<< HEAD Vitest 会将 `packages` 中的每个文件夹视为独立项目,即使其中没有配置文件。如果 glob 模式匹配到文件,它将验证文件名是否以 `vitest.config`/`vite.config` 开头,或匹配 `(vite|vitest).*.config.*` 模式,以确保它是 Vitest 配置文件。例如,以下配置文件是有效的: +======= +Vitest will treat every folder in `packages` as a separate project even if it doesn't have a config file inside. If a project entry resolves to a file (either from a glob pattern or a direct file path), Vitest will validate that the name either: + +- starts with `vitest.config` or `vite.config` (for example, `vitest.config.unit.ts`) +- or matches `vitest..config.*` / `vite..config.*`, where `` can contain letters, numbers, `_`, and `-` + +For example, these config files are valid: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 - `vitest.config.ts` - `vite.config.js` - `vitest.unit.config.ts` +- `vitest.e2e-node.config.ts` - `vite.e2e.config.js` - `vitest.config.unit.js` - `vite.config.e2e.js` diff --git a/guide/reporters.md b/guide/reporters.md index a9fa4087..5098394e 100644 --- a/guide/reporters.md +++ b/guide/reporters.md @@ -99,7 +99,15 @@ export default defineConfig({ 默认情况下(即如果没有指定报告器),Vitest 会在底部显示运行测试的摘要及其状态。一旦测试套件通过,其状态将被报告在摘要的顶部。 +<<<<<<< HEAD 我们可以通过配置报告器来禁用摘要: +======= +::: tip +When Vitest detects it is running inside an AI coding agent, the [`agent`](#agent-reporter) reporter is used instead to reduce output and minimize token usage. You can override this by explicitly configuring the [`reporters`](/config/reporters) option. +::: + +You can disable the summary by configuring the reporter: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 :::code-group ```ts [vitest.config.ts] @@ -548,18 +556,27 @@ export default defineConfig({ ### GitHub Actions 报告器 {#github-actions-reporter} +<<<<<<< HEAD 输出 [工作流命令](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message) 为测试失败提供注释。当 `process.env.GITHUB_ACTIONS === 'true'` 时,会自动启用 [`default`](#default-reporter)报告器。 +======= +Output [workflow commands](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message) +to provide annotations for test failures. This reporter is automatically enabled when the `reporters` option is not configured and `process.env.GITHUB_ACTIONS === 'true'` (on GitHub Actions environment). +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 GitHub Actions GitHub Actions +<<<<<<< HEAD 当你使用自定义报告器时,如果想在 GitHub Actions 中显示结果,需要手动把 `github-actions` 添加到报告器列表中。 +======= +If you configure reporters, you need to explicitly add `github-actions`. +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```ts export default defineConfig({ test: { - reporters: process.env.GITHUB_ACTIONS ? ['dot', 'github-actions'] : ['dot'], + reporters: process.env.GITHUB_ACTIONS === 'true' ? ['dot', 'github-actions'] : ['dot'], }, }) ``` @@ -569,7 +586,7 @@ export default defineConfig({ ```ts export default defineConfig({ test: { - reporters: process.env.GITHUB_ACTIONS + reporters: process.env.GITHUB_ACTIONS === 'true' ? [ 'default', ['github-actions', { onWritePath(path) { @@ -593,7 +610,92 @@ export default defineConfig({ }) ``` +<<<<<<< HEAD ### Blob 报告器 +======= +The GitHub Actions reporter automatically generates a [Job Summary](https://github.blog/news-insights/product-news/supercharging-github-actions-with-job-summaries/) with an overview of your test results. The summary includes test file and test case statistics, and highlights flaky tests that required retries. + +GitHub Actions Job Summary +GitHub Actions Job Summary + +The job summary is enabled by default and writes to the path specified by `$GITHUB_STEP_SUMMARY`. You can override it by using the `jobSummary.outputPath` option: + +```ts +export default defineConfig({ + test: { + reporters: [ + ['github-actions', { + jobSummary: { + outputPath: '/home/runner/jobs/summary/step', + }, + }], + ], + }, +}) +``` + +To disable the job summary: + +```ts +export default defineConfig({ + test: { + reporters: [ + ['github-actions', { jobSummary: { enabled: false } }], + ], + }, +}) +``` + +The flaky tests section of the summary includes permalink URLs that link test names directly to the relevant source lines on GitHub. These links are generated automatically using environment variables that GitHub Actions provides (`$GITHUB_REPOSITORY`, `$GITHUB_SHA`, and `$GITHUB_WORKSPACE`), so no configuration is needed in most cases. + +If you need to override these values — for example, when running in a container or a custom environment — you can customize them via the `fileLinks` option: + +- `repository`: the GitHub repository in `owner/repo` format. Defaults to `process.env.GITHUB_REPOSITORY`. +- `commitHash`: the commit SHA to use in permalink URLs. Defaults to `process.env.GITHUB_SHA`. +- `workspacePath`: the absolute path to the root of the repository on disk. Used to compute relative file paths for the permalink URLs. Defaults to `process.env.GITHUB_WORKSPACE`. + +All three values must be available for the links to be generated. + +```ts +export default defineConfig({ + test: { + reporters: [ + ['github-actions', { + jobSummary: { + fileLinks: { + repository: 'owner/repo', + commitHash: 'abcdefg', + workspacePath: '/home/runner/work/repo/', + }, + }, + }], + ], + }, +}) +``` + +### Agent Reporter + +Outputs a minimal report optimized for AI coding assistants and LLM-based workflows. Only failed tests and their error messages are displayed. Console logs from passing tests and the summary section are suppressed to reduce token usage. + +This reporter is automatically enabled when no `reporters` option is configured and Vitest detects it is running inside an AI coding agent. If you configure custom reporters, you can explicitly add `agent`: + +:::code-group +```bash [CLI] +npx vitest --reporter=agent +``` + +```ts [vitest.config.ts] +export default defineConfig({ + test: { + reporters: ['agent'] + }, +}) +``` +::: + +### Blob Reporter +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 将测试结果存储在计算机上,以便以后可以使用 [`--merge-reports`](/guide/cli#merge-reports) 命令进行合并。 默认情况下,将所有结果存储在 `.vitest-reports` 文件夹中,但可以用 `--outputFile` 或 `--outputFile.blob` 标志覆盖。 diff --git a/guide/snapshot.md b/guide/snapshot.md index c81c6236..0435cd0d 100644 --- a/guide/snapshot.md +++ b/guide/snapshot.md @@ -79,7 +79,17 @@ it('toUpperCase', () => { vitest -u ``` +<<<<<<< HEAD ## 文件快照 {#file-snapshots} +======= +### CI behavior + +By default, Vitest does not write snapshots in CI (`process.env.CI` is truthy) and any snapshot mismatches, missing snapshots, and obsolete snapshots fail the run. See [`update`](/config/update) for the details. + +An **obsolete snapshot** is a snapshot entry (or snapshot file) that no longer matches any collected test. This usually happens after removing or renaming tests. + +## File Snapshots +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 调用 `toMatchSnapshot()` 时,我们将所有快照存储在格式化的快照文件中。这意味着我们需要转义快照字符串中的一些字符(即双引号 `"` 和反引号 `` ` ``)。同时,你可能会丢失快照内容的语法突出显示(如果它们是某种语言)。 diff --git a/guide/test-context.md b/guide/test-context.md index 79f28884..9bf6759b 100644 --- a/guide/test-context.md +++ b/guide/test-context.md @@ -22,11 +22,11 @@ it('should work', ({ task }) => { ## 内置测试上下文 {#built-in-test-context} -#### `task` +### `task` 包含关于测试的元数据的只读对象。 -#### `expect` +### `expect` 绑定到当前测试的 `expect` API: @@ -52,7 +52,7 @@ it.concurrent('math is hard', ({ expect }) => { }) ``` -#### `skip` +### `skip` ```ts function skip(note?: string): never @@ -79,7 +79,7 @@ it('math is hard', ({ skip, mind }) => { }) ``` -#### `annotate` 3.2.0 {#annotate} +### `annotate` 3.2.0 {#annotate} ```ts function annotate( @@ -102,7 +102,7 @@ test('annotations API', async ({ annotate }) => { }) ``` -#### `signal` 3.2.0 {#signal} +### `signal` 3.2.0 {#signal} 一个由 Vitest 控制的 [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) ,在以下场景下会被触发中止: @@ -117,11 +117,11 @@ it('stop request when test times out', async ({ signal }) => { }, 2000) ``` -#### `onTestFailed` +### `onTestFailed` [`onTestFailed`](/api/hooks#ontestfailed) 与当前测试用例绑定。当你并发执行多个测试并希望只对某个具体测试进行特殊处理时,这个 API 会非常有用。 -#### `onTestFinished` +### `onTestFinished` [`onTestFinished`](/api/hooks#ontestfailed) 与当前测试用例绑定。当你并发执行多个测试并希望只对某个特定测试进行特殊处理时,这个 API 会非常有帮助。 @@ -505,7 +505,7 @@ test.describe('a nested suite', () => { Consider overriding it on the top level of the module, or by using [`injected`](#default-fixture-injected) option and providing the value in the project config. -Also note that in [non-isolate](/config/isolate) mode overriding a `worker` fixture will affect the fixture value in all test files running after it was overriden. +Also note that in [non-isolate](/config/isolate) mode overriding a `worker` fixture will affect the fixture value in all test files running after it was overridden. ::: #### Test Scope (Default) diff --git a/guide/test-tags.md b/guide/test-tags.md index fcfbdbea..7e676850 100644 --- a/guide/test-tags.md +++ b/guide/test-tags.md @@ -45,7 +45,11 @@ export default defineConfig({ ``` ::: warning +<<<<<<< HEAD 如果多个标签具有相同配置项且应用于同一个测试时,将按从上至下的顺序解析,或按优先级排序解析(数值越低,优先级越高)。未定义优先级的标签会先合并,随后被优先级更高的标签覆盖。 +======= +If several tags have the same options and are used on the same test, they will be resolved in the order they were specified, or sorted by priority first (the lower the number, the higher the priority). Tags without a defined priority are merged first and will be overridden by higher priority ones: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 ```ts test('flaky database test', { tags: ['flaky', 'db'] }) @@ -204,9 +208,13 @@ vitest --tags-filter=frontend vitest --tags-filter="frontend and backend" ``` +<<<<<<< HEAD 如果你使用 UI 模式,可通过 `tag:` 前缀启动筛选器,使用相同的标签表达式语法按标签过滤测试: 如果使用 UI 模式,你可以在过滤器中使用标签表达式进行过滤,例如 `tag:` 加前缀 +======= +If you are running Vitest UI, you can start a filter with a `tag:` prefix to filter out tests by tags using the same tags expression syntax: +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 The tags filter in Vitest UI The tags filter in Vitest UI diff --git a/guide/testing-types.md b/guide/testing-types.md index 2435cbdf..a00ca8cf 100644 --- a/guide/testing-types.md +++ b/guide/testing-types.md @@ -77,7 +77,11 @@ test/test.ts:999:999 - error TS2349: This expression is not callable. 如果 TypeScript 添加了对 ["throw" 类型](https://github.com/microsoft/TypeScript/pull/40468) 的支持,这些错误消息将会显著改进。在那之前,它们需要一定程度的仔细观察。 +<<<<<<< HEAD #### 具体的 "expected " 对象与类型参数 {#concrete-expected-objects-vs-typeargs} +======= +### Concrete "expected" objects vs typeargs +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 像这样的断言的错误消息: diff --git a/package.json b/package.json index 88a3acf5..ff82c4c8 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "vue": "^3.5.26" }, "devDependencies": { +<<<<<<< HEAD "@antfu/eslint-config": "^6.7.3", "@antfu/ni": "^28.1.0", "@iconify-json/carbon": "^1.2.16", @@ -37,6 +38,18 @@ "@voidzero-dev/vitepress-theme": "^4.4.2", "eslint": "^9.39.2", "eslint-factory": "^0.1.2", +======= + "@iconify-json/carbon": "catalog:", + "@iconify-json/logos": "catalog:", + "@iconify/vue": "catalog:", + "@shikijs/transformers": "^3.23.0", + "@shikijs/vitepress-twoslash": "^3.23.0", + "@unocss/reset": "catalog:", + "@vite-pwa/assets-generator": "^1.0.2", + "@vite-pwa/vitepress": "^1.1.0", + "@vitejs/plugin-vue": "catalog:", + "@voidzero-dev/vitepress-theme": "^4.8.3", +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 "https-localhost": "^4.7.1", "lint-staged": "^16.2.7", "pathe": "^2.0.3", @@ -48,8 +61,13 @@ "vite-plugin-pwa": "^1.2.0", "vitepress": "2.0.0-alpha.16", "vitepress-plugin-group-icons": "^1.7.1", +<<<<<<< HEAD "vitepress-plugin-tabs": "^0.7.3", "vitest": "^4.0.17", +======= + "vitepress-plugin-llms": "^1.11.0", + "vitepress-plugin-tabs": "^0.8.0", +>>>>>>> b72fc6b467384d82f530164b077760e0919f8532 "workbox-window": "^7.4.0" }, "simple-git-hooks": { diff --git a/public/aerius.png b/public/aerius.png new file mode 100644 index 00000000..5a05a637 Binary files /dev/null and b/public/aerius.png differ diff --git a/public/github-actions-job-summary-dark.png b/public/github-actions-job-summary-dark.png new file mode 100644 index 00000000..d1d40d1b Binary files /dev/null and b/public/github-actions-job-summary-dark.png differ diff --git a/public/github-actions-job-summary-light.png b/public/github-actions-job-summary-light.png new file mode 100644 index 00000000..5c9bc078 Binary files /dev/null and b/public/github-actions-job-summary-light.png differ diff --git a/public/nuxtlabs.svg b/public/nuxtlabs.svg deleted file mode 100644 index d2935645..00000000 --- a/public/nuxtlabs.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/og-vitest-4-1.jpg b/public/og-vitest-4-1.jpg new file mode 100644 index 00000000..42e39ee9 Binary files /dev/null and b/public/og-vitest-4-1.jpg differ diff --git a/public/trace-viewer-dark.png b/public/trace-viewer-dark.png new file mode 100644 index 00000000..b62e6968 Binary files /dev/null and b/public/trace-viewer-dark.png differ diff --git a/public/trace-viewer-light.png b/public/trace-viewer-light.png new file mode 100644 index 00000000..965708c0 Binary files /dev/null and b/public/trace-viewer-light.png differ diff --git a/public/ui/dark-ui-details-bottom.png b/public/ui/dark-ui-details-bottom.png new file mode 100644 index 00000000..017bd6f3 Binary files /dev/null and b/public/ui/dark-ui-details-bottom.png differ diff --git a/public/ui/dark-ui-details-right.png b/public/ui/dark-ui-details-right.png new file mode 100644 index 00000000..25a97c2d Binary files /dev/null and b/public/ui/dark-ui-details-right.png differ diff --git a/public/ui/light-ui-details-bottom.png b/public/ui/light-ui-details-bottom.png new file mode 100644 index 00000000..a982cd1a Binary files /dev/null and b/public/ui/light-ui-details-bottom.png differ diff --git a/public/ui/light-ui-details-right.png b/public/ui/light-ui-details-right.png new file mode 100644 index 00000000..83607e96 Binary files /dev/null and b/public/ui/light-ui-details-right.png differ diff --git a/public/vercel.svg b/public/vercel.svg new file mode 100644 index 00000000..81de44e4 --- /dev/null +++ b/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/vscode-import-breakdown.png b/public/vscode-import-breakdown.png new file mode 100644 index 00000000..941ac297 Binary files /dev/null and b/public/vscode-import-breakdown.png differ