🥟 Run tests with Bun
The test runner now runs under Bun. Bun transpiles your TypeScript test files itself, so Playwright does not use Babel or its compilation cache. Pass the --bun flag, because without it bunx playwright test runs on Node.js:
bunx --bun playwright testOur CI runs the test runner tests under Bun 1.4.3 on Linux. Some features work differently under Bun:
- There is no watch mode. UI mode does not run tests again when files change, and
--only-changeddoes not follow imports. - Bun loads modules itself, so
--tsconfigand the JSX options intsconfig.jsonhave no effect, and custom ESM loaders are not supported. - Stack traces do not include async frames, and API names do not include the class name:
clickinstead oflocator.click. This changes some step locations, step titles and error messages. - Console output of a test does not get into the trace and UI mode.
🚨 Reports with only failures
New failures reporter prints failures and successful retries as they occur, followed by a summary, without progress output.
New onlyFailures option of the HTML, JSON and JUnit reporters keeps only tests with unexpected outcomes, flaky tests and interrupted tests:
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
reporter: [
['failures'],
['html', { onlyFailures: true }],
],
});🎯 Test runner
-
New built-in
-exclusive-test lock runs a test only when no other tests are running. All other tests continue to run in parallel with each other:test('restart the server', { lock: '-exclusive-' }, async () => { // No other test runs while this one is running. });
-
test.skip(), test.fixme(), test.fail() and test.slow() now accept only a description. It is recorded in the test annotation:
test('upload a file', async ({ page }) => { test.skip('Not implemented yet'); });
-
New
PLAYWRIGHT_TRANSFORM_CACHE_DIRenvironment variable sets the directory for transpiled test files, for example on a Linux machine shared with other users.
New APIs
- New options
timeoutandsignalin cdpSession.send(). - New testRun.mode() returns the execution mode of a suite during reporter.preprocess().
Breaking Changes ⚠️
-
TypeScript class fields now follow
useDefineForClassFieldsfrom yourtsconfig.json, the same astsc. It is enabled forES2022and later targets, and whentargetis not specified. A field initializer that reads a constructor parameter property now fails, because the initializer runs first:class LoginPage { // TypeError: Cannot read properties of undefined (reading 'getByRole') readonly submit = this.page.getByRole('button', { name: 'Submit' }); constructor(private readonly page: Page) {} }
Move the initialization to the constructor, or set
"useDefineForClassFields": falsein yourtsconfig.json. -
Actions such as locator.click(), locator.check(), locator.tap(), locator.fill(), locator.clear() and locator.selectOption() now wait for the element to be not inert. An action on an element with the
inertattribute, or inside such an element, now times out if the element stays inert. -
A sharded run now fails with "No tests found" when no tests match across all shards. Pass
--pass-with-no-teststo allow this. An empty shard still passes when other shards have tests. -
Cookie matching now follows RFC 6265. With a URL, browserContext.cookies() and apiRequestContext.cookies() no longer return host-only cookies for subdomains or
Path=/apicookies for/apiv2, and aPath=/foo/cookie does not match/foo. APIRequestContext sends a cookie without a name asCookie: xinstead ofCookie: =x, and storesSet-Cookie: tokenas a cookie without a name. -
Proxy credentials are no longer sent to websites. The credentials in the
proxyoption now answer only proxy challenges. To authenticate on a website, usehttpCredentials. -
Text that the browser does not render, such as text that is not assigned to a slot or text directly inside a closed
<details>, is no longer part of accessible names and aria snapshots. This can change the results of page.getByRole() with a name, locator.ariaSnapshot() and expect(locator).toMatchAriaSnapshot(). -
String and
URLSearchParamsvalues of theparamsoption in APIRequestContext requests are now appended to the query that the URL already has, instead of replacing it. -
.css,.lessand.scssimports in test files now load as empty modules instead of being removed, so the imported file must exist. -
The blob reporter again deletes the content of its output directory before it writes the report. Playwright 1.64 kept reports with other names.
-
Test locations of imported calls such as
test(in CommonJS output now point to the start of the callee, for examplea.spec.ts:3:7instead ofa.spec.ts:3:11. This is the same as in ESM.
Announcements
- ⚠️ Playwright no longer tests on Node.js 20. Use Node.js 22, 24 or 26, as listed in the system requirements.
- 🐳 Docker images now include Node.js 26 instead of Node.js 24, and the latest patch of Chromium on the same branch.
Browser Versions
- Chromium 158.0.8127.18
- Mozilla Firefox 159.0
- WebKit 27.2
This version was also tested against the following stable channels:
- Google Chrome 157
- Microsoft Edge 156