Tryb przeglądarkowy Eksperymentalny
Ta strona zawiera informacje na temat eksperymentalnej funkcji trybu przeglądarkowego w Vitest API, która umożliwia uruchamianie testów natywnie w przeglądarce, zapewniając dostęp do globalnych obiektów przeglądarki, takich jak window i document. Funkcja ta jest obecnie w fazie rozwoju, a jej API mogą ulec zmianie w przyszłości.
TIP
Jeśli szukasz dokumentacji dla expect, vi lub jakiegokolwiek ogólnego API, takiego jak projekty testowe lub testowanie typów, zapoznaj się z przewodnikiem “Getting Started” (“Pierwsze kroki”).


Instalacja
Aby ułatwić konfigurację, możesz użyć polecenia vitest init browser, aby zainstalować wymagane zależności i utworzyć konfigurację przeglądarki.
npx vitest init browseryarn exec vitest init browserpnpx vitest init browserbunx vitest init browserRęczna instalacja
Możesz również zainstalować pakiety ręcznie. Domyślnie tryb przeglądarkowy nie wymaga żadnego dodatkowego dostawcy E2E do uruchamiania testów lokalnie, ponieważ wykorzystuje już zainstalowaną przeglądarkę.
npm install -D vitest @vitest/browseryarn add -D vitest @vitest/browserpnpm add -D vitest @vitest/browserbun add -D vitest @vitest/browserWARNING
Aby uruchomić testy w CI, musisz zainstalować playwright lub webdriverio. Zalecamy również przełączenie się na jednego z nich do lokalnego testowania zamiast używania domyślnego dostawcy preview, ponieważ opiera się on na symulacji zdarzeń zamiast używania protokołu Chrome DevTools.
Jeśli jeszcze nie używasz jednego z tych narzędzi, zalecamy rozpoczęcie od Playwright, ponieważ obsługuje on wykonanie równoległe, co przyspiesza działanie testów. Dodatkowo, Playwright używa Chrome DevTools Protocol, który jest zazwyczaj szybszy niż WebDriver.
::: tabs key:provider == Playwright Playwright to framework do testowania i automatyzacji stron WWW.
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 umożliwia uruchamianie testów lokalnie przy użyciu protokołu 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 webdriverioKonfiguracja
Aby aktywować tryb przeglądarkowy w konfiguracji Vitest, ustaw pole browser.enabled na true w pliku konfiguracyjnym Vitest. Oto przykład konfiguracji używającej pola browser:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
browser: {
provider: 'playwright', // lub 'webdriverio'
enabled: true,
// wymagane jest co najmniej jedno wystąpienie
instances: [{ browser: 'chromium' }],
},
},
});INFO
Vitest przypisuje port 63315, aby uniknąć konfliktów z serwerem deweloperskim, co umożliwia uruchamianie obu równolegle. Możesz to zmienić za pomocą opcji browser.api.
Od Vitest 2.1.5, CLI nie drukuje już automatycznie adresu URL Vite. Możesz nacisnąć „b”, aby wydrukować adres URL podczas działania w trybie watch.
Jeśli nie korzystałeś wcześniej z Vite, upewnij się, że masz zainstalowaną wtyczkę swojego frameworka i że jest ona określona w konfiguracji. Niektóre frameworki mogą wymagać dodatkowej konfiguracji, aby działać – sprawdź ich dokumentację związaną z Vite, aby się upewnić.
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' }],
},
},
});Jeśli potrzebujesz uruchomić niektóre testy za pomocą runnera opartego na Node, możesz zdefiniować opcję projects z oddzielnymi konfiguracjami dla różnych strategii testowania:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
projects: [
{
test: {
// przykład konwencji plikowej,
// nie musisz jej przestrzegać
include: [
'tests/unit/**/*.{test,spec}.ts',
'tests/**/*.unit.{test,spec}.ts',
],
name: 'unit',
environment: 'node',
},
},
{
test: {
// przykład konwencji plikowej,
// nie musisz jej przestrzegać
include: [
'tests/browser/**/*.{test,spec}.ts',
'tests/**/*.browser.{test,spec}.ts',
],
name: 'browser',
browser: {
enabled: true,
instances: [{ browser: 'chromium' }],
},
},
},
],
},
});Typy opcji przeglądarki
Opcja przeglądarki w Vitest zależy od dostawcy. Vitest zgłosi błąd, jeśli przekażesz --browser i nie określisz jego nazwy w pliku konfiguracyjnym. Dostępne opcje:
webdriverioobsługuje następujące przeglądarki:firefoxchromeedgesafari
playwrightobsługuje następujące przeglądarki:firefoxwebkitchromium
TypeScript
Domyślnie TypeScript nie rozpoznaje opcji dla dostawców i dodatkowych właściwości obiektu expect. Jeśli nie używasz żadnych dostawców, upewnij się, że @vitest/browser/matchers jest gdzieś odwołany w twoich testach, pliku setup lub pliku konfiguracyjnym, aby pobrać dodatkowe definicje expect. Jeśli używasz niestandardowych dostawców, upewnij się, że dodałeś @vitest/browser/providers/playwright lub @vitest/browser/providers/webdriverio do tego samego pliku, aby TypeScript mógł pobrać definicje dla niestandardowych opcji:
/// <reference types="@vitest/browser/matchers" />/// <reference types="@vitest/browser/providers/playwright" />/// <reference types="@vitest/browser/providers/webdriverio" />Alternatywnie, możesz również dodać je do pola compilerOptions.types w pliku tsconfig.json. Należy pamiętać, że określenie czegokolwiek w tym polu wyłączy automatyczne ładowanie pakietów @types/*.
{
"compilerOptions": {
"types": ["@vitest/browser/matchers"]
}
}{
"compilerOptions": {
"types": ["@vitest/browser/providers/playwright"]
}
}{
"compilerOptions": {
"types": ["@vitest/browser/providers/webdriverio"]
}
}Kompatybilność z przeglądarkami
Vitest używa serwera deweloperskiego Vite do uruchamiania testów, więc obsługujemy tylko funkcje zdefiniowane w opcji esbuild.target (esnext domyślnie).
Domyślnie, Vite celuje w przeglądarki, które wspierają natywne ES Modules, natywny ESM dynamic import oraz import.meta. Dodatkowo, wykorzystujemy BroadcastChannel do komunikacji pomiędzy iframe'ami:
- Chrome >=87
- Firefox >=78
- Safari >=15.4
- Edge >=88
Uruchamianie testów
Gdy określisz nazwę przeglądarki w opcji browser, Vitest spróbuje uruchomić określoną przeglądarkę domyślnie w trybie preview, a następnie uruchomi tam testy. Jeśli nie chcesz używać preview, możesz skonfigurować niestandardowego dostawcę przeglądarki za pomocą opcji browser.provider.
Aby określić przeglądarkę za pomocą CLI, użyj flagi --browser, a następnie nazwy przeglądarki, w ten sposób:
npx vitest --browser=chromiumLub możesz przekazać opcje przeglądarki do CLI za pomocą notacji kropkowej:
npx vitest --browser.headlessWARNING
Od Vitest 3.2, jeśli nie masz opcji browser w swojej konfiguracji, ale określisz flagę --browser, Vitest zgłosi błąd, ponieważ nie może założyć, że konfiguracja jest przeznaczona dla przeglądarki, a nie dla testów Node.js.
Domyślnie Vitest automatycznie otworzy interfejs użytkownika przeglądarki do celów deweloperskich. Twoje testy będą uruchamiane wewnątrz iframe'a w centralnej części interfejsu. Możesz skonfigurować obszar widoku, wybierając preferowane wymiary, wywołując page.viewport w teście lub ustawiając wartości domyślne w konfiguracji.
Tryb bezgłowy (Headless)
Tryb bezgłowy to kolejna opcja dostępna w trybie przeglądarkowym. W trybie bezgłowym przeglądarka działa w tle, bez interfejsu użytkownika, co czyni ją przydatną do uruchamiania zautomatyzowanych testów. Opcję headless w Vitest można ustawić na wartość logiczną, aby włączyć lub wyłączyć tryb bezgłowy.
W trybie bezgłowym Vitest nie otworzy automatycznie interfejsu użytkownika. Jeśli chcesz nadal używać interfejsu użytkownika, ale uruchamiać testy w trybie bezgłowym, możesz zainstalować pakiet @vitest/ui i przekazać flagę --ui podczas uruchamiania Vitest.
Przykład konfiguracji włączającej tryb bezgłowy:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
browser: {
provider: 'playwright',
enabled: true,
headless: true,
},
},
});Możesz również ustawić tryb bezgłowy za pomocą flagi --browser.headless w CLI, w ten sposób:
npx vitest --browser.headlessW tym przypadku Vitest uruchomi się w trybie bezgłowym, używając przeglądarki Chrome.
WARNING
Tryb bezgłowy nie jest dostępny domyślnie. Aby włączyć tę funkcję, musisz użyć dostawców playwright lub webdriverio.
Przykłady
Domyślnie nie potrzebujesz żadnych zewnętrznych pakietów, aby pracować z trybem przeglądarkowym:
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(); // renderuje elementy DOM
// Aseruje stan początkowy.
await expect
.element(page.getByText('Hi, my name is Alice'))
.toBeInTheDocument();
// Pobiera węzeł DOM inputu, odnajdując go za pomocą powiązanej etykiety.
const usernameInput = page.getByLabelText(/username/i);
// Wpisuje nazwę do inputu. To już weryfikuje, że input
// jest poprawnie wypełniony, eliminując potrzebę ręcznego sprawdzania wartości.
await usernameInput.fill('Bob');
await expect
.element(page.getByText('Hi, my name is Bob'))
.toBeInTheDocument();
});Jednak Vitest dostarcza również pakiety do renderowania komponentów dla kilku popularnych frameworków gotowe do użycia:
vitest-browser-vuedo renderowania komponentów Vuevitest-browser-sveltedo renderowania komponentów Sveltevitest-browser-reactdo renderowania komponentów React
Pakiety społecznościowe są dostępne dla innych frameworków:
vitest-browser-litdo renderowania komponentów Litvitest-browser-preactdo renderowania komponentów Preact
Jeśli Twój framework nie jest obsługiwany, śmiało stwórz własny pakiet – jest to prosta otoczka wokół renderera frameworka i API page.elementLocator. Dodamy do niego link na tej stronie. Upewnij się, że jego nazwa zaczyna się od vitest-browser-.
Oprócz renderowania komponentów i lokalizowania elementów, będziesz również musiał wykonywać asercje. Vitest wykorzystuje forka biblioteki @testing-library/jest-dom, aby domyślnie zapewnić szeroki zakres asercji DOM. Więcej informacji znajdziesz w API asercji.
import { expect } from 'vitest';
import { page } from '@vitest/browser/context';
// element został poprawnie wyrenderowany
await expect.element(page.getByText('Hello World')).toBeInTheDocument();Vitest udostępnia Context API z zestawem narzędzi, które mogą być przydatne w testach. Na przykład, jeśli potrzebujesz wykonać interakcję, taką jak kliknięcie elementu lub wpisanie tekstu do pola wejściowego, możesz użyć userEvent z @vitest/browser/context. Więcej informacji znajdziesz w API interaktywności.
import { page, userEvent } from '@vitest/browser/context';
await userEvent.fill(page.getByLabelText(/username/i), 'Alice');
// lub po prostu 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);
// Aseruje stan początkowy.
await expect
.element(screen.getByText('Hi, my name is Alice'))
.toBeInTheDocument();
// Pobiera węzeł DOM inputu, odnajdując go za pomocą powiązanej etykiety.
const usernameInput = screen.getByLabelText(/username/i);
// Wpisuje nazwę do inputu. To już weryfikuje, że input
// jest poprawnie wypełniony, eliminując potrzebę ręcznego sprawdzania wartości.
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 () => {
// Renderuje element React w drzewie DOM
const screen = render(<Fetch url="/greeting" />);
await screen.getByText('Load Greeting').click();
// czeka, zanim zgłosi błąd, jeśli nie może znaleźć elementu
const heading = screen.getByRole('heading');
// aseruje, że treść alertu jest poprawna
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 nie obsługuje wszystkich frameworków domyślnie, ale możesz użyć zewnętrznych narzędzi do uruchamiania testów z tymi frameworkami. Zachęcamy również społeczność do tworzenia własnych wrapperów vitest-browser – jeśli masz taki, możesz go dodać do powyższych przykładów.
Dla nieobsługiwanych frameworków zalecamy użycie pakietów testing-library:
@solidjs/testing-librarydo renderowania komponentów Solid@marko/testing-librarydo renderowania komponentów Marko
Więcej przykładów znajdziesz również w repozytorium browser-examples.
WARNING
testing-library dostarcza pakiet @testing-library/user-event. Nie zalecamy używania go bezpośrednio, ponieważ symuluje on zdarzenia zamiast je rzeczywiście wywoływać – zamiast tego użyj userEvent importowanego z @vitest/browser/context, który w tle używa protokołu Chrome DevTools lub Webdriver (w zależności od dostawcy).
// na podstawie API @testing-library/solid
// https://testing-library.com/docs/solid-testing-library/api
import { render } from '@testing-library/solid';
it('uses params', 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();
});// na podstawie 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>
`);
});Ograniczenia
Okna dialogowe blokujące wątek
Podczas korzystania z Vitest Browser należy pamiętać, że okna dialogowe blokujące wątek, takie jak alert lub confirm, nie mogą być używane natywnie. Dzieje się tak, ponieważ blokują one stronę internetową, co oznacza, że Vitest nie może kontynuować komunikacji ze stroną, co powoduje zawieszenie wykonania.
W takich sytuacjach Vitest udostępnia domyślne atrapy z domyślnymi wartościami zwracanymi dla tych API. Zapewnia to, że jeśli użytkownik przypadkowo użyje synchronicznych API okienek dialogowych, wykonanie nie zostanie zawieszone. Jednak nadal zaleca się, aby użytkownik zamockował te interfejsy API, aby zapewnić lepsze wrażenia. Więcej informacji w Mocking.