Add argtype stories

This commit is contained in:
Tom Coleman 2022-09-06 11:27:47 +10:00
parent efbfaf4b1d
commit 7835e77ad0
3 changed files with 72 additions and 129 deletions

View File

@ -1,98 +0,0 @@
import React, { FC, useState } from 'react';
import { useArgs } from '@storybook/client-api';
interface CustomArgs {
first?: string;
last?: string;
foo?: string;
}
type UpdateArgs = ReturnType<typeof useArgs>[1];
type ResetArgs = ReturnType<typeof useArgs>[2];
const ArgUpdater: FC<{ args: CustomArgs; updateArgs: UpdateArgs; resetArgs: ResetArgs }> = ({
args,
updateArgs,
resetArgs,
}) => {
const [argsInput, updateArgsInput] = useState(JSON.stringify(args));
return (
<div>
<h3>Hooks args:</h3>
<pre>{JSON.stringify(args)}</pre>
<form
onSubmit={(e) => {
e.preventDefault();
updateArgs(JSON.parse(argsInput));
}}
>
<textarea value={argsInput} onChange={(e) => updateArgsInput(e.target.value)} />
<br />
<button type="submit">Change</button>
<button type="button" onClick={() => resetArgs()}>
Reset all
</button>
</form>
</div>
);
};
export default {
title: 'Core/Args',
decorators: [
(story) => {
const [args, updateArgs, resetArgs] = useArgs<CustomArgs>();
return (
<>
{story()}
<ArgUpdater args={args} updateArgs={updateArgs} resetArgs={resetArgs} />
</>
);
},
],
};
const Template = (args) => {
return (
<div>
<h3>Input args:</h3>
<pre>{JSON.stringify(args)}</pre>
</div>
);
};
export const PassedToStory = Template.bind({});
PassedToStory.argTypes = { name: { defaultValue: 'initial', control: 'text' } };
export const OtherValues = Template.bind({});
OtherValues.argTypes = { name: { control: 'text' } };
export const DifferentSet = Template.bind({});
DifferentSet.args = {
foo: 'bar',
bar: 2,
} as CustomArgs;
export const TestUndefinedArgs = Template.bind({});
TestUndefinedArgs.args = {
first: 'Bob',
last: 'Miller',
foo: 'bar',
} as CustomArgs;
TestUndefinedArgs.argTypes = {
first: {
control: { type: 'select' },
options: ['Bob', 'Alice'],
},
last: {
control: { type: 'select' },
options: ['Miller', 'Meyer'],
},
foo: {
control: { type: 'text' },
},
};

View File

@ -1,31 +0,0 @@
// storiesOf('Core|Async', module).add('storyFn returns a Promise', () =>
// Promise.resolve(<div>I Promise!</div>)
// );
// const AsyncStories = storiesOf('Core|Async', module);
// setTimeout(() => {
// AsyncStories.add('.add called in setTimeout', () => <div>Added late</div>);
// });
// import('fast-deep-equal').then(m => {
// storiesOf('Core|Async', module).add('storyOf is added async', () => (
// <div>{m.default('foo', 'foo') ? 'TRUE' : 'FALSE'}</div>
// ));
// });
// storiesOf('Core|Async', module).add('storyFn returns a Promise', () =>
// Promise.resolve(<div>I Promise!</div>)
// );
// const AsyncStories = storiesOf('Core|Async', module);
// setTimeout(() => {
// AsyncStories.add('.add called in setTimeout', () => <div>Added late</div>);
// });
// import('fast-deep-equal').then(m => {
// storiesOf('Core|Async', module).add('storyOf is added async', () => (
// <div>{m.default('foo', 'foo') ? 'TRUE' : 'FALSE'}</div>
// ));
// });

View File

@ -0,0 +1,72 @@
import globalThis from 'global';
import { PartialStoryFn, PlayFunctionContext, StoryContext } from '@storybook/csf';
import { within } from '@storybook/testing-library';
import { expect } from '@storybook/jest';
export default {
component: globalThis.Components.Pre,
// Compose all the argTypes into `object`, so the pre component only needs a single prop
decorators: [
(storyFn: PartialStoryFn, context: StoryContext) =>
storyFn({ args: { object: context.argTypes } }),
],
argTypes: {
componentArg: { type: 'string' },
storyArg: { type: 'string' },
composedArg: { type: 'string' },
},
};
export const Inheritance = {
argTypes: {
storyArg: { type: 'number' },
composedArg: { options: ['a', 'b'] },
},
play: async ({ canvasElement }: PlayFunctionContext) => {
// NOTE: these stories don't test project-level argTypes inheritance as it is too problematic
// to have an argType floating around that will apply too *all* other stories in our sandboxes.
await expect(JSON.parse(within(canvasElement).getByTestId('pre').innerHTML)).toMatchObject({
componentArg: { type: { name: 'string' } },
storyArg: { type: { name: 'number' } },
composedArg: { type: { name: 'string' }, options: ['a', 'b'] },
});
},
};
// Check the inferred arg types from the args
export const ArgTypeInference = {
args: {
a: 1,
b: '1',
c: true,
d: { a: 'b' },
e: ['a', 'b'],
},
play: async ({ canvasElement }: PlayFunctionContext) => {
await expect(JSON.parse(within(canvasElement).getByTestId('pre').innerHTML)).toMatchObject({
a: { type: { name: 'number' } },
b: { type: { name: 'string' } },
c: { type: { name: 'boolean' } },
d: { type: { name: 'object', value: { a: { name: 'string' } } } },
e: { type: { name: 'array', value: { name: 'string' } } },
});
},
};
// Check the inferred controls from the arg types
export const ControlInference = {
argTypes: {
a: { type: 'number' },
b: { type: 'string' },
c: { type: 'boolean' },
d: { type: 'object' },
},
play: async ({ canvasElement }: PlayFunctionContext) => {
await expect(JSON.parse(within(canvasElement).getByTestId('pre').innerHTML)).toMatchObject({
a: { control: { type: 'number' } },
b: { control: { type: 'text' } },
c: { control: { type: 'boolean' } },
d: { control: { type: 'object' } },
});
},
};