Back to blog

Code coverage with Storybook test runner

Get story coverage to find missing edge cases

loading
Yann Braga
โ€” @yannbf
Last updated:

Apps are more complex, multi-state, and personalized than ever. That yields thousands of UI permutations which need to be tested for bugs. But how do you ensure your tests cover every state of a UI component?

Code coverage scans your code for untested edge cases. That helps you write more comprehensive tests and increases confidence in UI.

I'm excited to share that Storybook test runner now generates coverage reports. Read on to learn more:

  • ๐Ÿงฉ Easy to setup via addon
  • โœ… React, Preact, Vue, Svelte, Web components & HTML support
  • ๐Ÿงฐ Babel and Vite compatible
  • โš™๏ธ Customizable to your project's needs

Use stories to test components

Before diving into coverage reports, let's take a moment to recap how you can test component behavior using Storybook.

While writing stories for a component, you also capture its test cases. Each story describes one component state. You supply props and mock data to render that variation in isolation. That acts as the initial state for your test.

You can then attach a play function to the story to simulate user behavior (e.g., clicks and inputs) and run assertions. Finally, use Storybook test runner to execute the tests.

// AccountForm.stories.ts
import { within, userEvent } from '@storybook/testing-library';
import { expect } from '@storybook/jest';
import { AccountForm } from './AccountForm';

const meta = { component: AccountForm };
export default meta;

export const VerificationSuccess = {
  args: {
    passwordVerification: true,
  },
  play:  async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    await userEvent.type(canvas.getByTestId('email'), 'michael@chromatic.com');
    await userEvent.type(canvas.getByTestId('password1'), 'k32904nยฃ#1kjad');
    await userEvent.type(canvas.getByTestId('password2'), 'k32904nยฃ#1kjad');
    await userEvent.click(canvas.getByTestId('submit'));
    await expect(
      canvas.getByText(
        'Everything is perfect. Your account is ready and we should probably get you started!'
      )
    ).toBeInTheDocument();
  },
};

Powered by Jest & Playwright

The test runner is powered by Jest and Playwright to verify that stories render without errors and that all assertions pass.

Generate code coverage reports with Storybook test runner

Bugs often sneak through even if you have the best test automation. That doesn't mean there's a flaw in your test suite but that the tests are incomplete. Your code has multiple logic branches and conditions so it's easy to miss test cases for a few of them.

Code coverage makes it easier to spot untested edge cases. It lets you see which lines of your code are tested. This helps you to write more relevant tests and improve the quality of your test suite.

Let's go ahead and set up code coverage for Storybook test runner in two steps.

1. Instrument the code

Instrumenting your code allows Storybook to track your lines of code and figure out which ones are covered by tests. Istanbul is the goto instrumentation library in the JavaScript ecosystem. With Storybook, you can use the @storybook/addon-coverage to set up Istanbul instrumentation for your project.

The coverage addon offers out-of-the-box support for React, Preact, HTML, Web components, Svelte and Vue. It detects whether you're using Babel or Vite and configures Istanbul instrumentation accordingly.

To use it, install @storybook/addon-coverage:

yarn add -D @storybook/addon-coverage

And register it in your .storybook/main.js file:

// .storybook/main.js
module.exports = {
  // ...rest of your code here
  addons: [
    "@storybook/addon-coverage",
  ]
};

Manually configuring Istanbul

The addon is configured to work for most projects by default. However, you can pass in an options object to customize it to your project's needs.

You can control what files to include or exclude in the coverage report. Or set the working directory, which is especially useful when working in a monorepo.

Some frameworks, such as Angular, do not use Babel or Vite. In that case you have to manually instrument your code. Check out ย Storybook coverage recipes repository for more such recipes and examples.

2. Run tests with the coverage flag

Now that you've set up the instrumentation, you're ready to use the test runner. First, start your Storybook:

yarn storybook

Then, run Storybook test runner in a separate terminal, with the --coverage flag:

yarn test-storybook --coverage

The test runner will report the results in the CLI and generate a coverage/storybook/coverage-storybook.json file which can be used by nyc (the Istanbul command line interface).

Use alternative coverage reporters

By default, the test runner gives you a text report. However, you can use the output coverage-storybook.json file to generate other types of reports.

One example is a lcov report which gives you a more detailed, interactive coverage summary that you can access via the browser.

To generate the lcov report, run the following:

npx nyc report --reporter=lcov -t coverage/storybook --report-dir coverage/storybook

nyc is a dependency of the test runner, so you'll already have it in your project. Note, if you use Vue or Svelte, you'll have to configure nyc to include .vue or .svelte files in the report.

It outputs the HTML files in the coverage folder. Open the coverage/storybook/lcov-report/index.html file in your browser to view the report.

Additionally, you can use tools like Codecov to automate code coverage reporting. Codecov will automatically detect the coverage files and visualize coverage progress over time.

Send us feedback

The coverage addon is experimental, and we need your help to stabilize it. Try it on your project and report any bugs or suggestions to improve it. Join us in Storybook Discordโ€™s #testing channel or contribute via GitHub.

You can learn more about code coverage in the test runner documentation.

Coverage tracks test suite health

Stories are the starting point for component testing. You can quickly isolate a component and capture all its states and variations as stories. Then use Storybook test runner to simulate interactions and verify component behavior.

The code coverage addon gives you valuable insights about your test suite. It tracks which components are being tested and alerts you to edge cases you might have missed.

Join the Storybook mailing list

Get the latest news, updates and releases

6,613 developers and counting

Weโ€™re hiring!

Join the team behind Storybook and Chromatic. Build tools that are used in production by 100s of thousands of developers. Remote-first.

View jobs

Popular posts

Community Showcase #4

CSF 3 crash course, workflow tools and universal components in Storybook
loading
Varun Vachhar

Storybook for full-stack developers

Streamline your app development workflow by building, testing and documenting components in isolation
loading
Varun Vachhar

New website for Storybook

Refreshed look & feel for 2022
loading
Dominic Nguyen
Join the community
6,613 developers and counting
WhyWhy StorybookComponent-driven UI
DocsGuidesTutorialsChangelogTelemetry
CommunityAddonsGet involvedBlog
ShowcaseExploreProjectsComponent glossary
Open source software
Storybook

Maintained by
Chromatic
Special thanks to Netlify and CircleCI