diff --git a/addons/jest/README.md b/addons/jest/README.md index 1e0956347a4..5a75fce42ca 100644 --- a/addons/jest/README.md +++ b/addons/jest/README.md @@ -1,28 +1,36 @@ # Storybook addon Jest -Brings Jest results in storybook. +Storybook addon for inspecting Jest unit test results. [Framework Support](https://github.com/storybookjs/storybook/blob/main/ADDONS_SUPPORT.md) [![Storybook Jest Addon Demo](https://raw.githubusercontent.com/storybookjs/storybook/next/addons/jest/docs/storybook-addon-jest.gif)](http://storybooks-official.netlify.com/?selectedKind=Addons%7Cjest&selectedStory=withTests&full=0&addons=1&stories=1&panelRight=0&addonPanel=storybook%2Ftests%2Fpanel) -> Checkout the above [Live Storybook](http://storybooks-official.netlify.com/?selectedKind=Addons%7Cjest&selectedStory=withTests&full=0&addons=1&stories=1&panelRight=0&addonPanel=storybook%2Ftests%2Fpanel). +> Check out the above [Live Storybook](http://storybooks-official.netlify.com/?selectedKind=Addons%7Cjest&selectedStory=withTests&full=0&addons=1&stories=1&panelRight=0&addonPanel=storybook%2Ftests%2Fpanel). -## Getting started +## Installation -### Install +Install this addon by adding the `@storybook/addon-jest` as a development dependency with: `npm install --save-dev @storybook/addon-jest` -or +Or if you're using yarn as a package manager: `yarn add --dev @storybook/addon-jest` -### Jest Configuration +## Configuration -When running **Jest**, be sure to save the results in a json file: +Register the addon in your [`.storybook/main.js`](https://storybook.js.org/docs/react/configure/overview#configure-your-storybook-project): -`package.json` +```js +module.exports = { + addons: ['@storybook/addon-jest'], +}; +``` + +## Jest Configuration + +When running **Jest**, be sure to save the results in a JSON file: ```js "scripts": { @@ -30,30 +38,27 @@ When running **Jest**, be sure to save the results in a json file: } ``` -You may want to add it the result file to `.gitignore`, since it's a generated file: +You may want to add the result file to `.gitignore`, since it's a generated file: ``` .jest-test-results.json ``` -But much like lockfiles and snapshots checking-in generated files can have certain advantages as well. It's up to you. -We recommend to **do** check in the test results file so starting storybook from an clean git clone doesn't require running all tests first, -but this can mean you'll experience merge conflicts on this file in the future. (_re-generating this file is very similar to re-generating lockfiles and snapshots_) +But much like lockfiles and snapshots, checking-in generated files can have certain advantages as well. It's up to you. +We recommend to **do** check in the test results file so starting Storybook from a clean git clone doesn't require running all tests first, +but this can mean you'll encounter merge conflicts on this file in the future (_re-generating this file is very similar to re-generating lockfiles and snapshots_). -## Generating the test results +### Generating the test results -You need to make sure the generated test-results file exists before you start storybook. -During development you will likely start jest in watch-mode -and so the json file will be re-generated every time code or tests change. +Ensure the generated test-results file exists before you start Storybook. During development, you will likely start Jest in watch-mode and so the JSON file will be re-generated every time code or tests change. ```sh npm run test:generate-output -- --watch ``` -This change will then be HMR (hot module reloaded) using webpack and displayed by this addon. +This change will then be HMR (hot module reloaded) using Webpack and displayed by the addon. -If you want to pre-run jest automatically during development or a static build, -you may need to consider that if your tests fail, the script receives a non-0 exit code and will exit. +If you want to pre-run Jest automatically during development or a static build, you may need to consider that if your tests fail, the script receives a non-0 exit code and will exit. You could create a `prebuild:storybook` npm script, which will never fail by appending `|| true`: ```json @@ -67,125 +72,175 @@ You could create a `prebuild:storybook` npm script, which will never fail by app } ``` -### Register - -within `.storybook/main.js`: - -```js -module.exports = { - addons: ['@storybook/addon-jest'], -}; -``` - ## Usage -Assuming that you have created test files `MyComponent.test.js` and `MyOtherComponent.test.js` +Assuming that you have already created a test file for your component (e.g., `MyComponent.test.js`). -In your `story.js` +### Story-level + +In your story file, add a [decorator](https://storybook.js.org/docs/react/writing-stories/decorators) to your story's default export to display the results: ```js +// MyComponent.stories.js | MyComponent.stories.jsx + +import MyComponent from './MyComponent'; + import results from '../.jest-test-results.json'; + import { withTests } from '@storybook/addon-jest'; export default { + component: MyComponent, title: 'MyComponent', decorators: [withTests({ results })], }; +``` -export const defaultView = () =>
Jest results in storybook
; -defaultView.parameters = { - jest: ['MyComponent.test.js', 'MyOtherComponent.test.js'], +You can also add multiple tests results within your story by including the `jest` [parameter](https://storybook.js.org/docs/react/writing-stories/parameters), for example: + +```js +// MyComponent.stories.js | MyComponent.stories.jsx + +import MyComponent from './MyComponent'; + +import results from '../.jest-test-results.json'; + +import { withTests } from '@storybook/addon-jest'; + +export default { + component: MyComponent, + title: 'MyComponent', + decorators: [withTests({ results })], +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); +Default.args = { + text: 'Jest results in Storybook', +}; +Default.parameters = { + jest: ['MyComponent.test.js', 'MyOtherComponent.test.js'] }; ``` -Or in order to avoid importing `.jest-test-results.json` in each story, add the decorator in your `.storybook/preview.js` and results will display for stories that you have set the `jest` parameter on: +### Global level + +To avoid importing the results of the tests in each story, you can update +your [`.storybook/preview.js`](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering) and include a decorator allowing you to display the results only for the stories that have the `jest` parameter defined: ```js -import { addDecorator } from '@storybook/react'; // <- or your view layer -import { withTests } from '@storybook/addon-jest'; +// .storybook/preview.js + +import { withTests } from "@storybook/addon-jest"; import results from '../.jest-test-results.json'; -addDecorator( +export const decorators = [ withTests({ results, - }) -); + }), +]; ``` -Then in your story: +Then in your story file: ```js -import React from 'react'; +// MyComponent.stories.js | MyComponent.stories.jsx + +import MyComponent from './MyComponent'; export default { + component: MyComponent, title: 'MyComponent', }; -export const defaultView = () =>
Jest results in storybook
; -defaultView.parameters = { - jest: ['MyComponent.test.js', 'MyOtherComponent.test.js'], +const Template = (args) => ; + +export const Default = Template.bind({}); +Default.args={ + text: 'Jest results in Storybook', +}; +Default.parameters = { + jest: ['MyComponent.test.js'], }; ``` -The jest parameter will default to inferring from your story file name if not provided. For example, if your story file is `MyComponent.stories.js`, -then "MyComponent" will be used to find your test file results. This currently doesn't work in production environments. +The `jest` parameter will default to inferring from your story file name if not provided. For example, if your story file is `MyComponent.stories.js`, +then "MyComponent" will be used to find your test file results. It currently doesn't work in production environments. ### Disabling You can disable the addon for a single story by setting the `jest` parameter to `{disable: true}`: ```js -import React from 'react'; +import MyComponent from './MyComponent'; export default { + component: MyComponent, title: 'MyComponent', }; -export const defaultView = () =>
Jest results in storybook
; -defaultView.parameters = { +const Template = (args) => ; + +export const Default = Template.bind({}); + +Default.args={ + text: 'Jest results in Storybook', +}; +Default.parameters = { jest: { disable: true }, }; ``` -### withTests(options) - -- **options.results**: OBJECT jest output results. _mandatory_ -- **filesExt**: STRING test file extension. _optional_. This allows you to write "MyComponent" and not "MyComponent.test.js". It will be used as regex to find your file results. Default value is `((\\.specs?)|(\\.tests?))?(\\.js)?$`. That means it will match: MyComponent.js, MyComponent.test.js, MyComponent.tests.js, MyComponent.spec.js, MyComponent.specs.js... - ## Usage with Angular -Assuming that you have created test files `my.component.spec.ts` and `my-other.component.spec.ts` +Using this addon with Angular will require some additional configuration. You'll need to install and configure Jest with [jest-preset-angular](https://www.npmjs.com/package/jest-preset-angular). -Configure Jest with [jest-preset-angular](https://www.npmjs.com/package/jest-preset-angular) +Then, in your `.storybook/preview.js`, you'll need to add a decorator with the following: -In project's `typings.d.ts` add - -```ts -declare module '*.json' { - const value: any; - export default value; -} -``` - -In your `.storybook/preview.ts`: - -```ts -import { addDecorator } from '@storybook/angular'; +```js import { withTests } from '@storybook/addon-jest'; import results from '../.jest-test-results.json'; -addDecorator( +export const decorators = [ withTests({ results, - filesExt: '((\\.specs?)|(\\.tests?))?(\\.ts)?$', - }) -); + filesExt: "((\\.specs?)|(\\.tests?))?(\\.ts)?$", + }), +]; +``` + +Finally, in your story, you'll need to include the following: + +```ts +import { Meta, Story } from '@storybook/angular/types-6-0'; + +import MyComponent from './MyComponent.component'; + +export default { + component: MyComponent, + title: 'MyComponent', +} as Meta; + +const Template: Story = (args: MyComponent) => ({ + props: args, +}); + +export const Default = Template.bind({}); +Default.parameters = { + jest: ['MyComponent.component'], +}; ``` ##### Example [here](https://github.com/storybookjs/storybook/tree/main/examples/angular-cli) +## Available options + +- **options.results**: OBJECT jest output results. _mandatory_ +- **filesExt**: STRING test file extension. _optional_. This allows you to write "MyComponent" and not "MyComponent.test.js". It will be used as regex to find your file results. Default value is `((\\.specs?)|(\\.tests?))?(\\.js)?$`. That means it will match: MyComponent.js, MyComponent.test.js, MyComponent.tests.js, MyComponent.spec.js, MyComponent.specs.js... + ## TODO - [ ] Add coverage @@ -197,7 +252,7 @@ addDecorator( ## Contributing -All ideas and contributions are welcomed. +All ideas and contributions are welcome. ## Licence diff --git a/addons/jest/docs/storybook-addon-jest.gif b/addons/jest/docs/storybook-addon-jest.gif index 4e94db960f2..6b52be69a10 100644 Binary files a/addons/jest/docs/storybook-addon-jest.gif and b/addons/jest/docs/storybook-addon-jest.gif differ