diff --git a/.vitepress/components/FeaturesList.vue b/.vitepress/components/FeaturesList.vue index 56cbafd2..849e867e 100644 --- a/.vitepress/components/FeaturesList.vue +++ b/.vitepress/components/FeaturesList.vue @@ -1,10 +1,29 @@ diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 9d01d1b4..a016c971 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -469,8 +469,13 @@ function guide(): DefaultTheme.SidebarItem[] { link: '/guide/filtering', }, { +<<<<<<< HEAD text: '工作空间', link: '/guide/workspace', +======= + text: 'Test Projects', + link: '/guide/projects', +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 }, { text: '报告器「Reporters」', diff --git a/advanced/api/index.md b/advanced/api/index.md index 710e7a36..d6875d07 100644 --- a/advanced/api/index.md +++ b/advanced/api/index.md @@ -119,7 +119,11 @@ const { vitestConfig, viteConfig } = await resolveConfig({ ::: ::: warning +<<<<<<< HEAD `resolveConfig` 不会解析 `workspace`。要解析工作区配置,Vitest 需要一个已建立的 Vite 服务器。 +======= +The `resolveConfig` doesn't resolve `projects`. To resolve projects configs, Vitest needs an established Vite server. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 另外请注意,`viteConfig.test` 不会被完全解析。如果你需要 Vitest 配置,请使用 `vitestConfig` 代替。 ::: diff --git a/advanced/api/plugin.md b/advanced/api/plugin.md index fad03683..a167d628 100644 --- a/advanced/api/plugin.md +++ b/advanced/api/plugin.md @@ -53,7 +53,11 @@ Vitest 通过 `Vite` namespace 重新导出所有仅 Vite 类型的导入,我 ``` ::: +<<<<<<< HEAD 与 [`reporter.onInit`](/advanced/api/reporters#oninit) 不同,此 hooks 在 Vitest 生命周期的早期运行,允许我们更改 `coverage` 和 `reporters` 等配置。更值得注意的变化是,如果我们的插件是在项目中定义而不是在全局配置中定义的,我们可以从 [工作区项目](/guide/workspace) 操作全局配置。 +======= +Unlike [`reporter.onInit`](/advanced/api/reporters#oninit), this hooks runs early in Vitest lifecycle allowing you to make changes to configuration like `coverage` and `reporters`. A more notable change is that you can manipulate the global config from a [test project](/guide/projects) if your plugin is defined in the project and not in the global config. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ## Context @@ -93,10 +97,10 @@ function injectTestProjects( ```ts // inject a single project with a custom alias const newProjects = await injectTestProjects({ - // you can inherit the current project config by referencing `configFile` + // you can inherit the current project config by referencing `extends` // note that you cannot have a project with the name that already exists, // so it's a good practice to define a custom name - configFile: project.vite.config.configFile, + extends: project.vite.config.configFile, test: { name: 'my-custom-alias', alias: { @@ -107,7 +111,11 @@ const newProjects = await injectTestProjects({ ``` ::: warning Projects are Filtered +<<<<<<< HEAD Vitest 在配置解析期间过滤项目,因此如果用户定义了过滤器,则注入的项目可能无法解析,除非它 [与 filter 匹配](./vitest#matchesprojectfilter)。我们可以通过 `vitest.config.project` 选项更新过滤器,以始终包含我们的工作区项目: +======= +Vitest filters projects during the config resolution, so if the user defined a filter, injected project might not be resolved unless it [matches the filter](./vitest#matchesprojectfilter). You can update the filter via the `vitest.config.project` option to always include your test project: +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```ts vitest.config.project.push('my-project-name') @@ -117,7 +125,11 @@ vitest.config.project.push('my-project-name') ::: ::: tip Referencing the Current Config +<<<<<<< HEAD 如果我们想保留用户配置,可以指定 `configFile` 属性。所有其他属性都将与用户定义的配置合并。 +======= +If you want to keep the user configuration, you can specify the `extends` property. All other properties will be merged with the user defined config. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 项目的 `configFile` 可以在 Vite 的配置中访问:`project.vite.config.configFile`。 diff --git a/advanced/api/test-project.md b/advanced/api/test-project.md index fece1516..d8e95eda 100644 --- a/advanced/api/test-project.md +++ b/advanced/api/test-project.md @@ -4,10 +4,15 @@ title: TestProject # TestProject 3.0.0 {#testproject} +<<<<<<< HEAD - **别名**:在 3.0.0 之前称为 `WorkspaceProject` ::: warning 本指南描述了高级的 Node.js API。如果我们只是想创建一个工作区,请遵循 [Workspace](/guide/workspace) 指南。 +======= +::: warning +This guide describes the advanced Node.js API. If you just want to define projects, follow the ["Test Projects"](/guide/projects) guide. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ::: ## name @@ -26,6 +31,7 @@ vitest.projects.map(p => p.name) === [ 'custom' ] ``` +<<<<<<< HEAD ```ts [vitest.workspace.js] export default [ './packages/server', // 有 package.json,名称为 "@pkg/server" @@ -43,11 +49,40 @@ export default [ }, }, ] +======= +```ts [vitest.config.js] +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + projects: [ + './packages/server', // has package.json with "@pkg/server" + './utils', // doesn't have a package.json file + { + // doesn't customize the name + test: { + pool: 'threads', + }, + }, + { + // customized the name + test: { + name: 'custom', + }, + }, + ], + }, +}) +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ``` ::: ::: info +<<<<<<< HEAD 如果 [根项目](/advanced/api/vitest#getroottestproject) 不是用户工作区的一部分,则不会解析其 `name`。 +======= +If the [root project](/advanced/api/vitest#getroottestproject) is not part of user projects, its `name` will not be resolved. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ::: ## vitest @@ -279,7 +314,11 @@ dynamicExample !== staticExample // ✅ ::: ::: info +<<<<<<< HEAD 在内部,Vitest 使用此方法导入全局设置、自定义覆盖率提供者、工作区文件和自定义报告器,这意味着只要它们属于同一个 Vite 服务器,它们就共享相同的模块图。 +======= +Internally, Vitest uses this method to import global setups, custom coverage providers and custom reporters, meaning all of them share the same module graph as long as they belong to the same Vite server. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ::: ## onTestsRerun diff --git a/advanced/api/vitest.md b/advanced/api/vitest.md index 4966efbe..140b5497 100644 --- a/advanced/api/vitest.md +++ b/advanced/api/vitest.md @@ -64,7 +64,11 @@ Vitest 3 在稳定公共 API 方面迈出了一步。为了实现这一点,我 ## config +<<<<<<< HEAD 根(或全局)配置。如果启用了工作区功能,项目将引用此配置作为 `globalConfig`。 +======= +The root (or global) config. If projects are defined, they will reference this as `globalConfig`. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ::: warning 这是 Vitest 配置,它不扩展 _Vite_ 配置。它仅包含从 `test` 属性解析的值。 @@ -101,9 +105,15 @@ const testCase = vitest.state.getReportedEntity(task) // 新 API ## projects +<<<<<<< HEAD 属于用户工作区的 [测试项目](/advanced/api/test-project) 数组。如果用户未指定自定义工作区,则工作区将仅包含一个 [根项目](#getrootproject)。 Vitest 将确保工作区中始终至少有一个项目。如果用户指定了不存在的 `--project` 名称,Vitest 将抛出错误。 +======= +An array of [test projects](/advanced/api/test-project) that belong to user's projects. If the user did not specify a them, this array will only contain a [root project](#getrootproject). + +Vitest will ensure that there is always at least one project in this array. If the user specifies a non-existent `--project` name, Vitest will throw an error before this array is defined. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ## getRootProject @@ -111,7 +121,11 @@ Vitest 将确保工作区中始终至少有一个项目。如果用户指定了 function getRootProject(): TestProject ``` +<<<<<<< HEAD 返回根测试项目。根项目通常不运行任何测试,并且除非用户明确在其工作区中包含根配置,或者根本没有定义工作区,否则不会包含在 `vitest.projects` 中。 +======= +This returns the root test project. The root project generally doesn't run any tests and is not included in `vitest.projects` unless the user explicitly includes the root config in their configuration, or projects are not defined at all. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 根项目的主要目标是设置全局配置。实际上,`rootProject.config` 直接引用 `rootProject.globalConfig` 和 `vitest.config`: @@ -433,7 +447,11 @@ dynamicExample !== staticExample // ✅ ::: ::: info +<<<<<<< HEAD 在内部,Vitest 使用此方法导入全局设置、自定义覆盖率提供者、工作区文件和自定义报告器,这意味着只要它们属于同一个 Vite 服务器,它们就共享相同的模块图。 +======= +Internally, Vitest uses this method to import global setups, custom coverage providers, and custom reporters, meaning all of them share the same module graph as long as they belong to the same Vite server. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ::: ## close diff --git a/advanced/pool.md b/advanced/pool.md index a2180da1..697deb78 100644 --- a/advanced/pool.md +++ b/advanced/pool.md @@ -31,12 +31,16 @@ export default defineConfig({ }) ``` +<<<<<<< HEAD 如果我们在不同 pools 中运行测试,可以使用 [workspace](/guide/workspace) 功能: +======= +If you need to run tests in different pools, use the [`projects`](/guide/projects) feature: +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```ts [vitest.config.ts] export default defineConfig({ test: { - workspace: [ + projects: [ { extends: true, test: { @@ -48,10 +52,13 @@ export default defineConfig({ }) ``` +<<<<<<< HEAD ::: info `workspace` 字段是在 Vitest 3 中引入的。在 [Vitest 2](https://v2.vitest.dev/) 中定义工作区,需要创建一个单独的 `vitest.workspace.ts` 文件。 ::: +======= +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ## API 在 `pool` 选项中指定的文件应该导出一个函数(可以是异步的),该函数接受 `Vitest` 接口作为其第一个选项。这个函数需要返回一个与 `ProcessPool` 接口匹配的对象: @@ -69,7 +76,11 @@ export interface ProcessPool { 这个函数只会被调用一次(除非服务器配置被更新),通常最好在这个函数内初始化测试所需的一切,并在调用 `runTests` 时重复使用它。 +<<<<<<< HEAD Vitest 在安排运行新测试时调用 `runTest`。如果 `files` 为空,将不会调用它。第一个参数是一个 [TestSpecifications](/advanced/api/test-specification) 数组。在调用 `runTests` 之前,文件将使用 [`sequencer`](/config/#sequence-sequencer) 进行排序。可能(但不太可能)会有相同的文件出现两次,但它们将始终属于不同的项目 - 这是通过 [`vitest.workspace.ts`](/guide/workspace) 配置实现的。 +======= +Vitest calls `runTest` when new tests are scheduled to run. It will not call it if `files` is empty. The first argument is an array of [TestSpecifications](/advanced/api/test-specification). Files are sorted using [`sequencer`](/config/#sequence-sequencer) before `runTests` is called. It's possible (but unlikely) to have the same file twice, but it will always have a different project - this is implemented via [`projects`](/guide/projects) configuration. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 Vitest 会等到 `runTests` 执行完毕后才结束运行(即只有在 `runTests` 解决后才会触发 [`onFinished`](/advanced/reporters))。 diff --git a/advanced/runner.md b/advanced/runner.md index 84fb57eb..f5d33919 100644 --- a/advanced/runner.md +++ b/advanced/runner.md @@ -173,7 +173,11 @@ interface File extends Suite { */ filepath: string /** +<<<<<<< HEAD * 文件所属的工作区项目的名称。 +======= + * The name of the test project the file belongs to. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 */ projectName: string | undefined /** @@ -218,7 +222,11 @@ interface Test extends TaskBase { */ file: File /** +<<<<<<< HEAD * 任务是否通过调用 `t.skip()` 被跳过。 +======= + * Whether the task was skipped by calling `context.skip()`. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 */ pending?: boolean /** diff --git a/api/expect.md b/api/expect.md index dd671bb4..adb3644e 100644 --- a/api/expect.md +++ b/api/expect.md @@ -773,7 +773,11 @@ test('throws on pineapples', async () => { ## toMatchSnapshot +<<<<<<< HEAD - **类型:** `(shape?: Partial | string, message?: string) => void` +======= +- **Type:** `(shape?: Partial | string, hint?: string) => void` +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 这样可以确保一个值与最近的快照匹配。 @@ -805,7 +809,11 @@ test('matches snapshot', () => { ## toMatchInlineSnapshot +<<<<<<< HEAD - **类型:** `(shape?: Partial | string, snapshot?: string, message?: string) => void` +======= +- **Type:** `(shape?: Partial | string, snapshot?: string, hint?: string) => void` +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 这确保了一个值与最近的快照相匹配。 @@ -848,7 +856,11 @@ test('matches snapshot', () => { ## toMatchFileSnapshot {#tomatchfilesnapshot} +<<<<<<< HEAD - **类型:** `(filepath: string, message?: string) => Promise` +======= +- **Type:** `(filepath: string, hint?: string) => Promise` +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 指定文件内容与快照进行比较或更新(而非使用 `.snap` 文件)。 @@ -865,13 +877,21 @@ it('render basic', async () => { ## toThrowErrorMatchingSnapshot +<<<<<<< HEAD - **类型:** `(message?: string) => void` +======= +- **Type:** `(hint?: string) => void` +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 与 [`toMatchSnapshot`](#tomatchsnapshot) 相同,但期望的值与 [`toThrowError`](#tothrowerror) 相同。 ## toThrowErrorMatchingInlineSnapshot +<<<<<<< HEAD - **类型:** `(snapshot?: string, message?: string) => void` +======= +- **Type:** `(snapshot?: string, hint?: string) => void` +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 与 [`toMatchInlineSnapshot`](#tomatchinlinesnapshot) 类似,但期望的值与 [`toThrowError`](#tothrowerror) 相同。 diff --git a/api/index.md b/api/index.md index c413096a..5b48060f 100644 --- a/api/index.md +++ b/api/index.md @@ -179,7 +179,11 @@ test('skipped test', (context) => { }) ``` +<<<<<<< HEAD 自 Vitest 3.1 起,如果条件未知,我们可以将其作为第一个参数提供给 `skip` 方法: +======= +Since Vitest 3.1, if the condition is unknown, you can provide it to the `skip` method as the first arguments: +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```ts import { assert, test } from 'vitest' @@ -498,6 +502,7 @@ Vitest 使用 chai `format` 方法处理 `$values`。如果数值太短,可以 - **Alias:** `it.for` +<<<<<<< HEAD 作为 `test.each` 的替代,提供 [`TestContext`](/guide/test-context)。 与 `test.each` 的区别在于如何在参数中提供数组情况。 @@ -505,6 +510,15 @@ Vitest 使用 chai `format` 方法处理 `$values`。如果数值太短,可以 ```ts // `each` 展开数组用例 +======= +Alternative to `test.each` to provide [`TestContext`](/guide/test-context). + +The difference from `test.each` lies in how arrays are provided in the arguments. +Non-array arguments to `test.for` (including template string usage) work exactly the same as for `test.each`. + +```ts +// `each` spreads arrays +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 test.each([ [1, 1, 2], [1, 2, 3], @@ -514,7 +528,11 @@ test.each([ expect(a + b).toBe(expected) }) +<<<<<<< HEAD // `for` 不会展开数组用例 +======= +// `for` doesn't spread arrays (notice the square brackets around the arguments) +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 test.for([ [1, 1, 2], [1, 2, 3], @@ -525,7 +543,11 @@ test.for([ }) ``` +<<<<<<< HEAD 第二个参数是 [`TestContext`](/guide/test-context),可用于并发快照等 +======= +The 2nd argument is [`TestContext`](/guide/test-context) and can be used for concurrent snapshots, for example: +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```ts test.concurrent.for([ @@ -541,9 +563,15 @@ test.concurrent.for([ - **类型:** `(name: string | Function, fn: BenchFunction, options?: BenchOptions) => void` +<<<<<<< HEAD `bench` 定义了一个基准。在 Vitest 术语中,基准是定义一系列操作的函数。Vitest 会多次运行该函数,以显示不同的性能结果。 Vitest 使用了 [`tinybench`](https://github.com/tinylibs/tinybench)库,继承其所有可用作第三个参数的选项。 +======= +`bench` defines a benchmark. In Vitest terms, benchmark is a function that defines a series of operations. Vitest runs this function multiple times to display different performance results. + +Vitest uses the [`tinybench`](https://github.com/tinylibs/tinybench) library under the hood, inheriting all its options that can be used as a third argument. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```ts import { bench } from 'vitest' @@ -1359,6 +1387,7 @@ test('performs an organization query', async () => { ``` ::: tip +<<<<<<< HEAD 此 hook 始终以相反的顺序调用,并且不受 [`sequence.hooks`](/config/#sequence-hooks) 选项的影响。 @@ -1372,6 +1401,9 @@ test('skipped dynamically', (t) => { }) ``` +======= +This hook is always called in reverse order and is not affected by [`sequence.hooks`](/config/#sequence-hooks) option. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ::: ### onTestFailed diff --git a/api/vi.md b/api/vi.md index 3196a523..bf66effc 100644 --- a/api/vi.md +++ b/api/vi.md @@ -385,6 +385,33 @@ expect(res).toBe(5) expect(getApples).toHaveNthReturnedWith(2, 5) ``` +### vi.mockObject 3.2.0 + +- **Type:** `(value: T) => MaybeMockedDeep` + +Deeply mocks properties and methods of a given object in the same way as `vi.mock()` mocks module exports. See [automocking](/guide/mocking.html#automocking-algorithm) for the detail. + +```ts +const original = { + simple: () => 'value', + nested: { + method: () => 'real' + }, + prop: 'foo', +} + +const mocked = vi.mockObject(original) +expect(mocked.simple()).toBe(undefined) +expect(mocked.nested.method()).toBe(undefined) +expect(mocked.prop).toBe('foo') + +mocked.simple.mockReturnValue('mocked') +mocked.nested.method.mockReturnValue('mocked nested') + +expect(mocked.simple()).toBe('mocked') +expect(mocked.nested.method()).toBe('mocked nested') +``` + ### vi.isMockFunction - **类型:** `(fn: Function) => boolean` diff --git a/blog/vitest-3.md b/blog/vitest-3.md index c410b555..a7b9faf4 100644 --- a/blog/vitest-3.md +++ b/blog/vitest-3.md @@ -72,7 +72,11 @@ _January 17, 2025_ ## 内联工作区(Inline Workspace) +<<<<<<< HEAD 让我们欢呼一下,芜湖!不再需要单独的文件来定义你的[工作区](/guide/workspace) - 你可以使用 vitest.config 文件中的 `workspace` 字段指定项目数组: +======= +Rejoice! No more separate files to define your [workspace](/guide/projects) - specify an array of projects using the `workspace` field in your `vitest.config` file: +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```jsx import { defineConfig } from 'vitest/config' diff --git a/config/index.md b/config/index.md index 7e5242e1..4f5ad862 100644 --- a/config/index.md +++ b/config/index.md @@ -106,7 +106,11 @@ export default defineConfig({ 由于 Vitest 使用 Vite 的配置,我们也可以使用 [Vite](https://vitejs.dev/config/) 中的任何配置选项。例如,使用 `define` 来定义全局变量,或者使用 `resolve.alias` 来定义别名——这些选项应该在顶级定义,而不是在 `test` 属性内部。 +<<<<<<< HEAD 不支持在[工作区](/guide/workspace)项目配置中的配置选项旁边会有 标志。这意味着这些选项只能在根 Vitest 配置中设置。 +======= +Configuration options that are not supported inside a [project](/guide/projects) config have sign next to them. This means they can only be set in the root Vitest config. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ::: ### include @@ -139,9 +143,15 @@ export default defineConfig({ ### name -- **Type:** `string` +- **Type:** `string | { label: string, color?: LabelColor }` +<<<<<<< HEAD 为测试项目或 Vitest 进程分配一个自定义名称。该名称将在 CLI 中可见,并且可以通过 Node.js API 中的 [`project.name`](/advanced/api/test-project#name) 获取。 +======= +Assign a custom name to the test project or Vitest process. The name will be visible in the CLI and UI, and available in the Node.js API via [`project.name`](/advanced/api/test-project#name). + +Color used by CLI and UI can be changed by providing an object with `color` property. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ### server {#server} @@ -583,7 +593,11 @@ jsdom 环境变量导出了等同于当前[JSDOM](https://github.com/jsdom/jsdom - **默认值:** `[]` ::: danger DEPRECATED +<<<<<<< HEAD 此 API 在 Vitest 3 中已弃用。请使用 [workspace](/guide/workspace) 来定义不同的配置。 +======= +This API was deprecated in Vitest 3. Use [projects](/guide/projects) to define different configurations instead. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```ts export default defineConfig({ @@ -591,7 +605,7 @@ export default defineConfig({ environmentMatchGlobs: [ // [!code --] ['./*.jsdom.test.ts', 'jsdom'], // [!code --] ], // [!code --] - workspace: [ // [!code ++] + projects: [ // [!code ++] { // [!code ++] extends: true, // [!code ++] test: { // [!code ++] @@ -630,7 +644,11 @@ export default defineConfig({ - **默认值:** `[]` ::: danger DEPRECATED +<<<<<<< HEAD 此 API 在 Vitest 3 中已被弃用。请使用 [workspace](/guide/workspace) 来定义不同的配置: +======= +This API was deprecated in Vitest 3. Use [projects](/guide/projects) to define different configurations instead: +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```ts export default defineConfig({ @@ -638,7 +656,7 @@ export default defineConfig({ poolMatchGlobs: [ // [!code --] ['./*.threads.test.ts', 'threads'], // [!code --] ], // [!code --] - workspace: [ // [!code ++] + projects: [ // [!code ++] { // [!code ++] test: { // [!code ++] extends: true, // [!code ++] @@ -692,6 +710,36 @@ In interactive environments, this is the default, unless `--run` is specified ex In CI, or when run from a non-interactive shell, "watch" mode is not the default, but can be enabled explicitly with this flag. +### watchTriggerPatterns 3.2.0 {#watchtriggerpatterns} + +- **Type:** `WatcherTriggerPattern[]` + +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. + +```ts +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + watchTriggerPatterns: [ + { + pattern: /^src\/(mailers|templates)\/(.*)\.(ts|html|txt)$/, + testToRun: (id, match) => { + // relative to the root value + return `./api/tests/mailers/${match[2]}.test.ts` + }, + }, + ], + }, +}) +``` + +::: warning +Returned files should be either absolute or relative to the root. Note that this is a global option, and it cannot be used inside of [project](/guide/projects) configs. +::: + ### root - **类型:** `string` @@ -1651,7 +1699,11 @@ Sets thresholds to 100 for files matching the glob pattern. - **可用的测试提供者:** `'v8'` - **命令行终端:** `--coverage.ignoreEmptyLines=` +<<<<<<< HEAD 忽略空行、注释和其他非运行时代码,如 Typescript 类型。 +======= +Ignore empty lines, comments and other non-runtime code, e.g. Typescript types. Requires `experimentalAstAwareRemapping: false`. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 该选项只有在使用的编译器删除了转译代码中的注释和其他非运行时代码时才有效。 默认情况下,Vite 使用 ESBuild,它会删除 `.ts`、`.tsx` 和 `.jsx` 文件中的注释和 Typescript 类型。 @@ -1675,6 +1727,14 @@ export default defineConfig({ }, }) ``` +#### coverage.experimentalAstAwareRemapping + +- **Type:** `boolean` +- **Default:** `false` +- **Available for providers:** `'v8'` +- **CLI:** `--coverage.experimentalAstAwareRemapping=` + +Remap coverage with experimental AST based analysis. Provides more accurate results compared to default mode. #### coverage.ignoreClassMethods @@ -2424,14 +2484,33 @@ Limit the depth to recurse when printing nested objects ### workspace {#workspace} +<<<<<<< HEAD - **类型:** `string | TestProjectConfiguration` - **命令行终端:** `--workspace=./file.js` - **默认值:** `vitest.{workspace,projects}.{js,ts,json}` close to the config file or root 相对于[root](#root) 的 [workspace](/guide/workspace) 配置文件的路径。 +======= +::: danger DEPRECATED +This options is deprecated and will be removed in the next major. Please, use [`projects`](#projects) instead. +::: + +- **Type:** `string | TestProjectConfiguration[]` +- **CLI:** `--workspace=./file.js` +- **Default:** `vitest.{workspace,projects}.{js,ts,json}` close to the config file or root + +Path to a [workspace](/guide/projects) config file relative to [root](#root). +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 Since Vitest 3, you can also define the workspace array in the root config. If the `workspace` is defined in the config manually, Vitest will ignore the `vitest.workspace` file in the root. +### projects {#projects} + +- **Type:** `TestProjectConfiguration[]` +- **Default:** `[]` + +An array of [projects](/guide/projects). + ### isolate - **类型:** `boolean` diff --git a/guide/browser/commands.md b/guide/browser/commands.md index 912055d7..b98d1018 100644 --- a/guide/browser/commands.md +++ b/guide/browser/commands.md @@ -11,7 +11,11 @@ outline: deep ### 文件处理 +<<<<<<< HEAD 你可以使用 `readFile` 、`writeFile` 和 `removeFile` API 来处理浏览器测试中的文件。所有路径都是相对于测试文件解析的,即使它们是在位于另一个文件中的辅助函数中调用的。 +======= +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 overriden manually). Previously, paths were resolved relative to the test file. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 默认情况下,Vitest 使用 `utf-8` 编码,但你可以使用选项覆盖它。 diff --git a/guide/browser/index.md b/guide/browser/index.md index 81d9799f..a74057c4 100644 --- a/guide/browser/index.md +++ b/guide/browser/index.md @@ -8,7 +8,11 @@ outline: deep 此页面提供有关 Vitest API 中实验性浏览器模式功能的信息,该功能允许你在浏览器中本地运行测试,提供对窗口和文档等浏览器全局变量的访问。此功能目前正在开发中,API 未来可能会更改。 ::: tip +<<<<<<< HEAD 如果你正在寻找关于 `expect`、`vi` 或任何通用 API(如工作区或类型测试)的文档,请参阅 ["入门指南"](/guide/)。 +======= +If you are looking for documentation for `expect`, `vi` or any general API like test projects or type testing, refer to the ["Getting Started" guide](/guide/). +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ::: Vitest UI @@ -209,13 +213,18 @@ export default defineConfig({ ``` ::: +<<<<<<< HEAD 如果我们需要使用基于 Node 的运行器来运行一些测试,可以定义一个 [工作区](/guide/workspace) 文件,其中包含不同测试策略的独立配置: +======= +If you need to run some tests using Node-based runner, you can define a [`projects`](/guide/projects) option with separate configurations for different testing strategies: +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 -{#workspace-config} +{#projects-config} -```ts [vitest.workspace.ts] -import { defineWorkspace } from 'vitest/config' +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' +<<<<<<< HEAD export default defineWorkspace([ { test: { @@ -243,10 +252,43 @@ export default defineWorkspace([ instances: [ { browser: 'chromium' }, ], +======= +export default defineConfig({ + test: { + projects: [ + { + test: { + // an example of file based convention, + // you don't have to follow it + include: [ + 'tests/unit/**/*.{test,spec}.ts', + 'tests/**/*.unit.{test,spec}.ts', + ], + name: 'unit', + environment: 'node', + }, +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 }, - }, + { + test: { + // an example of file based convention, + // you don't have to follow it + include: [ + 'tests/browser/**/*.{test,spec}.ts', + 'tests/**/*.browser.{test,spec}.ts', + ], + name: 'browser', + browser: { + enabled: true, + instances: [ + { browser: 'chromium' }, + ], + }, + }, + }, + ], }, -]) +}) ``` ## Browser Option Types diff --git a/guide/browser/multiple-setups.md b/guide/browser/multiple-setups.md index 9ec063fa..96510380 100644 --- a/guide/browser/multiple-setups.md +++ b/guide/browser/multiple-setups.md @@ -2,7 +2,11 @@ 自 Vitest 3 起,你可以使用新的 [`browser.instances`](/guide/browser/config#browser-instances) 选项来指定多个不同的浏览器设置。 +<<<<<<< HEAD 使用 `browser.instances` 而不是 [workspace](/guide/workspace) 的主要优势是改进了缓存。每个项目都将使用相同的 Vite 服务器,这意味着文件转换和 [依赖项预捆绑](https://vite.dev/guide/dep-pre-bundling.html) 只需进行一次。 +======= +The main advantage of using the `browser.instances` over the [test projects](/guide/projects) is improved caching. Every project will use the same Vite server meaning the file transform and [dependency pre-bundling](https://vite.dev/guide/dep-pre-bundling.html) has to happen only once. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ## 多个浏览器 diff --git a/guide/browser/playwright.md b/guide/browser/playwright.md index d073d64b..a510e670 100644 --- a/guide/browser/playwright.md +++ b/guide/browser/playwright.md @@ -16,9 +16,13 @@ } ``` +<<<<<<< HEAD Vitest 打开一个页面以在同一文件中运行所有测试。我们可以在 `instances` 中配置 `launch` 和 `context` 属性: +======= +Vitest opens a single page to run all tests in the same file. You can configure the `launch`, `connect` and `context` properties in `instances`: +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 -```ts{9-10} [vitest.config.ts] +```ts{9-11} [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ @@ -28,6 +32,7 @@ export default defineConfig({ { browser: 'firefox', launch: {}, + connect: {}, context: {}, }, ], @@ -65,6 +70,14 @@ Vitest 将忽略 `launch.headless` 选项。请改用 [`test.browser.headless`]( 请注意,如果启用了 [`--inspect`](/guide/cli#inspect),Vitest 会将调试标志推送到 `launch.args`。 ::: +## connect 3.2.0 {#connect} + +These options are directly passed down to `playwright[browser].connect` command. You can read more about the command and available arguments in the [Playwright documentation](https://playwright.dev/docs/api/class-browsertype#browser-type-connect). + +::: warning +Since this command connects to an existing Playwright server, any `launch` options will be ignored. +::: + ## context Vitest 通过调用 [`browser.newContext()`](https://playwright.dev/docs/api/class-browsercontext) 为每个测试文件创建一个新的上下文。我们可以通过指定 [自定义参数](https://playwright.dev/docs/api/class-apirequest#api-request-new-context) 来配置此行为。 diff --git a/guide/cli-generated.md b/guide/cli-generated.md index c4e6eb1b..c5fac691 100644 --- a/guide/cli-generated.md +++ b/guide/cli-generated.md @@ -291,7 +291,11 @@ High and low watermarks for functions in the format of `,` - **CLI:** `--workspace ` - **Config:** [workspace](/config/#workspace) +<<<<<<< HEAD 工作区配置文件的路径 +======= +[deprecated] Path to a workspace configuration file +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ### isolate @@ -360,7 +364,11 @@ High and low watermarks for functions in the format of `,` - **CLI:** `--browser.provider ` - **Config:** [browser.provider](/guide/browser/config#browser-provider) +<<<<<<< HEAD 用于运行浏览器测试的 Provider。某些浏览器只适用于特定的提供 Provider,可以是"webdriverio", "playwright", "preview",或自定义 provider. 通过 [`browser.provider`](https://vitest.dev/config/#browser-provider) 查看更多信息 (默认值: `"preview"`) +======= +Provider used to run browser tests. Some browsers are only available for specific providers. Can be "webdriverio", "playwright", "preview", or the path to a custom provider. Visit [`browser.provider`](https://vitest.dev/guide/browser/config.html#browser-provider) for more information (default: `"preview"`) +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ### browser.providerOptions @@ -761,6 +769,13 @@ Omit annotation lines from the output (default: `false`) Print basic prototype Object and Array (default: `true`) +### diff.maxDepth + +- **CLI:** `--diff.maxDepth ` +- **Config:** [diff.maxDepth](/config/#diff-maxdepth) + +Limit the depth to recurse when printing nested objects (default: `20`) + ### diff.truncateThreshold - **CLI:** `--diff.truncateThreshold ` diff --git a/guide/coverage.md b/guide/coverage.md index 094b0cb1..3eff518d 100644 --- a/guide/coverage.md +++ b/guide/coverage.md @@ -193,25 +193,35 @@ export default defineConfig({ - [`v8`](https://github.com/istanbuljs/v8-to-istanbul#ignoring-uncovered-lines) - [`ìstanbul`](https://github.com/istanbuljs/nyc#parsing-hints-ignoring-lines) +- `v8` with [`experimentalAstAwareRemapping: true`](https://vitest.dev/config/#coverage-experimentalAstAwareRemapping) see [ast-v8-to-istanbul | Ignoring code](https://github.com/AriPerkkio/ast-v8-to-istanbul?tab=readme-ov-file#ignoring-code) 使用 TypeScript 时,源代码使用 `esbuild` 进行转译,这会从源代码中删除所有注释([esbuild#516](https://github.com/evanw/esbuild/issues/516))。 被视为[合法注释](https://esbuild.github.io/api/#legal-comments)的注释将被保留。 +<<<<<<< HEAD 对于 `istanbul` 测试提供者,你可以在忽略提示中包含 `@preserve` 关键字。 请注意,这些忽略提示现在也可能包含在最终的产品构建中。 +======= +You can include a `@preserve` keyword in the ignore hint. +Beware that these ignore hints may now be included in final production build as well. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```diff -/* istanbul ignore if */ +/* istanbul ignore if -- @preserve */ if (condition) { -``` +<<<<<<< HEAD 不幸的是,目前这在 `v8` 中不起作用。你通常可以在 TypeScript 使用 `v8 ignore` 注释: ```ts /* v8 ignore next 3 */ +======= +-/* v8 ignore if */ ++/* v8 ignore if -- @preserve */ +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 if (condition) { ``` diff --git a/guide/environment.md b/guide/environment.md index 3bc4a14e..65564498 100644 --- a/guide/environment.md +++ b/guide/environment.md @@ -22,7 +22,11 @@ Vitest 提供 [`environment`](/config/#environment) 选项以在特定环境中 ::: warning "环境" 仅在 Node.js 中运行测试时存在。 +<<<<<<< HEAD 在 Vitest 中,`浏览器` 不被视为一个环境。如果希望使用[浏览器模式](/guide/browser/)运行部分测试,可以创建一个[workspace project](/guide/browser/#workspace-config)。 +======= +`browser` is not considered an environment in Vitest. If you wish to run part of your tests using [Browser Mode](/guide/browser/), you can create a [test project](/guide/browser/#projects-config). +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ::: ## 特定文件的环境 diff --git a/guide/features.md b/guide/features.md index 931ac83a..5de1c2dd 100644 --- a/guide/features.md +++ b/guide/features.md @@ -279,3 +279,60 @@ export default defineConfig(({ mode }) => ({ }, })) ``` + +## Unhandled Errors + +By default, Vitest catches and reports all [unhandled rejections](https://developer.mozilla.org/en-US/docs/Web/API/Window/unhandledrejection_event), [uncaught exceptions](https://nodejs.org/api/process.html#event-uncaughtexception) (in Node.js) and [error](https://developer.mozilla.org/en-US/docs/Web/API/Window/error_event) events (in the [browser](/guide/browser/)). + +You can disable this behaviour by catching them manually. Vitest assumes the callback is handled by you and won't report the error. + +::: code-group +```ts [setup.node.js] +// in Node.js +process.on('unhandledRejection', () => { + // your own handler +}) + +process.on('uncaughtException', () => { + // your own handler +}) +``` +```ts [setup.browser.js] +// in the browser +window.addEventListener('error', () => { + // your own handler +}) + +window.addEventListener('unhandledrejection', () => { + // your own handler +}) +``` +::: + +Alternatively, you can also ignore reported errors with a [`dangerouslyIgnoreUnhandledErrors`](/config/#dangerouslyignoreunhandlederrors) option. Vitest will still report them, but they won't affect the test result (exit code won't be changed). + +If you need to test that error was not caught, you can create a test that looks like this: + +```ts +test('my function throws uncaught error', async ({ onTestFinished }) => { + onTestFinished(() => { + // if the event was never called during the test, + // make sure it's removed before the next test starts + process.removeAllListeners('unhandledrejection') + }) + + return new Promise((resolve, reject) => { + process.once('unhandledrejection', (error) => { + try { + expect(error.message).toBe('my error') + resolve() + } + catch (error) { + reject(error) + } + }) + + callMyFunctionThatRejectsError() + }) +}) +``` diff --git a/guide/index.md b/guide/index.md index 448a947d..f6d9198b 100644 --- a/guide/index.md +++ b/guide/index.md @@ -179,17 +179,23 @@ export default defineConfig({ 但我们建议 Vite 和 Vitest 使用相同的文件,而不是创建两个单独的文件。 ::: +<<<<<<< HEAD ## 支持工作空间 在同一个项目中使用 [Vitest 工作区](/guide/workspace)运行不同的项目配置。你可以在 `vitest.config` 文件中定义一个包含文件和文件夹的列表来指定你的工作区。 +======= +## Projects Support + +Run different project configurations inside the same project with [Test Projects](/guide/projects). You can define a list of files and folders that define your projects in `vitest.config` file. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ test: { - workspace: [ - // you can use a list of glob patterns to define your workspaces + projects: [ + // you can use a list of glob patterns to define your projects // Vitest expects a list of config files // or directories where there is a config file 'packages/*', @@ -265,7 +271,7 @@ export default defineConfig({ | `sveltekit` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/sveltekit) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/sveltekit?initialPath=__vitest__/) | | `profiling` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/profiling) | Not Available | | `typecheck` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/typecheck) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/typecheck?initialPath=__vitest__/) | -| `workspace` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/workspace) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/workspace?initialPath=__vitest__/) | +| `projects` | [GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/projects) | [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/projects?initialPath=__vitest__/) | ## 使用 Vitest 的项目 diff --git a/guide/workspace.md b/guide/projects.md similarity index 63% rename from guide/workspace.md rename to guide/projects.md index 7f6df597..71f4a4f0 100644 --- a/guide/workspace.md +++ b/guide/projects.md @@ -1,31 +1,51 @@ --- +<<<<<<< HEAD:guide/workspace.md title: 工作空间 | 指南 --- # 工作空间 +======= +title: Test Projects | Guide +--- + +# Test Projects +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84:guide/projects.md ::: tip Sample Project -[GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/workspace) - [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/workspace?initialPath=__vitest__/) +[GitHub](https://github.com/vitest-dev/vitest/tree/main/examples/projects) - [Play Online](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/projects?initialPath=__vitest__/) ::: +<<<<<<< HEAD:guide/workspace.md Vitest 提供了在单个 Vitest 进程中定义多个项目配置的方法。该功能对单核设置尤为有用,但也可用于运行不同配置的测试,如 `resolve.alias`、`plugins` 或 `test.browser` 等。 ## 定义工作空间 从 Vitest 3 开始,你可以在根 [配置](/config/) 中定义工作区。在这种情况下,如果根目录下存在 `vitest.workspace` 文件,Vitest 将会忽略它。 +======= +::: warning +This feature is also known as a `workspace`. The `workspace` is deprecated since 3.2 and replaced with the `projects` configuration. They are functionally the same. +::: + +Vitest provides a way to define multiple project configurations within a single Vitest process. This feature is particularly useful for monorepo setups but can also be used to run tests with different configurations, such as `resolve.alias`, `plugins`, or `test.browser` and more. + +## Defining Projects + +You can define projects in your root [config](/config/): +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84:guide/projects.md ```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ test: { - workspace: ['packages/*'], + projects: ['packages/*'], }, }) ``` +<<<<<<< HEAD:guide/workspace.md 如果你使用的是较早的版本,工作区必须在其根目录中包含 `vitest.workspace` 或 `vitest.projects` 文件(如果不存在,则位于根配置文件所在的文件夹或工作目录中)。请注意,`projects` 只是一个别名,并不会改变此功能的行为或语义。Vitest 支持该文件的 `ts`、`js` 和 `json` 扩展名。 ::: tip NAMING @@ -35,57 +55,59 @@ export default defineConfig({ :::code-group ```ts [vitest.config.ts 3.0.0] +======= +Project configurations are inlined configs, files, or glob patterns referencing your projects. For example, if you have a folder named `packages` that contains your projects, you can define an array in your root Vitest config: + +```ts [vitest.config.ts] +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84:guide/projects.md import { defineConfig } from 'vitest/config' export default defineConfig({ test: { - workspace: ['packages/*'], + projects: ['packages/*'], }, }) ``` -```ts [vitest.workspace.ts] -export default [ - 'packages/*' -] -``` -::: +<<<<<<< HEAD:guide/workspace.md Vitest 会将 `packages` 中的每个文件夹视为一个独立的项目,即使它里面没有配置文件。如果这个全局模式匹配到任何文件,即使文件名中没有 `vitest`,也会被视作 Vitest 的配置文件。 ::: warning Vitest 不会将根目录下的 `vitest.config` 文件视为工作区项目,除非在工作区配置中明确指定。因此,根配置只会影响全局选项,例如 `reporters` 和 `coverage`。请注意,Vitest 将始终运行根配置文件中指定的某些插件钩子,例如 `apply`、`config`、`configResolved` 或 `configureServer`。Vitest 还使用相同的插件来执行全局设置、工作区文件和自定义覆盖率提供者。 +======= +Vitest will treat every folder in `packages` as a separate project even if it doesn't have a config file inside. If this glob pattern matches _any file_, it will be considered a Vitest config even if it doesn't have a `vitest` in its name or has an obscure file extension. + +::: warning +Vitest does not treat the root `vitest.config` file as a project unless it is explicitly specified in the configuration. Consequently, the root configuration will only influence global options such as `reporters` and `coverage`. Note that Vitest will always run certain plugin hooks, like `apply`, `config`, `configResolved` or `configureServer`, specified in the root config file. Vitest also uses the same plugins to execute global setups and custom coverage provider. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84:guide/projects.md ::: 你还可以使用项目的配置文件引用项目: -:::code-group -```ts [vitest.config.ts 3.0.0] +```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ test: { - workspace: ['packages/*/vitest.config.{e2e,unit}.ts'], + projects: ['packages/*/vitest.config.{e2e,unit}.ts'], }, }) ``` -```ts [vitest.workspace.ts] -export default [ - 'packages/*/vitest.config.{e2e,unit}.ts' -] -``` -::: 该模式仅包括具有包含 `e2e` 或 `unit` 的 `vitest.config` 文件的项目。这些关键字需要在文件扩展名之前出现。 +<<<<<<< HEAD:guide/workspace.md 你也可以使用内联配置来定义项目。工作区配置同时支持这两种语法。 +======= +You can also define projects using inline configuration. The configuration supports both syntaxes simultaneously. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84:guide/projects.md -:::code-group -```ts [vitest.config.ts 3.0.0] +```ts [vitest.config.ts] import { defineConfig } from 'vitest/config' export default defineConfig({ test: { - workspace: [ + projects: [ // matches every folder and file inside the `packages` folder 'packages/*', { @@ -101,7 +123,8 @@ export default defineConfig({ { test: { include: ['tests/**/*.{node}.test.{ts,js}'], - name: 'node', + // color of the name label can be changed + name: { label: 'node', color: 'green' }, environment: 'node', } } @@ -109,38 +132,12 @@ export default defineConfig({ } }) ``` -```ts [vitest.workspace.ts] -import { defineWorkspace } from 'vitest/config' - -// defineWorkspace provides a nice type hinting DX -export default defineWorkspace([ - // matches every folder and file inside the `packages` folder - 'packages/*', - { - // add "extends" to merge two configs together - extends: './vite.config.js', - test: { - include: ['tests/**/*.{browser}.test.{ts,js}'], - // it is recommended to define a name when using inline configs - name: 'happy-dom', - environment: 'happy-dom', - } - }, - { - test: { - include: ['tests/**/*.{node}.test.{ts,js}'], - name: 'node', - environment: 'node', - } - } -]) -``` -::: ::: warning 所有项目都必须有唯一的名称,否则 Vitest 会出错。如果内联配置中没有提供名称,Vitest 将分配一个数字。对于使用 glob 语法定义的项目配置,Vitest 将默认使用最近的 `package.json` 文件中的 "name" 属性,如果不存在,则使用文件夹名称。 ::: +<<<<<<< HEAD:guide/workspace.md 如果我们不使用内联配置,我们可以在根目录创建一个小的 JSON 文件,或者仅仅在根配置中指定它: ```json [vitest.workspace.json] @@ -148,6 +145,9 @@ export default defineWorkspace([ ``` 工作区项目不支持所有配置属性。为了提高类型安全性,请在项目配置文件中使用 `defineProject` 方法而不是 `defineConfig` 方法: +======= +Projects do not support all configuration properties. For better type safety, use the `defineProject` method instead of `defineConfig` within project configuration files: +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84:guide/projects.md ```ts twoslash [packages/a/vitest.config.ts] // @errors: 2769 @@ -165,7 +165,11 @@ export default defineProject({ ## 运行测试 +<<<<<<< HEAD:guide/workspace.md 要在工作区内运行测试,请在根目录 `package.json` 中定义一个脚本: +======= +To run tests, define a script in your root `package.json`: +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84:guide/projects.md ```json [package.json] { @@ -234,7 +238,11 @@ bun run test --project e2e --project unit ## 配置 +<<<<<<< HEAD:guide/workspace.md 即使工作区是在根级配置文件中定义的,而不是在单独的 `vitest.workspace` 文件中定义的,也不会从根级配置文件中继承任何配置选项。我们可以创建一个共享配置文件,并手动将其与项目配置合并: +======= +None of the configuration options are inherited from the root-level config file. You can create a shared config file and merge it with the project config yourself: +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84:guide/projects.md ```ts [packages/a/vitest.config.ts] import { defineProject, mergeConfig } from 'vitest/config' @@ -250,10 +258,17 @@ export default mergeConfig( ) ``` +<<<<<<< HEAD:guide/workspace.md 此外,在 `defineWorkspace` 层级,我们可以使用 `extends` 选项来继承根级别的配置。所有选项将被合并。 ::: code-group ```ts [vitest.config.ts 3.0.0] +======= +Additionally, you can use the `extends` option to inherit from your root-level configuration. All options will be merged. + +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84:guide/projects.md import react from '@vitejs/plugin-react' import { defineConfig } from 'vitest/config' @@ -261,7 +276,7 @@ export default defineConfig({ plugins: [react()], test: { pool: 'threads', - workspace: [ + projects: [ { // will inherit options from this config like plugins and pool extends: true, @@ -283,35 +298,21 @@ export default defineConfig({ }, }) ``` -```ts [vitest.workspace.ts] -import { defineWorkspace } from 'vitest/config' - -export default defineWorkspace([ - { - extends: './vitest.config.ts', - test: { - name: 'unit', - include: ['**/*.unit.test.ts'], - }, - }, - { - extends: './vitest.config.ts', - test: { - name: 'integration', - include: ['**/*.integration.test.ts'], - }, - }, -]) -``` -::: ::: danger Unsupported Options 某些配置选项不允许在项目配置中使用。其中最明显的是: +<<<<<<< HEAD:guide/workspace.md - `coverage`: 覆盖率是针对整个工作区进行的。 - `reporters`: 仅支持根级别的报告器。 - `resolveSnapshotPath`: 仅支持根级别的解析器。 - 所有其他不影响测试运行器的选项。 +======= +- `coverage`: coverage is done for the whole process +- `reporters`: only root-level reporters can be supported +- `resolveSnapshotPath`: only root-level resolver is respected +- all other options that don't affect test runners +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84:guide/projects.md 所有在项目配置中不支持的配置选项在 ["Config"](/config/) 指南中都会标记为 。这些选项必须在根配置文件中定义一次。 ::: diff --git a/guide/test-context.md b/guide/test-context.md index 3f61ba60..c36e07b0 100644 --- a/guide/test-context.md +++ b/guide/test-context.md @@ -14,19 +14,25 @@ outline: deep ```ts import { it } from 'vitest' +<<<<<<< HEAD it('should work', (ctx) => { // 打印测试的名称 console.log(ctx.task.name) +======= +it('should work', ({ task }) => { + // prints name of the test + console.log(task.name) +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 }) ``` ## 内置测试上下文 -#### `context.task` +#### `task` 包含关于测试的元数据的只读对象。 -#### `context.expect` +#### `expect` 绑定到当前测试的 `expect` API: @@ -52,7 +58,12 @@ it.concurrent('math is hard', ({ expect }) => { }) ``` -#### `context.skip` +#### `skip` + +```ts +function skip(note?: string): never +function skip(condition: boolean, note?: string): void +``` 跳过后续测试执行并将测试标记为已跳过: @@ -65,7 +76,43 @@ it('math is hard', ({ skip }) => { }) ``` +<<<<<<< HEAD ## 扩展测试上下文 +======= +Since Vitest 3.1, it accepts a boolean parameter to skip the test conditionally: + +```ts +it('math is hard', ({ skip, mind }) => { + skip(mind === 'foggy') + expect(2 + 2).toBe(5) +}) +``` + +#### `context.signal` 3.2.0 {#context-signal} + +An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that can be aborted by Vitest. The signal is aborted in these situations: + +- Test times out +- User manually cancelled the test run with Ctrl+C +- [`vitest.cancelCurrentRun`](/advanced/api/vitest#cancelcurrentrun) was called programmatically +- Another test failed in parallel and the [`bail`](/config/#bail) flag is set + +```ts +it('stop request when test times out', async ({ signal }) => { + await fetch('/resource', { signal }) +}, 2000) +``` + +#### `onTestFailed` + +The [`onTestFailed`](/api/#ontestfailed) hook bound to the current test. This API is useful if you are running tests concurrently and need to have a special handling only for this specific test. + +#### `onTestFinished` + +The [`onTestFinished`](/api/#ontestfailed) hook bound to the current test. This API is useful if you are running tests concurrently and need to have a special handling only for this specific test. + +## Extend Test Context +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 Vitest 提供了两种不同的方式来帮助你扩展测试上下文。 @@ -73,16 +120,24 @@ Vitest 提供了两种不同的方式来帮助你扩展测试上下文。 与 [Playwright](https://playwright.dev/docs/api/class-test#test-extend) 一样,你可以使用此方法通过自定义装置定义你自己的 `test` API,并在任何地方重复使用它。 +<<<<<<< HEAD 例如,我们首先使用两个固定装置创建 `myTest`,`todos` 和 `archive`。 +======= +For example, we first create the `test` collector with two fixtures: `todos` and `archive`. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```ts [my-test.ts] -import { test } from 'vitest' +import { test as baseTest } from 'vitest' const todos = [] const archive = [] +<<<<<<< HEAD export const myTest = test.extend({ +======= +export const test = baseTest.extend({ +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 todos: async ({}, use) => { // 在每次测试函数运行之前设置固定装置 todos.push(1, 2, 3) @@ -101,16 +156,16 @@ export const myTest = test.extend({ ```ts [my-test.test.ts] import { expect } from 'vitest' -import { myTest } from './my-test.js' +import { test } from './my-test.js' -myTest('add items to todos', ({ todos }) => { +test('add items to todos', ({ todos }) => { expect(todos.length).toBe(3) todos.push(4) expect(todos.length).toBe(4) }) -myTest('move items from todos to archive', ({ todos, archive }) => { +test('move items from todos to archive', ({ todos, archive }) => { expect(todos.length).toBe(3) expect(archive.length).toBe(0) @@ -120,10 +175,16 @@ myTest('move items from todos to archive', ({ todos, archive }) => { }) ``` +<<<<<<< HEAD 我们还可以通过扩展 `myTest` 添加更多的固定装置或覆盖现有的固定装置。 +======= +We can also add more fixtures or override existing fixtures by extending our `test`. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```ts -export const myTest2 = myTest.extend({ +import { test as todosTest } from './my-test.js' + +export const test = todosTest.extend({ settings: { // ... }, @@ -135,8 +196,9 @@ export const myTest2 = myTest.extend({ Vitest 运行器将智能地初始化你的固定装置并根据使用情况将它们注入到测试上下文中。 ```ts -import { test } from 'vitest' +import { test as baseTest } from 'vitest' +<<<<<<< HEAD async function todosFn({ task }, use) { await use([1, 2, 3]) } @@ -152,17 +214,35 @@ myTest('', ({ archive }) => {}) // todosFn 会运行 myTest('', ({ todos }) => {}) +======= +const test = baseTest.extend<{ + todos: number[] + archive: number[] +}>({ + todos: async ({ task }, use) => { + await use([1, 2, 3]) + }, + archive: [] +}) + +// todos will not run +test('skip', () => {}) +test('skip', ({ archive }) => {}) + +// todos will run +test('run', ({ todos }) => {}) +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ``` ::: warning 在固定装置中使用 `test.extend()` 时,需要始终使用对象解构模式 `{ todos }` 来访问固定装置函数和测试函数中的上下文。 ```ts -myTest('context must be destructured', (context) => { // [!code --] +test('context must be destructured', (context) => { // [!code --] expect(context.todos.length).toBe(2) }) -myTest('context must be destructured', ({ todos }) => { // [!code ++] +test('context must be destructured', ({ todos }) => { // [!code ++] expect(todos.length).toBe(2) }) ``` @@ -193,7 +273,7 @@ test('works correctly') #### Default fixture -Since Vitest 3, you can provide different values in different [projects](/guide/workspace). To enable this feature, pass down `{ injected: true }` to the options. If the key is not specified in the [project configuration](/config/#provide), then the default value will be used. +Since Vitest 3, you can provide different values in different [projects](/guide/projects). To enable this feature, pass down `{ injected: true }` to the options. If the key is not specified in the [project configuration](/config/#provide), then the default value will be used. :::code-group ```ts [fixtures.test.ts] @@ -214,32 +294,36 @@ test('works correctly', ({ url }) => { // url is "/empty" in "project-empty" }) ``` -```ts [vitest.workspace.ts] -import { defineWorkspace } from 'vitest/config' - -export default defineWorkspace([ - { - test: { - name: 'project-new', - }, - }, - { - test: { - name: 'project-full', - provide: { - url: '/full', +```ts [vitest.config.ts] +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + projects: [ + { + test: { + name: 'project-new', + }, }, - }, - }, - { - test: { - name: 'project-empty', - provide: { - url: '/empty', + { + test: { + name: 'project-full', + provide: { + url: '/full', + }, + }, }, - }, + { + test: { + name: 'project-empty', + provide: { + url: '/empty', + }, + }, + }, + ], }, -]) +}) ``` ::: @@ -317,20 +401,51 @@ interface MyFixtures { archive: number[] } -const myTest = test.extend({ +const test = baseTest.extend({ todos: [], archive: [], }) -myTest('types are defined correctly', ({ todos, archive }) => { +test('types are defined correctly', ({ todos, archive }) => { expectTypeOf(todos).toEqualTypeOf() expectTypeOf(archive).toEqualTypeOf() }) ``` +::: info Type Infering +Note that Vitest doesn't support infering the types when the `use` function is called. It is always preferable to pass down the whole context type as the generic type when `test.extend` is called: + +```ts +import { test as baseTest } from 'vitest' + +const test = baseTest.extend<{ + todos: number[] + schema: string +}>({ + todos: ({ schema }, use) => use([]), + schema: 'test' +}) + +test('types are correct', ({ + todos, // number[] + schema, // string +}) => { + // ... +}) +``` +::: + ### `beforeEach` and `afterEach` +<<<<<<< HEAD 每个测试的上下文都不同。 你可以在 `beforeEach` 和 `afterEach` hooks 中访问和扩展它们。 +======= +::: danger Deprecated +This is an outdated way of extending context and it will not work when the `test` is extended with `test.extend`. +::: + +The contexts are different for each test. You can access and extend them within the `beforeEach` and `afterEach` hooks. +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```ts import { beforeEach, it } from 'vitest' @@ -347,7 +462,11 @@ it('should work', ({ foo }) => { #### TypeScript +<<<<<<< HEAD 你可以通过添加聚合(aggregate)类型 `TestContext`, 为你的自定义上下文属性提供类型支持。 +======= +To provide property types for all your custom contexts, you can augment the `TestContext` type by adding +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 ```ts declare module 'vitest' { diff --git a/guide/testing-types.md b/guide/testing-types.md index 32bad889..a7744e58 100644 --- a/guide/testing-types.md +++ b/guide/testing-types.md @@ -97,7 +97,7 @@ expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: string }>() const one = valueFromFunctionOne({ some: { complex: inputs } }) const two = valueFromFunctionTwo({ some: { other: inputs } }) -expectTypeOf(one).toEqualTypeof() +expectTypeOf(one).toEqualTypeOf() ``` 如果你发现很难使用 `expectTypeOf` API 并找出错误,你始终可以使用更简单的 `assertType` API: diff --git a/package.json b/package.json index 078b64b8..d1c0a558 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "vue": "latest" }, "devDependencies": { +<<<<<<< HEAD "@antfu/eslint-config": "^4.10.1", "@antfu/ni": "^24.3.0", "@iconify-json/carbon": "latest", @@ -30,6 +31,13 @@ "@types/fs-extra": "^11.0.4", "@types/node": "^22.10.7", "@unocss/reset": "latest", +======= + "@iconify-json/carbon": "catalog:", + "@iconify-json/logos": "catalog:", + "@shikijs/transformers": "^3.3.0", + "@shikijs/vitepress-twoslash": "^3.3.0", + "@unocss/reset": "catalog:", +>>>>>>> 7eae51ccf951498de39ec8f8bc8ef2202e8cbe84 "@vite-pwa/assets-generator": "^0.2.6", "@vite-pwa/vitepress": "^0.5.4", "@vitejs/plugin-vue": "latest", @@ -50,7 +58,7 @@ "unplugin-vue-components": "latest", "vite": "^5.2.8", "vite-plugin-pwa": "^0.21.2", - "vitepress": "2.0.0-alpha.4", + "vitepress": "2.0.0-alpha.5", "vitepress-plugin-group-icons": "^1.5.2", "vitepress-plugin-tabs": "^0.7.0", "vitest": "^3.0.2",