Install dependencies with pnpm
.
The test script will also install Chromium binaries to run Playwright
with!
The button we are going to test is a simple one:
export const Button = () => {
return <button>Click me</button>;
};
As well as its' test:
import { page } from '@vitest/browser/context';
import { Button } from '@repo/components/ui/button.js';
import { describe, expect, it} from 'vitest';
import { render } from 'vitest-browser-react';
describe(Button, () => {
it('renders with default variants', async () => {
render(<Button />);
const button = page.getByRole('button', { name: 'Click me' });
await expect.element(button).toBeInTheDocument();
});
});
Run
pnpm test:coverage
Observe the coverage report:
✓ Button > renders with default variants 9ms
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 20:34:46
Duration 632ms (transform 0ms, setup 133ms, collect 28ms, tests 9ms, environment 0ms, prepare 93ms)
% Coverage report from v8
------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------|---------|----------|---------|---------|-------------------
All files | 100 | 50 | 100 | 100 |
button.tsx | 100 | 50 | 100 | 100 | 2
------------|---------|----------|---------|---------|-------------------
The component has no branching logic while the report shows are the are missing some. I believe I've managed to set up the vitest
configuration to also log the transformed component and we have:
import { jsxDEV } from "react/jsx-dev-runtime";
import { c as _c } from "react/compiler-runtime";
export const Button = () => {
const $ = _c(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = /* @__PURE__ */ jsxDEV("button", { children: "Click me" }, void 0, false, {
fileName: "/Users/<my-user>/Projects/vitest-react-compiler-coverage/src/components/ui/button.tsx",
lineNumber: 6,
columnNumber: 10
}, this);
$[0] = t0;
} else {
t0 = $[0];
}
return t0;
};
So there appears to be a condition related to memoization? I don't know if we can ever test for it though.
First edit the react plugin configuration vitest.config.ts
to not use the react compiler:
- react({
- babel: {
- plugins: [
- ["babel-plugin-react-compiler", {}]
- ],
- },
- }),
+ react(),
Run
pnpm test:coverage
Observe the coverage report:
✓ Button > renders with default variants 10ms
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 20:36:42
Duration 490ms (transform 0ms, setup 36ms, collect 6ms, tests 10ms, environment 0ms, prepare 92ms)
% Coverage report from v8
------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
button.tsx | 100 | 100 | 100 | 100 |
------------|---------|----------|---------|---------|-------------------
The code coverage is 100% as expected. The output code also has no conditions:
import { jsxDEV } from "react/jsx-dev-runtime";
export const Button = () => {
return /* @__PURE__ */ jsxDEV("button", { children: "Click me" }, void 0, false, {
fileName: "/Users/<my-user>/Projects/vitest-react-compiler-coverage/src/components/ui/button.tsx",
lineNumber: 2,
columnNumber: 12
}, this);
};