Skip to content

feat: add browser mode with Playwright provider#16173

Closed
ahnpnl wants to merge 1 commit into
jestjs:mainfrom
ahnpnl:feat/browser-mode
Closed

feat: add browser mode with Playwright provider#16173
ahnpnl wants to merge 1 commit into
jestjs:mainfrom
ahnpnl:feat/browser-mode

Conversation

@ahnpnl

@ahnpnl ahnpnl commented May 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds Browser Mode to Jest — run tests in real browsers (Chromium, Firefox, WebKit) via Playwright, with full DOM APIs, real event handling, and visual regression testing.

Tests execute as native ESM inside a Vite dev server, eliminating the gap between jsdom simulation and real browser behavior.

New Packages

@jest/browser

The core browser mode package. Provides:

  • BrowserTestRunner — Jest test runner that launches browsers
  • Vite dev server with virtual modules (@jest/globals, @jest/browser)
  • Client runtime (test runner, expect, mocks, fake timers, error catcher)
  • birpc WebSocket server for Node↔Browser RPC
  • Screenshot comparison (toMatchScreenshot)
  • Provider plugin system (defineBrowserProvider, resolveProvider)
  • page.extend() API for framework component testing plugins

@jest/browser-playwright

Playwright provider plugin (extracted, following Vitest's pattern). Provides:

  • PlaywrightBrowserProvider — manages browser/context/page lifecycle
  • Command registry for userEvent actions (click, type, fill, hover, etc.)
  • Trace recording support
  • Can be swapped for other providers in the future (WebDriverIO, etc.)

Architecture

┌───────────────────────────────────────────────────────────────────┐
│                         Node.js (Jest)                             │
│                                                                   │
│  ┌────────────────┐  ┌────────────────┐  ┌────────────────────┐  │
│  │ BrowserTest    │  │  Vite Dev      │  │ @jest/browser-     │  │
│  │ Runner         │─▶│  Server        │  │ playwright         │  │
│  │                │  │                │  │                    │  │
│  │ • parallel/    │  │ • Virtual mods │  │ • Browser launch   │  │
│  │   serial queue │  │ • HMR disabled │  │ • Context/Page     │  │
│  │ • per-file run │  │ • ESM serving  │  │ • Command handlers │  │
│  └────────────────┘  └────────┬───────┘  └─────────┬──────────┘  │
│                               │                     │             │
│                        ┌──────┴──────┐              │             │
│                        │  birpc WS   │◀─────────────┘             │
│                        │  Server     │  (triggerCommand dispatch)  │
│                        └──────┬──────┘                            │
└───────────────────────────────┼───────────────────────────────────┘
                                │ WebSocket (birpc + flatted)
                                ▼
┌───────────────────────────────────────────────────────────────────┐
│                      Browser (Chromium/Firefox/WebKit)             │
│                                                                   │
│  ┌─────────────────────────────────────────────────────────────┐  │
│  │                      Test Page                               │  │
│  │                                                             │  │
│  │  @jest/globals (virtual module)                             │  │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐  │  │
│  │  │  Runner  │ │  Expect  │ │  Mocks   │ │ Fake Timers  │  │  │
│  │  │ describe │ │ matchers │ │ fn/spyOn │ │ advance/run  │  │  │
│  │  │ it/test  │ │ .not     │ │ mock impl│ │ useFake/Real │  │  │
│  │  └──────────┘ └──────────┘ └──────────┘ └──────────────┘  │  │
│  │                                                             │  │
│  │  @jest/browser (virtual module)                             │  │
│  │  ┌──────────────┐ ┌────────────┐ ┌──────────┐             │  │
│  │  │  userEvent   │ │    page    │ │ commands │             │  │
│  │  │ click/type/  │ │ .extend() │ │ RPC proxy│             │  │
│  │  │ hover/fill   │ │ .screenshot│ │          │             │  │
│  │  │  (RPC→PW)    │ │ .locator  │ │          │             │  │
│  │  └──────────────┘ └────────────┘ └──────────┘             │  │
│  │                                                             │  │
│  │  ┌──────────────────────────────────────────────────────┐  │  │
│  │  │  Error Catcher (window.onerror + unhandledrejection) │  │  │
│  │  └──────────────────────────────────────────────────────┘  │  │
│  └─────────────────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────────────────┘

Key design decisions:

  • birpc over WebSocket for Node↔Browser RPC (same wire protocol as Vitest)
  • Virtual modules resolved by Vite plugin — no bundling needed
  • Provider plugin pattern@jest/browser-playwright implements BrowserProvider interface, registered via defineBrowserProvider()
  • page.extend() enables framework plugins (e.g. jest-browser-vue adds page.render())
  • triggerCommand dispatch — browser calls RPC → node routes to provider's command registry

Configuration Options

All options under browserMode in Jest config:

Option Type Default Description
enabled boolean false Enable browser mode
name 'chromium'|'firefox'|'webkit' 'chromium' Browser to launch
headless boolean true Headless mode
provider string 'playwright' Automation provider
providerOptions object {} Playwright launch options
viewport {width, height} {414, 896} Default viewport
instances array Multi-browser configs
screenshotDirectory string '__screenshots__' Screenshot storage path
screenshotFailures boolean true Auto-screenshot on failure
connectTimeout number 60000 Browser WS connect timeout (ms)
trackUnhandledErrors boolean true Catch unhandled errors/rejections
fileParallelism boolean true Run test files in parallel
trace 'off'|'on'|'retain-on-failure' 'off' Playwright trace recording
api number|{port?, host?} random Vite server port/host
testerHtmlPath string built-in Custom HTML template path
expect {toMatchScreenshot: {threshold?, maxDiffPixelRatio?, maxDiffPixels?}} {threshold: 0.1} Screenshot comparison config

APIs

From @jest/browser

userEvent — Real browser interactions via Playwright automation:

Method Description
click(element) Click element
dblClick(element) Double-click element
type(element, text) Type character by character
fill(element, text) Fill input (fast)
clear(element) Clear input value
hover(element) Hover over element
unhover(element) Move pointer away
tab() Press Tab key
keyboard(keys) Press key combination
selectOptions(element, values) Select dropdown options

page — Page interactions and framework extension point:

Method Description
page.screenshot(options?) Capture page screenshot
page.extend(methods) Add custom methods (for framework plugins)
page.elementLocator(el) Wrap element with locator API

commands — Execute Node-side functions via RPC:

  • commands.removeFile(path) — delete a file

server — Environment metadata:

  • server.browser — current browser name
  • server.platform — OS platform

Screenshot matching:

await expect(element).toMatchScreenshot({ name: 'button-hover' });

From @jest/browser-playwright

Provider plugin for Playwright. Can be used directly for custom setups:

import {playwright, PlaywrightBrowserProvider, defineBrowserProvider} from '@jest/browser-playwright';
Export Description
playwright() Factory function — returns a provider plugin instance
PlaywrightBrowserProvider Class managing browser/context/page lifecycle
defineBrowserProvider(plugin) Helper to create custom provider plugins (re-exported from @jest/browser)

Custom provider example:

import {defineBrowserProvider} from '@jest/browser-playwright';

export default defineBrowserProvider({
  name: 'my-provider',
  setup: async (options) => {
    // launch browser, return provider with getCommands()
  },
});

Test Coverage

  • 35 e2e tests across 11 suites
  • Unit tests for provider, runner parallelism, screenshot config, error catcher, page.extend
  • Inner browser tests: basic, DOM, userEvent, timers, mocking, viewport, lifecycle, console forwarding

Documentation

Split into 5 pages under Guides > Browser Mode:

  1. Overview & Getting Started
  2. Configuration Reference
  3. API Reference
  4. Visual Regression (Screenshots)
  5. Multi-Browser Testing

@netlify

netlify Bot commented May 12, 2026

Copy link
Copy Markdown

Deploy Preview for jestjs ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 5105609
🔍 Latest deploy log https://app.netlify.com/projects/jestjs/deploys/6a054c3018a8cd00084f1560
😎 Deploy Preview https://deploy-preview-16173--jestjs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@ahnpnl
ahnpnl force-pushed the feat/browser-mode branch 4 times, most recently from 3ebbf6e to 1d9036d Compare May 12, 2026 18:50
@pkg-pr-new

pkg-pr-new Bot commented May 12, 2026

Copy link
Copy Markdown

Open in StackBlitz

babel-jest

npm i https://pkg.pr.new/jestjs/jest/babel-jest@16173

babel-plugin-jest-hoist

npm i https://pkg.pr.new/jestjs/jest/babel-plugin-jest-hoist@16173

babel-preset-jest

npm i https://pkg.pr.new/jestjs/jest/babel-preset-jest@16173

create-jest

npm i https://pkg.pr.new/jestjs/jest/create-jest@16173

@jest/diff-sequences

npm i https://pkg.pr.new/jestjs/jest/@jest/diff-sequences@16173

expect

npm i https://pkg.pr.new/jestjs/jest/expect@16173

@jest/expect-utils

npm i https://pkg.pr.new/jestjs/jest/@jest/expect-utils@16173

jest

npm i https://pkg.pr.new/jestjs/jest@16173

@jest/browser

npm i https://pkg.pr.new/jestjs/jest/@jest/browser@16173

@jest/browser-playwright

npm i https://pkg.pr.new/jestjs/jest/@jest/browser-playwright@16173

jest-changed-files

npm i https://pkg.pr.new/jestjs/jest/jest-changed-files@16173

jest-circus

npm i https://pkg.pr.new/jestjs/jest/jest-circus@16173

jest-cli

npm i https://pkg.pr.new/jestjs/jest/jest-cli@16173

jest-config

npm i https://pkg.pr.new/jestjs/jest/jest-config@16173

@jest/console

npm i https://pkg.pr.new/jestjs/jest/@jest/console@16173

@jest/core

npm i https://pkg.pr.new/jestjs/jest/@jest/core@16173

@jest/create-cache-key-function

npm i https://pkg.pr.new/jestjs/jest/@jest/create-cache-key-function@16173

jest-diff

npm i https://pkg.pr.new/jestjs/jest/jest-diff@16173

jest-docblock

npm i https://pkg.pr.new/jestjs/jest/jest-docblock@16173

jest-each

npm i https://pkg.pr.new/jestjs/jest/jest-each@16173

@jest/environment

npm i https://pkg.pr.new/jestjs/jest/@jest/environment@16173

jest-environment-jsdom

npm i https://pkg.pr.new/jestjs/jest/jest-environment-jsdom@16173

@jest/environment-jsdom-abstract

npm i https://pkg.pr.new/jestjs/jest/@jest/environment-jsdom-abstract@16173

jest-environment-node

npm i https://pkg.pr.new/jestjs/jest/jest-environment-node@16173

@jest/expect

npm i https://pkg.pr.new/jestjs/jest/@jest/expect@16173

@jest/fake-timers

npm i https://pkg.pr.new/jestjs/jest/@jest/fake-timers@16173

@jest/get-type

npm i https://pkg.pr.new/jestjs/jest/@jest/get-type@16173

@jest/globals

npm i https://pkg.pr.new/jestjs/jest/@jest/globals@16173

jest-haste-map

npm i https://pkg.pr.new/jestjs/jest/jest-haste-map@16173

jest-jasmine2

npm i https://pkg.pr.new/jestjs/jest/jest-jasmine2@16173

jest-leak-detector

npm i https://pkg.pr.new/jestjs/jest/jest-leak-detector@16173

jest-matcher-utils

npm i https://pkg.pr.new/jestjs/jest/jest-matcher-utils@16173

jest-message-util

npm i https://pkg.pr.new/jestjs/jest/jest-message-util@16173

jest-mock

npm i https://pkg.pr.new/jestjs/jest/jest-mock@16173

@jest/pattern

npm i https://pkg.pr.new/jestjs/jest/@jest/pattern@16173

jest-phabricator

npm i https://pkg.pr.new/jestjs/jest/jest-phabricator@16173

jest-regex-util

npm i https://pkg.pr.new/jestjs/jest/jest-regex-util@16173

@jest/reporters

npm i https://pkg.pr.new/jestjs/jest/@jest/reporters@16173

jest-resolve

npm i https://pkg.pr.new/jestjs/jest/jest-resolve@16173

jest-resolve-dependencies

npm i https://pkg.pr.new/jestjs/jest/jest-resolve-dependencies@16173

jest-runner

npm i https://pkg.pr.new/jestjs/jest/jest-runner@16173

jest-runtime

npm i https://pkg.pr.new/jestjs/jest/jest-runtime@16173

@jest/schemas

npm i https://pkg.pr.new/jestjs/jest/@jest/schemas@16173

jest-snapshot

npm i https://pkg.pr.new/jestjs/jest/jest-snapshot@16173

@jest/snapshot-utils

npm i https://pkg.pr.new/jestjs/jest/@jest/snapshot-utils@16173

@jest/source-map

npm i https://pkg.pr.new/jestjs/jest/@jest/source-map@16173

@jest/test-result

npm i https://pkg.pr.new/jestjs/jest/@jest/test-result@16173

@jest/test-sequencer

npm i https://pkg.pr.new/jestjs/jest/@jest/test-sequencer@16173

@jest/transform

npm i https://pkg.pr.new/jestjs/jest/@jest/transform@16173

@jest/types

npm i https://pkg.pr.new/jestjs/jest/@jest/types@16173

jest-util

npm i https://pkg.pr.new/jestjs/jest/jest-util@16173

jest-validate

npm i https://pkg.pr.new/jestjs/jest/jest-validate@16173

jest-watcher

npm i https://pkg.pr.new/jestjs/jest/jest-watcher@16173

jest-worker

npm i https://pkg.pr.new/jestjs/jest/jest-worker@16173

pretty-format

npm i https://pkg.pr.new/jestjs/jest/pretty-format@16173

commit: 5105609

@ahnpnl
ahnpnl force-pushed the feat/browser-mode branch 15 times, most recently from 26557e4 to 35a45e4 Compare May 14, 2026 04:00
Adds jest-browser package that runs tests in real browsers via Vite dev
server and Playwright. Tests execute as native ESM in Chromium/Firefox/WebKit
with full DOM APIs, real event handling, and visual regression testing.

Architecture:
- Vite serves test files as ESM with virtual @jest/globals module
- birpc over WebSocket for Node<->Browser communication
- Playwright manages browser lifecycle (launch, context, page)
- Client runtime: test runner, expect, mocks, fake timers
- Provider plugin system (@jest/browser-playwright extractable)
- page.extend() API for framework component testing

Config options:
- viewport, headless, provider, providerOptions, instances
- screenshotFailures, screenshotDirectory, connectTimeout
- trackUnhandledErrors, fileParallelism, trace
- api (port/host), testerHtmlPath, expect (screenshot config)

Includes:
- jest-browser + jest-browser-playwright packages
- Full e2e test suite (35 tests across 11 suites)
- Unit tests for provider, runner, screenshot, error-catcher, page
- Multi-page documentation (guide, config, API, screenshots, multi-browser)
@ahnpnl
ahnpnl force-pushed the feat/browser-mode branch from 35a45e4 to 5105609 Compare May 14, 2026 04:14
@ahnpnl ahnpnl closed this May 14, 2026
@ahnpnl
ahnpnl deleted the feat/browser-mode branch May 14, 2026 05:41
@github-actions

Copy link
Copy Markdown

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Jun 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant