Merge pull request #11701 from storybookjs/migrate_workflows_6_0
Migrate Workflows section to 6 0
17
docs/toc.js
@ -21,5 +21,22 @@ module.exports = {
|
||||
prefix: 'writing-docs',
|
||||
pages: ['introduction', 'docs-page', 'mdx', 'doc-blocks'],
|
||||
},
|
||||
{
|
||||
title:'Workflows',
|
||||
prefix:'workflows',
|
||||
pages:[
|
||||
'publish-storybook',
|
||||
'build-pages-with-storybook',
|
||||
'stories-for-multiple-components',
|
||||
'testing-with-storybook',
|
||||
'unit-testing',
|
||||
'visual-testing',
|
||||
'interaction-testing',
|
||||
'snapshot-testing',
|
||||
'storybook-composition',
|
||||
'package-composition'
|
||||
|
||||
]
|
||||
}
|
||||
],
|
||||
};
|
||||
|
BIN
docs/workflows/argstable-subcomponents.png
Normal file
After Width: | Height: | Size: 12 KiB |
133
docs/workflows/build-pages-with-storybook.md
Normal file
@ -0,0 +1,133 @@
|
||||
---
|
||||
title: 'Building pages with Storybook'
|
||||
---
|
||||
|
||||
Storybook helps you build any component, from small “atomic” components to composed pages. But as you move up the component hierarchy toward the level of pages, you end up dealing with more complexity.
|
||||
|
||||
There are many ways to build pages in Storybook. Here are common patterns and solutions.
|
||||
|
||||
- Pure presentational pages.
|
||||
- Connected components (e.g. network requests, context, browser environment).
|
||||
|
||||
### Pure presentational pages
|
||||
|
||||
Teams at the BBC, The Guardian, and the Storybook maintainers themselves build pure presentational pages. If you take this approach, you don't need to do anything special to render your pages in Storybook.
|
||||
|
||||
It's straightforward to write components to be fully presentational all the way up to the screen level. That makes it easy to show in Storybook. The idea is you then do all the messy “connected” logic in a single wrapper component in your app outside of Storybook. You can see an example of this approach in the [Data](https://www.learnstorybook.com/intro-to-storybook/react/en/data/) chapter of Learn Storybook.
|
||||
|
||||
The benefits:
|
||||
|
||||
- Easy to write stories once components are in this form.
|
||||
- All the data for the story is encoded in the args of the story, which works well with other parts of Storybook's tooling (e.g. [controls](../essentials/controls)).
|
||||
|
||||
The downsides:
|
||||
|
||||
- Your existing app may not be structured in this way and it may be difficult to change it.
|
||||
|
||||
- Fetching data in one place means that you need to drill it down to the components that actually use it. This can be natural in a page that composes one big GraphQL query (for instance), but in other data fetching approaches may make this less appropriate.
|
||||
|
||||
- It's less flexible if you want to load data incrementally in different places on the screen.
|
||||
|
||||
#### Args composition for presentational screens
|
||||
|
||||
When you are building screens in this way, it is typical that the inputs of a composite component are a combination of the inputs of the various sub-components it renders. For instance, if your screen renders a page layout (containing details of the current user), a header (describing the document you are looking at), and a list (of the subdocuments), the inputs of the screen may consist of the user, document and subdocuments.
|
||||
|
||||
```js
|
||||
// your-page.js
|
||||
|
||||
import React from 'react';
|
||||
import PageLayout from './PageLayout';
|
||||
import DocumentHeader from './DocumentHeader';
|
||||
import DocumentList from './DocumentList';
|
||||
|
||||
function DocumentScreen({ user, document, subdocuments }) {
|
||||
return (
|
||||
<PageLayout user={user}>
|
||||
<DocumentHeader document={document} />
|
||||
<DocumentList documents={subdocuments} />
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
In such cases it is natural to use [args composition](../writing-stories/args#args-composition) to build the stories for the page based on the stories of the sub-components:
|
||||
|
||||
```js
|
||||
// your-page.story.js
|
||||
|
||||
import React from 'react';
|
||||
import DocumentScreen from './DocumentScreen';
|
||||
|
||||
import PageLayout from './PageLayout.stories';
|
||||
import DocumentHeader from './DocumentHeader.stories';
|
||||
import DocumentList from './DocumentList.stories';
|
||||
|
||||
export default {
|
||||
component: DocumentScreen,
|
||||
title: 'DocumentScreen',
|
||||
}
|
||||
|
||||
const Template = (args) => <DocumentScreen {...args} />;
|
||||
|
||||
export const Simple = Template.bind({});
|
||||
Simple.args = {
|
||||
user: PageLayout.Simple.user,
|
||||
document: DocumentHeader.Simple.document,
|
||||
subdocuments: DocumentList.Simple.documents,
|
||||
};
|
||||
```
|
||||
|
||||
This approach is particularly useful when the various subcomponents export a complex list of different stories, which you can pick and choose to build realistic scenarios for your screen-level stories without repeating yourself. By reusing the data and taking a Don't-Repeat-Yourself(DRY) philosophy, your story maintenance burden is minimal.
|
||||
|
||||
### Mocking connected components
|
||||
|
||||
Render a connected component in Storybook by mocking the network requests that it makes to fetch its data. There are various layers in which you can do that.
|
||||
|
||||
#### Mocking providers
|
||||
|
||||
If you are using a provider that supplies data via the context, you can wrap your story in a decorator that supplies a mocked version of that provider. For example, in the [Screens](https://www.learnstorybook.com/intro-to-storybook/react/en/screen/) chapter of Learn Storybook we mock a Redux provider with mock data.
|
||||
|
||||
Additionally, there may be addons that supply such providers and nice APIs to set the data they provide. For instance [`storybook-addon-apollo-client`](https://www.npmjs.com/package/storybook-addon-apollo-client) provides this API:
|
||||
|
||||
```js
|
||||
// my-component-with-query.story.js
|
||||
|
||||
import MyComponentThatHasAQuery, {
|
||||
MyQuery,
|
||||
} from '../component-that-has-a-query';
|
||||
|
||||
export const LoggedOut = () => <MyComponentThatHasAQuery />;
|
||||
LoggedOut.parameters: {
|
||||
apolloClient: {
|
||||
mocks: [
|
||||
{ request: { query: MyQuery }, result: { data: { viewer: null } } },
|
||||
],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
#### Mocking imports
|
||||
|
||||
It is also possible to mock imports directly, similar to Jest, using webpack’s aliasing. This is useful if your component makes network requests directly.
|
||||
|
||||
|
||||
```js
|
||||
// .storybook/main.js
|
||||
module.exports = {
|
||||
// your Storybook configuration
|
||||
|
||||
webpackFinal: config => {
|
||||
config.resolve.alias.fetch = '../__mocks__/fetch.js'
|
||||
return config;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
You would still need to write the fetch mock and wire up a decorator to provide results to it based on the current story.
|
||||
|
||||
#### Specific mocks
|
||||
|
||||
Another mocking approach is to use libraries that intercept calls at a lower level. For instance you can use [`fetch-mock`](https://www.npmjs.com/package/fetch-mock) to mock fetch requests specifically, or [`msw`](https://www.npmjs.com/package/msw) to mock all kinds of network traffic.
|
||||
|
||||
Similar to the import mocking above, once you have a mock you’ll still want to set the return value of the mock on a per-story basis. Do this in Storybook with a decorator that reads story parameters.
|
||||
|
BIN
docs/workflows/combine-storybooks.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
docs/workflows/component-unit-testing.gif
Normal file
After Width: | Height: | Size: 319 KiB |
BIN
docs/workflows/component-visual-testing.gif
Normal file
After Width: | Height: | Size: 499 KiB |
BIN
docs/workflows/composition-versioning.png
Normal file
After Width: | Height: | Size: 14 KiB |
23
docs/workflows/interaction-testing.md
Normal file
@ -0,0 +1,23 @@
|
||||
---
|
||||
title: 'Interaction testing'
|
||||
---
|
||||
|
||||
Stories are useful for verifying the known states of a component. But sometimes you need to test how a component changes in response to user interaction.
|
||||
|
||||
Stories are convenient **starting points** and **harnesses** for interaction tests using end-to-end tools like [Enzyme](https://enzymejs.github.io/enzyme/) and [Cypress](https://www.cypress.io/).
|
||||
|
||||
Luckily, this is straightforward. Point your interaction testing tool at Storybook’s isolated iframe [URL for a specific story](../configure/user-interface#permalinking-to-stories) then execute the test script as usual. Here’s an example using Cypress:
|
||||
|
||||
```js
|
||||
// My-component_spec.js
|
||||
|
||||
describe('My Component', () => {
|
||||
it('should respond to click on button with warning', () => {
|
||||
cy.visit('http://localhost:6006/iframe.html?id=my-component--basic-story’);
|
||||
cy.get('#button').click();
|
||||
cy.get('#warning').should('contain.text', 'You need to fill in the form!');
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
|
96
docs/workflows/package-composition.md
Normal file
@ -0,0 +1,96 @@
|
||||
---
|
||||
title: 'Package Composition'
|
||||
---
|
||||
|
||||
Storybook is widely used by component libraries and design systems. Design system authors can automatically compose their design systems inside their consumer’s Storybooks.
|
||||
|
||||
For example, if you use a design system package, its stories can appear alongside your own. That makes it convenient to cross reference usage documentation without leaving Storybook.
|
||||
|
||||
### For package consumers
|
||||
|
||||
Composition happens automatically if the package [supports](#for-package-authors) it. When you install the package, Storybook will load its stories alongside your own.
|
||||
|
||||

|
||||
|
||||
#### Configuring
|
||||
|
||||
If you want to configure how the composed Storybook behaves, you can disable the `ref` element in your [`.storybook/main.js`](../configure/overview#configure-story-rendering)
|
||||
|
||||
```js
|
||||
// .storybook/main.js
|
||||
|
||||
module.exports = {
|
||||
// your Storybook configuration
|
||||
refs: {
|
||||
'package-name': { disable: true }
|
||||
}
|
||||
```
|
||||
|
||||
#### Changing versions
|
||||
|
||||
Change the version of the composed Storybook to see how the library evolves. This requires [configuration](#providing-a-version-section) from the package author.
|
||||
|
||||

|
||||
|
||||
### For package authors
|
||||
|
||||
Component library authors can expand adoption by composing their components in their consumer’s Storybooks.
|
||||
|
||||
Add a `storybook` property in your published `package.json `that contains an object with a `url` field. Point the URL field to a published Storybook at the version you want.
|
||||
|
||||
```json
|
||||
// Your component library’s package.json
|
||||
{
|
||||
"storybook": {
|
||||
"url": "https://host.com/your-storybook-for-this-version"
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### Automatic version selection
|
||||
|
||||
If you are using a [CHP level 1 service](#chp-level-1) for hosting (such as [Chromatic.com](https://www.chromatic.com/)), you can provide a single URL for your Storybook in the `storybook.url` field. You do not need to change the URL each time you publish a new version. Storybook will automatically find the correct URL for your package.
|
||||
|
||||
For example, for Chromatic, you might do:
|
||||
|
||||
```json
|
||||
{
|
||||
"storybook": {
|
||||
"url": "https://master--xyz123.chromatic.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In this example `xyz123` is your project’s id. Storybook will automatically compose in the Storybook published to that project corresponding to the version the user has installed.
|
||||
|
||||
#### Providing a version section
|
||||
|
||||
Similarly, if you're using a [CHP level 1 service](#chp-level-1) (such as chromatic.com) for hosting, you can provide a list of versions for the user to [choose from](#changing-versions) to experiment with other versions of your package.
|
||||
|
||||
### Component Hosting Protocol (CHP)
|
||||
|
||||
Storybook can communicate with services that host built Storybooks online. This enables features such as [Composition](./storybook-composition). We categorize services via compliance with the "Component Hosting Protocol" (CHP) with various levels of support in Storybook.
|
||||
|
||||
#### CHP level 1
|
||||
|
||||
<div style="background-color:#F8FAFC">
|
||||
TODO: "version=x.y.z query parameter".(vet this)
|
||||
</div>
|
||||
|
||||
The service serves uploaded Storybooks and makes the following available:
|
||||
|
||||
- Versioned endpoints, URLs that resolve to different published Storybooks depending on a version=x.y.z query parameter.
|
||||
- Support for /stories.json
|
||||
- Support for /metadata.json and the releases field.
|
||||
|
||||
Examples of such services:
|
||||
- [chromatic.com](https://www.chromatic.com/)
|
||||
|
||||
#### CHP level 0
|
||||
|
||||
The service can serve uploaded Storybooks. There is no special integration with Storybook APIs.
|
||||
|
||||
Examples of such services:
|
||||
- [Netlify](https://www.netlify.com/)
|
||||
- [S3](https://aws.amazon.com/en/s3/)
|
BIN
docs/workflows/package-composition.png
Normal file
After Width: | Height: | Size: 12 KiB |
57
docs/workflows/publish-storybook.md
Normal file
@ -0,0 +1,57 @@
|
||||
---
|
||||
title: 'Publish Storybook'
|
||||
---
|
||||
|
||||
Storybook is more than a UI component development tool. Teams also publish Storybook online to review and collaborate on works in progress. That allows developers, designers, and PMs to check if UI looks right without touching code or needing a local dev environment.
|
||||
|
||||
### Build Storybook as a static web application
|
||||
|
||||
First, we’ll need to build Storybook as a static web application using `build-storybook`, a command that’s installed by default.
|
||||
|
||||
```shell
|
||||
yarn build-storybook -o ./path/to/build
|
||||
```
|
||||
|
||||
Storybook will create a static web application at the path you specify. This can be served by any web server. Try it out locally by running:
|
||||
|
||||
```shell
|
||||
npx http-server ./path/to/build
|
||||
```
|
||||
|
||||
### Publish Storybook online
|
||||
|
||||
Once your Storybook is built as a static web app it can be deployed to any static site hosting services. The Storybook team uses [Chromatic](https://www.chromatic.com/), a free publishing service made by Storybook maintainers that documents, versions, and indexes your UI components securely in the cloud.
|
||||
|
||||
We also maintain [`storybook-deployer`](https://github.com/storybookjs/storybook-deployer) to deploy to GitHub pages or AWS S3.
|
||||
|
||||
<video autoPlay muted playsInline loop>
|
||||
<source
|
||||
src="storybook-publish-review-optimized.mp4"
|
||||
type="video/mp4"
|
||||
/>
|
||||
</video>
|
||||
|
||||
### Review with your team
|
||||
|
||||
Publishing Storybook as part of the development process makes it quick and easy to [gather team feedback](https://www.learnstorybook.com/design-systems-for-developers/react/en/review/).
|
||||
|
||||
A common method to ask for review is to paste a link to the published Storybook in a pull request or Slack.
|
||||
|
||||
If you publish your Storybook to Chromatic, you can use the [UI Review](https://www.chromatic.com/features/publish) feature to automatically scan your PRs for new and updated stories. That makes it easy to identify what changed and give feedback.
|
||||
|
||||

|
||||
|
||||
### Reference external Storybooks
|
||||
|
||||
Storybook allows you to browse components from any [Storybook published online](./storybook-composition) inside your local Storybook. It unlocks common workflows that teams often struggle with:
|
||||
|
||||
- 👩💻 UI developers can quickly reference prior art without switching between Storybooks.
|
||||
- 🎨 Design systems can expand adoption by composing themselves into their users’ Storybooks.
|
||||
- 🛠 Frontend platform can audit how components are used across projects.
|
||||
|
||||
|
||||

|
||||
|
||||
Toggle between multiple versions of Storybook to see how components change between versions. This is useful for design system package authors who maintain many versions at once.
|
||||
|
||||
**Requires** a [CHP level 1](./package-composition#chp-level-1) server (such as [chromatic.com](https://www.chromatic.com/)),
|
BIN
docs/workflows/reference-external-storybooks-composition.jpg
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
docs/workflows/snapshot-test.png
Normal file
After Width: | Height: | Size: 14 KiB |
54
docs/workflows/snapshot-testing.md
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
title: '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.
|
||||
|
||||
Storybook is a convenient tool for snapshot testing because every story is essentially a test specification. Any time you write or update a story you get a snapshot test for free.
|
||||
|
||||
> Snapshot vs visual tests. Visual tests take screenshots of stories and compare them against known baselines. When used to test appearance, visual tests are often a more robust solution than snapshot tests because verifying markup doesn’t test for visual changes.
|
||||
|
||||
Storyshots is an [official addon](https://github.com/storybookjs/storybook/tree/master/addons/storyshots/storyshots-core) that enables snapshot testing. It’s powered by Jest so you’ll need to [install that](https://jestjs.io/docs/en/getting-started) first. Continue on if you already have Jest.
|
||||
|
||||
Install the addon. **Make sure** the version of Storyshots and your project’s Storybook version are identical.
|
||||
|
||||
```shell
|
||||
yarn add --dev @storybook/addon-storyshots
|
||||
```
|
||||
|
||||
Configure Storyshots by adding the following test file to your project:
|
||||
|
||||
```js
|
||||
// storybook.test.js
|
||||
|
||||
import initStoryshots from '@storybook/addon-storyshots';
|
||||
initStoryshots();
|
||||
```
|
||||
|
||||
> You can name the file whatever you like as long as it's picked up by Jest.
|
||||
|
||||
|
||||
Run your first test. Storyshot will recognize all your CSF files (based on [`.storybook/main.js`](../configure/overview#configure-story-rendering)) and produces snapshots.
|
||||
|
||||
```shell
|
||||
yarn test storybook.test.js
|
||||
```
|
||||
|
||||
<div style="background-color:#F8FAFC">
|
||||
TODO: ask for clarification on this note below. What extra steps?
|
||||
</div>
|
||||
|
||||
> If you are loading stories via `.storybook/main.js`, you will need to follow some more steps to ensure Jest finds them.
|
||||
|
||||
|
||||
This will create an initial set of snapshots inside your Storybook config directory.
|
||||
|
||||

|
||||
|
||||
When you make changes to your components or stories, run the test again to identify the changes to the rendered markup.
|
||||
|
||||

|
||||
|
||||
If the changes are intentional we can accept them as new baselines. If the changes are bugs, fix the underlying code then run the snapshot tests again.
|
||||
|
||||
Storyshots has many options for advanced use cases; read more in the [addon’s documentation](https://github.com/storybookjs/storybook/tree/master/addons/storyshots/storyshots-core).
|
107
docs/workflows/stories-for-multiple-components.md
Normal file
@ -0,0 +1,107 @@
|
||||
---
|
||||
title: 'Stories for multiple components'
|
||||
---
|
||||
|
||||
It's useful to write stories that [render two or more components](../writing-stories/introduction#stories-for-two-or-more-components) at once if those components are designed to work together. For example, `ButtonGroups`, `Lists`, and `Page` components.
|
||||
|
||||
```js
|
||||
// List.story.js
|
||||
|
||||
import List from './List';
|
||||
import ListItem from './ListItem';
|
||||
|
||||
export default {
|
||||
component: List,
|
||||
subcomponents: [ListItem],
|
||||
title: 'List',
|
||||
};
|
||||
|
||||
export const Empty = (args) => <List {...args} />;
|
||||
|
||||
export const OneItem = (args) => (
|
||||
<List {...args}>
|
||||
<ListItem />
|
||||
</List>
|
||||
);
|
||||
```
|
||||
Note that by adding `subcomponents` to the default export, we get an extra pane on the ArgsTable, listing the props of `ListItem`:
|
||||
|
||||

|
||||
|
||||
The downside of the above approach is that it does not take advantage of Storybook [Args](../writing-stories/args) meaning:
|
||||
|
||||
1. You cannot change the stories via the controls panel
|
||||
2. There is no [args reuse](../writing-stories/introduction#using-args) possible, which makes the stories harder to maintain.
|
||||
|
||||
Let's talk about some techniques you can use to mitigate the above, which are especially useful in more complicated situations.
|
||||
|
||||
### Reusing subcomponent stories
|
||||
|
||||
The simplest change we can make to the above is to reuse the stories of the `ListItem` in the `List`:
|
||||
|
||||
```js
|
||||
// List.story.js
|
||||
|
||||
import List from './List';
|
||||
// Instead of importing the ListItem, we import its stories
|
||||
import { Unchecked } from './ListItem.stories';
|
||||
|
||||
export const OneItem = (args) => (
|
||||
<List {...args}>
|
||||
<Unchecked {...Unchecked.args} />
|
||||
</List>
|
||||
);
|
||||
```
|
||||
|
||||
By rendering the `Unchecked` story with its args, we are able to reuse the input data from the `ListItem` stories in the `List`.
|
||||
|
||||
However, we still aren’t using args to control the `ListItem` stories, which means we cannot change them with controls and we cannot reuse them in other, more complex component stories.
|
||||
|
||||
|
||||
### Using children as an arg
|
||||
|
||||
One way we improve that situation is by pulling the render subcomponent out into a `children` arg:
|
||||
|
||||
```js
|
||||
// List.story.js
|
||||
|
||||
const Template = (args) => <List {...args} />
|
||||
|
||||
export const OneItem = Template.bind({});
|
||||
OneItem.args = {
|
||||
children: <Unchecked {...Unchecked.args} />
|
||||
}
|
||||
```
|
||||
|
||||
Now that `children` is an arg, we can potentially reuse it in another story. As things stand (we hope to improve this soon) you cannot edit children in a control yet.
|
||||
|
||||
### Creating a Template Component
|
||||
|
||||
Another option that is more “data”-based is to create a special “story-generating” template component:
|
||||
|
||||
```js
|
||||
// List.story.js
|
||||
|
||||
import React from 'react';
|
||||
import List from './List';
|
||||
import ListItem from './ListItem';
|
||||
import { Unchecked } from './ListItem.stories';
|
||||
|
||||
const ListTemplate = ({ items, ...args }) => (
|
||||
<List>
|
||||
{items.map(item => <ListItem {...item} />)}
|
||||
</List>
|
||||
);
|
||||
|
||||
export const Empty = ListTemplate.bind({});
|
||||
Empty.args = { items: [] };
|
||||
|
||||
export const OneItem = ListTemplate.bind({});
|
||||
OneItem.args = { items: [Unchecked.args] };
|
||||
```
|
||||
|
||||
This approach is a little more complex to setup, but it means you can more easily reuse the `args` to each story in a composite component. It also means that you can alter the args to the component with the Controls addon:
|
||||
|
||||
<div style="background-color:#F8FAFC">
|
||||
TODO: mention of a gif in the SB 6.0 doc (needs to be vetted)
|
||||
</div>
|
53
docs/workflows/storybook-composition.md
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
title: 'Storybook Composition'
|
||||
---
|
||||
|
||||
Composition allows you to embed components from any Storybook inside your local Storybook.
|
||||
|
||||
It’s made for teams who adopt Storybook in multiple projects but can’t ensure that the projects have the same tech stack or share the same repo.
|
||||
|
||||
You can compose any Storybook [published online](./publish-storybook) or running locally no matter the view layer, tech stack, or dependencies.
|
||||
|
||||

|
||||
|
||||
### Compose published Storybooks
|
||||
|
||||
In your [`storybook/main.js`](../configure/overview#configure-story-rendering) file add a `refs` field with information about the reference Storybook. Pass in a URL to a statically built Storybook.
|
||||
|
||||
```js
|
||||
//.storybook/main.js
|
||||
module.exports={
|
||||
// your Storybook configuration
|
||||
refs: {
|
||||
'design-system': {
|
||||
title: "Storybook Design System",
|
||||
url: "https://5ccbc373887ca40020446347-yldsqjoxzb.chromatic.com"
|
||||
}
|
||||
}`
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Compose local Storybooks
|
||||
|
||||
You can also compose Storybook that are running locally. For instance, if you have a React Storybook and a Angular Storybook running on different ports:
|
||||
|
||||
```js
|
||||
//.storybook/main.js
|
||||
module.exports={
|
||||
// your Storybook configuration
|
||||
refs: {
|
||||
react: {
|
||||
title: "React",
|
||||
url: 'http://localhost:7007'
|
||||
},
|
||||
angular: {
|
||||
title: "Angular",
|
||||
url: 'http://localhost:7008'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This composes the React and Angular Storybooks into your current Storybook. When either code base changes, hot-module-reload will work perfectly. That enables you to develop both frameworks in sync.
|
||||
|
BIN
docs/workflows/storybook-publish-review-optimized.mp4
Normal file
BIN
docs/workflows/storybook-switch-stories.gif
Normal file
After Width: | Height: | Size: 439 KiB |
BIN
docs/workflows/storyshots-fail.png
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
docs/workflows/storyshots-pass.png
Normal file
After Width: | Height: | Size: 52 KiB |
19
docs/workflows/testing-with-storybook.md
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
title: 'Testing with Storybook'
|
||||
---
|
||||
|
||||
Storybook is a development tool that helps you build components in isolation and record their states as stories. Stories make it easy to explore a component in all its permutations no matter how complex. They also serve as excellent visual test cases.
|
||||
|
||||
A story records a way your component can be used. That means your complete set of stories is a catalogue of all the important use cases to test in your component.
|
||||
|
||||
The simplest testing method is manual. [Publish](./publish-storybook) your Storybook or run it locally, then look at every story to verify its appearance and behavior. This is appropriate for smaller Storybooks.
|
||||
|
||||

|
||||
|
||||
As you add more stories, manual testing becomes infeasible. We recommend automating testing to catch bugs and regressions. A complete Storybook testing strategy combines the following techniques to balance coverage, accuracy, and maintainability:
|
||||
|
||||
- Manual tests rely on developers to manually look at a component to verify it for correctness. They help us sanity check a component’s appearance as we build.
|
||||
- [Unit tests](./unit-testing) verify that the output of a component remains the same given a fixed input. They’re great for testing the functional qualities of a component.
|
||||
- [Visual regression tests](./visual-testing) capturing screenshots of every story and comparing them against known baselines. They’re great for catching UI appearance bugs.
|
||||
- [Interaction tests](./interaction-testing) will render a story and then interact with it in the browser, asserting things about the way it renders and changes.
|
||||
- [Snapshot tests](./snapshot-testing) compare the rendered markup of every story against known baselines. This catches markup changes that cause rendering errors and warnings.
|
32
docs/workflows/unit-testing.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
title: 'Unit testing'
|
||||
---
|
||||
|
||||
Unit tests are useful for verifying functional aspects of components. They verify that the output of a component remains the same given a fixed input.
|
||||
|
||||

|
||||
|
||||
Thanks to the [CSF format](../../formats/component-story-format/), your stories are reusable in unit testing tools. Each [named export](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) is “renderable” without depending on Storybook. That means your testing framework will also be able to render that story.
|
||||
|
||||
Additionally, the Storybook framework packages have an export that makes this easy and doesn’t rely on any other Storybook dependencies.
|
||||
|
||||
Here is an example of how you can use it in a testing library:
|
||||
|
||||
```js
|
||||
// Button.test.js
|
||||
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import '@testing-library/jest-dom/extend-expect';
|
||||
import { renderStory } from '@storybook/react/render';
|
||||
|
||||
import { Primary } from './Button.stories';
|
||||
|
||||
it('renders the button in the primary state’, () => {
|
||||
render(renderStory(Primary));
|
||||
expect(screen.getByRole('button')).toHaveTextContent(‘Primary’);
|
||||
});
|
||||
```
|
||||
|
||||
Unit tests can be brittle and expensive to maintain for _every_ component. We recommend combining unit tests with other testing methods like [visual regression testing](./visual-testing) for comprehensive coverage with less maintenance work.
|
||||
|
29
docs/workflows/visual-testing.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
title: 'Visual Testing'
|
||||
---
|
||||
|
||||
Visual tests, also called visual regression tests, catch bugs in UI appearance. They work by taking screenshots of every story and comparing them commit-to-commit to identify changes.
|
||||
|
||||
This is ideal for verifying what the user sees:
|
||||
|
||||
- 🖼️ Layout.
|
||||
- 🎨 Color.
|
||||
- 📐 Size.
|
||||
- 🔳 Contrast.
|
||||
|
||||
Storybook is a fantastic tool for visual testing because every story is essentially a test specification. Any time you write or update a story you get a spec for free.
|
||||
|
||||
> Visual vs snapshot tests. Snapshot tests compare the rendered markup of every story against known baselines. When used to test how things look, snapshot tests generate a lot of false positives because code changes don’t always yield visual changes.
|
||||
|
||||
|
||||

|
||||
|
||||
There are [many tools](https://github.com/mojoaxel/awesome-regression-testing) for visual testing. Storybook uses [Chromatic](https://www.chromatic.com), a visual testing service made by Storybook maintainers to run tests in the cloud across browsers.
|
||||
|
||||
This prevents UI bugs in our:
|
||||
|
||||
- 🖥️ [Application](https://www.chromatic.com/library?appId=5a375b97f4b14f0020b0cda3).
|
||||
- ⚙️ [Design system](https://www.chromatic.com/library?appId=5ccbc373887ca40020446347)
|
||||
- 🔗 [Website](https://www.chromatic.com/library?appId=5be26744d2f6250024a9117d).
|
||||
|
||||
We also maintain [StoryShots](https://github.com/storybookjs/storybook/tree/master/addons/storyshots), a snapshot testing addon that integrates with [jest-image-snapshot](https://github.com/storybookjs/storybook/tree/master/addons/storyshots#configure-storyshots-for-image-snapshots).
|
BIN
docs/workflows/workflow-publish.png
Normal file
After Width: | Height: | Size: 27 KiB |