Guide de migration
Migration vers Vitest 2.0
Le pool par défaut est forks
Vitest 2.0 modifie la configuration par défaut de pool
en 'forks'
pour une meilleure stabilité. Vous pouvez consulter la justification complète dans la PR.
Si vous utilisiez poolOptions
sans spécifier de pool
, une mise à jour de votre configuration pourrait être nécessaire :
export default defineConfig({
test: {
poolOptions: {
threads: {
singleThread: true,
},
forks: {
singleFork: true,
},
},
},
});
Les hooks s'exécutent en série
Avant Vitest 2.0, tous les hooks s'exécutaient en parallèle. Dans la version 2.0, ils s'exécutent désormais en série. De plus, les hooks afterAll
/afterEach
s'exécutent dans l'ordre inverse.
Pour rétablir l'exécution parallèle des hooks, définissez sequence.hooks
sur 'parallel'
:
export default defineConfig({
test: {
sequence: {
hooks: 'parallel',
},
},
});
suite.concurrent
exécute tous les tests concurremment
Auparavant, l'utilisation de concurrent
sur une suite regroupait les tests concurrents par suite, les exécutant séquentiellement. Désormais, conformément au comportement de Jest, tous les tests s'exécutent concurremment (sous réserve des limites de maxConcurrency
).
L'option coverage.ignoreEmptyLines
de la couverture V8 est activée par défaut
La valeur par défaut de coverage.ignoreEmptyLines
est désormais true
. Ce changement significatif peut affecter les rapports de couverture de code, nécessitant des ajustements des seuils de couverture pour certains projets. Cet ajustement n'affecte que le paramètre par défaut lorsque coverage.provider
est 'v8'
.
Suppression de l'option watchExclude
Vitest utilise le watcher de Vite. Pour exclure des fichiers ou des répertoires, ajoutez-les à server.watch.ignored
:
export default defineConfig({
server: {
watch: {
ignored: ['!node_modules/examplejs'],
},
},
});
--segfault-retry
supprimé
Avec les changements apportés au pool par défaut, cette option n'est plus nécessaire. Si vous rencontrez des erreurs de segfault, essayez de passer au pool 'forks'
. Si le problème persiste, veuillez ouvrir une nouvelle issue avec une reproduction.
Suppression des tâches vides dans les suites
Ceci est un changement apporté à l'API de tâche avancée. Auparavant, la traversée de .suite
menait finalement à la suite interne vide qui était utilisée à la place d'une tâche de fichier.
Cela rend .suite
facultatif ; si la tâche est définie au niveau supérieur, elle n'aura pas de suite. Vous pouvez revenir à la propriété .file
qui est maintenant présente sur toutes les tâches (y compris la tâche de fichier elle-même, donc faites attention à ne pas tomber dans une récursion infinie).
Ce changement supprime également le fichier de expect.getState().currentTestName
et rend expect.getState().testPath
obligatoire.
task.meta
est ajouté au reporter JSON
Le reporter JSON inclut désormais task.meta
pour chaque résultat d'assertion.
Simplification des types génériques des fonctions de mock (par exemple vi.fn<T>
, Mock<T>
)
Auparavant, vi.fn<TArgs, TReturn>
acceptait deux types génériques distincts pour les arguments et la valeur de retour. Ceci a été modifié pour accepter directement un type de fonction vi.fn<T>
afin de simplifier son utilisation.
import { type Mock, vi } from 'vitest';
const add = (x: number, y: number): number => x + y;
// using vi.fn<T>
const mockAdd = vi.fn<Parameters<typeof add>, ReturnType<typeof add>>();
const mockAdd = vi.fn<typeof add>();
// using Mock<T>
const mockAdd: Mock<Parameters<typeof add>, ReturnType<typeof add>> = vi.fn();
const mockAdd: Mock<typeof add> = vi.fn();
Accès aux mock.results
résolus
Auparavant, Vitest résolvait les valeurs de mock.results
si la fonction renvoyait une Promesse. Il existe maintenant une propriété mock.settledResults
distincte qui n'est remplie que lorsque la Promesse retournée est résolue ou rejetée.
const fn = vi.fn().mockResolvedValueOnce('result');
await fn();
const result = fn.mock.results[0]; // 'result'
const result = fn.mock.results[0]; // 'Promise<result>'
const settledResult = fn.mock.settledResults[0]; // 'result'
Avec ce changement, nous introduisons également de nouveaux matchers toHaveResolved*
similaires à toHaveReturned
pour faciliter la migration si vous utilisiez toHaveReturned
auparavant :
const fn = vi.fn().mockResolvedValueOnce('result');
await fn();
expect(fn).toHaveReturned('result');
expect(fn).toHaveResolved('result');
Mode Navigateur
Le mode navigateur de Vitest a connu de nombreux changements pendant le cycle bêta. Vous pouvez en savoir plus sur notre philosophie concernant le mode navigateur sur la page de discussion GitHub.
La plupart des changements étaient additifs, mais il y a eu quelques petits changements cassants :
- Le fournisseur
none
a été renommé enpreview
#5842 - Le fournisseur
preview
est désormais le fournisseur par défaut #5842 indexScripts
a été renommé enorchestratorScripts
#5842
Options dépréciées supprimées
Certaines options obsolètes ont été supprimées :
- Commande
vitest typecheck
- utilisezvitest --typecheck
à la place - Variables d'environnement
VITEST_JUNIT_CLASSNAME
etVITEST_JUNIT_SUITE_NAME
(utilisez les options du reporter à la place) - Vérification de la couverture
c8
(utilisez coverage-v8 à la place) - Exportation de
SnapshotEnvironment
depuisvitest
- importez-le depuisvitest/snapshot
à la place SpyInstance
est supprimé au profit deMockInstance
Migration vers Vitest 1.0
Exigences minimales
Vitest 1.0 nécessite Vite 5.0 et Node.js 18 ou supérieur.
Tous les sous-packages @vitest/*
nécessitent Vitest version 1.0.
Mise à jour des instantanés #3961
Les guillemets dans les instantanés ne sont plus échappés, et tous les instantanés utilisent des guillemets inversés (`) même si la chaîne est une seule ligne.
- Les guillemets ne sont plus échappés :
expect({ foo: 'bar' }).toMatchInlineSnapshot(`
Object {
- \\"foo\\": \\"bar\\",
+ "foo": "bar",
}
`)
- Les instantanés sur une seule ligne utilisent maintenant les guillemets "`" au lieu de '"' :
- expect('some string').toMatchInlineSnapshot('"some string"')
+ expect('some string').toMatchInlineSnapshot(`"some string"`)
Il y a également eu des modifications au package @vitest/snapshot
. Si vous ne l'utilisez pas directement, vous n'avez rien à changer.
- Vous n'avez plus besoin d'étendre
SnapshotClient
juste pour remplacer la méthodeequalityCheck
: il suffit de la passer en tant queisEqual
lors de l'initialisation d'une instance. client.setTest
a été renommé enclient.startCurrentRun
client.resetCurrent
a été renommé enclient.finishCurrentRun
Les pools sont standardisés #4172
Nous avons éliminé de nombreuses options de configuration pour faciliter la configuration du runner selon vos besoins. Veuillez consulter les exemples de migration si vous utilisez --threads
ou d'autres drapeaux similaires.
--threads
est maintenant--pool=threads
--no-threads
est maintenant--pool=forks
--single-thread
est maintenant--poolOptions.threads.singleThread
--experimental-vm-threads
est maintenant--pool=vmThreads
--experimental-vm-worker-memory-limit
est maintenant--poolOptions.vmThreads.memoryLimit
--isolate
est maintenant--poolOptions.<pool-name>.isolate
etbrowser.isolate
test.maxThreads
est maintenanttest.poolOptions.<pool-name>.maxThreads
test.minThreads
est maintenanttest.poolOptions.<pool-name>.minThreads
test.useAtomics
est maintenanttest.poolOptions.<pool-name>.useAtomics
test.poolMatchGlobs.child_process
est maintenanttest.poolMatchGlobs.forks
test.poolMatchGlobs.experimentalVmThreads
est maintenanttest.poolMatchGlobs.vmThreads
{
scripts: {
- "test": "vitest --no-threads"
// Pour un comportement identique :
+ "test": "vitest --pool forks --poolOptions.forks.singleFork"
// Ou plusieurs forks parallèles :
+ "test": "vitest --pool forks"
}
}
{
scripts: {
- "test": "vitest --experimental-vm-threads"
+ "test": "vitest --pool vmThreads"
}
}
{
scripts: {
- "test": "vitest --isolate false"
+ "test": "vitest --poolOptions.threads.isolate false"
}
}
{
scripts: {
- "test": "vitest --no-threads --isolate false"
+ "test": "vitest --pool forks --poolOptions.forks.isolate false"
}
}
Modifications de la couverture #4265, #4442
L'option coverage.all
est maintenant activée par défaut. Cela signifie que tous les fichiers du projet correspondant au modèle coverage.include
seront traités même s'ils ne sont pas exécutés.
La forme de l'API des seuils de couverture a été modifiée, et elle prend désormais en charge la spécification de seuils pour des fichiers spécifiques à l'aide de modèles glob :
export default defineConfig({
test: {
coverage: {
- perFile: true,
- thresholdAutoUpdate: true,
- 100: true,
- lines: 100,
- functions: 100,
- branches: 100,
- statements: 100,
+ thresholds: {
+ perFile: true,
+ autoUpdate: true,
+ 100: true,
+ lines: 100,
+ functions: 100,
+ branches: 100,
+ statements: 100,
+ }
}
}
})
Types de mocks #4400
Quelques types ont été supprimés au profit de la nomenclature "Mock" de style Jest.
- import { EnhancedSpy, SpyInstance } from 'vitest'
+ import { MockInstance } from 'vitest'
WARNING
SpyInstance
est déprécié au profit de MockInstance
et sera supprimé dans la prochaine version majeure.
Mocks de temporisateurs #3925
vi.useFakeTimers()
ne simule plus automatiquement process.nextTick
. Il est toujours possible de simuler process.nextTick
en le spécifiant explicitement à l'aide de vi.useFakeTimers({ toFake: ['nextTick'] })
.
Cependant, la simulation de process.nextTick
n'est pas possible lors de l'utilisation de --pool=forks
. Utilisez une option --pool
différente si vous avez besoin de la simulation de process.nextTick
.
Migration depuis Jest
Vitest a été conçu avec une API compatible avec Jest, afin de rendre la migration depuis Jest aussi simple que possible. Malgré ces efforts, vous pourriez toujours rencontrer les différences suivantes :
Les globales par défaut
Jest a son API globale activée par défaut. Vitest ne l'a pas. Vous pouvez soit activer les globales via le paramètre de configuration globals
, soit mettre à jour votre code pour utiliser les importations du module vitest
à la place.
Si vous décidez de laisser les globales désactivées, sachez que les bibliothèques courantes comme testing-library
n'exécuteront pas le nettoyage automatique du DOM.
Mocks de modules
Lors de la simulation d'un module dans Jest, la valeur de retour de l'argument factory est l'exportation par défaut. Dans Vitest, l'argument factory doit retourner un objet avec chaque exportation explicitement définie. Par exemple, le jest.mock
suivant devrait être mis à jour comme suit :
jest.mock('./some-path', () => 'hello');
vi.mock('./some-path', () => ({
default: 'hello',
}));
Pour plus de détails, veuillez vous référer à la section de l'API vi.mock
.
Comportement d'auto-mocking
Contrairement à Jest, les modules mockés dans <root>/__mocks__
ne sont pas chargés à moins que vi.mock()
ne soit appelé. Si vous avez besoin qu'ils soient mockés dans chaque test, comme dans Jest, vous pouvez les mocker à l'intérieur de setupFiles
.
Importation de l'original d'un package mocké
Si vous ne simulez qu'une partie d'un package, vous avez peut-être utilisé auparavant la fonction requireActual
de Jest. Dans Vitest, vous devriez remplacer ces appels par vi.importActual
.
const { cloneDeep } = jest.requireActual('lodash/cloneDeep');
const { cloneDeep } = await vi.importActual('lodash/cloneDeep');
Étendre la simulation aux bibliothèques externes
Contrairement à Jest qui le fait par défaut, si vous simulez un module et souhaitez que cette simulation s'applique également aux bibliothèques externes qui utilisent ce même module, vous devez explicitement spécifier la bibliothèque tierce à simuler. Pour cela, utilisez server.deps.inline
afin que la bibliothèque externe soit traitée comme faisant partie de votre code source.
server.deps.inline: ["lib-name"]
expect.getState().currentTestName
Les noms de test
de Vitest sont joints par un symbole >
pour faciliter la distinction entre les tests et les suites, tandis que Jest utilise un espace vide ().
- `${describeTitle} ${testTitle}`
+ `${describeTitle} > ${testTitle}`
Variables d'environnement
Tout comme Jest, Vitest définit NODE_ENV
à test
, s'il n'était pas déjà défini. Vitest a également un équivalent pour JEST_WORKER_ID
appelé VITEST_POOL_ID
(toujours inférieur ou égal à maxThreads
), donc si vous vous en servez, n'oubliez pas de le renommer. Vitest expose également VITEST_WORKER_ID
qui est un ID unique d'un worker en cours d'exécution - ce nombre n'est pas affecté par maxThreads
, et augmentera avec chaque worker créé.
Remplacement de propriété
Si vous souhaitez modifier l'objet, vous utiliserez l'API replaceProperty dans Jest, vous pouvez utiliser vi.stubEnv
ou vi.spyOn
pour faire la même chose également dans Vitest.
Fonction de rappel done
À partir de Vitest v0.10.0, le style de déclaration des tests par rappel est déprécié. Vous pouvez les réécrire pour utiliser des fonctions async
/await
, ou utiliser une Promesse pour imiter le style de rappel.
it('should work', (done) => { // [!code --]
it('should work', () => new Promise(done => { // [!code ++]
// ...
done()
}) // [!code --]
})) // [!code ++]
Hooks
Les hooks beforeAll
/beforeEach
peuvent retourner une fonction de nettoyage dans Vitest. Pour cette raison, vous devrez peut-être réécrire vos déclarations de hooks, s'ils retournent autre chose que undefined
ou null
:
beforeEach(() => setActivePinia(createTestingPinia()));
beforeEach(() => {
setActivePinia(createTestingPinia());
});
Dans Jest, les hooks sont appelés séquentiellement (l'un après l'autre). Par défaut, Vitest exécute les hooks en parallèle. Pour utiliser le comportement de Jest, mettez à jour l'option sequence.hooks
:
export default defineConfig({
test: {
sequence: {
hooks: 'list',
},
},
});
Types
Vitest n'a pas d'équivalent à l'espace de noms jest
, vous devrez donc importer les types directement depuis vitest
:
let fn: jest.Mock<(name: string) => number>;
import type { Mock } from 'vitest';
let fn: Mock<(name: string) => number>;
Temporisateurs
Vitest ne prend pas en charge les temporisateurs hérités de Jest.
Délai d'attente
Si vous utilisiez jest.setTimeout
, vous devrez migrer vers vi.setConfig
:
jest.setTimeout(5_000);
vi.setConfig({ testTimeout: 5_000 });
Instantanés Vue
Ce n'est pas une fonctionnalité spécifique à Jest, mais si vous utilisiez auparavant Jest avec le préréglage vue-cli, vous devrez installer le package jest-serializer-vue
et l'utiliser dans setupFiles :
import { defineConfig } from 'vite';
export default defineConfig({
test: {
setupFiles: ['./tests/unit/setup.js'],
},
});
import vueSnapshotSerializer from 'jest-serializer-vue';
expect.addSnapshotSerializer(vueSnapshotSerializer);
Sinon, vos instantanés auront beaucoup de caractères "
échappés.