mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-07 07:21:17 +08:00
Merge pull request #28764 from storybookjs/kasper/introduce-run
Core: Introduce run over play in portable stories, and revert back play changes of 8.2
This commit is contained in:
commit
3b65e7267e
@ -89,25 +89,8 @@ export function composeStory<TRenderer extends Renderer = Renderer, TArgs extend
|
||||
normalizedComponentAnnotations
|
||||
);
|
||||
|
||||
// TODO: Remove this in 9.0
|
||||
// We can only use the renderToCanvas definition of the default config when testingLibraryRender is set
|
||||
// This makes sure, that when the user doesn't do this, and doesn't provide its own renderToCanvas definition,
|
||||
// we fall back to the < 8.1 behavior of the play function.
|
||||
|
||||
const fallback =
|
||||
defaultConfig &&
|
||||
!globalProjectAnnotations?.testingLibraryRender &&
|
||||
!projectAnnotations?.testingLibraryRender;
|
||||
|
||||
const normalizedProjectAnnotations = normalizeProjectAnnotations<TRenderer>(
|
||||
composeConfigs([
|
||||
{
|
||||
...defaultConfig,
|
||||
renderToCanvas: fallback ? undefined : defaultConfig?.renderToCanvas,
|
||||
},
|
||||
globalProjectAnnotations,
|
||||
projectAnnotations ?? {},
|
||||
])
|
||||
composeConfigs([defaultConfig ?? {}, globalProjectAnnotations, projectAnnotations ?? {}])
|
||||
);
|
||||
|
||||
const story = prepareStory<TRenderer>(
|
||||
@ -130,7 +113,7 @@ export function composeStory<TRenderer extends Renderer = Renderer, TArgs extend
|
||||
loaded: {},
|
||||
abortSignal: new AbortController().signal,
|
||||
step: (label, play) => story.runStep(label, play, context),
|
||||
canvasElement: globalThis?.document?.body,
|
||||
canvasElement: null!,
|
||||
canvas: {} as Canvas,
|
||||
...story,
|
||||
context: null!,
|
||||
@ -149,6 +132,7 @@ export function composeStory<TRenderer extends Renderer = Renderer, TArgs extend
|
||||
id: story.id,
|
||||
name: story.name,
|
||||
tags: story.tags,
|
||||
showMain: () => {},
|
||||
showError: (error) => {},
|
||||
showException: (error) => {},
|
||||
forceRemount: true,
|
||||
@ -171,28 +155,23 @@ export function composeStory<TRenderer extends Renderer = Renderer, TArgs extend
|
||||
|
||||
let loadedContext: StoryContext<TRenderer> | undefined;
|
||||
|
||||
// TODO: Remove in 9.0
|
||||
const backwardsCompatiblePlay = async (
|
||||
extraContext?: Partial<StoryContext<TRenderer, Partial<TArgs>>>
|
||||
) => {
|
||||
const play = async (extraContext?: Partial<StoryContext<TRenderer, Partial<TArgs>>>) => {
|
||||
const context = initializeContext();
|
||||
context.canvasElement ??= globalThis?.document?.body;
|
||||
if (loadedContext) {
|
||||
context.loaded = loadedContext.loaded;
|
||||
}
|
||||
Object.assign(context, extraContext);
|
||||
return story.playFunction!(context);
|
||||
};
|
||||
const newPlay = (extraContext?: Partial<StoryContext<TRenderer, Partial<TArgs>>>) => {
|
||||
|
||||
const run = (extraContext?: Partial<StoryContext<TRenderer, Partial<TArgs>>>) => {
|
||||
const context = initializeContext();
|
||||
Object.assign(context, extraContext);
|
||||
return playStory(story, context);
|
||||
return runStory(story, context);
|
||||
};
|
||||
const playFunction =
|
||||
!story.renderToCanvas && story.playFunction
|
||||
? backwardsCompatiblePlay
|
||||
: !story.renderToCanvas && !story.playFunction
|
||||
? undefined
|
||||
: newPlay;
|
||||
|
||||
const playFunction = story.playFunction ? play : undefined;
|
||||
|
||||
const composedStory: ComposedStoryFn<TRenderer, Partial<TArgs>> = Object.assign(
|
||||
function storyFn(extraArgs?: Partial<TArgs>) {
|
||||
@ -226,6 +205,7 @@ export function composeStory<TRenderer extends Renderer = Renderer, TArgs extend
|
||||
parameters: story.parameters as Parameters,
|
||||
argTypes: story.argTypes as StrictArgTypes<TArgs>,
|
||||
play: playFunction!,
|
||||
run,
|
||||
tags: story.tags,
|
||||
}
|
||||
);
|
||||
@ -325,13 +305,24 @@ export function createPlaywrightTest<TFixture extends { extend: any }>(
|
||||
|
||||
// TODO At some point this function should live in prepareStory and become the core of StoryRender.render as well.
|
||||
// Will make a follow up PR for that
|
||||
async function playStory<TRenderer extends Renderer>(
|
||||
async function runStory<TRenderer extends Renderer>(
|
||||
story: PreparedStory<TRenderer>,
|
||||
context: StoryContext<TRenderer>
|
||||
) {
|
||||
for (const callback of [...cleanups].reverse()) await callback();
|
||||
cleanups.length = 0;
|
||||
|
||||
if (!context.canvasElement) {
|
||||
const container = document.createElement('div');
|
||||
globalThis?.document?.body?.appendChild(container);
|
||||
context.canvasElement = container;
|
||||
cleanups.push(() => {
|
||||
if (globalThis?.document?.body?.contains(container)) {
|
||||
globalThis?.document?.body?.removeChild(container);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
context.loaded = await story.applyLoaders(context);
|
||||
if (context.abortSignal.aborted) return;
|
||||
|
||||
|
@ -44,7 +44,8 @@ export type ComposedStoryFn<
|
||||
> = PartialArgsStoryFn<TRenderer, TArgs> & {
|
||||
args: TArgs;
|
||||
id: StoryId;
|
||||
play: (context?: Partial<StoryContext<TRenderer, Partial<TArgs>>>) => Promise<void>;
|
||||
play?: (context?: Partial<StoryContext<TRenderer, Partial<TArgs>>>) => Promise<void>;
|
||||
run: (context?: Partial<StoryContext<TRenderer, Partial<TArgs>>>) => Promise<void>;
|
||||
load: () => Promise<void>;
|
||||
storyName: string;
|
||||
parameters: Parameters;
|
||||
|
@ -53,7 +53,7 @@ describe('renders', () => {
|
||||
});
|
||||
|
||||
it('should render component mounted in play function', async () => {
|
||||
await MountInPlayFunction.play();
|
||||
await MountInPlayFunction.run();
|
||||
|
||||
expect(screen.getByTestId('spy-data').textContent).toEqual('mockFn return value');
|
||||
expect(screen.getByTestId('loaded-data').textContent).toEqual('loaded data');
|
||||
@ -65,7 +65,7 @@ describe('renders', () => {
|
||||
expect(getByTestId('spy-data').textContent).toEqual('mockFn return value');
|
||||
expect(getByTestId('loaded-data').textContent).toEqual('loaded data');
|
||||
// spy assertions happen in the play function and should work
|
||||
await LoaderStory.play!();
|
||||
await LoaderStory.run!();
|
||||
});
|
||||
});
|
||||
|
||||
@ -125,7 +125,7 @@ describe('CSF3', () => {
|
||||
|
||||
it('renders with play function without canvas element', async () => {
|
||||
const CSF3InputFieldFilled = composeStory(stories.CSF3InputFieldFilled, stories.default);
|
||||
await CSF3InputFieldFilled.play();
|
||||
await CSF3InputFieldFilled.run();
|
||||
|
||||
const input = screen.getByTestId('input') as HTMLInputElement;
|
||||
expect(input.value).toEqual('Hello world!');
|
||||
@ -138,7 +138,7 @@ describe('CSF3', () => {
|
||||
console.log(div.tagName);
|
||||
document.body.appendChild(div);
|
||||
|
||||
await CSF3InputFieldFilled.play({ canvasElement: div });
|
||||
await CSF3InputFieldFilled.run({ canvasElement: div });
|
||||
|
||||
const input = screen.getByTestId('input') as HTMLInputElement;
|
||||
expect(input.value).toEqual('Hello world!');
|
||||
@ -185,6 +185,6 @@ const testCases = Object.values(composeStories(stories)).map(
|
||||
);
|
||||
it.each(testCases)('Renders %s story', async (_storyName, Story) => {
|
||||
if (_storyName === 'CSF2StoryWithLocale') return;
|
||||
await Story.play();
|
||||
await Story.run();
|
||||
expect(document.body).toMatchSnapshot();
|
||||
});
|
||||
|
@ -45,11 +45,16 @@ export function setProjectAnnotations(
|
||||
// This will not be necessary once we have auto preset loading
|
||||
export const INTERNAL_DEFAULT_PROJECT_ANNOTATIONS: ProjectAnnotations<ReactRenderer> = {
|
||||
...reactProjectAnnotations,
|
||||
renderToCanvas: ({
|
||||
storyContext: { context, unboundStoryFn: Story, testingLibraryRender: render, canvasElement },
|
||||
}) => {
|
||||
if (render == null) throw new TestingLibraryMustBeConfiguredError();
|
||||
const { unmount } = render(<Story {...context} />, { baseElement: context.canvasElement });
|
||||
renderToCanvas: (renderContext, canvasElement) => {
|
||||
if (renderContext.storyContext.testingLibraryRender == null) {
|
||||
throw new TestingLibraryMustBeConfiguredError();
|
||||
// Enable for 8.3
|
||||
// return reactProjectAnnotations.renderToCanvas(renderContext, canvasElement);
|
||||
}
|
||||
const {
|
||||
storyContext: { context, unboundStoryFn: Story, testingLibraryRender: render },
|
||||
} = renderContext;
|
||||
const { unmount } = render(<Story {...context} />, { container: context.canvasElement });
|
||||
return unmount;
|
||||
},
|
||||
};
|
||||
|
@ -2,82 +2,48 @@
|
||||
|
||||
exports[`Renders CSF2Secondary story 1`] = `
|
||||
<body>
|
||||
|
||||
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
label coming from story args!
|
||||
<!---->
|
||||
</button>
|
||||
|
||||
<div>
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
label coming from story args!
|
||||
<!---->
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders CSF2StoryWithParamsAndDecorator story 1`] = `
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
<div
|
||||
data-testid="local-decorator"
|
||||
style="margin: 3em;"
|
||||
>
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
type="button"
|
||||
<div>
|
||||
<div
|
||||
data-testid="local-decorator"
|
||||
style="margin: 3em;"
|
||||
>
|
||||
foo
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
foo
|
||||
<!---->
|
||||
</button>
|
||||
<!---->
|
||||
</button>
|
||||
<!---->
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders CSF3Button story 1`] = `
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
foo
|
||||
<!---->
|
||||
</button>
|
||||
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders CSF3ButtonWithRender story 1`] = `
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<p
|
||||
data-testid="custom-render"
|
||||
>
|
||||
I am a custom render function
|
||||
</p>
|
||||
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
@ -86,88 +52,52 @@ exports[`Renders CSF3ButtonWithRender story 1`] = `
|
||||
foo
|
||||
<!---->
|
||||
</button>
|
||||
<!---->
|
||||
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders CSF3ButtonWithRender story 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<p
|
||||
data-testid="custom-render"
|
||||
>
|
||||
I am a custom render function
|
||||
</p>
|
||||
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
foo
|
||||
<!---->
|
||||
</button>
|
||||
<!---->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders CSF3InputFieldFilled story 1`] = `
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<input
|
||||
data-testid="input"
|
||||
formaction="http://localhost:3000/"
|
||||
formmethod=""
|
||||
/>
|
||||
|
||||
<div>
|
||||
<input
|
||||
data-testid="input"
|
||||
formaction="http://localhost:3000/"
|
||||
formmethod=""
|
||||
/>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders CSF3Primary story 1`] = `
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<button
|
||||
class="storybook-button storybook-button--large storybook-button--primary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
foo
|
||||
<!---->
|
||||
</button>
|
||||
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders LoaderStory story 1`] = `
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<div
|
||||
data-testid="loaded-data"
|
||||
>
|
||||
loaded data
|
||||
</div>
|
||||
|
||||
<div
|
||||
data-testid="spy-data"
|
||||
>
|
||||
mockFn return value
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders NewStory story 1`] = `
|
||||
<body>
|
||||
|
||||
|
||||
|
||||
|
||||
<div
|
||||
data-testid="local-decorator"
|
||||
style="margin: 3em;"
|
||||
>
|
||||
<button
|
||||
class="storybook-button storybook-button--large storybook-button--primary"
|
||||
style=""
|
||||
@ -176,11 +106,53 @@ exports[`Renders NewStory story 1`] = `
|
||||
foo
|
||||
<!---->
|
||||
</button>
|
||||
<!---->
|
||||
<!---->
|
||||
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders LoaderStory story 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
data-testid="loaded-data"
|
||||
>
|
||||
loaded data
|
||||
</div>
|
||||
|
||||
<div
|
||||
data-testid="spy-data"
|
||||
>
|
||||
mockFn return value
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders NewStory story 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
data-testid="local-decorator"
|
||||
style="margin: 3em;"
|
||||
>
|
||||
<button
|
||||
class="storybook-button storybook-button--large storybook-button--primary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
foo
|
||||
<!---->
|
||||
</button>
|
||||
<!---->
|
||||
<!---->
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
|
||||
</div>
|
||||
<!---->
|
||||
<!---->
|
||||
|
||||
</body>
|
||||
`;
|
||||
|
@ -70,7 +70,7 @@ describe('renders', () => {
|
||||
expect(getByTestId('spy-data').textContent).toEqual('mockFn return value');
|
||||
expect(getByTestId('loaded-data').textContent).toEqual('loaded data');
|
||||
// spy assertions happen in the play function and should work
|
||||
await LoaderStory.play!();
|
||||
await LoaderStory.run!();
|
||||
});
|
||||
});
|
||||
|
||||
@ -120,7 +120,7 @@ describe('CSF3', () => {
|
||||
it('renders with play function without canvas element', async () => {
|
||||
const CSF3InputFieldFilled = composeStory(stories.CSF3InputFieldFilled, stories.default);
|
||||
|
||||
await CSF3InputFieldFilled.play();
|
||||
await CSF3InputFieldFilled.run();
|
||||
|
||||
const input = screen.getByTestId('input') as HTMLInputElement;
|
||||
expect(input.value).toEqual('Hello world!');
|
||||
@ -132,7 +132,7 @@ describe('CSF3', () => {
|
||||
const div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
|
||||
await CSF3InputFieldFilled.play({ canvasElement: div });
|
||||
await CSF3InputFieldFilled.run({ canvasElement: div });
|
||||
|
||||
const input = screen.getByTestId('input') as HTMLInputElement;
|
||||
expect(input.value).toEqual('Hello world!');
|
||||
@ -171,6 +171,6 @@ const testCases = Object.values(composeStories(stories)).map(
|
||||
);
|
||||
it.each(testCases)('Renders %s story', async (_storyName, Story) => {
|
||||
if (_storyName === 'CSF2StoryWithLocale') return;
|
||||
await Story.play();
|
||||
await Story.run();
|
||||
expect(document.body).toMatchSnapshot();
|
||||
});
|
||||
|
@ -63,8 +63,16 @@ export function setProjectAnnotations(
|
||||
// This will not be necessary once we have auto preset loading
|
||||
export const INTERNAL_DEFAULT_PROJECT_ANNOTATIONS: ProjectAnnotations<SvelteRenderer> = {
|
||||
...svelteProjectAnnotations,
|
||||
renderToCanvas: ({ storyFn, storyContext: { testingLibraryRender: render, canvasElement } }) => {
|
||||
if (render == null) throw new TestingLibraryMustBeConfiguredError();
|
||||
renderToCanvas: (renderContext, canvasElement) => {
|
||||
if (renderContext.storyContext.testingLibraryRender == null) {
|
||||
throw new TestingLibraryMustBeConfiguredError();
|
||||
// Enable for 8.3
|
||||
// return svelteProjectAnnotations.renderToCanvas(renderContext, canvasElement);
|
||||
}
|
||||
const {
|
||||
storyFn,
|
||||
storyContext: { testingLibraryRender: render },
|
||||
} = renderContext;
|
||||
const { Component, props } = storyFn();
|
||||
const { unmount } = render(Component, { props, target: canvasElement });
|
||||
return unmount;
|
||||
|
@ -52,7 +52,7 @@ describe('renders', () => {
|
||||
expect(getByTestId('spy-data').textContent).toEqual('mockFn return value');
|
||||
expect(getByTestId('loaded-data').textContent).toEqual('loaded data');
|
||||
// spy assertions happen in the play function and should work
|
||||
await LoaderStory.play!();
|
||||
await LoaderStory.run!();
|
||||
});
|
||||
});
|
||||
|
||||
@ -103,7 +103,7 @@ describe('CSF3', () => {
|
||||
it('renders with play function', async () => {
|
||||
const CSF3InputFieldFilled = composeStory(stories.CSF3InputFieldFilled, stories.default);
|
||||
|
||||
await CSF3InputFieldFilled.play();
|
||||
await CSF3InputFieldFilled.run();
|
||||
|
||||
const input = screen.getByTestId('input') as HTMLInputElement;
|
||||
expect(input.value).toEqual('Hello world!');
|
||||
@ -145,7 +145,7 @@ describe('ComposeStories types', () => {
|
||||
const testCases = Object.values(composeStories(stories)).map((Story) => [Story.storyName, Story]);
|
||||
it.each(testCases)('Renders %s story', async (_storyName, Story) => {
|
||||
if (typeof Story === 'string' || _storyName === 'CSF2StoryWithLocale') return;
|
||||
await Story.play();
|
||||
await Story.run();
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
expect(document.body).toMatchSnapshot();
|
||||
});
|
||||
|
@ -53,9 +53,17 @@ export function setProjectAnnotations(
|
||||
// This will not be necessary once we have auto preset loading
|
||||
export const vueProjectAnnotations: ProjectAnnotations<VueRenderer> = {
|
||||
...defaultProjectAnnotations,
|
||||
renderToCanvas: ({ storyFn, storyContext: { testingLibraryRender: render, canvasElement } }) => {
|
||||
if (render == null) throw new TestingLibraryMustBeConfiguredError();
|
||||
const { unmount } = render(storyFn(), { baseElement: canvasElement });
|
||||
renderToCanvas: (renderContext, canvasElement) => {
|
||||
if (renderContext.storyContext.testingLibraryRender == null) {
|
||||
throw new TestingLibraryMustBeConfiguredError();
|
||||
// Enable for 8.3
|
||||
// return defaultProjectAnnotations.renderToCanvas(renderContext, canvasElement);
|
||||
}
|
||||
const {
|
||||
storyFn,
|
||||
storyContext: { testingLibraryRender: render },
|
||||
} = renderContext;
|
||||
const { unmount } = render(storyFn(), { container: canvasElement });
|
||||
return unmount;
|
||||
},
|
||||
};
|
||||
|
@ -2184,12 +2184,12 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@babel/runtime-corejs3@npm:^7.10.2":
|
||||
version: 7.23.1
|
||||
resolution: "@babel/runtime-corejs3@npm:7.23.1"
|
||||
version: 7.25.0
|
||||
resolution: "@babel/runtime-corejs3@npm:7.25.0"
|
||||
dependencies:
|
||||
core-js-pure: "npm:^3.30.2"
|
||||
regenerator-runtime: "npm:^0.14.0"
|
||||
checksum: 10c0/6e2c2b11779ff56c88b1f3a8742498640f7271ad4fcf9cfd24052bbb236a5e7c4c7c8d81cda751da3b4effa678736303deb78441c5752e63bfb90d6453fd870f
|
||||
checksum: 10c0/7c9e7896749b5968bc6a7638cf1735e5d2dc791780f4f46daf15a45777780cd0485d1357e92f54b03f815269064dc84d771e83486d49e18b847ffa8cfb6a6afa
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -2220,7 +2220,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.15, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.24.4, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
|
||||
"@babel/runtime@npm:^7.10.2":
|
||||
version: 7.25.0
|
||||
resolution: "@babel/runtime@npm:7.25.0"
|
||||
dependencies:
|
||||
regenerator-runtime: "npm:^0.14.0"
|
||||
checksum: 10c0/bd3faf246170826cef2071a94d7b47b49d532351360ecd17722d03f6713fd93a3eb3dbd9518faa778d5e8ccad7392a7a604e56bd37aaad3f3aa68d619ccd983d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.15, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.24.4, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
|
||||
version: 7.24.7
|
||||
resolution: "@babel/runtime@npm:7.24.7"
|
||||
dependencies:
|
||||
@ -7615,7 +7624,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1":
|
||||
"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0":
|
||||
version: 2.0.6
|
||||
resolution: "@types/istanbul-lib-coverage@npm:2.0.6"
|
||||
checksum: 10c0/3948088654f3eeb45363f1db158354fb013b362dba2a5c2c18c559484d5eb9f6fd85b23d66c0a7c2fcfab7308d0a585b14dadaca6cc8bf89ebfdc7f8f5102fb7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/istanbul-lib-coverage@npm:^2.0.1":
|
||||
version: 2.0.4
|
||||
resolution: "@types/istanbul-lib-coverage@npm:2.0.4"
|
||||
checksum: 10c0/af5f6b64e788331ed3f7b2e2613cb6ca659c58b8500be94bbda8c995ad3da9216c006f1cfe6f66b321c39392b1bda18b16e63cef090a77d24a00b4bd5ba3b018
|
||||
@ -7623,20 +7639,20 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@types/istanbul-lib-report@npm:*":
|
||||
version: 3.0.1
|
||||
resolution: "@types/istanbul-lib-report@npm:3.0.1"
|
||||
version: 3.0.3
|
||||
resolution: "@types/istanbul-lib-report@npm:3.0.3"
|
||||
dependencies:
|
||||
"@types/istanbul-lib-coverage": "npm:*"
|
||||
checksum: 10c0/a2a002ee7ecd9079a2c06235d28d1bc77089c3d834eec7e6dac38986203634936f2a017812624acfbedabec4bddd933942f14ac93eba2dc57f581ad4f35bbf1d
|
||||
checksum: 10c0/247e477bbc1a77248f3c6de5dadaae85ff86ac2d76c5fc6ab1776f54512a745ff2a5f791d22b942e3990ddbd40f3ef5289317c4fca5741bedfaa4f01df89051c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/istanbul-reports@npm:^3.0.0":
|
||||
version: 3.0.2
|
||||
resolution: "@types/istanbul-reports@npm:3.0.2"
|
||||
version: 3.0.4
|
||||
resolution: "@types/istanbul-reports@npm:3.0.4"
|
||||
dependencies:
|
||||
"@types/istanbul-lib-report": "npm:*"
|
||||
checksum: 10c0/df6c9e6865006be06bae29f63d5240b96bc7041b18a8c6d66be5b5d92ef5c95675c7a605a603029065f4f8aece7dba7360349e9d0543f512417e64a707a3c4fa
|
||||
checksum: 10c0/1647fd402aced5b6edac87274af14ebd6b3a85447ef9ad11853a70fd92a98d35f81a5d3ea9fcb5dbb5834e800c6e35b64475e33fcae6bfa9acc70d61497c54ee
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -8143,18 +8159,18 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@types/yargs-parser@npm:*":
|
||||
version: 21.0.1
|
||||
resolution: "@types/yargs-parser@npm:21.0.1"
|
||||
checksum: 10c0/f1d723a4c4383a9c53b975820b7490186ca127237ca58eb2ee8f5eacdcdb195a81aeabd1d75560abdf22fc29f70e8bb103d7ab34c5ec49bc19196195a7bf3189
|
||||
version: 21.0.3
|
||||
resolution: "@types/yargs-parser@npm:21.0.3"
|
||||
checksum: 10c0/e71c3bd9d0b73ca82e10bee2064c384ab70f61034bbfb78e74f5206283fc16a6d85267b606b5c22cb2a3338373586786fed595b2009825d6a9115afba36560a0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/yargs@npm:^15.0.0":
|
||||
version: 15.0.16
|
||||
resolution: "@types/yargs@npm:15.0.16"
|
||||
version: 15.0.19
|
||||
resolution: "@types/yargs@npm:15.0.19"
|
||||
dependencies:
|
||||
"@types/yargs-parser": "npm:*"
|
||||
checksum: 10c0/07f0960062e66226ae602fccd62e351143291d778e1f4dd645c51111e62fbedafe2a976c223dcfa7ae052e989407b62e97a7472fc1d73536110cd05502c204a5
|
||||
checksum: 10c0/9fe9b8645304a628006cbba2d1990fb015e2727274d0e3853f321a379a1242d1da2c15d2f56cff0d4313ae94f0383ccf834c3bded9fb3589608aefb3432fcf00
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 434 KiB After Width: | Height: | Size: 568 KiB |
@ -5,7 +5,7 @@ import * as stories from '../stories/Button.stories';
|
||||
|
||||
const { Primary } = composeStories(stories);
|
||||
test('Button snapshot', async () => {
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
expect(document.body.firstChild).toMatchSnapshot();
|
||||
});
|
||||
```
|
||||
@ -21,7 +21,7 @@ import * as stories from '../stories/Button.stories';
|
||||
|
||||
const { Primary } = composeStories(stories);
|
||||
test('Button snapshot', async () => {
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
expect(document.body.firstChild).toMatchSnapshot();
|
||||
});
|
||||
```
|
||||
@ -37,7 +37,7 @@ import * as stories from '../stories/Button.stories';
|
||||
|
||||
const { Primary } = composeStories(stories);
|
||||
test('Button snapshot', async () => {
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
expect(document.body.firstChild).toMatchSnapshot();
|
||||
});
|
||||
```
|
||||
@ -53,7 +53,7 @@ import * as stories from '../stories/Button.stories';
|
||||
|
||||
const { Primary } = composeStories(stories);
|
||||
test('Button snapshot', async () => {
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
expect(document.body.firstChild).toMatchSnapshot();
|
||||
});
|
||||
```
|
||||
|
@ -47,7 +47,7 @@ const { InvalidForm } = composeStories(stories);
|
||||
|
||||
test('Checks if the form is valid', async () => {
|
||||
// Renders the composed story
|
||||
await InvalidForm.play();
|
||||
await InvalidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -71,7 +71,7 @@ const { InvalidForm } = composeStories(stories);
|
||||
|
||||
test('Checks if the form is valid', async () => {
|
||||
// Renders the composed story
|
||||
await InvalidForm.play();
|
||||
await InvalidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -95,7 +95,7 @@ const { InvalidForm } = composeStories(stories);
|
||||
|
||||
it('Checks if the form is valid', async () => {
|
||||
// Renders the composed story
|
||||
await InvalidForm.play();
|
||||
await InvalidForm.run();
|
||||
|
||||
await fireEvent.click(screen.getByText('Submit'));
|
||||
|
||||
@ -115,7 +115,7 @@ const { InvalidForm } = composeStories(stories);
|
||||
|
||||
test('Checks if the form is valid', async () => {
|
||||
// Renders the composed story
|
||||
await InvalidForm.play();
|
||||
await InvalidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -139,7 +139,7 @@ const { InvalidForm } = composeStories(stories);
|
||||
|
||||
test('Checks if the form is valid', async () => {
|
||||
// Renders the composed story
|
||||
await InvalidForm.play();
|
||||
await InvalidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
|
@ -51,7 +51,7 @@ describe('Stories Snapshots', () => {
|
||||
|
||||
stories.forEach(({ name, story }) => {
|
||||
test(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
// Defines the custom snapshot path location and file name
|
||||
@ -131,7 +131,7 @@ describe("Stories Snapshots", () => {
|
||||
|
||||
stories.forEach(({ name, story }) => {
|
||||
test(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
// Defines the custom snapshot path location and file name
|
||||
@ -191,7 +191,7 @@ describe('Stories Snapshots', () => {
|
||||
|
||||
stories.forEach(({ name, story }) => {
|
||||
test(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
// Defines the custom snapshot path location and file name
|
||||
@ -262,7 +262,7 @@ describe('Stories Snapshots', () => {
|
||||
|
||||
stories.forEach(({ name, story }) => {
|
||||
test(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
// Defines the custom snapshot path location and file name
|
||||
|
@ -8,7 +8,7 @@ import * as FormStories from './LoginForm.stories';
|
||||
const { InvalidForm, ValidForm } = composeStories(FormStories);
|
||||
|
||||
test('Tests invalid form state', async () => {
|
||||
await InvalidForm.play();
|
||||
await InvalidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -21,7 +21,7 @@ test('Tests invalid form state', async () => {
|
||||
});
|
||||
|
||||
test('Tests filled form', async () => {
|
||||
await ValidForm.play();
|
||||
await ValidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -44,7 +44,7 @@ import * as FormStories from './LoginForm.stories';
|
||||
const { InvalidForm, ValidForm } = composeStories(FormStories);
|
||||
|
||||
test('Tests invalid form state', async () => {
|
||||
await InvalidForm.play();
|
||||
await InvalidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -57,7 +57,7 @@ test('Tests invalid form state', async () => {
|
||||
});
|
||||
|
||||
test('Tests filled form', async () => {
|
||||
await ValidForm.play();
|
||||
await ValidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -80,7 +80,7 @@ import * as FormStories from './LoginForm.stories';
|
||||
const { InvalidForm, ValidForm } = composeStories(FormStories);
|
||||
|
||||
test('Tests invalid form state', async () => {
|
||||
await InvalidForm.play();
|
||||
await InvalidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -93,7 +93,7 @@ test('Tests invalid form state', async () => {
|
||||
});
|
||||
|
||||
test('Tests filled form', async () => {
|
||||
await ValidForm.play();
|
||||
await ValidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -116,7 +116,7 @@ import * as FormStories from './LoginForm.stories';
|
||||
const { InvalidForm, ValidForm } = composeStories(FormStories);
|
||||
|
||||
test('Tests invalid form state', async () => {
|
||||
await InvalidForm.play();
|
||||
await InvalidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -129,7 +129,7 @@ test('Tests invalid form state', async () => {
|
||||
});
|
||||
|
||||
test('Tests filled form', async () => {
|
||||
await ValidForm.play();
|
||||
await ValidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
|
@ -11,7 +11,7 @@ test('onclick handler is called', () => {
|
||||
const Primary = composeStory(PrimaryStory, meta);
|
||||
|
||||
const onClickSpy = jest.fn();
|
||||
await Primary.play({ args: { ...Primary.args, onClick: onClickSpy } });
|
||||
await Primary.run({ args: { ...Primary.args, onClick: onClickSpy } });
|
||||
|
||||
const buttonElement = screen.getByRole('button');
|
||||
buttonElement.click();
|
||||
@ -31,7 +31,7 @@ test('onclick handler is called', () => {
|
||||
const Primary = composeStory(PrimaryStory, meta);
|
||||
|
||||
const onClickSpy = jest.fn();
|
||||
await Primary.play({ args: { ...Primary.args, onClick: onClickSpy } });
|
||||
await Primary.run({ args: { ...Primary.args, onClick: onClickSpy } });
|
||||
|
||||
const buttonElement = screen.getByRole('button');
|
||||
buttonElement.click();
|
||||
|
@ -13,7 +13,7 @@ describe(options.suite, () => {
|
||||
stories.forEach(({ name, story }) => {
|
||||
// ...Previously existing code
|
||||
testFn(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
|
||||
|
@ -12,13 +12,13 @@ test('renders in English', async () => {
|
||||
{ globals: { locale: 'en' } } // 👈 Project annotations to override the locale
|
||||
);
|
||||
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
|
||||
test('renders in Spanish', async () => {
|
||||
const Primary = composeStory(PrimaryStory, meta, { globals: { locale: 'es' } });
|
||||
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
```
|
||||
|
||||
@ -36,12 +36,12 @@ test('renders in English', async () => {
|
||||
{ globals: { locale: 'en' } } // 👈 Project annotations to override the locale
|
||||
);
|
||||
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
|
||||
test('renders in Spanish', async () => {
|
||||
const Primary = composeStory(PrimaryStory, meta, { globals: { locale: 'es' } });
|
||||
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
```
|
||||
|
@ -67,7 +67,7 @@ describe(options.suite, () => {
|
||||
const testFn = story.parameters.storyshots?.skip ? test.skip : test;
|
||||
|
||||
testFn(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
expect(document.body.firstChild).toMatchSnapshot();
|
||||
@ -155,7 +155,7 @@ describe(options.suite, () => {
|
||||
const testFn = story.parameters.storyshots?.skip ? test.skip : test;
|
||||
|
||||
testFn(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
expect(document.body.firstChild).toMatchSnapshot();
|
||||
|
@ -9,7 +9,7 @@ const { Primary } = composeStories(stories);
|
||||
|
||||
test('renders and executes the play function', async () => {
|
||||
// Mount story and run interactions
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
```
|
||||
|
||||
@ -23,6 +23,6 @@ const { Primary } = composeStories(stories);
|
||||
|
||||
test('renders and executes the play function', async () => {
|
||||
// Mount story and run interactions
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
```
|
||||
|
@ -11,14 +11,14 @@ import * as stories from './Button.stories';
|
||||
const { Primary, Secondary } = composeStories(stories);
|
||||
|
||||
test('renders primary button with default args', async () => {
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
const buttonElement = screen.getByText('Text coming from args in stories file!');
|
||||
expect(buttonElement).not.toBeNull();
|
||||
});
|
||||
|
||||
test('renders primary button with overridden props', async () => {
|
||||
// You can override props by passing them in the context argument of the play function
|
||||
await Primary.play({ args: { ...Primary.args, children: 'Hello world' } });
|
||||
await Primary.run({ args: { ...Primary.args, children: 'Hello world' } });
|
||||
const buttonElement = screen.getByText(/Hello world/i);
|
||||
expect(buttonElement).not.toBeNull();
|
||||
});
|
||||
@ -37,14 +37,14 @@ import * as stories from './Button.stories';
|
||||
const { Primary, Secondary } = composeStories(stories);
|
||||
|
||||
test('renders primary button with default args', async () => {
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
const buttonElement = screen.getByText('Text coming from args in stories file!');
|
||||
expect(buttonElement).not.toBeNull();
|
||||
});
|
||||
|
||||
test('renders primary button with overridden props', async () => {
|
||||
// You can override props by passing them in the context argument of the play function
|
||||
await Primary.play({ args: { ...Primary.args, children: 'Hello world' } });
|
||||
await Primary.run({ args: { ...Primary.args, children: 'Hello world' } });
|
||||
const buttonElement = screen.getByText(/Hello world/i);
|
||||
expect(buttonElement).not.toBeNull();
|
||||
});
|
||||
@ -63,14 +63,14 @@ import * as stories from './Button.stories';
|
||||
const { Primary, Secondary } = composeStories(stories);
|
||||
|
||||
test('renders primary button with default args', async () => {
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
const buttonElement = screen.getByText('Text coming from args in stories file!');
|
||||
expect(buttonElement).not.toBeNull();
|
||||
});
|
||||
|
||||
test('renders primary button with overridden props', async () => {
|
||||
// You can override props by passing them in the context argument of the play function
|
||||
await Primary.play({ args: { ...Primary.args, children: 'Hello world' } });
|
||||
await Primary.run({ args: { ...Primary.args, children: 'Hello world' } });
|
||||
const buttonElement = screen.getByText(/Hello world/i);
|
||||
expect(buttonElement).not.toBeNull();
|
||||
});
|
||||
|
@ -9,14 +9,14 @@ import meta, { Primary as PrimaryStory } from './Button.stories';
|
||||
const Primary = composeStory(PrimaryStory, meta);
|
||||
|
||||
test('renders primary button with default args', async () => {
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
|
||||
const buttonElement = screen.getByText('Text coming from args in stories file!');
|
||||
expect(buttonElement).not.toBeNull();
|
||||
});
|
||||
|
||||
test('renders primary button with overridden props', async () => {
|
||||
await Primary.play({ args: { ...Primary.args, label: 'Hello world' } });
|
||||
await Primary.run({ args: { ...Primary.args, label: 'Hello world' } });
|
||||
|
||||
const buttonElement = screen.getByText(/Hello world/i);
|
||||
expect(buttonElement).not.toBeNull();
|
||||
@ -34,14 +34,14 @@ import meta, { Primary as PrimaryStory } from './Button.stories';
|
||||
const Primary = composeStory(PrimaryStory, meta);
|
||||
|
||||
test('renders primary button with default args', async () => {
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
|
||||
const buttonElement = screen.getByText('Text coming from args in stories file!');
|
||||
expect(buttonElement).not.toBeNull();
|
||||
});
|
||||
|
||||
test('renders primary button with overridden props', async () => {
|
||||
await Primary.play({ args: { ...Primary.args, label: 'Hello world' } });
|
||||
await Primary.run({ args: { ...Primary.args, label: 'Hello world' } });
|
||||
|
||||
const buttonElement = screen.getByText(/Hello world/i);
|
||||
expect(buttonElement).not.toBeNull();
|
||||
@ -59,14 +59,14 @@ import meta, { Primary as PrimaryStory } from './Button.stories';
|
||||
const Primary = composeStory(PrimaryStory, meta);
|
||||
|
||||
test('renders primary button with default args', async () => {
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
|
||||
const buttonElement = screen.getByText('Text coming from args in stories file!');
|
||||
expect(buttonElement).not.toBeNull();
|
||||
});
|
||||
|
||||
test('renders primary button with overridden props', async () => {
|
||||
await Primary.play({ args: { ...Primary.args, label: 'Hello world' } });
|
||||
await Primary.run({ args: { ...Primary.args, label: 'Hello world' } });
|
||||
|
||||
const buttonElement = screen.getByText(/Hello world/i);
|
||||
expect(buttonElement).not.toBeNull();
|
||||
|
@ -10,7 +10,7 @@ describe(options.suite, () => {
|
||||
stories.forEach(({ name, story }) => {
|
||||
// ...Previously existing code
|
||||
testFn(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
|
||||
|
@ -12,13 +12,13 @@ test('renders in English', async () => {
|
||||
{ globals: { locale: 'en' } } // 👈 Project annotations to override the locale
|
||||
);
|
||||
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
|
||||
test('renders in Spanish', async () => {
|
||||
const Primary = composeStory(PrimaryStory, meta, { globals: { locale: 'es' } });
|
||||
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
```
|
||||
|
||||
@ -36,13 +36,13 @@ test('renders in English', async () => {
|
||||
{ globals: { locale: 'en' } } // 👈 Project annotations to override the locale
|
||||
);
|
||||
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
|
||||
test('renders in Spanish', async () => {
|
||||
const Primary = composeStory(PrimaryStory, meta, { globals: { locale: 'es' } });
|
||||
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
```
|
||||
|
||||
@ -60,12 +60,12 @@ test('renders in English', async () => {
|
||||
{ globals: { locale: 'en' } } // 👈 Project annotations to override the locale
|
||||
);
|
||||
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
|
||||
test('renders in Spanish', async () => {
|
||||
const Primary = composeStory(PrimaryStory, meta, { globals: { locale: 'es' } });
|
||||
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
```
|
||||
|
@ -69,7 +69,7 @@ describe(options.suite, () => {
|
||||
const testFn = story.parameters.storyshots?.skip ? test.skip : test;
|
||||
|
||||
testFn(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
|
||||
@ -160,7 +160,7 @@ describe(options.suite, () => {
|
||||
const testFn = story.parameters.storyshots?.skip ? test.skip : test;
|
||||
|
||||
testFn(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
|
||||
|
@ -8,7 +8,7 @@ const { Primary } = composeStories(stories);
|
||||
|
||||
test('renders and executes the play function', async () => {
|
||||
// Mount story and run interactions
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
```
|
||||
|
||||
@ -22,7 +22,7 @@ const { Primary } = composeStories(stories);
|
||||
|
||||
test('renders and executes the play function', async () => {
|
||||
// Mount story and run interactions
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
```
|
||||
|
||||
@ -36,6 +36,6 @@ const { Primary } = composeStories(stories);
|
||||
|
||||
test('renders and executes the play function', async () => {
|
||||
// Mount story and run interactions
|
||||
await Primary.play();
|
||||
await Primary.run();
|
||||
});
|
||||
```
|
||||
|
@ -8,7 +8,7 @@ import Meta, { ValidForm as ValidFormStory } from './LoginForm.stories';
|
||||
const ValidForm = composeStory(ValidFormStory, Meta);
|
||||
|
||||
test('Validates form', async () => {
|
||||
await ValidForm.play();
|
||||
await ValidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -31,7 +31,7 @@ import Meta, { ValidForm as ValidFormStory } from './LoginForm.stories';
|
||||
const ValidForm = composeStory(ValidFormStory, Meta);
|
||||
|
||||
test('Validates form', async () => {
|
||||
await ValidForm.play();
|
||||
await ValidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -54,7 +54,7 @@ import Meta, { ValidForm as ValidFormStory } from './LoginForm.stories';
|
||||
const ValidForm = composeStory(ValidFormStory, Meta);
|
||||
|
||||
test('Validates form', async () => {
|
||||
await ValidForm.play();
|
||||
await ValidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
@ -77,7 +77,7 @@ import Meta, { ValidForm as ValidFormStory } from './LoginForm.stories';
|
||||
const ValidForm = composeStory(ValidFormStory, Meta);
|
||||
|
||||
test('Validates form', async () => {
|
||||
await ValidForm.play();
|
||||
await ValidForm.run();
|
||||
|
||||
const buttonElement = screen.getByRole('button', {
|
||||
name: 'Submit',
|
||||
|
@ -117,7 +117,7 @@ describe('Stories Snapshots', () => {
|
||||
|
||||
stories.forEach(({ name, story }) => {
|
||||
test(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
expect(document.body.firstChild).toMatchSnapshot();
|
||||
@ -176,7 +176,7 @@ describe('Stories Snapshots', () => {
|
||||
|
||||
stories.forEach(({ name, story }) => {
|
||||
test(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
expect(document.body.firstChild).toMatchSnapshot();
|
||||
@ -245,7 +245,7 @@ describe('Stories Snapshots', () => {
|
||||
|
||||
stories.forEach(({ name, story }) => {
|
||||
test(name, async () => {
|
||||
await story.play();
|
||||
await story.run();
|
||||
// Ensures a consistent snapshot by waiting for the component to render by adding a delay of 1 ms before taking the snapshot.
|
||||
await new Promise((resolve) => setTimeout(resolve, 1));
|
||||
expect(document.body.firstChild).toMatchSnapshot();
|
||||
|
@ -83,13 +83,14 @@ sidebar:
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------- | ----------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||
| storyName | `string` | The story's name |
|
||||
| args | `Record<string, any>` | The story's [args](../../writing-stories/args.mdx) |
|
||||
| argTypes | `ArgType` | The story's [argTypes](../arg-types.mdx) |
|
||||
| id | `string` | The story's id |
|
||||
| tags | `string[]` | The story's [tags](../../writing-stories/tags.mdx) |
|
||||
| parameters | `Record<string, any>` | The story's [parameters](../parameters.mdx) |
|
||||
| play | `(context) => Promise<void> \| undefined` | Mounts and executes the [play function](#3-play) of a given story |
|
||||
| play | `(context) => Promise<void> \| undefined` | Executes the play function of a given story |
|
||||
| run | `(context) => Promise<void> \| undefined` | [Mounts and executes the play function](#3-run) of a given story |
|
||||
| storyName | `string` | The story's name |
|
||||
| tags | `string[]` | The story's [tags](../../writing-stories/tags.mdx) |
|
||||
|
||||
## composeStory
|
||||
|
||||
@ -202,7 +203,7 @@ sidebar:
|
||||
|
||||
To preview your stories in Storybook, Storybook runs a story pipeline, which includes applying project annotations, loading data, rendering the story, and playing interactions. This is a simplified version of the pipeline:
|
||||
|
||||

|
||||

|
||||
|
||||
When you want to reuse a story in a different environment, however, it's crucial to understand that all these steps make a story. The portable stories API provides you with the mechanism to recreate that story pipeline in your external environment:
|
||||
|
||||
@ -216,11 +217,11 @@ sidebar:
|
||||
|
||||
The story is prepared by running [`composeStories`](#composestories) or [`composeStory`](#composestory). The outcome is a renderable component that represents the render function of the story.
|
||||
|
||||
### 3. Play
|
||||
### 3. Run
|
||||
|
||||
Finally, stories can prepare data they need (e.g. setting up some mocks or fetching data) before rendering by defining [loaders](../../writing-stories/loaders.mdx), [beforeEach](../../writing-tests/interaction-testing.mdx#run-code-before-each-story) or by having all the story code in the play function when using the [mount](../../writing-tests/interaction-testing.mdx#run-code-before-the-component-gets-rendered). In portable stories, all of these steps will be executed when you run the `play` method of the composed story.
|
||||
Finally, stories can prepare data they need (e.g. setting up some mocks or fetching data) before rendering by defining [loaders](../../writing-stories/loaders.mdx), [beforeEach](../../writing-tests/interaction-testing.mdx#run-code-before-each-story) or by having all the story code in the play function when using the [mount](../../writing-tests/interaction-testing.mdx#run-code-before-the-component-gets-rendered). In portable stories, all of these steps will be executed when you call the `run` method of the composed story.
|
||||
|
||||
👉 For this, you use the [`composeStories`](#composestories) or [`composeStory`](#composestory) API. The composed story will return a `play` method to be called.
|
||||
👉 For this, you use the [`composeStories`](#composestories) or [`composeStory`](#composestory) API. The composed story will return a `run` method to be called.
|
||||
|
||||
{/* prettier-ignore-start */}
|
||||
|
||||
|
@ -116,7 +116,7 @@ sidebar:
|
||||
## setProjectAnnotations
|
||||
|
||||
This API should be called once, before the tests run, in [`playwright/index.ts`](https://playwright.dev/docs/test-components#step-1-install-playwright-test-for-components-for-your-respective-framework). This will make sure that when `mount` is called, the project annotations are taken into account as well.
|
||||
|
||||
|
||||
These are the configurations needed in the setup file:
|
||||
- preview annotations: those defined in `.storybook/preview.ts`
|
||||
- addon annotations (optional): those exported by addons
|
||||
|
@ -89,13 +89,14 @@ sidebar:
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------- | ----------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||
| storyName | `string` | The story's name |
|
||||
| args | `Record<string, any>` | The story's [args](../../writing-stories/args.mdx) |
|
||||
| argTypes | `ArgType` | The story's [argTypes](../arg-types.mdx) |
|
||||
| id | `string` | The story's id |
|
||||
| tags | `string[]` | The story's [tags](../../writing-stories/tags.mdx) |
|
||||
| parameters | `Record<string, any>` | The story's [parameters](../parameters.mdx) |
|
||||
| play | `(context) => Promise<void> \| undefined` | Mounts and executes the [play function](#3-play) of a given story |
|
||||
| play | `(context) => Promise<void> \| undefined` | Executes the play function of a given story |
|
||||
| run | `(context) => Promise<void> \| undefined` | [Mounts and executes the play function](#3-run) of a given story |
|
||||
| storyName | `string` | The story's name |
|
||||
| tags | `string[]` | The story's [tags](../../writing-stories/tags.mdx) |
|
||||
|
||||
## composeStory
|
||||
|
||||
@ -216,7 +217,7 @@ sidebar:
|
||||
|
||||
To preview your stories in Storybook, Storybook runs a story pipeline, which includes applying project annotations, loading data, rendering the story, and playing interactions. This is a simplified version of the pipeline:
|
||||
|
||||

|
||||

|
||||
|
||||
When you want to reuse a story in a different environment, however, it's crucial to understand that all these steps make a story. The portable stories API provides you with the mechanism to recreate that story pipeline in your external environment:
|
||||
|
||||
@ -230,11 +231,11 @@ sidebar:
|
||||
|
||||
The story is prepared by running [`composeStories`](#composestories) or [`composeStory`](#composestory). The outcome is a renderable component that represents the render function of the story.
|
||||
|
||||
### 3. Play
|
||||
### 3. Run
|
||||
|
||||
Finally, stories can prepare data they need (e.g. setting up some mocks or fetching data) before rendering by defining [loaders](../../writing-stories/loaders.mdx), [beforeEach](../../writing-tests/interaction-testing.mdx#run-code-before-each-story) or by having all the story code in the play function when using the [mount](../../writing-tests/interaction-testing.mdx#run-code-before-the-component-gets-rendered). In portable stories, all of these steps will be executed when you run the `play` method of the composed story.
|
||||
Finally, stories can prepare data they need (e.g. setting up some mocks or fetching data) before rendering by defining [loaders](../../writing-stories/loaders.mdx), [beforeEach](../../writing-tests/interaction-testing.mdx#run-code-before-each-story) or by having all the story code in the play function when using the [mount](../../writing-tests/interaction-testing.mdx#run-code-before-the-component-gets-rendered). In portable stories, all of these steps will be executed when you call the `run` method of the composed story.
|
||||
|
||||
👉 For this, you use the [`composeStories`](#composestories) or [`composeStory`](#composestory) API. The composed story will return a `play` method to be called.
|
||||
👉 For this, you use the [`composeStories`](#composestories) or [`composeStory`](#composestory) API. The composed story will return a `run` method to be called.
|
||||
|
||||
{/* prettier-ignore-start */}
|
||||
|
||||
|
@ -20,7 +20,7 @@ const runTests = (name: string, storiesModule: any) => {
|
||||
const composedStories = composeStories(storiesModule);
|
||||
Object.entries(composedStories).forEach(([name, Story]: [any, any]) => {
|
||||
it(`renders ${name}`, async () => {
|
||||
await Story.play?.();
|
||||
await Story.run?.();
|
||||
expect(document.body).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -92,7 +92,7 @@ describe('CSF3', () => {
|
||||
it('renders with play function', async () => {
|
||||
const CSF3InputFieldFilled = composeStory(stories.CSF3InputFieldFilled, stories.default);
|
||||
|
||||
await CSF3InputFieldFilled.play();
|
||||
await CSF3InputFieldFilled.run();
|
||||
|
||||
const input = screen.getByTestId('input') as HTMLInputElement;
|
||||
expect(input.value).toEqual('Hello world!');
|
||||
@ -117,6 +117,6 @@ it('should pass with decorators that need addons channel', () => {
|
||||
// Batch snapshot testing
|
||||
const testCases = Object.values(composeStories(stories)).map((Story) => [Story.storyName, Story]);
|
||||
it.each(testCases)('Renders %s story', async (_storyName, Story) => {
|
||||
await Story.play();
|
||||
await Story.run();
|
||||
expect(document.body).toMatchSnapshot();
|
||||
});
|
||||
|
@ -55,7 +55,7 @@ describe('renders', () => {
|
||||
expect(getByTestId('spy-data').textContent).toEqual('mockFn return value');
|
||||
expect(getByTestId('loaded-data').textContent).toEqual('loaded data');
|
||||
// spy assertions happen in the play function and should work
|
||||
await LoaderStory.play!();
|
||||
await LoaderStory.run!();
|
||||
});
|
||||
});
|
||||
|
||||
@ -114,7 +114,7 @@ describe('CSF3', () => {
|
||||
it('renders with play function without canvas element', async () => {
|
||||
const CSF3InputFieldFilled = composeStory(stories.CSF3InputFieldFilled, stories.default);
|
||||
|
||||
await CSF3InputFieldFilled.play();
|
||||
await CSF3InputFieldFilled.run();
|
||||
|
||||
const input = screen.getByTestId('input') as HTMLInputElement;
|
||||
expect(input.value).toEqual('Hello world!');
|
||||
@ -126,7 +126,7 @@ describe('CSF3', () => {
|
||||
const div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
|
||||
await CSF3InputFieldFilled.play({ canvasElement: div });
|
||||
await CSF3InputFieldFilled.run({ canvasElement: div });
|
||||
|
||||
const input = screen.getByTestId('input') as HTMLInputElement;
|
||||
expect(input.value).toEqual('Hello world!');
|
||||
@ -141,6 +141,6 @@ const testCases = Object.values(composeStories(stories)).map(
|
||||
);
|
||||
it.each(testCases)('Renders %s story', async (_storyName, Story) => {
|
||||
if (_storyName === 'CSF2StoryWithLocale') return;
|
||||
await Story.play();
|
||||
await Story.run();
|
||||
expect(document.body).toMatchSnapshot();
|
||||
});
|
||||
|
@ -2,22 +2,44 @@
|
||||
|
||||
exports[`Renders CSF2Secondary story 1`] = `
|
||||
<body>
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
label coming from story args!
|
||||
|
||||
</button>
|
||||
<div>
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
label coming from story args!
|
||||
|
||||
</button>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders CSF2StoryWithParamsAndDecorator story 1`] = `
|
||||
<body>
|
||||
<div
|
||||
style="margin: 3em;"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
style="margin: 3em;"
|
||||
>
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
foo
|
||||
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders CSF3Button story 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
@ -26,91 +48,46 @@ exports[`Renders CSF2StoryWithParamsAndDecorator story 1`] = `
|
||||
foo
|
||||
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders CSF3Button story 1`] = `
|
||||
<body>
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
foo
|
||||
|
||||
</button>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders CSF3ButtonWithRender story 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<p
|
||||
data-testid="custom-render"
|
||||
>
|
||||
I am a custom render function
|
||||
</p>
|
||||
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
foo
|
||||
<div>
|
||||
<p
|
||||
data-testid="custom-render"
|
||||
>
|
||||
I am a custom render function
|
||||
</p>
|
||||
|
||||
</button>
|
||||
<button
|
||||
class="storybook-button storybook-button--medium storybook-button--secondary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
foo
|
||||
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders CSF3InputFieldFilled story 1`] = `
|
||||
<body>
|
||||
<input
|
||||
data-testid="input"
|
||||
/>
|
||||
<div>
|
||||
<input
|
||||
data-testid="input"
|
||||
/>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders CSF3Primary story 1`] = `
|
||||
<body>
|
||||
<button
|
||||
class="storybook-button storybook-button--large storybook-button--primary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
foo
|
||||
|
||||
</button>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders LoaderStory story 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
data-testid="loaded-data"
|
||||
>
|
||||
loaded data
|
||||
</div>
|
||||
|
||||
<div
|
||||
data-testid="spy-data"
|
||||
>
|
||||
mockFn return value
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders NewStory story 1`] = `
|
||||
<body>
|
||||
<div
|
||||
style="margin: 3em;"
|
||||
>
|
||||
<button
|
||||
class="storybook-button storybook-button--large storybook-button--primary"
|
||||
style=""
|
||||
@ -119,9 +96,48 @@ exports[`Renders NewStory story 1`] = `
|
||||
foo
|
||||
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders LoaderStory story 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
data-testid="loaded-data"
|
||||
>
|
||||
loaded data
|
||||
</div>
|
||||
|
||||
<div
|
||||
data-testid="spy-data"
|
||||
>
|
||||
mockFn return value
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
exports[`Renders NewStory story 1`] = `
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
style="margin: 3em;"
|
||||
>
|
||||
<button
|
||||
class="storybook-button storybook-button--large storybook-button--primary"
|
||||
style=""
|
||||
type="button"
|
||||
>
|
||||
foo
|
||||
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</body>
|
||||
`;
|
||||
|
Loading…
x
Reference in New Issue
Block a user