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
nonea été renommé enpreview#5842 - Le fournisseur
previewest désormais le fournisseur par défaut #5842 indexScriptsa é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_CLASSNAMEetVITEST_JUNIT_SUITE_NAME(utilisez les options du reporter à la place) - Vérification de la couverture
c8(utilisez coverage-v8 à la place) - Exportation de
SnapshotEnvironmentdepuisvitest- importez-le depuisvitest/snapshotà la place SpyInstanceest 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
SnapshotClientjuste pour remplacer la méthodeequalityCheck: il suffit de la passer en tant queisEquallors de l'initialisation d'une instance. client.setTesta été renommé enclient.startCurrentRunclient.resetCurrenta é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.
--threadsest maintenant--pool=threads--no-threadsest maintenant--pool=forks--single-threadest maintenant--poolOptions.threads.singleThread--experimental-vm-threadsest maintenant--pool=vmThreads--experimental-vm-worker-memory-limitest maintenant--poolOptions.vmThreads.memoryLimit--isolateest maintenant--poolOptions.<pool-name>.isolateetbrowser.isolatetest.maxThreadsest maintenanttest.poolOptions.<pool-name>.maxThreadstest.minThreadsest maintenanttest.poolOptions.<pool-name>.minThreadstest.useAtomicsest maintenanttest.poolOptions.<pool-name>.useAtomicstest.poolMatchGlobs.child_processest maintenanttest.poolMatchGlobs.forkstest.poolMatchGlobs.experimentalVmThreadsest 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) => {
it('should work', () => new Promise(done => {
// ...
done()
})
})) 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.