Vitest 3.2 est sorti !
2 juin 2025
Vitest 3.2 met l'accent sur l'amélioration du mode navigateur et du support de TypeScript. Cette version introduit également de nouvelles méthodes et options de configuration utiles, et marque la dépréciation de la configuration workspace
au profit de projects
.
workspace
est déprécié
Afin de simplifier la configuration, l'équipe a décidé de déprécier le fichier vitest.workspace
séparé et de recommander l'utilisation de l'option projects
uniquement dans la configuration principale. Cela simplifie également la configuration des options globales (car il n'est plus nécessaire de deviner comment ajouter des reporters en l'absence de configuration principale).
Nous avons également décidé de déprécier le nom workspace
car il entre en conflit avec d'autres outils comme PNPM qui offrent un support monorepo via cette option. Vitest n'exécute pas ces projets avec un CWD
distinct et les traite davantage comme des sous-Vitest. Cela nous donne également plus de marge pour trouver une meilleure solution pour les monorepos sans perturber les autres.
Cette option sera complètement supprimée dans une future version majeure, remplacée par projects
. D'ici là, Vitest affichera un avertissement si la fonctionnalité workspace
est utilisée.
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
// "test.workspace" est maintenant "test.projects"
workspace: [
projects: [
{ test: { name: "Unit" } },
{ test: { name: "Integration" } },
],
},
});
API d'annotation
La nouvelle API d'annotation vous permet d'annoter n'importe quel test avec un message et une pièce jointe personnalisés. Ces annotations sont visibles dans l'interface utilisateur, ainsi que dans les rapports HTML, JUnit, TAP et GitHub Actions. Vitest affichera également l'annotation associée dans la CLI si le test échoue.

Fixtures avec portée
Les fixtures test.extend
peuvent désormais spécifier l'option scope
: soit file
soit worker
.
const test = baseTest.extend({
db: [
async ({}, use) => {
// ...configuration
await use(db);
await db.close();
},
{ scope: 'worker' },
],
});
La fixture au niveau du fichier est similaire à l'utilisation de beforeAll
et afterAll
au niveau supérieur du fichier, mais elle ne sera pas appelée si la fixture n'est utilisée dans aucun test.
La fixture au niveau du worker
est initiée une fois par worker, mais notez que par défaut Vitest crée un worker pour chaque test. Vous devez donc désactiver l'isolation pour en bénéficier.
Couleurs de nom de projet personnalisées
Vous pouvez maintenant définir une couleur personnalisée lors de l'utilisation de projects
:
Exemple de configuration
export default defineConfig({
test: {
projects: [
{
test: {
name: {
label: 'unit',
color: 'red',
},
},
},
{
test: {
name: {
label: 'browser',
color: 'green',
},
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
},
],
},
})

API de localisateurs de navigateur personnalisés
Les localisateurs intégrés pourraient ne pas suffire à répondre aux besoins de votre application. Au lieu de revenir au CSS et de perdre la protection de réessai que Vitest offre via son API de localisateur, nous recommandons maintenant d'étendre les localisateurs en utilisant la nouvelle API locators.extend
.
import { locators } from '@vitest/browser/context';
locators.extend({
getByCommentsCount(count: number) {
return `.comments :text("${count} comments")`;
},
});
Retournez une chaîne de localisateur Playwright pour construire un nouveau localisateur. Notez que la chaîne retournée par cette méthode sera limitée au localisateur parent, s'il y en a un.
Vous pouvez maintenant appeler getByCommentsCount
sur la page
ou tout autre localisateur directement :
await expect.element(page.getByCommentsCount(1)).toBeVisible();
await expect
.element(
page.getByRole('article', { name: 'Hello World' }).getByCommentsCount(1)
)
.toBeVisible();
Si cette méthode retourne une chaîne, la valeur de retour sera convertie en localisateur, vous pouvez donc continuer à la chaîner :
page
.getByRole('article', { name: 'Hello World' })
.getByCommentsCount(1)
.getByText('comments');
Cette méthode a accès au contexte du localisateur actuel, s'il y en a un. Si la méthode est appelée sur la page
, alors le contexte fera référence à la page
. Cela vous permet de chaîner toutes les méthodes du localisateur à l'intérieur :
import { locators } from '@vitest/browser/context';
import type { Locator } from '@vitest/browser/context';
locators.extend({
getByCommentsCount(this: Locator, count: number) {
return this.getByRole('comment').and(this.getByText(`${count} comments`));
},
});
L'accès au contexte vous permet également d'appeler des méthodes régulières du localisateur pour définir un événement utilisateur personnalisé :
import { locators, page } from '@vitest/browser/context';
import type { Locator } from '@vitest/browser/context';
locators.extend({
clickAndFill(this: Locator, text: string) {
await this.click();
await this.fill(text);
},
});
await page.getByRole('textbox').clickAndFill('Hello World');
Veuillez vous référer à l'API locators.extend
pour davantage de détails.
Gestion explicite des ressources dans vi.spyOn
et vi.fn
Dans les environnements qui prennent en charge la gestion explicite des ressources, vous pouvez utiliser using
au lieu de const
pour appeler automatiquement mockRestore
sur toute fonction mockée à la sortie du bloc conteneur. Ceci est particulièrement utile pour les méthodes espionnées :
it('calls console.log', () => {
using spy = vi.spyOn(console, 'log').mockImplementation(() => {})
debug('message')
expect(spy).toHaveBeenCalled()
})
// console.log est restauré ici
API signal
de test
Vitest fournit désormais un objet AbortSignal
au corps du test. Vous pouvez l'utiliser pour arrêter toute ressource qui prend en charge cette API Web.
Le signal est annulé lorsque le test expire, qu'un autre test échoue et que le drapeau --bail
est défini sur une valeur non nulle, ou lorsque l'utilisateur appuie sur Ctrl+C dans le terminal.
Par exemple, vous pouvez arrêter une requête fetch
lorsque les tests sont interrompus :
it('stop request when test times out', async ({ signal }) => {
await fetch('/heavy-resource', { signal });
}, 2000);
Remappage de la couverture V8 sensible à l'AST
Vitest utilise désormais le package ast-v8-to-istanbul
développé par l'un des mainteneurs de Vitest, AriPerkkio. Cela aligne le rapport de couverture V8 sur Istanbul, tout en offrant de meilleures performances ! Activez cette fonctionnalité en définissant coverage.experimentalAstAwareRemapping
sur true
.
Nous prévoyons de faire de ce mode de remappage le mode par défaut dans la prochaine version majeure. L'ancien v8-to-istanbul
sera complètement supprimé. N'hésitez pas à rejoindre la discussion sur https://github.com/vitest-dev/vitest/issues/7928.
Option watchTriggerPatterns
Lorsque vous modifiez un fichier, Vitest est suffisamment intelligent pour ne réexécuter que les tests qui importent ce fichier. Malheureusement, l'analyse statique de Vitest ne prend en compte que les instructions import
statiques et dynamiques. Si vous lisez un fichier ou démarrez un processus séparé, Vitest ignorera les modifications apportées aux fichiers associés.
Avec l'option watchTriggerPatterns
, vous pouvez configurer quels tests réexécuter en fonction du fichier qui a été modifié. Par exemple, pour toujours réexécuter les tests mailers
lorsqu'un modèle est modifié, ajoutez un modèle de déclenchement :
export default defineConfig({
test: {
watchTriggerPatterns: [
{
pattern: /^src\/templates\/(.*)\.(ts|html|txt)$/,
testsToRun: (file, match) => {
return `api/tests/mailers/${match[2]}.test.ts`;
},
},
],
},
});
Le nouveau type polyvalent Matchers
Vitest dispose désormais d'un type Matchers
que vous pouvez étendre pour ajouter la prise en charge des types pour tous vos matchers personnalisés en un seul endroit. Ce type affecte tous ces cas d'utilisation :
expect().to*
expect.to*
expect.extend({ to* })
Par exemple, pour avoir un matcher toBeFoo
de type sûr, vous pouvez écrire quelque chose comme ceci :
import { expect } from 'vitest';
interface CustomMatchers<R = unknown> {
toBeFoo: (arg: string) => R;
}
declare module 'vitest' {
interface Matchers<T = any> extends CustomMatchers<T> {}
}
expect.extend({
toBeFoo(actual, arg) {
// ^?
// ... implémentation
return {
pass: true,
message: () => '',
};
},
});
expect('foo').toBeFoo('foo');
expect.toBeFoo('foo');
sequence.groupOrder
La nouvelle option sequence.groupOrder
contrôle l'ordre dans lequel les projets exécutent leurs tests lors de l'utilisation de plusieurs projets.
- Les projets avec le même numéro d'ordre de groupe s'exécuteront ensemble, et les groupes sont exécutés du plus bas au plus élevé.
- Si vous ne définissez pas cette option, tous les projets s'exécutent en parallèle.
- Si plusieurs projets utilisent le même ordre de groupe, ils s'exécuteront simultanément.
Exemple
Considérez cet exemple :
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
projects: [
{
test: {
name: 'slow',
sequence: {
groupOrder: 0,
},
},
},
{
test: {
name: 'fast',
sequence: {
groupOrder: 0,
},
},
},
{
test: {
name: 'flaky',
sequence: {
groupOrder: 1,
},
},
},
],
},
});
Les tests de ces projets s'exécuteront dans cet ordre :
0. slow |
|> s'exécutent ensemble
0. fast |
1. flaky |> s'exécute seul après slow et fast
La liste complète des modifications se trouve dans le Changelog de Vitest 3.2.