> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# Browser mode (experimental)

Rstest provides Browser Mode, allowing you to run tests in a real browser instead of simulated environments like jsdom or happy-dom.


## What is browser Mode?

Browser Mode uses [Playwright](https://playwright.dev/) to execute your test code in real browsers (Chromium, Firefox, or WebKit). This means your tests run with the exact same browser APIs and behaviors as in production.

:::note
Like Node mode, Browser Mode fails a test file when an unhandled error or promise rejection escapes it — even if every test in the file passed. If a rejection is expected, `await` the promise or attach a handler inside the test so it does not leak to the page.
:::

## Locator API

Browser Mode now supports a Playwright-style Locator workflow: you can use `page.getBy*` for element queries, then use `expect.element(locator)` for auto-waiting assertions.

This approach is ideal when you want semantic queries (role/label/text) and chainable assertions, making component tests and DOM tests closer to real user interaction semantics.

See [User interactions](/guide/browser-testing/user-interactions.md#locator-api) for detailed usage.

## When to use browser mode

Use this decision tree to determine if you need Browser Mode:

```
Depends on real browser APIs? ─── Yes ─▶ ✅ Browser Mode
         │ No
         ▼
Need cross-browser testing?  ─── Yes ─▶ ✅ Browser Mode
         │ No
         ▼
Unexpected behavior in jsdom? ── Yes ─▶ ✅ Browser Mode
         │ No
         ▼
    💡 jsdom is fine
```

:::tip Recommendation
Even if your tests work fine in jsdom, we still **recommend using Browser Mode**. See the comparison table below for specific advantages.
:::

## Browser mode vs jsdom/happy-dom

Browser Mode and jsdom/happy-dom represent different trade-offs: Browser Mode provides full browser compatibility and visual debugging but consumes more resources; jsdom/happy-dom runs faster and lighter but can only simulate a subset of browser APIs.

| Feature               | Browser Mode        | jsdom / happy-dom               |
| --------------------- | ------------------- | ------------------------------- |
| Browser API coverage  | ✅ Full support      | ⚠️ Partial simulation           |
| Canvas / WebGL        | ✅ Native support    | ❌ Unsupported or needs polyfill |
| CSS computed styles   | ✅ Real rendering    | ⚠️ Limited support              |
| Web Workers           | ✅ Native support    | ❌ Unsupported                   |
| Execution speed       | ⚠️ Slower           | ✅ Faster                        |
| Resource usage        | ⚠️ Higher           | ✅ Lower                         |
| Debugging experience  | ✅ Visual debugging  | ⚠️ Console only                 |
| Cross-browser testing | ✅ Multiple browsers | ❌ Unsupported                   |

## Config compatibility

Most config options behave the same in Browser Mode. The table below collects the exceptions in one place — node-only options that are ignored (with a one-time warning when set to a non-default value), features not supported yet, and options whose scheduling semantics differ:

| Option / API                                                                                           | Behavior in Browser Mode                                                                                                                                                                                                                                                                                                                                                                                                        |
| ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [coverage.provider: 'v8'](/config/test/coverage.md#provider)                                           | Stable for page-renderer scripts in headless, non-watch Chromium runs with the Playwright provider. Dedicated workers are not collected. Headed and watch runs are experimental and do not guarantee isolation from inactive runner frames or exact script/source-map pairing across rebuilds. Firefox and WebKit must use `istanbul`.                                                                                          |
| [isolate](/config/test/isolate.md)                                                                     | `true` uses a fresh browser context/page per file. With `false`, headless browser workers reuse a context/page for their assigned files, so worker-scoped fixtures can live across files; projects with `setupFiles` remain file-isolated so setup modules run for each file. Headed mode keeps the visible file frames isolated. When `bail` is enabled, files run one at a time and worker-scoped fixtures do not span files. |
| [pool.type / pool.execArgv](/config/test/pool.md)                                                      | Ignored — node process mechanisms.                                                                                                                                                                                                                                                                                                                                                                                              |
| [pool.maxWorkers](/config/test/pool.md)                                                                | Headless runs execute files in parallel across up to `maxWorkers` browser contexts. Headed runs always execute files serially, because all tests share the single visible container page.                                                                                                                                                                                                                                       |
| [testEnvironment](/config/test/test-environment.md)                                                    | Ignored — the real browser is the environment.                                                                                                                                                                                                                                                                                                                                                                                  |
| [detectAsyncLeaks](/config/test/detect-async-leaks.md), [logHeapUsage](/config/test/log-heap-usage.md) | Ignored — node-only mechanisms.                                                                                                                                                                                                                                                                                                                                                                                                 |
| [bail](/config/test/bail.md)                                                                           | Supported in headless runs: once the failure budget is reached, Rstest stops dispatching the remaining files. Files already running in parallel finish first, so a few more results can still appear. The headed debugging UI (`headless: false`) does not apply bail.                                                                                                                                                          |

Module mocking (the [rs.mock family](/api/runtime-api/rstest/mock-modules.md)), including [virtual modules configured with `resolve.alias`](/api/runtime-api/rstest/mock-modules.md#mock-virtual-modules), and [includeSource](/config/test/include-source.md) in-source testing behave the same as in Node mode. `rs.mockRequire` also works in browser tests, but it exists for CommonJS interop — prefer `rs.mock` / `rs.doMock` when writing browser tests.

## Next steps

- [Getting started](/guide/browser-testing/getting-started.md) - Configure and run your first browser test
- [User interactions](/guide/browser-testing/user-interactions.md#locator-api) - Use `page` + `expect.element` for semantic tests
- [Framework guides](/guide/browser-testing/framework-guides.md) - Complete configuration and component testing examples for each framework
- [User interactions](/guide/browser-testing/user-interactions.md) - Simulate user clicks, typing, and other actions
