mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-04 16:51:09 +08:00
Merge remote-tracking branch 'upstream/next' into feature/typescript-mithril
This commit is contained in:
commit
a7b50f8fea
31
CHANGELOG.md
31
CHANGELOG.md
@ -1,3 +1,28 @@
|
||||
## 5.3.0-alpha.15 (October 8, 2019)
|
||||
|
||||
### Features
|
||||
|
||||
* Addon-docs: support vue inline rendering ([#7929](https://github.com/storybookjs/storybook/pull/7929))
|
||||
|
||||
### Maintenance
|
||||
|
||||
* Typescript: Migrate addon-storyshots ([#7674](https://github.com/storybookjs/storybook/pull/7674))
|
||||
|
||||
## 5.3.0-alpha.14 (October 8, 2019)
|
||||
|
||||
NPM publish failed
|
||||
|
||||
## 5.3.0-alpha.13 (October 8, 2019)
|
||||
|
||||
### Features
|
||||
|
||||
* MDX: Better ergonomics for documenting CSF ([#8312](https://github.com/storybookjs/storybook/pull/8312))
|
||||
* Addon-docs: Story parameter for disabling docs ([#8313](https://github.com/storybookjs/storybook/pull/8313))
|
||||
|
||||
### Dependency Upgrades
|
||||
|
||||
* Remove redundant dependency on hoist-non-react-statics (#6349) ([#8310](https://github.com/storybookjs/storybook/pull/8310))
|
||||
|
||||
## 5.3.0-alpha.12 (October 7, 2019)
|
||||
|
||||
### Features
|
||||
@ -9,6 +34,12 @@
|
||||
* CSF: Ignore __esModule export ([#8317](https://github.com/storybookjs/storybook/pull/8317))
|
||||
* React: Improve type of storyFn ([#8197](https://github.com/storybookjs/storybook/pull/8197))
|
||||
|
||||
## 5.2.3 (October 7, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Core: Fix lib/core whitelist ([#8182](https://github.com/storybookjs/storybook/pull/8182))
|
||||
|
||||
## 5.2.2 (October 7, 2019)
|
||||
|
||||
### Bug Fixes
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-a11y",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "a11y addon for storybook",
|
||||
"keywords": [
|
||||
"a11y",
|
||||
@ -32,16 +32,15 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/client-logger": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/client-logger": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"axe-core": "^3.3.2",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"hoist-non-react-statics": "^3.3.0",
|
||||
"memoizerific": "^1.11.3",
|
||||
"react": "^16.8.3",
|
||||
"react-redux": "^7.0.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-actions",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Action Logger addon for storybook",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -27,12 +27,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/client-api": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/client-api": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-backgrounds",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "A storybook addon to show different backgrounds for your preview",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -31,12 +31,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/client-logger": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/client-logger": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"memoizerific": "^1.11.3",
|
||||
"react": "^16.8.3",
|
||||
|
2
addons/centered/ember.d.ts
vendored
Normal file
2
addons/centered/ember.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import centered from './dist/ember';
|
||||
export default centered;
|
2
addons/centered/html.d.ts
vendored
Normal file
2
addons/centered/html.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import centered from './dist/html';
|
||||
export default centered;
|
2
addons/centered/mithril.d.ts
vendored
Normal file
2
addons/centered/mithril.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import centered from './dist/mithril';
|
||||
export default centered;
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-centered",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook decorator to center components",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -20,16 +20,8 @@
|
||||
"files": [
|
||||
"dist/**/*",
|
||||
"README.md",
|
||||
"angular.js",
|
||||
"angular.d.ts",
|
||||
"ember.js",
|
||||
"html.js",
|
||||
"mithril.js",
|
||||
"preact.js",
|
||||
"rax.js",
|
||||
"react.js",
|
||||
"svelte.js",
|
||||
"vue.js"
|
||||
"*.js",
|
||||
"*.d.ts"
|
||||
],
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
@ -37,7 +29,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"util-deprecate": "^1.0.2"
|
||||
|
2
addons/centered/preact.d.ts
vendored
Normal file
2
addons/centered/preact.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import centered from './dist/preact';
|
||||
export default centered;
|
2
addons/centered/react.d.ts
vendored
Normal file
2
addons/centered/react.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import centered from './dist/react';
|
||||
export default centered;
|
2
addons/centered/svelte.d.ts
vendored
Normal file
2
addons/centered/svelte.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import centered from './dist/svelte';
|
||||
export default centered;
|
2
addons/centered/vue.d.ts
vendored
Normal file
2
addons/centered/vue.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
import centered from './dist/vue';
|
||||
export default centered;
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-contexts",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook Addon Contexts",
|
||||
"keywords": [
|
||||
"preact",
|
||||
@ -28,10 +28,10 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"qs": "^6.6.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-cssresources",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "A storybook addon to switch between css resources at runtime for your story",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -31,10 +31,10 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.8.3"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-design-assets",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Design asset preview for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -33,12 +33,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/client-logger": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/client-logger": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.8.3",
|
||||
|
@ -94,7 +94,7 @@ features as well. This chart captures the current state of support
|
||||
First add the package. Make sure that the versions for your `@storybook/*` packages match:
|
||||
|
||||
```sh
|
||||
yarn add -D @storybook/addon-docs@next
|
||||
yarn add -D @storybook/addon-docs
|
||||
```
|
||||
|
||||
Docs has peer dependencies on `react` and `babel-loader`. If you want to write stories in MDX, you may need to add these dependencies as well:
|
||||
|
@ -237,6 +237,31 @@ Unless you use a custom webpack configuration, all of your story files should ha
|
||||
|
||||
The docs preset assumes this naming convention for its `source-loader` setup. If you want to use a different naming convention, you'll need a [manual configuration](../README.md#manual-configuration).
|
||||
|
||||
## Inline stories vs. Iframe stories
|
||||
|
||||
Due to the complex nature of writing a cross-framework utility like Storybook, the story blocks for most frameworks exist within an `<iframe>` element. This creates a clean separation of the context the code for each framework lives inside, but, of course, it isn't a perfect tradeoff. It does create a set of disadvantages--namely, you have to explicitly set the height of a story. It also causes some headaches for certain dev tools (Vue dev tools, for example, don't pick up components that exist in an iframe, without substantial jerry-rigging).
|
||||
|
||||
That being said, there is a system in place to remove the necessity of this tradeoff. The docs configuration contains two options, `inlineStories` and `prepareForInline` that can work together to integrate non-react stories seamlessly (or should I say "scroll-bar-less-ly") into DocsPage. Setting `inlineStories` to `true` is the easy part. It's just tells storybook to stop putting your stories into an iframe. The hard(er) part is providing the `prepareForInline` parameter. This parameter accepts a function that transforms story content in your given framework into something react can render. Any given framework will need to approach this in a different way. Angular, for example, might convert its story content into a custom element (you can read about that [here](https://angular.io/guide/elements)). We've actually taken the initiative and implemented Vue inline stories _for you_ in the default docs config for Vue, because we're such nice people. The following docs config block allows Vue components to be rendered inline through a simple effect hook provided by [@egoist/vue-to-react](https://github.com/egoist/vue-to-react):
|
||||
|
||||
```js
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import toReact from '@egoist/vue-to-react';
|
||||
import { addParameters } from '@storybook/vue';
|
||||
|
||||
addParameters({
|
||||
docs: {
|
||||
prepareForInline: storyFn => {
|
||||
const Story = toReact(storyFn());
|
||||
return <Story />;
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
With that simple function, anyone using the docs addon for `@storybook/vue` can make their stories render inline, either globally with the `inlineStories` docs parameter, or on a per-story-basis using the `inline` prop on the `<Story>` doc block. If you come up with an elegant and flexible implementation for the `prepareForInline` function for your own framework, let us know! We'd love to make it the default configuration, to make inline stories more accessible for a larger variety of frameworks!
|
||||
|
||||
|
||||
## More resources
|
||||
|
||||
Want to learn more? Here are some more articles on Storybook Docs:
|
||||
|
@ -9,6 +9,7 @@
|
||||
- [Mixing storiesOf with CSF/MDX](#mixing-storiesof-with-csfmdx)
|
||||
- [Migrating from notes/info addons](#migrating-from-notesinfo-addons)
|
||||
- [Exporting documentation](#exporting-documentation)
|
||||
- [Disabling docs stories](#disabling-docs-stories)
|
||||
- [More resources](#more-resources)
|
||||
|
||||
## Component Story Format (CSF) with DocsPage
|
||||
@ -31,46 +32,50 @@ The only limitation is that your exported titles (CSF: `default.title`, MDX `Met
|
||||
|
||||
Perhaps you want to write your stories in CSF, but document them in MDX? Here's how to do that:
|
||||
|
||||
**Button.mdx**
|
||||
**Button.stories.js**
|
||||
|
||||
```js
|
||||
import React from 'react';
|
||||
import { Button } from './Button';
|
||||
|
||||
export default {
|
||||
title: 'Demo/Button',
|
||||
component: Button,
|
||||
includeStories: [], // or simply don't load this file at all
|
||||
};
|
||||
|
||||
export const basic = () => <Button>Basic</Button>;
|
||||
basic.story = {
|
||||
parameters: { foo: 'bar' },
|
||||
};
|
||||
```
|
||||
|
||||
**Button.stories.mdx**
|
||||
|
||||
```md
|
||||
import { Story } from '@storybook/addon-docs/blocks';
|
||||
import { SomeComponent } from 'somewhere';
|
||||
import { Meta, Story } from '@storybook/addon-docs/blocks';
|
||||
import * as stories from './Button.stories.js';
|
||||
import { SomeComponent } from 'path/to/SomeComponent';
|
||||
|
||||
<Meta {...stories.default} />
|
||||
|
||||
# Button
|
||||
|
||||
I can embed a story (but not define one, since this file should not contain a `Meta`):
|
||||
I can define a story with the function imported from CSF:
|
||||
|
||||
<Story id="some--id" />
|
||||
<Story name="basic">{stories.basic}</Story>
|
||||
|
||||
And of course I can also embed arbitrary markdown & JSX in this file.
|
||||
|
||||
<SomeComponent prop1="val1" />
|
||||
```
|
||||
|
||||
**Button.stories.js**
|
||||
What's happening here:
|
||||
|
||||
```js
|
||||
import { Button } from './Button';
|
||||
import mdx from './Button.mdx';
|
||||
|
||||
export default {
|
||||
title: 'Demo/Button',
|
||||
parameters: {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const basic = () => <Button>Basic</Button>;
|
||||
```
|
||||
|
||||
Note that in contrast to other examples, the MDX file suffix is `.mdx` rather than `.stories.mdx`. This key difference means that the file will be loaded with the default MDX loader rather than Storybook's CSF loader, which has several implications:
|
||||
|
||||
1. You don't need to provide a `Meta` declaration.
|
||||
2. You can refer to existing stories (i.e. `<Story id="...">`) but cannot define new stories (i.e. `<Story name="...">`).
|
||||
3. The documentation gets exported as the default export (MDX default) rather than as a parameter hanging off the default export (CSF).
|
||||
- Your stories are defined in CSF, but because of `includeStories: []`, they are not actually added to Storybook.
|
||||
- The MDX file is adding the stories to Storybook, and using the story function defined in CSF.
|
||||
- The MDX loader is using story metadata from CSF, such as name, decorators, parameters, but will give giving preference to anything defined in the MDX file.
|
||||
- The MDX file is using the Meta `default` defined in the CSF.
|
||||
|
||||
## Mixing storiesOf with CSF/MDX
|
||||
|
||||
@ -128,6 +133,29 @@ To address this, we’ve added a CLI flag to export just the docs. This flag is
|
||||
yarn build-storybook --docs
|
||||
```
|
||||
|
||||
## Disabling docs stories
|
||||
|
||||
There are two cases where a user might wish to exclude stories from their documentation pages:
|
||||
|
||||
### DocsPage
|
||||
|
||||
User defines stories in CSF and renders docs using DocsPage, but wishes to exclude some fo the stories from the DocsPage to reduce noise on the page.
|
||||
|
||||
```js
|
||||
export const foo = () => <Button>foo</Button>;
|
||||
foo.story = { parameters: { docs: { disable: true } } };
|
||||
```
|
||||
|
||||
### MDX Stories
|
||||
|
||||
User writes documentation & stories side-by-side in a single MDX file, and wants those stories to show up in the canvas but not in the docs themselves. They want something similar to the recipe "CSF stories with MDX docs" but want to do everything in MDX:
|
||||
|
||||
```js
|
||||
<Story name="foo" parameters={{ docs: { disable: true }} >
|
||||
<Button>foo</Button>
|
||||
</Story>
|
||||
```
|
||||
|
||||
## More resources
|
||||
|
||||
Want to learn more? Here are some more articles on Storybook Docs:
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-docs",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Superior documentation for your components",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -39,15 +39,16 @@
|
||||
"@babel/generator": "^7.4.0",
|
||||
"@babel/parser": "^7.4.2",
|
||||
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
||||
"@egoist/vue-to-react": "^1.1.0",
|
||||
"@mdx-js/loader": "^1.1.0",
|
||||
"@mdx-js/mdx": "^1.1.0",
|
||||
"@mdx-js/react": "^1.0.27",
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/router": "5.3.0-alpha.12",
|
||||
"@storybook/source-loader": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/router": "5.3.0-alpha.15",
|
||||
"@storybook/source-loader": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"js-string-escape": "^1.0.1",
|
||||
|
@ -113,7 +113,9 @@ export const DocsPage: React.FunctionComponent<DocsPageProps> = ({
|
||||
const propsTableProps = propsSlot(context);
|
||||
|
||||
const { selectedKind, storyStore } = context;
|
||||
const componentStories = storyStore.getStoriesForKind(selectedKind);
|
||||
const componentStories = storyStore
|
||||
.getStoriesForKind(selectedKind)
|
||||
.filter((s: any) => !(s.parameters && s.parameters.docs && s.parameters.docs.disable));
|
||||
const primary = primarySlot(componentStories, context);
|
||||
const stories = storiesSlot(componentStories, context);
|
||||
|
||||
|
@ -40,7 +40,7 @@ const inferInlineStories = (framework: string): boolean => {
|
||||
|
||||
export const getStoryProps = (
|
||||
props: StoryProps,
|
||||
{ id: currentId, storyStore, parameters, mdxStoryNameToId }: DocsContextProps
|
||||
{ id: currentId, storyStore, parameters, mdxStoryNameToId }: DocsContextProps | null
|
||||
): PureStoryProps => {
|
||||
const { id } = props as StoryRefProps;
|
||||
const { name } = props as StoryDefProps;
|
||||
@ -49,17 +49,35 @@ export const getStoryProps = (
|
||||
|
||||
const { height, inline } = props;
|
||||
const data = storyStore.fromId(previewId);
|
||||
const { framework = null } = parameters || {};
|
||||
const { framework = null } = (data && data.parameters) || {};
|
||||
|
||||
const docsParam = (data && data.parameters && data.parameters.docs) || {};
|
||||
|
||||
if (docsParam.disable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// prefer props, then global options, then framework-inferred values
|
||||
const { inlineStories = inferInlineStories(framework), iframeHeight = undefined } =
|
||||
(parameters && parameters.docs) || {};
|
||||
const {
|
||||
inlineStories = inferInlineStories(framework),
|
||||
iframeHeight = undefined,
|
||||
prepareForInline = undefined,
|
||||
} = docsParam;
|
||||
const { storyFn = undefined, name: storyName = undefined } = data || {};
|
||||
|
||||
const storyIsInline = typeof inline === 'boolean' ? inline : inlineStories;
|
||||
if (storyIsInline && !prepareForInline) {
|
||||
throw new Error(
|
||||
`Story '${storyName}' is set to render inline, but no 'prepareForInline' function is implemented in your docs configuration!`
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
inline: typeof inline === 'boolean' ? inline : inlineStories,
|
||||
inline: storyIsInline,
|
||||
id: previewId,
|
||||
storyFn: data && data.storyFn,
|
||||
height: height || iframeHeight,
|
||||
title: data && data.name,
|
||||
storyFn: prepareForInline && storyFn ? () => prepareForInline(storyFn) : storyFn,
|
||||
height: height || (storyIsInline ? undefined : iframeHeight),
|
||||
title: storyName,
|
||||
};
|
||||
};
|
||||
|
||||
@ -67,6 +85,9 @@ const StoryContainer: React.FunctionComponent<StoryProps> = props => (
|
||||
<DocsContext.Consumer>
|
||||
{context => {
|
||||
const storyProps = getStoryProps(props, context);
|
||||
if (!storyProps) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div id={storyBlockIdFromId(storyProps.id)}>
|
||||
<MDXProvider components={resetComponents}>
|
||||
|
@ -11,3 +11,6 @@ export * from './Props';
|
||||
export * from './Source';
|
||||
export * from './Story';
|
||||
export * from './Wrapper';
|
||||
|
||||
// helper function for MDX
|
||||
export const makeStoryFn = (val: any) => (typeof val === 'function' ? val : () => val);
|
||||
|
@ -6,5 +6,7 @@ addParameters({
|
||||
docs: {
|
||||
container: DocsContainer,
|
||||
page: DocsPage,
|
||||
// react is Storybook's "native" framework, so it's stories are inherently prepared to be rendered inline
|
||||
prepareForInline: (storyFn: StoryFn) => storyFn(),
|
||||
},
|
||||
});
|
||||
|
@ -1,4 +1,6 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import React from 'react';
|
||||
import toReact from '@egoist/vue-to-react';
|
||||
import { addParameters } from '@storybook/vue';
|
||||
import { DocsPage, DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
|
||||
@ -6,5 +8,9 @@ addParameters({
|
||||
docs: {
|
||||
container: DocsContainer,
|
||||
page: DocsPage,
|
||||
prepareForInline: storyFn => {
|
||||
const Story = toReact(storyFn());
|
||||
return <Story />;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
exports[`docs-mdx-compiler-plugin decorators.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
@ -89,7 +89,7 @@ export default componentMeta;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin docs-only.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
@ -145,7 +145,7 @@ export default componentMeta;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin non-story-exports.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
@ -210,7 +210,7 @@ export default componentMeta;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin parameters.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
@ -298,7 +298,7 @@ export default componentMeta;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin previews.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Preview, Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
@ -378,7 +378,7 @@ export default componentMeta;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin story-current.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Story } from '@storybook/addon-docs/blocks';
|
||||
|
||||
@ -423,7 +423,7 @@ export default componentMeta;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin story-def-text-only.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
|
||||
@ -453,7 +453,7 @@ function MDXContent({ components, ...props }) {
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const text = () => 'Plain text';
|
||||
export const text = makeStoryFn('Plain text');
|
||||
text.story = {};
|
||||
text.story.name = 'text';
|
||||
text.story.parameters = { mdxSource: \\"'Plain text'\\" };
|
||||
@ -476,7 +476,7 @@ export default componentMeta;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin story-definitions.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
@ -550,7 +550,7 @@ export default componentMeta;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin story-function.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
const makeShortcode = name =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
@ -581,12 +581,12 @@ function MDXContent({ components, ...props }) {
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const functionStory = () => {
|
||||
export const functionStory = makeStoryFn(() => {
|
||||
const btn = document.createElement('button');
|
||||
btn.innerHTML = 'Hello Button';
|
||||
btn.addEventListener('click', action('Click'));
|
||||
return btn;
|
||||
};
|
||||
});
|
||||
functionStory.story = {};
|
||||
functionStory.story.name = 'function';
|
||||
functionStory.story.parameters = {
|
||||
@ -610,9 +610,66 @@ export default componentMeta;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin story-function-var.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Meta, Story } from '@storybook/addon-docs/blocks';
|
||||
export const basicFn = () => <Button mdxType=\\"Button\\" />;
|
||||
const makeShortcode = name =>
|
||||
function MDXDefaultShortcode(props) {
|
||||
console.warn(
|
||||
'Component ' +
|
||||
name +
|
||||
' was not imported, exported, or provided by MDXProvider as global scope'
|
||||
);
|
||||
return <div {...props} />;
|
||||
};
|
||||
const Button = makeShortcode('Button');
|
||||
const layoutProps = {
|
||||
basicFn,
|
||||
};
|
||||
const MDXLayout = 'wrapper';
|
||||
function MDXContent({ components, ...props }) {
|
||||
return (
|
||||
<MDXLayout {...layoutProps} {...props} components={components} mdxType=\\"MDXLayout\\">
|
||||
<Meta title=\\"story-function-var\\" mdxType=\\"Meta\\" />
|
||||
|
||||
<h1>{\`Button\`}</h1>
|
||||
<p>{\`I can define a story with the function defined in CSF:\`}</p>
|
||||
<Story name=\\"basic\\" mdxType=\\"Story\\">
|
||||
{basicFn}
|
||||
</Story>
|
||||
</MDXLayout>
|
||||
);
|
||||
}
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const basic = makeStoryFn(basicFn);
|
||||
basic.story = {};
|
||||
basic.story.name = 'basic';
|
||||
basic.story.parameters = { mdxSource: 'basicFn' };
|
||||
|
||||
const componentMeta = { title: 'story-function-var', includeStories: ['basic'] };
|
||||
|
||||
const mdxStoryNameToId = { basic: 'story-function-var--basic' };
|
||||
|
||||
componentMeta.parameters = componentMeta.parameters || {};
|
||||
componentMeta.parameters.docs = {
|
||||
container: ({ context, children }) => (
|
||||
<DocsContainer context={{ ...context, mdxStoryNameToId }}>{children}</DocsContainer>
|
||||
),
|
||||
page: MDXContent,
|
||||
};
|
||||
|
||||
export default componentMeta;
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin story-object.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Story, Meta } from '@storybook/addon-docs/blocks';
|
||||
import { Welcome, Button } from '@storybook/angular/demo';
|
||||
@ -652,7 +709,7 @@ function MDXContent({ components, ...props }) {
|
||||
|
||||
MDXContent.isMDXComponent = true;
|
||||
|
||||
export const toStorybook = () => ({
|
||||
export const toStorybook = makeStoryFn({
|
||||
template: \`<storybook-welcome-component (showApp)=\\"showApp()\\"></storybook-welcome-component>\`,
|
||||
props: {
|
||||
showApp: linkTo('Button'),
|
||||
@ -686,7 +743,7 @@ export default componentMeta;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin story-references.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Story } from '@storybook/addon-docs/blocks';
|
||||
|
||||
@ -731,7 +788,7 @@ export default componentMeta;
|
||||
|
||||
exports[`docs-mdx-compiler-plugin vanilla.mdx 1`] = `
|
||||
"/* @jsx mdx */
|
||||
import { DocsContainer } from '@storybook/addon-docs/blocks';
|
||||
import { DocsContainer, makeStoryFn } from '@storybook/addon-docs/blocks';
|
||||
|
||||
import { Button } from '@storybook/react/demo';
|
||||
|
||||
|
11
addons/docs/src/mdx/__testfixtures__/story-function-var.mdx
Normal file
11
addons/docs/src/mdx/__testfixtures__/story-function-var.mdx
Normal file
@ -0,0 +1,11 @@
|
||||
import { Meta, Story } from '@storybook/addon-docs/blocks';
|
||||
|
||||
<Meta title="story-function-var" />
|
||||
|
||||
export const basicFn = () => <Button />;
|
||||
|
||||
# Button
|
||||
|
||||
I can define a story with the function defined in CSF:
|
||||
|
||||
<Story name="basic">{basicFn}</Story>
|
@ -52,6 +52,7 @@ function genStoryExport(ast, context) {
|
||||
|
||||
let body = ast.children.find(n => n.type !== 'JSXText');
|
||||
let storyCode = null;
|
||||
let isJsx = false;
|
||||
if (!body) {
|
||||
// plain text node
|
||||
const { code } = generate(ast.children[0], {});
|
||||
@ -60,18 +61,20 @@ function genStoryExport(ast, context) {
|
||||
if (body.type === 'JSXExpressionContainer') {
|
||||
// FIXME: handle fragments
|
||||
body = body.expression;
|
||||
} else {
|
||||
isJsx = true;
|
||||
}
|
||||
const { code } = generate(body, {});
|
||||
storyCode = code;
|
||||
}
|
||||
if (storyCode.trim().startsWith('() =>')) {
|
||||
statements.push(`export const ${storyKey} = ${storyCode}`);
|
||||
} else {
|
||||
if (isJsx) {
|
||||
statements.push(
|
||||
`export const ${storyKey} = () => (
|
||||
${storyCode}
|
||||
);`
|
||||
);
|
||||
} else {
|
||||
statements.push(`export const ${storyKey} = makeStoryFn(${storyCode});`);
|
||||
}
|
||||
statements.push(`${storyKey}.story = {};`);
|
||||
|
||||
@ -240,7 +243,7 @@ function extractExports(node, options) {
|
||||
);
|
||||
|
||||
const fullJsx = [
|
||||
'import { DocsContainer } from "@storybook/addon-docs/blocks";',
|
||||
'import { DocsContainer, makeStoryFn } from "@storybook/addon-docs/blocks";',
|
||||
defaultJsx,
|
||||
...storyExports,
|
||||
`const componentMeta = ${stringifyMeta(metaExport)};`,
|
||||
|
@ -36,6 +36,7 @@ describe('docs-mdx-compiler-plugin', () => {
|
||||
'non-story-exports.mdx',
|
||||
'story-function.mdx',
|
||||
'docs-only.mdx',
|
||||
'story-function-var.mdx',
|
||||
];
|
||||
fixtures.forEach(fixtureFile => {
|
||||
it(fixtureFile, async () => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-events",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Add events to your Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -30,11 +30,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/client-api": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/client-api": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"format-json": "^1.0.3",
|
||||
"lodash": "^4.17.11",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-google-analytics",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook addon for google analytics",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -20,8 +20,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react-ga": "^2.5.7"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-graphql",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook addon to display the GraphiQL IDE",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -28,8 +28,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"graphiql": "^0.14.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-info",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "A Storybook addon to show additional information for your stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -27,10 +27,10 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/client-logger": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/client-logger": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"jsx-to-string": "^1.4.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-jest",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "React storybook addon that show component jest report",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -34,11 +34,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.8.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-knobs",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook Addon Prop Editor Component",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -35,12 +35,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/client-api": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/client-api": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"@types/react-color": "^3.0.1",
|
||||
"copy-to-clipboard": "^3.0.8",
|
||||
"core-js": "^3.0.1",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-links",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Story Links addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -29,10 +29,10 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/client-logger": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/router": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/client-logger": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"@storybook/router": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"prop-types": "^15.7.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-notes",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Write notes for your Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -30,13 +30,13 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/client-logger": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/router": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/client-logger": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"@storybook/router": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"markdown-to-jsx": "^6.10.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-actions",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Action Logger addon for react-native storybook",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -25,13 +25,13 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"fast-deep-equal": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-actions": "5.3.0-alpha.12"
|
||||
"@storybook/addon-actions": "5.3.0-alpha.15"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@storybook/addon-actions": "*",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-backgrounds",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "A react-native storybook addon to show different backgrounds for your preview",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -30,9 +30,9 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/client-api": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/client-api": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"prop-types": "^15.7.2"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-knobs",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Display storybook story knobs on your deviced.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -26,8 +26,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"deep-equal": "^1.0.1",
|
||||
"prop-types": "^15.7.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-ondevice-notes",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Write notes for your react-native Storybook stories.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -26,11 +26,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/client-api": "5.3.0-alpha.12",
|
||||
"@storybook/client-logger": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/client-api": "5.3.0-alpha.15",
|
||||
"@storybook/client-logger": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-native-simple-markdown": "^1.1.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-options",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Options addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -28,7 +28,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-queryparams",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "parameter addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -28,12 +28,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/client-logger": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/client-logger": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"qs": "^6.6.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-storyshots",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "StoryShots is a Jest Snapshot Testing Addon for Storybook.",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,6 +22,7 @@
|
||||
"README.md"
|
||||
],
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build-storybook": "build-storybook",
|
||||
"example": "jest storyshot.test",
|
||||
@ -30,7 +31,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/transform": "^24.9.0",
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/client-api": "5.3.0-alpha.15",
|
||||
"@types/glob": "^7.1.1",
|
||||
"@types/jest": "^24.0.16",
|
||||
"@types/jest-specific-snapshot": "^0.5.3",
|
||||
"core-js": "^3.0.1",
|
||||
"glob": "^7.1.3",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,4 +1,4 @@
|
||||
import Stories2SnapsConverter from './Stories2SnapsConverter';
|
||||
import { Stories2SnapsConverter } from './Stories2SnapsConverter';
|
||||
|
||||
const target = new Stories2SnapsConverter();
|
||||
|
@ -1,14 +1,22 @@
|
||||
import path from 'path';
|
||||
import dedent from 'ts-dedent';
|
||||
|
||||
const defaultOptions = {
|
||||
const defaultOptions: Stories2SnapsConverterOptions = {
|
||||
snapshotsDirName: '__snapshots__',
|
||||
snapshotExtension: '.storyshot',
|
||||
storiesExtensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||
};
|
||||
|
||||
class DefaultStories2SnapsConverter {
|
||||
constructor(options = {}) {
|
||||
export interface Stories2SnapsConverterOptions {
|
||||
storiesExtensions: string[];
|
||||
snapshotExtension: string;
|
||||
snapshotsDirName: string;
|
||||
}
|
||||
|
||||
export class Stories2SnapsConverter {
|
||||
options: Stories2SnapsConverterOptions;
|
||||
|
||||
constructor(options: Partial<Stories2SnapsConverterOptions> = {}) {
|
||||
this.options = {
|
||||
...defaultOptions,
|
||||
...options,
|
||||
@ -17,14 +25,14 @@ class DefaultStories2SnapsConverter {
|
||||
|
||||
getSnapshotExtension = () => this.options.snapshotExtension;
|
||||
|
||||
getStoryshotFile(fileName) {
|
||||
getStoryshotFile(fileName: string) {
|
||||
const { dir, name } = path.parse(fileName);
|
||||
const { snapshotsDirName, snapshotExtension } = this.options;
|
||||
|
||||
return path.format({ dir: path.join(dir, snapshotsDirName), name, ext: snapshotExtension });
|
||||
}
|
||||
|
||||
getSnapshotFileName(context) {
|
||||
getSnapshotFileName(context: { fileName?: string; kind: any }) {
|
||||
const { fileName, kind } = context;
|
||||
|
||||
if (!fileName) {
|
||||
@ -45,7 +53,7 @@ class DefaultStories2SnapsConverter {
|
||||
return this.getStoryshotFile(fileName);
|
||||
}
|
||||
|
||||
getPossibleStoriesFiles(storyshotFile) {
|
||||
getPossibleStoriesFiles(storyshotFile: string) {
|
||||
const { dir, name } = path.parse(storyshotFile);
|
||||
const { storiesExtensions } = this.options;
|
||||
|
||||
@ -58,5 +66,3 @@ class DefaultStories2SnapsConverter {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default DefaultStories2SnapsConverter;
|
@ -0,0 +1,23 @@
|
||||
import { IOptions } from 'glob';
|
||||
import { Stories2SnapsConverter } from '../Stories2SnapsConverter';
|
||||
import { SupportedFramework } from '../frameworks';
|
||||
import { RenderTree } from '../frameworks/Loader';
|
||||
|
||||
export interface StoryshotsOptions {
|
||||
asyncJest?: boolean;
|
||||
config?: (options: any) => void;
|
||||
integrityOptions?: IOptions | false;
|
||||
configPath?: string;
|
||||
suite?: string;
|
||||
storyKindRegex?: RegExp | string;
|
||||
storyNameRegex?: RegExp | string;
|
||||
framework?: SupportedFramework;
|
||||
test?: (story: any, context: any, renderTree: RenderTree, options?: any) => any;
|
||||
renderer?: Function;
|
||||
snapshotSerializers?: jest.SnapshotSerializerPlugin[];
|
||||
/**
|
||||
* @Deprecated The functionality of this option is completely covered by snapshotSerializers which should be used instead.
|
||||
*/
|
||||
serializer?: any;
|
||||
stories2snapsConverter?: Stories2SnapsConverter;
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
import { snapshotWithOptions } from '../test-bodies';
|
||||
import Stories2SnapsConverter from '../Stories2SnapsConverter';
|
||||
import { Stories2SnapsConverter } from '../Stories2SnapsConverter';
|
||||
import { StoryshotsOptions } from './StoryshotsOptions';
|
||||
|
||||
const ignore = ['**/node_modules/**'];
|
||||
const defaultStories2SnapsConverter = new Stories2SnapsConverter();
|
||||
|
||||
function getIntegrityOptions({ integrityOptions }) {
|
||||
function getIntegrityOptions({ integrityOptions }: StoryshotsOptions) {
|
||||
if (integrityOptions === false) {
|
||||
return false;
|
||||
}
|
||||
@ -13,14 +14,18 @@ function getIntegrityOptions({ integrityOptions }) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ignoreOption: string[] = Array.isArray(integrityOptions.ignore)
|
||||
? integrityOptions.ignore
|
||||
: [];
|
||||
|
||||
return {
|
||||
...integrityOptions,
|
||||
ignore: [...ignore, ...(integrityOptions.ignore || [])],
|
||||
ignore: [...ignore, ...ignoreOption],
|
||||
absolute: true,
|
||||
};
|
||||
}
|
||||
|
||||
function ensureOptionsDefaults(options) {
|
||||
function ensureOptionsDefaults(options: StoryshotsOptions) {
|
||||
const {
|
||||
suite = 'Storyshots',
|
||||
asyncJest,
|
@ -4,12 +4,16 @@ import ensureOptionsDefaults from './ensureOptionsDefaults';
|
||||
import snapshotsTests from './snapshotsTestsTemplate';
|
||||
import integrityTest from './integrityTestTemplate';
|
||||
import loadFramework from '../frameworks/frameworkLoader';
|
||||
import { StoryshotsOptions } from './StoryshotsOptions';
|
||||
|
||||
global.STORYBOOK_REACT_CLASSES = global.STORYBOOK_REACT_CLASSES || {};
|
||||
|
||||
const methods = ['beforeAll', 'beforeEach', 'afterEach', 'afterAll'];
|
||||
type TestMethod = 'beforeAll' | 'beforeEach' | 'afterEach' | 'afterAll';
|
||||
const methods: TestMethod[] = ['beforeAll', 'beforeEach', 'afterEach', 'afterAll'];
|
||||
|
||||
function callTestMethodGlobals(testMethod) {
|
||||
function callTestMethodGlobals(
|
||||
testMethod: { [key in TestMethod]?: Function } & { [key in string]: any }
|
||||
) {
|
||||
methods.forEach(method => {
|
||||
if (typeof testMethod[method] === 'function') {
|
||||
global[method](testMethod[method]);
|
||||
@ -17,9 +21,10 @@ function callTestMethodGlobals(testMethod) {
|
||||
});
|
||||
}
|
||||
|
||||
const isDisabled = parameter => parameter === false || (parameter && parameter.disable === true);
|
||||
const isDisabled = (parameter: any) =>
|
||||
parameter === false || (parameter && parameter.disable === true);
|
||||
|
||||
function testStorySnapshots(options = {}) {
|
||||
function testStorySnapshots(options: StoryshotsOptions = {}) {
|
||||
if (typeof describe !== 'function') {
|
||||
throw new Error('testStorySnapshots is intended only to be used inside jest');
|
||||
}
|
||||
@ -47,23 +52,29 @@ function testStorySnapshots(options = {}) {
|
||||
.raw()
|
||||
.filter(({ name }) => (storyNameRegex ? name.match(storyNameRegex) : true))
|
||||
.filter(({ kind }) => (storyKindRegex ? kind.match(storyKindRegex) : true))
|
||||
.reduce((acc, item) => {
|
||||
const { kind, storyFn: render, parameters } = item;
|
||||
const existing = acc.find(i => i.kind === kind);
|
||||
const { fileName } = item.parameters;
|
||||
.reduce(
|
||||
(acc, item) => {
|
||||
const { kind, storyFn: render, parameters } = item;
|
||||
const existing = acc.find((i: any) => i.kind === kind);
|
||||
const { fileName } = item.parameters;
|
||||
|
||||
if (!isDisabled(parameters.storyshots)) {
|
||||
if (existing) {
|
||||
existing.children.push({ ...item, render, fileName });
|
||||
} else {
|
||||
acc.push({
|
||||
kind,
|
||||
children: [{ ...item, render, fileName }],
|
||||
});
|
||||
if (!isDisabled(parameters.storyshots)) {
|
||||
if (existing) {
|
||||
existing.children.push({ ...item, render, fileName });
|
||||
} else {
|
||||
acc.push({
|
||||
kind,
|
||||
children: [{ ...item, render, fileName }],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
return acc;
|
||||
},
|
||||
[] as Array<{
|
||||
kind: string;
|
||||
children: any[];
|
||||
}>
|
||||
);
|
||||
|
||||
if (data.length) {
|
||||
callTestMethodGlobals(testMethod);
|
@ -2,7 +2,7 @@ import fs from 'fs';
|
||||
import glob from 'glob';
|
||||
import { describe, it } from 'global';
|
||||
|
||||
function integrityTest(integrityOptions, stories2snapsConverter) {
|
||||
function integrityTest(integrityOptions: any, stories2snapsConverter: any) {
|
||||
if (integrityOptions === false) {
|
||||
return;
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
import { describe, it } from 'global';
|
||||
import { addSerializer } from 'jest-specific-snapshot';
|
||||
|
||||
function snapshotTest({ item, asyncJest, framework, testMethod, testMethodParams }) {
|
||||
function snapshotTest({ item, asyncJest, framework, testMethod, testMethodParams }: any) {
|
||||
const { name } = item;
|
||||
const context = { ...item, framework };
|
||||
|
||||
if (asyncJest === true) {
|
||||
it(name, done =>
|
||||
it(name, (done: jest.DoneCallback) =>
|
||||
testMethod({
|
||||
done,
|
||||
story: item,
|
||||
@ -25,28 +25,28 @@ function snapshotTest({ item, asyncJest, framework, testMethod, testMethodParams
|
||||
}
|
||||
}
|
||||
|
||||
function snapshotTestSuite({ item, suite, ...restParams }) {
|
||||
function snapshotTestSuite({ item, suite, ...restParams }: any) {
|
||||
const { kind, children } = item;
|
||||
// eslint-disable-next-line jest/valid-describe
|
||||
describe(suite, () => {
|
||||
// eslint-disable-next-line jest/valid-describe
|
||||
describe(kind, () => {
|
||||
children.forEach(c => {
|
||||
children.forEach((c: any) => {
|
||||
snapshotTest({ item: c, ...restParams });
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function snapshotsTests({ data, snapshotSerializers, ...restParams }) {
|
||||
function snapshotsTests({ data, snapshotSerializers, ...restParams }: any) {
|
||||
if (snapshotSerializers) {
|
||||
snapshotSerializers.forEach(serializer => {
|
||||
snapshotSerializers.forEach((serializer: any) => {
|
||||
addSerializer(serializer);
|
||||
expect.addSnapshotSerializer(serializer);
|
||||
});
|
||||
}
|
||||
|
||||
data.forEach(item => {
|
||||
data.forEach((item: any) => {
|
||||
snapshotTestSuite({ item, ...restParams });
|
||||
});
|
||||
}
|
17
addons/storyshots/storyshots-core/src/frameworks/Loader.ts
Normal file
17
addons/storyshots/storyshots-core/src/frameworks/Loader.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { ClientApi } from '@storybook/client-api';
|
||||
import { StoryshotsOptions } from '../api/StoryshotsOptions';
|
||||
import { SupportedFramework } from './SupportedFramework';
|
||||
|
||||
export type RenderTree = (story: any, context?: any, options?: any) => any;
|
||||
|
||||
export interface Loader {
|
||||
load: (
|
||||
options: StoryshotsOptions
|
||||
) => {
|
||||
framework: SupportedFramework;
|
||||
renderTree: RenderTree;
|
||||
renderShallowTree: any;
|
||||
storybook: ClientApi;
|
||||
};
|
||||
test: (options: StoryshotsOptions) => boolean;
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
export type SupportedFramework =
|
||||
| 'angular'
|
||||
| 'html'
|
||||
| 'preact'
|
||||
| 'react'
|
||||
| 'riot'
|
||||
| 'react-native'
|
||||
| 'svelte'
|
||||
| 'vue';
|
@ -2,6 +2,8 @@ import 'core-js';
|
||||
import 'core-js/es/reflect';
|
||||
import hasDependency from '../hasDependency';
|
||||
import configure from '../configure';
|
||||
import { Loader } from '../Loader';
|
||||
import { StoryshotsOptions } from '../../api/StoryshotsOptions';
|
||||
|
||||
function setupAngularJestPreset() {
|
||||
// Needed to prevent "Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten."
|
||||
@ -18,13 +20,13 @@ function setupAngularJestPreset() {
|
||||
require.requireActual('jest-preset-angular/setupJest');
|
||||
}
|
||||
|
||||
function test(options) {
|
||||
function test(options: StoryshotsOptions): boolean {
|
||||
return (
|
||||
options.framework === 'angular' || (!options.framework && hasDependency('@storybook/angular'))
|
||||
);
|
||||
}
|
||||
|
||||
function load(options) {
|
||||
function load(options: StoryshotsOptions) {
|
||||
setupAngularJestPreset();
|
||||
|
||||
const { configPath, config } = options;
|
||||
@ -33,7 +35,7 @@ function load(options) {
|
||||
configure({ configPath, config, storybook });
|
||||
|
||||
return {
|
||||
framework: 'angular',
|
||||
framework: 'angular' as const,
|
||||
renderTree: require.requireActual('./renderTree').default,
|
||||
renderShallowTree: () => {
|
||||
throw new Error('Shallow renderer is not supported for angular');
|
||||
@ -42,7 +44,9 @@ function load(options) {
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
const angularLoader: Loader = {
|
||||
load,
|
||||
test,
|
||||
};
|
||||
|
||||
export default angularLoader;
|
@ -14,18 +14,21 @@ import { initModuleData } from './helpers';
|
||||
addSerializer(HTMLCommentSerializer);
|
||||
addSerializer(AngularSnapshotSerializer);
|
||||
|
||||
function getRenderedTree(story) {
|
||||
function getRenderedTree(story: any) {
|
||||
const currentStory = story.render();
|
||||
|
||||
const { moduleMeta, AppComponent } = initModuleData(currentStory);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [...moduleMeta.imports],
|
||||
declarations: [...moduleMeta.declarations],
|
||||
providers: [...moduleMeta.providers],
|
||||
schemas: [NO_ERRORS_SCHEMA, ...moduleMeta.schemas],
|
||||
bootstrap: [...moduleMeta.bootstrap],
|
||||
});
|
||||
TestBed.configureTestingModule(
|
||||
// TODO: take a look at `bootstrap` because it looks it does not exists in TestModuleMetadata
|
||||
{
|
||||
imports: [...moduleMeta.imports],
|
||||
declarations: [...moduleMeta.declarations],
|
||||
providers: [...moduleMeta.providers],
|
||||
schemas: [NO_ERRORS_SCHEMA, ...moduleMeta.schemas],
|
||||
bootstrap: [...moduleMeta.bootstrap],
|
||||
} as any
|
||||
);
|
||||
|
||||
TestBed.overrideModule(BrowserDynamicTestingModule, {
|
||||
set: {
|
@ -1,7 +1,7 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
function getConfigPathParts(configPath) {
|
||||
function getConfigPathParts(configPath: string): string {
|
||||
const resolvedConfigPath = path.resolve(configPath);
|
||||
|
||||
if (fs.lstatSync(resolvedConfigPath).isDirectory()) {
|
||||
@ -11,7 +11,7 @@ function getConfigPathParts(configPath) {
|
||||
return resolvedConfigPath;
|
||||
}
|
||||
|
||||
function configure(options) {
|
||||
function configure(options: { configPath?: string; config: any; storybook: any }): void {
|
||||
const { configPath = '.storybook', config, storybook } = options;
|
||||
|
||||
if (config && typeof config === 'function') {
|
@ -1,22 +1,33 @@
|
||||
/* eslint-disable global-require,import/no-dynamic-require */
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { Loader } from './Loader';
|
||||
import { StoryshotsOptions } from '../api/StoryshotsOptions';
|
||||
|
||||
const loaderScriptName = 'loader.js';
|
||||
const loaderScriptName = 'loader';
|
||||
|
||||
const isDirectory = source => fs.lstatSync(source).isDirectory();
|
||||
const isDirectory = (source: string) => fs.lstatSync(source).isDirectory();
|
||||
|
||||
function getLoaders() {
|
||||
function getLoaders(): Loader[] {
|
||||
return fs
|
||||
.readdirSync(__dirname)
|
||||
.map(name => path.join(__dirname, name))
|
||||
.filter(isDirectory)
|
||||
.map(framework => path.join(framework, loaderScriptName))
|
||||
.reduce(
|
||||
(acc, framework) => {
|
||||
const filename = path.join(framework, loaderScriptName);
|
||||
const jsFile = `${filename}.js`;
|
||||
const tsFile = `${filename}.ts`;
|
||||
|
||||
return acc.concat([jsFile, tsFile]);
|
||||
},
|
||||
[] as string[]
|
||||
)
|
||||
.filter(fs.existsSync)
|
||||
.map(loader => require(loader).default);
|
||||
}
|
||||
|
||||
function loadFramework(options) {
|
||||
function loadFramework(options: StoryshotsOptions) {
|
||||
const loaders = getLoaders();
|
||||
|
||||
const loader = loaders.find(frameworkLoader => frameworkLoader.test(options));
|
@ -1,13 +0,0 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import readPkgUp from 'read-pkg-up';
|
||||
|
||||
const { packageJson: { dependencies, devDependencies } = {} } = readPkgUp.sync() || {};
|
||||
|
||||
export default function hasDependency(name) {
|
||||
return (
|
||||
(devDependencies && devDependencies[name]) ||
|
||||
(dependencies && dependencies[name]) ||
|
||||
fs.existsSync(path.join('node_modules', name, 'package.json'))
|
||||
);
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import readPkgUp from 'read-pkg-up';
|
||||
|
||||
const {
|
||||
packageJson: { dependencies, devDependencies } = {
|
||||
dependencies: undefined,
|
||||
devDependencies: undefined,
|
||||
},
|
||||
} = readPkgUp.sync() || {};
|
||||
|
||||
export default function hasDependency(name: string): boolean {
|
||||
return Boolean(
|
||||
(devDependencies && devDependencies[name]) ||
|
||||
(dependencies && dependencies[name]) ||
|
||||
fs.existsSync(path.join('node_modules', name, 'package.json'))
|
||||
);
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
import global from 'global';
|
||||
import configure from '../configure';
|
||||
import { Loader } from '../Loader';
|
||||
import { StoryshotsOptions } from '../../api/StoryshotsOptions';
|
||||
|
||||
function test(options) {
|
||||
function test(options: StoryshotsOptions): boolean {
|
||||
return options.framework === 'html';
|
||||
}
|
||||
|
||||
function load(options) {
|
||||
function load(options: StoryshotsOptions) {
|
||||
global.STORYBOOK_ENV = 'html';
|
||||
|
||||
const { configPath, config } = options;
|
||||
@ -14,7 +16,7 @@ function load(options) {
|
||||
configure({ configPath, config, storybook });
|
||||
|
||||
return {
|
||||
framework: 'html',
|
||||
framework: 'html' as const,
|
||||
renderTree: require.requireActual('./renderTree').default,
|
||||
renderShallowTree: () => {
|
||||
throw new Error('Shallow renderer is not supported for HTML');
|
||||
@ -23,7 +25,9 @@ function load(options) {
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
const htmLoader: Loader = {
|
||||
load,
|
||||
test,
|
||||
};
|
||||
|
||||
export default htmLoader;
|
@ -1,13 +1,13 @@
|
||||
import { document, Node } from 'global';
|
||||
|
||||
function getRenderedTree(story) {
|
||||
function getRenderedTree(story: { render: () => any }) {
|
||||
const component = story.render();
|
||||
|
||||
if (component instanceof Node) {
|
||||
return component;
|
||||
}
|
||||
|
||||
const section = document.createElement('section');
|
||||
const section: HTMLElement = document.createElement('section');
|
||||
section.innerHTML = component;
|
||||
|
||||
if (section.childElementCount > 1) {
|
@ -0,0 +1 @@
|
||||
export * from './SupportedFramework';
|
@ -3,14 +3,16 @@
|
||||
import global from 'global';
|
||||
import configure from '../configure';
|
||||
import hasDependency from '../hasDependency';
|
||||
import { Loader } from '../Loader';
|
||||
import { StoryshotsOptions } from '../../api/StoryshotsOptions';
|
||||
|
||||
function test(options) {
|
||||
function test(options: StoryshotsOptions): boolean {
|
||||
return (
|
||||
options.framework === 'preact' || (!options.framework && hasDependency('@storybook/preact'))
|
||||
);
|
||||
}
|
||||
|
||||
function load(options) {
|
||||
function load(options: StoryshotsOptions) {
|
||||
global.STORYBOOK_ENV = 'preact';
|
||||
|
||||
const { configPath, config } = options;
|
||||
@ -19,7 +21,7 @@ function load(options) {
|
||||
configure({ configPath, config, storybook });
|
||||
|
||||
return {
|
||||
framework: 'preact',
|
||||
framework: 'preact' as const,
|
||||
renderTree: require.requireActual('./renderTree').default,
|
||||
renderShallowTree: () => {
|
||||
throw new Error('Shallow renderer is not supported for preact');
|
||||
@ -28,7 +30,9 @@ function load(options) {
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
const preactLoader: Loader = {
|
||||
load,
|
||||
test,
|
||||
};
|
||||
|
||||
export default preactLoader;
|
@ -3,7 +3,7 @@
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import preactRenderer from 'preact-render-to-json';
|
||||
|
||||
function getRenderedTree(story, context, { renderer, ...rendererOptions }) {
|
||||
function getRenderedTree(story: any, context: any, { renderer, ...rendererOptions }: any) {
|
||||
const storyElement = story.render();
|
||||
const currentRenderer = renderer || preactRenderer;
|
||||
const tree = currentRenderer(storyElement, rendererOptions);
|
@ -1,15 +1,17 @@
|
||||
/* eslint-disable global-require */
|
||||
import path from 'path';
|
||||
import hasDependency from '../hasDependency';
|
||||
import { Loader } from '../Loader';
|
||||
import { StoryshotsOptions } from '../../api/StoryshotsOptions';
|
||||
|
||||
function test(options) {
|
||||
function test(options: StoryshotsOptions): boolean {
|
||||
return (
|
||||
options.framework === 'react-native' ||
|
||||
(!options.framework && hasDependency('@storybook/react-native'))
|
||||
);
|
||||
}
|
||||
|
||||
function configure(options, storybook) {
|
||||
function configure(options: StoryshotsOptions, storybook: any) {
|
||||
const { configPath = 'storybook', config } = options;
|
||||
|
||||
if (config && typeof config === 'function') {
|
||||
@ -21,7 +23,7 @@ function configure(options, storybook) {
|
||||
require.requireActual(resolvedConfigPath);
|
||||
}
|
||||
|
||||
function load(options) {
|
||||
function load(options: StoryshotsOptions) {
|
||||
const storybook = require.requireActual('@storybook/react-native');
|
||||
|
||||
configure(options, storybook);
|
||||
@ -29,12 +31,14 @@ function load(options) {
|
||||
return {
|
||||
renderTree: require('../react/renderTree').default,
|
||||
renderShallowTree: require('../react/renderShallowTree').default,
|
||||
framework: 'rn',
|
||||
framework: 'react-native' as const,
|
||||
storybook,
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
const reactNativeLoader: Loader = {
|
||||
load,
|
||||
test,
|
||||
};
|
||||
|
||||
export default reactNativeLoader;
|
@ -1,25 +1,29 @@
|
||||
import configure from '../configure';
|
||||
import hasDependency from '../hasDependency';
|
||||
import { Loader } from '../Loader';
|
||||
import { StoryshotsOptions } from '../../api/StoryshotsOptions';
|
||||
|
||||
function test(options) {
|
||||
function test(options: StoryshotsOptions): boolean {
|
||||
return options.framework === 'react' || (!options.framework && hasDependency('@storybook/react'));
|
||||
}
|
||||
|
||||
function load(options) {
|
||||
function load(options: StoryshotsOptions) {
|
||||
const { configPath, config } = options;
|
||||
const storybook = require.requireActual('@storybook/react');
|
||||
|
||||
configure({ configPath, config, storybook });
|
||||
|
||||
return {
|
||||
framework: 'react',
|
||||
framework: 'react' as const,
|
||||
renderTree: require.requireActual('./renderTree').default,
|
||||
renderShallowTree: require.requireActual('./renderShallowTree').default,
|
||||
storybook,
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
const reactLoader: Loader = {
|
||||
load,
|
||||
test,
|
||||
};
|
||||
|
||||
export default reactLoader;
|
@ -1,7 +1,7 @@
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import shallow from 'react-test-renderer/shallow';
|
||||
|
||||
function getRenderedTree(story, context, { renderer, serializer }) {
|
||||
function getRenderedTree(story: any, context: any, { renderer, serializer }: any) {
|
||||
const storyElement = story.render();
|
||||
const shallowRenderer = renderer || shallow.createRenderer();
|
||||
const tree = shallowRenderer.render(storyElement);
|
@ -1,7 +1,7 @@
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import reactTestRenderer from 'react-test-renderer';
|
||||
|
||||
function getRenderedTree(story, context, { renderer, ...rendererOptions }) {
|
||||
function getRenderedTree(story: any, context: any, { renderer, ...rendererOptions }: any) {
|
||||
const storyElement = story.render();
|
||||
const currentRenderer = renderer || reactTestRenderer.create;
|
||||
const tree = currentRenderer(storyElement, rendererOptions);
|
@ -1,16 +1,18 @@
|
||||
import global from 'global';
|
||||
import hasDependency from '../hasDependency';
|
||||
import configure from '../configure';
|
||||
import { Loader } from '../Loader';
|
||||
import { StoryshotsOptions } from '../../api/StoryshotsOptions';
|
||||
|
||||
function mockRiotToIncludeCompiler() {
|
||||
jest.mock('riot', () => require.requireActual('riot/riot.js'));
|
||||
}
|
||||
|
||||
function test(options) {
|
||||
function test(options: StoryshotsOptions): boolean {
|
||||
return options.framework === 'riot' || (!options.framework && hasDependency('@storybook/riot'));
|
||||
}
|
||||
|
||||
function load(options) {
|
||||
function load(options: StoryshotsOptions) {
|
||||
global.STORYBOOK_ENV = 'riot';
|
||||
mockRiotToIncludeCompiler();
|
||||
|
||||
@ -20,7 +22,7 @@ function load(options) {
|
||||
configure({ configPath, config, storybook });
|
||||
|
||||
return {
|
||||
framework: 'riot',
|
||||
framework: 'riot' as const,
|
||||
renderTree: require.requireActual('./renderTree').default,
|
||||
renderShallowTree: () => {
|
||||
throw new Error('Shallow renderer is not supported for riot');
|
||||
@ -29,7 +31,9 @@ function load(options) {
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
const riotLoader: Loader = {
|
||||
load,
|
||||
test,
|
||||
};
|
||||
|
||||
export default riotLoader;
|
@ -10,7 +10,7 @@ function bootstrapADocumentAndReturnANode() {
|
||||
return rootElement;
|
||||
}
|
||||
|
||||
function makeSureThatResultIsRenderedSomehow({ context, result, rootElement }) {
|
||||
function makeSureThatResultIsRenderedSomehow({ context, result, rootElement }: any) {
|
||||
if (!rootElement.firstChild) {
|
||||
riotForStorybook.render({
|
||||
storyFn: () => result,
|
||||
@ -20,7 +20,7 @@ function makeSureThatResultIsRenderedSomehow({ context, result, rootElement }) {
|
||||
}
|
||||
}
|
||||
|
||||
function getRenderedTree(story, context) {
|
||||
function getRenderedTree(story: any, context: any) {
|
||||
const rootElement = bootstrapADocumentAndReturnANode();
|
||||
|
||||
const result = story.render();
|
@ -1,14 +1,16 @@
|
||||
import global from 'global';
|
||||
import hasDependency from '../hasDependency';
|
||||
import configure from '../configure';
|
||||
import { Loader } from '../Loader';
|
||||
import { StoryshotsOptions } from '../../api/StoryshotsOptions';
|
||||
|
||||
function test(options) {
|
||||
function test(options: StoryshotsOptions): boolean {
|
||||
return (
|
||||
options.framework === 'svelte' || (!options.framework && hasDependency('@storybook/svelte'))
|
||||
);
|
||||
}
|
||||
|
||||
function load(options) {
|
||||
function load(options: StoryshotsOptions) {
|
||||
global.STORYBOOK_ENV = 'svelte';
|
||||
|
||||
const { configPath, config } = options;
|
||||
@ -17,7 +19,7 @@ function load(options) {
|
||||
configure({ configPath, config, storybook });
|
||||
|
||||
return {
|
||||
framework: 'svelte',
|
||||
framework: 'svelte' as const,
|
||||
renderTree: require.requireActual('./renderTree').default,
|
||||
renderShallowTree: () => {
|
||||
throw new Error('Shallow renderer is not supported for svelte');
|
||||
@ -26,7 +28,9 @@ function load(options) {
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
const svelteLoader: Loader = {
|
||||
load,
|
||||
test,
|
||||
};
|
||||
|
||||
export default svelteLoader;
|
@ -11,7 +11,7 @@ import { document } from 'global';
|
||||
* If we don't render to HTML, we will get a snapshot of the raw story
|
||||
* i.e. ({ Component, data }).
|
||||
*/
|
||||
function getRenderedTree(story) {
|
||||
function getRenderedTree(story: any) {
|
||||
const { Component, props } = story.render();
|
||||
|
||||
const DefaultCompatComponent = Component.default || Component;
|
@ -1,16 +1,18 @@
|
||||
import global from 'global';
|
||||
import hasDependency from '../hasDependency';
|
||||
import configure from '../configure';
|
||||
import { Loader } from '../Loader';
|
||||
import { StoryshotsOptions } from '../../api/StoryshotsOptions';
|
||||
|
||||
function mockVueToIncludeCompiler() {
|
||||
jest.mock('vue', () => require.requireActual('vue/dist/vue.common.js'));
|
||||
}
|
||||
|
||||
function test(options) {
|
||||
function test(options: StoryshotsOptions): boolean {
|
||||
return options.framework === 'vue' || (!options.framework && hasDependency('@storybook/vue'));
|
||||
}
|
||||
|
||||
function load(options) {
|
||||
function load(options: StoryshotsOptions) {
|
||||
global.STORYBOOK_ENV = 'vue';
|
||||
mockVueToIncludeCompiler();
|
||||
|
||||
@ -20,7 +22,7 @@ function load(options) {
|
||||
configure({ configPath, config, storybook });
|
||||
|
||||
return {
|
||||
framework: 'vue',
|
||||
framework: 'vue' as const,
|
||||
renderTree: require.requireActual('./renderTree').default,
|
||||
renderShallowTree: () => {
|
||||
throw new Error('Shallow renderer is not supported for vue');
|
||||
@ -29,7 +31,9 @@ function load(options) {
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
const vueLoader: Loader = {
|
||||
load,
|
||||
test,
|
||||
};
|
||||
|
||||
export default vueLoader;
|
@ -1,7 +1,7 @@
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import Vue from 'vue';
|
||||
|
||||
function getRenderedTree(story) {
|
||||
function getRenderedTree(story: any) {
|
||||
const component = story.render();
|
||||
|
||||
const vm = new Vue({
|
@ -1,4 +1,3 @@
|
||||
import Stories2SnapsConverter from './Stories2SnapsConverter';
|
||||
import api from './api';
|
||||
import {
|
||||
snapshotWithOptions,
|
||||
@ -10,7 +9,6 @@ import {
|
||||
} from './test-bodies';
|
||||
|
||||
export {
|
||||
Stories2SnapsConverter,
|
||||
snapshotWithOptions,
|
||||
multiSnapshotWithOptions,
|
||||
renderOnly,
|
||||
@ -19,4 +17,7 @@ export {
|
||||
snapshot,
|
||||
};
|
||||
|
||||
export * from './Stories2SnapsConverter';
|
||||
export * from './frameworks';
|
||||
|
||||
export default api;
|
@ -1,17 +1,26 @@
|
||||
import 'jest-specific-snapshot';
|
||||
import { RenderTree } from './frameworks/Loader';
|
||||
import { Stories2SnapsConverter } from './Stories2SnapsConverter';
|
||||
|
||||
const isFunction = obj => !!(obj && obj.constructor && obj.call && obj.apply);
|
||||
const optionsOrCallOptions = (opts, story) => (isFunction(opts) ? opts(story) : opts);
|
||||
const isFunction = (obj: any) => !!(obj && obj.constructor && obj.call && obj.apply);
|
||||
const optionsOrCallOptions = (opts: any, story: any) => (isFunction(opts) ? opts(story) : opts);
|
||||
|
||||
export const snapshotWithOptions = (options = {}) => ({
|
||||
export const snapshotWithOptions = (
|
||||
options: { renderer?: any; serializer?: any } | Function = {}
|
||||
) => ({
|
||||
story,
|
||||
context,
|
||||
renderTree,
|
||||
snapshotFileName,
|
||||
}) => {
|
||||
}: {
|
||||
story: any;
|
||||
context: any;
|
||||
renderTree: RenderTree;
|
||||
snapshotFileName: string;
|
||||
}): Promise<void> | void => {
|
||||
const result = renderTree(story, context, optionsOrCallOptions(options, story));
|
||||
|
||||
function match(tree) {
|
||||
function match(tree: any) {
|
||||
if (snapshotFileName) {
|
||||
expect(tree).toMatchSpecificSnapshot(snapshotFileName);
|
||||
} else {
|
||||
@ -35,6 +44,11 @@ export const multiSnapshotWithOptions = (options = {}) => ({
|
||||
context,
|
||||
renderTree,
|
||||
stories2snapsConverter,
|
||||
}: {
|
||||
story: any;
|
||||
context: any;
|
||||
renderTree: RenderTree;
|
||||
stories2snapsConverter: Stories2SnapsConverter;
|
||||
}) =>
|
||||
snapshotWithOptions(options)({
|
||||
story,
|
||||
@ -43,12 +57,30 @@ export const multiSnapshotWithOptions = (options = {}) => ({
|
||||
snapshotFileName: stories2snapsConverter.getSnapshotFileName(context),
|
||||
});
|
||||
|
||||
export function shallowSnapshot({ story, context, renderShallowTree, options = {} }) {
|
||||
export function shallowSnapshot({
|
||||
story,
|
||||
context,
|
||||
renderShallowTree,
|
||||
options = {},
|
||||
}: {
|
||||
story: any;
|
||||
context: any;
|
||||
renderShallowTree: RenderTree;
|
||||
options: any;
|
||||
}) {
|
||||
const result = renderShallowTree(story, context, options);
|
||||
expect(result).toMatchSnapshot();
|
||||
}
|
||||
|
||||
export const renderWithOptions = (options = {}) => ({ story, context, renderTree }) => {
|
||||
export const renderWithOptions = (options = {}) => ({
|
||||
story,
|
||||
context,
|
||||
renderTree,
|
||||
}: {
|
||||
story: any;
|
||||
context: any;
|
||||
renderTree: RenderTree;
|
||||
}) => {
|
||||
const result = renderTree(story, context, options);
|
||||
|
||||
if (typeof result.then === 'function') {
|
4
addons/storyshots/storyshots-core/src/typings.d.ts
vendored
Normal file
4
addons/storyshots/storyshots-core/src/typings.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
declare module 'global';
|
||||
declare module 'jest-preset-angular/*';
|
||||
declare module 'preact-render-to-json';
|
||||
declare module 'react-test-renderer*';
|
@ -5,6 +5,7 @@
|
||||
],
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"experimentalDecorators": true
|
||||
"experimentalDecorators": true,
|
||||
"declaration": true
|
||||
}
|
||||
}
|
||||
|
@ -120,12 +120,16 @@ You might use `getScreenshotOptions` to specify options for screenshot. Will be
|
||||
```js
|
||||
import initStoryshots from '@storybook/addon-storyshots';
|
||||
import { imageSnapshot } from '@storybook/addon-storyshots-puppeteer';
|
||||
const getScreenshotOptions = ({context, url}) => {
|
||||
const getScreenshotOptions = ({ context, url }) => {
|
||||
return {
|
||||
fullPage: false // Do not take the full page screenshot. Default is 'true' in Storyshots.
|
||||
}
|
||||
}
|
||||
initStoryshots({suite: 'Image storyshots', test: imageSnapshot({storybookUrl: 'http://localhost:6006', getScreenshotOptions})});
|
||||
encoding: 'base64', // encoding: 'base64' is a property required by puppeteer
|
||||
fullPage: false, // Do not take the full page screenshot. Default is 'true' in Storyshots.,
|
||||
};
|
||||
};
|
||||
initStoryshots({
|
||||
suite: 'Image storyshots',
|
||||
test: imageSnapshot({ storybookUrl: 'http://localhost:6006', getScreenshotOptions }),
|
||||
});
|
||||
```
|
||||
|
||||
`getScreenshotOptions` receives an object `{ context: {kind, story}, url}`. _kind_ is the kind of the story and the _story_ its name. _url_ is the URL the browser will use to screenshot.
|
||||
@ -156,17 +160,16 @@ import { imageSnapshot } from '@storybook/addon-storyshots-puppeteer';
|
||||
import puppeteer from 'puppeteer';
|
||||
|
||||
(async function() {
|
||||
initStoryshots({
|
||||
suite: 'Image storyshots',
|
||||
test: imageSnapshot({
|
||||
storybookUrl: 'http://localhost:6006',
|
||||
getCustomBrowser: async () => puppeteer.connect('ws://yourUrl')
|
||||
}),
|
||||
});
|
||||
initStoryshots({
|
||||
suite: 'Image storyshots',
|
||||
test: imageSnapshot({
|
||||
storybookUrl: 'http://localhost:6006',
|
||||
getCustomBrowser: async () => puppeteer.connect({ browserWSEndpoint: 'ws://yourUrl' }),
|
||||
}),
|
||||
});
|
||||
})();
|
||||
```
|
||||
|
||||
|
||||
### Customizing a `page` instance
|
||||
|
||||
Sometimes, there is a need to customize a page before it calls the `goto` api.
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-storyshots-puppeteer",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Image snapshots addition to StoryShots based on puppeteer",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -22,22 +22,22 @@
|
||||
"README.md"
|
||||
],
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"prepare": "node ../../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/node-logger": "5.3.0-alpha.12",
|
||||
"@storybook/router": "5.3.0-alpha.12",
|
||||
"@storybook/node-logger": "5.3.0-alpha.15",
|
||||
"@storybook/router": "5.3.0-alpha.15",
|
||||
"@types/jest-image-snapshot": "^2.8.0",
|
||||
"@types/puppeteer-core": "^1.9.0",
|
||||
"core-js": "^3.0.1",
|
||||
"jest-image-snapshot": "^2.8.2",
|
||||
"puppeteer-core": "^1.12.2",
|
||||
"regenerator-runtime": "^0.13.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@storybook/addon-storyshots": "5.2.0-beta.13",
|
||||
"puppeteer": "^1.12.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"puppeteer": "^1.12.2"
|
||||
"@storybook/addon-storyshots": "5.3.0-alpha.13"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
@ -0,0 +1,18 @@
|
||||
import { MatchImageSnapshotOptions } from 'jest-image-snapshot';
|
||||
import { Base64ScreenShotOptions, Browser, DirectNavigationOptions, Page } from 'puppeteer-core';
|
||||
|
||||
export interface Context {
|
||||
kind: string;
|
||||
story: string;
|
||||
}
|
||||
|
||||
export interface ImageSnapshotConfig {
|
||||
storybookUrl: string;
|
||||
chromeExecutablePath: string;
|
||||
getMatchOptions: (options: { context: Context; url: string }) => MatchImageSnapshotOptions;
|
||||
getScreenshotOptions: (options: { context: Context; url: string }) => Base64ScreenShotOptions;
|
||||
beforeScreenshot: (page: Page, options: { context: Context; url: string }) => void;
|
||||
getGotoOptions: (options: { context: Context; url: string }) => DirectNavigationOptions;
|
||||
customizePage: (page: Page) => Promise<void>;
|
||||
getCustomBrowser: () => Promise<Browser>;
|
||||
}
|
@ -1,17 +1,18 @@
|
||||
import puppeteer from 'puppeteer';
|
||||
import puppeteer, { Browser, Page } from 'puppeteer-core';
|
||||
import { toMatchImageSnapshot } from 'jest-image-snapshot';
|
||||
import { logger } from '@storybook/node-logger';
|
||||
import { constructUrl } from './url';
|
||||
import { ImageSnapshotConfig } from './ImageSnapshotConfig';
|
||||
|
||||
expect.extend({ toMatchImageSnapshot });
|
||||
|
||||
// We consider taking the full page is a reasonnable default.
|
||||
const defaultScreenshotOptions = () => ({ fullPage: true });
|
||||
// We consider taking the full page is a reasonable default.
|
||||
const defaultScreenshotOptions = () => ({ fullPage: true, encoding: 'base64' } as const);
|
||||
|
||||
const noop = () => {};
|
||||
const asyncNoop = async () => {};
|
||||
const noop: () => undefined = () => undefined;
|
||||
const asyncNoop: () => Promise<undefined> = async () => undefined;
|
||||
|
||||
const defaultConfig = {
|
||||
const defaultConfig: ImageSnapshotConfig = {
|
||||
storybookUrl: 'http://localhost:6006',
|
||||
chromeExecutablePath: undefined,
|
||||
getMatchOptions: noop,
|
||||
@ -22,7 +23,7 @@ const defaultConfig = {
|
||||
getCustomBrowser: undefined,
|
||||
};
|
||||
|
||||
export const imageSnapshot = (customConfig = {}) => {
|
||||
export const imageSnapshot = (customConfig: Partial<ImageSnapshotConfig> = {}) => {
|
||||
const {
|
||||
storybookUrl,
|
||||
chromeExecutablePath,
|
||||
@ -34,12 +35,12 @@ export const imageSnapshot = (customConfig = {}) => {
|
||||
getCustomBrowser,
|
||||
} = { ...defaultConfig, ...customConfig };
|
||||
|
||||
let browser; // holds ref to browser. (ie. Chrome)
|
||||
let page; // Hold ref to the page to screenshot.
|
||||
let browser: Browser; // holds ref to browser. (ie. Chrome)
|
||||
let page: Page; // Hold ref to the page to screenshot.
|
||||
|
||||
const testFn = async ({ context }) => {
|
||||
const testFn = async ({ context }: any) => {
|
||||
const { kind, framework, name } = context;
|
||||
if (framework === 'rn') {
|
||||
if (framework === 'react-native') {
|
||||
// Skip tests since we de not support RN image snapshots.
|
||||
logger.error(
|
||||
"It seems you are running imageSnapshot on RN app and it's not supported. Skipping test."
|
||||
@ -67,8 +68,7 @@ export const imageSnapshot = (customConfig = {}) => {
|
||||
image = await page.screenshot(getScreenshotOptions({ context, url }));
|
||||
} catch (e) {
|
||||
logger.error(
|
||||
`Error when connecting to ${url}, did you start or build the storybook first? A storybook instance should be running or a static version should be built when using image snapshot feature.`,
|
||||
e
|
||||
`Error when connecting to ${url}, did you start or build the storybook first? A storybook instance should be running or a static version should be built when using image snapshot feature.`
|
||||
);
|
||||
throw e;
|
||||
}
|
2
addons/storyshots/storyshots-puppeteer/src/index.ts
Normal file
2
addons/storyshots/storyshots-puppeteer/src/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './ImageSnapshotConfig';
|
||||
export * from './imageSnapshot';
|
@ -2,7 +2,7 @@ import { toId } from '@storybook/router/utils';
|
||||
|
||||
import { URL } from 'url';
|
||||
|
||||
export const constructUrl = (storybookUrl, kind, story) => {
|
||||
export const constructUrl = (storybookUrl: string, kind: string, story: string) => {
|
||||
const id = toId(kind, story);
|
||||
|
||||
const storyUrl = `/iframe.html?id=${id}`;
|
14
addons/storyshots/storyshots-puppeteer/tsconfig.json
Normal file
14
addons/storyshots/storyshots-puppeteer/tsconfig.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"types": ["webpack-env", "node"],
|
||||
"declaration": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"src/__tests__/**/*"
|
||||
]
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-storysource",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Stories addon for storybook",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -28,11 +28,11 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/router": "5.3.0-alpha.12",
|
||||
"@storybook/source-loader": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/router": "5.3.0-alpha.15",
|
||||
"@storybook/source-loader": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"estraverse": "^4.2.0",
|
||||
"loader-utils": "^1.2.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/addon-viewport",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook addon to change the viewport size to mobile",
|
||||
"keywords": [
|
||||
"addon",
|
||||
@ -28,12 +28,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/client-logger": "5.3.0-alpha.12",
|
||||
"@storybook/components": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/theming": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/client-logger": "5.3.0-alpha.15",
|
||||
"@storybook/components": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"@storybook/theming": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"memoizerific": "^1.11.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/angular",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook for Angular: Develop Angular Components in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -34,9 +34,9 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/core": "5.3.0-alpha.12",
|
||||
"@storybook/node-logger": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/core": "5.3.0-alpha.15",
|
||||
"@storybook/node-logger": "5.3.0-alpha.15",
|
||||
"angular2-template-loader": "^0.6.2",
|
||||
"core-js": "^3.0.1",
|
||||
"fork-ts-checker-webpack-plugin": "^1.3.4",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/ember",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook for Ember: Develop Ember Component in isolation with Hot Reloading.",
|
||||
"homepage": "https://github.com/storybookjs/storybook/tree/master/app/ember",
|
||||
"bugs": {
|
||||
@ -30,7 +30,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ember/test-helpers": "^1.5.0",
|
||||
"@storybook/core": "5.3.0-alpha.12",
|
||||
"@storybook/core": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/html",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook for HTML: View HTML snippets in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -32,8 +32,8 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/core": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/core": "5.3.0-alpha.15",
|
||||
"@types/webpack-env": "^1.13.9",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/marko",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook for Marko: Develop Marko Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -32,8 +32,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@marko/webpack": "^2.0.0",
|
||||
"@storybook/client-logger": "5.3.0-alpha.12",
|
||||
"@storybook/core": "5.3.0-alpha.12",
|
||||
"@storybook/client-logger": "5.3.0-alpha.15",
|
||||
"@storybook/core": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/mithril",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook for Mithril: Develop Mithril Component in isolation.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -34,8 +34,8 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.6.2",
|
||||
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/core": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/core": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/polymer",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook for Polymer: Develop Polymer components in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -31,7 +31,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.3.0-alpha.12",
|
||||
"@storybook/core": "5.3.0-alpha.15",
|
||||
"@webcomponents/webcomponentsjs": "^1.2.0",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/preact",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook for Preact: Develop Preact Component in isolation.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -33,8 +33,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-react-jsx": "^7.3.0",
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/core": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/core": "5.3.0-alpha.15",
|
||||
"@types/webpack-env": "^1.13.9",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/rax",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook for Rax: Develop Rax Component in isolation.",
|
||||
"keywords": [
|
||||
"rax",
|
||||
@ -32,7 +32,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.3.0-alpha.12",
|
||||
"@storybook/core": "5.3.0-alpha.15",
|
||||
"babel-preset-rax": "^1.0.0-beta.0",
|
||||
"core-js": "^3.0.1",
|
||||
"driver-dom": "^2.0.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/react-native-server",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "A better way to develop React Native Components for your app",
|
||||
"keywords": [
|
||||
"react",
|
||||
@ -29,12 +29,12 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/api": "5.3.0-alpha.12",
|
||||
"@storybook/channel-websocket": "5.3.0-alpha.12",
|
||||
"@storybook/core": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/ui": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/api": "5.3.0-alpha.15",
|
||||
"@storybook/channel-websocket": "5.3.0-alpha.15",
|
||||
"@storybook/core": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"@storybook/ui": "5.3.0-alpha.15",
|
||||
"commander": "^3.0.2",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/react-native",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "A better way to develop React Native Components for your app",
|
||||
"keywords": [
|
||||
"react",
|
||||
@ -29,11 +29,11 @@
|
||||
"dependencies": {
|
||||
"@emotion/core": "^10.0.20",
|
||||
"@emotion/native": "^10.0.14",
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/channel-websocket": "5.3.0-alpha.12",
|
||||
"@storybook/channels": "5.3.0-alpha.12",
|
||||
"@storybook/client-api": "5.3.0-alpha.12",
|
||||
"@storybook/core-events": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/channel-websocket": "5.3.0-alpha.15",
|
||||
"@storybook/channels": "5.3.0-alpha.15",
|
||||
"@storybook/client-api": "5.3.0-alpha.15",
|
||||
"@storybook/core-events": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"emotion-theming": "^10.0.19",
|
||||
"react-native-swipe-gestures": "^1.0.4",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/react",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook for React: Develop React Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -36,9 +36,9 @@
|
||||
"@babel/plugin-transform-react-constant-elements": "^7.2.0",
|
||||
"@babel/preset-flow": "^7.0.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@storybook/addons": "5.3.0-alpha.12",
|
||||
"@storybook/core": "5.3.0-alpha.12",
|
||||
"@storybook/node-logger": "5.3.0-alpha.12",
|
||||
"@storybook/addons": "5.3.0-alpha.15",
|
||||
"@storybook/core": "5.3.0-alpha.15",
|
||||
"@storybook/node-logger": "5.3.0-alpha.15",
|
||||
"@svgr/webpack": "^4.0.3",
|
||||
"@types/webpack-env": "^1.13.7",
|
||||
"babel-plugin-add-react-displayname": "^0.0.5",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/riot",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook for riot.js: View riot snippets in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -31,7 +31,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.3.0-alpha.12",
|
||||
"@storybook/core": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"raw-loader": "^3.1.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@storybook/svelte",
|
||||
"version": "5.3.0-alpha.12",
|
||||
"version": "5.3.0-alpha.15",
|
||||
"description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.",
|
||||
"keywords": [
|
||||
"storybook"
|
||||
@ -31,7 +31,7 @@
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "5.3.0-alpha.12",
|
||||
"@storybook/core": "5.3.0-alpha.15",
|
||||
"core-js": "^3.0.1",
|
||||
"global": "^4.3.2",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user