Skip to content
Vitest 3
Main Navigation Guía & APIConfiguraciónModo NavegadorAPI avanzada
3.2.0
2.1.9
1.6.1
0.34.6

Español

English
简体中文
繁體中文
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Español

English
简体中文
繁體中文
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Apariencia

Sidebar Navigation

Introducción

Por qué Vitest

Primeros pasos

Características

Configuración de Vitest

API

Referencia de la API de prueba

Funciones de Simulación

Vi

expect

expectTypeOf

assert

assertType

Guía

Interfaz de línea de comandos

Filtrado de Tests

Proyectos de prueba

Reportes

Cobertura

Instantáneas

Simulación (Mocking)

Paralelismo

Pruebas de Tipado

Interfaz de usuario de Vitest

Pruebas en el código fuente

Contexto de prueba

Anotaciones de prueba

Entorno de pruebas

Extender Matchers

Integraciones con IDE

Depuración

Errores comunes

Guía de migración

Migración a Vitest 3.0

Migración desde Jest

Rendimiento

Perfilado del rendimiento de las pruebas

Mejorando el Rendimiento

Modo Navegador

API Avanzadas

Comparaciones con otros ejecutores de pruebas

En esta página

Vi ​

Vitest proporciona funciones de utilidad a través de su asistente vi. Puedes acceder a él globalmente (si la configuración global está habilitada) o importarlo directamente desde vitest:

js
import { vi } from 'vitest';

Módulos Mock ​

Esta sección describe la API que puedes utilizar al simular un módulo. Ten en cuenta que Vitest no soporta la simulación de módulos importados mediante require().

vi.mock ​

  • Tipo: (path: string, factory?: MockOptions | ((importOriginal: () => unknown) => unknown)) => void
  • Tipo: <T>(path: Promise<T>, factory?: MockOptions | ((importOriginal: () => T) => T | Promise<T>)) => void

Sustituye todos los módulos importados desde la ruta proporcionada por otro módulo. Puedes utilizar los alias de Vite configurados dentro de una ruta. La llamada a vi.mock se eleva, lo que significa que se ejecutará siempre antes de todas las importaciones, independientemente de dónde la coloques. Si necesitas referenciar variables externas a su ámbito, puedes definirlas dentro de vi.hoisted y luego referenciarlas en vi.mock.

WARNING

vi.mock solo funciona para módulos importados con la palabra clave import. No es compatible con require.

Para elevar vi.mock, Vitest analiza estáticamente tus archivos. Esto implica que vi no puede ser utilizado si no se importa directamente del paquete vitest (por ejemplo, desde un archivo de utilidad). Utiliza vi.mock con vi importado de vitest, o habilita la opción de configuración globals.

Vitest no simulará módulos importados dentro de un archivo de configuración porque ya están en caché cuando se ejecuta un archivo de prueba. Puedes llamar a vi.resetModules() dentro de vi.hoisted para limpiar la caché de todos los módulos antes de ejecutar un archivo de prueba.

Si la función factory está definida, todas las importaciones devolverán su resultado. Vitest invoca la fábrica una única vez y almacena en caché los resultados para todas las importaciones subsiguientes hasta que se llama a vi.unmock o vi.doUnmock.

A diferencia de Jest, la fábrica puede ser asíncrona. Puedes usar vi.importActual o una función auxiliar que reciba la fábrica como primer argumento para obtener el módulo original.

También puedes proporcionar un objeto con una propiedad spy en lugar de una función de fábrica. Si spy es true, Vitest simulará automáticamente el módulo de forma habitual, pero no anulará la implementación de las exportaciones. Esto es útil si solo deseas verificar que el método exportado fue invocado correctamente por otro método.

ts
import { calculator } from './src/calculator.ts';

vi.mock('./src/calculator.ts', { spy: true });

// Invoca la implementación original,
// pero permite verificar el comportamiento posteriormente
const result = calculator(1, 2);

expect(result).toBe(3);
expect(calculator).toHaveBeenCalledWith(1, 2);
expect(calculator).toHaveReturned(3);

Vitest también soporta una promesa de módulo en lugar de una cadena en los métodos vi.mock y vi.doMock para una mejor integración con IDEs. Cuando el archivo se mueve, la ruta se actualizará, y importOriginal inferirá el tipo automáticamente. El uso de esta firma también forzará que el tipo de retorno de la fábrica sea compatible con el módulo original (manteniendo las exportaciones opcionales).

ts
// @filename: ./path/to/module.js
export declare function total(...numbers: number[]): number;
// @filename: test.js
import { vi } from 'vitest';
// ---cut---
vi.mock(import('./path/to/module.js'), async importOriginal => {
  const mod = await importOriginal(); // el tipo se infiere
  //    ^?
  return {
    ...mod,
    // reemplazar algunas exportaciones
    total: vi.fn(),
  };
});

Internamente, Vitest sigue operando con una cadena y no con un objeto de módulo.

Sin embargo, si estás utilizando TypeScript con alias paths configurados en tsconfig.json, el compilador no podrá resolver correctamente los tipos de importación. Para que funcione, asegúrate de reemplazar todas las importaciones con alias por sus rutas relativas correspondientes. Por ejemplo, usa import('./path/to/module.js') en lugar de import('@/module').

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), se invocará antes.

Esto también implica que no puedes usar ninguna variable definida fuera de la fábrica dentro de la misma.

Si necesitas usar variables dentro de la fábrica, considera vi.doMock. Funciona de la misma manera pero no se eleva. Ten en cuenta que solo simula importaciones posteriores.

También puedes referenciar variables definidas por el método vi.hoisted si se declaró antes de vi.mock:

ts
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 una exportación predeterminada, deberás proporcionar una clave default dentro del objeto devuelto por la función de fábrica. Esta es una particularidad específica del módulo ES; por lo tanto, la documentación de Jest puede diferir ya que Jest utiliza módulos CommonJS. Por ejemplo:

ts
vi.mock('./path/to/module.js', () => {
  return {
    default: { myDefaultKey: vi.fn() },
    namedExport: vi.fn(),
    // etc...
  };
});

Si existe una carpeta __mocks__ junto a un archivo que estás simulando, y la fábrica no se proporciona, Vitest intentará encontrar un archivo con el mismo nombre en la subcarpeta __mocks__ y lo utilizará 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 indicar a Vitest dónde se encuentran las dependencias a través de la opción de configuración deps.moduleDirectories.

Por ejemplo, si 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 una fábrica u opciones proporcionadas, buscará un archivo en la carpeta __mocks__ para usarlo como módulo:

ts
import { vi } from 'vitest';

// axios es una exportación predeterminada de `__mocks__/axios.js`
import axios from 'axios';

// increment es una exportación con nombre de `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 una fábrica proporcionada, Vitest importará el módulo original y simulará automáticamente todas sus exportaciones. Para las reglas aplicadas, consulta el algoritmo.

vi.doMock ​

  • Tipo: (path: string, factory?: MockOptions | ((importOriginal: () => unknown) => unknown)) => void
  • Tipo: <T>(path: Promise<T>, factory?: MockOptions | ((importOriginal: () => T) => T | Promise<T>)) => void

Similar a vi.mock, pero no se eleva a la parte superior del archivo, lo que te permite referenciar variables en el ámbito global del archivo. La siguiente importación dinámica del módulo será simulada.

WARNING

Esto no simulará módulos que fueron importados antes de que se ejecutara esta llamada. No olvides que todas las importaciones estáticas en ESM siempre se elevan, por lo que colocar esto antes de una importación estática no forzará que se llame antes de la importación:

ts
vi.doMock('./increment.js'); // esto se llamará _después_ de la declaración de importación

import { increment } from './increment.js';
ts
export function increment(number) {
  return number + 1;
}
ts
import { beforeEach, test } from 'vitest';
import { increment } from './increment.js';

// el módulo no está simulado, porque vi.doMock aún no se ha llamado
increment(1) === 2;

let mockedIncrement = 100;

beforeEach(() => {
  // puedes acceder a variables dentro de una fábrica
  vi.doMock('./increment.js', () => ({ increment: () => ++mockedIncrement }));
});

test('importar el siguiente módulo importa el simulado', async () => {
  // la importación original NO FUE SIMULADA, porque vi.doMock se evalúa DESPUÉS de las importaciones
  expect(increment(1)).toBe(2);
  const { increment: mockedIncrement } = await import('./increment.js');
  // la nueva importación dinámica devuelve el módulo simulado
  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 le pasó.

Cuando partial es true, esperará un Partial<T> como valor de retorno. Por defecto, esto solo hará que TypeScript crea que los valores de primer nivel están simulados. Puedes pasar { deep: true } como segundo argumento para indicar a TypeScript que todo el objeto está simulado, si realmente lo está.

ts
export function add(x: number, y: number): number {
  return x + y;
}

export function fetchSomething(): Promise<Response> {
  return fetch('https://vitest.dev/');
}
ts
import * as example from './example';

vi.mock('./example');

test('1 + 1 es igual a 10', async () => {
  vi.mocked(example.add).mockReturnValue(10);
  expect(example.add(1, 1)).toBe(10);
});

test('valor de retorno simulado con tipado parcialmente correcto', async () => {
  vi.mocked(example.fetchSomething).mockResolvedValue(new Response('hello'));
  vi.mocked(example.fetchSomething, { partial: true }).mockResolvedValue({
    ok: false,
  });
  // vi.mocked(example.someFn).mockResolvedValue({ ok: false }) // esto es un error de tipo
});

vi.importActual ​

  • Tipo: <T>(path: string) => Promise<T>

Importa un módulo, omitiendo todas las comprobaciones de si debe ser simulado. Puede ser útil si quieres simular un módulo parcialmente.

ts
vi.mock('./example.js', async () => {
  const originalModule = await vi.importActual('./example.js');

  return { ...originalModule, 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 las reglas aplicadas, consulta el algoritmo.

vi.unmock ​

  • Tipo: (path: string | Promise<Module>) => void

Elimina el módulo del registro de simulaciones. Todas las llamadas para importar devolverán el módulo original, incluso si se simuló previamente. Esta llamada se eleva a la parte superior del archivo, por lo que solo deshará la simulación de módulos que se definieron en setupFiles, por ejemplo.

vi.doUnmock ​

  • Tipo: (path: string | Promise<Module>) => void

Similar a 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 simulado. Esto no deshará la simulación de módulos importados previamente.

ts
export function increment(number) {
  return number + 1;
}
ts
import { increment } from './increment.js';

// increment ya está simulado, porque vi.mock se eleva
increment(1) === 100;

// esto se eleva, y la fábrica se llama antes de la importación en la línea 1
vi.mock('./increment.js', () => ({ increment: () => 100 }));

// todas las llamadas están simuladas, y `increment` siempre devuelve 100
increment(1) === 100;
increment(30) === 100;

// esto no se eleva, por lo que otra importación devolverá un módulo no simulado
vi.doUnmock('./increment.js');

// esto SIGUE devolviendo 100, porque `vi.doUnmock` no reevalúa un módulo
increment(1) === 100;
increment(30) === 100;

// la siguiente importación no está simulada, ahora `increment` es la función original que devuelve 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 limpiando la caché de todos los módulos. Esto permite que los módulos se reevalúen cuando se reimportan. Las importaciones de nivel superior no se pueden reevaluar. Puede ser útil para aislar módulos cuyo estado local entra en conflicto entre pruebas.

ts
import { vi } from 'vitest';

import { data } from './data.js'; // No se reevaluará antes de cada prueba

beforeEach(() => {
  vi.resetModules();
});

test('cambiar estado', async () => {
  const mod = await import('./some/path.js'); // Se reevaluará
  mod.changeLocalState('new value');
  expect(mod.getLocalState()).toBe('new value');
});

test('el módulo tiene estado antiguo', async () => {
  const mod = await import('./some/path.js'); // Se reevaluará
  expect(mod.getLocalState()).toBe('old value');
});

WARNING

No restablece el registro de simulaciones. Para borrar el registro de simulaciones, usa vi.unmock o vi.doUnmock.

vi.dynamicImportSettled ​

Espera a que todas las importaciones se carguen. Útil si tienes una llamada síncrona que inicia la importación de un módulo y no hay otra forma de esperar a que se complete.

ts
import { expect, test } from 'vitest';

// no se puede rastrear la importación porque no se devuelve una Promesa
function renderComponent() {
  import('./component.js').then(({ render }) => {
    render();
  });
}

test('las operaciones se resuelven', async () => {
  renderComponent();
  await vi.dynamicImportSettled();
  expect(document.querySelector('.component')).not.toBeNull();
});

TIP

Si durante una importación dinámica se inicia otra, este método esperará hasta que todas se resuelvan.

Este método también esperará al siguiente ciclo de setTimeout después de que la importación se resuelva para que todas las operaciones síncronas se completen.

Simulación de funciones y objetos ​

Esta sección describe cómo trabajar con simulaciones de métodos y reemplazar variables de entorno y globales.

vi.fn ​

  • Tipo: (fn?: Function) => Mock

Crea un espía en una función, aunque puede ser instanciada sin una. Cada vez que se invoca una función, almacena sus argumentos de llamada, valores de retorno e instancias. Además, puedes manipular su comportamiento con métodos. Si no se proporciona ninguna función, la simulación devolverá undefined cuando se invoque.

ts
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.mockObject 3.2.0+ ​

  • Tipo: <T>(value: T) => MaybeMockedDeep<T>

Simula profundamente las propiedades y métodos de un objeto dado de la misma manera que vi.mock() simula las exportaciones de módulos. Consulta automocking para más detalles.

ts
const original = {
  simple: () => 'value',
  nested: {
    method: () => 'real',
  },
  prop: 'foo',
};

const mocked = vi.mockObject(original);
expect(mocked.simple()).toBe(undefined);
expect(mocked.nested.method()).toBe(undefined);
expect(mocked.prop).toBe('foo');

mocked.simple.mockReturnValue('mocked');
mocked.nested.method.mockReturnValue('mocked nested');

expect(mocked.simple()).toBe('mocked');
expect(mocked.nested.method()).toBe('mocked nested');

vi.isMockFunction ​

  • Tipo: (fn: Function) => boolean

Comprueba si un parámetro dado es una función simulada. Si estás usando TypeScript, también restringirá su tipo.

vi.clearAllMocks ​

Llama a .mockClear() en todos los espías. Esto borrará el historial de simulaciones sin afectar las implementaciones de las simulaciones.

vi.resetAllMocks ​

Llama a .mockReset() en todos los espías. Esto borrará el historial de simulaciones y restablecerá la implementación de cada simulación a su original.

vi.restoreAllMocks ​

Llama a .mockRestore() en todos los espías. Esto borrará el historial de simulaciones, restaurará todas las implementaciones originales de las simulaciones y restaurará los descriptores originales de los objetos espiados.

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.

ts
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

En entornos que admiten Gestión explícita de recursos, puedes usar using en lugar de const para llamar automáticamente a mockRestore en cualquier función simulada cuando se sale del bloque que la contiene. Esto es especialmente útil para métodos espiados:

ts
it('llama a console.log', () => {
  using spy = vi.spyOn(console, 'log').mockImplementation(() => {})
  debug('mensaje')
  expect(spy).toHaveBeenCalled()
})
// console.log se restaura aquí

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:

ts
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!

TIP

No es posible espiar métodos exportados en el modo navegador. En su lugar, puedes espiar cada método exportado llamando a vi.mock("./file-path.js", { spy: true }). Esto simulará cada exportación pero mantendrá su implementación intacta, permitiéndote verificar si el método fue llamado correctamente.

ts
import { calculator } from './src/calculator.ts';

vi.mock('./src/calculator.ts', { spy: true });

calculator(1, 2);

expect(calculator).toHaveBeenCalledWith(1, 2);
expect(calculator).toHaveReturned(3);

Y aunque es posible espiar exportaciones en jsdom u otros entornos Node.js, esto podría cambiar en el futuro.

vi.stubEnv ​

  • Tipo: <T extends string>(name: T, value: T extends "PROD" | "DEV" | "SSR" ? boolean : string | undefined) => Vitest

Cambia el valor de la variable de entorno en process.env e import.meta.env. Puedes restaurar su valor llamando a vi.unstubAllEnvs.

ts
import { vi } from 'vitest';

// `process.env.NODE_ENV` e `import.meta.env.NODE_ENV`
// son "development" antes de llamar a "vi.stubEnv"

vi.stubEnv('NODE_ENV', 'production');

process.env.NODE_ENV === 'production';
import.meta.env.NODE_ENV === 'production';

vi.stubEnv('NODE_ENV', undefined);

process.env.NODE_ENV === undefined;
import.meta.env.NODE_ENV === undefined;

// no cambia otros entornos
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:

ts
import.meta.env.MODE = 'test';

vi.unstubAllEnvs ​

  • Tipo: () => Vitest

Restaura todos los valores de import.meta.env y process.env que fueron cambiados con vi.stubEnv. Cuando se llama por primera vez, Vitest recuerda el valor original y lo conservará hasta que se vuelva a llamar a unstubAllEnvs.

ts
import { vi } from 'vitest';

// `process.env.NODE_ENV` e `import.meta.env.NODE_ENV`
// son "development" antes de llamar a stubEnv

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();

// restaura al valor que se almacenó antes de la primera llamada a "stubEnv"
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 una variable global. Puedes restaurar su valor original llamando a vi.unstubAllGlobals.

ts
import { vi } from 'vitest';

// `innerWidth` es "0" antes de llamar a stubGlobal

vi.stubGlobal('innerWidth', 100);

innerWidth === 100;
globalThis.innerWidth === 100;
// si estás usando jsdom o 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:

ts
globalThis.innerWidth = 100;
// si estás usando jsdom o happy-dom
window.innerWidth = 100;

vi.unstubAllGlobals ​

  • 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 fueron cambiados con vi.stubGlobal. Cuando se llama por primera vez, Vitest recuerda el valor original y lo conservará hasta que se vuelva a llamar a unstubAllGlobals.

ts
import { vi } from 'vitest';

const Mock = vi.fn();

// IntersectionObserver es "undefined" antes de llamar a "stubGlobal"

vi.stubGlobal('IntersectionObserver', Mock);

IntersectionObserver === Mock;
global.IntersectionObserver === Mock;
globalThis.IntersectionObserver === Mock;
// si estás usando jsdom o happy-dom
window.IntersectionObserver === Mock;

vi.unstubAllGlobals();

globalThis.IntersectionObserver === undefined;
'IntersectionObserver' in globalThis === false;
// lanza ReferenceError, porque no está definido
IntersectionObserver === undefined;

Temporizadores Falsos ​

Esta sección describe cómo trabajar con temporizadores simulados.

vi.advanceTimersByTime ​

  • Tipo: (ms: number) => Vitest

Este método invocará cada temporizador iniciado hasta que el número de milisegundos especificado haya pasado o la cola esté vacía, lo que ocurra primero.

ts
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 invocará cada temporizador iniciado hasta que el número de milisegundos especificado haya pasado o la cola esté vacía, lo que ocurra primero. Esto incluirá temporizadores configurados asincrónicamente.

ts
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

Ejecutará el siguiente temporizador disponible. Útil para realizar aserciones entre cada llamada al temporizador. Puedes encadenar sus llamadas para gestionar los temporizadores por ti mismo.

ts
let i = 0;
setInterval(() => console.log(++i), 50);

vi.advanceTimersToNextTimer() // log: 1
  .advanceTimersToNextTimer() // log: 2
  .advanceTimersToNextTimer(); // log: 3

vi.advanceTimersToNextTimerAsync ​

  • Tipo: () => Promise<Vitest>

Ejecutará el siguiente temporizador disponible y esperará hasta que se resuelva si se configuró de forma asíncrona. Útil para realizar aserciones entre cada llamada al temporizador.

ts
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.advanceTimersToNextFrame 2.1.0+ ​

  • Tipo: () => Vitest

Similar a vi.advanceTimersByTime, pero avanzará los temporizadores por los milisegundos necesarios para ejecutar los callbacks actualmente programados con requestAnimationFrame.

ts
let frameRendered = false;

requestAnimationFrame(() => {
  frameRendered = true;
});

vi.advanceTimersToNextFrame();

expect(frameRendered).toBe(true);

vi.getTimerCount ​

  • Tipo: () => number

Obtiene el número de temporizadores en espera.

vi.clearAllTimers ​

Elimina todos los temporizadores programados para ejecutarse. Estos temporizadores nunca se ejecutarán en el futuro.

vi.getMockedSystemTime ​

  • Tipo: () => Date | null

Devuelve la fecha actual simulada. Si la fecha no está simulada, el método devolverá 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

Llama a cada microtarea que fue puesta en cola por process.nextTick. Esto también ejecutará todas las microtareas que se programaron a sí mismas.

vi.runAllTimers ​

  • Tipo: () => Vitest

Este método ejecutará cada temporizador iniciado hasta que la cola de temporizadores esté vacía. Esto significa que todos los temporizadores llamados durante runAllTimers se ejecutarán. Si tienes un intervalo infinito, lanzará un error después de 10.000 intentos (se puede configurar con fakeTimers.loopLimit).

ts
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 invocará de forma asíncrona cada temporizador iniciado hasta que la cola de temporizadores esté vacía. Esto significa que cada temporizador llamado durante runAllTimersAsync se ejecutará, incluso los temporizadores asíncronos. Si tienes un intervalo infinito, lanzará un error después de 10.000 intentos (se puede configurar con fakeTimers.loopLimit).

ts
setTimeout(async () => {
  console.log(await Promise.resolve('result'));
}, 100);

await vi.runAllTimersAsync();

// log: result

vi.runOnlyPendingTimers ​

  • Tipo: () => Vitest

Este método ejecutará cada temporizador que se inició después de la llamada a vi.useFakeTimers. No ejecutará ningún temporizador que se haya iniciado durante su llamada.

ts
let i = 0;
setInterval(() => console.log(++i), 50);

vi.runOnlyPendingTimers();

// log: 1

vi.runOnlyPendingTimersAsync ​

  • Tipo: () => Promise<Vitest>

Este método ejecutará de forma asíncrona cada temporizador que se inició después de la llamada a vi.useFakeTimers, incluidos los asíncronos. No ejecutará ningún temporizador que se haya iniciado durante su llamada.

ts
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 simulados están habilitados, este método simula que un usuario cambia el reloj del sistema (afectará la API relacionada con la fecha como hrtime, performance.now o new Date()); sin embargo, no ejecutará ningún temporizador. Si los temporizadores simulados no están habilitados, este método solo simulará las llamadas a Date.*.

Útil si necesitas probar algo que dependa de la fecha actual, por ejemplo, llamadas a Luxon dentro de tu código.

Acepta los mismos argumentos de cadena y número que Date.

ts
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 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 usando --pool=forks. NodeJS usa 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

vi.useFakeTimers() no simula automáticamente process.nextTick y queueMicrotask. Pero puedes habilitarlo especificando la opción en el argumento toFake: vi.useFakeTimers({ toFake: ['nextTick', 'queueMicrotask'] }).

vi.isFakeTimers ​

  • Tipo: () => boolean

Devuelve true si los temporizadores simulados están habilitados.

vi.useRealTimers ​

  • Tipo: () => Vitest

Cuando los temporizadores se han agotado, puedes llamar a este método para restaurar los temporizadores simulados a sus implementaciones originales. Todos los temporizadores que se programaron antes se descartarán.

Miscelánea ​

Un conjunto de funciones de ayuda útiles que Vitest proporciona.

vi.waitFor ​

  • Tipo: <T>(callback: WaitForCallback<T>, options?: number | WaitForOptions) => Promise<T>

Espera a que el callback se ejecute correctamente. Si el callback lanza un error o devuelve una promesa rechazada, seguirá esperando hasta que tenga éxito o se agote el tiempo de espera.

Si las opciones se establecen en un número, el efecto es equivalente a establecer { timeout: options }.

Esto es muy útil cuando necesitas esperar a que se complete alguna acción asíncrona, por ejemplo, cuando inicias un servidor y necesitas esperar a que se inicie.

ts
import { expect, test, vi } from 'vitest';
import { createServer } from './server.js';

test('Servidor iniciado correctamente', async () => {
  const server = createServer();

  await vi.waitFor(
    () => {
      if (!server.isReady) {
        throw new Error('Servidor no iniciado');
      }

      console.log('Servidor iniciado');
    },
    {
      timeout: 500, // el valor predeterminado es 1000
      interval: 20, // el valor predeterminado es 50
    }
  );
  expect(server.isReady).toBe(true);
});

También funciona para callbacks asíncronos

ts
// @vitest-environment jsdom

import { expect, test, vi } from 'vitest';
import { getDOMElementAsync, populateDOMAsync } from './dom.js';

test('El elemento existe en un DOM', async () => {
  // empezar a poblar el DOM
  populateDOMAsync();

  const element = await vi.waitFor(
    async () => {
      // intentar obtener el elemento hasta que exista
      const element = (await getDOMElementAsync()) as HTMLElement | null;
      expect(element).toBeTruthy();
      expect(element.dataset.initialized).toBeTruthy();
      return element;
    },
    {
      timeout: 500, // el valor predeterminado es 1000
      interval: 20, // el valor predeterminado es 50
    }
  );
  expect(element).toBeInstanceOf(HTMLElement);
});

Si se usa vi.useFakeTimers, vi.waitFor llama automáticamente a vi.advanceTimersByTime(interval) en cada callback de verificación.

vi.waitUntil ​

  • Tipo: <T>(callback: WaitUntilCallback<T>, options?: number | WaitUntilOptions) => Promise<T>

Esto es similar a vi.waitFor, pero si el callback lanza algún error, la ejecución se interrumpe inmediatamente y se recibe un mensaje de error. Si el callback devuelve un valor falsy, la siguiente verificación continuará hasta que se devuelva un valor truthy. Esto es útil cuando necesitas esperar a que algo exista antes de dar el siguiente paso.

Mira el ejemplo a continuación. Podemos usar vi.waitUntil para esperar a que el elemento aparezca en la página, y luego podemos hacer algo con el elemento.

ts
import { expect, test, vi } from 'vitest';

test('El elemento se renderiza correctamente', async () => {
  const element = await vi.waitUntil(() => document.querySelector('.element'), {
    timeout: 500, // el valor predeterminado es 1000
    interval: 20, // el valor predeterminado es 50
  });

  // hacer algo con el elemento
  expect(element.querySelector('.element-child')).toBeTruthy();
});

vi.hoisted ​

  • Tipo: <T>(factory: () => T) => T

Todas las declaraciones import estáticas en los módulos ES se elevan a la parte superior del archivo, por lo que cualquier código que se defina antes de las importaciones se ejecutará realmente después de que se evalúen las importaciones.

Sin embargo, puede ser útil invocar algunos efectos secundarios como la simulación de fechas antes de importar un módulo.

Para evitar esta limitación, puedes reescribir las importaciones estáticas en dinámicas de esta manera:

diff
callFunctionWithSideEffect()
- import { value } from './some/module.js'
+ const { value } = await import('./some/module.js')

Al ejecutar Vitest, puedes hacer esto automáticamente usando el método vi.hoisted. Internamente, Vitest convertirá las importaciones estáticas en dinámicas, preservando los live-bindings.

diff
- callFunctionWithSideEffect()
import { value } from './some/module.js'
+ vi.hoisted(() => callFunctionWithSideEffect())

LAS IMPORTACIONES NO ESTÁN DISPONIBLES

Ejecutar código antes de las importaciones significa que no puedes acceder a las variables importadas porque aún no están definidas:

ts
import { value } from './some/module.js';

vi.hoisted(() => { value }); // lanza un error

Este código producirá un error:

No se puede acceder a '__vi_import_0__' antes de la inicialización

Si necesitas acceder a una variable de otro módulo dentro de vi.hoisted, usa la importación dinámica:

ts
await vi.hoisted(async () => {
  const { value } = await import('./some/module.js');
});

Sin embargo, no se recomienda importar nada dentro de vi.hoisted porque las importaciones ya están elevadas; si necesitas ejecutar algo antes de que se ejecuten las pruebas, simplemente ejecútalo en el propio módulo importado.

Este método devuelve el valor que fue devuelto por la fábrica. Puedes usar ese valor en tus fábricas vi.mock si necesitas un acceso fácil a variables definidas localmente:

ts
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 puede llamarse de forma asíncrona incluso si tu entorno no admite top-level await:

ts
const json = await vi.hoisted(async () => {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts');
  return response.json();
});

vi.setConfig ​

  • Tipo: RuntimeConfig

Actualiza la configuración para el archivo de prueba actual. Este método solo admite opciones de configuración que afectarán al archivo de prueba actual:

ts
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',
    // soporta solo "sequence.hooks"
  },
});

vi.resetConfig ​

  • Tipo: RuntimeConfig

Si vi.setConfig fue llamado previamente, esto restablecerá la configuración a su estado original.

Pager
AnteriorFunciones de Simulación
Siguienteexpect

Publicado bajo la licencia MIT.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/api/vi

Publicado bajo la licencia MIT.

Copyright (c) 2021-Present Vitest Team