Reuse Storybook Stories in Tests
Bart Kooijman / 2021-07-19
4 min read
At my current project, we reuse our Storybook stories in our React Testing Library tests. This setup has the following benefits:
- We only have to setup the component variants and props once.
If a test fails you will have a visual of the unexpected behavior by interacting with your Storybook story.
Testing Library has an accessibility-first approach and Storybook provides an accessibility add-on.
Sweet!
In case you never heard of React Testing Library, you should check it out as soon as possible. Other test libraries like Enzyme test the implementation of the component, by asserting the props or state. React Testing Library, will run the test against the actual HTML output of your components. In other words, tests with testing-library/react represent what the user will experience while interacting with your component.
Storybook & React Testing Library.
Let's look at an simplified example. My folder structure looks like this:
--- TitleComponent
- index.js
- TitleComponent.stories.js
- TitleComponent.test.js
The component, test, and story are structured together. The TitleComponent is just a header:
const TitleComponent = ({title}) => <h1>{title}</h1>;
export default TitleComponent;
The story itself and the props are defined and exported outside the Storybook logic.
import { storiesOf } from "@storybook/react";
import TitleComponent from ".";
export const defaultProps = { title: 'My Title' };
export const TitleStory = (data) => <TitleComponent {...data} />;
storiesOf('Atoms', module).add('TitleComponent', () => (
<TitleStory {...defaultProps} />
));
This way I can use the story in Storybook and import the story in my tests.
import '@testing-library/jest-dom/extend-expect';
import { render, screen } from '@testing-library/react';
import { TitleStory, defaultProps } from './TitleComponent.stories';
const titleRegex = {
name : new RegExp(defaultProps.title, "i");
};
describe.only('TitleComponent', () => {
it('shows the title', () => {
render(<TitleStory {...defaultProps} />);
expect(screen.getByRole('heading', titleRegex).toBeInTheDocument();
});
});
If the test above fails the title wouldn't show up in your Storybook story as well.
Testing Playground.
Having trouble selecting the correct element in your test? You should definitely try out testing-playground, which is also available as a Chrome extension. Testing Library Playground will help you with selecting the elements in your tests and also gives you useful tips. I used the suggested query in the image below in the example test above, very useful!
Accessibility.
As you might have noticed, to get the best experience with React Testing Library your components must be accessible.
If you build components with accessibility in mind, you can use the *ByRole
queries more often. This is also recommended.
This is one of the perks while working with Testing Library. It encourages you to build accessible components, which enables you to easily query the elements needed in your tests.
Storybook also has a must-have accessibility add-on to help you out with analyzing the accessibility of your component.
Storybook 6.3.
With the release of Storybook 6.3, you will get the functionality of reusing stories in tests out of the box. You can read more about it here. I can't agree more with the title of this post. Storybook Stories are the visual representations of your tests!
Results.
While introducing this pattern at my current project I was able to remove hundreds of lines of code. It's a simple improvement but easy to miss. In short, this pattern will avoid setting up the variants of the components in your stories and your tests.
Have fun!