-
Notifications
You must be signed in to change notification settings - Fork 16.4k
[Browser Run] Document Vitest Browser Mode provider #31883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 3 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
8dfb08d
[Browser Run] Document Vitest Browser Mode provider
irvinebroque edef0db
[Browser Run] Clarify Vitest provider token setup
irvinebroque 0fa63d6
[Browser Run] Add Vitest screenshot guidance
irvinebroque 16c25c1
[Browser Run] Address Vitest provider docs feedback
irvinebroque ec96060
[Browser Run] Expand Vitest changelog example
irvinebroque 22a594c
Fixed title & moved cross-link per review
ask-bonk[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
35 changes: 35 additions & 0 deletions
35
src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| --- | ||
| title: Run Vitest Browser Mode tests on Browser Run | ||
| description: Use the Browser Run Vitest provider to run Vitest Browser Mode test suites in hosted Chromium over CDP. | ||
| products: | ||
| - browser-run | ||
| date: 2026-07-03 | ||
| --- | ||
|
|
||
| You can now run [Vitest Browser Mode](https://vitest.dev/guide/browser/) test suites on [Browser Run](/browser-run/) hosted Chromium using `@cloudflare/vitest-browser-run-provider`. The provider connects Vitest's Playwright browser provider to Browser Run over the [Chrome DevTools Protocol (CDP)](/browser-run/cdp/), so browser tests can run against a managed Chromium environment from local development or CI. | ||
|
|
||
| Use this for tests that need browser APIs, user interactions, screenshots, or visual regression. For tests that need Workers runtime APIs or bindings, continue to use the [Workers Vitest integration](/workers/testing/vitest-integration/). | ||
|
|
||
| Here is a minimal Browser Run provider configuration: | ||
|
|
||
| ```ts title="vitest.browser-run.config.ts" | ||
| import { cloudflare } from "@cloudflare/vite-plugin"; | ||
| import { browserRunCdp } from "@cloudflare/vitest-browser-run-provider"; | ||
| import { defineConfig } from "vitest/config"; | ||
|
|
||
| export default defineConfig({ | ||
| plugins: [cloudflare({ tunnel: { autoStart: true } })], | ||
| test: { | ||
| browser: { | ||
| enabled: true, | ||
| headless: true, | ||
| provider: browserRunCdp(), | ||
| instances: [{ browser: "chromium" }], | ||
| }, | ||
| }, | ||
| }); | ||
| ``` | ||
|
|
||
| Before running tests, set `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_API_TOKEN`. The token needs `Browser Rendering - Edit` permission. | ||
|
|
||
| To get started, refer to [Using with Vitest Browser Mode (CDP)](/browser-run/cdp/vitest-browser-mode/). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
257 changes: 257 additions & 0 deletions
257
src/content/docs/browser-run/cdp/vitest-browser-mode.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,257 @@ | ||
| --- | ||
| pcx_content_type: how-to | ||
| title: Using with Vitest Browser Mode (CDP) | ||
| description: Run Vitest Browser Mode tests on Browser Run using hosted Chromium over the Chrome DevTools Protocol. | ||
| sidebar: | ||
| order: 5 | ||
| label: Vitest Browser Mode | ||
| products: | ||
| - browser-run | ||
| --- | ||
|
|
||
| import { PackageManagers, Render, TypeScriptExample } from "~/components"; | ||
|
|
||
| Use Vitest Browser Mode with Browser Run to run browser tests, user interaction tests, and visual regression tests in a hosted Chromium browser. The `@cloudflare/vitest-browser-run-provider` package connects Vitest to Browser Run through the Chrome DevTools Protocol (CDP). | ||
|
|
||
| <Render file="cdp-api-token-permissions" product="browser-run" /> | ||
|
|
||
| Browser Run tests run in a real browser. If you need to test Worker handlers, bindings, Durable Objects, or Workers runtime APIs, use the [Workers Vitest integration](/workers/testing/vitest-integration/) instead. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - A Vite project that uses [Vitest Browser Mode](https://vitest.dev/guide/browser/) | ||
| - A Cloudflare account with Browser Run enabled | ||
| - A Browser Run API token with `Browser Rendering - Edit` permission | ||
| - The [Cloudflare Vite plugin](/workers/vite-plugin/), if Browser Run needs to reach a local Vite dev server | ||
|
|
||
| ## Install packages | ||
|
|
||
| Install Vitest Browser Mode, the Playwright browser provider, the Browser Run provider, and the Cloudflare Vite plugin: | ||
|
|
||
| <PackageManagers | ||
| pkg="vitest @vitest/browser @vitest/browser-playwright @cloudflare/vitest-browser-run-provider @cloudflare/vite-plugin playwright@npm:playwright-core" | ||
| dev | ||
| /> | ||
|
|
||
| The `playwright@npm:playwright-core` alias satisfies the Playwright provider without downloading local browser binaries. If your project already uses the full `playwright` package, you can use that package instead. | ||
|
|
||
| ## Configure credentials | ||
|
|
||
| Set the Browser Run credentials in your shell, CI environment, or an uncommitted `.env` file. By default, `browserRunCdp()` reads `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_API_TOKEN`: | ||
|
|
||
| ```txt title=".env" | ||
| CLOUDFLARE_ACCOUNT_ID="<ACCOUNT_ID>" | ||
| CLOUDFLARE_API_TOKEN="<API_TOKEN>" | ||
| CLOUDFLARE_BROWSER_RUN_CONCURRENCY="8" | ||
| ``` | ||
|
|
||
| `CLOUDFLARE_BROWSER_RUN_CONCURRENCY` controls how many Vitest browser test files can run at the same time. It does not create that many Browser Run browser instances. | ||
|
|
||
| ## Configure Vitest | ||
|
|
||
| Create a Vitest config for Browser Run tests: | ||
|
|
||
| <TypeScriptExample filename="vitest.browser-run.config.ts"> | ||
|
|
||
| ```ts | ||
| import { cloudflare } from "@cloudflare/vite-plugin"; | ||
| import { browserRunCdp } from "@cloudflare/vitest-browser-run-provider"; | ||
| import { defineConfig } from "vitest/config"; | ||
|
|
||
| const browserApiHost = process.env.VITEST_BROWSER_API_HOST ?? "0.0.0.0"; | ||
| const browserApiPort = Number(process.env.VITEST_BROWSER_API_PORT ?? "63315"); | ||
| const browserRunConcurrency = Number( | ||
| process.env.CLOUDFLARE_BROWSER_RUN_CONCURRENCY ?? "8", | ||
| ); | ||
|
|
||
| export default defineConfig({ | ||
| plugins: [ | ||
| cloudflare({ | ||
| tunnel: { autoStart: true }, | ||
| }), | ||
| ], | ||
| server: { | ||
| host: browserApiHost, | ||
| port: browserApiPort, | ||
| strictPort: true, | ||
| allowedHosts: true, | ||
| }, | ||
| test: { | ||
| include: ["test/browser/**/*.browser.test.ts"], | ||
| fileParallelism: true, | ||
| maxWorkers: browserRunConcurrency, | ||
| browser: { | ||
| enabled: true, | ||
| headless: true, | ||
| fileParallelism: true, | ||
| provider: browserRunCdp(), | ||
| api: { | ||
| host: browserApiHost, | ||
| port: browserApiPort, | ||
| allowExec: true, | ||
| allowWrite: true, | ||
| }, | ||
| expect: { | ||
| toMatchScreenshot: { | ||
| comparatorName: "pixelmatch", | ||
| comparatorOptions: { | ||
| threshold: 0.2, | ||
| allowedMismatchedPixelRatio: 0.005, | ||
| }, | ||
| }, | ||
| }, | ||
| instances: [ | ||
| { | ||
| browser: "chromium", | ||
| viewport: { width: 1280, height: 800 }, | ||
| }, | ||
| ], | ||
| }, | ||
| }, | ||
| }); | ||
| ``` | ||
|
|
||
| </TypeScriptExample> | ||
|
|
||
| The Cloudflare Vite plugin starts a tunnel and sets `CLOUDFLARE_TUNNEL_URL`. The Browser Run provider uses that public origin so hosted Chromium can reach the local Vitest browser API. | ||
|
|
||
| If you expose the Vitest browser API with a different tunnel, set `VITEST_BROWSER_PUBLIC_ORIGIN` to its public origin. | ||
|
|
||
| This configuration sets `test.browser.api.allowExec` and `test.browser.api.allowWrite` to `true` so browser tests can use APIs such as `cdp()` and write screenshot artifacts. If your tests do not use `cdp()` or write artifacts, remove the corresponding option. Anyone with the tunnel URL can reach your dev server while the tunnel is active. For more information, refer to [Share a local dev server](/workers/local-development/local-dev-tunnels/#security-considerations). | ||
|
|
||
| The `test.browser.expect.toMatchScreenshot` block configures shared defaults for visual regression assertions. The fixed viewport keeps screenshots the same size across local and CI runs. | ||
|
|
||
| ## Write a browser test | ||
|
|
||
| Create a browser test file under the configured `test/browser/` directory: | ||
|
|
||
| ```ts title="test/browser/greeting.browser.test.ts" | ||
| import { describe, expect, it } from "vitest"; | ||
| import { cdp, userEvent } from "vitest/browser"; | ||
|
|
||
| describe("Browser Run Vitest test", () => { | ||
| it("runs in hosted Chromium", async () => { | ||
| const userAgent = (await cdp().send("Runtime.evaluate", { | ||
| expression: "navigator.userAgent", | ||
| returnByValue: true, | ||
| })) as { result: { value: string } }; | ||
|
|
||
| expect(userAgent.result.value).toContain("Chrome"); | ||
|
|
||
| document.body.innerHTML = ` | ||
| <main> | ||
| <label for="name">Name</label> | ||
| <input id="name" /> | ||
| <button type="button">Greet</button> | ||
| <p data-testid="greeting"></p> | ||
| </main> | ||
| `; | ||
|
|
||
| const input = document.querySelector<HTMLInputElement>("#name"); | ||
| const button = document.querySelector<HTMLButtonElement>("button"); | ||
| const greeting = document.querySelector<HTMLElement>( | ||
| "[data-testid='greeting']", | ||
| ); | ||
|
|
||
| expect(input).not.toBeNull(); | ||
| expect(button).not.toBeNull(); | ||
| expect(greeting).not.toBeNull(); | ||
|
|
||
| button!.addEventListener("click", () => { | ||
| greeting!.textContent = `Hello, ${input!.value}!`; | ||
| }); | ||
|
|
||
| await userEvent.type(input!, "Cloudflare"); | ||
| await userEvent.click(button!); | ||
|
|
||
| expect(greeting!.textContent).toBe("Hello, Cloudflare!"); | ||
| }); | ||
| }); | ||
| ``` | ||
|
|
||
| ## Add visual regression tests | ||
|
|
||
| Use `expect.element(...).toMatchScreenshot()` to compare a page element against a reference screenshot: | ||
|
|
||
| ```ts title="test/browser/hero.browser.test.ts" | ||
| import { expect, test } from "vitest"; | ||
| import { page } from "vitest/browser"; | ||
|
|
||
| test("hero section", async () => { | ||
| document.body.innerHTML = ` | ||
| <main> | ||
| <section data-testid="hero"> | ||
| <h1>Build with Cloudflare</h1> | ||
| <p>Run browser tests in hosted Chromium.</p> | ||
| </section> | ||
| </main> | ||
| `; | ||
|
|
||
| await expect | ||
| .element(page.getByTestId("hero")) | ||
| .toMatchScreenshot("hero-section"); | ||
| }); | ||
| ``` | ||
|
|
||
| When you run a visual test for the first time, Vitest creates a reference screenshot in a `__screenshots__` directory and fails the test. Review the screenshot, commit it, and run the test again. | ||
|
|
||
| To intentionally update reference screenshots, run Vitest with `--update`: | ||
|
|
||
| <PackageManagers | ||
| type="exec" | ||
| pkg="vitest" | ||
| args="run --config vitest.browser-run.config.ts --update" | ||
| /> | ||
|
|
||
| Review updated screenshots before committing them. Keep `test.browser.api.allowWrite` set to `true` when tests need to create or update screenshots. | ||
|
|
||
| ## Run tests | ||
|
|
||
| Run Vitest with the Browser Run config: | ||
|
|
||
| <PackageManagers | ||
| type="exec" | ||
| pkg="vitest" | ||
| args="run --config vitest.browser-run.config.ts" | ||
| /> | ||
|
|
||
| To run fewer test files at the same time, lower `CLOUDFLARE_BROWSER_RUN_CONCURRENCY`: | ||
|
|
||
| <PackageManagers | ||
| type="exec" | ||
| pkg="vitest" | ||
| args="run --config vitest.browser-run.config.ts" | ||
| prefix="CLOUDFLARE_BROWSER_RUN_CONCURRENCY=2" | ||
| /> | ||
|
|
||
| ## Parallelism model | ||
|
|
||
| Vitest schedules browser test files across `test.maxWorkers`. The Browser Run provider connects to one hosted Chromium browser and opens isolated pages or contexts for Vitest browser sessions. | ||
|
|
||
| This means `CLOUDFLARE_BROWSER_RUN_CONCURRENCY=8` runs up to eight browser test files at once inside one shared Browser Run browser. It does not launch eight separate Browser Run browsers. | ||
|
|
||
| If your tests need separate browser processes for isolation, run separate Vitest invocations or lower concurrency. Each new Browser Run browser is subject to [Browser Run limits](/browser-run/limits/). | ||
|
|
||
| ## Configure provider options | ||
|
|
||
| `browserRunCdp()` reads credentials and Browser Run options from environment variables. You can also pass options directly to the provider, but avoid hardcoding secrets in committed files. | ||
|
|
||
| | Option | Environment variable | Description | | ||
| | -------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------- | | ||
| | `accountId` | `CLOUDFLARE_ACCOUNT_ID` | Cloudflare account ID used to create the Browser Run URL | | ||
| | `apiToken` | `CLOUDFLARE_API_TOKEN` | API token used in the Browser Run authorization header | | ||
| | `publicOrigin` | `VITEST_BROWSER_PUBLIC_ORIGIN` or `CLOUDFLARE_TUNNEL_URL` | Public origin for the Vitest browser API | | ||
| | `wsEndpoint` | `CLOUDFLARE_BROWSER_RUN_WS_ENDPOINT` | Custom Browser Run CDP WebSocket endpoint | | ||
| | `keepAliveMs` | `CLOUDFLARE_BROWSER_RUN_KEEP_ALIVE_MS` | Browser inactivity timeout in milliseconds. Defaults to `600000` | | ||
| | `recording` | `CLOUDFLARE_BROWSER_RUN_RECORDING` | Set to `true` to enable [session recording](/browser-run/features/session-recording/) | | ||
|
|
||
| For example: | ||
|
|
||
| ```ts title="vitest.browser-run.config.ts" | ||
| provider: browserRunCdp({ | ||
| keepAliveMs: 600000, | ||
| recording: true, | ||
| }), | ||
| ``` | ||
|
|
||
| <Render file="faq" product="browser-run" /> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -156,6 +156,8 @@ export default { | |
|
|
||
| One of the most common use cases for using Playwright is software testing. Playwright includes test assertion features in its APIs; refer to [Assertions](https://playwright.dev/docs/test-assertions) in the Playwright documentation for details. Here's an example of a Worker doing `expect()` test assertions of the [todomvc](https://demo.playwright.dev/todomvc) demo page: | ||
|
|
||
| To run Vitest Browser Mode tests against Browser Run hosted Chromium, refer to [Using with Vitest Browser Mode (CDP)](/browser-run/cdp/vitest-browser-mode/). | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This cross-link breaks the flow of the Assertions example. Move it to the end of the section, after the code block and before the heading. |
||
|
|
||
| ```ts | ||
| import { launch } from "@cloudflare/playwright"; | ||
| import { expect } from "@cloudflare/playwright/test"; | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Page titles must use imperative mood, not gerund phrases (style guide: 'Install Wrangler' not 'Installing Wrangler').