Skip to content

Commit ea4f167

Browse files
sheremet-vaAriPerkkiopatak-dev
authored
docs: add blog post for 3.2 (#8001)
Co-authored-by: Ari Perkkiö <[email protected]> Co-authored-by: patak-dev <[email protected]>
1 parent 70fb03c commit ea4f167

File tree

7 files changed

+249
-2
lines changed

7 files changed

+249
-2
lines changed

docs/blog/vitest-3-2.md

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
---
2+
title: Vitest 3.2 is out!
3+
author:
4+
name: The Vitest Team
5+
date: 2025-06-02
6+
sidebar: false
7+
head:
8+
- - meta
9+
- property: og:type
10+
content: website
11+
- - meta
12+
- property: og:title
13+
content: Announcing Vitest 3.2
14+
- - meta
15+
- property: og:image
16+
content: https://vitest.dev/og-vitest-3-2.png
17+
- - meta
18+
- property: og:url
19+
content: https://vitest.dev/blog/vitest-3-2
20+
- - meta
21+
- property: og:description
22+
content: Vitest 3.2 Release Announcement
23+
- - meta
24+
- name: twitter:card
25+
content: summary_large_image
26+
---
27+
28+
# Vitest 3.2 is out!
29+
30+
_June 2, 2025_
31+
32+
![Vitest 3.2 Announcement Cover Image](/og-vitest-3-2.png)
33+
34+
Vitest 3.2 focuses on improvements to Browser Mode and TypeScript support. This release also includes some new useful methods, config options and deprecates the `workspace` config in favour of `projects`.
35+
36+
## `workspace` is Deprecated
37+
38+
In an effort to simplify the configuration, the team decided to deprecate the separate `vitest.workspace` file and recommend using only the `projects` option in the root config. This also simplifies how the global options are configured (because you don't need to guess how to add reporters when you have no root config).
39+
40+
We also decided to deprecate the `workspace` name because it clashes with other tools like PNPM that provide monorepo support via this option. Vitest doesn't run these projects with separate `CWD` and treats them more like sub-Vitests. It also gives us more space to come up with a better solution for monorepos without breaking others.
41+
42+
This option will be removed completely in a future major, replaced by `projects`. Until then, Vitest will print a warning if workspace feature is used.
43+
44+
<!--@include: ../guide/examples/projects-workspace.md-->
45+
46+
## Annotation API
47+
48+
The 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.
49+
50+
<img src="/annotation-api-cute-puppy-example.png" />
51+
52+
## Scoped Fixtures
53+
54+
The `test.extend` fixtures can now specify the `scope` option: either `file` or `worker`.
55+
56+
```ts
57+
const test = baseTest.extend({
58+
db: [
59+
async ({}, use) => {
60+
// ...setup
61+
await use(db)
62+
await db.close()
63+
},
64+
{ scope: 'worker' },
65+
],
66+
})
67+
```
68+
69+
The file fixture is similar to using `beforeAll` and `afterAll` at the top level of the file, but it won't be called if the fixture is not used in any test.
70+
71+
The `worker` fixture is initiated once per worker, but note that by default Vitest creates one worker for every test, so you need to disable [isolation](/config/#isolate) to benefit from it.
72+
73+
## Custom Project Name Colors
74+
75+
You can now set a custom [color](/config/#name) when using `projects`:
76+
77+
::: details Config Example
78+
```ts{6-9,14-17}
79+
export default defineConfig({
80+
test: {
81+
projects: [
82+
{
83+
test: {
84+
name: {
85+
label: 'unit',
86+
color: 'red',
87+
},
88+
},
89+
},
90+
{
91+
test: {
92+
name: {
93+
label: 'browser',
94+
color: 'green',
95+
},
96+
browser: {
97+
enabled: true,
98+
provider: 'playwright',
99+
instances: [{ browser: 'chromium' }],
100+
},
101+
},
102+
},
103+
],
104+
},
105+
})
106+
```
107+
:::
108+
109+
<img src="/v3-2-custom-colors.png" />
110+
111+
## Custom Browser Locators API
112+
113+
Built-in locators might not be enough to express your application’s needs. Instead of falling back to CSS and losing the retry-ability protection that Vitest provides through its locator API, we now recommend extending locators using the new [`locators.extend` API](/guide/browser/locators#custom-locators).
114+
115+
```ts
116+
import { locators } from '@vitest/browser/context'
117+
118+
locators.extend({
119+
getByCommentsCount(count: number) {
120+
return `.comments :text("${count} comments")`
121+
},
122+
})
123+
```
124+
125+
Return a Playwright [locator string](https://playwright.dev/docs/other-locators) to construct a new locator. Note that string returned from this method will be scoped to the parent locator, if there is one.
126+
127+
Now you can call `getByCommentsCount` on the `page` or any other locator directly:
128+
129+
```ts
130+
await expect.element(page.getByCommentsCount(1)).toBeVisible()
131+
await expect.element(
132+
page.getByRole('article', { name: 'Hello World' })
133+
.getByCommentsCount(1)
134+
).toBeVisible()
135+
```
136+
137+
If this method returns a string, then the return value will be converted into a locator, so you can keep chaining it:
138+
139+
```ts
140+
page.getByRole('article', { name: 'Hello World' })
141+
.getByCommentsCount(1)
142+
.getByText('comments')
143+
```
144+
145+
This method has access to the current locator context, if there is one (if method is called on the `page`, then context will refer to `page`), so you can chain all locator methods inside:
146+
147+
```ts
148+
import { locators } from '@vitest/browser/context'
149+
import type { Locator } from '@vitest/browser/context'
150+
151+
locators.extend({
152+
getByCommentsCount(this: Locator, count: number) {
153+
return this.getByRole('comment')
154+
.and(this.getByText(`${count} comments`))
155+
},
156+
})
157+
```
158+
159+
Having access to context also allows you to call regular methods of the locator to define a custom user event:
160+
161+
```ts
162+
import { locators, page } from '@vitest/browser/context'
163+
import type { Locator } from '@vitest/browser/context'
164+
165+
locators.extend({
166+
clickAndFill(this: Locator, text: string) {
167+
await this.click()
168+
await this.fill(text)
169+
},
170+
})
171+
172+
await page.getByRole('textbox').clickAndFill('Hello World')
173+
```
174+
175+
Please, refer to the [`locators.extend` API](/guide/browser/locators#custom-locators) for more information.
176+
177+
## Explicit Resource Management in `vi.spyOn` and `vi.fn`
178+
179+
In environments that support [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management), you can use `using` instead of `const` to automatically call `mockRestore` on any mocked function when the containing block is exited. This is especially useful for spied methods:
180+
181+
```ts
182+
it('calls console.log', () => {
183+
using spy = vi.spyOn(console, 'log').mockImplementation(() => {})
184+
debug('message')
185+
expect(spy).toHaveBeenCalled()
186+
})
187+
188+
// console.log is restored here
189+
```
190+
191+
## Test `signal` API
192+
193+
Vitest now provides an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) object to the test body. You can use it to stop any resource that supports this Web API.
194+
195+
The signal is aborted when test times out, another test fails and [`--bail` flag](/config/#bail) is set to a non-zero value, or the user presses Ctrl+C in the terminal.
196+
197+
For example, you can stop a `fetch` request when tests are interrupted:
198+
199+
```ts
200+
it('stop request when test times out', async ({ signal }) => {
201+
await fetch('/heavy-resource', { signal })
202+
}, 2000)
203+
```
204+
205+
## Coverage V8 AST-aware remapping
206+
207+
Vitest now uses `ast-v8-to-istanbul` package developed by one of the Vitest maintainers, [AriPerkkio](https://github.com/AriPerkkio). This brings v8 coverage report in line with istanbul, but has a better performance! Enable this feature by setting [`coverage.experimentalAstAwareRemapping`](/config/#coverage-experimentalastawareremapping) to `true`.
208+
209+
We are planning to make this the default remapping mode in the next major. The old `v8-to-istanbul` will be removed completely. Feel free to join discussion at https://github.com/vitest-dev/vitest/issues/7928.
210+
211+
## `watchTriggerPatterns` Option
212+
213+
When you edit a file, Vitest is smart enough to rerun only tests that import this file. Unfortunately, Vitest static analysis respects only static and dynamic `import` statement. If you are reading a file or starting a separate process, Vitest will ignore changes to related files.
214+
215+
With `watchTriggerPatterns` option you can configure which tests to rerun depending on the file that was changed. For example, to always rerun `mailers` tests when a template is changed, add a trigger pattern:
216+
217+
```ts
218+
export default defineConfig({
219+
test: {
220+
watchTriggerPatterns: [
221+
{
222+
pattern: /^src\/templates\/(.*)\.(ts|html|txt)$/,
223+
testsToRun: (file, match) => {
224+
return `api/tests/mailers/${match[2]}.test.ts`
225+
},
226+
},
227+
],
228+
},
229+
})
230+
```

docs/config/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2053,9 +2053,9 @@ A custom class that defines methods for sharding and sorting. You can extend `Ba
20532053

20542054
Sharding is happening before sorting, and only if `--shard` option is provided.
20552055

2056-
If [`sequencer.groupOrder`](#groupOrder) is specified, the sequencer will be called once for each group and pool.
2056+
If [`sequencer.groupOrder`](#grouporder) is specified, the sequencer will be called once for each group and pool.
20572057

2058-
#### groupOrder <Version>3.2.0</Version> {#groupOrder}
2058+
#### groupOrder <Version>3.2.0</Version> {#grouporder}
20592059

20602060
- **Type:** `number`
20612061
- **Default:** `0`
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
```ts
2+
import { defineConfig } from "vitest/config";
3+
export default defineConfig({
4+
test: {
5+
// "test.workspace" is now "test.projects"
6+
workspace: [ // [!code --]
7+
projects: [ // [!code ++]
8+
{ test: { name: "Unit" } },
9+
{ test: { name: "Integration" } },
10+
],
11+
},
12+
});
13+
```

docs/guide/test-annotations.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ test('hello world', async ({ annotate }) => {
2020
})
2121
```
2222

23+
::: warning
24+
The `annotate` function returns a Promise, so it needs to be awaited if you rely on it somehow. However, Vitest will also automatically await any non-awaited annotation before the test finishes.
25+
:::
26+
2327
Depending on your reporter, you will see these annotations differently.
2428

2529
## Built-in Reporters
267 KB
Loading

docs/public/og-vitest-3-2.png

123 KB
Loading

docs/public/v3-2-custom-colors.png

153 KB
Loading

0 commit comments

Comments
 (0)