Playwright
@rstest/playwright provides Playwright fixtures and Playwright-style assertions for Rstest tests that run in Node.js workers. Use it for E2E tests against a complete page or app, such as a local dev server, a preview server, or a deployed URL. The test runs in Node.js and uses Playwright to drive the page.
Rstest browser mode vs playwright
The main difference is the testing scenario: Rstest browser mode web-bundles test modules and runs test code in a browser runtime, while @rstest/playwright controls a page that is already prepared by your app or server.
Because @rstest/playwright controls an external page instead of running the test in Rstest's browser runner, it does not use the Browser UI preview iframe. For visual debugging, use headed mode with PWDEBUG=1.
Rstest playwright vs native playwright
@rstest/playwright and native Playwright use different runners and configuration files:
Use @rstest/playwright when you want Playwright-driven E2E tests to run in the same Rstest workflow as the rest of your tests. Use native Playwright when you want the full Playwright Test runner workflow and its configuration model.
Install
Install both packages:
- @rstest/playwright adds the Rstest fixtures and assertions.
- playwright provides the browser automation runtime.
Install the Chromium browser binary used by Playwright:
Basic usage
Import test and expect from @rstest/playwright instead of @rstest/core:
Regular lifecycle helpers are also available from @rstest/playwright:
If your test modules do not rely on side effects that need isolation, set isolate: false in rstest.config.ts to reuse the worker module cache across test files and avoid repeated Playwright startup cost:
Fixtures
@rstest/playwright provides these fixtures:
The sections below show how each fixture is commonly used. page and serve link to the existing examples to avoid repeating the same code.
browser
Use browser when you need to create a custom browser context yourself:
context
Use context when one test needs multiple pages that share the same browser context:
page
See Basic usage for the common E2E flow of opening and asserting a page.
request
Use request when you only need Playwright's API client and do not need to launch a browser:
serve
See Local app server for serving a built app from local files.
Assertions
expect keeps normal Rstest assertions. When the actual value is a Playwright Locator or Page, it also provides retrying Playwright-style async assertions.
Locator assertions target Playwright Locator values and follow the naming of Playwright Locator assertions where possible. They are aligned with the element assertions already supported by @rstest/browser where possible:
toBeVisible(options?)toBeHidden(options?)toBeEnabled(options?)toBeDisabled(options?)toBeChecked(options?)toBeUnchecked(options?)toBeAttached(options?)toBeDetached(options?)toBeEditable(options?)toBeFocused(options?)toBeEmpty(options?)toBeInViewport(options?)toContainText(expected, options?)toHaveAttribute(name, expected?, options?)toHaveClass(expected, options?)toHaveCSS(propertyName, expected, options?)toHaveCount(expected, options?)toHaveId(expected, options?)toHaveJSProperty(name, expected, options?)toHaveText(expected, options?)toHaveValue(expected, options?)
Page assertions:
toHaveTitle(expected, options?)toHaveURL(expected, options?)
String text assertions normalize whitespace. Playwright assertions retry until they pass or the timeout option is reached. The default timeout is 5000 milliseconds.
.not and expect.soft are also supported:
Configure playwright options
Global playwright configuration is not supported yet. Override the playwright fixture when a test file needs custom Playwright options:
The playwright fixture supports these options:
Local app server
Use the serve fixture when a test needs to serve a built app. It starts a static server for the entry file and automatically stops the server after the test.
When PWDEBUG=1 is enabled, serve keeps the server alive by default so the opened page remains available for inspection. In non-watch runs, this may keep the Rstest process open until you stop it manually. Set keepAliveOnDebug: false if you want the server to close even in debug mode.
Headed debugging
Set PWDEBUG=1 to launch Chromium in headed mode while debugging locally:
This environment variable keeps your tests unchanged and applies these defaults:
headless: falseslowMo: 100devtools: true
You can also override the debug defaults from the test:
To stop on a page while debugging, use Playwright's page.pause() with a zero test timeout:
In debug mode, failed tests automatically call page.pause() before closing the page and context. Set pauseOnFailure: false in debug options, or RSTEST_PLAYWRIGHT_PAUSE=false, to disable this behavior.
For non-interactive debugging in CI or local runs, capture a screenshot when a test fails:
This keeps the test runner non-blocking while preserving the failed page state as an artifact. See examples/playwright for a complete Rsbuild + Playwright example.