Vitest 3.2 już dostępny!
2 czerwca 2025
Vitest 3.2 koncentruje się na ulepszeniach trybu przeglądarki i wsparciu dla TypeScriptu. Ta wersja wprowadza również kilka nowych, przydatnych metod i opcji konfiguracyjnych, a także wycofuje konfigurację workspace
na rzecz projects
.
workspace
jest przestarzałe
W celu uproszczenia konfiguracji, zespół zdecydował się wycofać oddzielny plik vitest.workspace
i zalecić używanie wyłącznie opcji projects
w głównej konfiguracji. Upraszcza to również sposób konfigurowania opcji globalnych, eliminując potrzebę zgadywania, jak dodać raporty, gdy brakuje konfiguracji głównej.
Podjęliśmy również decyzję o wycofaniu nazwy workspace
, ponieważ koliduje ona z innymi narzędziami, takimi jak PNPM, które zapewniają wsparcie dla monorepo za pomocą tej opcji. Vitest nie uruchamia tych projektów z oddzielnym CWD
i traktuje je bardziej jako podrzędne instancje Vitest. Daje nam to również więcej przestrzeni na opracowanie lepszego rozwiązania dla monorepo bez wprowadzania zmian niezgodnych wstecz.
Ta opcja zostanie całkowicie usunięta w przyszłej głównej wersji, zastąpiona przez projects
. Do tego czasu Vitest wyświetli ostrzeżenie, jeśli funkcja workspace zostanie użyta.
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
// "test.workspace" zostało zmienione na "test.projects"
workspace: [
projects: [
{ test: { name: "Unit" } },
{ test: { name: "Integration" } },
],
},
});
API adnotacji
Nowe API adnotacji pozwala na dodawanie adnotacji do dowolnego testu z niestandardową wiadomością i załącznikiem. Te adnotacje są widoczne w interfejsie użytkownika, HTML, junit, tap i raportach GitHub Actions. Vitest wydrukuje również powiązaną adnotację w CLI, jeśli test się nie powiedzie.

Fixtury o określonym zasięgu
Fixtury test.extend
mogą teraz określać opcję scope
: file
lub worker
.
const test = baseTest.extend({
db: [
async ({}, use) => {
// ...setup
await use(db);
await db.close();
},
{ scope: 'worker' },
],
});
Fixtura plikowa jest podobna do używania beforeAll
i afterAll
na poziomie pliku, ale nie zostanie wywołana, jeśli fixtura nie jest używana w żadnym teście.
Fixtura worker
jest inicjowana raz na proces roboczy. Należy jednak pamiętać, że domyślnie Vitest tworzy jeden proces roboczy dla każdego testu, więc aby z niej skorzystać, należy wyłączyć izolację.
Niestandardowe kolory nazw projektów
Możesz teraz ustawić własny kolor podczas używania projects
:
Przykład konfiguracji
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' }],
},
},
},
],
},
})

Niestandardowe API lokalizatorów przeglądarki
Wbudowane lokalizatory mogą nie wystarczyć do wyrażenia potrzeb Twojej aplikacji. Zamiast wracać do CSS i tracić ochronę przed ponownymi próbami, którą Vitest zapewnia poprzez swoje API lokalizatorów, zalecamy teraz rozszerzanie lokalizatorów za pomocą nowego locators.extend
API.
import { locators } from '@vitest/browser/context';
locators.extend({
getByCommentsCount(count: number) {
return `.comments :text("${count} comments")`;
},
});
Zwróć ciąg znaków lokalizatora z Playwright, aby skonstruować nowy lokalizator. Zauważ, że zwrócony ciąg znaków z tej metody będzie ograniczony do lokalizatora nadrzędnego, jeśli taki istnieje.
Teraz możesz wywołać getByCommentsCount
na page
lub dowolnym innym lokalizatorze bezpośrednio:
await expect.element(page.getByCommentsCount(1)).toBeVisible();
await expect
.element(
page.getByRole('article', { name: 'Hello World' }).getByCommentsCount(1)
)
.toBeVisible();
Jeśli ta metoda zwraca ciąg znaków, zwrócona wartość zostanie przekonwertowana na lokalizator, dzięki czemu można kontynuować łączenie:
page
.getByRole('article', { name: 'Hello World' })
.getByCommentsCount(1)
.getByText('comments');
Ta metoda ma dostęp do bieżącego kontekstu lokalizatora, jeśli taki istnieje (jeśli metoda jest wywoływana na page
, kontekst będzie odnosił się do page
), więc możesz swobodnie łączyć wszystkie metody lokalizatora w jej obrębie:
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`));
},
});
Dostęp do kontekstu pozwala również wywoływać standardowe metody lokalizatora w celu zdefiniowania niestandardowego zdarzenia użytkownika:
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');
Więcej informacji można znaleźć w locators.extend
API.
Jawne zarządzanie zasobami w vi.spyOn
i vi.fn
W środowiskach, które obsługują Jawne zarządzanie zasobami, możesz użyć using
zamiast const
, aby automatycznie wywołać mockRestore
na dowolnej zamockowanej funkcji po wyjściu z zawierającego bloku. Jest to szczególnie przydatne w przypadku monitorowanych metod:
it('calls console.log', () => {
using spy = vi.spyOn(console, 'log').mockImplementation(() => {})
debug('message')
expect(spy).toHaveBeenCalled()
})
// console.log jest przywrócony tutaj
API sygnału testowego
Vitest udostępnia teraz obiekt AbortSignal
do treści testu. Możesz go użyć do zatrzymania dowolnego zasobu, który obsługuje to Web API.
Sygnał jest przerywany, gdy test przekroczy limit czasu, inny test zakończy się niepowodzeniem (jeśli flaga --bail
jest ustawiona na wartość różną od zera) lub użytkownik naciśnie Ctrl+C w terminalu.
Na przykład, możesz zatrzymać żądanie fetch
, gdy testy zostaną przerwane:
it('stop request when test times out', async ({ signal }) => {
await fetch('/heavy-resource', { signal });
}, 2000);
Remapowanie pokrycia V8 z uwzględnieniem AST
Vitest używa teraz pakietu ast-v8-to-istanbul
opracowanego przez jednego z opiekunów Vitest, AriPerkkio. Dzięki temu raport pokrycia v8 jest zgodny z istanbul, oferując jednocześnie lepszą wydajność! Włącz tę funkcję, ustawiając coverage.experimentalAstAwareRemapping
na true
.
Planujemy uczynić to domyślnym trybem remapowania w następnej głównej wersji. Stary v8-to-istanbul
zostanie całkowicie usunięty. Zapraszamy do dyskusji na https://github.com/vitest-dev/vitest/issues/7928.
Opcja watchTriggerPatterns
Kiedy edytujesz plik, Vitest jest wystarczająco inteligentny, aby ponownie uruchomić tylko testy, które importują ten plik. Niestety, statyczna analiza Vitest uwzględnia tylko statyczne i dynamiczne instrukcje import
. Jeśli odczytujesz plik lub uruchamiasz oddzielny proces, Vitest zignoruje zmiany w powiązanych plikach.
Dzięki opcji watchTriggerPatterns
możesz skonfigurować, które testy mają być ponownie uruchamiane w zależności od zmienionego pliku. Na przykład, aby zawsze ponownie uruchamiać testy mailers
, gdy szablon zostanie zmieniony, dodaj wzorzec wyzwalający:
export default defineConfig({
test: {
watchTriggerPatterns: [
{
pattern: /^src\/templates\/(.*)\.(ts|html|txt)$/,
testsToRun: (file, match) => {
return `api/tests/mailers/${match[2]}.test.ts`;
},
},
],
},
});
Nowy, uniwersalny typ Matchers
Vitest ma teraz typ Matchers
, który możesz rozszerzyć, aby dodać obsługę typów dla wszystkich swoich niestandardowych matcherów w jednym miejscu. Ten typ wpływa na wszystkie te przypadki użycia:
expect().to*
expect.to*
expect.extend({ to* })
Na przykład, aby mieć bezpieczny typowo matcher toBeFoo
, możesz napisać coś takiego:
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
Nowa opcja sequence.groupOrder
kontroluje kolejność, w jakiej projekt uruchamia swoje testy, gdy używa wielu projektów.
- Projekty z tym samym numerem kolejności grupy będą uruchamiane razem, a grupy są wykonywane od najniższej do najwyższej.
- Jeśli nie ustawisz tej opcji, wszystkie projekty będą uruchamiane równolegle.
- Jeśli kilka projektów używa tej samej kolejności grup, będą one uruchamiane w tym samym czasie.
Przykład
Rozważ ten przykład:
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,
},
},
},
],
},
});
Testy w tych projektach będą uruchamiane w następującej kolejności:
0. slow |
|> running together
0. fast |
1. flaky |> runs after slow and fast alone
Pełna lista zmian znajduje się w Dzienniku zmian Vitest 3.2.