Rstest
Rstest is a testing framework developed by the Rspack team and built on top of Rspack for fast test execution.
This guide explains how to integrate Rstest with Modern.js for web app testing.
Quick Start
Install the base dependencies first:
npm add @rstest/core @modern-js/adapter-rstest -D
yarn add @rstest/core @modern-js/adapter-rstest -D
pnpm add @rstest/core @modern-js/adapter-rstest -D
bun add @rstest/core @modern-js/adapter-rstest -D
deno add npm:@rstest/core npm:@modern-js/adapter-rstest -D
Then create rstest.config.ts:
rstest.config.ts
import { defineConfig } from '@rstest/core';
import { withModernConfig } from '@modern-js/adapter-rstest';
export default defineConfig({
extends: withModernConfig(),
});
@modern-js/adapter-rstest lets Rstest inherit your existing Modern.js config so your test setup stays aligned with your app.
For more configuration details, refer to the Rstest configuration documentation.
You can run tests with npx rstest, or add a script in package.json:
package.json
{
"scripts": {
"test": "rstest"
}
}
Testing Web UI
For web UI tests in Modern.js, there are two common approaches:
- Use Rstest browser mode, which runs tests in a real browser. This is the recommended option in most cases, although it is currently experimental.
- Use a simulated DOM environment with
happy-dom and Testing Library. This matches the default web test environment provided by @modern-js/adapter-rstest.
We generally recommend browser mode because it uses real browser APIs and behavior, supports cases that simulated DOM environments cannot fully cover, and offers a better debugging experience when UI behavior does not match expectations.
Browser mode (experimental)
If you want to test in a real browser instead of a simulated DOM, install the browser mode dependencies:
npm add @rstest/browser @rstest/browser-react playwright -D
yarn add @rstest/browser @rstest/browser-react playwright -D
pnpm add @rstest/browser @rstest/browser-react playwright -D
bun add @rstest/browser @rstest/browser-react playwright -D
deno add npm:@rstest/browser npm:@rstest/browser-react npm:playwright -D
Then enable browser mode in rstest.config.ts:
rstest.config.ts
import { defineConfig } from '@rstest/core';
import { withModernConfig } from '@modern-js/adapter-rstest';
export default defineConfig({
extends: withModernConfig(),
browser: {
enabled: true,
provider: 'playwright',
},
});
Example test:
__tests__/page.browser.test.tsx
import { BrowserRouter as Router } from '@modern-js/runtime/router';
import { page } from '@rstest/browser';
import { render } from '@rstest/browser-react';
import { expect, test } from '@rstest/core';
import Page from '../routes/page';
test('Page', async () => {
await render(
<Router>
<Page />
</Router>,
);
await expect.element(
page.getByRole('heading', { level: 1, name: 'Home' }),
).toBeVisible();
});
For more browser mode setup, Locator APIs, and assertions, refer to the Rstest documentation.
DOM simulation with happy-dom
Install the DOM testing dependencies:
npm add happy-dom @testing-library/react @testing-library/dom -D
yarn add happy-dom @testing-library/react @testing-library/dom -D
pnpm add happy-dom @testing-library/react @testing-library/dom -D
bun add happy-dom @testing-library/react @testing-library/dom -D
deno add npm:happy-dom npm:@testing-library/react npm:@testing-library/dom -D
Update rstest.config.ts to use happy-dom:
rstest.config.ts
import { defineConfig } from '@rstest/core';
import { withModernConfig } from '@modern-js/adapter-rstest';
export default defineConfig({
extends: withModernConfig(),
testEnvironment: 'happy-dom',
});
First, create a simple page for testing:
routes/page.tsx
import { Link } from '@modern-js/runtime/router';
const Page = () => (
<div>
<h1>Home</h1>
<Link to="/about">About</Link>
</div>
);
export default Page;
Then add a test case:
__tests__/page.test.tsx
import { BrowserRouter as Router } from '@modern-js/runtime/router';
import { expect, test } from '@rstest/core';
import { render, screen } from '@testing-library/react';
import Page from '../routes/page';
test('Page', () => {
render(
<Router>
<Page />
</Router>,
);
expect(screen.getByRole('heading', { level: 1, name: 'Home' })).toBeDefined();
});
Running Test Cases
Execute the test command above to run your tests:
✓ __tests__/page.test.tsx (1)
✓ Page
Test Files 1 passed
Tests 1 passed
Duration 510ms (build 145ms, tests 365ms)
Node Mode
If you need node mode tests for server-side logic such as bff, refer to the Rstest documentation directly.
Modern.js mainly targets web apps, so this guide focuses on web UI testing and browser mode.