Highlights
New Playwright integration package
This release adds @rstest/playwright, providing Playwright-style browser automation fixtures such as browser, context, page, request, and serve, plus Playwright-style async assertions integrated with Rstest expect.
import { expect, test } from '@rstest/playwright';
test('home page', async ({ page, serve }) => {
const { url } = await serve('./dist/index.html');
await page.goto(url);
await expect(page.locator('h1')).toHaveText('Home');
});Rsbuild plugins can modify Rstest config
Rsbuild plugins can now use the exposed Rstest API to modify the current Rstest project config through modifyRstestConfig, making it easier for Rsbuild ecosystem plugins to customize test behavior in a scoped and validated way.
import type { RsbuildPlugin } from "@rsbuild/core";
import type { RstestExposeAPI } from "@rstest/core";
export const myPlugin = (): RsbuildPlugin => ({
name: "my-plugin",
setup(api) {
if (api.context.callerName === "rstest") {
const rstestApi = api.useExposed<RstestExposeAPI>("rstest");
rstestApi?.modifyRstestConfig((config) => {
config.source = {
...config.source,
define: {
...(config.source?.define || {}),
__TEST_TARGET__: JSON.stringify("node"),
},
};
});
}
},
});Task metadata support
Rstest now supports metadata for tests, suites, file results, and custom reporters. You can initialize metadata through TestOptions.meta, inherit suite metadata in descendant suites/tests, update it at runtime via context.task.meta or hook ctx.meta, and consume it from reporter hooks.
import { afterAll, describe, test } from '@rstest/core';
// File-level metadata is exposed on TestFileResult.meta.
afterAll((ctx) => {
ctx.meta.fileHook = 'afterAll';
});
describe('checkout', { meta: { owner: 'platform', area: 'payment' } }, () => {
test('submits order', { meta: { caseId: 'checkout-001' } }, (ctx) => {
// Test-level metadata inherits suite metadata and can be updated at runtime.
ctx.task.meta.mutantId = process.env.STRYKER_ACTIVE_MUTANT;
});
});Custom reporters can read the resolved metadata from case, suite, and file results:
import type { Reporter } from '@rstest/core';
const metadataReporter: Reporter = {
onTestCaseStart(test) {
console.log('case start metadata', test.meta);
},
onTestCaseResult(result) {
console.log('case result metadata', result.meta);
},
onTestSuiteResult(result) {
console.log('suite metadata', result.meta);
},
onTestFileResult(result) {
console.log('file metadata', result.meta);
},
};What's Changed
New Features 🎉
- feat(core): add task metadata support by @9aoy in #1507
- feat(core): mark @rstest/core sideEffects-free for tree-shaking by @fi3ework in #1513
- feat(playwright): add Playwright integration package by @9aoy in #1396
- feat(core): support modifying Rstest config via Rsbuild plugins by @9aoy in #1475
Bug Fixes 🐞
- fix(core): report running test case as failed on worker crash by @fi3ework in #1536
- fix(adapters): update peer dependency ranges to include TypeScript 7 by @chenjiahan in #1533
- fix(coverage-v8): reduce conversion memory usage by @9aoy in #1532
- fix(coverage-v8): omit invalid raw sourcemaps by @9aoy in #1527
- fix(e2e): avoid nested GitHub Actions annotations by @9aoy in #1525
- fix(core): keep Mocked construct signatures for this-typed members by @fi3ework in #1519
- fix(core): keep Mocked assignable to T for construct+call members by @fi3ework in #1516
- fix(core): accept rs.fn()/rs.spyOn() mocks in call-order matchers by @fi3ework in #1517
Document 📖
- docs: update 0.11 blog baseline label by @9aoy in #1511
- docs: add Rstest 0.11 release blog by @fi3ework in #1508
Other Changes
- release: 0.11.1 by @fi3ework in #1537
- ci: use Node 24 for release workflow by @fi3ework in #1538
- test(playwright): lighten core expect regression by @9aoy in #1529
- test(e2e): make no-isolate module-sharing fixtures order-independent by @fi3ework in #1523
- test(playwright): skip headed e2e without display by @9aoy in #1512
- chore: enforce unified package versions under packages/ by @fi3ework in #1510
Full Changelog: v0.11.0...v0.11.1