···2233> This is adapted from [Angular's commit convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular).
4455-#### TL;DR:
55+### TL;DR:
6677Messages must be matched by the following regex:
88
+1-1
docs/api/expect.md
···66type Awaitable<T> = T | PromiseLike<T>
77```
8899-`expect` is used to create assertions. In this context `assertions` are functions that can be called to assert a statement. Vitest provides `chai` assertions by default and also `Jest` compatible assertions built on top of `chai`. Since Vitest 4.1, for spy/mock testing, Vitest also provides [Chai-style assertions](#chai-style-spy-assertions) (e.g., `expect(spy).to.have.been.called()`) alongside Jest-style assertions (e.g., `expect(spy).toHaveBeenCalled()`). Unlike `Jest`, Vitest supports a message as the second argument - if the assertion fails, the error message will be equal to it.
99+`expect` is used to create assertions. In this context `assertions` are functions that can be called to assert a statement. Vitest provides `chai` assertions by default and also `Jest` compatible assertions built on top of `chai`. Since Vitest 4.1, for spy/mock testing, Vitest also provides Chai-style assertions (e.g., [`expect(spy).to.have.been.called()`](#called)) alongside Jest-style assertions (e.g., `expect(spy).toHaveBeenCalled()`). Unlike `Jest`, Vitest supports a message as the second argument - if the assertion fails, the error message will be equal to it.
10101111```ts
1212export interface ExpectStatic extends Chai.ExpectStatic, AsymmetricMatchersContaining {
+2-2
docs/blog/vitest-3-2.md
···47474848The new [annotation API](/guide/test-annotations) allows you to annotate any test with a custom message and attachment. These annotations are visible in the UI, HTML, junit, tap and GitHub Actions reporters. Vitest will also print related annotation in the CLI if the test fails.
49495050-<img src="/annotation-api-cute-puppy-example.png" />
5050+<img src="/annotation-api-cute-puppy-example.png" alt="an example of annotation with a cute puppy" />
51515252## Scoped Fixtures
5353···106106```
107107:::
108108109109-<img src="/v3-2-custom-colors.png" />
109109+<img src="/v3-2-custom-colors.png" alt="an example of project names with custom backgrounds" />
110110111111## Custom Browser Locators API
112112
+1-1
docs/blog/vitest-3.md
···6767You can follow the design process in [#7069](https://github.com/vitest-dev/vitest/pull/7069) PR. It was a hard fight trying to reverse-engineer the previous `onTaskUpdate` API to make this new elegant lifecycle possible.
68686969<div class="flex align-center justify-center">
7070- <img src="/on-task-update.gif" />
7070+ <img src="/on-task-update.gif" alt="a gif from it's always sunny with a drawing board" />
7171</div>
72727373## Inline Workspace
+1-1
docs/config/alias.md
···1212::: warning
1313Vitest uses Vite SSR primitives to run tests which has [certain pitfalls](https://vitejs.dev/guide/ssr.html#ssr-externals).
14141515-1. Aliases affect only modules imported directly with an `import` keyword by an [inlined](#server-deps-inline) module (all source code is inlined by default).
1515+1. Aliases affect only modules imported directly with an `import` keyword by an [inlined](/config/server#server-deps-inline) module (all source code is inlined by default).
16162. Vitest does not support aliasing `require` calls.
17173. If you are aliasing an external dependency (e.g., `react` -> `preact`), you may want to alias the actual `node_modules` packages instead to make it work for externalized dependencies. Both [Yarn](https://classic.yarnpkg.com/en/docs/cli/add/#toc-yarn-add-alias) and [pnpm](https://pnpm.io/aliases/) support aliasing via the `npm:` prefix.
1818:::
+1-1
docs/config/benchmark.md
···2828- **Type:** `string[]`
2929- **Default:** `[]`
30303131-Include globs for in-source benchmark test files. This option is similar to [`includeSource`](#includesource).
3131+Include globs for in-source benchmark test files. This option is similar to [`includeSource`](/config/include-source).
32323333When defined, Vitest will run all matched files with `import.meta.vitest` inside.
3434
+1-1
docs/config/coverage.md
···149149- **Available for providers:** `'v8' | 'istanbul'`
150150- **CLI:** `--coverage.allowExternal`, `--coverage.allowExternal=false`
151151152152-Collect coverage of files outside the [project `root`](#root).
152152+Collect coverage of files outside the [project `root`](/config/root).
153153154154## coverage.excludeAfterRemap
155155
+6-6
docs/config/deps.md
···44444545Options 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.
46464747-Usually, files inside `node_modules` are externalized, but these options also affect files in [`server.deps.external`](#server-deps-external).
4747+Usually, files inside `node_modules` are externalized, but these options also affect files in [`server.deps.external`](/config/server#server-deps-external).
48484949### deps.client.transformAssets
5050···5656This module will have a default export equal to the path to the asset, if no query is specified.
57575858::: warning
5959-At the moment, this option only works with [`vmThreads`](#vmthreads) and [`vmForks`](#vmforks) pools.
5959+At the moment, this option only works with [`vmThreads`](/config/pool#vmthreads) and [`vmForks`](/config/pool#vmforks) pools.
6060:::
61616262### deps.client.transformCss
···66666767Should Vitest process CSS (.css, .scss, .sass, etc) files and resolve them like Vite does in the browser.
68686969-If CSS files are disabled with [`css`](#css) options, this option will just silence `ERR_UNKNOWN_FILE_EXTENSION` errors.
6969+If CSS files are disabled with [`css`](/config/css) options, this option will just silence `ERR_UNKNOWN_FILE_EXTENSION` errors.
70707171::: warning
7272-At the moment, this option only works with [`vmThreads`](#vmthreads) and [`vmForks`](#vmforks) pools.
7272+At the moment, this option only works with [`vmThreads`](/config/pool#vmthreads) and [`vmForks`](/config/pool#vmforks) pools.
7373:::
74747575### deps.client.transformGlobPattern
···8282By default, files inside `node_modules` are externalized and not transformed, unless it's CSS or an asset, and corresponding option is not disabled.
83838484::: warning
8585-At the moment, this option only works with [`vmThreads`](#vmthreads) and [`vmForks`](#vmforks) pools.
8585+At the moment, this option only works with [`vmThreads`](/config/pool#vmthreads) and [`vmForks`](/config/pool#vmforks) pools.
8686:::
87878888## deps.interopDefault
···113113- **Type:** `string[]`
114114- **Default**: `['node_modules']`
115115116116-A list of directories that should be treated as module directories. This config option affects the behavior of [`vi.mock`](/api/vi#vi-mock): when no factory is provided and the path of what you are mocking matches one of the `moduleDirectories` values, Vitest will try to resolve the mock by looking for a `__mocks__` folder in the [root](#root) of the project.
116116+A list of directories that should be treated as module directories. This config option affects the behavior of [`vi.mock`](/api/vi#vi-mock): when no factory is provided and the path of what you are mocking matches one of the `moduleDirectories` values, Vitest will try to resolve the mock by looking for a `__mocks__` folder in the [root](/config/root) of the project.
117117118118This option will also affect if a file should be treated as a module when externalizing dependencies. By default, Vitest imports external modules with native Node.js bypassing Vite transformation step.
119119
+1-1
docs/config/fileparallelism.md
···1212Should all test files run in parallel. Setting this to `false` will override `maxWorkers` option to `1`.
13131414::: tip
1515-This option doesn't affect tests running in the same file. If you want to run those in parallel, use `concurrent` option on [describe](/api/describe#describe-concurrent) or via [a config](#sequence-concurrent).
1515+This option doesn't affect tests running in the same file. If you want to run those in parallel, use `concurrent` option on [describe](/api/describe#describe-concurrent) or via [a config](/config/sequence#sequence-concurrent).
1616:::
+1-1
docs/config/globalsetup.md
···6262If you need to execute code in the same process as tests, use [`setupFiles`](/config/setupfiles) instead, but note that it runs before every test file.
6363:::
64646565-### Handling Test Reruns
6565+## Handling Test Reruns
66666767You can define a custom callback function to be called when Vitest reruns tests. The test runner will wait for it to complete before executing tests. Note that you cannot destruct the `project` like `{ onTestsRerun }` because it relies on the context.
6868
+1-1
docs/config/includetasklocation.md
···88- **Type:** `boolean`
99- **Default:** `false`
10101111-Should `location` property be included when Vitest API receives tasks in [reporters](#reporters). If you have a lot of tests, this might cause a small performance regression.
1111+Should `location` property be included when Vitest API receives tasks in [reporters](/config/reporters). If you have a lot of tests, this might cause a small performance regression.
12121313The `location` property has `column` and `line` values that correspond to the `test` or `describe` position in the original file.
1414
+2-2
docs/config/sequence.md
···24242525Sharding is happening before sorting, and only if `--shard` option is provided.
26262727-If [`sequencer.groupOrder`](#grouporder) is specified, the sequencer will be called once for each group and pool.
2727+If [`sequence.groupOrder`](#sequence-grouporder) is specified, the sequencer will be called once for each group and pool.
28282929## sequence.groupOrder
3030···3838- If several projects use the same group order, they will run at the same time.
39394040This setting only affects the order in which projects run, not the order of tests within a project.
4141-To control test isolation or the order of tests inside a project, use the [`isolate`](#isolate) and [`sequence.sequencer`](#sequence-sequencer) options.
4141+To control test isolation or the order of tests inside a project, use the [`isolate`](/config/isolate) and [`sequence.sequencer`](/config/sequence#sequence-sequencer) options.
42424343::: details Example
4444Consider this example:
+4-4
docs/config/server.md
···1515Normally, Vitest should do this automatically.
1616:::
17171818-## deps
1818+## server.deps
19192020-### external
2020+### server.deps.external
21212222- **Type:** `(string | RegExp)[]`
2323- **Default:** files inside [`moduleDirectories`](/config/deps#moduledirectories)
···4848If a `RegExp` is provided, it is matched against the full file path.
4949:::
50505151-### inline
5151+### server.deps.inline
52525353- **Type:** `(string | RegExp)[] | true`
5454- **Default:** everything that is not externalized
···6363If a `RegExp` is provided, it is matched against the full file path.
6464:::
65656666-### fallbackCJS
6666+### server.deps.fallbackCJS
67676868- **Type:** `boolean`
6969- **Default:** `false`
+1-1
docs/config/snapshotenvironment.md
···2828::: warning
2929This is a low-level option and should be used only for advanced cases where you don't have access to default Node.js APIs.
30303131-If you just need to configure snapshots feature, use [`snapshotFormat`](#snapshotformat) or [`resolveSnapshotPath`](#resolvesnapshotpath) options.
3131+If you just need to configure snapshots feature, use [`snapshotFormat`](/config/snapshotformat) or [`resolveSnapshotPath`](/config/resolvesnapshotpath) options.
3232:::
+1-1
docs/config/snapshotformat.md
···1212::: tip
1313Beware that `plugins` field on this object will be ignored.
14141515-If you need to extend snapshot serializer via pretty-format plugins, please, use [`expect.addSnapshotSerializer`](/api/expect#expect-addsnapshotserializer) API or [snapshotSerializers](#snapshotserializers) option.
1515+If you need to extend snapshot serializer via pretty-format plugins, please, use [`expect.addSnapshotSerializer`](/api/expect#expect-addsnapshotserializer) API or [snapshotSerializers](/config/snapshotserializers) option.
1616:::
+1-2
docs/guide/cli.md
···169169## Options
170170171171::: tip
172172-Vitest supports both camel case and kebab case for CLI arguments. For example, `--passWithNoTests` and `--pass-with-no-tests` will both work (`--no-color` and `--inspect-brk` are the exceptions).
172172+Vitest supports both camel case and kebab case for [CLI arguments](https://github.com/cacjs/cac#dot-nested-options). For example, `--passWithNoTests` and `--pass-with-no-tests` will both work (`--no-color` and `--inspect-brk` are the exceptions).
173173174174Vitest also supports different ways of specifying the value: `--reporter dot` and `--reporter=dot` are both valid.
175175···238238vitest --merge-reports --reporter=junit
239239```
240240241241-[cac's dot notation]: https://github.com/cacjs/cac#dot-nested-options
+9-9
docs/guide/extending-matchers.md
···109109110110Matcher function has access to `this` context with the following properties:
111111112112-### `isNot`
112112+## `isNot`
113113114114Returns true, if matcher was called on `not` (`expect(received).not.toBeFoo()`). You do not need to respect it, Vitest will reverse the value of `pass` automatically.
115115116116-### `promise`
116116+## `promise`
117117118118If matcher was called on `resolved/rejected`, this value will contain the name of modifier. Otherwise, it will be an empty string.
119119120120-### `equals`
120120+## `equals`
121121122122This is a utility function that allows you to compare two values. It will return `true` if values are equal, `false` otherwise. This function is used internally for almost every matcher. It supports objects with asymmetric matchers by default.
123123124124-### `utils`
124124+## `utils`
125125126126This contains a set of utility functions that you can use to display messages.
127127128128`this` context also contains information about the current test. You can also get it by calling `expect.getState()`. The most useful properties are:
129129130130-### `currentTestName`
130130+## `currentTestName`
131131132132Full name of the current test (including describe block).
133133134134-### `task` <Advanced /> <Version>4.1.0</Version> {#task}
134134+## `task` <Advanced /> <Version>4.1.0</Version> {#task}
135135136136Contains a reference to [the `Test` runner task](/api/advanced/runner#tasks) when available.
137137···139139When using the global `expect` with concurrent tests, `this.task` is `undefined`. Use `context.expect` instead to ensure `task` is available in custom matchers.
140140:::
141141142142-### `testPath`
142142+## `testPath`
143143144144File path to the current test.
145145146146-### `environment`
146146+## `environment`
147147148148The name of the current [`environment`](/config/environment) (for example, `jsdom`).
149149150150-### `soft`
150150+## `soft`
151151152152Was assertion called as a [`soft`](/api/expect#soft) one. You don't need to respect it, Vitest will always catch the error.
153153
+3-3
docs/guide/ide.md
···1212## VS Code <Badge>Official</Badge> {#vs-code}
13131414<p text-center>
1515-<img :src="`https://raw.githubusercontent.com/vitest-dev/vscode/main/img/cover-${isDark ? 'light' : 'dark' }.png`" w-60>
1515+<img :src="`https://raw.githubusercontent.com/vitest-dev/vscode/main/img/cover-${isDark ? 'light' : 'dark' }.png`" w-60 alt="vscode logo">
1616</p>
17171818[GitHub](https://github.com/vitest-dev/vscode) | [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=vitest.explorer)
19192020-
2020+
21212222## JetBrains IDE
23232424WebStorm, PhpStorm, IntelliJ IDEA Ultimate, and other JetBrains IDEs come with built-in support for Vitest.
25252626<p text-center>
2727-<img :src="`/ide/vitest-jb-${isDark ? 'light' : 'dark'}.png`" w-60>
2727+<img :src="`/ide/vitest-jb-${isDark ? 'light' : 'dark'}.png`" w-60 alt="webstorm logo">
2828</p>
29293030[WebStorm Help](https://www.jetbrains.com/help/webstorm/vitest.html) | [IntelliJ IDEA Ultimate Help](https://www.jetbrains.com/help/idea/vitest.html) | [PhpStorm Help](https://www.jetbrains.com/help/phpstorm/vitest.html)
+1-1
docs/guide/mocking.md
···162162```
163163164164::: warning
165165-Don't forget that this only [mocks _external_ access](#mocking-pitfalls). In this example, if `original` calls `mocked` internally, it will always call the function defined in the module, not in the mock factory.
165165+Don't forget that this only [mocks _external_ access](/guide/mocking/modules#mocking-modules-pitfalls). In this example, if `original` calls `mocked` internally, it will always call the function defined in the module, not in the mock factory.
166166:::
167167168168### Mock the current date
+1-1
docs/guide/open-telemetry.md
···143143144144You can view traces using any of the open source or commercial products that support OpenTelemetry API. If you did not use OpenTelemetry before, we recommend starting with [Jaeger](https://www.jaegertracing.io/docs/2.11/getting-started/#all-in-one) because it is really easy to setup.
145145146146-<img src="/otel-jaeger.png" />
146146+<img src="/otel-jaeger.png" alt="an example of open telemetry result in jaeger" />
147147148148## `@opentelemetry/api`
149149
+7-7
docs/guide/test-context.md
···22222323## Built-in Test Context
24242525-#### `task`
2525+### `task`
26262727A readonly object containing metadata about the test.
28282929-#### `expect`
2929+### `expect`
30303131The `expect` API bound to the current test:
3232···5252})
5353```
54545555-#### `skip`
5555+### `skip`
56565757```ts
5858function skip(note?: string): never
···7979})
8080```
81818282-#### `annotate` <Version>3.2.0</Version> {#annotate}
8282+### `annotate` <Version>3.2.0</Version> {#annotate}
83838484```ts
8585function annotate(
···102102})
103103```
104104105105-#### `signal` <Version>3.2.0</Version> {#signal}
105105+### `signal` <Version>3.2.0</Version> {#signal}
106106107107An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that can be aborted by Vitest. The signal is aborted in these situations:
108108···117117}, 2000)
118118```
119119120120-#### `onTestFailed`
120120+### `onTestFailed`
121121122122The [`onTestFailed`](/api/hooks#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.
123123124124-#### `onTestFinished`
124124+### `onTestFinished`
125125126126The [`onTestFinished`](/api/hooks#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.
127127
+1-1
docs/guide/testing-types.md
···77777878If TypeScript added support for ["throw" types](https://github.com/microsoft/TypeScript/pull/40468) these error messages could be improved significantly. Until then they will take a certain amount of squinting.
79798080-#### Concrete "expected" objects vs typeargs
8080+### Concrete "expected" objects vs typeargs
81818282Error messages for an assertion like this:
8383
+1-1
packages/mocker/EXPORTS.md
···11-# Using as a Vite plugin
11+## Using as a Vite plugin
2233Make sure you have `vite` and `@vitest/spy` installed (and `msw` if you are planning to use `ModuleMockerMSWInterceptor`).
44
+3-3
docs/api/advanced/test-project.md
···5151:::
52525353::: info
5454-If the [root project](/api/advanced/vitest#getroottestproject) is not part of user projects, its `name` will not be resolved.
5454+If the [root project](/api/advanced/vitest#getrootproject) is not part of user projects, its `name` will not be resolved.
5555:::
56565757## vitest
···78787979## globalConfig
80808181-The test config that [`Vitest`](/api/advanced/vitest) was initialized with. If this is the [root project](/api/advanced/vitest#getroottestproject), `globalConfig` and `config` will reference the same object. This config is useful for values that cannot be set on the project level, like `coverage` or `reporters`.
8181+The test config that [`Vitest`](/api/advanced/vitest) was initialized with. If this is the [root project](/api/advanced/vitest#getrootproject), `globalConfig` and `config` will reference the same object. This config is useful for values that cannot be set on the project level, like `coverage` or `reporters`.
82828383```ts
8484import type { ResolvedConfig } from 'vitest/node'
···206206function isRootProject(): boolean
207207```
208208209209-Checks if the current project is the root project. You can also get the root project by calling [`vitest.getRootProject()`](#getrootproject).
209209+Checks if the current project is the root project. You can also get the root project by calling [`vitest.getRootProject()`](/api/advanced/vitest#getrootproject).
210210211211## globTestFiles
212212
+14-14
docs/api/browser/locators.md
···6565Providing roles via `role` or `aria-*` attributes to built-in elements that already have an implicit role is **highly discouraged** by ARIA guidelines.
6666:::
67676868-##### Options
6868+**Options**
69697070- `exact: boolean`
7171···189189 page.getByRole('button', { selected: false }) // ❌
190190 ```
191191192192-##### See also
192192+**See also**
193193194194- [List of ARIA roles at MDN](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles)
195195- [List of ARIA roles at w3.org](https://www.w3.org/TR/wai-aria-1.2/#role_definitions)
···213213page.getByAltText('non existing alt text') // ❌
214214```
215215216216-#### Options
216216+**Options**
217217218218- `exact: boolean`
219219220220 Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.
221221222222-#### See also
222222+**See also**
223223224224- [testing-library's `ByAltText`](https://testing-library.com/docs/queries/byalttext/)
225225···260260<input aria-label="Username" />
261261```
262262263263-#### Options
263263+**Options**
264264265265- `exact: boolean`
266266267267 Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.
268268269269-#### See also
269269+**See also**
270270271271- [testing-library's `ByLabelText`](https://testing-library.com/docs/queries/bylabeltext/)
272272···292292It is generally better to rely on a label using [`getByLabelText`](#getbylabeltext) than a placeholder.
293293:::
294294295295-#### Options
295295+**Options**
296296297297- `exact: boolean`
298298299299 Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.
300300301301-#### See also
301301+**See also**
302302303303- [testing-library's `ByPlaceholderText`](https://testing-library.com/docs/queries/byplaceholdertext/)
304304···324324This locator is useful for locating non-interactive elements. If you need to locate an interactive element, like a button or an input, prefer [`getByRole`](#getbyrole).
325325:::
326326327327-#### Options
327327+**Options**
328328329329- `exact: boolean`
330330331331 Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.
332332333333-#### See also
333333+**See also**
334334335335- [testing-library's `ByText`](https://testing-library.com/docs/queries/bytext/)
336336···352352page.getByTitle('Create') // ❌
353353```
354354355355-#### Options
355355+**Options**
356356357357- `exact: boolean`
358358359359 Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.
360360361361-#### See also
361361+**See also**
362362363363- [testing-library's `ByTitle`](https://testing-library.com/docs/queries/bytitle/)
364364···381381It is recommended to use this only after the other locators don't work for your use case. Using `data-testid` attributes does not resemble how your software is used and should be avoided if possible.
382382:::
383383384384-#### Options
384384+**Options**
385385386386- `exact: boolean`
387387388388 Whether the `text` is matched exactly: case-sensitive and whole-string. Disabled by default. This option is ignored if `text` is a regular expression. Note that exact match still trims whitespace.
389389390390-#### See also
390390+**See also**
391391392392- [testing-library's `ByTestId`](https://testing-library.com/docs/queries/bytestid/)
393393
+1-1
docs/config/browser/api.md
···99- **Default:** `63315`
1010- **CLI:** `--browser.api=63315`, `--browser.api.port=1234, --browser.api.host=example.com`
11111212-Configure options for Vite server that serves code in the browser. Does not affect [`test.api`](#api) option. By default, Vitest assigns port `63315` to avoid conflicts with the development server, allowing you to run both in parallel.
1212+Configure options for Vite server that serves code in the browser. Does not affect [`test.api`](/config/api) option. By default, Vitest assigns port `63315` to avoid conflicts with the development server, allowing you to run both in parallel.
13131414## api.allowWrite <Version>4.1.0</Version> {#api-allowwrite}
1515
+1-1
docs/config/browser/provider.md
···6464## Custom Provider <Badge type="danger">advanced</Badge>
65656666::: danger ADVANCED API
6767-The custom provider API is highly experimental and can change between patches. If you just need to run tests in a browser, use the [`browser.instances`](#browser-instances) option instead.
6767+The custom provider API is highly experimental and can change between patches. If you just need to run tests in a browser, use the [`browser.instances`](/config/browser/instances) option instead.
6868:::
69697070```ts
+10-10
docs/guide/browser/visual-regression-testing.md
···389389The trick here is keeping visual tests separate from your regular tests,
390390otherwise, you'll waste hours checking failing logs of screenshot mismatches.
391391392392-#### Organizing Your Tests
392392+### Organizing Your Tests
393393394394First, isolate your visual tests. Stick them in a `visual` folder (or whatever
395395makes sense for your project):
···414414- `vitest --project visual`
415415:::
416416417417-#### CI Setup
417417+### CI Setup
418418419419Your CI needs browsers installed. How you do this depends on your provider:
420420···454454 run: npm run test:visual
455455```
456456457457-#### The Update Workflow
457457+### The Update Workflow
458458459459Here's where it gets interesting. You don't want to update screenshots on every
460460PR automatically <small>*(chaos!)*</small>. Instead, create a
···599599Your tests stay local, only the browsers run in the cloud. It's Playwright's
600600remote browser feature, but Microsoft handles all the infrastructure.
601601602602-#### Organizing Your Tests
602602+### Organizing Your Tests
603603604604Keep visual tests separate to control costs. Only tests that actually take
605605screenshots should use the service.
606606607607The cleanest approach is using [Test Projects](/guide/projects):
608608609609-<!-- eslint-disable style/quote-props -->
609609+610610```ts [vitest.config.ts]
611611import { env } from 'node:process'
612612import { defineConfig } from 'vitest/config'
···637637 connectOptions: {
638638 wsEndpoint: `${env.PLAYWRIGHT_SERVICE_URL}?${new URLSearchParams({
639639 'api-version': '2025-09-01',
640640- os: 'linux', // always use Linux for consistency
640640+ 'os': 'linux', // always use Linux for consistency
641641 // helps identifying runs in the service's dashboard
642642- runName: `Vitest ${env.CI ? 'CI' : 'local'} run @${new Date().toISOString()}`,
642642+ 'runName': `Vitest ${env.CI ? 'CI' : 'local'} run @${new Date().toISOString()}`,
643643 })}`,
644644 exposeNetwork: '<loopback>',
645645 headers: {
···662662 },
663663})
664664```
665665-<!-- eslint-enable style/quote-props -->
665665+666666667667Follow the [official guide to create a Playwright Workspace](https://learn.microsoft.com/en-us/azure/app-testing/playwright-workspaces/quickstart-run-end-to-end-tests?tabs=playwrightcli&pivots=playwright-test-runner#create-a-workspace).
668668···688688}
689689```
690690691691-#### Running Tests
691691+### Running Tests
692692693693```bash
694694# Local development
···706706- **Pay for what you use**, only visual tests consume service minutes
707707- **No Docker or workflow setups needed**, nothing to manage or maintain
708708709709-#### CI Setup
709709+### CI Setup
710710711711In your CI, add the secrets:
712712
···188188 /**
189189 * Matches if the received number is within a certain precision of the expected number.
190190 *
191191- * @param precision - Optional decimal precision for comparison. Default is 2.
192192- *
193191 * @example
194192 * expect(10.45).toEqual(expect.closeTo(10.5, 1));
195193 * expect(5.11).toEqual(expect.closeTo(5.12)); // with default precision