Vitest 3.2 è stato rilasciato!
2 giugno 2025
Vitest 3.2 introduce miglioramenti alla modalità browser e al supporto TypeScript. Questa versione include anche alcuni nuovi metodi utili, opzioni di configurazione e introduce la deprecazione della configurazione workspace
in favore di projects
.
workspace
è deprecato
Nel tentativo di semplificare la configurazione, il team ha deciso di deprecare il file vitest.workspace
separato e di raccomandare l'uso dell'opzione projects
nella configurazione root. Questo semplifica anche la configurazione delle opzioni globali (eliminando la necessità di capire come aggiungere i reporter in assenza di una configurazione root).
Abbiamo anche deciso di deprecare il nome workspace
perché entra in conflitto con altri strumenti come PNPM che offrono supporto monorepo tramite questa opzione. Vitest non esegue questi progetti con CWD
separati, trattandoli piuttosto come sotto-istanze di Vitest. Ci offre anche maggiore flessibilità per sviluppare una soluzione migliore per i monorepo senza causare interruzioni ad altri strumenti.
Questa opzione verrà rimossa completamente in una futura versione major, sostituita da projects
. Fino ad allora, Vitest stamperà un avviso se la funzionalità workspace
è in uso.
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
// "test.workspace" è stato rinominato in "test.projects"
workspace: [
projects: [
{ test: { name: "Unit" } },
{ test: { name: "Integration" } },
],
},
});
API di annotazione
La nuova API di annotazione permette di annotare qualsiasi test con un messaggio e un allegato personalizzati. Queste annotazioni sono visibili nei reporter UI, HTML, junit, tap e GitHub Actions. Vitest visualizzerà anche l'annotazione correlata nella CLI in caso di fallimento del test.

Fixture con scope
Le fixture test.extend
possono ora specificare l'opzione scope
: file
o worker
.
const test = baseTest.extend({
db: [
async ({}, use) => {
// ...setup
await use(db);
await db.close();
},
{ scope: 'worker' },
],
});
La fixture file
è simile all'uso di beforeAll
e afterAll
a livello di file, ma non verrà chiamata se la fixture non è utilizzata in alcun test.
La fixture worker
viene avviata una volta per worker; tuttavia, si tenga presente che per impostazione predefinita Vitest crea un worker per ogni test, quindi è necessario disabilitare l'isolamento per trarne beneficio.
Colori personalizzati per il nome del progetto
Ora è possibile impostare un colore personalizzato quando si utilizzano i projects
:
Esempio di configurazione
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 di localizzatori browser personalizzati
I localizzatori integrati potrebbero non essere sufficienti a soddisfare le esigenze della tua applicazione. Invece di ricorrere a CSS e perdere la capacità di riprovare le operazioni che Vitest fornisce tramite la sua API di localizzatori, ora raccomandiamo di estendere i localizzatori utilizzando la nuova locators.extend
API.
import { locators } from '@vitest/browser/context';
locators.extend({
getByCommentsCount(count: number) {
return `.comments :text("${count} comments")`;
},
});
Restituisce una stringa di localizzatore di Playwright per creare un nuovo localizzatore. Si noti che la stringa restituita da questo metodo sarà limitata al contesto del localizzatore padre, se presente.
Ora puoi chiamare getByCommentsCount
sulla page
o su qualsiasi altro localizzatore direttamente:
await expect.element(page.getByCommentsCount(1)).toBeVisible();
await expect
.element(
page.getByRole('article', { name: 'Hello World' }).getByCommentsCount(1)
)
.toBeVisible();
Se questo metodo restituisce una stringa, il valore restituito verrà convertito in un localizzatore, consentendo di continuare a concatenare le chiamate:
page
.getByRole('article', { name: 'Hello World' })
.getByCommentsCount(1)
.getByText('comments');
Questo metodo ha accesso al contesto del localizzatore corrente, se presente (se il metodo viene chiamato sulla page
, il contesto si riferirà alla page
), consentendo di concatenare tutti i metodi del localizzatore al suo interno:
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`));
},
});
Avere accesso al contesto consente anche di chiamare i metodi standard del localizzatore per definire un evento utente personalizzato:
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');
Per maggiori informazioni, si prega di fare riferimento all'locators.extend
API.
Gestione esplicita delle risorse in vi.spyOn
e vi.fn
Negli ambienti che supportano la Gestione esplicita delle risorse, è possibile utilizzare using
invece di const
per chiamare automaticamente mockRestore
su qualsiasi funzione mockata all'uscita dal blocco contenitore. Questo è particolarmente utile per i metodi spiati:
it('calls console.log', () => {
using spy = vi.spyOn(console, 'log').mockImplementation(() => {})
debug('message')
expect(spy).toHaveBeenCalled()
})
// console.log è ripristinato qui
API signal
di test
Vitest ora fornisce un oggetto AbortSignal
al corpo del test. È possibile utilizzarlo per interrompere qualsiasi risorsa che supporta questa API Web.
Il segnale viene abortito quando il test scade, un altro test fallisce e il flag --bail
è impostato su un valore diverso da zero, oppure l'utente preme Ctrl+C nel terminale.
Ad esempio, è possibile interrompere una richiesta fetch
quando i test vengono interrotti:
it('stop request when test times out', async ({ signal }) => {
await fetch('/heavy-resource', { signal });
}, 2000);
Rimappatura della copertura V8 basata sull'AST
Vitest ora utilizza il pacchetto ast-v8-to-istanbul
sviluppato da uno dei manutentori di Vitest, AriPerkkio. Questo allinea il report di copertura v8 con Istanbul, offrendo al contempo prestazioni migliori. È possibile abilitare questa funzionalità impostando coverage.experimentalAstAwareRemapping
su true
.
Stiamo pianificando di rendere questa la modalità di rimappatura predefinita nella prossima major. Il vecchio v8-to-istanbul
verrà rimosso completamente. Siete invitati a partecipare alla discussione su https://github.com/vitest-dev/vitest/issues/7928.
Opzione watchTriggerPatterns
Quando si modifica un file, Vitest è in grado di rieseguire solo i test che importano tale file. Sfortunatamente, l'analisi statica di Vitest considera solo le istruzioni import
statiche e dinamiche. Se si sta leggendo un file o avviando un processo separato, Vitest ignorerà le modifiche ai file correlati.
Con l'opzione watchTriggerPatterns
è possibile configurare quali test rieseguire a seconda del file modificato. Ad esempio, per rieseguire sempre i test dei mailers
quando un template viene modificato, è possibile aggiungere un pattern di trigger:
export default defineConfig({
test: {
watchTriggerPatterns: [
{
pattern: /^src\/templates\/(.*)\.(ts|html|txt)$/,
testsToRun: (file, match) => {
return `api/tests/mailers/${match[2]}.test.ts`;
},
},
],
},
});
Il nuovo tipo Matchers
multiuso
Vitest ora include un tipo Matchers
che può essere esteso per aggiungere il supporto dei tipi per tutti i matcher personalizzati in un unico posto. Questo tipo si applica a tutti i seguenti casi d'uso:
expect().to*
expect.to*
expect.extend({ to* })
Ad esempio, per avere un matcher toBeFoo
type-safe, puoi scrivere qualcosa del genere:
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) {
// ^?
// ... implementazione
return {
pass: true,
message: () => '',
};
},
});
expect('foo').toBeFoo('foo');
expect.toBeFoo('foo');
sequence.groupOrder
La nuova opzione sequence.groupOrder
controlla l'ordine in cui il progetto esegue i suoi test quando si utilizzano più progetti.
- I progetti con lo stesso numero di ordine di gruppo verranno eseguiti insieme, con i gruppi eseguiti dal più basso al più alto.
- Se questa opzione non viene impostata, tutti i progetti verranno eseguiti in parallelo.
- Se più progetti utilizzano lo stesso ordine di gruppo, verranno eseguiti in parallelo.
Esempio
Considera questo esempio:
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,
},
},
},
],
},
});
I test in questi progetti verranno eseguiti in questo ordine:
0. slow |
|> esecuzione congiunta
0. fast |
1. flaky |> viene eseguito dopo slow e fast (singolarmente)
L'elenco completo delle modifiche è consultabile nel Changelog di Vitest 3.2.