브라우저 모드 실험적
이 페이지는 Vitest API의 실험적인 브라우저 모드 기능에 대한 정보를 제공합니다. 이 기능을 사용하면 window 및 document와 같은 브라우저 전역 객체에 접근하여 브라우저 환경에서 직접 테스트를 실행할 수 있습니다. 현재 개발 중인 기능이므로 API는 향후 변경될 수 있습니다.


설치
간편한 설정을 위해 vitest init browser 명령어를 사용하여 필요한 종속성을 설치하고 브라우저 구성을 생성할 수 있습니다.
npx vitest init browseryarn exec vitest init browserpnpx vitest init browserbunx vitest init browser수동 설치
패키지를 수동으로 설치할 수도 있습니다. 브라우저 모드는 기본적으로 기존 브라우저를 재사용하므로 로컬에서 테스트를 실행할 때 추가 E2E(End-to-End) 공급자가 필요하지 않습니다.
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부터 시작하는 것을 권장합니다. 또한 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 플래그를 사용하거나 Vitest 구성 파일에서 browser.enabled 필드를 true로 설정할 수 있습니다. 다음은 browser 필드를 사용한 구성 예시입니다.
export default defineConfig({
test: {
browser: {
provider: 'playwright', // 또는 'webdriverio'
enabled: true,
name: 'chromium', // 브라우저 이름은 필수입니다.
},
},
});INFO
Vitest는 개발 서버와의 충돌을 피하기 위해 포트 63315를 할당하여 병렬로 실행할 수 있도록 합니다. 이는 browser.api 옵션으로 변경할 수 있습니다.
Vitest 2.1.5부터 CLI는 더 이상 Vite URL을 자동으로 출력하지 않습니다. watch 모드에서 실행할 때 "b"를 눌러 URL을 출력할 수 있습니다.
Vite를 이전에 사용해 본 적이 없다면, 프레임워크의 플러그인이 설치되어 있고 구성에 지정되어 있는지 확인하십시오. 일부 프레임워크는 작동을 위해 추가 구성이 필요할 수 있습니다. 해당 Vite 관련 문서를 확인하여 확인하십시오.
import { defineConfig } from 'vitest/config';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
test: {
browser: {
enabled: true,
provider: 'playwright',
name: 'chromium',
},
},
});import { defineConfig } from 'vitest/config';
import { svelte } from '@sveltejs/vite-plugin-svelte';
export default defineConfig({
plugins: [svelte()],
test: {
browser: {
enabled: true,
provider: 'playwright',
name: 'chromium',
},
},
});import { defineConfig } from 'vitest/config';
import solidPlugin from 'vite-plugin-solid';
export default defineConfig({
plugins: [solidPlugin()],
test: {
browser: {
enabled: true,
provider: 'playwright',
name: 'chromium',
},
},
});import { defineConfig } from 'vitest/config';
import marko from '@marko/vite';
export default defineConfig({
plugins: [marko()],
test: {
browser: {
enabled: true,
provider: 'playwright',
name: 'chromium',
},
},
});TIP
react는 작동에 플러그인이 필요하지 않지만, preact는 별칭이 작동하도록 추가 구성이 필요합니다.
Node 기반 러너를 사용하여 일부 테스트를 실행해야 하는 경우, 다른 테스트 전략에 대한 별도의 구성으로 워크스페이스 파일을 정의할 수 있습니다.
// vitest.workspace.ts
import { defineWorkspace } from 'vitest/config';
export default defineWorkspace([
{
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,
name: 'chrome',
},
},
},
]);공급자 구성
:::tabs key:provider == Playwright providerOptions 필드를 통해 Vitest가 브라우저를 시작하고 페이지 컨텍스트를 생성하는 방법을 구성할 수 있습니다.
export default defineConfig({
test: {
browser: {
providerOptions: {
launch: {
devtools: true,
},
context: {
geolocation: {
latitude: 45,
longitude: -30,
},
reducedMotion: 'reduce',
},
},
},
},
});타입 힌트를 사용하려면 tsconfig.json 파일의 compilerOptions.types에 @vitest/browser/providers/playwright를 추가하십시오. == WebdriverIO providerOptions 필드를 통해 Vitest가 브라우저를 시작할 때 사용할 옵션을 구성할 수 있습니다.
export default defineConfig({
test: {
browser: {
browser: 'chrome',
providerOptions: {
region: 'eu',
capabilities: {
browserVersion: '27.0',
platformName: 'Windows 10',
},
},
},
},
});타입 힌트를 사용하려면 tsconfig.json 파일의 compilerOptions.types에 @vitest/browser/providers/webdriverio를 추가하십시오. :::
브라우저 옵션 유형
Vitest의 브라우저 옵션은 공급자에 따라 다릅니다. --browser를 전달하고 구성 파일에 이름을 지정하지 않으면 Vitest가 실패합니다. 사용 가능한 옵션:
webdriverio는 다음 브라우저를 지원합니다.firefoxchromeedgesafari
playwright는 다음 브라우저를 지원합니다.firefoxwebkitchromium
브라우저 호환성
Vitest는 Vite 개발 서버를 사용하여 테스트를 실행하므로, esbuild.target 옵션(기본값 esnext)에 지정된 기능만 지원합니다.
기본적으로 Vite는 기본 ES 모듈, 기본 ESM 동적 임포트, 그리고 import.meta를 지원하는 브라우저를 대상으로 합니다. 또한, iframe 간 통신을 위해 BroadcastChannel을 활용합니다.
- Chrome >=87
- Firefox >=78
- Safari >=15.4
- Edge >=88
테스트 실행
브라우저 옵션에 브라우저 이름을 지정하면 Vitest는 기본적으로 preview를 사용하여 지정된 브라우저를 실행한 다음 거기서 테스트를 실행합니다. preview를 사용하고 싶지 않다면 browser.provider 옵션을 사용하여 사용자 지정 브라우저 공급자를 구성할 수 있습니다.
CLI를 사용하여 브라우저를 지정하려면 --browser 플래그 뒤에 브라우저 이름을 다음과 같이 사용하십시오.
npx vitest --browser=chrome또는 점 표기법으로 CLI에 브라우저 옵션을 제공할 수 있습니다.
npx vitest --browser.name=chrome --browser.headless기본적으로 Vitest는 개발을 위해 브라우저 UI를 자동으로 엽니다. 테스트는 중앙의 iframe 내에서 실행됩니다. 선호하는 크기를 선택하거나, 테스트 내에서 page.viewport를 호출하거나, 구성에서 기본값을 설정하여 뷰포트를 구성할 수 있습니다.
헤드리스
헤드리스 모드는 브라우저 모드에서 사용할 수 있는 또 다른 옵션입니다. 헤드리스 모드에서는 브라우저가 사용자 인터페이스 없이 백그라운드에서 실행되므로 자동화된 테스트를 실행하는 데 유용합니다. Vitest의 헤드리스 옵션은 헤드리스 모드를 활성화하거나 비활성화하는 부울 값으로 설정할 수 있습니다.
헤드리스 모드를 사용하면 Vitest는 UI를 자동으로 열지 않습니다. UI를 계속 사용하면서 테스트를 헤드리스로 실행하려면 @vitest/ui 패키지를 설치하고 Vitest를 실행할 때 --ui 플래그를 전달하십시오.
다음은 헤드리스 모드를 활성화하는 구성 예시입니다.
export default defineConfig({
test: {
browser: {
provider: 'playwright',
enabled: true,
headless: true,
},
},
});CLI에서 --browser.headless 플래그를 사용하여 헤드리스 모드를 설정할 수도 있습니다.
npx vitest --browser.name=chrome --browser.headless이 경우 Vitest는 Chrome 브라우저를 사용하여 헤드리스 모드로 실행됩니다.
WARNING
헤드리스 모드는 기본적으로 사용할 수 없습니다. 이 기능을 활성화하려면 playwright 또는 webdriverio 공급자를 사용해야 합니다.
예시
Vitest는 여러 인기 프레임워크의 컴포넌트를 즉시 렌더링할 수 있는 패키지를 제공합니다.
- vue 컴포넌트를 렌더링하는
vitest-browser-vue - svelte 컴포넌트를 렌더링하는
vitest-browser-svelte - react 컴포넌트를 렌더링하는
vitest-browser-react
사용하는 프레임워크가 없다면 직접 패키지를 만들어도 좋습니다. 이는 프레임워크 렌더러와 page.elementLocator API를 감싸는 간단한 래퍼입니다. 이 페이지에 링크를 추가해 드리겠습니다. 이름이 vitest-browser-로 시작하는지 확인하십시오.
컴포넌트 렌더링 및 요소 찾기 외에도 어설션도 필요합니다. Vitest는 @testing-library/jest-dom 라이브러리를 번들로 제공하여 다양한 DOM 어설션을 즉시 사용할 수 있도록 합니다. 자세한 내용은 어설션 API를 참조하십시오.
import { expect } from 'vitest';
import { page } from '@vitest/browser/context';
// 요소가 제대로 렌더링되었는지 확인합니다.
await expect.element(page.getByText('Hello World')).toBeInTheDocument();Vitest는 테스트에 유용할 수 있는 작은 유틸리티 세트와 함께 컨텍스트 API를 노출합니다. 예를 들어, 요소를 클릭하거나 입력 필드에 텍스트를 입력하는 것과 같은 상호 작용을 해야 하는 경우 @vitest/browser/context에서 userEvent를 사용할 수 있습니다. 자세한 내용은 상호 작용 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();
});Vitest는 모든 프레임워크를 즉시 지원하지는 않지만, 외부 도구를 사용하여 이러한 프레임워크로 테스트를 실행할 수 있습니다. 또한 커뮤니티에서 자체 vitest-browser 래퍼를 만들도록 권장합니다. 만약 있다면 위 예시에 추가해 주십시오.
지원되지 않는 프레임워크의 경우 testing-library 패키지를 사용하는 것을 권장합니다.
- preact 컴포넌트를 렌더링하는
@testing-library/preact - solid 컴포넌트를 렌더링하는
@solidjs/testing-library - marko 컴포넌트를 렌더링하는
@marko/testing-library
WARNING
testing-library는 @testing-library/user-event 패키지를 제공합니다. 이 패키지는 이벤트를 실제로 트리거하는 대신 시뮬레이션하므로 직접 사용하는 것을 권장하지 않습니다. 대신, 내부적으로 Chrome DevTools Protocol 또는 Webdriver(공급자에 따라 다름)를 사용하는 @vitest/browser/context에서 가져온 userEvent를 사용하십시오.
// @testing-library/preact 예시 기반
// https://testing-library.com/docs/preact-testing-library/example
import { h } from 'preact';
import { page } from '@vitest/browser/context';
import { render } from '@testing-library/preact';
import HiddenMessage from '../hidden-message';
test('shows the children when the checkbox is checked', async () => {
const testMessage = 'Test Message';
const { baseElement } = render(<HiddenMessage>{testMessage}</HiddenMessage>);
const screen = page.elementLocator(baseElement);
// .query()는 요소를 찾으면 반환하고, 찾을 수 없으면 null을 반환합니다.
// .element()는 요소를 찾으면 반환하고, 찾을 수 없으면 오류를 발생시킵니다.
expect(screen.getByText(testMessage).query()).not.toBeInTheDocument();
// 쿼리는 정규식을 허용하여 선택자를 콘텐츠 변경에 더 강하게 만들 수 있습니다.
await screen.getByLabelText(/show/i).click();
await expect.element(screen.getByText(testMessage)).toBeInTheDocument();
});// @testing-library/solid API 기반
// 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();
});// @testing-library/marko API 기반
// 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();
await expect.element(container.firstChild).toMatchInlineSnapshot(`
<h1>Hello, Marko!</h1>
`);
});제한 사항
스레드 차단 다이얼로그
Vitest 브라우저를 사용할 때 alert 또는 confirm과 같은 스레드 차단 다이얼로그는 기본적으로 사용할 수 없다는 점에 유의해야 합니다. 이는 웹 페이지를 차단하여 Vitest가 페이지와 계속 통신할 수 없게 되어 실행이 중단되기 때문입니다.
이러한 상황에서 Vitest는 이러한 API에 대한 기본 반환 값을 가진 기본 모의(mock)를 제공합니다. 이는 사용자가 실수로 동기 팝업 웹 API를 사용하더라도 실행이 중단되지 않도록 보장합니다. 그러나 더 나은 경험을 위해 사용자가 이러한 웹 API를 모의하는 것이 여전히 권장됩니다. 자세한 내용은 모의(Mocking)를 참조하십시오.