The post Test Angular Components in Storybook appeared first on Kill All Defects.
Have you ever wanted a quick way of inspecting the appearance and behavior of Angular components in your project? Storybook is a free library that integrates into your Angular projects to let you look at any component in your application, tweak with configuration values, and ensure the component is behaving properly.
Storybook reduces the time between experiments and increases the odds that developers will catch unintended changes to components during development.
What is Storybook?
Storybook is a front-end JavaScript library that nearly defies explanation. I would call it a “JavaScript component test bench”.
Essentially, Storybook generates a web page for testing components in your Angular application or their equivalents in other user interface frameworks.
Storybook reads individual story definitions from your source code (more on this later) and populates a side bar full of scenarios that you’ve defined. The user can then click on a story to interact with the component in that scenario.
One use of this is to run Storybook to check the appearance and behavior of components after making changes. This can be helpful either in making sure a change in one area didn’t have unanticipated effects on another component. This is also helpful for components that are used less frequently or visible only after time-consuming operations.
Another use of Storybook is for developers to generate a static web page for quality assurance or product management to use. They can use this to verify that components appear and behave correctly in isolation.
Install Storybook
First, let’s install Storybook globally on our development machine by going to a command line and running npm i @storybook/cli -g
to g lobally i nstall the Storybook command-line interface (CLI). This will allow you to use Storybook anywhere on your machine.
Next, navigate in the command line into the root directory of an existing Angular application. For this article purposes I’ll be starting with a prior version of my Doggo Quest game development project. If you want to follow along, you can check out the appropriate tag on GitHub.
Once you are inside of your application, run getstorybook init
to install Storybook into your application. This will scan your application and determine that it is an Angular application. After that it will:
- Modify package.json and package-lock.json to reference Storybook
- Exclude stories.ts files from normal Angular builds
- Create a .storybook directory with several files defining good Angular behivor
- Create a few sample story files
Now if you run npm run storybook
you should see something like the following:
This is the result of the sample story files. Feel free to delete those files as you should not need them past running them to ensure Storybook works out of the box.
Your first Story
Okay, so we’ve established that we can install and run Storyboard in an Angular application. Let’s make this useful to our specific application.
We’ll start off by identifying a simple stand-alone component to test. In my case, the application has a header that displays the name of the game as well as the current score.
The component does have a dependency on Angular Material, which will create a minor obstacle for us, but it will be a good illustration of how to work around some common problems in Storybook.
I’ll start by going into the component’s directory and adding a new file named header.stories.ts
. Here I’m taking the name of the component and then ending with .stories.ts
, which tells Storybook to scan this file for stories.
My story file is as follows:
Here at line 5 I’m declaring a collection of stories named “Header”. These stories are all going to be related to header.component
so I figure it’s only right to call them header.
Next, at line 7 and 13 I begin two distinct stories, one for a game with a score of 0 and another for a game with a score of 10000. Note that I provide the HeaderComponent
to each story, but I provide different Score
values to each case on lines 10 and 16.
Here Score
is an @Input()
defined on my component, and Storybook will directly set that property on my component on construction. This is what makes the “Score 0” case render differently from the “Score 10000” case.
Another note here: On line 6 I’m using addDecorator
to import the AppModule
for the story. This is necessary because the component itself depends on things defined in that module definition. Without this, the component will not render in Storybook and you will see an error in the user interface.
Import Custom CSS
You may notice that your stories do not render well in Storybook, particularly if your application uses a dark theme like mine does.
You can do a few things about this.
First, if you add a .storybook/preview-head.html
file, you can add any custom imports or CSS inline like so:
Ideally you should only use this to customize any imports or classes you have defined in your application’s index.html
page.
Dark Theme
While the custom imports helps the components render correctly, if your main pain is dark and the rest of the application is light, it can be a little jarring.
Thankfully Storybook ships with a dark theme you can enable without too much additional work.
Simply add a manager.ts
file to your .storybook
directory and give it the following content:
Once you restart Storybook you’ll see something like the following screenshot:
That’s more like it!
Get Started with Storybook Knobs
While you should now be well-equipped to create Storyboards for every component in your application, there’s one more capability you should know about: Knobs.
Knobs is an add-on for Storybook that allows you to make changes to stories and see those changes impact the rendered component. Think of it as a way of testing how the component behaves with different settings.
First, we’ll install knobs by running npm i @storybook/addon-knobs --save-dev
from the command line.
Next, we need to edit .storybook/main.js
to add the new add-in to the list:
We should be all set to work with Knobs now.
Add Knobs to Stories
Let’s take a look at a sample component and how we can integrate Knobs into that component’s stories.
Specifically, let’s look at the story-entry.component
which will render differently based on the type of entry it is as well as the text provided to it. In Doggo Quest, this is the central building block of the story display, so this is a very important component to test.
Its story file looks like this:
First of all, note that we add another decorator called withKnobs
on line 10 to declare that this component relies on the Knobs system for getting values into the component.
Next, let’s look at the mess that is the StoryEntry
definition starting on line 14. A StoryEntry
needs a StoryEntryType
and a Text
parameter. Since the former is quite complex, let’s skip ahead to the Text
parameter on line 20.
On line 20 we call a knob function called text
to tell it we want a new configurable string property that should be labeled as Text
in the user interface and have an initial value of “This is the text of the entry”.
When the component renders in this story, the user will be able to customize the value of a Text
property and the component’s text will change as a result.
Storybook Knobs also let us use many other types of knobs including boolean, number, date, and others. See the documentation for more specifics.
Now let’s look back at that select
syntax on line 14. With select, we define a drop down list that the user will be able to pick from, specify the type of each value as the generic type parameter, and then provide an object with property definitions mapping to their specific values. Storybook uses these properties as labels for the values, which is helpful for enums like this as Error
is more meaningful than 3
, for example. Finally, we specify the initial option to specify.
Yes, the select syntax is hard to read, but the result is a very intuitive experience for testers.
Static Storybook Sites
Sometimes you’re working with quality assurance, product management, or another group that doesn’t routinely work directly with source code. These users can often benefit from working with Storyboard, but don’t necessarily have the technical skills or access to the source code to get Storybook running.
Thankfully, Storybook allows you to build a stand-alone web page that you can then distribute to stakeholders to experiment with locally.
Simply run npm run build-storybook
and your Storybook application will be built into the storybook-static
directory. You can deploy this folder as a stand-alone web application and direct stakeholders to go to index.html
in order to get the full experience of working with Storybook, without having to wrestle with Angular or npm.
If building static storybook files seems tedious, this would be a very simple command to automate as part of a continuous integration process. Just have your build pipeline run npm run build-storybook
and then do whatever you want with the results of the storybook-static
directory.
Conclusion and Next Steps
Hopefully this article adequately illustrates the value Storybook provides in giving you a central place to look at your components, a way to use Knobs to view components at different states, and as a means of giving your quality assurance and design teams a stand-alone test bed for the application’s visual styles.
This article doesn’t even cover some of the more advanced features and addons for Storybook such as:
- Automated user interface testing
- Accessibility analysis
- Linking stories together
- Documentation and tester-visible notes
There’s a lot you can do with Storybook and the team is constantly improving and growing it to better serve the web development community – regardless of which JavaScript framework you use.
Top comments (5)
Doesn't it create more work for web-developer as for UI changes we can directly inspect elements on the browser?
It's not just about inspecting UI changes. You can display a component in complete isolation without having to care how to access it into your application (routing, conditional rendering) and change its inputs on the fly to test different use cases.
Then it would be helpful in scenario where application comes for maintenance or bug tracking.
Imagine scenarios where it's hard or slow to get to a particular component or a component in a specific scenario. It actually makes it easier on developers pretty quickly. My experience is that you don't need to do a lot of maintenance on stories you've already created.
Admittedly, though, for the simple text-based game project, 95% of the components are going to be visible on initial app load, so it's a bit of a bad example, but on larger and more complex applications with more navigation and components tucked away in odd corners, it can make a lot more sense.
Yeah, need to do more project that requires intense UI then it would be useful to use this tool.