From dbb74c6c67d29f222f6d073f498a5dee8ccb7142 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Fri, 9 Jul 2021 12:06:16 +0300 Subject: [PATCH] feat(storybook): story generator takes into account actions (#6302) --- .../component-story/component-story.spec.ts | 61 +++++++++++++++++++ .../component-story/component-story.ts | 30 ++++++--- .../__componentFileName__.stories.__fileExt__ | 6 +- 3 files changed, 86 insertions(+), 11 deletions(-) diff --git a/packages/react/src/generators/component-story/component-story.spec.ts b/packages/react/src/generators/component-story/component-story.spec.ts index d0d14a1971..97a631537c 100644 --- a/packages/react/src/generators/component-story/component-story.spec.ts +++ b/packages/react/src/generators/component-story/component-story.spec.ts @@ -217,6 +217,67 @@ describe('react:component-story', () => { }); }); + describe('component with props and actions', () => { + beforeEach(async () => { + appTree.write( + cmpPath, + `import React from 'react'; + + import './test.scss'; + + export type ButtonStyle = 'default' | 'primary' | 'warning'; + + export interface TestProps { + name: string; + displayAge: boolean; + someAction: (e: unknown) => void; + style: ButtonStyle; + } + + export const Test = (props: TestProps) => { + return ( +
+

Welcome to test component, {props.name}

+ +
+ ); + }; + + export default Test; + ` + ); + + await componentStoryGenerator(appTree, { + componentPath: 'lib/test-ui-lib.tsx', + project: 'test-ui-lib', + }); + }); + + it('should setup controls based on the component props', () => { + expect(formatFile`${appTree.read(storyFilePath, 'utf-8')}`) + .toContain(formatFile` + import { Story, Meta } from '@storybook/react'; + import { Test, TestProps } from './test-ui-lib'; + + export default { + component: Test, + title: 'Test', + argTypes: { + someAction: { action: 'someAction executed!' }, + }, + } as Meta; + + const Template: Story = (args) => ; + + export const Primary = Template.bind({}); + Primary.args = { + name: '', + displayAge: false, + }; + `); + }); + }); + [ { name: 'default export function', diff --git a/packages/react/src/generators/component-story/component-story.ts b/packages/react/src/generators/component-story/component-story.ts index c8482ecebc..edb962df62 100644 --- a/packages/react/src/generators/component-story/component-story.ts +++ b/packages/react/src/generators/component-story/component-story.ts @@ -36,11 +36,7 @@ export function getArgsDefaultValue(property: ts.SyntaxKind): string { export function createComponentStoriesFile( host: Tree, - { - // name, - project, - componentPath, - }: CreateComponentStoriesFileSchema + { project, componentPath }: CreateComponentStoriesFileSchema ) { const proj = getProjects(host).get(project); const sourceRoot = proj.sourceRoot; @@ -98,16 +94,29 @@ export function createComponentStoriesFile( name: string; defaultValue: any; }[] = []; + let argTypes: { + name: string; + type: string; + actionText: string; + }[] = []; if (propsInterface) { propsTypeName = propsInterface.name.text; - props = propsInterface.members.map((member: ts.PropertySignature) => { - return { - name: (member.name as ts.Identifier).text, - defaultValue: getArgsDefaultValue(member.type.kind), - }; + if (member.type.kind === ts.SyntaxKind.FunctionType) { + argTypes.push({ + name: (member.name as ts.Identifier).text, + type: 'action', + actionText: `${(member.name as ts.Identifier).text} executed!`, + }); + } else { + return { + name: (member.name as ts.Identifier).text, + defaultValue: getArgsDefaultValue(member.type.kind), + }; + } }); + props = props.filter((p) => p && p.defaultValue !== undefined); } generateFiles( @@ -118,6 +127,7 @@ export function createComponentStoriesFile( componentFileName: name, propsTypeName, props, + argTypes, componentName: (cmpDeclaration as any).name.text, isPlainJs, fileExt, diff --git a/packages/react/src/generators/component-story/files/__componentFileName__.stories.__fileExt__ b/packages/react/src/generators/component-story/files/__componentFileName__.stories.__fileExt__ index 2154ac7d7a..f232d83f6b 100644 --- a/packages/react/src/generators/component-story/files/__componentFileName__.stories.__fileExt__ +++ b/packages/react/src/generators/component-story/files/__componentFileName__.stories.__fileExt__ @@ -3,7 +3,11 @@ import<% if ( !isPlainJs ) { %> { <% } %> <%= componentName %><% if ( propsTypeN export default { component: <%= componentName %>, - title: '<%= componentName %>' + title: '<%= componentName %>',<% if ( argTypes && argTypes.length > 0 ) { %> + argTypes: {<% for (let argType of argTypes) { %> + <%= argType.name %>: { <%- argType.type %> : "<%- argType.actionText %>" },<% } %> +} + <% } %> }<% if ( !isPlainJs ) { %> as Meta <% } %>; const Template<% if ( !isPlainJs ) { %>: Story<<%= propsTypeName %>><% } %> = (args) => <<%= componentName %> {...args} />;