feat(storybook): story generator takes into account actions (#6302)
This commit is contained in:
parent
63d9c578a3
commit
dbb74c6c67
@ -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',
|
name: 'default export function',
|
||||||
|
|||||||
@ -36,11 +36,7 @@ export function getArgsDefaultValue(property: ts.SyntaxKind): string {
|
|||||||
|
|
||||||
export function createComponentStoriesFile(
|
export function createComponentStoriesFile(
|
||||||
host: Tree,
|
host: Tree,
|
||||||
{
|
{ project, componentPath }: CreateComponentStoriesFileSchema
|
||||||
// name,
|
|
||||||
project,
|
|
||||||
componentPath,
|
|
||||||
}: CreateComponentStoriesFileSchema
|
|
||||||
) {
|
) {
|
||||||
const proj = getProjects(host).get(project);
|
const proj = getProjects(host).get(project);
|
||||||
const sourceRoot = proj.sourceRoot;
|
const sourceRoot = proj.sourceRoot;
|
||||||
@ -98,16 +94,29 @@ export function createComponentStoriesFile(
|
|||||||
name: string;
|
name: string;
|
||||||
defaultValue: any;
|
defaultValue: any;
|
||||||
}[] = [];
|
}[] = [];
|
||||||
|
let argTypes: {
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
actionText: string;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
if (propsInterface) {
|
if (propsInterface) {
|
||||||
propsTypeName = propsInterface.name.text;
|
propsTypeName = propsInterface.name.text;
|
||||||
|
|
||||||
props = propsInterface.members.map((member: ts.PropertySignature) => {
|
props = propsInterface.members.map((member: ts.PropertySignature) => {
|
||||||
|
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 {
|
return {
|
||||||
name: (member.name as ts.Identifier).text,
|
name: (member.name as ts.Identifier).text,
|
||||||
defaultValue: getArgsDefaultValue(member.type.kind),
|
defaultValue: getArgsDefaultValue(member.type.kind),
|
||||||
};
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
props = props.filter((p) => p && p.defaultValue !== undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateFiles(
|
generateFiles(
|
||||||
@ -118,6 +127,7 @@ export function createComponentStoriesFile(
|
|||||||
componentFileName: name,
|
componentFileName: name,
|
||||||
propsTypeName,
|
propsTypeName,
|
||||||
props,
|
props,
|
||||||
|
argTypes,
|
||||||
componentName: (cmpDeclaration as any).name.text,
|
componentName: (cmpDeclaration as any).name.text,
|
||||||
isPlainJs,
|
isPlainJs,
|
||||||
fileExt,
|
fileExt,
|
||||||
|
|||||||
@ -3,7 +3,11 @@ import<% if ( !isPlainJs ) { %> { <% } %> <%= componentName %><% if ( propsTypeN
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
component: <%= componentName %>,
|
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 <% } %>;
|
}<% if ( !isPlainJs ) { %> as Meta <% } %>;
|
||||||
|
|
||||||
const Template<% if ( !isPlainJs ) { %>: Story<<%= propsTypeName %>><% } %> = (args) => <<%= componentName %> {...args} />;
|
const Template<% if ( !isPlainJs ) { %>: Story<<%= propsTypeName %>><% } %> = (args) => <<%= componentName %> {...args} />;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user