¡Vitest 3.2 ya está disponible!
2 de junio de 2025
Vitest 3.2 se centra en mejoras para el modo navegador y el soporte de TypeScript. Esta versión también incluye nuevos métodos útiles, opciones de configuración y depreca la configuración workspace
en favor de projects
.
workspace
está obsoleto
En un esfuerzo por simplificar la configuración, el equipo decidió descontinuar el archivo vitest.workspace
separado y recomendar el uso exclusivo de la opción projects
en la configuración raíz. Esto también simplifica la configuración de opciones globales, ya que elimina la necesidad de adivinar cómo añadir reporters cuando no se tiene una configuración raíz.
También decidimos descontinuar el nombre workspace
porque entra en conflicto con otras herramientas, como PNPM, que proporcionan soporte de monorepo a través de esta opción. Vitest no ejecuta estos proyectos con directorios de trabajo (CWD
) separados, sino que los trata más como subproyectos de Vitest. Esto también nos da más margen para desarrollar una mejor solución para los monorepos sin afectar a otras herramientas.
Esta opción se eliminará por completo en una futura versión principal, siendo reemplazada por projects
. Hasta entonces, Vitest mostrará una advertencia si se utiliza la característica workspace
.
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
// "test.workspace" ahora se denomina "test.projects"
workspace: [
projects: [
{ test: { name: "Unit" } },
{ test: { name: "Integration" } },
],
},
});
API de Anotación
La nueva API de anotación permite añadir una anotación a cualquier prueba con un mensaje y un archivo adjunto personalizados. Estas anotaciones son visibles en la interfaz de usuario, HTML, y en los reportes de JUnit, TAP y GitHub Actions. Vitest también imprimirá la anotación correspondiente en la CLI si la prueba falla.

Fixtures con Ámbito
Las fixtures de test.extend
ahora pueden especificar la opción scope
: file
o worker
.
const test = baseTest.extend({
db: [
async ({}, use) => {
// ...inicialización
await use(db);
await db.close();
},
{ scope: 'worker' },
],
});
La fixture de file
es similar a usar beforeAll
y afterAll
en el nivel superior del archivo, pero no se invocará si no se utiliza en ninguna prueba.
La fixture worker
se inicia una vez por worker, pero tenga en cuenta que, por defecto, Vitest crea un worker para cada prueba, por lo que debe deshabilitar la opción de aislamiento para aprovecharla.
Colores de Nombre de Proyecto Personalizados
Ahora puede establecer un color personalizado al usar la opción projects
:
Ejemplo de Configuración
export default defineConfig({
test: {
projects: [
{
test: {
name: {
label: 'unit',
color: 'red',
},
},
},
{
test: {
name: {
label: 'browser',
color: 'green',
},
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
},
],
},
})

API de Localizadores de Navegador Personalizados
Los localizadores integrados pueden no ser suficientes para cubrir las necesidades de su aplicación. En lugar de recurrir a CSS y perder la protección de reintentos que Vitest proporciona a través de su API de localizadores, ahora recomendamos extender los localizadores utilizando la nueva API locators.extend
.
import { locators } from '@vitest/browser/context';
locators.extend({
getByCommentsCount(count: number) {
return `.comments :text("${count} comments")`;
},
});
Este método retorna una cadena que representa un localizador de Playwright para construir un nuevo localizador. Tenga en cuenta que la cadena devuelta por este método tendrá el ámbito del localizador padre, si existe.
Ahora puede llamar a getByCommentsCount
en la page
o en cualquier otro localizador directamente:
await expect.element(page.getByCommentsCount(1)).toBeVisible();
await expect
.element(
page.getByRole('article', { name: 'Hello World' }).getByCommentsCount(1)
)
.toBeVisible();
Si este método devuelve una cadena, el valor de retorno se transformará en un localizador, lo que permite encadenar llamadas:
page
.getByRole('article', { name: 'Hello World' })
.getByCommentsCount(1)
.getByText('comments');
Este método tiene acceso al contexto del localizador actual, si existe (si el método se llama en la page
, el contexto se referirá a page
), lo que le permite encadenar todos los métodos del localizador en su interior:
import { locators } from '@vitest/browser/context';
import type { Locator } from '@vitest/browser/context';
locators.extend({
getByCommentsCount(this: Locator, count: number) {
return this.getByRole('comment').and(this.getByText(`${count} comments`));
},
});
Tener acceso al contexto también le permite llamar a métodos regulares del localizador para definir un evento de usuario personalizado:
import { locators, page } from '@vitest/browser/context';
import type { Locator } from '@vitest/browser/context';
locators.extend({
clickAndFill(this: Locator, text: string) {
await this.click();
await this.fill(text);
},
});
await page.getByRole('textbox').clickAndFill('Hello World');
Consulte la API locators.extend
para obtener más información.
Gestión Explícita de Recursos en vi.spyOn
y vi.fn
En entornos que admiten la Gestión Explícita de Recursos, puede usar using
en lugar de const
para llamar automáticamente a mockRestore
en cualquier función simulada al salir del ámbito. Esto es especialmente útil para los métodos espiados:
it('calls console.log', () => {
using spy = vi.spyOn(console, 'log').mockImplementation(() => {})
debug('message')
expect(spy).toHaveBeenCalled()
})
// console.log se restaura aquí
API de signal
de Prueba
Vitest ahora proporciona un objeto AbortSignal
al cuerpo de la prueba. Puede usarlo para detener cualquier recurso que admita esta API web.
La señal se cancela cuando la prueba excede el tiempo límite, otra prueba falla y la bandera --bail
se establece en un valor distinto de cero, o el usuario presiona Ctrl+C en la terminal.
Por ejemplo, puede detener una solicitud fetch
cuando se interrumpen las pruebas:
it('stop request when test times out', async ({ signal }) => {
await fetch('/heavy-resource', { signal });
}, 2000);
Remapeo de Cobertura V8 con Conciencia AST
Vitest ahora utiliza el paquete ast-v8-to-istanbul
desarrollado por uno de los mantenedores de Vitest, AriPerkkio. ¡Esto sincroniza el informe de cobertura de V8 con el de Istanbul, pero con un mejor rendimiento! Habilite esta característica configurando coverage.experimentalAstAwareRemapping
en true
.
Estamos planeando hacer de este el modo de remapeo predeterminado en la próxima versión principal. La antigua herramienta v8-to-istanbul
se eliminará por completo. Siéntase libre de unirse a la discusión en https://github.com/vitest-dev/vitest/issues/7928.
Opción watchTriggerPatterns
Cuando edita un archivo, Vitest es lo suficientemente inteligente como para volver a ejecutar solo las pruebas que importan este archivo. Desafortunadamente, el análisis estático de Vitest solo considera las sentencias import
estáticas y dinámicas. Si está leyendo un archivo o iniciando un proceso separado, Vitest ignorará los cambios en los archivos relacionados.
Con la opción watchTriggerPatterns
puede configurar qué pruebas se deben volver a ejecutar según el archivo que se modificó. Por ejemplo, para volver a ejecutar siempre las pruebas de mailers
cuando se cambia una plantilla, agregue un patrón de activación:
export default defineConfig({
test: {
watchTriggerPatterns: [
{
pattern: /^src\/templates\/(.*)\.(ts|html|txt)$/,
testsToRun: (file, match) => {
return `api/tests/mailers/${match[2]}.test.ts`;
},
},
],
},
});
El Nuevo Tipo Matchers
de Propósito Múltiple
Vitest ahora tiene un tipo Matchers
que puede extender para agregar soporte de tipos para todos sus matchers personalizados en un solo lugar. Este tipo se aplica a todos estos casos de uso:
expect().to*
expect.to*
expect.extend({ to* })
Por ejemplo, para tener un matcher toBeFoo
con seguridad de tipos, puede escribir algo como esto:
import { expect } from 'vitest';
interface CustomMatchers<R = unknown> {
toBeFoo: (arg: string) => R;
}
declare module 'vitest' {
interface Matchers<T = any> extends CustomMatchers<T> {}
}
expect.extend({
toBeFoo(actual, arg) {
// ^?
// ... implementation
return {
pass: true,
message: () => '',
};
},
});
expect('foo').toBeFoo('foo');
expect.toBeFoo('foo');
sequence.groupOrder
La nueva opción sequence.groupOrder
controla el orden en que el proyecto ejecuta sus pruebas cuando se utilizan múltiples proyectos.
- Los proyectos con el mismo número de orden de grupo se ejecutarán juntos, y los grupos se ejecutan de menor a mayor.
- Si no establece esta opción, todos los proyectos se ejecutan en paralelo.
- Si varios proyectos usan el mismo orden de grupo, se ejecutarán al mismo tiempo.
Ejemplo
Considere este ejemplo:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
projects: [
{
test: {
name: 'slow',
sequence: {
groupOrder: 0,
},
},
},
{
test: {
name: 'fast',
sequence: {
groupOrder: 0,
},
},
},
{
test: {
name: 'flaky',
sequence: {
groupOrder: 1,
},
},
},
],
},
});
Las pruebas en estos proyectos se ejecutarán en este orden:
0. slow |
|> ejecutándose en paralelo
0. fast |
1. flaky |> se ejecuta después de slow y fast
La lista completa de cambios se encuentra en el Changelog de Vitest 3.2.