From 8dfb08df88f796022c6927fab69f0d775e00f454 Mon Sep 17 00:00:00 2001 From: Brendan Irvine-Broque Date: Fri, 3 Jul 2026 23:38:18 -0700 Subject: [PATCH 1/6] [Browser Run] Document Vitest Browser Mode provider --- ...026-07-03-vitest-browser-mode-provider.mdx | 33 +++ src/content/docs/browser-run/cdp/index.mdx | 6 +- .../browser-run/cdp/vitest-browser-mode.mdx | 200 ++++++++++++++++++ src/content/docs/browser-run/examples.mdx | 5 + .../docs/browser-run/playwright/index.mdx | 2 + src/content/docs/workers/testing/index.mdx | 2 + .../testing/vitest-integration/index.mdx | 2 + .../write-your-first-test.mdx | 1 + .../workers/vite-plugin/reference/api.mdx | 2 + .../browser-run/integration-methods.mdx | 3 +- src/content/release-notes/browser-run.yaml | 4 + 11 files changed, 256 insertions(+), 4 deletions(-) create mode 100644 src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx create mode 100644 src/content/docs/browser-run/cdp/vitest-browser-mode.mdx diff --git a/src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx b/src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx new file mode 100644 index 00000000000..c040743518c --- /dev/null +++ b/src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx @@ -0,0 +1,33 @@ +--- +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" }], + }, + }, +}); +``` + +To get started, refer to [Using with Vitest Browser Mode (CDP)](/browser-run/cdp/vitest-browser-mode/). diff --git a/src/content/docs/browser-run/cdp/index.mdx b/src/content/docs/browser-run/cdp/index.mdx index bc098f7d27d..3320ec2bbd4 100644 --- a/src/content/docs/browser-run/cdp/index.mdx +++ b/src/content/docs/browser-run/cdp/index.mdx @@ -13,7 +13,7 @@ import { Render } from "~/components"; The `/devtools` endpoints provide session management capabilities that follow the [Chrome DevTools Protocol (CDP)](https://chromedevtools.github.io/devtools-protocol/). These endpoints allow you to create persistent browser sessions, manage multiple tabs, and interact with browsers using CDP commands. This is useful for advanced automation, debugging, and remote browser control. -CDP endpoints can be accessed from any environment that supports WebSocket connections, including local development machines, external servers, and CI/CD pipelines. This means you can connect to Browser Run from Node.js scripts, Puppeteer, Playwright, or any CDP-compatible client. +CDP endpoints can be accessed from any environment that supports WebSocket connections, including local development machines, external servers, and CI/CD pipelines. This means you can connect to Browser Run from Node.js scripts, Puppeteer, Playwright, Vitest Browser Mode, or any CDP-compatible client. @@ -29,7 +29,7 @@ The browser sessions endpoints enable you to: - **Open, close, and list browser tabs (targets)** — Manage multiple debuggable targets (pages, iframes, etc.) within a single browser instance - **Connect via WebSocket to send CDP commands** — Automate browser actions programmatically - **View live browser sessions using Chrome DevTools UI** — Debug and inspect remote browser sessions visually -- **Integrate with existing CDP clients** — Use standard CDP clients like Puppeteer or custom WebSocket implementations +- **Integrate with existing CDP clients** — Use standard CDP clients like Puppeteer, Vitest Browser Mode, or custom WebSocket implementations ## How it works @@ -37,7 +37,7 @@ Once you acquire a browser session, you can interact with it in two ways: ### CDP over WebSocket -Connect to the WebSocket endpoint `/devtools/browser` to acquire a session and send [CDP commands](https://chromedevtools.github.io/devtools-protocol/) directly over the connection. This is the standard way to use CDP and works with any CDP client, including [Puppeteer](/browser-run/cdp/puppeteer/), [Playwright](/browser-run/cdp/playwright/), and [MCP clients](/browser-run/cdp/mcp-clients/). +Connect to the WebSocket endpoint `/devtools/browser` to acquire a session and send [CDP commands](https://chromedevtools.github.io/devtools-protocol/) directly over the connection. This is the standard way to use CDP and works with any CDP client, including [Puppeteer](/browser-run/cdp/puppeteer/), [Playwright](/browser-run/cdp/playwright/), [Vitest Browser Mode](/browser-run/cdp/vitest-browser-mode/), and [MCP clients](/browser-run/cdp/mcp-clients/). ### HTTP API diff --git a/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx b/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx new file mode 100644 index 00000000000..726ff96d6cc --- /dev/null +++ b/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx @@ -0,0 +1,200 @@ +--- +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). + + + +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: + + + +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: + +```txt title=".env" +CLOUDFLARE_ACCOUNT_ID="" +CLOUDFLARE_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: + + + +```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, + }, + instances: [{ browser: "chromium" }], + }, + }, +}); +``` + + + +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). + +## 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 = ` +
+ + + +

+
+ `; + + const input = document.querySelector("#name"); + const button = document.querySelector("button"); + const greeting = document.querySelector( + "[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!"); + }); +}); +``` + +You can also use Vitest Browser Mode APIs such as `expect.element(...).toMatchScreenshot()` for visual regression tests. When you update screenshots, keep `test.browser.api.allowWrite` set to `true`. + +## Run tests + +Run Vitest with the Browser Run config: + + + +To run fewer test files at the same time, lower `CLOUDFLARE_BROWSER_RUN_CONCURRENCY`: + + + +## 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, +}), +``` + + diff --git a/src/content/docs/browser-run/examples.mdx b/src/content/docs/browser-run/examples.mdx index d197904812d..5fcdf2c3820 100644 --- a/src/content/docs/browser-run/examples.mdx +++ b/src/content/docs/browser-run/examples.mdx @@ -134,6 +134,11 @@ Use [CDP](/browser-run/cdp/) to connect to Browser Run from any environment usin description="Run Puppeteer scripts against Browser Run from Node.js on your local machine, CI/CD, or any external server." href="/browser-run/cdp/puppeteer/" /> + Get started with Vitest diff --git a/src/content/docs/workers/testing/vitest-integration/index.mdx b/src/content/docs/workers/testing/vitest-integration/index.mdx index 2e037b3ba41..9efffd0e878 100644 --- a/src/content/docs/workers/testing/vitest-integration/index.mdx +++ b/src/content/docs/workers/testing/vitest-integration/index.mdx @@ -21,6 +21,8 @@ The Workers Vitest integration: - Leverages Vitest's hot-module reloading for near instant reruns. - Supports projects with multiple Workers. +This integration is separate from [Vitest Browser Mode with Browser Run](/browser-run/cdp/vitest-browser-mode/). Use the Workers Vitest integration for tests that need Workers runtime APIs or bindings. Use Browser Run for tests that need DOM APIs, user interactions, screenshots, or visual regression in real Chromium. + Write your first test diff --git a/src/content/docs/workers/testing/vitest-integration/write-your-first-test.mdx b/src/content/docs/workers/testing/vitest-integration/write-your-first-test.mdx index 9e64bb42b71..2b67b22ae19 100644 --- a/src/content/docs/workers/testing/vitest-integration/write-your-first-test.mdx +++ b/src/content/docs/workers/testing/vitest-integration/write-your-first-test.mdx @@ -187,5 +187,6 @@ Usually this is not a problem, but to run your Worker in a fresh environment tha ## Related resources - For more complex examples of testing using `@cloudflare/vitest-pool-workers`, refer to [Recipes](/workers/testing/vitest-integration/recipes/). +- To run Vitest Browser Mode tests in real hosted Chromium, refer to [Using with Vitest Browser Mode (CDP)](/browser-run/cdp/vitest-browser-mode/). - [Configuration API reference](/workers/testing/vitest-integration/configuration/) - [Test APIs reference](/workers/testing/vitest-integration/test-apis/) diff --git a/src/content/docs/workers/vite-plugin/reference/api.mdx b/src/content/docs/workers/vite-plugin/reference/api.mdx index b946c68e293..231d6653203 100644 --- a/src/content/docs/workers/vite-plugin/reference/api.mdx +++ b/src/content/docs/workers/vite-plugin/reference/api.mdx @@ -82,6 +82,8 @@ It accepts an optional `PluginConfig` parameter. Provide an object to configure a named tunnel or control whether the tunnel starts automatically. Press `t + Enter` to start or close the tunnel. Set `tunnel.autoStart` to `true` if you want the tunnel to open when Vite starts. + Vitest Browser Mode tests that run on Browser Run can use `tunnel.autoStart` to expose the local Vitest browser API to hosted Chromium. For a complete configuration, refer to [Using with Vitest Browser Mode (CDP)](/browser-run/cdp/vitest-browser-mode/). + ```ts import { defineConfig } from "vite"; diff --git a/src/content/partials/browser-run/integration-methods.mdx b/src/content/partials/browser-run/integration-methods.mdx index 0a5af1e218e..df1b9b69d5b 100644 --- a/src/content/partials/browser-run/integration-methods.mdx +++ b/src/content/partials/browser-run/integration-methods.mdx @@ -5,7 +5,7 @@ Browser Run offers two categories of integration methods: - **[Quick Actions](/browser-run/quick-actions/)**: Simple, stateless browser tasks like screenshots, PDFs, and scraping. No code deployment needed. -- **Browser Sessions**: Direct browser control via [Puppeteer](/browser-run/puppeteer/), [Playwright](/browser-run/playwright/), [CDP](/browser-run/cdp/), or [Stagehand](/browser-run/stagehand/). Deploy within Cloudflare Workers or connect from any environment via CDP. +- **Browser Sessions**: Direct browser control via [Puppeteer](/browser-run/puppeteer/), [Playwright](/browser-run/playwright/), [CDP](/browser-run/cdp/), [Vitest Browser Mode](/browser-run/cdp/vitest-browser-mode/), or [Stagehand](/browser-run/stagehand/). Deploy within Cloudflare Workers or connect from any environment via CDP. | Use case | Recommended | Why | | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- | @@ -15,5 +15,6 @@ Browser Run offers two categories of integration methods: | AI-powered data extraction | [JSON endpoint](/browser-run/quick-actions/json-endpoint/) | Structured data via natural language prompts | | Site-wide crawling | [Crawl endpoint](/browser-run/quick-actions/crawl-endpoint/) | Multi-page content extraction with async results | | AI agent browsing | [Playwright MCP](/browser-run/playwright/playwright-mcp/) or [CDP with MCP clients](/browser-run/cdp/mcp-clients/) | LLMs control browsers via MCP | +| Browser tests and visual regression | [Vitest Browser Mode](/browser-run/cdp/vitest-browser-mode/) | Real hosted Chromium for local or CI test suites | | Resilient scraping | [Stagehand](/browser-run/stagehand/) | AI finds elements by intent, not selectors | | Direct browser control from any environment | [CDP](/browser-run/cdp/) | WebSocket access from local machines, CI/CD, or external servers | diff --git a/src/content/release-notes/browser-run.yaml b/src/content/release-notes/browser-run.yaml index 726694e7707..64572d1ee38 100644 --- a/src/content/release-notes/browser-run.yaml +++ b/src/content/release-notes/browser-run.yaml @@ -3,6 +3,10 @@ link: "/browser-run/changelog/" productName: Browser Run productLink: "/browser-run/" entries: + - publish_date: "2026-07-03" + title: "Vitest Browser Mode provider for Browser Run" + description: |- + * You can now run [Vitest Browser Mode](/browser-run/cdp/vitest-browser-mode/) test suites on Browser Run hosted Chromium using `@cloudflare/vitest-browser-run-provider`. The provider connects Vitest's Playwright browser provider to Browser Run over CDP and supports parallel browser files in one hosted Chromium session. - publish_date: "2026-06-12" title: "New tutorial: Pre-render pages for crawlers" description: |- From edef0dbc760ac2713489ddd4e4ab073c2063f4b3 Mon Sep 17 00:00:00 2001 From: Brendan Irvine-Broque Date: Fri, 3 Jul 2026 23:42:31 -0700 Subject: [PATCH 2/6] [Browser Run] Clarify Vitest provider token setup --- ...026-07-03-vitest-browser-mode-provider.mdx | 2 ++ .../browser-run/cdp/vitest-browser-mode.mdx | 29 ++++++++++++------- src/content/release-notes/browser-run.yaml | 2 +- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx b/src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx index c040743518c..9eb7408fa4f 100644 --- a/src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx +++ b/src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx @@ -30,4 +30,6 @@ export default defineConfig({ }); ``` +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/). diff --git a/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx b/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx index 726ff96d6cc..ca153b1fcc7 100644 --- a/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx +++ b/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx @@ -28,13 +28,16 @@ Browser Run tests run in a real browser. If you need to test Worker handlers, bi Install Vitest Browser Mode, the Playwright browser provider, the Browser Run provider, and the Cloudflare Vite plugin: - + 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: +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="" @@ -156,7 +159,11 @@ You can also use Vitest Browser Mode APIs such as `expect.element(...).toMatchSc Run Vitest with the Browser Run config: - + To run fewer test files at the same time, lower `CLOUDFLARE_BROWSER_RUN_CONCURRENCY`: @@ -179,14 +186,14 @@ If your tests need separate browser processes for isolation, run separate Vitest `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/) | +| 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: diff --git a/src/content/release-notes/browser-run.yaml b/src/content/release-notes/browser-run.yaml index 64572d1ee38..58f7abce33e 100644 --- a/src/content/release-notes/browser-run.yaml +++ b/src/content/release-notes/browser-run.yaml @@ -6,7 +6,7 @@ entries: - publish_date: "2026-07-03" title: "Vitest Browser Mode provider for Browser Run" description: |- - * You can now run [Vitest Browser Mode](/browser-run/cdp/vitest-browser-mode/) test suites on Browser Run hosted Chromium using `@cloudflare/vitest-browser-run-provider`. The provider connects Vitest's Playwright browser provider to Browser Run over CDP and supports parallel browser files in one hosted Chromium session. + * You can now run [Vitest Browser Mode](/browser-run/cdp/vitest-browser-mode/) test suites on Browser Run hosted Chromium using `@cloudflare/vitest-browser-run-provider`. The provider connects Vitest's Playwright browser provider to Browser Run over CDP and supports parallel browser files in one hosted Chromium session. Set `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_API_TOKEN` before running tests. The token needs `Browser Rendering - Edit` permission. - publish_date: "2026-06-12" title: "New tutorial: Pre-render pages for crawlers" description: |- From 0fa63d67162c154adf13ad9056e5806d14aef4f8 Mon Sep 17 00:00:00 2001 From: Brendan Irvine-Broque Date: Fri, 3 Jul 2026 23:45:42 -0700 Subject: [PATCH 3/6] [Browser Run] Add Vitest screenshot guidance --- .../browser-run/cdp/vitest-browser-mode.mdx | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx b/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx index ca153b1fcc7..2501ef8a81a 100644 --- a/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx +++ b/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx @@ -91,7 +91,21 @@ export default defineConfig({ allowExec: true, allowWrite: true, }, - instances: [{ browser: "chromium" }], + expect: { + toMatchScreenshot: { + comparatorName: "pixelmatch", + comparatorOptions: { + threshold: 0.2, + allowedMismatchedPixelRatio: 0.005, + }, + }, + }, + instances: [ + { + browser: "chromium", + viewport: { width: 1280, height: 800 }, + }, + ], }, }, }); @@ -105,6 +119,8 @@ If you expose the Vitest browser API with a different tunnel, set `VITEST_BROWSE 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: @@ -153,7 +169,41 @@ describe("Browser Run Vitest test", () => { }); ``` -You can also use Vitest Browser Mode APIs such as `expect.element(...).toMatchScreenshot()` for visual regression tests. When you update screenshots, keep `test.browser.api.allowWrite` set to `true`. +## 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 = ` +
+
+

Build with Cloudflare

+

Run browser tests in hosted Chromium.

+
+
+ `; + + 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`: + + + +Review updated screenshots before committing them. Keep `test.browser.api.allowWrite` set to `true` when tests need to create or update screenshots. ## Run tests From 16c25c1a522765876f85f6807409399e0f57e03a Mon Sep 17 00:00:00 2001 From: Brendan Irvine-Broque Date: Sat, 4 Jul 2026 11:40:01 -0700 Subject: [PATCH 4/6] [Browser Run] Address Vitest provider docs feedback --- .../browser-run/cdp/vitest-browser-mode.mdx | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx b/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx index 2501ef8a81a..6abe9641bfb 100644 --- a/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx +++ b/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx @@ -11,12 +11,10 @@ products: 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). +Use [Vitest Browser Mode](https://vitest.dev/guide/browser/) 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). -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/) @@ -33,11 +31,9 @@ Install Vitest Browser Mode, the Playwright browser provider, the Browser Run pr 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`: +Set the Browser Run credentials in your shell, CI environment, or a `.env` file that is ignored by Git. By default, `browserRunCdp()` reads `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_API_TOKEN`: ```txt title=".env" CLOUDFLARE_ACCOUNT_ID="" @@ -117,7 +113,26 @@ The Cloudflare Vite plugin starts a tunnel and sets `CLOUDFLARE_TUNNEL_URL`. The 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). +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. + +By default, `tunnel: { autoStart: true }` creates a short-lived [Quick Tunnel](/tunnel/setup/#quick-tunnels-development). Anyone with the tunnel URL can reach your dev server while the tunnel is active. Use this mode for local runs only after you review what the dev server exposes. For more information, refer to [Share a local dev server](/workers/local-development/local-dev-tunnels/#security-considerations). + +For a stable hostname or stricter access control, use a [named tunnel](/tunnel/setup/#create-a-tunnel) with the Cloudflare Vite plugin: + + + +```ts +cloudflare({ + tunnel: { + name: "vitest-browser-run", + autoStart: true, + }, +}), +``` + + + +You can protect the named tunnel hostname by adding a [self-hosted Access application](/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app/). For non-interactive test runs, use a [Service Auth policy](/cloudflare-one/access-controls/policies/#service-auth) and an [Access service token](/cloudflare-one/access-controls/service-credentials/service-tokens/). Browser Run must be able to load the Vitest browser runner through that Access policy; service tokens authenticate HTTP requests with the `CF-Access-Client-Id` and `CF-Access-Client-Secret` headers. 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. From ec96060bd31cfbf8c0f29950e411bd896af26cf8 Mon Sep 17 00:00:00 2001 From: Brendan Irvine-Broque Date: Sat, 4 Jul 2026 11:43:00 -0700 Subject: [PATCH 5/6] [Browser Run] Expand Vitest changelog example --- ...026-07-03-vitest-browser-mode-provider.mdx | 19 +++++++++++++++++++ .../vitest-integration/browser-mode.mdx | 10 ++++++++++ .../testing/vitest-integration/recipes.mdx | 5 +++-- 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 src/content/docs/workers/testing/vitest-integration/browser-mode.mdx diff --git a/src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx b/src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx index 9eb7408fa4f..7b7ad37f789 100644 --- a/src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx +++ b/src/content/changelog/browser-run/2026-07-03-vitest-browser-mode-provider.mdx @@ -30,6 +30,25 @@ export default defineConfig({ }); ``` +After configuring the provider, you can write Vitest Browser Mode tests that run in Browser Run hosted Chromium. For example, the following test captures and compares 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 = ` +
+
+

Build with Cloudflare

+
+
+ `; + + await expect.element(page.getByTestId("hero")).toMatchScreenshot("hero"); +}); +``` + 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/). diff --git a/src/content/docs/workers/testing/vitest-integration/browser-mode.mdx b/src/content/docs/workers/testing/vitest-integration/browser-mode.mdx new file mode 100644 index 00000000000..9ec2c0c68b6 --- /dev/null +++ b/src/content/docs/workers/testing/vitest-integration/browser-mode.mdx @@ -0,0 +1,10 @@ +--- +pcx_content_type: navigation +title: Browser Mode with Browser Run +description: Run Vitest Browser Mode tests in hosted Chromium with Browser Run. +external_link: /browser-run/cdp/vitest-browser-mode/ +sidebar: + order: 3.5 +products: + - workers +--- diff --git a/src/content/docs/workers/testing/vitest-integration/recipes.mdx b/src/content/docs/workers/testing/vitest-integration/recipes.mdx index 79fb21b23ea..8045e476b3d 100644 --- a/src/content/docs/workers/testing/vitest-integration/recipes.mdx +++ b/src/content/docs/workers/testing/vitest-integration/recipes.mdx @@ -10,8 +10,9 @@ products: - workers --- -Recipes are examples that help demonstrate how to write unit tests and integration tests for Workers projects using the [`@cloudflare/vitest-pool-workers`](https://www.npmjs.com/package/@cloudflare/vitest-pool-workers) package. +Recipes are examples that help demonstrate how to write unit tests and integration tests for Workers projects using the [`@cloudflare/vitest-pool-workers`](https://www.npmjs.com/package/@cloudflare/vitest-pool-workers) package. For tests that need real browser APIs, use Vitest Browser Mode with Browser Run. +- [Browser tests and visual regression tests with Vitest Browser Mode and Browser Run](/browser-run/cdp/vitest-browser-mode/) - [Basic unit and integration tests for Workers using `exports.default`](https://github.com/cloudflare/workers-sdk/tree/main/fixtures/vitest-pool-workers-examples/basics-unit-integration-self) - [Basic unit and integration tests for Pages Functions using `exports.default`](https://github.com/cloudflare/workers-sdk/tree/main/fixtures/vitest-pool-workers-examples/pages-functions-unit-integration-self) - [Basic integration tests using an auxiliary Worker](https://github.com/cloudflare/workers-sdk/tree/main/fixtures/vitest-pool-workers-examples/basics-integration-auxiliary) @@ -30,4 +31,4 @@ Recipes are examples that help demonstrate how to write unit tests and integrati - [Resolving modules with Vite Dependency Pre-Bundling](https://github.com/cloudflare/workers-sdk/tree/main/fixtures/vitest-pool-workers-examples/module-resolution) - [Mocking Workers AI and Vectorize bindings in unit tests](https://github.com/cloudflare/workers-sdk/tree/main/fixtures/vitest-pool-workers-examples/ai-vectorize) - [Tests using the Images binding](https://github.com/cloudflare/workers-sdk/tree/main/fixtures/vitest-pool-workers-examples/images) -- [Tests mocking Workers Assets](https://github.com/cloudflare/workers-sdk/tree/main/fixtures/vitest-pool-workers-examples/workers-assets) \ No newline at end of file +- [Tests mocking Workers Assets](https://github.com/cloudflare/workers-sdk/tree/main/fixtures/vitest-pool-workers-examples/workers-assets) From 22a594cc5a9a3fa84f5cf9160b917cba73f6f4b8 Mon Sep 17 00:00:00 2001 From: "ask-bonk[bot]" Date: Sat, 4 Jul 2026 19:03:32 +0000 Subject: [PATCH 6/6] Fixed title & moved cross-link per review Co-authored-by: irvinebroque --- src/content/docs/browser-run/cdp/vitest-browser-mode.mdx | 2 +- src/content/docs/browser-run/playwright/index.mdx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx b/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx index 6abe9641bfb..16ceee593f2 100644 --- a/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx +++ b/src/content/docs/browser-run/cdp/vitest-browser-mode.mdx @@ -1,6 +1,6 @@ --- pcx_content_type: how-to -title: Using with Vitest Browser Mode (CDP) +title: Use Vitest Browser Mode (CDP) description: Run Vitest Browser Mode tests on Browser Run using hosted Chromium over the Chrome DevTools Protocol. sidebar: order: 5 diff --git a/src/content/docs/browser-run/playwright/index.mdx b/src/content/docs/browser-run/playwright/index.mdx index dc75ffc3567..eb4572a5c4b 100644 --- a/src/content/docs/browser-run/playwright/index.mdx +++ b/src/content/docs/browser-run/playwright/index.mdx @@ -156,8 +156,6 @@ 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/). - ```ts import { launch } from "@cloudflare/playwright"; import { expect } from "@cloudflare/playwright/test"; @@ -192,6 +190,8 @@ export default { }; ``` +To run Vitest Browser Mode tests against Browser Run hosted Chromium, refer to [Use Vitest Browser Mode (CDP)](/browser-run/cdp/vitest-browser-mode/). + ### Storage state Playwright supports [storage state](https://playwright.dev/docs/api/class-browsercontext#browsercontext-storage-state) to obtain and persist cookies and other storage data. In this example, you will use storage state to persist cookies and other storage data in [Workers KV](/kv).