Extender Matchers
Dado que Vitest es compatible tanto con Chai como con Jest, puedes elegir entre usar la API chai.use o expect.extend.
Esta guía se centrará en cómo extender los matchers con expect.extend. Si te interesa la API de Chai, consulta su guía.
Para extender los matchers predeterminados, llama a expect.extend con un objeto que contenga tus matchers personalizados.
expect.extend({
toBeFoo(received, expected) {
const { isNot } = this;
return {
// No modifiques el valor de "pass" basándote en isNot. Vitest lo gestiona automáticamente.
pass: received === 'foo',
message: () => `${received} is${isNot ? ' not' : ''} foo`,
};
},
});Si estás utilizando TypeScript, puedes extender la interfaz Assertion predeterminada en un archivo de declaración de entorno (por ejemplo: vitest.d.ts) con el siguiente código:
import 'vitest';
interface CustomMatchers<R = unknown> {
toBeFoo: () => R;
}
declare module 'vitest' {
interface Matchers<T = any> extends CustomMatchers<T> {}
}import 'vitest';
interface CustomMatchers<R = unknown> {
toBeFoo: () => R;
}
declare module 'vitest' {
interface Assertion<T = any> extends CustomMatchers<T> {}
interface AsymmetricMatchersContaining extends CustomMatchers {}
}TIP
A partir de Vitest 3.2, puedes extender la interfaz Matchers para obtener aserciones de tipo seguro en los métodos expect.extend, expect().* y expect.* simultáneamente. Anteriormente, era necesario definir interfaces separadas para cada uno de ellos.
WARNING
No olvides incluir el archivo de declaración de entorno en tu tsconfig.json.
El valor de retorno de un matcher debe ser compatible con la siguiente interfaz:
interface ExpectationResult {
pass: boolean;
message: () => string;
// Si proporcionas estos valores, aparecerán automáticamente en un diff cuando
// el matcher falle, eliminando la necesidad de imprimir el diff manualmente.
actual?: unknown;
expected?: unknown;
}WARNING
Si creas un matcher asíncrono, recuerda usar await con el resultado (await expect('foo').toBeFoo()) en la prueba:
expect.extend({
async toBeAsyncAssertion() {
// ...
},
});
await expect().toBeAsyncAssertion();El primer argumento dentro de la función de un matcher es el valor recibido (el que se pasa a expect(received)). Los argumentos adicionales se pasan directamente al matcher.
La función del matcher tiene acceso al contexto this con las siguientes propiedades:
isNot
Devuelve true si el matcher fue llamado con not (expect(received).not.toBeFoo()).
promise
Si el matcher fue llamado con los modificadores resolved o rejected, este valor contendrá el nombre del modificador. De lo contrario, será una cadena vacía.
equals
Esta es una función de utilidad que te permite comparar dos valores. Devolverá true si los valores son iguales, false en caso contrario. Esta función se utiliza internamente para casi todos los matchers y, por defecto, soporta objetos con matchers asimétricos.
utils
Contiene un conjunto de funciones de utilidad que puedes usar para formatear mensajes.
El contexto this también contiene información sobre la prueba actual. También puedes obtenerla llamando a expect.getState(). Las propiedades más útiles son:
currentTestName
Nombre completo de la prueba actual (incluido el bloque describe).
testPath
Ruta al archivo de la prueba actual.