diff --git a/__mocks__/inject-decorator.flow-stories.txt b/__mocks__/inject-decorator.flow-stories.txt new file mode 100644 index 000000000000..2f3ab992a523 --- /dev/null +++ b/__mocks__/inject-decorator.flow-stories.txt @@ -0,0 +1,35 @@ +// @flow +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import { withInfo } from '@storybook/addon-info'; + +import TableComponent from '../components/TableComponent'; + +import type { JssClasses } from '../types'; + +type State = { + value: any, +}; + +type Props = { + classes: JssClasses, + name: string, +}; + +class Table extends React.Component { + constructor(props) { + super(props); + this.state = { + value: undefined, + }; + } + + state: State; + + render() { + return ; + } +} + +const stories = storiesOf('Table', module); +stories.add('Flow Class', withInfo('Lorum Ipsum Nem')(() => )); diff --git a/addons/storysource/README.md b/addons/storysource/README.md index 847ad2157961..11f19e99d57a 100644 --- a/addons/storysource/README.md +++ b/addons/storysource/README.md @@ -46,6 +46,7 @@ The parser that will be parsing your code to AST (based on [prettier](https://gi Alowed values: * `javascript` - default * `typescript` +* `flow` Usage: diff --git a/addons/storysource/src/loader/__snapshots__/inject-decorator.test.js.snap b/addons/storysource/src/loader/__snapshots__/inject-decorator.test.js.snap index 40dbb369c25f..ef68c362afab 100644 --- a/addons/storysource/src/loader/__snapshots__/inject-decorator.test.js.snap +++ b/addons/storysource/src/loader/__snapshots__/inject-decorator.test.js.snap @@ -19,6 +19,45 @@ storiesOf('Custom|ng-content', module).add('Default', () => ({ " `; +exports[`inject-decorator injectDecorator option is false - flow does not inject stories decorator after the all "storiesOf" functions 1`] = ` +"// @flow +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import { withInfo } from '@storybook/addon-info'; + +import TableComponent from '../components/TableComponent'; + +import type { JssClasses } from '../types'; + +type State = { + value: any, +}; + +type Props = { + classes: JssClasses, + name: string, +}; + +class Table extends React.Component { + constructor(props) { + super(props); + this.state = { + value: undefined, + }; + } + + state: State; + + render() { + return ; + } +} + +const stories = storiesOf('Table', module); +stories.add('Flow Class', withInfo('Lorum Ipsum Nem')(() =>
)); +" +`; + exports[`inject-decorator injectDecorator option is false - ts does not inject stories decorator after the all "storiesOf" functions 1`] = ` "import { Component } from '@angular/core'; import { Store, StoreModule } from '@ngrx/store'; @@ -245,6 +284,60 @@ storiesOf('Custom|ng-content', module).addDecorator(withStorySource(__STORY__, _ " `; +exports[`inject-decorator positive - flow calculates "adds" map 1`] = ` +Object { + "@Flow Class": Object { + "endLoc": Object { + "col": 70, + "line": 35, + }, + "startLoc": Object { + "col": 12, + "line": 35, + }, + }, +} +`; + +exports[`inject-decorator positive - flow injects stories decorator after the all "storiesOf" functions 1`] = ` +"// @flow +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import { withInfo } from '@storybook/addon-info'; + +import TableComponent from '../components/TableComponent'; + +import type { JssClasses } from '../types'; + +type State = { + value: any, +}; + +type Props = { + classes: JssClasses, + name: string, +}; + +class Table extends React.Component { + constructor(props) { + super(props); + this.state = { + value: undefined, + }; + } + + state: State; + + render() { + return ; + } +} + +const stories = storiesOf('Table', module).addDecorator(withStorySource(__STORY__, __ADDS_MAP__)); +stories.add('Flow Class', withInfo('Lorum Ipsum Nem')(() =>
)); +" +`; + exports[`inject-decorator positive - ts calculates "adds" map 1`] = ` Object { "ngrx|Store@With component": Object { diff --git a/addons/storysource/src/loader/inject-decorator.test.js b/addons/storysource/src/loader/inject-decorator.test.js index 437a9ae53e28..17023390707e 100644 --- a/addons/storysource/src/loader/inject-decorator.test.js +++ b/addons/storysource/src/loader/inject-decorator.test.js @@ -51,6 +51,29 @@ describe('inject-decorator', () => { }); }); + describe('positive - flow', () => { + const mockFilePath = './__mocks__/inject-decorator.flow-stories.txt'; + const source = fs.readFileSync(mockFilePath, 'utf-8'); + const result = injectDecorator( + source, + ADD_DECORATOR_STATEMENT, + path.resolve(__dirname, mockFilePath), + { parser: 'flow' } + ); + + it('returns "changed" flag', () => { + expect(result.changed).toBeTruthy(); + }); + + it('injects stories decorator after the all "storiesOf" functions', () => { + expect(result.source).toMatchSnapshot(); + }); + + it('calculates "adds" map', () => { + expect(result.addsMap).toMatchSnapshot(); + }); + }); + describe('positive - ts', () => { const mockFilePath = './__mocks__/inject-decorator.ts.txt'; const source = fs.readFileSync(mockFilePath, 'utf-8'); @@ -155,6 +178,24 @@ describe('inject-decorator', () => { }); }); + describe('injectDecorator option is false - flow', () => { + const mockFilePath = './__mocks__/inject-decorator.flow-stories.txt'; + const source = fs.readFileSync(mockFilePath, 'utf-8'); + const result = injectDecorator( + source, + ADD_DECORATOR_STATEMENT, + path.resolve(__dirname, mockFilePath), + { + injectDecorator: false, + parser: 'flow', + } + ); + + it('does not inject stories decorator after the all "storiesOf" functions', () => { + expect(result.source).toMatchSnapshot(); + }); + }); + describe('injectDecorator option is false - ts', () => { const mockFilePath = './__mocks__/inject-decorator.ts.txt'; const source = fs.readFileSync(mockFilePath, 'utf-8'); diff --git a/addons/storysource/src/loader/parsers/index.js b/addons/storysource/src/loader/parsers/index.js index 192b7f3f59ce..a48f4fc52a68 100644 --- a/addons/storysource/src/loader/parsers/index.js +++ b/addons/storysource/src/loader/parsers/index.js @@ -9,6 +9,11 @@ function getParser(type) { return require('./parser-ts').default; } + if (type === 'flow') { + // eslint-disable-next-line global-require + return require('./parser-flow').default; + } + throw new Error(`Parser of type "${type}" is not supported`); } diff --git a/addons/storysource/src/loader/parsers/parser-flow.js b/addons/storysource/src/loader/parsers/parser-flow.js new file mode 100644 index 000000000000..95a743e02cf8 --- /dev/null +++ b/addons/storysource/src/loader/parsers/parser-flow.js @@ -0,0 +1,9 @@ +import parseFlow from 'prettier/parser-flow'; + +function parse(source) { + return parseFlow.parsers.flow.parse(source); +} + +export default { + parse, +};