Vi
Vitest proporciona funciones de utilidad para ayudarte a través de su helper vi
. Puedes acceder a él globalmente (cuando la configuración de globales está habilitada), o importarlo directamente desde vitest
:
import { vi } from 'vitest';
Simulación de Módulos
Esta sección describe la API que puedes usar cuando simulas un módulo (mocking a module). Ten en cuenta que Vitest no admite simular módulos importados usando require()
.
vi.mock
- Tipo:
(path: string, factory?: (importOriginal: () => unknown) => unknown) => void
Reemplaza todos los módulos importados desde la ruta
proporcionada con otro módulo. Puedes usar alias de Vite configurados dentro de una ruta. La llamada a vi.mock
se eleva, por lo que no importa dónde la llames. Siempre se ejecutará antes de todas las importaciones. Si necesitas hacer referencia a variables que están fuera de este ámbito, puedes definirlas dentro de vi.hoisted
y hacer referencia a ellas dentro de vi.mock
.
WARNING
vi.mock
solo funciona para módulos que se importaron con la palabra clave import
. No funciona con require
.
Para que vi.mock
funcione correctamente, Vitest realiza un análisis estático de tus archivos. Esto significa que no puedes usar vi
si no lo importaste directamente desde el paquete vitest
(por ejemplo, desde algún archivo de utilidad). Usa vi.mock
con vi
importado desde vitest
, o habilita la opción de configuración globals
.
Vitest no simulará módulos que se importaron dentro de un archivo de configuración. Esto se debe a que se almacenan en caché cuando se está ejecutando un archivo de prueba. Puedes llamar a vi.resetModules()
dentro de vi.hoisted
para borrar todas las cachés de módulos antes de ejecutar un archivo de prueba.
WARNING
El modo navegador actualmente no admite la simulación de módulos. Puedes hacer un seguimiento de esta función en el issue de GitHub.
Si se define factory
, todas las importaciones devolverán su resultado. Vitest llama a factory
solo una vez y almacena en caché los resultados para todas las importaciones posteriores hasta que se llama a vi.unmock
o vi.doUnmock
.
A diferencia de jest
, el factory
puede ser asíncrono. Puedes usar vi.importActual
o pasar el factory
como primer argumento de un helper para obtener el módulo original.
import { vi } from 'vitest';
// ---cut---
// JavaScript
vi.mock('./path/to/module.js', async importOriginal => {
const mod = await importOriginal();
return {
...mod,
// replace some exports
namedExport: vi.fn(),
};
});
// TypeScript
vi.mock('./path/to/module.js', async importOriginal => {
const mod = await importOriginal<typeof import('./path/to/module.js')>();
return {
...mod,
// replace some exports
namedExport: vi.fn(),
};
});
WARNING
vi.mock
se eleva (es decir, se mueve) a la parte superior del archivo. Esto significa que, independientemente de dónde lo escribas (ya sea dentro de beforeEach
o test
), en realidad se llamará antes de eso.
Esto también significa que no puedes usar ninguna variable dentro del factory
que esté definida fuera del factory
.
Si necesitas usar variables dentro del factory
, prueba vi.doMock
. Funciona de la misma manera, pero no se eleva. Ten en cuenta que solo simula las importaciones posteriores.
También puedes hacer referencia a variables definidas por el método vi.hoisted
si se declaró antes de vi.mock
:
import { namedExport } from './path/to/module.js';
const mocks = vi.hoisted(() => {
return {
namedExport: vi.fn(),
};
});
vi.mock('./path/to/module.js', () => {
return {
namedExport: mocks.namedExport,
};
});
vi.mocked(namedExport).mockReturnValue(100);
expect(namedExport()).toBe(100);
expect(namedExport).toBe(mocks.namedExport);
WARNING
Si estás simulando un módulo con exportación por defecto, deberás proporcionar una clave default
dentro del objeto de función factory
devuelto. Esta es una advertencia específica del módulo ES; por lo tanto, la documentación de jest
puede diferir ya que jest
usa módulos CommonJS. Por ejemplo:
vi.mock('./path/to/module.js', () => {
return {
default: { myDefaultKey: vi.fn() },
namedExport: vi.fn(),
// etc...
};
});
Si hay una carpeta __mocks__
junto a un archivo que estás simulando, y no se proporciona el factory
, Vitest intentará encontrar un archivo con el mismo nombre en la subcarpeta __mocks__
y lo usará como un módulo real. Si estás simulando una dependencia, Vitest intentará encontrar una carpeta __mocks__
en la raíz del proyecto (el valor predeterminado es process.cwd()
). Puedes indicarle a Vitest dónde se encuentran las dependencias a través de la opción de configuración deps.moduleDirectories.
Por ejemplo, tienes esta estructura de archivos:
- __mocks__
- axios.js
- src
__mocks__
- increment.js
- increment.js
- tests
- increment.test.js
Si llamas a vi.mock
en un archivo de prueba sin proporcionar un factory
, encontrará un archivo en la carpeta __mocks__
para usarlo como módulo:
// increment.test.js
import { vi } from 'vitest';
// axios is a default export from `__mocks__/axios.js`
import axios from 'axios';
// increment is a named export from `src/__mocks__/increment.js`
import { increment } from '../increment.js';
vi.mock('axios');
vi.mock('../increment.js');
axios.get(`/apples/${increment(1)}`);
WARNING
Ten en cuenta que si no llamas a vi.mock
, los módulos no se simulan automáticamente. Para replicar el comportamiento de simulación automática de Jest, puedes llamar a vi.mock
para cada módulo requerido dentro de setupFiles
.
Si no hay una carpeta __mocks__
o se proporciona un factory
, Vitest importará el módulo original y simulará automáticamente todas sus exportaciones. Para conocer las reglas aplicadas, consulta algoritmo.
vi.doMock
- Tipo:
(path: string, factory?: (importOriginal: () => unknown) => unknown) => void
Lo mismo que vi.mock
, pero no se eleva a la parte superior del archivo, por lo que puedes hacer referencia a variables en el ámbito del archivo global. La siguiente importación dinámica de este módulo será simulada.
WARNING
Esto no simulará los módulos que se importaron antes de que esto se llame. No olvides que todas las importaciones estáticas en ESM siempre se elevan, por lo que colocar esto antes de la importación estática no forzará que se llame antes de la importación:
vi.doMock('./increment.js'); // this will be called _after_ the import statement
import { increment } from './increment.js';
// ./increment.js
export function increment(number) {
return number + 1;
}
import { beforeEach, test } from 'vitest';
import { increment } from './increment.js';
// the module is not mocked, because vi.doMock is not called yet
increment(1) === 2;
let mockedIncrement = 100;
beforeEach(() => {
// you can access variables inside a factory
vi.doMock('./increment.js', () => ({ increment: () => ++mockedIncrement }));
});
test('importing the next module imports mocked one', async () => {
// original import WAS NOT MOCKED, because vi.doMock is evaluated AFTER imports
expect(increment(1)).toBe(2);
const { increment: mockedIncrement } = await import('./increment.js');
// new dynamic import returns mocked module
expect(mockedIncrement(1)).toBe(101);
expect(mockedIncrement(1)).toBe(102);
expect(mockedIncrement(1)).toBe(103);
});
vi.mocked
- Tipo:
<T>(obj: T, deep?: boolean) => MaybeMockedDeep<T>
- Tipo:
<T>(obj: T, options?: { partial?: boolean; deep?: boolean }) => MaybePartiallyMockedDeep<T>
Utilidad de tipo para TypeScript. Simplemente devuelve el objeto que se pasó.
Cuando partial
es true
, esperará un Partial<T>
como valor de retorno. De forma predeterminada, esto solo hará que TypeScript crea que los valores del primer nivel están simulados. Puedes pasar { deep: true }
como segundo argumento para indicarle a TypeScript que todo el objeto está simulado, si realmente lo está.
import example from './example.js';
vi.mock('./example.js');
test('1 + 1 equals 10', async () => {
vi.mocked(example.calc).mockReturnValue(10);
expect(example.calc(1, '+', 1)).toBe(10);
});
vi.importActual
- Tipo:
<T>(path: string) => Promise<T>
Importa el módulo, omitiendo todas las comprobaciones sobre si debe simularse. Puede ser útil si deseas simular el módulo parcialmente.
vi.mock('./example.js', async () => {
const axios = await vi.importActual('./example.js');
return { ...axios, get: vi.fn() };
});
vi.importMock
- Tipo:
<T>(path: string) => Promise<MaybeMockedDeep<T>>
Importa un módulo con todas sus propiedades (incluidas las propiedades anidadas) simuladas. Sigue las mismas reglas que vi.mock
. Para conocer las reglas aplicadas, consulta algoritmo.
vi.unmock
- Tipo:
(path: string) => void
Elimina el módulo del registro simulado. Todas las llamadas a import
devolverán el módulo original, incluso si se simuló antes. Esta llamada se eleva a la parte superior del archivo. Por lo tanto, solo anulará la simulación de los módulos definidos en setupFiles
, por ejemplo.
vi.doUnmock
- Tipo:
(path: string) => void
Lo mismo que vi.unmock
, pero no se eleva a la parte superior del archivo. La siguiente importación del módulo importará el módulo original en lugar del mock. Esto no anulará la simulación de los módulos importados anteriormente.
// ./increment.js
export function increment(number) {
return number + 1;
}
import { increment } from './increment.js';
// increment is already mocked, because vi.mock is hoisted
increment(1) === 100;
// this is hoisted, and factory is called before the import on line 1
vi.mock('./increment.js', () => ({ increment: () => 100 }));
// all calls are mocked, and `increment` always returns 100
increment(1) === 100;
increment(30) === 100;
// this is not hoisted, so other import will return unmocked module
vi.doUnmock('./increment.js');
// this STILL returns 100, because `vi.doUnmock` doesn't reevaluate a module
increment(1) === 100;
increment(30) === 100;
// the next import is unmocked, now `increment` is the original function that returns count + 1
const { increment: unmockedIncrement } = await import('./increment.js');
unmockedIncrement(1) === 2;
unmockedIncrement(30) === 31;
vi.resetModules
- Tipo:
() => Vitest
Restablece el registro de módulos borrando la caché de todos los módulos. Esto permite que los módulos se vuelvan a evaluar cuando se vuelven a importar. Las importaciones de nivel superior no se pueden volver a evaluar. Podría ser útil para aislar módulos donde el estado local entra en conflicto entre las pruebas.
import { vi } from 'vitest';
import { data } from './data.js'; // Will not get reevaluated beforeEach test
beforeEach(() => {
vi.resetModules();
});
test('change state', async () => {
const mod = await import('./some/path.js'); // Will get reevaluated
mod.changeLocalState('new value');
expect(mod.getLocalState()).toBe('new value');
});
test('module has old state', async () => {
const mod = await import('./some/path.js'); // Will get reevaluated
expect(mod.getLocalState()).toBe('old value');
});
WARNING
No restablece el registro de mocks. Para borrar el registro de mocks, usa vi.unmock
o vi.doUnmock
.
vi.dynamicImportSettled
Espera a que se carguen todas las importaciones dinámicas. Útil si tienes una llamada síncrona que comienza a importar un módulo que no puedes esperar de otra manera.
import { expect, test } from 'vitest';
// cannot track import because Promise is not returned
function renderComponent() {
import('./component.js').then(({ render }) => {
render();
});
}
test('operations are resolved', async () => {
renderComponent();
await vi.dynamicImportSettled();
expect(document.querySelector('.component')).not.toBeNull();
});
TIP
Si durante una importación dinámica se inicia otra importación dinámica, este método esperará hasta que se resuelvan todas.
Este método también esperará el siguiente tick de setTimeout
después de que se resuelva la importación, por lo que todas las operaciones síncronas deberían completarse cuando se resuelva.
Simulación de funciones y objetos
Esta sección describe cómo trabajar con simulacros de métodos y reemplazar variables ambientales y globales.
vi.fn
- Tipo:
(fn?: Function) => Mock
Crea un espía en una función, aunque se puede iniciar sin una. Cada vez que se invoca una función, almacena sus argumentos de llamada, devoluciones e instancias. Además, puedes manipular su comportamiento con métodos. Si no se proporciona ninguna función, el mock devolverá undefined
cuando se invoque.
import { expect, vi } from 'vitest';
// ---cut---
const getApples = vi.fn(() => 0);
getApples();
expect(getApples).toHaveBeenCalled();
expect(getApples).toHaveReturnedWith(0);
getApples.mockReturnValueOnce(5);
const res = getApples();
expect(res).toBe(5);
expect(getApples).toHaveNthReturnedWith(2, 5);
vi.isMockFunction
- Tipo:
(fn: Function) => boolean
Comprueba que un parámetro dado sea una función simulada. Si estás usando TypeScript, también reducirá su tipo.
vi.clearAllMocks
Llamará a .mockClear()
en todos los espías. Esto borrará el historial de mocks, pero no restablecerá su implementación a la predeterminada.
vi.resetAllMocks
Llamará a .mockReset()
en todos los espías. Esto borrará el historial de mocks y restablecerá su implementación a una función vacía (devolverá undefined
).
vi.restoreAllMocks
Llamará a .mockRestore()
en todos los espías. Esto borrará el historial de mocks y restablecerá su implementación a la original.
vi.spyOn
- Tipo:
<T, K extends keyof T>(object: T, method: K, accessType?: 'get' | 'set') => MockInstance
Crea un espía en un método o getter/setter de un objeto similar a vi.fn()
. Devuelve una función simulada.
import { expect, vi } from 'vitest';
// ---cut---
let apples = 0;
const cart = {
getApples: () => 42,
};
const spy = vi.spyOn(cart, 'getApples').mockImplementation(() => apples);
apples = 1;
expect(cart.getApples()).toBe(1);
expect(spy).toHaveBeenCalled();
expect(spy).toHaveReturnedWith(1);
TIP
Puedes llamar a vi.restoreAllMocks
dentro de afterEach
(o habilitar test.restoreMocks
) para restaurar todos los métodos a sus implementaciones originales. Esto restaurará el descriptor de objeto original, por lo que no podrás cambiar la implementación del método:
const cart = {
getApples: () => 42,
};
const spy = vi.spyOn(cart, 'getApples').mockReturnValue(10);
console.log(cart.getApples()); // 10
vi.restoreAllMocks();
console.log(cart.getApples()); // 42
spy.mockReturnValue(10);
console.log(cart.getApples()); // ¡sigue siendo 42!
vi.stubEnv 0.26.0+
- Tipo:
(name: string, value: string) => Vitest
Cambia el valor de la variable de entorno en process.env
e import.meta.env
. Puedes restaurar su valor llamando a vi.unstubAllEnvs
.
import { vi } from 'vitest';
// `process.env.NODE_ENV` and `import.meta.env.NODE_ENV`
// Valor inicial: "development"
vi.stubEnv('NODE_ENV', 'production');
process.env.NODE_ENV === 'production';
import.meta.env.NODE_ENV === 'production';
// doesn't change other envs
import.meta.env.MODE === 'development';
TIP
También puedes cambiar el valor simplemente asignándolo, pero no podrás usar vi.unstubAllEnvs
para restaurar el valor anterior:
import.meta.env.MODE = 'test';
vi.unstubAllEnvs 0.26.0+
- Tipo:
() => Vitest
Restaura todos los valores de import.meta.env
y process.env
que se cambiaron con vi.stubEnv
. Cuando se llama por primera vez, Vitest recuerda el valor original y lo almacenará hasta que se vuelva a llamar a unstubAllEnvs
.
import { vi } from 'vitest';
// `process.env.NODE_ENV` and `import.meta.env.NODE_ENV`
// Valor inicial: "development"
vi.stubEnv('NODE_ENV', 'production');
process.env.NODE_ENV === 'production';
import.meta.env.NODE_ENV === 'production';
vi.stubEnv('NODE_ENV', 'staging');
process.env.NODE_ENV === 'staging';
import.meta.env.NODE_ENV === 'staging';
vi.unstubAllEnvs();
// restores to the value that were stored before the first "stubEnv" call
process.env.NODE_ENV === 'development';
import.meta.env.NODE_ENV === 'development';
vi.stubGlobal
- Tipo:
(name: string | number | symbol, value: unknown) => Vitest
Cambia el valor de la variable global. Puedes restaurar su valor original llamando a vi.unstubAllGlobals
.
import { vi } from 'vitest';
// `innerWidth` is "0" before calling stubGlobal
vi.stubGlobal('innerWidth', 100);
innerWidth === 100;
globalThis.innerWidth === 100;
// if you are using jsdom or happy-dom
window.innerWidth === 100;
TIP
También puedes cambiar el valor simplemente asignándolo a globalThis
o window
(si estás usando el entorno jsdom
o happy-dom
), pero no podrás usar vi.unstubAllGlobals
para restaurar el valor original:
globalThis.innerWidth = 100;
// if you are using jsdom or happy-dom
window.innerWidth = 100;
vi.unstubAllGlobals 0.26.0+
- Tipo:
() => Vitest
Restaura todos los valores globales en globalThis
/global
(y window
/top
/self
/parent
, si estás usando el entorno jsdom
o happy-dom
) que se cambiaron con vi.stubGlobal
. Cuando se llama por primera vez, Vitest recuerda el valor original y lo almacenará hasta que se vuelva a llamar a unstubAllGlobals
.
import { vi } from 'vitest';
const Mock = vi.fn();
// IntersectionObserver is "undefined" before calling "stubGlobal"
vi.stubGlobal('IntersectionObserver', Mock);
IntersectionObserver === Mock;
global.IntersectionObserver === Mock;
globalThis.IntersectionObserver === Mock;
// if you are using jsdom or happy-dom
window.IntersectionObserver === Mock;
vi.unstubAllGlobals();
globalThis.IntersectionObserver === undefined;
'IntersectionObserver' in globalThis === false;
// throws ReferenceError, because it's not defined
IntersectionObserver === undefined;
Temporizadores Falsos
Esta sección describe cómo trabajar con temporizadores falsos.
vi.advanceTimersByTime
- Tipo:
(ms: number) => Vitest
Este método avanza los temporizadores simulados el número especificado de milisegundos o hasta que la cola de temporizadores esté vacía, lo que ocurra primero.
import { vi } from 'vitest';
// ---cut---
let i = 0;
setInterval(() => console.log(++i), 50);
vi.advanceTimersByTime(150);
// log: 1
// log: 2
// log: 3
vi.advanceTimersByTimeAsync
- Tipo:
(ms: number) => Promise<Vitest>
Este método avanza los temporizadores simulados el número especificado de milisegundos o hasta que la cola de temporizadores esté vacía, lo que ocurra primero. Esto incluye los temporizadores establecidos de forma asíncrona.
import { vi } from 'vitest';
// ---cut---
let i = 0;
setInterval(() => Promise.resolve().then(() => console.log(++i)), 50);
await vi.advanceTimersByTimeAsync(150);
// log: 1
// log: 2
// log: 3
vi.advanceTimersToNextTimer
- Tipo:
() => Vitest
Ejecuta el siguiente temporizador disponible en la cola. Es útil para realizar aserciones entre cada ejecución del temporizador. Puedes encadenar las llamadas para controlar los temporizadores individualmente.
import { vi } from 'vitest';
// ---cut---
let i = 0;
setInterval(() => console.log(++i), 50);
vi.advanceTimersToNextTimer() // log: 1
.advanceTimersToNextTimer() // log: 2
.advanceTimersToNextTimer(); // log: 3
vi.advanceTimersToNextTimerAsync
- Tipo:
() => Promise<Vitest>
Ejecuta el siguiente temporizador disponible y espera a que se resuelva si se estableció de forma asíncrona. Es útil para realizar aserciones entre cada ejecución del temporizador.
import { expect, vi } from 'vitest';
// ---cut---
let i = 0;
setInterval(() => Promise.resolve().then(() => console.log(++i)), 50);
await vi.advanceTimersToNextTimerAsync(); // log: 1
expect(console.log).toHaveBeenCalledWith(1);
await vi.advanceTimersToNextTimerAsync(); // log: 2
await vi.advanceTimersToNextTimerAsync(); // log: 3
vi.getTimerCount
- Tipo:
() => number
Obtiene el número de temporizadores pendientes en la cola.
vi.clearAllTimers
Elimina todos los temporizadores que están programados para ejecutarse. Estos temporizadores no se ejecutarán.
vi.getMockedSystemTime
- Tipo:
() => Date | null
Devuelve la fecha simulada actual establecida con setSystemTime
. Si no se ha simulado la fecha, el método devuelve null
.
vi.getRealSystemTime
- Tipo:
() => number
Cuando se usa vi.useFakeTimers
, las llamadas a Date.now
se simulan. Si necesitas obtener la hora real en milisegundos, puedes llamar a esta función.
vi.runAllTicks
- Tipo:
() => Vitest
Ejecuta cada microtarea que se ha encolado con process.nextTick
. Esto también ejecutará todas las microtareas programadas por sí mismas.
vi.runAllTimers
- Tipo:
() => Vitest
Este método ejecuta todos los temporizadores iniciados hasta que la cola de temporizadores esté vacía. Esto significa que cada temporizador ejecutado durante runAllTimers
se activará. Si hay un intervalo infinito, se lanzará una excepción después de 10 000 intentos (se puede configurar con fakeTimers.loopLimit
).
import { vi } from 'vitest';
// ---cut---
let i = 0;
setTimeout(() => console.log(++i));
const interval = setInterval(() => {
console.log(++i);
if (i === 3) clearInterval(interval);
}, 50);
vi.runAllTimers();
// log: 1
// log: 2
// log: 3
vi.runAllTimersAsync
- Tipo:
() => Promise<Vitest>
Este método ejecuta de forma asíncrona todos los temporizadores iniciados hasta que la cola de temporizadores esté vacía. Esto significa que cada temporizador ejecutado durante runAllTimersAsync
se activará, incluso los temporizadores asíncronos. Si hay un intervalo infinito, se lanzará una excepción después de 10 000 intentos (se puede configurar con fakeTimers.loopLimit
).
import { vi } from 'vitest';
// ---cut---
setTimeout(async () => {
console.log(await Promise.resolve('result'));
}, 100);
await vi.runAllTimersAsync();
// log: result
vi.runOnlyPendingTimers
- Tipo:
() => Vitest
Este método ejecuta cada temporizador que se inició después de la llamada a vi.useFakeTimers
. No activará ningún temporizador que se haya iniciado durante su llamada.
import { vi } from 'vitest';
// ---cut---
let i = 0;
setInterval(() => console.log(++i), 50);
vi.runOnlyPendingTimers();
// log: 1
vi.runOnlyPendingTimersAsync
- Tipo:
() => Promise<Vitest>
Este método ejecuta de forma asíncrona cada temporizador que se inició después de la llamada a vi.useFakeTimers
, incluso los asíncronos. No activará ningún temporizador que se haya iniciado durante su llamada.
import { vi } from 'vitest';
// ---cut---
setTimeout(() => {
console.log(1);
}, 100);
setTimeout(() => {
Promise.resolve().then(() => {
console.log(2);
setInterval(() => {
console.log(3);
}, 40);
});
}, 10);
await vi.runOnlyPendingTimersAsync();
// log: 2
// log: 3
// log: 3
// log: 1
vi.setSystemTime
- Tipo:
(date: string | number | Date) => void
Si los temporizadores falsos están habilitados, este método simula un cambio en el reloj del sistema por parte del usuario (afectará a las API relacionadas con la fecha, como hrtime
, performance.now
o new Date()
), pero no activará ningún temporizador. Si los temporizadores falsos no están habilitados, este método solo simulará las llamadas a Date.*
.
Es útil si necesitas probar algo que dependa de la fecha actual, por ejemplo, las llamadas a Luxon dentro de tu código.
import { expect, vi } from 'vitest';
// ---cut---
const date = new Date(1998, 11, 19);
vi.useFakeTimers();
vi.setSystemTime(date);
expect(Date.now()).toBe(date.valueOf());
vi.useRealTimers();
vi.useFakeTimers
- Tipo:
(config?: FakeTimerInstallOpts) => Vitest
Para habilitar la simulación de temporizadores, debes llamar a este método. Interceptará todas las llamadas posteriores a los temporizadores (como setTimeout
, setInterval
, clearTimeout
, clearInterval
, setImmediate
, clearImmediate
y Date
) hasta que se llame a vi.useRealTimers()
.
La simulación de nextTick
no es compatible cuando se ejecuta Vitest dentro de node:child_process
utilizando --pool=forks
. NodeJS utiliza process.nextTick
internamente en node:child_process
y se bloquea cuando se simula. La simulación de nextTick
es compatible cuando se ejecuta Vitest con --pool=threads
.
La implementación se basa internamente en @sinonjs/fake-timers
.
TIP
Desde la versión 0.35.0
, vi.useFakeTimers()
ya no simula automáticamente process.nextTick
. Todavía se puede simular especificando la opción en el argumento toFake
: vi.useFakeTimers({ toFake: ['nextTick'] })
.
vi.isFakeTimers 0.34.5+
- Tipo:
() => boolean
Devuelve true
si los temporizadores falsos están habilitados.
vi.useRealTimers
- Tipo:
() => Vitest
Cuando terminas de usar los temporizadores simulados, puedes llamar a este método para restaurar los temporizadores a sus implementaciones originales. Todos los temporizadores que se programaron antes se descartarán.
Miscelánea
Un conjunto de funciones de ayuda útiles que proporciona Vitest.
vi.waitFor 0.34.5+
- Tipo:
<T>(callback: WaitForCallback<T>, options?: number | WaitForOptions) => Promise<T>
Espera a que la función de retrollamada se ejecute correctamente. Si la función de retrollamada lanza un error o devuelve una promesa rechazada, continuará esperando hasta que tenga éxito o se agote el tiempo de espera.
Esto es muy útil cuando necesitas esperar a que se complete alguna acción asíncrona, como cuando inicias un servidor y necesitas esperar a que esté listo.
import { expect, test, vi } from 'vitest';
import { createServer } from './server.js';
test('Server started successfully', async () => {
const server = createServer();
await vi.waitFor(
() => {
if (!server.isReady) throw new Error('Server not started');
console.log('Server started');
},
{
timeout: 500, // por defecto es 1000
interval: 20, // por defecto es 50
}
);
expect(server.isReady).toBe(true);
});
También funciona para funciones de retrollamada asíncronas
// @vitest-environment jsdom
import { expect, test, vi } from 'vitest';
import { getDOMElementAsync, populateDOMAsync } from './dom.js';
test('Element exists in a DOM', async () => {
// start populating DOM
populateDOMAsync();
const element = await vi.waitFor(
async () => {
// try to get the element until it exists
const element = (await getDOMElementAsync()) as HTMLElement | null;
expect(element).toBeTruthy();
expect(element.dataset.initialized).toBeTruthy();
return element;
},
{
timeout: 500, // por defecto es 1000
interval: 20, // por defecto es 50
}
);
expect(element).toBeInstanceOf(HTMLElement);
});
Si se usa vi.useFakeTimers
, vi.waitFor
invoca automáticamente a vi.advanceTimersByTime(interval)
en cada función de retrollamada de verificación.
vi.waitUntil 0.34.5+
- Tipo:
<T>(callback: WaitUntilCallback<T>, options?: number | WaitUntilOptions) => Promise<T>
Es similar a vi.waitFor
, pero si la función de retrollamada lanza algún error, la ejecución se interrumpe inmediatamente y se recibe un mensaje de error. Si la función de retrollamada devuelve un valor falso, la siguiente verificación continuará hasta que se devuelva un valor verdadero. Esto es útil cuando necesitas esperar a que algo exista antes de proceder con el siguiente paso.
Mira el siguiente ejemplo. Podemos usar vi.waitUntil
para esperar a que el elemento aparezca en la página, y luego podemos hacer algo con el elemento.
import { expect, test, vi } from 'vitest';
test('Element render correctly', async () => {
const element = await vi.waitUntil(() => document.querySelector('.element'), {
timeout: 500, // por defecto es 1000
interval: 20, // por defecto es 50
});
// do something with the element
expect(element.querySelector('.element-child')).toBeTruthy();
});
vi.hoisted 0.31.0+
- Tipo:
<T>(factory: () => T) => T
Todas las declaraciones import
estáticas en los módulos ES se elevan al principio del archivo, por lo que cualquier código definido antes de las importaciones se ejecutará en realidad después de que se evalúen las importaciones.
Sin embargo, puede ser útil invocar algunos efectos secundarios, como falsificar fechas, antes de importar un módulo.
Para evitar esta limitación, puedes reescribir las importaciones estáticas en dinámicas como esta:
callFunctionWithSideEffect()
- import { value } from './some/module.js'
+ const { value } = await import('./some/module.js')
Cuando se ejecuta vitest
, puedes hacer esto automáticamente utilizando el método vi.hoisted
.
- callFunctionWithSideEffect()
import { value } from './some/module.js'
+ vi.hoisted(() => callFunctionWithSideEffect())
Este método devuelve el valor que se devolvió de la fábrica. Puedes usar ese valor en tus fábricas vi.mock
si necesitas un acceso fácil a las variables definidas localmente:
import { expect, vi } from 'vitest';
import { originalMethod } from './path/to/module.js';
const { mockedMethod } = vi.hoisted(() => {
return { mockedMethod: vi.fn() };
});
vi.mock('./path/to/module.js', () => {
return { originalMethod: mockedMethod };
});
mockedMethod.mockReturnValue(100);
expect(originalMethod()).toBe(100);
Ten en cuenta que este método también se puede llamar de forma asíncrona, incluso si tu entorno no admite la espera de nivel superior:
const promised = await vi.hoisted(async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
return response.json();
});
vi.setConfig
- Tipo:
RuntimeConfig
Actualiza la configuración del archivo de prueba actual. Este método solo admite opciones de configuración que afecten al archivo de prueba actual:
vi.setConfig({
allowOnly: true,
testTimeout: 10_000,
hookTimeout: 10_000,
clearMocks: true,
restoreMocks: true,
fakeTimers: {
now: new Date(2021, 11, 19),
// soporta todo el objeto
},
maxConcurrency: 10,
sequence: {
hooks: 'stack',
// solo admite "sequence.hooks"
},
});
vi.resetConfig
- Tipo:
RuntimeConfig
Si se ha llamado a vi.setConfig
anteriormente, esto restablecerá la configuración a su estado original.