Vitest Tests
Storybook >=10 addon that displays Vitest tests and coverage for the current component
@pilmee/storybook-addon-vitest
ESM addon for Storybook >=10 that adds a Tests panel and shows only the Vitest tests and coverage related to the component rendered by the active story.
Requirements
- Storybook
>=10 - Node.js
>=20.19 - Vitest
>=3when coverage is needed in the JSON report - A Vitest JSON report generated with the
jsonreporter
Installation
npm install --save-dev @pilmee/storybook-addon-vitest
Register the addon immediately after Accessibility. Storybook keeps the addons array order when rendering panels:
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/your-framework';
const config: StorybookConfig = {
addons: [
'@storybook/addon-a11y',
{
name: '@pilmee/storybook-addon-vitest',
options: {
reportPath: './vitest-report.json',
},
},
],
};
export default config;
reportPath is a browser-read URL relative to the published Storybook. The
recommended setup is to generate the file inside the same folder as the static
Storybook build, after Storybook has been built:
{
"scripts": {
"build-storybook": "storybook build",
"test:storybook-report": "vitest run --reporter=json --coverage --outputFile=storybook-static/vitest-report.json",
"storybook:ci": "npm run build-storybook && npm run test:storybook-report"
}
}
Vitest needs a coverage provider such as @vitest/coverage-v8 when using
--coverage. Vitest 3 and newer include the resulting coverageMap in the JSON
report. Using a relative URL (./vitest-report.json) also works when Storybook
is published under a subdirectory.
For local development, generate the file in a folder served through
staticDirs:
// .storybook/main.ts
const config = {
staticDirs: [{ from: '../storybook-reports', to: '/' }],
addons: [
'@storybook/addon-a11y',
{
name: '@pilmee/storybook-addon-vitest',
options: { reportPath: './vitest-report.json' },
},
],
};
vitest run --reporter=json --coverage --outputFile=storybook-reports/vitest-report.json
How Stories Are Matched With Vitest
By default, the addon infers the component from the story import path:
src/components/Button/Button.stories.tsx
↓
src/components/Button/Button.tsx
src/components/Button/Button.test.tsx
It first selects suites whose coverage includes the component file. As a
fallback, it compares *.test.* or *.spec.* paths. From global coverage, it
keeps only the inferred component file.
When a story does not follow that convention, for example when it imports from
an index.ts, declare the path explicitly in the CSF meta:
const meta = {
component: Button,
parameters: {
vitest: {
componentPath: 'src/components/Button/Button.tsx',
},
},
};
export default meta;
You can also override reportPath or disable results for a story/component:
parameters: {
vitest: {
reportPath: './reports/unit.json',
disable: true,
},
},
Utility API
The package exports
filterVitestReport(report, storyImportPath, componentPath?) and
inferComponentPath(storyImportPath) so the filtering logic can be reused or
tested directly. It also exports the report, coverage, options, and story
parameter TypeScript types.