-
-
Notifications
You must be signed in to change notification settings - Fork 9.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6f92476
commit 8f4dee7
Showing
5 changed files
with
154 additions
and
165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
/* eslint-disable jest/expect-expect */ | ||
import React, { KeyboardEventHandler, ReactNode } from 'react'; | ||
import { Meta, StoryObj } from '../public-types'; | ||
import { DecoratorFn } from '../public-api'; | ||
import { describe, satisfies, test } from './utils'; | ||
|
||
type ButtonProps = { label: string; disabled: boolean }; | ||
const Button: (props: ButtonProps) => JSX.Element = () => <></>; | ||
|
||
describe('Args can be provided in multiple ways', () => { | ||
test('✅All required args may be provided in meta', () => { | ||
const meta = satisfies<Meta<typeof Button>>()({ | ||
component: Button, | ||
args: { label: 'good', disabled: false }, | ||
}); | ||
|
||
type Story = StoryObj<typeof meta>; | ||
const Basic: Story = {}; | ||
}); | ||
|
||
test('✅ Required args may be provided partial in meta and the story', () => { | ||
const meta = satisfies<Meta<typeof Button>>()({ | ||
component: Button, | ||
args: { label: 'good' }, | ||
}); | ||
const Basic: StoryObj<typeof meta> = { | ||
args: { disabled: false }, | ||
}; | ||
}); | ||
|
||
test('❌ The combined shape of meta args and story args must match the required args.', () => { | ||
{ | ||
const meta = satisfies<Meta<typeof Button>>()({ component: Button }); | ||
const Basic: StoryObj<typeof meta> = { | ||
// @ts-expect-error disabled not provided ❌ | ||
args: { label: 'good' }, | ||
}; | ||
} | ||
{ | ||
const meta = satisfies<Meta<typeof Button>>()({ | ||
component: Button, | ||
args: { label: 'good' }, | ||
}); | ||
// @ts-expect-error disabled not provided ❌ | ||
const Basic: StoryObj<typeof meta> = {}; | ||
} | ||
{ | ||
const meta = satisfies<Meta<ButtonProps>>()({ component: Button }); | ||
const Basic: StoryObj<typeof meta> = { | ||
// @ts-expect-error disabled not provided ❌ | ||
args: { label: 'good' }, | ||
}; | ||
} | ||
}); | ||
}); | ||
|
||
test('✅ All void functions are optional', () => { | ||
interface CmpProps { | ||
label: string; | ||
disabled: boolean; | ||
onClick(): void; | ||
onKeyDown: KeyboardEventHandler; | ||
onLoading: (s: string) => JSX.Element; | ||
submitAction(): void; | ||
} | ||
|
||
const Cmp: (props: CmpProps) => JSX.Element = () => <></>; | ||
|
||
const meta = satisfies<Meta<CmpProps>>()({ | ||
component: Cmp, | ||
args: { label: 'good' }, | ||
}); | ||
|
||
const Basic: StoryObj<typeof meta> = { | ||
args: { disabled: false, onLoading: () => <div>Loading...</div> }, | ||
}; | ||
}); | ||
|
||
type ThemeData = 'light' | 'dark'; | ||
declare const Theme: (props: { theme: ThemeData; children?: ReactNode }) => JSX.Element; | ||
|
||
describe('Story args can be inferred', () => { | ||
test('Correct args are inferred when type is widened for render function', () => { | ||
type Props = ButtonProps & { theme: ThemeData }; | ||
|
||
const meta = satisfies<Meta<Props>>()({ | ||
component: Button, | ||
args: { label: 'good', disabled: false }, | ||
render: (args, { component }) => { | ||
// TODO: Might be nice if we can infer that. | ||
// component is not null as it is provided in meta | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
const Component = component!; | ||
return ( | ||
<Theme theme={args.theme}> | ||
<Component {...args} /> | ||
</Theme> | ||
); | ||
}, | ||
}); | ||
|
||
const Basic: StoryObj<typeof meta> = { args: { theme: 'light' } }; | ||
}); | ||
|
||
test('Correct args are inferred when type is widened for decorators', () => { | ||
type Props = ButtonProps & { decoratorArg: number }; | ||
|
||
const withDecorator: DecoratorFn<{ decoratorArg: number }> = (Story, { args }) => ( | ||
<> | ||
Decorator: {args.decoratorArg} | ||
This Story allows optional TArgs, but the decorator only knows about the decoratorArg. It | ||
should really allow optionally a Partial of TArgs. | ||
<Story args={{ decoratorArg: 0 }} /> | ||
</> | ||
); | ||
|
||
const meta = satisfies<Meta<Props>>()({ | ||
component: Button, | ||
args: { label: 'good', disabled: false }, | ||
decorators: [withDecorator], | ||
}); | ||
|
||
// Yes, decorator arg is required | ||
const Basic: StoryObj<typeof meta> = { args: { decoratorArg: 0 } }; | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Inspired by: https://github.com/vuejs/core/blob/main/test-dts/index.d.ts | ||
|
||
export function describe(name: string, fn: () => void): void {} | ||
export function test(name: string, fn: () => void): void {} | ||
|
||
export function expectAssignable<T>(value: T): void {} | ||
type IsAny<T> = T extends true ? (T extends false ? true : never) : never; | ||
|
||
/** | ||
* Mimicking the satisfies operator. | ||
*/ | ||
export function satisfies<A>() { | ||
return <T extends A>(x: T) => x; | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters