Table of Contents
Getting started
- Install the addon:
yarn add @storybook-extras/angular -D
- Add the addon
// .storybook/main.ts
import { StorybookConfig } from '@storybook/angular';
import { ExtrasConfig } from '@storybook-extras/preset';
const config: StorybookConfig & ExtrasConfig = {
...
"addons": [
"@storybook-extras/angular",
...
],
...
}
export default config;
- Refer to the sections below for the documentation of the built-in features.
Demo/Chromatic
Find the published demo storybook on chromatic here
Features
- โก๏ธ Zero config setup.
- ๐ Supports latest Storybook v7.
- ๐
ฐ๏ธ Supports latest Angular v15.
- ๐ Introduce
must-have
features for Storybook
on Angular
.
- ๐โ Integrate as much
nice-to-have
features as possible.
- ๐ Coverage Instrumentation for Test-Runner
- ๐งช Auto injector for Angular services
- ๐ฆฅ Lazy loading documentation
- ๐ฌ Source code display
- ๐ฏ Story Wrappers selector toolbar
Test Runner Coverage Instrumentation
We've recently moved from @jsdevtools/coverage-istanbul-loader
to one of our own created libraries webpack-plugin-istanbul
to ensue it is working better with the latest versions of Storybook
and Angular
and specifically with the proper versions of webpack
and istanbul-lib-instrument
.
Read more about the coverage instrumentation in the official Test Runner documentation here.
Simply running test-storybook --coverage
will show you test results coverage in the terminal and also will save the coverage results into coverage/storybook.
Angular Services Unit Testing
- This feature is for developers who want their testing to all run in the same place.
- Particulary this is helpful when you want to move business logic from components into services.
- But you still want to test it through Storybook.
- This feature does not require any setup. It relies on the official
@storybook/angular
implementation.
- It simply injects the service into an
APP_INITIALIZER
which runs before the Angular
application starts.
- When the initializer runs, it puts the service instance into
parameters.providers
which you can retrieve in the play function like so:
const meta: Meta = {
title: 'Services/AppService',
decorators: [
moduleMetadata({
imports: [AppModule, CommonModule],
providers: [AppService],
}),
],
};
export default meta;
export const Primary: StoryObj = {
play: async ({ parameters: { providers } }) => {
const appService: AppService = providers.AppService;
expect(appService).toBeTruthy();
},
};
Documentation Lazy Loading
- This feature uses
fetch
to load the documentation.json
file during runtime, specifically in the preview iframe before the load of each story.
- This is very helpful if you are doing active development and your documentation is being updated regularly.
- This is also helpful if your application is already published along with its documentation and you need to load that remotely served documentation.
Here is a simple example of the first scenario:
// .storybook/main.ts
import { StorybookConfig } from '@storybook/angular';
import { ExtrasConfig } from '@storybook-extras/preset';
const config: StorybookConfig & ExtrasConfig = {
staticDirs: [{ from: '<DOCS_DIR_PATH>', to: '/<DOCS_SERVE_DIR>' }],
}
export default config;
- Next, enable the documentation lazy loading in the
preview.@(js|ts)
file like so:
export const parameters = {
...
docs: {
inlineStories: true,
...
fetch: '<DOCS_SERVE_DIR>/documentation.json'
}
}
The url property here can be a full url like http://example.com/storybook/docs/documentation.json
or a relative path to the current storybook instance like ../dist/docs/documentation.json
.
You can also provide compodoc
property to be something like require('<DOCS_DIR_PATH>/documentation.json')
or have it imported already with import compodoc from '<DOCS_DIR_PATH>/documentation.json
, this way you don't need to call setCompodocJson
method, it will be called automatically on your behalf, and the docs will be stored in memory for later usage.
Source Code
Wrappers Selector
- This feature uses
componentWrapperDecorator
from the official @storybook/angular
to render wrapper elements dynamically around stories.
- This simply reads a list of pre-defined wrapper elements from the global parameters or each individual story parameters.
- This allows you to change the wrapper element during runtime instead of having static decorator all the time.
- This is very helpful specially if you want to see how your components render inside a root component with header and footer, or just simply inside a specific parent element.
Configuration
- This toolbar menu works very similar to the official
@storybook/addon-backgrounds
addon.
- The configuration looks something like this:
In preview.js
or preview.ts
:
export const parameters = {
wrappers: {
disable: false,
default: 'None',
values: [
{ name: 'None', value: '' },
{ name: 'Container', value: 'app-container' },
{ name: 'Root', value: 'app-root' },
],
},
};
In a story file like button.stories.ts
:
import { type StoryObj, type Meta } from '@storybook/angular';
import Button from './button.component';
const meta: Meta<Button> = {
title: 'Example/Button',
component: Button,
parameters: {
wrappers: {
default: 'None',
values: [
{ name: 'None', value: '' },
{
name: 'Button Container',
value: 'btn-container',
options: {
class: 'small',
style: 'padding:5px;',
},
},
{ name: 'Container', value: 'app-container' },
{ name: 'Root', value: 'app-root' },
],
},
},
};
export default meta;
The wrapper item can also contain an options
property which will be translated into HTML attributes for the wrapper. For example; the configuration above will render the following if Button Container
is selected:
<btn-container class="small" style="padding:5px;"></btn-container>
Roadmap
Please feel free to request features, I will try to add them as soon as humanly possible. Currently the following features are in my pipeline:
- UI representation of Angular Service.
- UI representation for Issues/Pull Requests (Github/Bitbucket/Jira).
- Coverage Enhancements.
- Story Source representation.