Режим браузера Экспериментальный
Эта страница содержит информацию об экспериментальной функции режима браузера в Vitest API, которая позволяет запускать тесты непосредственно в браузере, предоставляя доступ к глобальным объектам браузера, таким как window и document. Эта функция в настоящее время находится в разработке, и её API может измениться в будущем.
TIP
Если вы ищете документацию по expect, vi или любому общему API, такому как тестовые проекты или тестирование типов, обратитесь к руководству "Начало работы".


Установка
Для упрощения настройки можно использовать команду vitest init browser, которая установит необходимые зависимости и создаст конфигурацию браузера.
npx vitest init browseryarn exec vitest init browserpnpx vitest init browserbunx vitest init browserРучная установка
Пакеты можно установить и вручную. По умолчанию режим браузера не требует дополнительных E2E-провайдеров для локального запуска тестов, поскольку он использует ваш существующий браузер.
npm install -D vitest @vitest/browseryarn add -D vitest @vitest/browserpnpm add -D vitest @vitest/browserbun add -D vitest @vitest/browserWARNING
Однако для запуска тестов в CI вам необходимо установить либо playwright, либо webdriverio. Мы также рекомендуем использовать один из них для локального тестирования вместо провайдера preview по умолчанию, поскольку он имитирует события вместо использования Chrome DevTools Protocol.
Если вы еще не используете один из этих инструментов, мы рекомендуем начать с Playwright, поскольку он поддерживает параллельное выполнение, что ускоряет ваши тесты. Кроме того, Playwright использует Chrome DevTools Protocol, который обычно быстрее WebDriver.
::: tabs key:provider == Playwright Playwright — это фреймворк для веб-тестирования и автоматизации веб-приложений.
npm install -D vitest @vitest/browser playwrightyarn add -D vitest @vitest/browser playwrightpnpm add -D vitest @vitest/browser playwrightbun add -D vitest @vitest/browser playwright== WebdriverIO
WebdriverIO позволяет запускать тесты локально с использованием протокола WebDriver.
npm install -D vitest @vitest/browser webdriverioyarn add -D vitest @vitest/browser webdriveriopnpm add -D vitest @vitest/browser webdriveriobun add -D vitest @vitest/browser webdriverioКонфигурация
Чтобы активировать режим браузера в конфигурации Vitest, установите поле browser.enabled в true в вашем файле конфигурации Vitest. Пример конфигурации с использованием поля browser:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
browser: {
provider: 'playwright', // или 'webdriverio'
enabled: true,
// требуется хотя бы один экземпляр
instances: [{ browser: 'chromium' }],
},
},
});INFO
Vitest назначает порт 63315, чтобы избежать конфликтов с сервером разработки, позволяя запускать их параллельно. Вы можете изменить это с помощью опции browser.api.
Начиная с Vitest 2.1.5, CLI больше не выводит URL Vite автоматически. Вы можете нажать "b", чтобы вывести URL при работе в режиме наблюдения.
Если вы не использовали Vite ранее, убедитесь, что плагин вашего фреймворка установлен и указан в конфигурации. Некоторые фреймворки могут требовать дополнительной настройки для работы — проверьте их документацию, связанную с Vite, чтобы убедиться.
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
test: {
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
});import { defineConfig } from 'vitest/config';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
test: {
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
});import { defineConfig } from 'vitest/config';
import { svelte } from '@sveltejs/vite-plugin-svelte';
export default defineConfig({
plugins: [svelte()],
test: {
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
});import { defineConfig } from 'vitest/config';
import solidPlugin from 'vite-plugin-solid';
export default defineConfig({
plugins: [solidPlugin()],
test: {
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
});import { defineConfig } from 'vitest/config';
import marko from '@marko/vite';
export default defineConfig({
plugins: [marko()],
test: {
browser: {
enabled: true,
provider: 'playwright',
instances: [{ browser: 'chromium' }],
},
},
});Если вам нужно запустить тесты с использованием Node-based runner, вы можете определить опцию projects с отдельными конфигурациями для различных стратегий тестирования:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
projects: [
{
test: {
// пример соглашения на основе файлов,
// вы не обязаны ему следовать
include: [
'tests/unit/**/*.{test,spec}.ts',
'tests/**/*.unit.{test,spec}.ts',
],
name: 'unit',
environment: 'node',
},
},
{
test: {
// пример соглашения на основе файлов,
// вы не обязаны ему следовать
include: [
'tests/browser/**/*.{test,spec}.ts',
'tests/**/*.browser.{test,spec}.ts',
],
name: 'browser',
browser: {
enabled: true,
instances: [{ browser: 'chromium' }],
},
},
},
],
},
});Типы опций браузера
Опция browser в Vitest варьируется в зависимости от выбранного провайдера. Vitest выдаст ошибку, если вы передадите --browser и не укажете имя браузера в конфигурации. Доступные опции:
webdriverioподдерживает следующие браузеры:firefoxchromeedgesafari
playwrightподдерживает следующие браузеры:firefoxwebkitchromium
TypeScript
По умолчанию TypeScript не видит опции провайдеров и дополнительные свойства expect. Если вы не используете провайдеров, убедитесь, что @vitest/browser/matchers импортирован в ваших тестах, файле настройки или файле конфигурации, для получения дополнительных определений expect. Если вы используете пользовательские провайдеры, убедитесь, что вы добавили @vitest/browser/providers/playwright или @vitest/browser/providers/webdriverio в тот же файл, чтобы TypeScript мог распознать определения для пользовательских опций:
/// <reference types="@vitest/browser/matchers" />/// <reference types="@vitest/browser/providers/playwright" />/// <reference types="@vitest/browser/providers/webdriverio" />В качестве альтернативы вы также можете добавить их в поле compilerOptions.types в вашем файле tsconfig.json. Обратите внимание, что указание любых значений в этом поле отключит автоматическую загрузку пакетов @types/*.
{
"compilerOptions": {
"types": ["@vitest/browser/matchers"]
}
}{
"compilerOptions": {
"types": ["@vitest/browser/providers/playwright"]
}
}{
"compilerOptions": {
"types": ["@vitest/browser/providers/webdriverio"]
}
}Совместимость с браузерами
Vitest использует сервер разработки Vite для запуска ваших тестов, поэтому поддерживаются только функции, указанные в опции esbuild.target (esnext по умолчанию).
По умолчанию Vite нацелен на браузеры, поддерживающие нативные ES Modules, нативный динамический импорт ESM и import.meta. Кроме того, мы используем BroadcastChannel для связи между iframe:
- Chrome >=87
- Firefox >=78
- Safari >=15.4
- Edge >=88
Запуск тестов
Когда вы указываете имя браузера в опции browser, Vitest по умолчанию попытается запустить указанный браузер с помощью preview, а затем запустит тесты. Если вы не хотите использовать preview, вы можете настроить пользовательский провайдер браузера с помощью опции browser.provider.
Чтобы указать браузер с помощью CLI, используйте флаг --browser с именем браузера, например:
npx vitest --browser=chromiumИли вы можете предоставить опции браузера в CLI с помощью точечной нотации:
npx vitest --browser.headlessWARNING
Начиная с Vitest 3.2, если у вас нет опции browser в вашей конфигурации, но вы указываете флаг --browser, Vitest завершит работу с ошибкой, потому что невозможно определить, предназначена ли конфигурация для браузера или для тестов Node.js.
По умолчанию Vitest автоматически откроет браузерный пользовательский интерфейс для разработки. Ваши тесты будут запускаться внутри iframe. Вы можете настроить область просмотра, выбрав предпочтительные размеры, вызвав page.viewport внутри теста или установив значения по умолчанию в конфигурации.
Безголовый режим
Безголовый режим — это дополнительная опция, доступная в режиме браузера. В безголовом режиме браузер работает в фоновом режиме без интерфейса, что делает его полезным для автоматизированных тестов. Опция headless в Vitest может быть установлена в логическое значение для включения или отключения безголового режима.
При использовании безголового режима Vitest не будет автоматически открывать пользовательский интерфейс. Если вы хотите продолжать использовать интерфейс, но запускать тесты в безголовом режиме, вы можете установить пакет @vitest/ui и передать флаг --ui при запуске Vitest.
Вот пример конфигурации, включающей безголовый режим:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
browser: {
provider: 'playwright',
enabled: true,
headless: true,
},
},
});Вы также можете установить безголовый режим с помощью флага --browser.headless в CLI, например:
npx vitest --browser.headlessВ этом случае Vitest будет работать в безголовом режиме в браузере Chrome.
WARNING
Безголовый режим не доступен по умолчанию. Для включения этой функции необходимо использовать провайдеры playwright или webdriverio.
Примеры
По умолчанию вам не нужны внешние пакеты для работы с режимом браузера:
import { expect, test } from 'vitest';
import { page } from '@vitest/browser/context';
import { render } from './my-render-function.js';
test('properly handles form inputs', async () => {
render(); // рендеринг DOM-элементов
// Утверждает начальное состояние.
await expect
.element(page.getByText('Hi, my name is Alice'))
.toBeInTheDocument();
// Получает DOM-узел ввода, используя связанную метку.
const usernameInput = page.getByLabelText(/username/i);
// Вводит имя в поле ввода. Это действие уже подтверждает, что поле ввода
// заполнено правильно, и нет необходимости проверять значение вручную.
await usernameInput.fill('Bob');
await expect
.element(page.getByText('Hi, my name is Bob'))
.toBeInTheDocument();
});Однако Vitest также предоставляет пакеты для рендеринга компонентов для нескольких популярных фреймворков из коробки:
vitest-browser-vueдля рендеринга компонентов vuevitest-browser-svelteдля рендеринга компонентов sveltevitest-browser-reactдля рендеринга компонентов react
Пакеты сообщества доступны для других фреймворков:
vitest-browser-litдля рендеринга компонентов litvitest-browser-preactдля рендеринга компонентов preact
Если ваш фреймворк не представлен, не стесняйтесь создать свой собственный пакет — это простая обертка вокруг рендерера фреймворка и API page.elementLocator. Мы добавим ссылку на него на этой странице. Убедитесь, что его имя начинается с vitest-browser-.
Помимо рендеринга компонентов и поиска элементов, вам также нужно выполнять утверждения. Vitest форкает библиотеку @testing-library/jest-dom, чтобы предоставить широкий спектр утверждений DOM из коробки. Подробнее читайте в Assertions API.
import { expect } from 'vitest';
import { page } from '@vitest/browser/context';
// элемент отрендерен правильно
await expect.element(page.getByText('Hello World')).toBeInTheDocument();Vitest предоставляет Context API с небольшим набором утилит, которые могут быть полезны в тестах. Например, если вам нужно выполнить взаимодействие, такое как нажатие на элемент или ввод текста в поле ввода, вы можете использовать userEvent из @vitest/browser/context. Подробнее читайте в Interactivity API.
import { page, userEvent } from '@vitest/browser/context';
await userEvent.fill(page.getByLabelText(/username/i), 'Alice');
// или просто locator.fill
await page.getByLabelText(/username/i).fill('Alice');import { render } from 'vitest-browser-vue';
import Component from './Component.vue';
test('properly handles v-model', async () => {
const screen = render(Component);
// Утверждает начальное состояние.
await expect
.element(screen.getByText('Hi, my name is Alice'))
.toBeInTheDocument();
// Получает DOM-узел ввода, используя связанную метку.
const usernameInput = screen.getByLabelText(/username/i);
// Вводит имя в поле ввода. Это действие уже подтверждает, что поле ввода
// заполнено правильно, и нет необходимости проверять значение вручную.
await usernameInput.fill('Bob');
await expect
.element(screen.getByText('Hi, my name is Bob'))
.toBeInTheDocument();
});import { render } from 'vitest-browser-svelte';
import { expect, test } from 'vitest';
import Greeter from './greeter.svelte';
test('greeting appears on click', async () => {
const screen = render(Greeter, { name: 'World' });
const button = screen.getByRole('button');
await button.click();
const greeting = screen.getByText(/hello world/iu);
await expect.element(greeting).toBeInTheDocument();
});import { render } from 'vitest-browser-react';
import Fetch from './fetch';
test('loads and displays greeting', async () => {
// Отображает React-элемент в DOM
const screen = render(<Fetch url="/greeting" />);
await screen.getByText('Load Greeting').click();
// ожидает перед тем, как сгенерировать ошибку, если элемент не найден
const heading = screen.getByRole('heading');
// проверяет, что сообщение-уведомление корректно
await expect.element(heading).toHaveTextContent('hello there');
await expect.element(screen.getByRole('button')).toBeDisabled();
});import { render } from 'vitest-browser-lit';
import { html } from 'lit';
import './greeter-button';
test('greeting appears on click', async () => {
const screen = render(html`<greeter-button name="World"></greeter-button>`);
const button = screen.getByRole('button');
await button.click();
const greeting = screen.getByText(/hello world/iu);
await expect.element(greeting).toBeInTheDocument();
});import { render } from 'vitest-browser-preact';
import { createElement } from 'preact';
import Greeting from './Greeting';
test('greeting appears on click', async () => {
const screen = render(<Greeting />);
const button = screen.getByRole('button');
await button.click();
const greeting = screen.getByText(/hello world/iu);
await expect.element(greeting).toBeInTheDocument();
});Vitest не поддерживает все фреймворки по умолчанию, но вы можете использовать внешние инструменты для тестирования с этими фреймворками. Мы также призываем сообщество создавать свои собственные обертки vitest-browser — если у вас есть подобная, добавьте ее в примеры выше.
Для неподдерживаемых фреймворков мы рекомендуем использовать пакеты testing-library:
@solidjs/testing-libraryдля рендеринга компонентов solid@marko/testing-libraryдля рендеринга компонентов marko
Вы также можете найти больше примеров в репозитории browser-examples.
WARNING
testing-library предоставляет пакет @testing-library/user-event. Мы не рекомендуем использовать его напрямую, так как он имитирует события вместо их фактического запуска — вместо этого используйте userEvent, импортированный из @vitest/browser/context, который использует Chrome DevTools Protocol или Webdriver (в зависимости от провайдера) в своей основе.
// на основе API @testing-library/solid
// https://testing-library.com/docs/solid-testing-library/api
import { render } from '@testing-library/solid';
it('использует параметры', async () => {
const App = () => (
<>
<Route
path="/ids/:id"
component={() => (
<p>
Id:
{useParams()?.id}
</p>
)}
/>
<Route path="/" component={() => <p>Start</p>} />
</>
);
const { baseElement } = render(() => <App />, { location: 'ids/1234' });
const screen = page.elementLocator(baseElement);
await expect.screen(screen.getByText('Id: 1234')).toBeInTheDocument();
});// на основе API @testing-library/marko
// https://testing-library.com/docs/marko-testing-library/api
import { render, screen } from '@marko/testing-library';
import Greeting from './greeting.marko';
test('renders a message', async () => {
const { baseElement } = await render(Greeting, { name: 'Marko' });
const screen = page.elementLocator(baseElement);
await expect.element(screen.getByText(/Marko/)).toBeInTheDocument();
expect(container.firstChild).toMatchInlineSnapshot(`
<h1>Hello, Marko!</h1>
`);
});Ограничения
Диалоги, блокирующие поток
При использовании Vitest Browser важно отметить, что блокирующие поток диалоги, такие как alert или confirm, не могут использоваться встроенно. Это связано с тем, что они блокируют веб-страницу, что означает, что Vitest не может продолжать общаться со страницей, что приводит к зависанию выполнения.
В таких ситуациях Vitest предоставляет стандартные заглушки с возвращаемыми значениями по умолчанию для этих API. Это гарантирует, что если пользователь случайно использует синхронные веб-API для всплывающих окон, выполнение не будет зависать. Тем не менее, рекомендуется пользователям создавать заглушки для этих веб-API для более оптимальной работы. Подробнее читайте в Мокирование.