@storybook-extras/angular
v0.0.68
Published
Storybook addon to add extra configurations for Angular applications.
Downloads
590
Maintainers
Readme
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 forStorybook
onAngular
. - 🐈 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 theAngular
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 thedocumentation.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:
- execute compodoc into a specific directory
compodoc -e json -d dist/docs
- Make sure to include static dir like so
// .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
- This feature relies on the documentation loaded previously from
compodoc
to display the source code of the components and/or services that exists in themoduleMetadata
. - You don't need to re-declare your main component in the
declarations
section ofmoduleMetadata
, it will be added directly. - Basically, the addon will retrieve the source code of any class under
declarations
orproviders
, along with templates & styles for the components if they exist. - No setup is needed for this feature, it is enabled by default.
- You can disable it by using global or story parameters like so:
parameters: { sourceCode: { disable: true; } }
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.