Skip to content

Conversation

@fi3ework
Copy link
Member

@fi3ework fi3ework commented Dec 11, 2025

Summary

Add browser mode support for Rstest, allowing tests to run in real browser environments (Chromium/WebKit) via Playwright.

TODO:

  • documentation
  • framework dedicated wrapper (react/vue/etc)

new configurations:

New: browser config

  • browser.enabled - Enable browser mode (default: false)
  • browser.provider - Browser driver provider: 'playwright' (default: 'playwright')
  • browser.browser - Browser to use: 'chromium' | 'firefox' | 'webkit' (default: 'chromium')
  • browser.headless - Run in headless mode (default: inferred from CI, true in CI, false otherwise)
  • browser.port - Port for browser mode dev server (default: random available port)

New Packages

  • @rstest/browser - Host controller managing Rsbuild dev server, Playwright, and WebSocket RPC
  • @rstest/browser-ui - React-based container UI (React 19 + Tailwind + Ant Design)

Architecture

┌─────────────────────────────────────────────────────────────────────────────────┐
│  HOST (Node.js) - @rstest/browser/hostController.ts                             │
│                                                                                 │
│  ┌──────────────────────┐   ┌───────────────────┐   ┌────────────────────────┐  │
│  │   Rsbuild Dev Server │   │   Playwright      │   │  WebSocket Server      │  │
│  │   (port: N)          │   │   (Chromium/      │   │  (port: N+1)           │  │
│  │                      │   │    WebKit)        │   │                        │  │
│  │  • Bundle tests      │   │                   │   │  birpc protocol:       │  │
│  │  • Lazy compilation  │   │  • Launch browser │   │  • rerunTest()         │  │
│  │  • Virtual manifest  │   │  • Create context │   │  • getTestFiles()      │  │
│  │  • Serve HTML pages  │   │  • Manage pages   │   │  • onTestFileStart()   │  │
│  │  • HMR (watch mode)  │   │                   │   │  • onTestCaseResult()  │  │
│  └──────────────────────┘   └───────────────────┘   │  • onTestFileComplete()│  │
│           │                         │               │  • snapshot file ops   │  │
│           │ serves                  │ controls      └────────────────────────┘  │
│           ▼                         ▼                           ▲               │
│  ┌──────────────────────────────────────────────────────────────│───────────────┤
│  │  /container.html  (Container Page)                           │               │
│  │  /runner.html     (Runner iframe)                            │ WebSocket     │
│  └──────────────────────────────────────────────────────────────│───────────────┤
└─────────────────────────────────────────────────────────────────│───────────────┘
                                                                  │
┌─────────────────────────────────────────────────────────────────│───────────────┐
│  BROWSER (Chromium/WebKit via Playwright)                       │               │
│                                                                 │               │
│  ┌─────────────────────────────────────────────────────────────────────────────┐│
│  │  Container Page (@rstest/browser-ui)                         │              ││
│  │  URL: http://localhost:N/container.html                      │              ││
│  │                                                              │              ││
│  │  ┌─────────────────────────┐  ┌───────────────────────────┐  │              ││
│  │  │  Sidebar               │  │  Preview Panel            │  │              ││
│  │  │  • Test file tree      │  │  • Active test iframe     │◄─┘ (birpc)     ││
│  │  │  • Status indicators   │  │  • Reload controls        │                ││
│  │  │  • Filter/search       │  │                           │                ││
│  │  │  • Rerun buttons       │  │  ┌───────────────────────┐│                ││
│  │  │                        │  │  │  <iframe>             ││                ││
│  │  │                        │  │  │  Runner Page          │◄── postMessage ││
│  │  │                        │  │  │  /runner.html?testFile│ │                ││
│  │  └────────────────────────┘  │  └───────────────────────┘│                ││
│  │                              └───────────────────────────┘                ││
│  └─────────────────────────────────────────────────────────────────────────────┘│
│                                         │                                       │
│                                         │ postMessage                           │
│                                         ▼                                       │
│  ┌─────────────────────────────────────────────────────────────────────────────┐│
│  │  Runner iframe (@rstest/browser/client/entry.ts)                            ││
│  │  URL: http://localhost:N/runner.html?testFile=/path/to/test.ts              ││
│  │                                                                             ││
│  │  • Receives config from Container via postMessage                           ││
│  │  • Loads test via @rstest/browser-manifest (virtual module)                 ││
│  │  • Executes tests using @rstest/core runtime                                ││
│  │  • Intercepts console.log → forwards to Host                                ││
│  │  • Snapshot ops → RPC request to Container → forwarded to Host              ││
│  │  • Reports results back via postMessage → Container → Host                  ││
│  └─────────────────────────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────────────────────────┘

Communication Flow

1. Test Execution Flow:
   Host                    Container (UI)              Runner (iframe)
     │                          │                           │
     │──── WebSocket ──────────►│                           │
     │     testFiles update     │                           │
     │                          │──── postMessage ─────────►│
     │                          │     RSTEST_CONFIG         │
     │                          │                           │── execute tests
     │                          │◄─── postMessage ──────────│
     │                          │     file-start/case-result│
     │◄──── WebSocket ──────────│                           │
     │      onTestCaseResult    │                           │

2. Snapshot Flow (browser has no filesystem access):
   Runner                  Container                   Host
     │                          │                         │
     │── snapshot-rpc-request ─►│                         │
     │   (postMessage)          │── resolveSnapshotPath ─►│ (reads/writes
     │                          │   readSnapshotFile      │  actual files)
     │                          │   saveSnapshotFile      │
     │◄─ snapshot-response ─────│◄────── result ──────────│

Key Features

  • Real browser environment - Tests run in Chromium/WebKit via Playwright
  • Lazy compilation - Rsbuild builds test files on-demand
  • Isolated iframe execution - Each test file runs in its own iframe for isolation
  • Full snapshot support - File and inline snapshots via RPC to host (browser has no fs)
  • Console forwarding - console.log in tests shows in terminal
  • Source map support - Proper stack traces for browser errors
  • Watch mode - File changes trigger HMR and automatic re-runs
  • Multi-project support - Run browser and node tests together via projects config

Changes

  • Add browser config option (browser.enabled, browser.browser, browser.headless)
  • Add projects config for multi-project workspaces
  • Add @rstest/browser and @rstest/browser-ui packages
  • Add comprehensive e2e tests (e2e/browser-mode/)
  • Add examples (examples/browser, examples/browser-projects)

UI to show the interaction:

iShot_2025-12-11_11.15.14.mp4

the updated UI.

iShot_2026-01-05_11.08.16.mp4

Related Links

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).

@netlify
Copy link

netlify bot commented Dec 11, 2025

Deploy Preview for rstest-dev ready!

Name Link
🔨 Latest commit 0ba6f9b
🔍 Latest deploy log https://app.netlify.com/projects/rstest-dev/deploys/695b6415f940cb000842e9cc
😎 Deploy Preview https://deploy-preview-757--rstest-dev.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.

@fi3ework fi3ework force-pushed the browser-mode branch 23 times, most recently from ebeed81 to eb7ad24 Compare January 4, 2026 11:13
@fi3ework fi3ework marked this pull request as ready for review January 5, 2026 03:12
Copilot AI review requested due to automatic review settings January 5, 2026 03:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces comprehensive browser-mode testing capability to Rstest, allowing tests to run in actual browser environments (Chromium, Firefox, or WebKit) via Playwright. The implementation includes a React-based test UI, WebSocket-based RPC communication between host and browser, and support for browser-specific features like snapshots.

Key Changes:

  • New @rstest/browser package for browser test orchestration using Playwright
  • New @rstest/browser-ui package with React UI for visualizing browser test execution
  • Core package enhancements to support browser mode configuration and runtime
  • Browser runtime that shares test execution logic with Node.js mode
  • WebSocket RPC for host-browser communication

Reviewed changes

Copilot reviewed 161 out of 167 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
scripts/dictionary.txt Added spelling dictionary entries for new terms (fastpaths, noglobstar)
rstest.config.ts Excluded browser-projects from test discovery
packages/vscode/tests/fixtures/fixtures.code-workspace Formatting changes (whitespace normalization)
packages/vscode/AGENTS.md Restructured documentation with clearer architecture and command sections
packages/coverage-istanbul/package.json Added typecheck script
packages/coverage-istanbul/AGENTS.md New documentation for coverage package
packages/core/tests/tsconfig.json Added rstestEnv.d.ts to include list
packages/core/tests/core/rstest.test.ts Mocked std-env for consistent snapshots
packages/core/tests/core/rsbuild.test.ts Updated snapshots with browser config defaults
packages/core/tests/__snapshots__/*.snap Updated snapshots to include browser configuration
packages/core/src/types/config.ts Added BrowserModeConfig and NormalizedBrowserModeConfig types
packages/core/src/runtime/worker/env/jsdom.ts Minor formatting change
packages/core/src/runtime/worker/console.ts Updated import path (utils → utils/helper)
packages/core/src/runtime/util.ts Added browser-compatible formatTemplate, updated checkPkgInstalled
packages/core/src/runtime/runner/*.ts Updated import paths for utils refactoring
packages/core/src/runtime/api/*.ts Import path updates and React Fast Refresh compatibility
packages/core/src/env.d.ts Added DOM types and module declarations for browser package
packages/core/src/core/runTests.ts Separated browser and node mode test execution
packages/core/src/core/rsbuild.ts Filtered browser projects from node mode builds
packages/core/src/core/listTests.ts Added browser test collection via listBrowserTests
packages/core/src/core/browserLoader.ts Browser package loader with version validation
packages/core/src/config.ts Browser config merging and defaults
packages/core/src/cli/*.ts Added --browser CLI flag
packages/core/src/browserRuntime.ts Browser-safe runtime exports
packages/core/src/browser.ts Internal exports for browser package
packages/core/rslib.config.ts Added browser and browser-runtime entry points
packages/core/package.json New exports, dependencies (playwright-core, ws, sirv, etc.)
packages/core/LICENSE.md Added url-extras license
packages/core/AGENTS.md New documentation for core package
packages/browser/** Complete new package for browser mode orchestration
packages/browser-ui/** Complete new package for browser test UI

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

let isNewPage = false;

if (isWatchMode && runtime.containerPage && runtime.containerContext) {
containerContext = runtime.containerContext;
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value assigned to containerContext here is unused.

Copilot uses AI. Check for mistakes.
@9aoy
Copy link
Collaborator

9aoy commented Jan 5, 2026

🎉

rerun test on watch

use virtual module

isolated pages

lazy compilation

iframe

rebase

type check

react

@rstest/browser-ui

tailwind

allow chrome

better UI

refine

antd

rerun

remove canUseRpc

nested tree

add e2e

fix globals

fix e2e

rewrite watch

ui

rename ui

update all AGENTS.md

basic react e2e

support forward console.log to stdio

clean e2e ports

refine ui  RSTEST_CONTAINER_DEV_SERVER=http://localhost:7392/

remove exposeBinding

merge more configs

support projects

rebase

projects should run separately, diversion browser/node mode in runTests

fix list command with browser mode

ui: polish

snapshot

inline snapshot

rebase

chore

@rstest/browser

support provider and browser

lint

polish readme

win32

fix: handle Windows EBUSY error in watch.test.ts cleanup

fix: only tolerate cleanup errors on Windows

fix: handle Windows EBUSY error in prepareFixtures cleanup

fix: increase CI test timeout to 30s for slower environments

fix: use dynamic port for watch fixture to avoid conflicts

Revert "fix: use dynamic port for watch fixture to avoid conflicts"

This reverts commit 517bf8f.

clean

fix fast refresh vs proxy race

mock headless

clean

cr
@fi3ework fi3ework merged commit 6e22145 into main Jan 5, 2026
15 checks passed
@fi3ework fi3ework deleted the browser-mode branch January 5, 2026 07:36
@9aoy 9aoy mentioned this pull request Jan 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants