Document & Test Vue 3 Components With Storybook
Storybook is my tool of choice for UI component documentation. Vue.js is very well supported in the Storybook ecosystem and has first-class integrations with Vuetify and NuxtJS. It also has official support for Vue 3, the latest major installment of Vue.js.
This article will demonstrate how you can set up Storybook with zero-config and built-in TypeScript support, auto-generate controls & documentation, and perform automated snapshot tests for your Vue components.
Why Storybook?
We have components that can have many props, states, slots, etc., which influences its visual representation and more.
This circumstance causes some typical problems for any front-end developer:
- How can I create documentation for my component that doesn't get outdated?
- How can I get an overview of all different states and kinds of my component?
- How can I guarantee that my changes don't influence other states and kinds?
- How can I show the current implementation to non-developer team members?
Storybook will help us here.
Storybook Setup
First, we need to create a Vue 3 application. We'll use Vite, a new build tool from Evan You, the creator of Vue.js:
Setting up Storybook in an existing Vue 3 project can be done with zero configuration:
This command installs Storybook with its dependencies, configures the Storybook instance, and generates some demo components and stories which are located at src/stories
:
We can now run the following command, which starts a local development server for Storybook and automatically opens it in a new browser tab:
These generated Vue components and stories are good examples of how to write Vue 3 stories. I want to show you some advanced documentation examples using a custom component.
Custom Component Demo
I created a Counter.vue
demo component to demonstrate the Storybook integration for this article. The source code is available at GitHub.
The component provides basic counter functionality, has two different visual variants and two slots for custom content.
Let's take a look at the component's code:
In the above code, you can see that I've annotated the Vue component with JSDoc comments. Storybook converts them into living documentation alongside our stories.
Warning
Unfortunately, I found no way to add JSDoc comments to the counter-update
event. I think it is currently not supported in vue-docgen-api, which Storybook uses under the hood to extract code comments into descriptions. Leave a comment if you know a way how to document events in Vue 3.
Storybook uses so-called stories:
A story captures the rendered state of a UI component. Developers write multiple stories per component that describe all the βinterestingβ states a component can support.
A componentβs stories are defined in a story file that lives alongside the component file. The story file is for development-only, it won't be included in your production bundle.
Now, let's take a look at the code of our Counter.stories.ts
:
This code is written in Component Story Format and generates four stories:
- Default: The counter component in its default state
- Colored: The counter component in the colored variation
- NegativeValue: The counter component that allows negative values
- Slot: The counter component with a slot content
Let's take a look at our living documentation in Storybook:
As already mentioned, Storybook converts the JSDoc comments from our code snippet above into documentation, shown in the following picture:
Testing
Now that we have our living documentation in Storybook we can run tests against them.
Jest Setup
I chose Jest as the test runner. It has a fast & straightforward setup process and includes a test runner, an assertion library, and a DOM implementation to mount our Vue components.
To install Jest in our existing Vue 3 + Vite project, we need to run the following command:
Then we need to create a jest.config.js
config file in the root directory:
The next step is to add a script that executes the tests in our package.json
:
Unit testing with Storybook
Unit tests help verify functional aspects of components. They prove that the output of a component remains the same given a fixed input.
Let's take a look at a simple unit test for our Storybook story:
We wrote two exemplary unit tests Jest executes against our Storybook story Counter.stories.ts
:
renders default button
: asserts that the component container contains the CSS classdefault
renders colored button
: asserts that the component container contains the CSS classcolored
The test result looks like this:
Snapshot Testing
Snapshot tests compare the rendered markup of every story against known baselines. Itβs an easy way to identify markup changes that trigger rendering errors and warnings.
A snapshot test renders the markup of our story, takes a snapshot, and compares it to a reference snapshot file stored alongside the test.
The test case will fail if the two snapshots do not match. There are two typical causes why a snapshot test fails:
- The change is expected
- The reference snapshot needs to be updated
We can use Jest Snapshot Testing as Jest library for snapshot tests.
Let's install it by running the following command:
Next, we need to add it as snapshotSerializers
to our jest.config.js
config file:
Finally, we can write a snapshot test for Storybook story:
If we now run our tests, we get the following result:
The test run generates snapshot reference files that are located at src/components/__snapshots__
.
Conclusion
Storybook is a fantastic tool to create living documentation for components. If you keep the story files next to your component's source code, the chances are high that the story gets updated if you modify the component.
Storybook has first-class support for Vue 3, and it works very well. If you want more information about Vue and Storybook, you should look at the official Storybook documentation.
If you liked this article, follow me on Twitter to get notified about new blog posts and more content from me.
Alternatively (or additionally), you can also subscribe to my newsletter.
Why I Love Vue 3's Composition API
Vue 3 introduced the Composition API to provide a better way to collocate code related to the same logical concern. In this article, I want to tell you why I love this new way of writing Vue components.
How I Built a Twitter Keyword Monitoring Using a Serverless Node.js Function With AWS Amplify
In this article, I will demonstrate to you how I built a simple serverless Node.js function on AWS that sends me a daily email with a list of tweets that mention me on Twitter.