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.
Migrating from Existing Projects
If your project already uses Jest or Vitest, refer to the official Rstest migration guides:
We recommend installing the migrate-to-rstest skill first, then copying this prompt to your coding agent. It keeps the Modern.js @modern-js/adapter-rstest integration during migration:
Migrate this Modern.js project from Jest or Vitest to Rstest.
First install and use the migrate-to-rstest skill. If it is not installed, install it with:
npx skills add rstackjs/agent-skills --skill migrate-to-rstest
Follow the migrate-to-rstest skill instructions and the official Rstest migration guides:
- Jest: https://rstest.rs/guide/migration/jest
- Vitest: https://rstest.rs/guide/migration/vitest
Modern.js-specific requirement:
- Install and use @modern-js/adapter-rstest together with @rstest/core.
- Create or update rstest.config.ts to import withModernConfig from @modern-js/adapter-rstest.
- Reuse the Modern.js app configuration with extends: withModernConfig().
- Do not replace this with a plain Rstest config unless the project explicitly does not need Modern.js config integration.