Passer au contenu

Guide de Migration

Migration vers Vitest 2.0

Le Pool par Défaut est forks

Vitest 2.0 change la configuration par défaut pour pool en 'forks' pour une meilleure stabilité. Vous pouvez lire la motivation complète dans PR.

Si vous avez utilisé poolOptions sans spécifier un pool, vous devez mettre à jour la configuration :

export default defineConfig({
test: {
poolOptions: {
threads: { // [!code --]
singleThread: true, // [!code --]
}, // [!code --]
forks: { // [!code ++]
singleFork: true, // [!code ++]
}, // [!code ++]
}
}
})

Les Hooks S’exécutent en Pile

Avant Vitest 2.0, tous les hooks s’exécutaient en parallèle. Dans 2.0, tous les hooks s’exécutent de manière séquentielle. De plus, les hooks afterAll/afterEach s’exécutent dans l’ordre inverse.

Pour revenir à l’exécution parallèle des hooks, changez sequence.hooks à 'parallel' :

export default defineConfig({
test: {
sequence: { // [!code ++]
hooks: 'parallel', // [!code ++]
}, // [!code ++]
},
})

suite.concurrent Exécute Tous les Tests Concurrentement

Auparavant, spécifier concurrent sur un suite regroupait les tests concurrents par suites, les exécutant séquentiellement. Maintenant, suivant le comportement de Jest, tous les tests s’exécutent de manière concurrente (sous réserve des limites maxConcurrency).

coverage.ignoreEmptyLines de V8 Est Activé par Défaut

La valeur par défaut de coverage.ignoreEmptyLines est maintenant vraie. 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. Excluez les fichiers ou répertoires en les ajoutant à server.watch.ignored :

export default defineConfig({
server: { // [!code ++]
watch: { // [!code ++]
ignored: ['!node_modules/examplejs'] // [!code ++]
} // [!code ++]
} // [!code ++]
})

--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 segmentation, essayez de passer au pool 'forks'. Si le problème persiste, veuillez ouvrir un nouveau problème avec une reproduction.

Suppression de Tâches Vides dans les Tâches de Suite

C’est le changement dans l’API de tâche avancée. Auparavant, parcourir .suite conduisait 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, alors soyez prudent pour ne pas tomber dans la récursivité infinie).

Ce changement supprime également le fichier de expect.getState().currentTestName et rend expect.getState().testPath requis.

task.meta Est Ajouté au Rapporteur JSON

Le rapporteur JSON imprime maintenant task.meta pour chaque résultat d’assertion.

Types Génériques Simplifiés des Fonctions Mock (par exemple, vi.fn<T>, Mock<T>)

Auparavant, vi.fn<TArgs, TReturn> acceptait deux types génériques séparément pour les arguments et la valeur de retour. Cela a été modifié pour accepter directement un type de fonction vi.fn<T> afin de simplifier l’utilisation.

import { type Mock, vi } from 'vitest'
const add = (x: number, y: number): number => x + y
// utilisant vi.fn<T>
const mockAdd = vi.fn<Parameters<typeof add>, ReturnType<typeof add>>() // [!code --]
const mockAdd = vi.fn<typeof add>() // [!code ++]
// utilisant Mock<T>
const mockAdd: Mock<Parameters<typeof add>, ReturnType<typeof add>> = vi.fn() // [!code --]
const mockAdd: Mock<typeof add> = vi.fn() // [!code ++]

Accès aux Résultats Résolus de mock.results

Auparavant, Vitest résolvait les valeurs de mock.results si la fonction retournait une promesse. Maintenant, il y a une propriété mock.settledResults séparée qui se remplit uniquement 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' // [!code --]
const result = fn.mock.results[0] // 'Promise<result>' // [!code ++]
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 avez utilisé toHaveReturned auparavant :

const fn = vi.fn().mockResolvedValueOnce('result')
await fn()
expect(fn).toHaveReturned('result') // [!code --]
expect(fn).toHaveResolved('result') // [!code ++]

Mode Navigateur

Le mode navigateur de Vitest a subi de nombreux changements durant le cycle beta. Vous pouvez lire notre philosophie sur le mode navigateur dans la page de discussion GitHub.

La plupart des changements ont été additifs, mais il y a eu quelques petits changements perturbateurs :

  • Le fournisseur none a été renommé en preview #5842
  • Le fournisseur preview est maintenant par défaut #5842
  • indexScripts a été renommé en orchestratorScripts #5842

Options Dépréciées Supprimées

Certaines options dépréciées ont été supprimées :

  • la commande vitest typecheck - utilisez vitest --typecheck à la place
  • les variables d’environnement VITEST_JUNIT_CLASSNAME et VITEST_JUNIT_SUITE_NAME (utilisez plutôt les options de rapporteur)
  • vérifiez la couverture c8 (utilisez plutôt coverage-v8)
  • exportation de SnapshotEnvironment depuis vitest - importez-le depuis vitest/snapshot
  • SpyInstance a été supprimé au profit de MockInstance

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 la version 1.0 de Vitest.

Mises à Jour des Snapshots #3961

Les guillemets dans les snapshots ne sont plus échappés, et tous les snapshots utilisent des guillemets inversés (`) même si la chaîne est une seule ligne.

  1. Les guillemets ne sont plus échappés :
expect({ foo: 'bar' }).toMatchInlineSnapshot(`
Object {
\\"foo\\": \\"bar\\",
"foo": "bar",
}
`)
  1. Les snapshots d’une ligne utilisent maintenant des guillemets ”`” au lieu de ’ :
expect('some string').toMatchInlineSnapshot('"some string"')
expect('some string').toMatchInlineSnapshot(`"some string"`)

Il y a également eu des changements dans le package @vitest/snapshot. Si vous ne l’utilisez pas directement, vous n’avez pas besoin de changer quoi que ce soit.

  • Vous n’avez plus besoin d’étendre SnapshotClient juste pour remplacer la méthode equalityCheck : passez-la simplement comme isEqual lors de l’initialisation d’une instance
  • client.setTest a été renommé en client.startCurrentRun
  • client.resetCurrent a été renommé en client.finishCurrentRun

Les Pools sont Standardisés #4172

Nous avons supprimé de nombreuses options de configuration pour faciliter la configuration du runner selon vos besoins. Veuillez consulter des exemples de migration si vous dépendez de --threads ou d’autres drapeaux connexes.

  • --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 et browser.isolate
  • test.maxThreads est maintenant test.poolOptions.<pool-name>.maxThreads
  • test.minThreads est maintenant test.poolOptions.<pool-name>.minThreads
  • test.useAtomics est maintenant test.poolOptions.<pool-name>.useAtomics
  • test.poolMatchGlobs.child_process est maintenant test.poolMatchGlobs.forks
  • test.poolMatchGlobs.experimentalVmThreads est maintenant test.poolMatchGlobs.vmThreads
{
scripts: {
"test": "vitest --no-threads"
// Pour un comportement identique :
"test": "vitest --pool forks --poolOptions.forks.singleFork"
// Ou multi 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"
}
}

Changements de 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 structure de l’API des seuils de couverture a été modifiée, et elle prend maintenant en charge la spécification des seuils pour des fichiers spécifiques en utilisant des modèles globaux :

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 Mock #4400

Quelques types ont été supprimés au profit de la nomenclature de type “Mock” de Jest.

import { EnhancedSpy, SpyInstance } from 'vitest'
import { MockInstance } from 'vitest'

Mocks de Minuteurs #3925

vi.useFakeTimers() ne simule plus automatiquement process.nextTick. Il est toujours possible de simuler process.nextTick en le spécifiant explicitement en utilisant vi.useFakeTimers({ toFake: ['nextTick'] }).

Cependant, la simulation de process.nextTick n’est pas possible lors de l’utilisation de --pool=forks. Utilisez une autre option --pool si vous avez besoin de simuler process.nextTick.

Migration de Jest

Vitest a été conçu avec une API compatible avec Jest, afin de rendre la migration de Jest aussi simple que possible. Malgré ces efforts, vous pourriez encore rencontrer les différences suivantes :

Globals par Défaut

Jest a leur API globals activée par défaut. Vitest ne le fait pas. Vous pouvez soit activer les globals via le paramètre de configuration globals soit mettre à jour votre code pour utiliser des importations du module vitest à la place.

Si vous décidez de garder les globals désactivés, soyez conscient que des bibliothèques courantes comme testing-library ne feront pas d’auto nettoyage du DOM cleanup.

Mocks de Modules

Lors de la simulation d’un module dans Jest, la valeur de retour de l’argument de la factory est l’exportation par défaut. Dans Vitest, l’argument de la factory doit retourner un objet avec chaque exportation définie explicitement. Par exemple, le jest.mock suivant devrait être mis à jour comme suit :

jest.mock('./some-path', () => 'hello') // [!code --]
vi.mock('./some-path', () => ({ // [!code ++]
default: 'hello', // [!code ++]
})) // [!code ++]

Pour plus de détails, veuillez vous référer à la section vi.mock api.

Comportement de Simulation Automatique

Contrairement à Jest, les modules simulés dans <root>/__mocks__ ne sont pas chargés à moins que vi.mock() soit appelé. Si vous avez besoin qu’ils soient simulés dans chaque test, comme dans Jest, vous pouvez les simuler dans setupFiles.

Importation de l’Original d’un Paquet Simulé

Si vous ne simulez qu’une partie d’un paquet, vous avez peut-être utilisé la fonction requireActual de Jest. Dans Vitest, vous devez remplacer ces appels par vi.importActual.

const { cloneDeep } = jest.requireActual('lodash/cloneDeep') // [!code --]
const { cloneDeep } = await vi.importActual('lodash/cloneDeep') // [!code ++]

Extension de la Simulation aux Bibliothèques Externes

Là où Jest le fait par défaut, lors de la simulation d’un module et souhaitant que cette simulation soit étendue à d’autres bibliothèques externes qui utilisent le même module, vous devez spécifiquement indiquer quelle bibliothèque tierce vous souhaitez simuler, afin que la bibliothèque externe fasse partie de votre code source, en utilisant server.deps.inline.

server.deps.inline: ["lib-name"]

expect.getState().currentTestName

Les noms de test de Vitest sont joints avec un symbole > pour faciliter la distinction entre les tests et les suites, tandis que Jest utilise un espace vide ( ).

`${describeTitle} ${testTitle}`
`${describeTitle} > ${testTitle}`

Envs

Tout comme Jest, Vitest définit NODE_ENV à test, s’il n’était pas défini auparavant. Vitest a également un pendant pour JEST_WORKER_ID appelé VITEST_POOL_ID (toujours inférieur ou égal à maxThreads), donc si vous en dépendez, n’oubliez pas de renommer. Vitest expose également VITEST_WORKER_ID qui est un identifiant unique d’un worker en cours d’exécution - ce nombre n’est pas affecté par maxThreads et augmentera avec chaque worker créé.

Remplacer la 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 de même également dans Vitest.

Callback de Fin

Depuis Vitest v0.10.0, le style de callback pour déclarer des tests est déprécié. Vous pouvez les réécrire pour utiliser des fonctions async/await, ou utiliser Promise pour imiter le style de callback.

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. De ce fait, vous devrez peut-être réécrire vos déclarations de hooks, si elles retournent quelque chose d’autre que undefined ou null :

beforeEach(() => setActivePinia(createTestingPinia())) // [!code --]
beforeEach(() => { setActivePinia(createTestingPinia()) }) // [!code ++]

Dans Jest, les hooks sont appelés séquentiellement (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: { // [!code ++]
hooks: 'list', // [!code ++]
} // [!code ++]
}
})

Types

Vitest n’a pas d’équivalent au namespace jest, donc vous devrez importer les types directement depuis vitest :

let fn: jest.Mock<(name: string) => number> // [!code --]
import type { Mock } from 'vitest' // [!code ++]
let fn: Mock<(name: string) => number> // [!code ++]

Minuteurs

Vitest ne prend pas en charge les minuteries héritées de Jest.

Délai d’attente

Si vous avez utilisé jest.setTimeout, vous devrez migrer vers vi.setConfig :

jest.setTimeout(5_000) // [!code --]
vi.setConfig({ testTimeout: 5_000 }) // [!code ++]

Snapshots Vue

Ce n’est pas une fonctionnalité spécifique à Jest, mais si vous utilisiez auparavant Jest avec le preset vue-cli, vous devrez installer le package jest-serializer-vue, et l’utiliser à l’intérieur des setupFiles:

import { defineConfig } from 'vite'
export default defineConfig({
test: {
setupFiles: ['./tests/unit/setup.js']
}
})

Sinon, vos snapshots contiendront de nombreux caractères " échappés.