Vitest 3.2 выпущен!
2 июня 2025 г.
Vitest 3.2 сосредоточен на улучшениях режима браузера и поддержке TypeScript. Этот выпуск также включает несколько новых полезных методов, опций конфигурации и помечает конфигурацию workspace
как устаревшую в пользу projects
.
workspace
устарел
В целях упрощения конфигурации команда решила отказаться от отдельного файла vitest.workspace
и рекомендовать использовать только опцию projects
в корневой конфигурации. Это также упрощает настройку глобальных опций (поскольку вам не нужно догадываться, как добавить репортеры при отсутствии корневой конфигурации).
Мы также решили отказаться от имени workspace
, потому что оно конфликтует с другими инструментами, такими как PNPM, которые обеспечивают поддержку монорепозиториев через эту опцию. Vitest не запускает эти проекты с отдельным CWD
и рассматривает их скорее как вложенные Vitest-проекты. Это также дает нам больше возможностей для разработки лучшего решения для монорепозиториев, не нарушая совместимость с другими инструментами.
Эта опция будет полностью удалена в будущем мажорном выпуске и заменена на projects
. До тех пор Vitest будет выводить предупреждение, если используется функциональность workspace
.
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
// "test.workspace" теперь "test.projects"
workspace: [
projects: [
{ test: { name: "Unit" } },
{ test: { name: "Integration" } },
],
},
});
Annotation API
Новый Annotation API позволяет аннотировать любой тест пользовательским сообщением и вложением. Эти аннотации видны в UI, HTML, junit, tap и репортерах для GitHub Actions. Vitest также будет выводить соответствующую аннотацию в CLI, если тест не пройдет.

Scoped Fixtures
Фикстуры test.extend
теперь могут указывать опцию scope
: либо file
, либо worker
.
const test = baseTest.extend({
db: [
async ({}, use) => {
// ...настройка
await use(db);
await db.close();
},
{ scope: 'worker' },
],
});
Файловая фикстура работает аналогично beforeAll
и afterAll
, но на верхнем уровне файла, и она не будет вызвана, если фикстура не используется ни в одном тесте.
Фикстура worker
инициализируется один раз для каждого воркера, но обратите внимание, что по умолчанию Vitest создает отдельный воркер для каждого теста, поэтому вам нужно отключить изоляцию, чтобы воспользоваться этим преимуществом.
Пользовательские цвета названий проектов
Теперь вы можете установить пользовательский цвет при использовании projects
:
Пример конфигурации
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' }],
},
},
},
],
},
})

Custom Browser Locators API
Встроенные локаторы могут не покрывать все потребности вашего приложения. Вместо того чтобы возвращаться к CSS и терять защиту от повторных попыток, обеспечиваемую API локаторов Vitest, мы теперь рекомендуем расширять локаторы с помощью нового locators.extend
API.
import { locators } from '@vitest/browser/context';
locators.extend({
getByCommentsCount(count: number) {
return `.comments :text("${count} comments")`;
},
});
Метод возвращает строку локатора Playwright для создания нового локатора. Обратите внимание, что строка, возвращаемая этим методом, будет ограничена родительским локатором, если он существует.
Теперь вы можете вызывать getByCommentsCount
на page
или любом другом локаторе напрямую:
await expect.element(page.getByCommentsCount(1)).toBeVisible();
await expect
.element(
page.getByRole('article', { name: 'Hello World' }).getByCommentsCount(1)
)
.toBeVisible();
Если этот метод возвращает строку, то возвращаемое значение будет преобразовано в локатор, так что вы можете продолжать вызовы по цепочке:
page
.getByRole('article', { name: 'Hello World' })
.getByCommentsCount(1)
.getByText('comments');
Этот метод имеет доступ к текущему контексту локатора, если он существует (если метод вызывается на page
, то контекст будет ссылаться на page
), так что вы можете вызывать все методы локатора внутри него по цепочке:
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`));
},
});
Наличие доступа к контексту также позволяет вызывать стандартные методы локатора для определения пользовательского события:
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');
Пожалуйста, обратитесь к locators.extend
API для получения дополнительной информации.
Явное управление ресурсами в vi.spyOn
и vi.fn
В средах, поддерживающих явное управление ресурсами, вы можете использовать using
вместо const
, чтобы автоматически вызывать mockRestore
для любой замоканной функции при выходе из соответствующего блока. Это особенно полезно для методов-шпионов:
it('calls console.log', () => {
using spy = vi.spyOn(console, 'log').mockImplementation(() => {})
debug('message')
expect(spy).toHaveBeenCalled()
})
// console.log восстанавливается здесь
Test signal
API
Vitest теперь предоставляет объект AbortSignal
в теле теста. Вы можете использовать его для остановки любого ресурса, который поддерживает этот Web API.
Сигнал прерывается, если тест превышает время ожидания, другой тест не проходит и флаг --bail
установлен в ненулевое значение, или пользователь нажимает Ctrl+C в терминале.
Например, вы можете остановить запрос fetch
, когда тесты прерываются:
it('stop request when test times out', async ({ signal }) => {
await fetch('/heavy-resource', { signal });
}, 2000);
Покрытие V8 с учетом AST-перемаппинга
Vitest теперь использует пакет ast-v8-to-istanbul
, разработанный одним из сопровождающих Vitest, AriPerkkio. Это приводит отчеты о покрытии v8 в соответствие с istanbul, но обеспечивает лучшую производительность! Включите эту функцию, установив coverage.experimentalAstAwareRemapping
в true
.
Мы планируем сделать это режимом перемаппинга по умолчанию в следующем мажорном выпуске. Старый v8-to-istanbul
будет полностью удален. Приглашаем вас присоединиться к обсуждению на https://github.com/vitest-dev/vitest/issues/7928.
Опция watchTriggerPatterns
Когда вы редактируете файл, Vitest достаточно интеллектуален, чтобы перезапускать только тесты, которые импортируют этот файл. К сожалению, статический анализ Vitest учитывает только статические и динамические инструкции import
. Если вы читаете файл или запускаете дочерний процесс, Vitest будет игнорировать изменения в связанных файлах.
С помощью опции watchTriggerPatterns
вы можете настроить, какие тесты следует перезапускать при изменении файла. Например, чтобы всегда перезапускать тесты mailers
при изменении шаблона, добавьте шаблон-триггер:
export default defineConfig({
test: {
watchTriggerPatterns: [
{
pattern: /^src\/templates\/(.*)\.(ts|html|txt)$/,
testsToRun: (file, match) => {
return `api/tests/mailers/${match[2]}.test.ts`;
},
},
],
},
});
Новый многоцелевой тип Matchers
Vitest теперь имеет тип Matchers
, который вы можете расширить, чтобы добавить поддержку типов для всех ваших пользовательских матчеров централизованно. Этот тип влияет на все следующие сценарии использования:
expect().to*
expect.to*
expect.extend({ to* })
Например, чтобы иметь типобезопасный матчер toBeFoo
, вы можете написать что-то вроде этого:
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) {
// ^?
// ... реализация
return {
pass: true,
message: () => '',
};
},
});
expect('foo').toBeFoo('foo');
expect.toBeFoo('foo');
sequence.groupOrder
Новая опция sequence.groupOrder
контролирует порядок, в котором проект запускает свои тесты при использовании нескольких проектов.
- Проекты с одинаковым номером порядка группы будут запускаться вместе, при этом группы выполняются от наименьшего номера к наибольшему.
- Если вы не укажете эту опцию, все проекты будут запускаться параллельно.
- Если несколько проектов имеют одинаковый порядок группы, они будут запускаться одновременно.
Пример
Рассмотрим этот пример:
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,
},
},
},
],
},
});
Тесты в этих проектах выполняются в следующем порядке:
0. slow |
|> запускаются вместе
0. fast |
1. flaky |> запускается после slow и fast отдельно
Полный список изменений находится в журнале изменений Vitest 3.2.