Testing
Generated apps come test-ready: Vitest (jsdom) + React Testing Library + jest-dom matchers, wired with a real example test that renders the home page and asserts on the DOM — not a placeholder expect(1 + 1). pnpm test passes on a fresh scaffold.
What gets scaffolded
| File | Purpose |
|---|---|
vitest.config.ts | jsdom env, globals, coverage (v8), setupFiles |
vitest.setup.ts | Registers jest-dom matchers + auto-cleanup() between tests |
src/pages/index.test.tsx | A working RTL render test to copy from |
import { render, screen } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
import HomePage from './index.js';
describe('dashboard — HomePage', () => {
it('renders the home heading', () => {
render(<HomePage />);
expect(screen.getByRole('heading', { name: /home/i })).toBeInTheDocument();
});
});The setup file
import '@testing-library/jest-dom/vitest';
import { afterEach } from 'vitest';
import { cleanup } from '@testing-library/react';
afterEach(() => {
cleanup();
});@testing-library/jest-dom/vitest adds matchers like toBeInTheDocument() / toHaveTextContent(); @testing-library/user-event is installed for realistic interaction tests.
Running tests
pnpm test # vitest run (one app, or -r across the workspace)
pnpm test:watch # watch mode
pnpm test:coverage # v8 coverage → text + html + lcov
pnpm test:ui # @vitest/uiFederation contract tests
jorvel federation diff.Test the page, not the framework
Storybook
Scaffold Storybook 8 (Rsbuild builder) into an app — config, a sample component + story, and storybook / build-storybook scripts:
jorvel generate storybook # into the host
jorvel generate storybook dashboard # into a specific app
pnpm --filter ./apps/shell storybookPlaywright Component Testing
For real-browser component tests (CSS, layout, focus) beyond jsdom, use Playwright CT. It renders components in a real Chromium/WebKit/Firefox.
pnpm create playwright@latest --ct # scaffolds playwright/index.html + playwright-ct.config.tsimport { test, expect } from '@playwright/experimental-ct-react';
import { Button } from './Button.js';
test('renders + clicks', async ({ mount }) => {
let clicked = false;
const cmp = await mount(<Button label="Go" onClick={() => (clicked = true)} />);
await cmp.click();
expect(clicked).toBe(true);
});Contract tests + bundle size in CI
jorvel init scaffolds two PR workflows: contract-tests.yml (runs jorvel federation diff --base origin/<base> + package tests, failing on a breaking contract change) and bundle-size.yml (comments compressed-size deltas for remoteEntry + chunks on the PR).
