[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

test: allow running browser mode tests with docker playwright + add docs examples (#9600)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

authored by

Hiroshi Ogawa
Claude Opus 4.6
and committed by
GitHub
(Feb 8, 2026, 12:08 PM +0100) 136d6ddf 209b1b0e

+100 -51
+13
test/browser/README.md
··· 1 + # Browser Tests 2 + 3 + ## Using docker playwright 4 + 5 + Some test suites don't support running it remotely (`fixtures/inspect` and `fixtures/insecure-context`). 6 + 7 + ```sh 8 + # Start playwright browser server 9 + pnpm docker up -d 10 + 11 + # Run tests with BROWSER_WS_ENDPOINT 12 + BROWSER_WS_ENDPOINT=ws://127.0.0.1:6677/ pnpm test:playwright 13 + ```
+9
test/browser/docker-compose.yaml
··· 1 + services: 2 + playwright: 3 + image: mcr.microsoft.com/playwright:v1.58.1-noble 4 + command: /bin/sh -c "npx -y playwright@1.58.1 run-server --port 6677 --host 0.0.0.0" 5 + init: true 6 + ipc: host 7 + user: pwuser 8 + ports: 9 + - '6677:6677'
+2 -1
test/browser/package.json
··· 26 26 "test:browser:preview": "PROVIDER=preview vitest", 27 27 "test:browser:playwright": "PROVIDER=playwright vitest", 28 28 "test:browser:webdriverio": "PROVIDER=webdriverio vitest", 29 - "test:browser:playwright:html": "PROVIDER=playwright vitest --reporter=html" 29 + "test:browser:playwright:html": "PROVIDER=playwright vitest --reporter=html", 30 + "docker": "docker compose" 30 31 }, 31 32 "devDependencies": { 32 33 "@types/react": "^19.2.10",
+17 -8
test/browser/settings.ts
··· 4 4 import { webdriverio } from '@vitest/browser-webdriverio' 5 5 6 6 const providerName = (process.env.PROVIDER || 'playwright') as 'playwright' | 'webdriverio' | 'preview' 7 + 7 8 export const providers = { 8 - playwright, 9 + playwright: (options?: Parameters<typeof playwright>[0]) => playwright(process.env.BROWSER_WS_ENDPOINT 10 + ? { 11 + ...options, 12 + connectOptions: { 13 + wsEndpoint: process.env.BROWSER_WS_ENDPOINT, 14 + exposeNetwork: '<loopback>', 15 + }, 16 + } 17 + : options), 9 18 preview, 10 19 webdriverio, 11 20 } 12 21 13 22 export const provider = providers[providerName]() 14 - export const browser = process.env.BROWSER || (provider.name !== 'playwright' ? 'chromium' : 'chrome') 15 - 16 - const devInstances: BrowserInstanceOption[] = [ 17 - { browser }, 18 - ] 19 23 20 24 const playwrightInstances: BrowserInstanceOption[] = [ 21 25 { browser: 'chromium' }, ··· 30 34 { browser: 'firefox' }, 31 35 ] 32 36 33 - export const instances = process.env.BROWSER 34 - ? devInstances 37 + export const instances: BrowserInstanceOption[] = process.env.BROWSER 38 + ? [ 39 + { 40 + browser: process.env.BROWSER as any, 41 + headless: process.env.BROWSER === 'safari' ? false : undefined, 42 + }, 43 + ] 35 44 : provider.name === 'playwright' 36 45 ? playwrightInstances 37 46 : webdriverioInstances
+4 -33
test/browser/vitest.config.mts
··· 1 - import type { BrowserCommand, BrowserInstanceOption } from 'vitest/node' 1 + import type { BrowserCommand } from 'vitest/node' 2 2 import { dirname, resolve } from 'node:path' 3 3 import { fileURLToPath } from 'node:url' 4 4 import * as util from 'node:util' 5 - import { playwright } from '@vitest/browser-playwright' 6 - import { preview } from '@vitest/browser-preview' 7 - import { webdriverio } from '@vitest/browser-webdriverio' 8 5 import { defineConfig } from 'vitest/config' 6 + import { instances, provider } from './settings' 9 7 10 8 const dir = dirname(fileURLToPath(import.meta.url)) 11 - 12 - const providerName = process.env.PROVIDER || 'playwright' 13 - const browser = process.env.BROWSER as 'firefox' || (providerName === 'playwright' ? 'chromium' : 'chrome') 14 - const provider = { 15 - playwright, 16 - preview, 17 - webdriverio, 18 - }[providerName] 19 9 20 10 const myCustomCommand: BrowserCommand<[arg1: string, arg2: string]> = ({ testPath }, arg1, arg2) => { 21 11 return { testPath, arg1, arg2 } ··· 24 14 const stripVTControlCharacters: BrowserCommand<[text: string]> = (_, text) => { 25 15 return util.stripVTControlCharacters(text) 26 16 } 27 - 28 - const devInstances: BrowserInstanceOption[] = [ 29 - { browser }, 30 - ] 31 - 32 - const playwrightInstances: BrowserInstanceOption[] = [ 33 - { browser: 'chromium' }, 34 - { browser: 'firefox' }, 35 - { browser: 'webkit' }, 36 - ] 37 - 38 - const webdriverioInstances: BrowserInstanceOption[] = [ 39 - { browser: 'chrome' }, 40 - { browser: 'firefox' }, 41 - ] 42 17 43 18 export default defineConfig({ 44 19 server: { ··· 66 41 browser: { 67 42 enabled: true, 68 43 headless: false, 69 - instances: process.env.BROWSER 70 - ? devInstances 71 - : providerName === 'playwright' 72 - ? playwrightInstances 73 - : webdriverioInstances, 74 - provider: provider(), 44 + instances, 45 + provider, 75 46 // isolate: false, 76 47 testerHtmlPath: './custom-tester.html', 77 48 orchestratorScripts: [
+49
docs/config/browser/playwright.md
··· 71 71 72 72 These options are directly passed down to `playwright[browser].connect` command. You can read more about the command and available arguments in the [Playwright documentation](https://playwright.dev/docs/api/class-browsertype#browser-type-connect). 73 73 74 + Use `connectOptions.wsEndpoint` to connect to an existing Playwright server instead of launching browsers locally. This is useful for running browsers in Docker, in CI, or on a remote machine. 75 + 74 76 ::: warning 75 77 Since this command connects to an existing Playwright server, any `launch` options will be ignored. 78 + ::: 79 + 80 + ::: details Example: Running a Playwright Server in Docker 81 + To run browsers in a Docker container (see [Playwright Docker guide](https://playwright.dev/docs/docker#remote-connection)): 82 + 83 + Start a Playwright server using Docker Compose: 84 + 85 + ```yaml [docker-compose.yml] 86 + services: 87 + playwright: 88 + image: mcr.microsoft.com/playwright:v1.58.1-noble 89 + command: /bin/sh -c "npx -y playwright@1.58.1 run-server --port 6677 --host 0.0.0.0" 90 + init: true 91 + ipc: host 92 + user: pwuser 93 + ports: 94 + - '6677:6677' 95 + ``` 96 + 97 + ```sh 98 + docker compose up -d 99 + ``` 100 + 101 + Then configure Vitest to connect to it. The [`exposeNetwork`](https://playwright.dev/docs/api/class-browsertype#browser-type-connect-option-expose-network) option lets the containerized browser reach Vitest's dev server on the host: 102 + 103 + ```ts [vitest.config.ts] 104 + import { playwright } from '@vitest/browser-playwright' 105 + import { defineConfig } from 'vitest/config' 106 + 107 + export default defineConfig({ 108 + test: { 109 + browser: { 110 + provider: playwright({ 111 + connectOptions: { 112 + wsEndpoint: 'ws://127.0.0.1:6677/', 113 + exposeNetwork: '<loopback>', 114 + }, 115 + }), 116 + instances: [ 117 + { browser: 'chromium' }, 118 + { browser: 'firefox' }, 119 + { browser: 'webkit' }, 120 + ], 121 + }, 122 + }, 123 + }) 124 + ``` 76 125 ::: 77 126 78 127 ## contextOptions
+4 -7
test/browser/specs/utils.ts
··· 2 2 import type { TestUserConfig } from 'vitest/node' 3 3 import type { RunVitestConfig, TestFsStructure, VitestRunnerCLIOptions } from '../../test-utils' 4 4 import { runInlineTests, runVitest } from '../../test-utils' 5 - import { browser, instances, provider } from '../settings' 5 + import { instances, provider } from '../settings' 6 6 7 - export { browser, instances, provider } from '../settings' 7 + export { instances, provider } from '../settings' 8 8 9 9 export async function runInlineBrowserTests( 10 10 structure: TestFsStructure, ··· 21 21 enabled: true, 22 22 provider, 23 23 instances, 24 - headless: browser !== 'safari', 24 + headless: true, 25 25 ...config?.browser, 26 26 } as TestUserConfig['browser'], 27 27 }, ··· 39 39 watch: false, 40 40 reporters: 'none', 41 41 ...config, 42 - browser: { 43 - headless: browser !== 'safari', 44 - ...config?.browser, 45 - } as TestUserConfig['browser'], 42 + browser: { headless: true, ...config?.browser }, 46 43 $viteConfig: viteOverrides, 47 44 }, include, runnerOptions) 48 45 }
+2 -2
test/browser/fixtures/trace-view/vitest.config.ts
··· 1 1 import { fileURLToPath } from 'node:url' 2 2 import { defineConfig } from 'vitest/config' 3 - import { playwright } from '@vitest/browser-playwright' 3 + import { providers } from '../../settings' 4 4 5 5 export default defineConfig({ 6 6 cacheDir: fileURLToPath(new URL("./node_modules/.vite", import.meta.url)), 7 7 test: { 8 8 browser: { 9 9 enabled: true, 10 - provider: playwright(), 10 + provider: providers.playwright(), 11 11 instances: [ 12 12 { browser: 'chromium' }, 13 13 { browser: 'firefox' },