diff --git a/.vitepress/config.ts b/.vitepress/config.ts
index 5af62f4e..5ac4ca83 100644
--- a/.vitepress/config.ts
+++ b/.vitepress/config.ts
@@ -7,8 +7,13 @@ import {
groupIconMdPlugin,
groupIconVitePlugin,
} from 'vitepress-plugin-group-icons'
+<<<<<<< HEAD
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
import { version } from '../package.json'
+=======
+import llmstxt from 'vitepress-plugin-llms'
+import { version } from '../../package.json'
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
import { teamMembers } from './contributors'
import {
bluesky,
@@ -79,6 +84,7 @@ export default ({ mode }: { mode: string }) => {
'qwik': 'logos:qwik-icon',
},
}),
+ llmstxt(),
],
},
markdown: {
@@ -283,6 +289,11 @@ export default ({ mode }: { mode: string }) => {
link: '/guide/browser/multiple-setups',
docFooterText: 'Multiple Setups | Browser Mode',
},
+ {
+ text: 'Visual Regression Testing',
+ link: '/guide/browser/visual-regression-testing',
+ docFooterText: 'Visual Regression Testing | Browser Mode',
+ },
],
},
{
diff --git a/advanced/runner.md b/advanced/runner.md
index 7beaf8bc..5848e368 100644
--- a/advanced/runner.md
+++ b/advanced/runner.md
@@ -130,14 +130,20 @@ export default CustomRunner
```
::: warning
+<<<<<<< HEAD
Vitest 还会将 `ViteNodeRunner` 的实例作为 `__vitest_executor` 属性注入。你可以使用它来处理 `importFile` 方法中的文件(这是 `TestRunner` 和 `BenchmarkRunner` 的默认行为)。
`ViteNodeRunner` 暴露了 `executeId` 方法,该方法用于在友好的 Vite 环境中导入测试文件。这意味着它会在运行时解析导入并转换文件内容,以便 Node 能够理解。
+=======
+Vitest also injects an instance of `ModuleRunner` from `vite/module-runner` as `moduleRunner` property. You can use it to process files in `importFile` method (this is default behavior of `TestRunner` and `BenchmarkRunner`).
+
+`ModuleRunner` exposes `import` method, which is used to import test files in a Vite-friendly environment. Meaning, it will resolve imports and transform file content at runtime so that Node can understand it:
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
```ts
export default class Runner {
async importFile(filepath: string) {
- await this.__vitest_executor.executeId(filepath)
+ await this.moduleRunner.import(filepath)
}
}
```
diff --git a/config/index.md b/config/index.md
index 2dd927e9..c09bd8aa 100644
--- a/config/index.md
+++ b/config/index.md
@@ -227,8 +227,13 @@ Vite 将处理内联模块。这可能有助于处理以 ESM 格式传送 `.js`
#### deps.optimizer {#deps-optimizer}
+<<<<<<< HEAD
- **类型:** `{ ssr?, web? }`
- **参考:** [依赖优化选项](https://cn.vitejs.dev/config/dep-optimization-options.html)
+=======
+- **Type:** `{ ssr?, client? }`
+- **See also:** [Dep Optimization Options](https://vitejs.dev/config/dep-optimization-options.html)
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
启用依赖优化。如果你有很多测试,这可能会提高它们的性能。
@@ -239,7 +244,11 @@ Vite 将处理内联模块。这可能有助于处理以 ESM 格式传送 `.js`
- 你的 `alias` 配置现在在捆绑包中得到处理
- 测试中的代码更接近于它在浏览器中的运行方式
+<<<<<<< HEAD
请注意,只有 `deps.experimentalOptimizer?.[mode].include` 选项中的包会被捆绑(一些插件会自动填充它,比如 Svelte)。 你可以在 [Vite](https://cn.vitejs.dev/config/dep-optimization-options.html) 文档中阅读有关可用选项的更多信息。默认情况,Vitest 的 `experimentalOptimizer.web` 用在 `jsdom` 和 `happy-dom`, 在 `node` 和 `edge` 环境下使用 `experimentalOptimizer.ssr`,但这可以在 [`transformMode`](#transformmode) 进行配置。
+=======
+Be aware that only packages in `deps.optimizer?.[mode].include` option are bundled (some plugins populate this automatically, like Svelte). You can read more about available options in [Vite](https://vitejs.dev/config/dep-optimization-options.html) docs (Vitest doesn't support `disable` and `noDiscovery` options). By default, Vitest uses `optimizer.client` for `jsdom` and `happy-dom` environments, and `optimizer.ssr` for `node` and `edge` environments.
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
此选项还继承了你的 `optimizeDeps` 配置(对于 web 环境, Vitest 将会继承 `optimizeDeps`,对于 ssr 则是 `ssr.optimizeDeps`)。如果你在 `deps.experimentalOptimizer` 中重新定义 `include`/`exclude`/`entries` 选项,它将在运行测试时覆盖你的 `optimizeDeps`。如果它们在 `exclude` 中配置,Vitest 会自动从 `include` 中删除相同的选项。
@@ -254,13 +263,21 @@ Vite 将处理内联模块。这可能有助于处理以 ESM 格式传送 `.js`
启用依赖优化。
+<<<<<<< HEAD
::: warning
此选项仅适用于 Vite 4.3.2 及更高版本。
:::
+=======
+#### deps.client {#deps-client}
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
#### deps.web 0.34.2+
+<<<<<<< HEAD
#### deps.web
+=======
+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.
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
- **类型:** `{ transformAssets?, ... }`
@@ -268,7 +285,7 @@ Vite 将处理内联模块。这可能有助于处理以 ESM 格式传送 `.js`
通常,`node_modules` 内的文件是外部化的,但这些选项也会影响 [`server.deps.external`](#server-deps-external) 中的文件。
-#### deps.web.transformAssets
+#### deps.client.transformAssets
- **类型:** `boolean`
- **默认值:** `true`
@@ -281,7 +298,7 @@ Vitest 是否应该像 Vite 在浏览器中一样处理静态资源(.png、.sv
目前,此选项适用于 [`vmThreads`](#vmthreads) 和 [`vmForks`](#vmForks) 池。
:::
-#### deps.web.transformCss
+#### deps.client.transformCss
- **类型:** `boolean`
- **默认值:** `true`
@@ -294,7 +311,7 @@ Vitest 是否应该像 Vite 在浏览器中一样处理静态资源(.css, .scs
目前,此选项仅适用于 [`vmThreads`](#vmthreads) 和 [`vmForks`](#vmForks) 池。
:::
-#### deps.web.transformGlobPattern
+#### deps.client.transformGlobPattern
- **类型:** `RegExp | RegExp[]`
- **默认值:** `[]`
@@ -556,7 +573,7 @@ import type { Environment } from 'vitest'
export default {
name: 'custom',
- transformMode: 'ssr',
+ viteEnvironment: 'ssr',
setup() {
// custom setup
return {
@@ -616,7 +633,7 @@ In CI, or when run from a non-interactive shell, "watch" mode is not the default
Vitest reruns tests based on the module graph which is populated by static and dynamic `import` statements. However, if you are reading from the file system or fetching from a proxy, then Vitest cannot detect those dependencies.
-To correctly rerun those tests, you can define a regex pattern and a function that retuns a list of test files to run.
+To correctly rerun those tests, you can define a regex pattern and a function that returns a list of test files to run.
```ts
import { defineConfig } from 'vitest/config'
@@ -1681,6 +1698,7 @@ test('doNotRun', () => {
将在每次测试前调用 [`vi.unstubAllGlobals`](/api/#vi-unstuballglobals)。
+<<<<<<< HEAD
### testTransformMode {#testtransformmode}
- **类型:** `{ web?, ssr? }`
@@ -1717,6 +1735,8 @@ export default defineConfig({
})
```
+=======
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
### snapshotFormat
- **类型:** `PrettyFormatOptions`
diff --git a/guide/browser/assertion-api.md b/guide/browser/assertion-api.md
index 371ed353..d51f6f32 100644
--- a/guide/browser/assertion-api.md
+++ b/guide/browser/assertion-api.md
@@ -951,7 +951,12 @@ function toHaveSelection(selection?: string): Promise
这在检查元素内是否选择了文本或部分文本时非常有用。该元素可以是文本类型的输入框、`textarea`,或者是任何包含文本的其他元素,例如段落、`span`、`div` 等。
::: warning
+<<<<<<< HEAD
预期的选择是一个字符串,它不允许检查选择范围的索引。
+=======
+The expected selection is a string, it does not allow to check for
+selection range indices.
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
:::
```html
@@ -1000,3 +1005,216 @@ await expect.element(queryByTestId('parent')).toHaveSelection('ected text')
await expect.element(queryByTestId('prev')).not.toHaveSelection()
await expect.element(queryByTestId('next')).toHaveSelection('ne')
```
+
+## toMatchScreenshot experimental
+
+```ts
+function toMatchScreenshot(
+ options?: ScreenshotMatcherOptions,
+): Promise
+function toMatchScreenshot(
+ name?: string,
+ options?: ScreenshotMatcherOptions,
+): Promise
+```
+
+::: tip
+The `toMatchScreenshot` assertion can be configured globally in your
+[Vitest config](/guide/browser/config#browser-expect-tomatchscreenshot).
+:::
+
+This assertion allows you to perform visual regression testing by comparing
+screenshots of elements or pages against stored reference images.
+
+When differences are detected beyond the configured threshold, the test fails.
+To help identify the changes, the assertion generates:
+
+- The actual screenshot captured during the test
+- The expected reference screenshot
+- A diff image highlighting the differences (when possible)
+
+::: warning Screenshots Stability
+The assertion automatically retries taking screenshots until two consecutive
+captures yield the same result. This helps reduce flakiness caused by
+animations, loading states, or other dynamic content. You can control this
+behavior with the `timeout` option.
+
+However, browser rendering can vary across:
+
+- Different browsers and browser versions
+- Operating systems (Windows, macOS, Linux)
+- Screen resolutions and pixel densities
+- GPU drivers and hardware acceleration
+- Font rendering and system fonts
+
+It is recommended to read the
+[Visual Regression Testing guide](/guide/browser/visual-regression-testing) to
+implement this testing strategy efficiently.
+:::
+
+::: tip
+When a screenshot comparison fails due to **intentional changes**, you can
+update the reference screenshot by pressing the `u` key in watch mode, or by
+running tests with the `-u` or `--update` flags.
+:::
+
+```html
+
+```
+
+```ts
+// basic usage, auto-generates screenshot name
+await expect.element(getByTestId('button')).toMatchScreenshot()
+
+// with custom name
+await expect.element(getByTestId('button')).toMatchScreenshot('fancy-button')
+
+// with options
+await expect.element(getByTestId('button')).toMatchScreenshot({
+ comparatorName: 'pixelmatch',
+ comparatorOptions: {
+ allowedMismatchedPixelRatio: 0.01,
+ },
+})
+
+// with both name and options
+await expect.element(getByTestId('button')).toMatchScreenshot('fancy-button', {
+ comparatorName: 'pixelmatch',
+ comparatorOptions: {
+ allowedMismatchedPixelRatio: 0.01,
+ },
+})
+```
+
+### Options
+
+- `comparatorName: "pixelmatch" = "pixelmatch"`
+
+ The name of the algorithm/library used for comparing images.
+
+ Currently, [`"pixelmatch"`](https://github.com/mapbox/pixelmatch) is the only
+ supported comparator.
+
+- `comparatorOptions: object`
+
+ These options allow changing the behavior of the comparator. What properties
+ can be set depends on the chosen comparator algorithm.
+
+ Vitest has set default values out of the box, but they can be overridden.
+
+ - [`"pixelmatch"` options](#pixelmatch-comparator-options)
+
+ ::: warning
+ **Always explicitly set `comparatorName` to get proper type inference for
+ `comparatorOptions`**.
+
+ Without it, TypeScript won't know which options are valid:
+
+ ```ts
+ // ❌ TypeScript can't infer the correct options
+ await expect.element(button).toMatchScreenshot({
+ comparatorOptions: {
+ // might error when new comparators are added
+ allowedMismatchedPixelRatio: 0.01,
+ },
+ })
+
+ // ✅ TypeScript knows these are pixelmatch options
+ await expect.element(button).toMatchScreenshot({
+ comparatorName: 'pixelmatch',
+ comparatorOptions: {
+ allowedMismatchedPixelRatio: 0.01,
+ },
+ })
+ ```
+ :::
+
+- `screenshotOptions: object`
+
+ The same options allowed by
+ [`locator.screenshot()`](/guide/browser/locators.html#screenshot), except for:
+
+ - `'base64'`
+ - `'path'`
+ - `'save'`
+ - `'type'`
+
+- `timeout: number = 5_000`
+
+ Time to wait until a stable screenshot is found.
+
+ Setting this value to `0` disables the timeout, but if a stable screenshot
+ can't be determined the process will not end.
+
+#### `"pixelmatch"` comparator options
+
+The following options are available when using the `"pixelmatch"` comparator:
+
+- `allowedMismatchedPixelRatio: number | undefined = undefined`
+
+ The maximum allowed ratio of differing pixels between the captured screenshot
+ and the reference image.
+
+ Must be a value between `0` and `1`.
+
+ For example, `allowedMismatchedPixelRatio: 0.02` means the test will pass
+ if up to 2% of pixels differ, but fail if more than 2% differ.
+
+- `allowedMismatchedPixels: number | undefined = undefined`
+
+ The maximum number of pixels that are allowed to differ between the captured
+ screenshot and the stored reference image.
+
+ If set to `undefined`, any non-zero difference will cause the test to fail.
+
+ For example, `allowedMismatchedPixels: 10` means the test will pass if 10 or
+ fewer pixels differ, but fail if 11 or more differ.
+
+- `threshold: number = 0.1`
+
+ Acceptable perceived color difference between the same pixel in two images.
+
+ Value ranges from `0` (strict) to `1` (very lenient). Lower values mean small
+ differences will be detected.
+
+ The comparison uses the [YIQ color space](https://en.wikipedia.org/wiki/YIQ).
+
+- `includeAA: boolean = false`
+
+ If `true`, disables detection and ignoring of anti-aliased pixels.
+
+- `alpha: number = 0.1`
+
+ Blending level of unchanged pixels in the diff image.
+
+ Ranges from `0` (white) to `1` (original brightness).
+
+- `aaColor: [r: number, g: number, b: number] = [255, 255, 0]`
+
+ Color used for anti-aliased pixels in the diff image.
+
+- `diffColor: [r: number, g: number, b: number] = [255, 0, 0]`
+
+ Color used for differing pixels in the diff image.
+
+- `diffColorAlt: [r: number, g: number, b: number] | undefined = undefined`
+
+ Optional alternative color for dark-on-light differences, to help show what's
+ added vs. removed.
+
+ If not set, `diffColor` is used for all differences.
+
+- `diffMask: boolean = false`
+
+ If `true`, shows only the diff as a mask on a transparent background, instead
+ of overlaying it on the original image.
+
+ Anti-aliased pixels won't be shown (if detected).
+
+::: warning
+When both `allowedMismatchedPixels` and `allowedMismatchedPixelRatio` are set,
+the more restrictive value is used.
+
+For example, if you allow 100 pixels or 2% ratio, and your image has 10,000
+pixels, the effective limit would be 100 pixels instead of 200.
+:::
diff --git a/guide/browser/commands.md b/guide/browser/commands.md
index c9df8eb0..01d42acf 100644
--- a/guide/browser/commands.md
+++ b/guide/browser/commands.md
@@ -11,7 +11,11 @@ outline: deep
### 文件处理
+<<<<<<< HEAD
在浏览器端的测试中,你可以通过 `readFile` 、`writeFile` 和 `removeFile` 这些 API 来操作文件。从 Vitest 3.2 版本起,所有文件路径都会相对于 [项目](/guide/projects) 根目录解析(默认为 `process.cwd()`,除非你手动修改过)。在此之前,路径是以测试文件所在位置作为基准进行解析的。
+=======
+You can use the `readFile`, `writeFile`, and `removeFile` APIs to handle files in your browser tests. Since Vitest 3.2, all paths are resolved relative to the [project](/guide/projects) root (which is `process.cwd()`, unless overridden manually). Previously, paths were resolved relative to the test file.
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
默认情况下,Vitest 使用 `utf-8` 编码,但你可以使用选项覆盖它。
@@ -162,7 +166,11 @@ Vitest 在上下文对象上公开了一些 `webdriverio` 特有属性。
- `browser` 是 `WebdriverIO.Browser` API.
+<<<<<<< HEAD
Vitest 通过在调用命令前调用 `browser.switchToFrame` 自动将 `webdriver` 上下文切换到测试 iframe,因此 `$` 和 `$` 方法将引用 iframe 内的元素,而不是 orchestrator 中的元素,但非 Webdriver API 仍将引用 parent frame 上下文。
+=======
+Vitest automatically switches the `webdriver` context to the test iframe by calling `browser.switchFrame` before the command is called, so `$` and `$$` methods refer to the elements inside the iframe, not in the orchestrator, but non-webdriver APIs will still refer to the parent frame context.
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
::: tip
如果我们使用的是 TypeScript,请记得在您的 [setup 文件](/config/#setupfile)或 [config 文件](/config/)中引用 `@vitest/browser/providers/webdriverio` ,以便获得自动补全功能。
diff --git a/guide/browser/config.md b/guide/browser/config.md
index 0d402377..a260161c 100644
--- a/guide/browser/config.md
+++ b/guide/browser/config.md
@@ -325,3 +325,152 @@ export interface BrowserScript {
::: info
这是浏览器与 Vitest 服务器建立 WebSocket 连接所需的时间。在正常情况下,此超时不应被触发。
:::
+
+## browser.expect
+
+- **Type:** `ExpectOptions`
+
+### browser.expect.toMatchScreenshot
+
+Default options for the
+[`toMatchScreenshot` assertion](/guide/browser/assertion-api.html#tomatchscreenshot).
+These options will be applied to all screenshot assertions.
+
+::: tip
+Setting global defaults for screenshot assertions helps maintain consistency
+across your test suite and reduces repetition in individual tests. You can still
+override these defaults at the assertion level when needed for specific test cases.
+:::
+
+```ts
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ browser: {
+ enabled: true,
+ expect: {
+ toMatchScreenshot: {
+ comparatorName: 'pixelmatch',
+ comparatorOptions: {
+ threshold: 0.2,
+ allowedMismatchedPixels: 100,
+ },
+ resolveScreenshotPath: ({ arg, browserName, ext, testFileName }) =>
+ `custom-screenshots/${testFileName}/${arg}-${browserName}${ext}`,
+ },
+ },
+ },
+ },
+})
+```
+
+[All options available in the `toMatchScreenshot` assertion](/guide/browser/assertion-api#options)
+can be configured here. Additionally, two path resolution functions are
+available: `resolveScreenshotPath` and `resolveDiffPath`.
+
+#### browser.expect.toMatchScreenshot.resolveScreenshotPath
+
+- **Type:** `(data: PathResolveData) => string`
+- **Default output:** `` `${root}/${testFileDirectory}/${screenshotDirectory}/${testFileName}/${arg}-${browserName}-${platform}${ext}` ``
+
+A function to customize where reference screenshots are stored. The function
+receives an object with the following properties:
+
+- `arg: string`
+
+ Path **without** extension, sanitized and relative to the test file.
+
+ This comes from the arguments passed to `toMatchScreenshot`; if called
+ without arguments this will be the auto-generated name.
+
+ ```ts
+ test('calls `onClick`', () => {
+ expect(locator).toMatchScreenshot()
+ // arg = "calls-onclick-1"
+ })
+
+ expect(locator).toMatchScreenshot('foo/bar/baz.png')
+ // arg = "foo/bar/baz"
+
+ expect(locator).toMatchScreenshot('../foo/bar/baz.png')
+ // arg = "foo/bar/baz"
+ ```
+
+- `ext: string`
+
+ Screenshot extension, with leading dot.
+
+ This can be set through the arguments passed to `toMatchScreenshot`, but
+ the value will fall back to `'.png'` if an unsupported extension is used.
+
+- `browserName: string`
+
+ The instance's browser name.
+
+- `platform: NodeJS.Platform`
+
+ The value of
+ [`process.platform`](https://nodejs.org/docs/v22.16.0/api/process.html#processplatform).
+
+- `screenshotDirectory: string`
+
+ The value provided to
+ [`browser.screenshotDirectory`](/guide/browser/config#browser-screenshotdirectory),
+ if none is provided, its default value.
+
+- `root: string`
+
+ Absolute path to the project's [`root`](/config/#root).
+
+- `testFileDirectory: string`
+
+ Path to the test file, relative to the project's [`root`](/config/#root).
+
+- `testFileName: string`
+
+ The test's filename.
+
+- `testName: string`
+
+ The [`test`](/api/#test)'s name, including parent
+ [`describe`](/api/#describe), sanitized.
+
+- `attachmentsDir: string`
+
+ The value provided to [`attachmentsDir`](/config/#attachmentsdir), if none is
+ provided, its default value.
+
+For example, to group screenshots by browser:
+
+```ts
+resolveScreenshotPath: ({ arg, browserName, ext, root, testFileName }) =>
+ `${root}/screenshots/${browserName}/${testFileName}/${arg}${ext}`
+```
+
+#### browser.expect.toMatchScreenshot.resolveDiffPath
+
+- **Type:** `(data: PathResolveData) => string`
+- **Default output:** `` `${root}/${attachmentsDir}/${testFileDirectory}/${testFileName}/${arg}-${browserName}-${platform}${ext}` ``
+
+A function to customize where diff images are stored when screenshot comparisons
+fail. Receives the same data object as
+[`resolveScreenshotPath`](#browser-expect-tomatchscreenshot-resolvescreenshotpath).
+
+For example, to store diffs in a subdirectory of attachments:
+
+```ts
+resolveDiffPath: ({ arg, attachmentsDir, browserName, ext, root, testFileName }) =>
+ `${root}/${attachmentsDir}/screenshot-diffs/${testFileName}/${arg}-${browserName}${ext}`
+```
+
+::: tip
+To have a better type safety when using built-in providers, you should reference
+one of these types (for provider that you are using) in your
+[config file](/config/):
+
+```ts
+///
+///
+```
+:::
diff --git a/guide/browser/locators.md b/guide/browser/locators.md
index c3a1c30c..c1bee035 100644
--- a/guide/browser/locators.md
+++ b/guide/browser/locators.md
@@ -234,7 +234,11 @@ function getByLabelText(
创建一个能够找到具有关联标签的元素的定位器。
+<<<<<<< HEAD
`page.getByLabelText('Username')` 定位器将在以下示例中找到所有的输入元素:
+=======
+The `page.getByLabelText('Username')` locator will find every input in the example below:
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
```html
// for/htmlFor relationship between label and form element id
@@ -1004,7 +1008,7 @@ declare module '@vitest/browser/context' {
}
```
-If the method is called on the global `page` object, then selector will be applied to the whole page. In the example bellow, `getByArticleTitle` will find all elements with an attribute `data-title` with the value of `title`. However, if the method is called on the locator, then it will be scoped to that locator.
+If the method is called on the global `page` object, then selector will be applied to the whole page. In the example below, `getByArticleTitle` will find all elements with an attribute `data-title` with the value of `title`. However, if the method is called on the locator, then it will be scoped to that locator.
```html
diff --git a/guide/browser/visual-regression-testing.md b/guide/browser/visual-regression-testing.md
new file mode 100644
index 00000000..544ea1de
--- /dev/null
+++ b/guide/browser/visual-regression-testing.md
@@ -0,0 +1,715 @@
+---
+title: Visual Regression Testing
+outline: [2, 3]
+---
+
+# Visual Regression Testing
+
+Vitest can run visual regression tests out of the box. It captures screenshots
+of your UI components and pages, then compares them against reference images to
+detect unintended visual changes.
+
+Unlike functional tests that verify behavior, visual tests catch styling issues,
+layout shifts, and rendering problems that might otherwise go unnoticed without
+thorough manual testing.
+
+## Why Visual Regression Testing?
+
+Visual bugs don’t throw errors, they just look wrong. That’s where visual
+testing comes in.
+
+- That button still submits the form... but why is it hot pink now?
+- The text fits perfectly... until someone views it on mobile
+- Everything works great... except those two containers are out of viewport
+- That careful CSS refactor works... but broke the layout on a page no one tests
+
+Visual regression testing acts as a safety net for your UI, automatically
+catching these visual changes before they reach production.
+
+## Getting Started
+
+::: warning Browser Rendering Differences
+Visual regression tests are **inherently unstable across different
+environments**. Screenshots will look different on different machines because
+of:
+
+- Font rendering (the big one. Windows, macOS, Linux, they all render text
+differently)
+- GPU drivers and hardware acceleration
+- Whether you're running headless or not
+- Browser settings and versions
+- ...and honestly, sometimes just the phase of the moon
+
+That's why Vitest includes the browser and platform in screenshot names (like
+`button-chromium-darwin.png`).
+
+For stable tests, use the same environment everywhere. We **strongly recommend**
+cloud services like
+[Microsoft Playwright Testing](https://azure.microsoft.com/en-us/products/playwright-testing)
+or [Docker containers](https://playwright.dev/docs/docker).
+:::
+
+Visual regression testing in Vitest can be done through the
+[`toMatchScreenshot` assertion](/guide/browser/assertion-api.html#tomatchscreenshot):
+
+```ts
+import { expect, test } from 'vitest'
+import { page } from '@vitest/browser/context'
+
+test('hero section looks correct', async () => {
+ // ...the rest of the test
+
+ // capture and compare screenshot
+ await expect(page.getByTestId('hero')).toMatchScreenshot('hero-section')
+})
+```
+
+### Creating References
+
+When you run a visual test for the first time, Vitest creates a reference (also
+called baseline) screenshot and fails the test with the following error message:
+
+```
+expect(element).toMatchScreenshot()
+
+No existing reference screenshot found; a new one was created. Review it before running tests again.
+
+Reference screenshot:
+ tests/__screenshots__/hero.test.ts/hero-section-chromium-darwin.png
+```
+
+This is normal. Check that the screenshot looks right, then run the test again.
+Vitest will now compare future runs against this baseline.
+
+::: tip
+Reference screenshots live in `__screenshots__` folders next to your tests.
+**Don't forget to commit them!**
+:::
+
+### Screenshot Organization
+
+By default, screenshots are organized as:
+
+```
+.
+├── __screenshots__
+│ └── test-file.test.ts
+│ ├── test-name-chromium-darwin.png
+│ ├── test-name-firefox-linux.png
+│ └── test-name-webkit-win32.png
+└── test-file.test.ts
+```
+
+The naming convention includes:
+- **Test name**: either the first argument of the `toMatchScreenshot()` call,
+or automatically generated from the test's name.
+- **Browser name**: `chrome`, `chromium`, `firefox` or `webkit`.
+- **Platform**: `aix`, `darwin`, `freebsd`, `linux`, `openbsd`, `sunos`, or
+`win32`.
+
+This ensures screenshots from different environments don't overwrite each other.
+
+### Updating References
+
+When you intentionally change your UI, you'll need to update the reference
+screenshots:
+
+```bash
+$ vitest --update
+```
+
+Review updated screenshots before committing to make sure changes are
+intentional.
+
+## Configuring Visual Tests
+
+### Global Configuration
+
+Configure visual regression testing defaults in your
+[Vitest config](/guide/browser/config#browser-expect-tomatchscreenshot):
+
+```ts [vitest.config.ts]
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ browser: {
+ expect: {
+ toMatchScreenshot: {
+ comparatorName: 'pixelmatch',
+ comparatorOptions: {
+ // 0-1, how different can colors be?
+ threshold: 0.2,
+ // 1% of pixels can differ
+ allowedMismatchedPixelRatio: 0.01,
+ },
+ },
+ },
+ },
+ },
+})
+```
+
+### Per-Test Configuration
+
+Override global settings for specific tests:
+
+```ts
+await expect(element).toMatchScreenshot('button-hover', {
+ comparatorName: 'pixelmatch',
+ comparatorOptions: {
+ // more lax comparison for text-heavy elements
+ allowedMismatchedPixelRatio: 0.1,
+ },
+})
+```
+
+## Best Practices
+
+### Test Specific Elements
+
+Unless you explicitly want to test the whole page, prefer capturing specific
+components to reduce false positives:
+
+```ts
+// ❌ Captures entire page; prone to unrelated changes
+await expect(page).toMatchScreenshot()
+
+// ✅ Captures only the component under test
+await expect(page.getByTestId('product-card')).toMatchScreenshot()
+```
+
+### Handle Dynamic Content
+
+Dynamic content like timestamps, user data, or random values will cause tests
+to fail. You can either mock the sources of dynamic content or mask them when
+using the Playwright provider by using the
+[`mask` option](https://playwright.dev/docs/api/class-page#page-screenshot-option-mask)
+in `screenshotOptions`.
+
+```ts
+await expect(page.getByTestId('profile')).toMatchScreenshot({
+ screenshotOptions: {
+ mask: [page.getByTestId('last-seen')],
+ },
+})
+```
+
+### Disable Animations
+
+Animations can cause flaky tests. Disable them during testing by injecting
+a custom CSS snippet:
+
+```css
+*, *::before, *::after {
+ animation-duration: 0s !important;
+ animation-delay: 0s !important;
+ transition-duration: 0s !important;
+ transition-delay: 0s !important;
+}
+```
+
+::: tip
+When using the Playwright provider, animations are automatically disabled
+when using the assertion: the `animations` option's value in `screenshotOptions`
+is set to `"disabled"` by default.
+:::
+
+### Set Appropriate Thresholds
+
+Tuning thresholds is tricky. It depends on the content, test environment,
+what's acceptable for your app, and might also change based on the test.
+
+Vitest does not set a default for the mismatching pixels, that's up for the
+user to decide based on their needs. The recommendation is to use
+`allowedMismatchedPixelRatio`, so that the threshold is computed on the size
+of the screenshot and not a fixed number.
+
+When setting both `allowedMismatchedPixelRatio` and
+`allowedMismatchedPixels`, Vitest uses whichever limit is stricter.
+
+### Set consistent viewport sizes
+
+As the browser instance might have a different default size, it's best to
+set a specific viewport size, either on the test or the instance
+configuration:
+
+```ts
+await page.viewport(1280, 720)
+```
+
+```ts [vitest.config.ts]
+export default defineConfig({
+ test: {
+ browser: {
+ enabled: true,
+ provider: 'playwright',
+ instances: [
+ {
+ browser: 'chromium',
+ viewport: { width: 1280, height: 720 },
+ },
+ ],
+ },
+ },
+})
+```
+
+### Use Git LFS
+
+Store reference screenshots in
+[Git LFS](https://github.com/git-lfs/git-lfs?tab=readme-ov-file) if you plan to
+have a large test suite.
+
+## Debugging Failed Tests
+
+When a visual test fails, Vitest provides three images to help debug:
+
+1. **Reference screenshot**: the expected baseline image
+1. **Actual screenshot**: what was captured during the test
+1. **Diff image**: highlights the differences, but this might not get generated
+
+You'll see something like:
+
+```
+expect(element).toMatchScreenshot()
+
+Screenshot does not match the stored reference.
+245 pixels (ratio 0.03) differ.
+
+Reference screenshot:
+ tests/__screenshots__/button.test.ts/button-chromium-darwin.png
+
+Actual screenshot:
+ tests/.vitest-attachments/button.test.ts/button-chromium-darwin-actual.png
+
+Diff image:
+ tests/.vitest-attachments/button.test.ts/button-chromium-darwin-diff.png
+```
+
+### Understanding the diff image
+
+- **Red pixels** are areas that differ between reference and actual
+- **Yellow pixels** are anti-aliasing differences (when anti-alias is not ignored)
+- **Transparent/original** are unchanged areas
+
+:::tip
+If the diff is mostly red, something's really wrong. If it's speckled with a
+few red pixels around text, you probably just need to bump your threshold.
+:::
+
+## Common Issues and Solutions
+
+### False Positives from Font Rendering
+
+Font availability and rendering varies significantly between systems. Some
+possible solutions might be to:
+
+- Use web fonts and wait for them to load:
+
+ ```ts
+ // wait for fonts to load
+ await document.fonts.ready
+
+ // continue with your tests
+ ```
+
+- Increase comparison threshold for text-heavy areas:
+
+ ```ts
+ await expect(page.getByTestId('article-summary')).toMatchScreenshot({
+ comparatorName: 'pixelmatch',
+ comparatorOptions: {
+ // 10% of the pixels are allowed to change
+ allowedMismatchedPixelRatio: 0.1,
+ },
+ })
+ ```
+
+- Use a cloud service or containerized environment for consistent font rendering.
+
+### Flaky Tests or Different Screenshot Sizes
+
+If tests pass and fail randomly, or if screenshots have different dimensions
+between runs:
+
+- Wait for everything to load, including loading indicators
+- Set explicit viewport sizes: `await page.viewport(1920, 1080)`
+- Check for responsive behavior at viewport boundaries
+- Check for unintended animations or transitions
+- Increase test timeout for large screenshots
+- Use a cloud service or containerized environment
+
+## Visual Regression Testing for Teams
+
+Remember when we mentioned visual tests need a stable environment? Well, here's
+the thing: your local machine isn't it.
+
+For teams, you've basically got three options:
+
+1. **Self-hosted runners**, complex to set up, painful to maintain
+1. **GitHub Actions**, free (for open source), works with any provider
+1. **Cloud services**, like
+[Microsoft Playwright Testing](https://azure.microsoft.com/en-us/products/playwright-testing),
+built for this exact problem
+
+We'll focus on options 2 and 3 since they're the quickest to get running.
+
+To be upfront, the main trade-offs for each are:
+
+- **GitHub Actions**: visual tests only run in CI (developers can't run them
+locally)
+- **Microsoft's service**: works everywhere but costs money and only works
+with Playwright
+
+:::: tabs key:vrt-for-teams
+=== GitHub Actions
+
+The trick here is keeping visual tests separate from your regular tests,
+otherwise, you'll waste hours checking failing logs of screenshot mismatches.
+
+#### Organizing Your Tests
+
+First, isolate your visual tests. Stick them in a `visual` folder (or whatever
+makes sense for your project):
+
+```json [package.json]
+{
+ "scripts": {
+ "test:unit": "vitest --exclude tests/visual/*.test.ts",
+ "test:visual": "vitest tests/visual/*.test.ts"
+ }
+}
+```
+
+Now developers can run `npm run test:unit` locally without visual tests getting
+in the way. Visual tests stay in CI where the environment is consistent.
+
+::: tip Alternative
+Not a fan of glob patterns? You could also use separate
+[Test Projects](/guide/projects) instead and run them using:
+
+- `vitest --project unit`
+- `vitest --project visual`
+:::
+
+#### CI Setup
+
+Your CI needs browsers installed. How you do this depends on your provider:
+
+::: tabs key:provider
+== Playwright
+
+[Playwright](https://npmjs.com/package/playwright) makes this easy. Just pin
+your version and add this before running tests:
+
+```yaml [.github/workflows/ci.yml]
+# ...the rest of the workflow
+- name: Install Playwright Browsers
+ run: npx --no playwright install --with-deps --only-shell
+```
+
+== WebdriverIO
+
+[WebdriverIO](https://www.npmjs.com/package/webdriverio) expects you to bring
+your own browsers. The folks at
+[@browser-actions](https://github.com/browser-actions) have your back:
+
+```yaml [.github/workflows/ci.yml]
+# ...the rest of the workflow
+- uses: browser-actions/setup-chrome@v1
+ with:
+ chrome-version: 120
+```
+
+:::
+
+Then run your visual tests:
+
+```yaml [.github/workflows/ci.yml]
+# ...the rest of the workflow
+# ...browser setup
+- name: Visual Regression Testing
+ run: npm run test:visual
+```
+
+#### The Update Workflow
+
+Here's where it gets interesting. You don't want to update screenshots on every
+PR automatically *(chaos!)*. Instead, create a
+manually-triggered workflow that developers can run when they intentionally
+change the UI.
+
+The workflow below:
+- Only runs on feature branches (never on main)
+- Credits the person who triggered it as co-author
+- Prevents concurrent runs on the same branch
+- Shows a nice summary:
+ - **When screenshots changed**, it lists what changed
+
+
+
+
+ - **When nothing changed**, well, it tells you that too
+
+
+
+
+::: tip
+This is just one approach. Some teams prefer PR comments (`/update-screenshots`),
+others use labels. Adjust it to fit your workflow!
+
+The important part is having a controlled way to update baselines.
+:::
+
+```yaml [.github/workflows/update-screenshots.yml]
+name: Update Visual Regression Screenshots
+
+on:
+ workflow_dispatch: # manual trigger only
+
+env:
+ AUTHOR_NAME: 'github-actions[bot]'
+ AUTHOR_EMAIL: '41898282+github-actions[bot]@users.noreply.github.com'
+ COMMIT_MESSAGE: |
+ test: update visual regression screenshots
+
+ Co-authored-by: ${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com>
+
+jobs:
+ update-screenshots:
+ runs-on: ubuntu-24.04
+
+ # safety first: don't run on main
+ if: github.ref_name != github.event.repository.default_branch
+
+ # one at a time per branch
+ concurrency:
+ group: visual-regression-screenshots@${{ github.ref_name }}
+ cancel-in-progress: true
+
+ permissions:
+ contents: write # needs to push changes
+
+ steps:
+ - name: Checkout selected branch
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.ref_name }}
+ # use PAT if triggering other workflows
+ # token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Configure Git
+ run: |
+ git config --global user.name "${{ env.AUTHOR_NAME }}"
+ git config --global user.email "${{ env.AUTHOR_EMAIL }}"
+
+ # your setup steps here (node, pnpm, whatever)
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 24
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Install Playwright Browsers
+ run: npx --no playwright install --with-deps --only-shell
+
+ # the magic happens below 🪄
+ - name: Update Visual Regression Screenshots
+ run: npm run test:visual --update
+
+ # check what changed
+ - name: Check for changes
+ id: check_changes
+ run: |
+ CHANGED_FILES=$(git status --porcelain | awk '{print $2}')
+ if [ "${CHANGED_FILES:+x}" ]; then
+ echo "changes=true" >> $GITHUB_OUTPUT
+ echo "Changes detected"
+
+ # save the list for the summary
+ echo "changed_files<> $GITHUB_OUTPUT
+ echo "$CHANGED_FILES" >> $GITHUB_OUTPUT
+ echo "EOF" >> $GITHUB_OUTPUT
+ echo "changed_count=$(echo "$CHANGED_FILES" | wc -l)" >> $GITHUB_OUTPUT
+ else
+ echo "changes=false" >> $GITHUB_OUTPUT
+ echo "No changes detected"
+ fi
+
+ # commit if there are changes
+ - name: Commit changes
+ if: steps.check_changes.outputs.changes == 'true'
+ run: |
+ git add -A
+ git commit -m "${{ env.COMMIT_MESSAGE }}"
+
+ - name: Push changes
+ if: steps.check_changes.outputs.changes == 'true'
+ run: git push origin ${{ github.ref_name }}
+
+ # pretty summary for humans
+ - name: Summary
+ run: |
+ if [[ "${{ steps.check_changes.outputs.changes }}" == "true" ]]; then
+ echo "### 📸 Visual Regression Screenshots Updated" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "Successfully updated **${{ steps.check_changes.outputs.changed_count }}** screenshot(s) on \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "#### Changed Files:" >> $GITHUB_STEP_SUMMARY
+ echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
+ echo "${{ steps.check_changes.outputs.changed_files }}" >> $GITHUB_STEP_SUMMARY
+ echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "✅ The updated screenshots have been committed and pushed. Your visual regression baseline is now up to date!" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "### ℹ️ No Screenshot Updates Required" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "The visual regression test command ran successfully but no screenshots needed updating." >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "All screenshots are already up to date! 🎉" >> $GITHUB_STEP_SUMMARY
+ fi
+```
+
+=== Microsoft Playwright Testing
+
+Your tests stay local, only the browsers run in the cloud. It's Playwright's
+remote browser feature, but Microsoft handles all the infrastructure.
+
+#### Organizing Your Tests
+
+Keep visual tests separate to control costs. Only tests that actually take
+screenshots should use the service.
+
+The cleanest approach is using [Test Projects](/guide/projects):
+
+```ts [vitest.config.ts]
+import { env } from 'node:process'
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ // ...global Vite config
+ tests: {
+ // ...global Vitest config
+ projects: [
+ {
+ extends: true,
+ test: {
+ name: 'unit',
+ include: ['tests/**/*.test.ts'],
+ // regular config, can use local browsers
+ },
+ },
+ {
+ extends: true,
+ test: {
+ name: 'visual',
+ // or you could use a different suffix, e.g.,: `tests/**/*.visual.ts?(x)`
+ include: ['visual-regression-tests/**/*.test.ts?(x)'],
+ browser: {
+ enabled: true,
+ provider: 'playwright',
+ headless: true,
+ instances: [
+ {
+ browser: 'chromium',
+ viewport: { width: 2560, height: 1440 },
+ connect: {
+ wsEndpoint: `${env.PLAYWRIGHT_SERVICE_URL}?cap=${JSON.stringify({
+ os: 'linux', // always use Linux for consistency
+ // helps identifying runs in the service's dashboard
+ runId: `Vitest ${env.CI ? 'CI' : 'local'} run @${new Date().toISOString()}`,
+ })}`,
+ options: {
+ exposeNetwork: '',
+ headers: {
+ 'x-mpt-access-key': env.PLAYWRIGHT_SERVICE_ACCESS_TOKEN,
+ },
+ timeout: 30_000,
+ },
+ },
+ },
+ ],
+ },
+ },
+ },
+ ],
+ },
+})
+```
+
+The service gives you two environment variables:
+
+- `PLAYWRIGHT_SERVICE_URL` tells Playwright where to connect
+- `PLAYWRIGHT_SERVICE_ACCESS_TOKEN` is your auth token
+
+::: danger Keep that Token Secret!
+Never commit `PLAYWRIGHT_SERVICE_ACCESS_TOKEN` to your repository. Anyone with
+the token can rack up your bill. Use environment variables locally and secrets
+in CI.
+:::
+
+Then split your `test` script like this:
+
+```json [package.json]
+{
+ "scripts": {
+ "test:visual": "vitest --project visual",
+ "test:unit": "vitest --project unit"
+ }
+}
+```
+
+#### Running Tests
+
+```bash
+# Local development
+npm run test:unit # free, runs locally
+npm run test:visual # uses cloud browsers
+
+# Update screenshots
+npm run test:visual -- --update
+```
+
+The best part of this approach is that it just works:
+
+- **Consistent screenshots**, everyone uses the same cloud browsers
+- **Works locally**, developers can run and update visual tests on their machines
+- **Pay for what you use**, only visual tests consume service minutes
+- **No Docker or workflow setups needed**, nothing to manage or maintain
+
+#### CI Setup
+
+In your CI, add the secrets:
+
+```yaml
+env:
+ PLAYWRIGHT_SERVICE_URL: ${{ vars.PLAYWRIGHT_SERVICE_URL }}
+ PLAYWRIGHT_SERVICE_ACCESS_TOKEN: ${{ secrets.PLAYWRIGHT_SERVICE_ACCESS_TOKEN }}
+```
+
+Then run your tests like normal. The service handles the rest.
+
+::::
+
+### So Which One?
+
+Both approaches work. The real question is what pain points matter most to your
+team.
+
+If you're already deep in the GitHub ecosystem, GitHub Actions is hard to beat.
+Free for open source, works with any browser provider, and you control
+everything.
+
+The downside? That "works on my machine" conversation when someone generates
+screenshots locally and they don't match CI expectations anymore.
+
+The cloud service makes sense if developers need to run visual tests locally.
+
+Some teams have designers checking their work or developers who prefer catching
+issues before pushing. It allows skipping the push-wait-check-fix-push cycle.
+
+Still on the fence? Start with GitHub Actions. You can always add the cloud
+service later if local testing becomes a pain point.
diff --git a/guide/environment.md b/guide/environment.md
index 3f2e0674..eb223337 100644
--- a/guide/environment.md
+++ b/guide/environment.md
@@ -48,7 +48,7 @@ import type { Environment } from 'vitest/environments'
export default {
name: 'custom',
- transformMode: 'ssr',
+ viteEnvironment: 'ssr',
// optional - only if you support "experimental-vm" pool
async setupVM() {
const vm = await import('node:vm')
@@ -74,7 +74,11 @@ export default {
```
::: warning
+<<<<<<< HEAD
Vitest 需要指定环境对象上的 `transformMode` 选项。它应该等于 `ssr` 或 `web`。该值决定插件如何转换源代码。如果设置为 `ssr`,则插件挂钩在转换或解析文件时将收到 `ssr: true`。 否则,`ssr` 被设置为 `false`。
+=======
+Vitest requires `viteEnvironment` option on environment object (fallbacks to the Vitest environment name by default). It should be equal to `ssr`, `client` or any custom [Vite environment](https://vite.dev/guide/api-environment) name. This value determines which environment is used to process file.
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
:::
你还可以通过 `vitest/environments` 访问默认的 Vitest 环境:
diff --git a/guide/migration.md b/guide/migration.md
index 97059be0..8f4a1ddf 100644
--- a/guide/migration.md
+++ b/guide/migration.md
@@ -138,15 +138,43 @@ $ pnpm run test:dev math.test.ts
```
:::
+<<<<<<< HEAD
### 移除废弃的 API
+=======
+### Replacing `vite-node` with [Module Runner](https://vite.dev/guide/api-environment-runtimes.html#modulerunner)
+
+Module Runner is a successor to `vite-node` implemented directly in Vite. Vitest now uses it directly instead of having a wrapper around Vite SSR handler. This means that certain features are no longer available:
+
+- `VITE_NODE_DEPS_MODULE_DIRECTORIES` environment variable was replaced with `VITEST_MODULE_DIRECTORIES`
+- Vitest no longer injects `__vitest_executor` into every [test runner](/advanced/runner). Instead, it injects `moduleRunner` which is an instance of [`ModuleRunner`](https://vite.dev/guide/api-environment-runtimes.html#modulerunner)
+- `vitest/execute` entry point was removed. It was always meant to be internal
+- [Custom environments](/guide/environment) no longer need to provide a `transformMode` property. Instead, provide `viteEnvironment`. If it is not provided, Vitest will use the environment name to transform files on the server (see [`server.environments`](https://vite.dev/guide/api-environment-instances.html))
+- `vite-node` is no longer a dependency of Vitest
+- `deps.optimizer.web` was renamed to [`deps.optimizer.client`](/config/#deps-optimizer-client). You can also use any custom names to apply optimizer configs when using other server environments
+
+Vite has its own externalization mechanism, but we decided to keep using the old one to reduce the amount of breaking changes. You can keep using [`server.deps`](/config/#server-deps) to inline or externalize packages.
+
+This update should not be noticeable unless you rely on advanced features mentioned above.
+
+### Deprecated APIs are Removed
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
Vitest 4.0 移除了以下废弃的配置项:
+<<<<<<< HEAD
- `poolMatchGlobs` 配置项,请使用 [`projects`](/guide/projects) 代替。
- `environmentMatchGlobs` 配置项,请使用 [`projects`](/guide/projects) 代替。
- `workspace` 配置项,请使用 [`projects`](/guide/projects) 代替。
此次发布还移除了所有废弃类型,这也解决了 Vitest 错误引入 `node` 类型的问题(详见 [#5481](https://github.com/vitest-dev/vitest/issues/5481) 和 [#6141](https://github.com/vitest-dev/vitest/issues/6141))。
+=======
+- `poolMatchGlobs` config option. Use [`projects`](/guide/projects) instead.
+- `environmentMatchGlobs` config option. Use [`projects`](/guide/projects) instead.
+- `workspace` config option. Use [`projects`](/guide/projects) instead.
+- `deps.external`, `deps.inline`, `deps.fallbackCJS` config options. Use `server.deps.external`, `server.deps.inline`, or `server.deps.fallbackCJS` instead.
+
+This release also removes all deprecated types. This finally fixes an issue where Vitest accidentally pulled in `@types/node` (see [#5481](https://github.com/vitest-dev/vitest/issues/5481) and [#6141](https://github.com/vitest-dev/vitest/issues/6141)).
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
## 从 Jest 迁移 {#jest}
diff --git a/guide/test-context.md b/guide/test-context.md
index 6fa7d2e5..7110be0f 100644
--- a/guide/test-context.md
+++ b/guide/test-context.md
@@ -325,7 +325,7 @@ describe('use scoped values', () => {
test.scoped({ dependency: 'new' })
test('uses scoped value', ({ dependant }) => {
- // `dependant` uses the new overriden value that is scoped
+ // `dependant` uses the new overridden value that is scoped
// to all tests in this suite
expect(dependant).toEqual({ dependency: 'new' })
})
diff --git a/package.json b/package.json
index 0e60310a..2fc4da28 100644
--- a/package.json
+++ b/package.json
@@ -49,9 +49,16 @@
"unocss": "latest",
"unplugin-vue-components": "latest",
"vite": "^6.3.5",
+<<<<<<< HEAD
"vite-plugin-pwa": "^1.0.0",
"vitepress": "2.0.0-alpha.6",
"vitepress-plugin-group-icons": "^1.6.0",
+=======
+ "vite-plugin-pwa": "^0.21.2",
+ "vitepress": "2.0.0-alpha.8",
+ "vitepress-plugin-group-icons": "^1.6.1",
+ "vitepress-plugin-llms": "^1.3.4",
+>>>>>>> d26d535abd4748e0ec0863ff3d1a0a6a7f5eb3a7
"vitepress-plugin-tabs": "^0.7.1",
"vitest": "^4.0.0-beta.2",
"workbox-window": "^7.3.0"
diff --git a/public/vrt-gha-summary-no-update-dark.png b/public/vrt-gha-summary-no-update-dark.png
new file mode 100644
index 00000000..78ad5ecd
Binary files /dev/null and b/public/vrt-gha-summary-no-update-dark.png differ
diff --git a/public/vrt-gha-summary-no-update-light.png b/public/vrt-gha-summary-no-update-light.png
new file mode 100644
index 00000000..77de12a0
Binary files /dev/null and b/public/vrt-gha-summary-no-update-light.png differ
diff --git a/public/vrt-gha-summary-update-dark.png b/public/vrt-gha-summary-update-dark.png
new file mode 100644
index 00000000..6d8d498a
Binary files /dev/null and b/public/vrt-gha-summary-update-dark.png differ
diff --git a/public/vrt-gha-summary-update-light.png b/public/vrt-gha-summary-update-light.png
new file mode 100644
index 00000000..e9381f79
Binary files /dev/null and b/public/vrt-gha-summary-update-light.png differ