Skip to content

Commit

Permalink
feat(storybook): story generator takes into account actions (#6302)
Browse files Browse the repository at this point in the history
  • Loading branch information
mandarini authored and FrozenPandaz committed Jul 12, 2021
1 parent 86fb228 commit 60ff3fa
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 11 deletions.
Expand Up @@ -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 (
<div>
<h1>Welcome to test component, {props.name}</h1>
<button onClick={props.someAction}>Click me!</button>
</div>
);
};
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<TestProps> = (args) => <Test {...args} />;
export const Primary = Template.bind({});
Primary.args = {
name: '',
displayAge: false,
};
`);
});
});

[
{
name: 'default export function',
Expand Down
30 changes: 20 additions & 10 deletions packages/react/src/generators/component-story/component-story.ts
Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand All @@ -118,6 +127,7 @@ export function createComponentStoriesFile(
componentFileName: name,
propsTypeName,
props,
argTypes,
componentName: (cmpDeclaration as any).name.text,
isPlainJs,
fileExt,
Expand Down
Expand Up @@ -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} />;
Expand Down

0 comments on commit 60ff3fa

Please sign in to comment.