diff --git a/docs/api/csf.md b/docs/api/csf.md index d4a94c527477..722af2d73c59 100644 --- a/docs/api/csf.md +++ b/docs/api/csf.md @@ -145,7 +145,9 @@ A good use case for the `play` function is a form component. With previous Story 'react/login-form-with-play-function.ts.mdx', 'angular/login-form-with-play-function.ts.mdx', 'vue/login-form-with-play-function.2.js.mdx', + 'vue/login-form-with-play-function.ts-2.ts.mdx', 'vue/login-form-with-play-function.3.js.mdx', + 'vue/login-form-with-play-function.ts-3.ts.mdx', 'svelte/login-form-with-play-function.js.mdx', ]} /> diff --git a/docs/essentials/interactions.md b/docs/essentials/interactions.md index a5b47696596a..8ac1f79421c6 100644 --- a/docs/essentials/interactions.md +++ b/docs/essentials/interactions.md @@ -62,6 +62,8 @@ Make sure to import the Storybook wrappers for Jest and Testing Library rather t @@ -71,4 +73,4 @@ The above example uses the `canvasElement` to scope your element queries to the While you can refer to the [Testing Library documentation](https://testing-library.com/docs/) for details on how to use it, there's an important detail that's different when using the Storybook wrapper: **method invocations must be `await`-ed**. It allows you to step back and forth through your interactions using the debugger. -Any `args` that have been marked as an Action, either using the [argTypes annotation](./actions.md#action-argtype-annotation) or the [argTypesRegex](./actions.md#automatically-matching-args), will be automatically converted to a [Jest mock function](https://jestjs.io/docs/mock-function-api) (spy). This allows you to make assertions about calls to these functions. +Any `args` that have been marked as an Action, either using the [argTypes annotation](./actions.md#action-argtype-annotation) or the [argTypesRegex](./actions.md#automatically-matching-args), will be automatically converted to a [Jest mock function](https://jestjs.io/docs/mock-function-api) (spy). This allows you to make assertions about calls to these functions. \ No newline at end of file diff --git a/docs/snippets/angular/login-form-with-play-function.mdx.mdx b/docs/snippets/angular/login-form-with-play-function.mdx.mdx index ed6ef23d9f3e..e20408f0c10e 100644 --- a/docs/snippets/angular/login-form-with-play-function.mdx.mdx +++ b/docs/snippets/angular/login-form-with-play-function.mdx.mdx @@ -11,21 +11,19 @@ import { LoginForm } from './LoginForm.component'; - +export const Template = (args) => ({ props: args }); - ({ - props: args, - })} /> + + {Template.bind({})} + + { + play={async ({ canvasElement }) => { // Starts querying the component from its root element const canvas = within(canvasElement); @@ -34,7 +32,7 @@ import { LoginForm } from './LoginForm.component'; await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); - // See https://storybook.js.org/docs/7.0/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + // See https://storybook.js.org/docs/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel await userEvent.click(canvas.getByRole('button')); // πŸ‘‡ Assert DOM structure @@ -43,9 +41,8 @@ import { LoginForm } from './LoginForm.component'; 'Everything is perfect. Your account is ready and we should probably get you started!' ) ).toBeInTheDocument(); - }} - render={(args) => ({ - props: args, - })} /> + }}> + {Template.bind({})} + -``` +``` \ No newline at end of file diff --git a/docs/snippets/angular/login-form-with-play-function.ts.mdx b/docs/snippets/angular/login-form-with-play-function.ts.mdx index d668cef903e6..fca0eb0b47f9 100644 --- a/docs/snippets/angular/login-form-with-play-function.ts.mdx +++ b/docs/snippets/angular/login-form-with-play-function.ts.mdx @@ -1,7 +1,7 @@ ```ts -// LoginForm.stories.ts +/// LoginForm.stories.ts -import type { Meta, Story } from '@storybook/angular'; +import { Meta, Story } from '@storybook/angular'; import { userEvent, within } from '@storybook/testing-library'; @@ -11,34 +11,40 @@ import { LoginForm } from './LoginForm.component'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/angular/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/angular/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'Form', component: LoginForm, } as Meta; -export const EmptyForm: Story = {}; +const Template: Story = (args) => ({ + props: args, +}); -export const FilledForm: Story = { - play: async ({ canvasElement }) => { - // Starts querying the component from its root element - const canvas = within(canvasElement); +export const EmptyForm = Template.bind({}); - // πŸ‘‡ Simulate interactions with the component - await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); +/* +* See https://storybook.js.org/docs/angular/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); - await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); + // πŸ‘‡ Simulate interactions with the component + await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(canvas.getByRole('button')); + await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); - // πŸ‘‡ Assert DOM structure - await expect( - canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!' - ) - ).toBeInTheDocument(); - }, + // See https://storybook.js.org/docs/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + + // πŸ‘‡ Assert DOM structure + await expect( + canvas.getByText( + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) + ).toBeInTheDocument(); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-alt-queries.mdx.mdx b/docs/snippets/angular/my-component-play-function-alt-queries.mdx.mdx index 0e7fd887e118..ccb5a12f7d35 100644 --- a/docs/snippets/angular/my-component-play-function-alt-queries.mdx.mdx +++ b/docs/snippets/angular/my-component-play-function-alt-queries.mdx.mdx @@ -1,27 +1,28 @@ ```md -import { Meta, Story }Β from '@storybook/addon-docs'; +import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; - +export const Template = (args) => ({ props: args }); + { - // See https://storybook.js.org/docs/7.0/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button', { name: / button label/i })); - }} - render={(args) => ({ - props: args, - })} /> + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-alt-queries.ts.mdx b/docs/snippets/angular/my-component-play-function-alt-queries.ts.mdx index 36f5458a3e27..e0e5e31252a1 100644 --- a/docs/snippets/angular/my-component-play-function-alt-queries.ts.mdx +++ b/docs/snippets/angular/my-component-play-function-alt-queries.ts.mdx @@ -1,25 +1,35 @@ ```ts // MyComponent.stories.ts -import type { Meta, Story } from '@storybook/angular'; +import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/angular/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/angular/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'QueryMethods', component: MyComponent, + } as Meta; -export const ExampleWithRole: Story = { - play: async () => { - // See https://storybook.js.org/docs/7.0/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button', { name: / button label/i })); - }, +const Template: Story = (args) => ({ + props: args, +}); + +/* +* See https://storybook.js.org/docs/angular/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleWithRole = Template.bind({}); +ExampleWithRole.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); }; ``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-composition.ts.mdx b/docs/snippets/angular/my-component-play-function-composition.ts.mdx index 4c357654ce3d..d59cc48f6f9c 100644 --- a/docs/snippets/angular/my-component-play-function-composition.ts.mdx +++ b/docs/snippets/angular/my-component-play-function-composition.ts.mdx @@ -1,39 +1,48 @@ ```ts // MyComponent.stories.ts -import type { Meta, Story } from '@storybook/angular'; +import { Meta, Story } from '@storybook/angular'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/angular/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/angular/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'MyComponent', - component: MyComponent, + component: MyComponent, } as Meta; -export const FirstStory: Story = { - play: async () => { - userEvent.type(screen.getByTestId('an-element'), 'example-value'); - }, +const Template: Story = (args) => ({ + props: args, +}); + +/* +* See https://storybook.js.org/docs/angular/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FirstStory = Template.bind({}); +FirstStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + userEvent.type(canvas.getByTestId('an-element'), 'example-value'); }; -export const SecondStory: Story = { - play: async () => { - await userEvent.type(screen.getByTestId('other-element'), 'another value'); - }, +export const SecondStory = Template.bind({}); +SecondStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + await userEvent.type(canvas.getByTestId('other-element'), 'another value'); }; -export const CombinedStories: Story = { - play: async () => { - // Runs the FirstStory and Second story play function before running this story's play function - await FirstStory.play(); - await SecondStory.play(); - await userEvent.type(screen.getByTestId('another-element'), 'random value'); - }, +export const CombinedStories = Template.bind({}); +CombinedStories.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Runs the FirstStory and Second story play function before running this story's play function + await FirstStory.play({ canvasElement }); + await SecondStory.play({ canvasElement }); + await userEvent.type(canvas.getByTestId('another-element'), 'random value'); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-query-findby.mdx.mdx b/docs/snippets/angular/my-component-play-function-query-findby.mdx.mdx index cef66ae17b66..26c095f76130 100644 --- a/docs/snippets/angular/my-component-play-function-query-findby.mdx.mdx +++ b/docs/snippets/angular/my-component-play-function-query-findby.mdx.mdx @@ -3,27 +3,27 @@ import { Meta, Story }Β from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; - +export const Template = (args) => ({ props: args }); + { + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); // Other steps // Waits for the component to be rendered before querying the element - await screen.findByRole('button', { name: / button label/i })); - }} - render={(args) => ({ - props: args, - })} /> + await canvas.findByRole('button', { name: / button label/i })); + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-query-findby.ts.mdx b/docs/snippets/angular/my-component-play-function-query-findby.ts.mdx index ba9229b5c11e..f44db8b183e5 100644 --- a/docs/snippets/angular/my-component-play-function-query-findby.ts.mdx +++ b/docs/snippets/angular/my-component-play-function-query-findby.ts.mdx @@ -3,7 +3,7 @@ import type { Meta, Story } from '@storybook/angular'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; @@ -16,12 +16,21 @@ export default { component: MyComponent, } as Meta; -export const AsyncExample: Story = { - play: async () => { - // Other steps +const Template: Story = (args) => ({ + props: args, +}); - // Waits for the component to be rendered before querying the element - await screen.findByRole('button', { name: / button label/i })); - }, +/* +* See https://storybook.js.org/docs/angular/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const AsyncExample = Template.bind({}); +AsyncExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Other steps + + // Waits for the component to be rendered before querying the element + await canvas.findByRole('button', { name: / button label/i })); }; ``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-waitfor.mdx.mdx b/docs/snippets/angular/my-component-play-function-waitfor.mdx.mdx index 00cbd59e61c8..e479f6911b32 100644 --- a/docs/snippets/angular/my-component-play-function-waitfor.mdx.mdx +++ b/docs/snippets/angular/my-component-play-function-waitfor.mdx.mdx @@ -3,22 +3,24 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent, waitFor } from '@storybook/testing-library'; +import { userEvent, waitFor, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; - +export const Template = (args) => ({ props: args }); + { - const Input = screen.getByLabelText('Username', { + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { selector: 'input', }); @@ -26,16 +28,15 @@ import { MyComponent } from './MyComponent.component'; delay: 100, }); - // See https://storybook.js.org/docs/7.0/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - - const Submit = screen.getByRole('button'); + // See https://storybook.js.org/docs/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + + const Submit = canvas.getByRole('button'); await userEvent.click(Submit); await waitFor(async () => { - await userEvent.hover(screen.getByTestId('error')); + await userEvent.hover(canvas.getByTestId('error')); }); - }} - render={(args) => ({ - props: args, - })} /> + }} > + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-waitfor.ts.mdx b/docs/snippets/angular/my-component-play-function-waitfor.ts.mdx index 9d6753110c5e..09548280af32 100644 --- a/docs/snippets/angular/my-component-play-function-waitfor.ts.mdx +++ b/docs/snippets/angular/my-component-play-function-waitfor.ts.mdx @@ -1,38 +1,48 @@ ```ts // MyComponent.stories.ts -import type { Meta, Story } from '@storybook/angular'; +import { Meta, Story } from '@storybook/angular'; -import { screen, userEvent, waitFor } from '@storybook/testing-library'; +import { userEvent, waitFor, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/angular/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/angular/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithAsync', component: MyComponent, + } as Meta; -export const ExampleAsyncStory: Story = { - play: async () => { - const Input = screen.getByLabelText('Username', { - selector: 'input', - }); - - await userEvent.type(Input, 'WrongInput', { - delay: 100, - }); - - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const Submit = screen.getByRole('button'); - await userEvent.click(Submit); - - await waitFor(async () => { - await userEvent.hover(screen.getByTestId('error')); - }); - }, +const Template: Story = (args) => ({ + props: args, +}); + +/* +* See https://storybook.js.org/docs/angular/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleAsyncStory = Template.bind({}); +ExampleAsyncStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { + selector: 'input', + }); + + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + + // See https://storybook.js.org/docs/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + await userEvent.click(Submit); + + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('error')); + }); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-with-clickevent.mdx.mdx b/docs/snippets/angular/my-component-play-function-with-clickevent.mdx.mdx index 85ca78cb6491..4e16e01e96fc 100644 --- a/docs/snippets/angular/my-component-play-function-with-clickevent.mdx.mdx +++ b/docs/snippets/angular/my-component-play-function-with-clickevent.mdx.mdx @@ -3,34 +3,37 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { fireEvent, screen, userEvent } from '@storybook/testing-library'; +import { fireEvent, userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; - +export const Template = (args) => ({ props: args }); + { - // See https://storybook.js.org/docs/7.0/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button')); - }} - render={(args) => ({ - props: args, - })} /> + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + }}> + {Template.bind({})} + + { - // See https://storybook.js.org/docs/7.0/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await fireEvent.click(screen.getByTestId('data-testid')); - }} - render={(args) => ({ - props: args, - })} /> + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-with-clickevent.ts.mdx b/docs/snippets/angular/my-component-play-function-with-clickevent.ts.mdx index bbff077d97a2..663d83a0fd14 100644 --- a/docs/snippets/angular/my-component-play-function-with-clickevent.ts.mdx +++ b/docs/snippets/angular/my-component-play-function-with-clickevent.ts.mdx @@ -1,32 +1,42 @@ ```ts // MyComponent.stories.ts -import type { Meta, Story } from '@storybook/angular'; +import { Meta, Story } from '@storybook/angular'; -import { fireEvent, screen, userEvent } from '@storybook/testing-library'; +import { fireEvent, userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/angular/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/angular/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'ClickExamples', component: MyComponent, } as Meta; -export const ClickExample: Story = { - play: async () => { - // See https://storybook.js.org/docs/7.0/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button')); - }, +const Template: Story = (args) => ({ + props: args, +}); + +/* +* See https://storybook.js.org/docs/angular/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ClickExample = Template.bind({}); +ClickExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); }; -export const FireEventExample: Story = { - play: async () => { - // See https://storybook.js.org/docs/7.0/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await fireEvent.click(screen.getByTestId('data-testid')); - }, +export const FireEventExample = Template.bind({}); +FireEventExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-with-delay.mdx.mdx b/docs/snippets/angular/my-component-play-function-with-delay.mdx.mdx index 6fd941e4ee27..c165de4469ef 100644 --- a/docs/snippets/angular/my-component-play-function-with-delay.mdx.mdx +++ b/docs/snippets/angular/my-component-play-function-with-delay.mdx.mdx @@ -3,34 +3,35 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; - +export const Template = (args) => ({ props: args }); + { - const exampleElement= screen.getByLabelText('example-element'); + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement= canvas.getByLabelText('example-element'); // The delay option set the amount of milliseconds between characters being typed await userEvent.type(exampleElement, 'random string', { delay: 100, }); - const AnotherExampleElement= screen.getByLabelText('another-example-element'); + const AnotherExampleElement= canvas.getByLabelText('another-example-element'); await userEvent.type(AnotherExampleElement, 'another random string', { delay: 100, }); - }} - render={(args) => ({ - props: args, - })} /> -``` + }} > + {Template.bind({})} + +``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-with-delay.ts.mdx b/docs/snippets/angular/my-component-play-function-with-delay.ts.mdx index dfc26e57fdd1..03a0051e8c7a 100644 --- a/docs/snippets/angular/my-component-play-function-with-delay.ts.mdx +++ b/docs/snippets/angular/my-component-play-function-with-delay.ts.mdx @@ -1,34 +1,42 @@ ```ts // MyComponent.stories.ts -import type { Meta, Story } from '@storybook/angular'; +import { Meta, Story } from '@storybook/angular'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/angular/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/angular/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithDelay', component: MyComponent, } as Meta; -export const DelayedStory: Story = { - play: async () => { - const exampleElement = screen.getByLabelText('example-element'); +const Template: Story = (args) => ({ + props: args, +}); - // The delay option set the ammount of milliseconds between characters being typed - await userEvent.type(exampleElement, 'random string', { - delay: 100, - }); +/* +* See https://storybook.js.org/docs/angular/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const DelayedStory = Template.bind({}); +DelayedStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); - const AnotherExampleElement = screen.getByLabelText('another-example-element'); - await userEvent.type(AnotherExampleElement, 'another random string', { - delay: 100, - }); - }, + const exampleElement= canvas.getByLabelText('example-element'); + // The delay option set the amount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); + + const AnotherExampleElement= canvas.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-with-selectevent.mdx.mdx b/docs/snippets/angular/my-component-play-function-with-selectevent.mdx.mdx index 42c89c623ca6..db30f2699161 100644 --- a/docs/snippets/angular/my-component-play-function-with-selectevent.mdx.mdx +++ b/docs/snippets/angular/my-component-play-function-with-selectevent.mdx.mdx @@ -3,7 +3,7 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; @@ -15,10 +15,18 @@ export const sleep= (ms) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; +export const Template = (args) => ({ props: args }); + + { - const select = screen.getByRole('listbox'); + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const select = canvas.getByRole('listbox'); await userEvent.selectOptions(select, ['One Item']); await sleep(2000); @@ -28,8 +36,7 @@ export const sleep= (ms) => { await userEvent.selectOptions(select, ['Yet another item']); - }} - render={(args) => ({ - props: args, - })} /> + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/angular/my-component-play-function-with-selectevent.ts.mdx b/docs/snippets/angular/my-component-play-function-with-selectevent.ts.mdx index b59cfa636664..4cef54a91451 100644 --- a/docs/snippets/angular/my-component-play-function-with-selectevent.ts.mdx +++ b/docs/snippets/angular/my-component-play-function-with-selectevent.ts.mdx @@ -1,17 +1,17 @@ ```ts // MyComponent.stories.ts -import type { Meta, Story } from '@storybook/angular'; +import { Meta, Story } from '@storybook/angular'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent.component'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/angular/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/angular/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithSelectEvent', component: MyComponent, } as Meta; @@ -21,17 +21,26 @@ function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } -export const ExampleChangeEvent: Story = { - play: async () => { - const select = screen.getByRole('listbox'); +const Template: Story = (args) => ({ + props: args, +}); - await userEvent.selectOptions(select, ['One Item']); - await sleep(2000); +/* +* See https://storybook.js.org/docs/angular/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleChangeEvent = Template.bind({}); +ExampleChangeEvent.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); - await userEvent.selectOptions(select, ['Another Item']); - await sleep(2000); + const select = canvas.getByRole('listbox'); - await userEvent.selectOptions(select, ['Yet another item']); - }, + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Yet another item']); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/angular/register-component-with-play-function.mdx.mdx b/docs/snippets/angular/register-component-with-play-function.mdx.mdx index 0908c9a0e704..5b5613f02cd4 100644 --- a/docs/snippets/angular/register-component-with-play-function.mdx.mdx +++ b/docs/snippets/angular/register-component-with-play-function.mdx.mdx @@ -3,22 +3,24 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { RegistrationForm } from './RegistrationForm.component'; - +export const Template = (args) => ({ props: args }); + { - const emailInput = screen.getByLabelText('email', { + play={async ({ canvasElement, args}) => { + const canvas = within(canvasElement); + + const emailInput = canvas.getByLabelText('email', { selector: 'input', }); @@ -26,20 +28,19 @@ import { RegistrationForm } from './RegistrationForm.component'; delay: 100, }); - const passwordInput = screen.getByLabelText('password', { + const passwordInput = canvas.getByLabelText('password', { selector: 'input', }); await userEvent.type(passwordInput, 'ExamplePassword', { delay: 100, }); - - // See https://storybook.js.org/docs/7.0/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const Submit = screen.getByRole('button'); - - await userEvent.click(Submit); - }} - render={(args) => ({ - props: args, - })} /> + + // See https://storybook.js.org/docs/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); + + await userEvent.click(submitButton); + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/angular/register-component-with-play-function.ts.mdx b/docs/snippets/angular/register-component-with-play-function.ts.mdx index c327886df4dc..78b223eebd58 100644 --- a/docs/snippets/angular/register-component-with-play-function.ts.mdx +++ b/docs/snippets/angular/register-component-with-play-function.ts.mdx @@ -1,42 +1,47 @@ ```ts // RegistrationForm.stories.ts -import type { Meta, Story } from '@storybook/angular'; +import { Meta, Story } from '@storybook/angular'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { RegistrationForm } from './RegistrationForm.component'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/angular/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/angular/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'RegistrationForm', component: RegistrationForm, } as Meta; -export const FilledForm: Story = { - play: async () => { - const emailInput = screen.getByLabelText('email', { - selector: 'input', - }); - - await userEvent.type(emailInput, 'example-email@email.com', { - delay: 100, - }); - - const passwordInput = screen.getByLabelText('password', { - selector: 'input', - }); - - await userEvent.type(passwordInput, 'ExamplePassword', { - delay: 100, - }); - // See https://storybook.js.org/docs/7.0/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const submitButton = screen.getByRole('button'); - - await userEvent.click(submitButton); - }, +const Template: Story = (args) => ({ + props: args, +}); + +/* +* See https://storybook.js.org/docs/angular/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); + + const passwordInput = canvas.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + // See https://storybook.js.org/docs/angular/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); + + await userEvent.click(submitButton); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/common/storybook-interactions-play-function.js.mdx b/docs/snippets/common/storybook-interactions-play-function.js.mdx index dafb7dde0e51..9676caa689aa 100644 --- a/docs/snippets/common/storybook-interactions-play-function.js.mdx +++ b/docs/snippets/common/storybook-interactions-play-function.js.mdx @@ -1,5 +1,5 @@ ```js -// MyForm.stories.js +// MyForm.stories.js|jsx import { expect } from '@storybook/jest'; @@ -9,7 +9,7 @@ import { MyForm } from './MyForm'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading * to learn how to generate automatic titles */ title: 'MyForm', @@ -19,21 +19,23 @@ export default { }, }; -export const Submitted = { - play: async ({ args, canvasElement, step }) => { - // Starts querying the component from its root element - const canvas = within(canvasElement); +const Template = (args) => ( + // πŸ‘‡ Your story template goes here +); - await step('Enter credentials', async () => { - await userEvent.type(canvas.getByTestId('email'), 'hi@example.com'); - await userEvent.type(canvas.getByTestId('password'), 'supersecret'); - }); +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const Submitted = Template.bind({}); +Submitted.play = async ({ args, canvasElement }) => { + const canvas = within(canvasElement); - await step('Submit form', async () => { - await userEvent.click(canvas.getByRole('button')); - }); + await userEvent.type(canvas.getByTestId('email'), 'hi@example.com'); + await userEvent.type(canvas.getByTestId('password'), 'supersecret'); - await waitFor(() => expect(args.onSubmit).toHaveBeenCalled()); - }, + await userEvent.click(canvas.getByRole('button')); + + await waitFor(() => expect(args.onSubmit).toHaveBeenCalled()); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/common/storybook-interactions-play-function.mdx.mdx b/docs/snippets/common/storybook-interactions-play-function.mdx.mdx new file mode 100644 index 000000000000..0b697fa598ab --- /dev/null +++ b/docs/snippets/common/storybook-interactions-play-function.mdx.mdx @@ -0,0 +1,38 @@ +```md + + +import { Canvas, Meta, Story } from '@storybook/addon-docs'; + +import { userEvent, waitFor, within } from '@storybook/testing-library'; + +import { expect } from '@storybook/jest'; + +import { MyForm } from './MyForm'; + + + +export const Template = (args) => ( + // πŸ‘‡ Your story template goes here +); + + + + { + const canvas = within(canvasElement); + + await userEvent.type(canvas.getByTestId('Email'), 'hi@example.com'); + await userEvent.type(canvas.getByTestId('Password'), 'supersecret'); + + await userEvent.click(canvas.getByRole('button')); + + await waitFor(() => expect(args.onSubmit).toHaveBeenCalled()); + }}> + {Template.bind({})} + + +``` \ No newline at end of file diff --git a/docs/snippets/common/storybook-interactions-play-function.ts.mdx b/docs/snippets/common/storybook-interactions-play-function.ts.mdx new file mode 100644 index 000000000000..b1bed2d0e665 --- /dev/null +++ b/docs/snippets/common/storybook-interactions-play-function.ts.mdx @@ -0,0 +1,44 @@ +```ts +// MyForm.stories.ts|tsx + +// Replace your-framework with your framework of choice +import { Meta, Story } from '@storybook/your-framework'; + +import { expect } from '@storybook/jest'; + +import { userEvent, waitFor, within } from '@storybook/testing-library'; + +import { MyForm } from './MyForm'; + +export default { + /* πŸ‘‡ The title prop is optional. + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: 'MyForm', + component: MyForm, + argTypes: { + onSubmit: { action: true }, + }, +} as Meta; + +const Template: Story = (args) => ( + // πŸ‘‡ Your story template goes here +); + +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const Submitted = Template.bind({}); +Submitted.play = async ({ args, canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.type(canvas.getByTestId('email'), 'hi@example.com'); + await userEvent.type(canvas.getByTestId('password'), 'supersecret'); + + await userEvent.click(canvas.getByRole('button')); + + await waitFor(() => expect(args.onSubmit).toHaveBeenCalled()); +}; +``` \ No newline at end of file diff --git a/docs/snippets/react/login-form-with-play-function.js.mdx b/docs/snippets/react/login-form-with-play-function.js.mdx index 686ebc05e65b..783e098cf4b8 100644 --- a/docs/snippets/react/login-form-with-play-function.js.mdx +++ b/docs/snippets/react/login-form-with-play-function.js.mdx @@ -1,6 +1,8 @@ ```js // LoginForm.stories.js|jsx +import React from 'react'; + import { userEvent, within } from '@storybook/testing-library'; import { expect } from '@storybook/jest'; @@ -9,34 +11,38 @@ import { LoginForm } from './LoginForm'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'Form', component: LoginForm, }; -export const EmptyForm = {}; +const Template = (args) => ; -export const FilledForm = { - play: async ({ canvasElement }) => { - // Starts querying the component from its root element - const canvas = within(canvasElement); +export const EmptyForm = Template.bind({}); - // πŸ‘‡ Simulate interactions with the component - await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); - await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); + // πŸ‘‡ Simulate interactions with the component + await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); + + await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(canvas.getByRole('button')); + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); - // πŸ‘‡ Assert DOM structure - await expect( - canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!' - ) - ).toBeInTheDocument(); - }, + // πŸ‘‡ Assert DOM structure + await expect( + canvas.getByText( + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) + ).toBeInTheDocument(); }; ``` \ No newline at end of file diff --git a/docs/snippets/react/login-form-with-play-function.mdx.mdx b/docs/snippets/react/login-form-with-play-function.mdx.mdx index a37280ade7f4..bcaa5b2a3c0e 100644 --- a/docs/snippets/react/login-form-with-play-function.mdx.mdx +++ b/docs/snippets/react/login-form-with-play-function.mdx.mdx @@ -3,7 +3,7 @@ import { Canvas, Meta, Story } from '@storybook/addon-docs'; -import { within, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { expect } from '@storybook/jest'; @@ -11,15 +11,20 @@ import { LoginForm } from './LoginForm'; +export const Template = (args) => ; - + {Template.bind({})} + + { - // Starts querying the component from its root element + play={async ({ canvasElement }) => { const canvas = within(canvasElement); // πŸ‘‡ Simulate interactions with the component @@ -27,7 +32,7 @@ import { LoginForm } from './LoginForm'; await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel await userEvent.click(canvas.getByRole('button')); // πŸ‘‡ Assert DOM structure @@ -37,7 +42,7 @@ import { LoginForm } from './LoginForm'; ) ).toBeInTheDocument(); }}> - + {Template.bind({})} -``` +``` \ No newline at end of file diff --git a/docs/snippets/react/login-form-with-play-function.ts.mdx b/docs/snippets/react/login-form-with-play-function.ts.mdx index 97b0bdd0119b..11efaf228b80 100644 --- a/docs/snippets/react/login-form-with-play-function.ts.mdx +++ b/docs/snippets/react/login-form-with-play-function.ts.mdx @@ -3,9 +3,9 @@ import React from 'react'; -import type { ComponentStoryObj, ComponentMeta } from '@storybook/react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; -import { within, userEvent } from '@storybook/testing-library'; +import { userEvent, within} from '@storybook/testing-library'; import { expect } from '@storybook/jest'; @@ -13,34 +13,38 @@ import { LoginForm } from './LoginForm'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'Form', component: LoginForm, } as ComponentMeta; -export const EmptyForm: ComponentStoryObj = {}; +const Template: ComponentStory = (args) => ; -export const FilledForm: ComponentStoryObj = { - play: async ({ canvasElement }) => { - // Starts querying the component from its root element - const canvas = within(canvasElement); +export const EmptyForm = Template.bind({}); - // πŸ‘‡ Simulate interactions with the component - await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); - await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); + // πŸ‘‡ Simulate interactions with the component + await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); + + await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(canvas.getByRole('button')); + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); - // πŸ‘‡ Assert DOM structure - await expect( - canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!' - ) - ).toBeInTheDocument(); - }, + // πŸ‘‡ Assert DOM structure + await expect( + canvas.getByText( + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) + ).toBeInTheDocument(); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-alt-queries.js.mdx b/docs/snippets/react/my-component-play-function-alt-queries.js.mdx index 8017824f22fa..ee3e05b5dc1b 100644 --- a/docs/snippets/react/my-component-play-function-alt-queries.js.mdx +++ b/docs/snippets/react/my-component-play-function-alt-queries.js.mdx @@ -1,23 +1,32 @@ ```js // MyComponent.stories.js|jsx -import { screen, userEvent } from '@storybook/testing-library'; +import React from 'react'; + +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'QueryMethods', component: MyComponent, }; -export const ExampleWithRole = { - play: async () => { - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button', { name: / button label/i })); - }, +const Template = (args) => ; + +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleWithRole = Template.bind({}); +ExampleWithRole.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); }; ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-alt-queries.mdx.mdx b/docs/snippets/react/my-component-play-function-alt-queries.mdx.mdx index c4b5cf2f9d1e..6e61e65af3ae 100644 --- a/docs/snippets/react/my-component-play-function-alt-queries.mdx.mdx +++ b/docs/snippets/react/my-component-play-function-alt-queries.mdx.mdx @@ -3,18 +3,26 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; +export const Template = (args) => ; + + { - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button', { name: / button label/i })); + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); }}> - + {Template.bind({})} ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-alt-queries.ts.mdx b/docs/snippets/react/my-component-play-function-alt-queries.ts.mdx index 2902b937a742..07f456287769 100644 --- a/docs/snippets/react/my-component-play-function-alt-queries.ts.mdx +++ b/docs/snippets/react/my-component-play-function-alt-queries.ts.mdx @@ -3,25 +3,32 @@ import React from 'react'; -import type { ComponentStoryObj, ComponentMeta } from '@storybook/react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'QueryMethods', component: MyComponent, } as ComponentMeta; -export const ExampleWithRole: ComponentStoryObj = { - play: async () => { - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button', { name: / button label/i })); - }, +const Template: ComponentStory = (args) => ; + +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleWithRole = Template.bind({}); +ExampleWithRole.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); }; ``` diff --git a/docs/snippets/react/my-component-play-function-composition.js.mdx b/docs/snippets/react/my-component-play-function-composition.js.mdx index 7b17b60735a9..0e4af20a0a99 100644 --- a/docs/snippets/react/my-component-play-function-composition.js.mdx +++ b/docs/snippets/react/my-component-play-function-composition.js.mdx @@ -1,37 +1,48 @@ ```js // MyComponent.stories.js|jsx -import { screen, userEvent } from '@storybook/testing-library'; +import React from 'react'; + +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'MyComponent', component: MyComponent, }; -export const FirstStory = { - play: async () => { - userEvent.type(screen.getByTestId('an-element'), 'example-value'); - }, +const Template = (args) => ; + +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FirstStory = Template.bind({}); +FirstStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.type(canvas.getByTestId('an-element'), 'example-value'); }; -export const SecondStory = { - play: async () => { - await userEvent.type(screen.getByTestId('other-element'), 'another value'); - }, +export const SecondStory = Template.bind({}); +SecondStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.type(canvas.getByTestId('other-element'), 'another value'); }; -export const CombinedStories = { - play: async () => { - // Runs the FirstStory and Second story play function before running this story's play function - await FirstStory.play(); - await SecondStory.play(); - await userEvent.type(screen.getByTestId('another-element'), 'random value'); - }, +export const CombinedStories = Template.bind({}); +CombinedStories.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Runs the FirstStory and Second story play function before running this story's play function + await FirstStory.play({ canvasElement }); + await SecondStory.play({ canvasElement }); + await userEvent.type(canvas.getByTestId('another-element'), 'random value'); }; ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-composition.ts.mdx b/docs/snippets/react/my-component-play-function-composition.ts.mdx index d7776a6cf3f1..38692ead88bd 100644 --- a/docs/snippets/react/my-component-play-function-composition.ts.mdx +++ b/docs/snippets/react/my-component-play-function-composition.ts.mdx @@ -3,39 +3,48 @@ import React from 'react'; -import type { ComponentStoryObj, ComponentMeta } from '@storybook/react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/eact/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'MyComponent', component: MyComponent, } as ComponentMeta; -export const FirstStory: ComponentStoryObj = { - play: async () => { - userEvent.type(screen.getByTestId('an-element'), 'example-value'); - }, +const Template: ComponentStory = (args) => ; + +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FirstStory = Template.bind({}); +FirstStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.type(canvas.getByTestId('an-element'), 'example-value'); }; -export const SecondStory: ComponentStoryObj = { - play: async () => { - await userEvent.type(screen.getByTestId('other-element'), 'another value'); - }, +export const SecondStory = Template.bind({}); +SecondStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.type(canvas.getByTestId('other-element'), 'another value'); }; -export const CombinedStories: ComponentStoryObj = { - play: async () => { - // Runs the FirstStory and Second story play function before running this story's play function - await FirstStory.play(); - await SecondStory.play(); - await userEvent.type(screen.getByTestId('another-element'), 'random value'); - }, +export const CombinedStories = Template.bind({}); +CombinedStories.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Runs the FirstStory and Second story play function before running this story's play function + await FirstStory.play({ canvasElement }); + await SecondStory.play({ canvasElement }); + await userEvent.type(canvas.getByTestId('another-element'), 'random value'); }; ``` diff --git a/docs/snippets/react/my-component-play-function-query-findby.js.mdx b/docs/snippets/react/my-component-play-function-query-findby.js.mdx index c133b906a64f..77323c82e7db 100644 --- a/docs/snippets/react/my-component-play-function-query-findby.js.mdx +++ b/docs/snippets/react/my-component-play-function-query-findby.js.mdx @@ -1,25 +1,31 @@ ```js // MyComponent.stories.js|jsx -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading * to learn how to generate automatic titles */ title: 'Async Query Methods', component: MyComponent, }; -export const AsyncExample = { - play: async () => { - // Other steps +const Template = (args) => ; - // Waits for the component to be rendered before querying the element - await screen.findByRole('button', { name: / button label/i })); - }, +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const AsyncExample= Template.bind({}); +AsyncExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + // Other steps + + // Waits for the component to be rendered before querying the element + await canvas.findByRole('button', { name: / button label/i })); }; ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-query-findby.mdx.mdx b/docs/snippets/react/my-component-play-function-query-findby.mdx.mdx index dc3a28e2c841..3ed90fc6afa3 100644 --- a/docs/snippets/react/my-component-play-function-query-findby.mdx.mdx +++ b/docs/snippets/react/my-component-play-function-query-findby.mdx.mdx @@ -3,20 +3,27 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; +export const Template = (args) => ; + + { + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); // Other steps // Waits for the component to be rendered before querying the element - await screen.findByRole('button', { name: / button label/i })); + await canvas.findByRole('button', { name: / button label/i })); }}> - + {Template.bind({})} ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-query-findby.ts.mdx b/docs/snippets/react/my-component-play-function-query-findby.ts.mdx index 6d8a48bb8e30..ce5f96e352bd 100644 --- a/docs/snippets/react/my-component-play-function-query-findby.ts.mdx +++ b/docs/snippets/react/my-component-play-function-query-findby.ts.mdx @@ -3,27 +3,33 @@ import React from 'react'; -import type { ComponentStoryObj, ComponentMeta } from '@storybook/react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading * to learn how to generate automatic titles */ title: 'Async Query Methods', component: MyComponent, } as ComponentMeta; -export const AsyncExample: ComponentStoryObj = { - play: async () => { - // Other steps +const Template: ComponentStory = (args) => ; - // Waits for the component to be rendered before querying the element - await screen.findByRole('button', { name: / button label/i })); - }, +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const AsyncExample= Template.bind({}); +AsyncExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + // Other steps + + // Waits for the component to be rendered before querying the element + await canvas.findByRole('button', { name: / button label/i })); }; ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-waitfor.js.mdx b/docs/snippets/react/my-component-play-function-waitfor.js.mdx index e6ba8ea5d22b..e0b4aa743818 100644 --- a/docs/snippets/react/my-component-play-function-waitfor.js.mdx +++ b/docs/snippets/react/my-component-play-function-waitfor.js.mdx @@ -1,36 +1,46 @@ ```js // MyComponent.stories.js|jsx -import { screen, userEvent, waitFor } from '@storybook/testing-library'; +import React from 'react'; + +import { userEvent, waitFor, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithAsync', component: MyComponent, }; -export const ExampleAsyncStory = { - play: async () => { - const Input = screen.getByLabelText('Username', { - selector: 'input', - }); +const Template = (args) => ; + +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleAsyncStory = Template.bind({}); +ExampleAsyncStory.play = async ({ canvasElement }) => { + + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { + selector: 'input', + }); - await userEvent.type(Input, 'WrongInput', { - delay: 100, - }); + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const Submit = screen.getByRole('button'); - await userEvent.click(Submit); + await userEvent.click(Submit); - await waitFor(async () => { - await userEvent.hover(screen.getByTestId('error')); - }); - }, + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('error')); + }); }; ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-waitfor.mdx.mdx b/docs/snippets/react/my-component-play-function-waitfor.mdx.mdx index ba2de20bb456..62234e7986e4 100644 --- a/docs/snippets/react/my-component-play-function-waitfor.mdx.mdx +++ b/docs/snippets/react/my-component-play-function-waitfor.mdx.mdx @@ -3,16 +3,23 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent, waitFor } from '@storybook/testing-library'; +import { userEvent, waitFor, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; +export const Template = (args) => ; + + { - const Input = screen.getByLabelText('Username', { + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + const Input = canvas.getByLabelText('Username', { selector: 'input', }); @@ -20,15 +27,15 @@ import { MyComponent } from './MyComponent'; delay: 100, }); - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel const Submit = screen.getByRole('button'); await userEvent.click(Submit); await waitFor(async () => { - await userEvent.hover(screen.getByTestId('error')); + await userEvent.hover(canvas.getByTestId('error')); }); }}> - + {Template.bind({})} ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-waitfor.ts.mdx b/docs/snippets/react/my-component-play-function-waitfor.ts.mdx index 9d43d13ddf35..2a9882ab5995 100644 --- a/docs/snippets/react/my-component-play-function-waitfor.ts.mdx +++ b/docs/snippets/react/my-component-play-function-waitfor.ts.mdx @@ -3,38 +3,44 @@ import React from 'react'; -import type { ComponentStoryObj, ComponentMeta } from '@storybook/react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; -import { screen, userEvent, waitFor } from '@storybook/testing-library'; +import { userEvent, waitFor, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithAsync', component: MyComponent, } as ComponentMeta; -export const ExampleAsyncStory: ComponentStoryObj = { - play: async () => { - const Input = screen.getByLabelText('Username', { - selector: 'input', - }); - - await userEvent.type(Input, 'WrongInput', { - delay: 100, - }); - - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const Submit = screen.getByRole('button'); - await userEvent.click(Submit); - - await waitFor(async () => { - await userEvent.hover(screen.getByTestId('error')); - }); - }, +const Template: ComponentStory = (args) => ; + +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleAsyncStory = Template.bind({}); +ExampleAsyncStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + const Input = canvas.getByLabelText('Username', { + selector: 'input', + }); + + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + + await userEvent.click(Submit); + + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('error')); + }); }; ``` diff --git a/docs/snippets/react/my-component-play-function-with-clickevent.js.mdx b/docs/snippets/react/my-component-play-function-with-clickevent.js.mdx index 4b9959f264f9..42258e38697c 100644 --- a/docs/snippets/react/my-component-play-function-with-clickevent.js.mdx +++ b/docs/snippets/react/my-component-play-function-with-clickevent.js.mdx @@ -1,7 +1,7 @@ ```js // MyComponent.stories.js|jsx -import { fireEvent, screen, userEvent } from '@storybook/testing-library'; +import { fireEvent, userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; @@ -14,17 +14,25 @@ export default { component: MyComponent, }; -export const ClickExample = { - play: async () => { - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button')); - }, +const Template = (args) => ; + +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ClickExample = Template.bind({}); +ClickExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); }; -export const FireEventExample = { - play: async () => { - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await fireEvent.click(screen.getByTestId('data-testid')); - }, +export const FireEventExample = Template.bind({}); +FireEventExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); }; ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-with-clickevent.mdx.mdx b/docs/snippets/react/my-component-play-function-with-clickevent.mdx.mdx index c94aea01fb62..9cf19a9fe8d0 100644 --- a/docs/snippets/react/my-component-play-function-with-clickevent.mdx.mdx +++ b/docs/snippets/react/my-component-play-function-with-clickevent.mdx.mdx @@ -1,29 +1,41 @@ ```md + + import { Meta, Story } from '@storybook/addon-docs'; -import { fireEvent, screen, userEvent } from '@storybook/testing-library'; +import { fireEvent, userEvent, within} from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; +export const Template = (args) => ; + + { - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button')); + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); }}> - + {Template.bind({})} { - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await fireEvent.click(screen.getByTestId('data-testid')); + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); }}> - + {Template.bind({})} ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-with-clickevent.ts.mdx b/docs/snippets/react/my-component-play-function-with-clickevent.ts.mdx index 2deaa5daf555..76029fd53908 100644 --- a/docs/snippets/react/my-component-play-function-with-clickevent.ts.mdx +++ b/docs/snippets/react/my-component-play-function-with-clickevent.ts.mdx @@ -3,32 +3,40 @@ import React from 'react'; -import type { ComponentStoryObj, ComponentMeta } from '@storybook/react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; -import { fireEvent, screen, userEvent } from '@storybook/testing-library'; +import { fireEvent, userEvent, within} from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'ClickExamples', component: MyComponent, } as ComponentMeta; -export const ClickExample: ComponentStoryObj = { - play: async () => { - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button')); - }, +const Template: ComponentStory = (args) => ; + +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ClickExample = Template.bind({}); +ClickExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); }; -export const FireEventExample: ComponentStoryObj = { - play: async () => { - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await fireEvent.click(screen.getByTestId('data-testid')); - }, +export const FireEventExample = Template.bind({}); +FireEventExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); }; ``` diff --git a/docs/snippets/react/my-component-play-function-with-delay.js.mdx b/docs/snippets/react/my-component-play-function-with-delay.js.mdx index f0f38d5a71f7..a0019d3e474f 100644 --- a/docs/snippets/react/my-component-play-function-with-delay.js.mdx +++ b/docs/snippets/react/my-component-play-function-with-delay.js.mdx @@ -1,32 +1,41 @@ ```js // MyComponent.stories.js|jsx -import { screen, userEvent } from '@storybook/testing-library'; +import React from 'react'; + +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithDelay', component: MyComponent, }; -export const DelayedStory = { - play: async () => { - const exampleElement = screen.getByLabelText('example-element'); +const Template = (args) => ; + +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const DelayedStory = Template.bind({}); +DelayedStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement = canvas.getByLabelText('example-element'); - // The delay option set the ammount of milliseconds between characters being typed - await userEvent.type(exampleElement, 'random string', { - delay: 100, - }); + // The delay option set the amount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); - const AnotherExampleElement = screen.getByLabelText('another-example-element'); - await userEvent.type(AnotherExampleElement, 'another random string', { - delay: 100, - }); - }, + const AnotherExampleElement = canvas.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); }; ``` diff --git a/docs/snippets/react/my-component-play-function-with-delay.mdx.mdx b/docs/snippets/react/my-component-play-function-with-delay.mdx.mdx index 6f925fd8b7f7..3d260730d924 100644 --- a/docs/snippets/react/my-component-play-function-with-delay.mdx.mdx +++ b/docs/snippets/react/my-component-play-function-with-delay.mdx.mdx @@ -3,27 +3,35 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; +export const Template = (args) => ; + + { - const exampleElement= screen.getByLabelText('example-element'); + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement = canvas.getByLabelText('example-element'); // The delay option set the amount of milliseconds between characters being typed await userEvent.type(exampleElement, 'random string', { delay: 100, }); - const AnotherExampleElement= screen.getByLabelText('another-example-element'); + const AnotherExampleElement = canvas.getByLabelText('another-example-element'); await userEvent.type(AnotherExampleElement, 'another random string', { delay: 100, }); }}> - + {Template.bind({})} ``` diff --git a/docs/snippets/react/my-component-play-function-with-delay.ts.mdx b/docs/snippets/react/my-component-play-function-with-delay.ts.mdx index e9966a552b14..0ded64a45e81 100644 --- a/docs/snippets/react/my-component-play-function-with-delay.ts.mdx +++ b/docs/snippets/react/my-component-play-function-with-delay.ts.mdx @@ -3,34 +3,41 @@ import React from 'react'; -import type { ComponentStoryObj, ComponentMeta } from '@storybook/react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithDelay', component: MyComponent, } as ComponentMeta; -export const DelayedStory: ComponentStoryObj = { - play: async () => { - const exampleElement = screen.getByLabelText('example-element'); +const Template: ComponentStory = (args) => ; - // The delay option set the ammount of milliseconds between characters being typed - await userEvent.type(exampleElement, 'random string', { - delay: 100, - }); +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const DelayedStory = Template.bind({}); +DelayedStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); - const AnotherExampleElement = screen.getByLabelText('another-example-element'); - await userEvent.type(AnotherExampleElement, 'another random string', { - delay: 100, - }); - }, + const exampleElement = canvas.getByLabelText('example-element'); + + // The delay option set the amount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); + + const AnotherExampleElement = canvas.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-with-selectevent.js.mdx b/docs/snippets/react/my-component-play-function-with-selectevent.js.mdx index 742038b8cee7..e1824daa3185 100644 --- a/docs/snippets/react/my-component-play-function-with-selectevent.js.mdx +++ b/docs/snippets/react/my-component-play-function-with-selectevent.js.mdx @@ -1,15 +1,17 @@ ```js // MyComponent.stories.js|jsx -import { userEvent, screen } from '@storybook/testing-library'; +import React from 'react'; + +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithSelectEvent', component: MyComponent, }; @@ -19,19 +21,24 @@ function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } -// Queries the element by it's role and fires the event +const Template = (args) => ; + +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleChangeEvent = Template.bind({}); +ExampleChangeEvent.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); -export const ExampleChangeEvent = { - play: async () => { - const select = screen.getByRole('listbox'); + const select = canvas.getByRole('listbox'); - await userEvent.selectOptions(select, ['One Item']); - await sleep(2000); + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); - await userEvent.selectOptions(select, ['Another Item']); - await sleep(2000); + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); - await userEvent.selectOptions(select, ['Yet another item']); - }, + await userEvent.selectOptions(select, ['Yet another item']); }; ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-with-selectevent.mdx.mdx b/docs/snippets/react/my-component-play-function-with-selectevent.mdx.mdx index 168ee8e35b6b..276480595bc4 100644 --- a/docs/snippets/react/my-component-play-function-with-selectevent.mdx.mdx +++ b/docs/snippets/react/my-component-play-function-with-selectevent.mdx.mdx @@ -3,7 +3,7 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { userEvent, screen } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; @@ -15,10 +15,18 @@ export const sleep = (ms) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; +export const Template = (args) => ; + + + { - const select = screen.getByRole('listbox'); + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + const select = canvas.getByRole('listbox'); await userEvent.selectOptions(select, ['One Item']); await sleep(2000); @@ -29,6 +37,6 @@ export const sleep = (ms) => { await userEvent.selectOptions(select, ['Yet another item']); }}> - + {Template.bind({})} ``` \ No newline at end of file diff --git a/docs/snippets/react/my-component-play-function-with-selectevent.ts.mdx b/docs/snippets/react/my-component-play-function-with-selectevent.ts.mdx index c60811a2ed26..c50d1917245f 100644 --- a/docs/snippets/react/my-component-play-function-with-selectevent.ts.mdx +++ b/docs/snippets/react/my-component-play-function-with-selectevent.ts.mdx @@ -3,17 +3,17 @@ import React from 'react'; -import type { ComponentStoryObj, ComponentMeta } from '@storybook/react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; -import { userEvent, screen } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import { MyComponent } from './MyComponent'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithSelectEvent', component: MyComponent, } as ComponentMeta; @@ -23,19 +23,24 @@ function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } -// Queries the element by it's role and fires the event +const Template: ComponentStory = (args) => ; -export const ExampleChangeEvent: ComponentStoryObj = { - play: async () => { - const select = screen.getByRole('listbox'); +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleChangeEvent = Template.bind({}); +ExampleChangeEvent.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); - await userEvent.selectOptions(select, ['One Item']); - await sleep(2000); + const select = canvas.getByRole('listbox'); - await userEvent.selectOptions(select, ['Another Item']); - await sleep(2000); + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); - await userEvent.selectOptions(select, ['Yet another item']); - }, + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Yet another item']); }; ``` diff --git a/docs/snippets/react/register-component-with-play-function.js.mdx b/docs/snippets/react/register-component-with-play-function.js.mdx index bcb456e1c94e..97c7bbe4f807 100644 --- a/docs/snippets/react/register-component-with-play-function.js.mdx +++ b/docs/snippets/react/register-component-with-play-function.js.mdx @@ -1,40 +1,47 @@ ```js // RegistrationForm.stories.js|jsx -import { screen, userEvent } from '@storybook/testing-library'; +import { within, userEvent } from '@storybook/testing-library'; import { RegistrationForm } from './RegistrationForm'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading * to learn how to generate automatic titles */ title: 'RegistrationForm', component: RegistrationForm, }; -export const FilledForm = { - play: async () => { - const emailInput = screen.getByLabelText('email', { - selector: 'input', - }); +const Template = (args) => ; - await userEvent.type(emailInput, 'example-email@email.com', { - delay: 100, - }); +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas= within(canvasElement); - const passwordInput = screen.getByLabelText('password', { - selector: 'input', - }); + const emailInput = canvas.getByLabelText('email', { + selector: 'input', + }); - await userEvent.type(passwordInput, 'ExamplePassword', { - delay: 100, - }); - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const submitButton = screen.getByRole('button'); + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); - await userEvent.click(submitButton); - }, + const passwordInput = canvas.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); + + await userEvent.click(submitButton); }; ``` \ No newline at end of file diff --git a/docs/snippets/react/register-component-with-play-function.mdx.mdx b/docs/snippets/react/register-component-with-play-function.mdx.mdx index 3faec01dbe12..42326ec43c73 100644 --- a/docs/snippets/react/register-component-with-play-function.mdx.mdx +++ b/docs/snippets/react/register-component-with-play-function.mdx.mdx @@ -3,16 +3,24 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { within, userEvent } from '@storybook/testing-library'; import { RegistrationForm } from './RegistrationForm'; +export const Template = (args) => ; + + + { - const emailInput = screen.getByLabelText('email', { + play={ async ({ canvasElement }) => { + const canvas= within(canvasElement); + const emailInput = canvas.getByLabelText('email', { selector: 'input', }); @@ -20,18 +28,18 @@ import { RegistrationForm } from './RegistrationForm'; delay: 100, }); - const passwordInput = screen.getByLabelText('password', { + const passwordInput = canvas.getByLabelText('password', { selector: 'input', }); await userEvent.type(passwordInput, 'ExamplePassword', { delay: 100, }); - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const submitButton = screen.getByRole('button'); + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); await userEvent.click(submitButton); }}> - + {Template.bind({})} ``` \ No newline at end of file diff --git a/docs/snippets/react/register-component-with-play-function.ts.mdx b/docs/snippets/react/register-component-with-play-function.ts.mdx index 7d86f06489bb..53af9910354a 100644 --- a/docs/snippets/react/register-component-with-play-function.ts.mdx +++ b/docs/snippets/react/register-component-with-play-function.ts.mdx @@ -3,42 +3,49 @@ import React from 'react'; -import type { ComponentStoryObj, ComponentMeta } from '@storybook/react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; -import { screen, userEvent } from '@storybook/testing-library'; +import { within, userEvent } from '@storybook/testing-library'; import { RegistrationForm } from './RegistrationForm'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'RegistrationForm', component: RegistrationForm, } as ComponentMeta; -export const FilledForm: ComponentStoryObj = { - play: async () => { - const emailInput = screen.getByLabelText('email', { - selector: 'input', - }); +const Template: ComponentStory = (args) => ; - await userEvent.type(emailInput, 'example-email@email.com', { - delay: 100, - }); +/* +* See https://storybook.js.org/docs/react/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas= within(canvasElement); - const passwordInput = screen.getByLabelText('password', { - selector: 'input', - }); + const emailInput = canvas.getByLabelText('email', { + selector: 'input', + }); - await userEvent.type(passwordInput, 'ExamplePassword', { - delay: 100, - }); - // See https://storybook.js.org/docs/7.0/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const submitButton = screen.getByRole('button'); + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); - await userEvent.click(submitButton); - }, + const passwordInput = canvas.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + // See https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); + + await userEvent.click(submitButton); }; ``` diff --git a/docs/snippets/svelte/login-form-with-play-function.js.mdx b/docs/snippets/svelte/login-form-with-play-function.js.mdx index 010a758118ae..7b9c5409fe28 100644 --- a/docs/snippets/svelte/login-form-with-play-function.js.mdx +++ b/docs/snippets/svelte/login-form-with-play-function.js.mdx @@ -9,48 +9,41 @@ import LoginForm from './LoginForm.svelte'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/svelte/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/svelte/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'Form', component: LoginForm, }; -/* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/svelte/api/csf - * to learn how to use render functions. - */ -export const EmptyForm = { - render: (args) => ({ - Component: LoginForm, - props: args, - }), -}; +const Template = (args) => ({ + Component: LoginForm, + props: args, +}); -export const FilledForm = { - render: (args) => ({ - Component: LoginForm, - props: args, - }), - play: async ({ canvasElement }) => { - // Starts querying the component from its root element - const canvas = within(canvasElement); - - // πŸ‘‡ Simulate interactions with the component - await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); - - await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); - - // See https://storybook.js.org/docs/7.0/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(canvas.getByRole('button')); - - // πŸ‘‡ Assert DOM structure - await expect( - canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!' - ) - ).toBeInTheDocument(); - }, +export const EmptyForm = Template.bind({}); + +/* +* See https://storybook.js.org/docs/svelte/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // πŸ‘‡ Simulate interactions with the component + await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); + + await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); + + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + + // πŸ‘‡ Assert DOM structure + await expect( + canvas.getByText( + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) + ).toBeInTheDocument(); }; ``` \ No newline at end of file diff --git a/docs/snippets/svelte/login-form-with-play-function.mdx.mdx b/docs/snippets/svelte/login-form-with-play-function.mdx.mdx index 06ce15dc6b70..16541780c03f 100644 --- a/docs/snippets/svelte/login-form-with-play-function.mdx.mdx +++ b/docs/snippets/svelte/login-form-with-play-function.mdx.mdx @@ -11,27 +11,22 @@ import LoginForm from './LoginForm.svelte'; - +export const Template = (args) => ({ + Component: LoginForm, + props: args, +}); - ({ - Component: LoginForm, - props: args, - })} /> + + {Template.bind({})} + + ({ - Component: LoginForm, - props: args, - })} - play={ async ({ canvasElement }) => { - // Starts querying the component from its root element + play={async ({ canvasElement }) => { const canvas = within(canvasElement); // πŸ‘‡ Simulate interactions @@ -39,7 +34,7 @@ import LoginForm from './LoginForm.svelte'; await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); - // See https://storybook.js.org/docs/7.0/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel await userEvent.click(canvas.getByRole('button')); // πŸ‘‡ Assert DOM structure @@ -48,6 +43,8 @@ import LoginForm from './LoginForm.svelte'; 'Everything is perfect. Your account is ready and we should probably get you started!' ) ).toBeInTheDocument(); - }} /> + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-alt-queries.js.mdx b/docs/snippets/svelte/my-component-play-function-alt-queries.js.mdx index 91175c94b285..305b7934d3a3 100644 --- a/docs/snippets/svelte/my-component-play-function-alt-queries.js.mdx +++ b/docs/snippets/svelte/my-component-play-function-alt-queries.js.mdx @@ -1,32 +1,33 @@ ```js // MyComponent.stories.js -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/svelte/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/svelte/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'QueryMethods', component: MyComponent, }; +const Template = (args) => ({ + Component: MyComponent, + props: args, +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/svelte/api/csf - * to learn how to use render functions. - */ -export const ExampleWithRole = { - render: (args) => ({ - Component: MyComponent, - props: args, - }), - play: async () => { - // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button', { name: / button label/i })); - }, +* See https://storybook.js.org/docs/svelte/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleWithRole = Template.bind({}); +ExampleWithRole.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); }; ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-alt-queries.mdx.mdx b/docs/snippets/svelte/my-component-play-function-alt-queries.mdx.mdx index c3994d606519..7a30bea907c1 100644 --- a/docs/snippets/svelte/my-component-play-function-alt-queries.mdx.mdx +++ b/docs/snippets/svelte/my-component-play-function-alt-queries.mdx.mdx @@ -3,26 +3,29 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; - +export const Template = (args) => ({ + Component: MyComponent, + props: args, +}); + { - // See https://storybook.js.org/docs/7.0/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button', { name: / button label/i })); - }} - render={(args) => ({ - Component: MyComponent, - props: args, - })} /> + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-composition.js.mdx b/docs/snippets/svelte/my-component-play-function-composition.js.mdx index 1b28803f27c4..2697f68f4503 100644 --- a/docs/snippets/svelte/my-component-play-function-composition.js.mdx +++ b/docs/snippets/svelte/my-component-play-function-composition.js.mdx @@ -1,55 +1,49 @@ ```js // MyComponent.stories.js -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/svelte/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/svelte/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'MyComponent', component: MyComponent, }; +const Template = (args) => ({ + Component: MyComponent, + props: args, +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/svelte/api/csf - * to learn how to use render functions. - */ - -export const FirstStory = { - render: (args) => ({ - Component: MyComponent, - props: args, - }), - play: async () => { - userEvent.type(screen.getByTestId('an-element'), 'example-value'); - }, +* See https://storybook.js.org/docs/svelte/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FirstStory = Template.bind({}); +FirstStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + userEvent.type(canvas.getByTestId('an-element'), 'example-value'); }; -export const SecondStory = { - render: (args) => ({ - Component: MyComponent, - props: args, - }), - play: async () => { - await userEvent.type(screen.getByTestId('other-element'), 'another value'); - }, +export const SecondStory = Template.bind({}); +SecondStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.type(canvas.getByTestId('other-element'), 'another value'); }; -export const CombinedStories = { - render: (args) => ({ - Component: MyComponent, - props: args, - }), - play: async () => { - // Runs the FirstStory and Second story play function before running this story's play function - await FirstStory.play(); - await SecondStory.play(); - await userEvent.type(screen.getByTestId('another-element'), 'random value'); - }, +export const CombinedStories = Template.bind({}); +CombinedStories.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Runs the FirstStory and Second story play function before running this story's play function + await FirstStory.play({ canvasElement }); + await SecondStory.play({ canvasElement }); + await userEvent.type(canvas.getByTestId('another-element'), 'random value'); }; ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-query-findby.js.mdx b/docs/snippets/svelte/my-component-play-function-query-findby.js.mdx index ddcd1e605b52..dbc70d9e6e6b 100644 --- a/docs/snippets/svelte/my-component-play-function-query-findby.js.mdx +++ b/docs/snippets/svelte/my-component-play-function-query-findby.js.mdx @@ -1,34 +1,34 @@ ```js // MyComponent.stories.js -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/svelte/configure/overview#configure-story-loading + * See https://storybook.js.org/docs/svelte/configure/overview#configure-story-loading * to learn how to generate automatic titles */ title: 'Async Query Methods', component: MyComponent, }; +const Template = (args) => ({ + Component: MyComponent, + props: args, +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/svelte/api/csf - * to learn how to use render functions. - */ -export const AsyncExample = { - render: (args) => ({ - Component: MyComponent, - props: args, - }), - play: async () => { - // Other steps +* See https://storybook.js.org/docs/svelte/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const AsyncExample = Template.bind({}); +AsyncExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + // Other steps - // Waits for the component to be rendered before querying the element - await screen.findByRole('button', { name: / button label/i })); - }, + // Waits for the component to be rendered before querying the element + await canvas.findByRole('button', { name: / button label/i })); }; ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-query-findby.mdx.mdx b/docs/snippets/svelte/my-component-play-function-query-findby.mdx.mdx index af2acc4a66f3..8108435e4358 100644 --- a/docs/snippets/svelte/my-component-play-function-query-findby.mdx.mdx +++ b/docs/snippets/svelte/my-component-play-function-query-findby.mdx.mdx @@ -3,28 +3,31 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; - +export const Template = (args) => ({ + Component: MyComponent, + props: args, +}); + { + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + // Other steps // Waits for the component to be rendered before querying the element - await screen.findByRole('button', { name: / button label/i })); - }} - render={(args) => ({ - Component: MyComponent, - props: args, - })} /> + await canvas.findByRole('button', { name: / button label/i })); + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-waitfor.js.mdx b/docs/snippets/svelte/my-component-play-function-waitfor.js.mdx index b68676b2696a..c22507dd11f2 100644 --- a/docs/snippets/svelte/my-component-play-function-waitfor.js.mdx +++ b/docs/snippets/svelte/my-component-play-function-waitfor.js.mdx @@ -1,46 +1,46 @@ ```js // MyComponent.stories.js -import { screen, userEvent, waitFor } from '@storybook/testing-library'; +import { userEvent, waitFor, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/svelte/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/svelte/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithAsync', component: MyComponent, }; +const Template = (args) => ({ + Component: MyComponent, + props: args, +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/svelte/api/csf - * to learn how to use render functions. - */ -export const ExampleAsyncStory = { - render: (args) => ({ - component: MyComponent, - props: args, - }), - play: async () => { - const exampleElement = screen.getByLabelText('Username', { - selector: 'input', - }); - - // The delay option set the ammount of milliseconds between characters being typed - await userEvent.type(exampleElement, 'WrongInput', { - delay: 100, - }); - - // See https://storybook.js.org/docs/7.0/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const Submit = screen.getByRole('button'); - await userEvent.click(Submit); - - await waitFor(async () => { - await userEvent.hover(screen.getByTestId('error')); - }); - }, +* See https://storybook.js.org/docs/svelte/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleAsyncStory = Template.bind({}); +ExampleAsyncStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { + selector: 'input', + }); + + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + await userEvent.click(Submit); + + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('error')); + }); }; ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-waitfor.mdx.mdx b/docs/snippets/svelte/my-component-play-function-waitfor.mdx.mdx index e3e2c204d784..965a21fb9e13 100644 --- a/docs/snippets/svelte/my-component-play-function-waitfor.mdx.mdx +++ b/docs/snippets/svelte/my-component-play-function-waitfor.mdx.mdx @@ -3,22 +3,27 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent, waitFor } from '@storybook/testing-library'; +import { userEvent, waitFor, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; - +export const Template = (args) => ({ + Component: MyComponent, + props: args, +}); + { - const Input = screen.getByLabelText('Username', { + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { selector: 'input', }); @@ -26,16 +31,14 @@ import MyComponent from './MyComponent.svelte'; delay: 100, }); - // See https://storybook.js.org/docs/7.0/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const Submit = screen.getByRole('button'); + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); await userEvent.click(Submit); await waitFor(async () => { - await userEvent.hover(screen.getByTestId('error')); + await userEvent.hover(canvas.getByTestId('error')); }); - }} - render={(args) => ({ - Component: MyComponent, - props: args, - })} /> + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-with-clickevent.js.mdx b/docs/snippets/svelte/my-component-play-function-with-clickevent.js.mdx index ef7da34712c9..2ab4415f83fa 100644 --- a/docs/snippets/svelte/my-component-play-function-with-clickevent.js.mdx +++ b/docs/snippets/svelte/my-component-play-function-with-clickevent.js.mdx @@ -1,44 +1,41 @@ ```js // MyComponent.stories.js -import { fireEvent, screen, userEvent } from '@storybook/testing-library'; +import { fireEvent, userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/svelte/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/svelte/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'ClickExamples', component: MyComponent, }; +const Template = (args) => ({ + Component: MyComponent, + props: args, +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/svelte/api/csf - * to learn how to use render functions. - */ - -export const ClickExample = { - render: (args) => ({ - Component: MyComponent, - props: args, - }), - play: async () => { - // See https://storybook.js.org/docs/7.0/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button')); - }, +* See https://storybook.js.org/docs/svelte/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ClickExample = Template.bind({}); +ClickExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); }; -export const FireEventExample = { - render: (args) => ({ - Component: MyComponent, - props: args, - }), - play: async () => { - // See https://storybook.js.org/docs/7.0/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await fireEvent.click(screen.getByTestId('data-testid')); - }, +export const FireEventExample = Template.bind({}); +FireEventExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); }; ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-with-clickevent.mdx.mdx b/docs/snippets/svelte/my-component-play-function-with-clickevent.mdx.mdx index 3cb43de88f88..522fbe3e7876 100644 --- a/docs/snippets/svelte/my-component-play-function-with-clickevent.mdx.mdx +++ b/docs/snippets/svelte/my-component-play-function-with-clickevent.mdx.mdx @@ -3,36 +3,40 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { fireEvent, screen, userEvent } from '@storybook/testing-library'; +import { fireEvent, userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; - +export const Template = (args) => ({ + Component: MyComponent, + props: args, +}); + { - // See https://storybook.js.org/docs/7.0/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button')); - }} - render={(args) => ({ - Component: MyComponent, - props: args, - })} /> + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + }}> + {Template.bind({})} + + { - // See https://storybook.js.org/docs/7.0/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await fireEvent.click(screen.getByTestId('data-testid')); - }} - render={(args) => ({ - Component: MyComponent, - props: args, - })} /> + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-with-delay.js.mdx b/docs/snippets/svelte/my-component-play-function-with-delay.js.mdx index 32648be43be6..cc558b3a7f72 100644 --- a/docs/snippets/svelte/my-component-play-function-with-delay.js.mdx +++ b/docs/snippets/svelte/my-component-play-function-with-delay.js.mdx @@ -1,41 +1,42 @@ ```js // MyComponent.stories.js -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/svelte/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/svelte/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithDelay', component: MyComponent, }; +const Template = (args) => ({ + Component: MyComponent, + props: args, +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/svelte/api/csf - * to learn how to use render functions. - */ -export const DelayedStory = { - render: (args) => ({ - Component: MyComponent, - props: args, - }), - play: async () => { - const exampleElement = screen.getByLabelText('example-element'); - - // The delay option set the amount of milliseconds between characters being typed - await userEvent.type(exampleElement, 'random string', { - delay: 100, - }); - - const AnotherExampleElement = screen.getByLabelText('another-example-element'); - await userEvent.type(AnotherExampleElement, 'another random string', { - delay: 100, - }); - }, +* See https://storybook.js.org/docs/svelte/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const DelayedStory = Template.bind({}); +DelayedStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement= canvas.getByLabelText('example-element'); + + // The delay option set the amount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); + + const AnotherExampleElement= canvas.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-with-delay.mdx.mdx b/docs/snippets/svelte/my-component-play-function-with-delay.mdx.mdx index 41ebd73e086c..c7fb2084a58b 100644 --- a/docs/snippets/svelte/my-component-play-function-with-delay.mdx.mdx +++ b/docs/snippets/svelte/my-component-play-function-with-delay.mdx.mdx @@ -3,35 +3,38 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; - +export const Template = (args) => ({ + Component: MyComponent, + props: args, +}); + { - const exampleElement= screen.getByLabelText('example-element'); + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement= canvas.getByLabelText('example-element'); // The delay option set the amount of milliseconds between characters being typed await userEvent.type(exampleElement, 'random string', { delay: 100, }); - const AnotherExampleElement= screen.getByLabelText('another-example-element'); + const AnotherExampleElement= canvas.getByLabelText('another-example-element'); await userEvent.type(AnotherExampleElement, 'another random string', { delay: 100, }); - }} - render={(args) => ({ - Component: MyComponent, - props: args, - })} /> -``` + }}> + {Template.bind({})} + +``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-with-selectevent.js.mdx b/docs/snippets/svelte/my-component-play-function-with-selectevent.js.mdx index b5461b9e438f..2e3912dc96ec 100644 --- a/docs/snippets/svelte/my-component-play-function-with-selectevent.js.mdx +++ b/docs/snippets/svelte/my-component-play-function-with-selectevent.js.mdx @@ -1,15 +1,15 @@ ```js // MyComponent.stories.js -import { userEvent, screen } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/svelte/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/svelte/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithSelectEvent', component: MyComponent, }; @@ -19,26 +19,27 @@ function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } +const Template = (args) => ({ + Component: MyComponent, + props: args, +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/svelte/api/csf - * to learn how to use render functions. - */ -export const ExampleChangeEvent = { - render: (args) => ({ - Component: MyComponent, - props: args, - }), - play: async () => { - const select = screen.getByRole('listbox'); - - await userEvent.selectOptions(select, ['One Item']); - await sleep(2000); - - await userEvent.selectOptions(select, ['Another Item']); - await sleep(2000); - - await userEvent.selectOptions(select, ['Yet another item']); - }, +* See https://storybook.js.org/docs/svelte/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleChangeEvent = Template.bind({}); +ExampleChangeEvent.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const select = canvas.getByRole('listbox'); + + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Yet another item']); }; ``` \ No newline at end of file diff --git a/docs/snippets/svelte/my-component-play-function-with-selectevent.mdx.mdx b/docs/snippets/svelte/my-component-play-function-with-selectevent.mdx.mdx index bba4c2db104e..db98b120d163 100644 --- a/docs/snippets/svelte/my-component-play-function-with-selectevent.mdx.mdx +++ b/docs/snippets/svelte/my-component-play-function-with-selectevent.mdx.mdx @@ -3,7 +3,7 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { userEvent, screen } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.svelte'; @@ -15,16 +15,21 @@ export const sleep(ms) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; - +export const Template= (args)=>({ + Component: MyComponent, + props: args, +}); + { - const select = screen.getByRole('listbox'); + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const select = canvas.getByRole('listbox'); await userEvent.selectOptions(select, ['One Item']); await sleep(2000); @@ -34,9 +39,7 @@ export const sleep(ms) => { await userEvent.selectOptions(select, ['Yet another item']); - }} - render={(args) => ({ - Component: MyComponent, - props: args, - })} /> + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/svelte/register-component-with-play-function.js.mdx b/docs/snippets/svelte/register-component-with-play-function.js.mdx index f30390cf6252..639acfebd827 100644 --- a/docs/snippets/svelte/register-component-with-play-function.js.mdx +++ b/docs/snippets/svelte/register-component-with-play-function.js.mdx @@ -1,50 +1,50 @@ ```js // RegistrationForm.stories.js -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import RegistrationForm from './RegistrationForm.svelte'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/svelte/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/svelte/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'RegistrationForm', component: RegistrationForm, }; +const Template = (args) => ({ + Component: RegistrationForm, + props: args, +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/svelte/api/csf - * to learn how to use render functions. - */ - -export const FilledForm = { - render: (args) => ({ - Component: RegistrationForm, - props: args, - }), - play: async () => { - const emailInput = screen.getByLabelText('email', { - selector: 'input', - }); - - await userEvent.type(emailInput, 'example-email@email.com', { - delay: 100, - }); - - const passwordInput = screen.getByLabelText('password', { - selector: 'input', - }); - - await userEvent.type(passwordInput, 'ExamplePassword', { - delay: 100, - }); - // See https://storybook.js.org/docs/7.0/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const submitButton = screen.getByRole('button'); - - await userEvent.click(submitButton); - }, +* See https://storybook.js.org/docs/svelte/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const emailInput = canvas.getByLabelText('email', { + selector: 'input', + }); + + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); + + const passwordInput = canvas.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); + + await userEvent.click(submitButton); }; ``` \ No newline at end of file diff --git a/docs/snippets/svelte/register-component-with-play-function.mdx.mdx b/docs/snippets/svelte/register-component-with-play-function.mdx.mdx index 0f7dc0717ef6..8c27461f648d 100644 --- a/docs/snippets/svelte/register-component-with-play-function.mdx.mdx +++ b/docs/snippets/svelte/register-component-with-play-function.mdx.mdx @@ -3,41 +3,44 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import RegistrationForm from './RegistrationForm.svelte'; - +export const Template = (args) => ({ + Component: RegistrationForm, + props: args, +}); + { - const emailInput = screen.getByLabelText('email', { + play={async ({ canvasElement}) => { + const canvas = within(canvasElement); + + const emailInput = canvas.getByLabelText('email', { selector: 'input', }); await userEvent.type(emailInput, 'example-email@email.com', { delay: 100, }); - const passwordInput = screen.getByLabelText('password', { + const passwordInput = canvas.getByLabelText('password', { selector: 'input', }); await userEvent.type(passwordInput, 'ExamplePassword', { delay: 100, }); - // See https://storybook.js.org/docs/7.0/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const submitButton = screen.getByRole('button'); + // See https://storybook.js.org/docs/svelte/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); await userEvent.click(submitButton); - } - render={() => ({ - component: RegistrationForm, - props: {}, - })} /> + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/vue/login-form-with-play-function.2.js.mdx b/docs/snippets/vue/login-form-with-play-function.2.js.mdx index 125d8e607521..0b352b3e3bd6 100644 --- a/docs/snippets/vue/login-form-with-play-function.2.js.mdx +++ b/docs/snippets/vue/login-form-with-play-function.2.js.mdx @@ -9,50 +9,42 @@ import LoginForm from './LoginForm.vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'Form', component: LoginForm, }; -/* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const EmptyForm = { - render: (args, { argTypes }) => ({ - components: { LoginForm }, - props: Object.keys(argTypes), - template: ``, - }), -}; +const Template = (args, { argTypes }) => ({ + components: { LoginForm }, + props: Object.keys(argTypes), + template: ``, +}); -export const FilledForm = { - render: (args, { argTypes }) => ({ - components: { LoginForm }, - props: Object.keys(argTypes), - template: ``, - }), - play: async ({ canvasElement }) => { - // Starts querying the component from its root element - const canvas = within(canvasElement); - - // πŸ‘‡ Simulate interactions with the component - await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); - - await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); - - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(canvas.getByRole('button')); - - // πŸ‘‡ Assert DOM structure - await expect( - canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!' - ) - ).toBeInTheDocument(); - }, +export const EmptyForm = Template.bind({}); + +/* +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // πŸ‘‡ Simulate interactions with the component + await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); + + await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + + // πŸ‘‡ Assert DOM structure + await expect( + canvas.getByText( + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) + ).toBeInTheDocument(); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/login-form-with-play-function.3.js.mdx b/docs/snippets/vue/login-form-with-play-function.3.js.mdx index 60c4bb89d983..a5b3cd391cd2 100644 --- a/docs/snippets/vue/login-form-with-play-function.3.js.mdx +++ b/docs/snippets/vue/login-form-with-play-function.3.js.mdx @@ -9,54 +9,44 @@ import LoginForm from './LoginForm.vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'Form', component: LoginForm, }; -/* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const EmptyForm = { - render: (args) => ({ - components: { LoginForm }, - setup() { - return args; - }, - template: '', - }), -}; - -export const FilledForm = { - render: (args) => ({ - components: { LoginForm }, - setup() { - return args; - }, - template: '', - }), - play: async ({ canvasElement }) => { - // Starts querying the component from its root element - const canvas = within(canvasElement); - - // πŸ‘‡ Simulate interactions with the component - await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); - - await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); - - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(canvas.getByRole('button')); - - // πŸ‘‡ Assert DOM structure - await expect( - canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!' - ) - ).toBeInTheDocument(); +const Template = (args) => ({ + components: { LoginForm }, + setup() { + return args; }, + template: '', +}); + +export const EmptyForm = Template.bind({}); + +/* +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // πŸ‘‡ Simulate interactions with the component + await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); + + await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + + // πŸ‘‡ Assert DOM structure + await expect( + canvas.getByText( + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) + ).toBeInTheDocument(); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/login-form-with-play-function.mdx-2.mdx b/docs/snippets/vue/login-form-with-play-function.mdx-2.mdx index a6e449bc4f20..704791f36de1 100644 --- a/docs/snippets/vue/login-form-with-play-function.mdx-2.mdx +++ b/docs/snippets/vue/login-form-with-play-function.mdx-2.mdx @@ -11,24 +11,23 @@ import LoginForm from './LoginForm.vue'; - +export const Template = (args, { argTypes }) => ({ + components: { LoginForm }, + props: Object.keys(argTypes), + template: ``, +}); - ({ - props: Object.keys(argTypes), - components: { LoginForm }, - template: ``, - })} /> + + {Template.bind({})} + + { - // Starts querying the component from its root element + play={async ({ canvasElement }) => { const canvas = within(canvasElement); // πŸ‘‡ Simulate interactions with the component @@ -36,7 +35,7 @@ import LoginForm from './LoginForm.vue'; await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel await userEvent.click(canvas.getByRole('button')); // πŸ‘‡ Assert DOM structure @@ -45,11 +44,8 @@ import LoginForm from './LoginForm.vue'; 'Everything is perfect. Your account is ready and we should probably get you started!' ) ).toBeInTheDocument(); - }} - render={(args, { argTypes }) => ({ - props: Object.keys(argTypes), - components: { LoginForm }, - template: ``, - })} /> + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/vue/login-form-with-play-function.mdx-3.mdx b/docs/snippets/vue/login-form-with-play-function.mdx-3.mdx index cc79337b989d..8f00b0064682 100644 --- a/docs/snippets/vue/login-form-with-play-function.mdx-3.mdx +++ b/docs/snippets/vue/login-form-with-play-function.mdx-3.mdx @@ -11,26 +11,25 @@ import LoginForm from './LoginForm.vue'; - +export const Template = (args) => ({ + components: { LoginForm }, + setup() { + return { args }; + }, + template: '', +}); - ({ - components: { LoginForm }, - setup() { - return { args }; - }, - template: '', - })} /> + + {Template.bind({})} + + { - // Starts querying the component from its root element const canvas = within(canvasElement); // πŸ‘‡ Simulate interactions with the component @@ -38,7 +37,7 @@ import LoginForm from './LoginForm.vue'; await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel await userEvent.click(canvas.getByRole('button')); // πŸ‘‡ Assert DOM structure @@ -47,13 +46,8 @@ import LoginForm from './LoginForm.vue'; 'Everything is perfect. Your account is ready and we should probably get you started!' ) ).toBeInTheDocument(); - }} - render={(args) => ({ - components: { LoginForm }, - setup() { - return { args }; - }, - template: '', - })} /> + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/vue/login-form-with-play-function.ts-2.ts.mdx b/docs/snippets/vue/login-form-with-play-function.ts-2.ts.mdx index 12ae56cb1dda..c694e5946114 100644 --- a/docs/snippets/vue/login-form-with-play-function.ts-2.ts.mdx +++ b/docs/snippets/vue/login-form-with-play-function.ts-2.ts.mdx @@ -7,54 +7,46 @@ import { expect } from '@storybook/jest'; import LoginForm from './LoginForm.vue'; -import type { Meta, Story } from '@storybook/vue'; +import { Meta, StoryFn } from '@storybook/vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading * to learn how to generate automatic titles */ title: 'Form', component: LoginForm, } as Meta; -/* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const EmptyForm: Story = { - render: (args, { argTypes }) => ({ - components: { LoginForm }, - props: Object.keys(argTypes), - template: ``, - }), -}; +const Template: StoryFn = (args) => ({ + components: { LoginForm }, + props: Object.keys(argTypes), + template: ``, +}); -export const FilledForm: Story = { - render: (args, { argTypes }) => ({ - components: { LoginForm }, - props: Object.keys(argTypes), - template: ``, - }), - play: async ({ canvasElement }) => { - // Starts querying the component from its root element - const canvas = within(canvasElement); - - // πŸ‘‡ Simulate interactions with the component - await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); - - await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); - - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(canvas.getByRole('button')); - - // πŸ‘‡ Assert DOM structure - await expect( - canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!' - ) - ).toBeInTheDocument(); - }, +export const EmptyForm = Template.bind({}); + +/* +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // πŸ‘‡ Simulate interactions with the component + await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); + + await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + + // πŸ‘‡ Assert DOM structure + await expect( + canvas.getByText( + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) + ).toBeInTheDocument(); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/vue/login-form-with-play-function.ts-3.ts.mdx b/docs/snippets/vue/login-form-with-play-function.ts-3.ts.mdx index 40cea12b6c72..1be96c326372 100644 --- a/docs/snippets/vue/login-form-with-play-function.ts-3.ts.mdx +++ b/docs/snippets/vue/login-form-with-play-function.ts-3.ts.mdx @@ -7,58 +7,48 @@ import { expect } from '@storybook/jest'; import LoginForm from './LoginForm.vue'; -import type { Meta, Story } from '@storybook/vue3'; +import { Meta, StoryFn } from '@storybook/vue3'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading * to learn how to generate automatic titles */ title: 'Form', component: LoginForm, } as Meta; -/* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const EmptyForm: Story = { - render: (args) => ({ - components: { LoginForm }, - setup() { - return args; - }, - template: '', - }), -}; - -export const FilledForm: Story = { - render: (args) => ({ - components: { LoginForm }, - setup() { - return args; - }, - template: '', - }), - play: async ({ canvasElement }) => { - // Starts querying the component from its root element - const canvas = within(canvasElement); - - // πŸ‘‡ Simulate interactions with the component - await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); - - await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); +const Template: StoryFn = (args) => ({ + components: { LoginForm }, + setup() { + return args; + }, + template: '', +}); - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(canvas.getByRole('button')); +export const EmptyForm = Template.bind({}); - // πŸ‘‡ Assert DOM structure - await expect( - canvas.getByText( - 'Everything is perfect. Your account is ready and we should probably get you started!' - ) - ).toBeInTheDocument(); - }, +/* +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // πŸ‘‡ Simulate interactions with the component + await userEvent.type(canvas.getByTestId('email'), 'email@provider.com'); + + await userEvent.type(canvas.getByTestId('password'), 'a-random-password'); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + + // πŸ‘‡ Assert DOM structure + await expect( + canvas.getByText( + 'Everything is perfect. Your account is ready and we should probably get you started!' + ) + ).toBeInTheDocument(); }; -``` +``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-alt-queries.js.mdx b/docs/snippets/vue/my-component-play-function-alt-queries.js.mdx index ee1cbfc0fd60..f3d7b94752e1 100644 --- a/docs/snippets/vue/my-component-play-function-alt-queries.js.mdx +++ b/docs/snippets/vue/my-component-play-function-alt-queries.js.mdx @@ -1,32 +1,33 @@ ```js // MyComponent.stories.js -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'QueryMethods', component: MyComponent, }; +const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const ExampleWithRole = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button', { name: / button label/i })); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleWithRole = Template.bind({}); +ExampleWithRole.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-alt-queries.mdx.mdx b/docs/snippets/vue/my-component-play-function-alt-queries.mdx.mdx index 5db21a34f92a..f1acd8839e7e 100644 --- a/docs/snippets/vue/my-component-play-function-alt-queries.mdx.mdx +++ b/docs/snippets/vue/my-component-play-function-alt-queries.mdx.mdx @@ -3,26 +3,29 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; - +export const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); - + { - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button', { name: / button label/i })); - }} - render={() => ({ - components: { MyComponent }, - template: '', - })} /> + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-alt-queries.ts.mdx b/docs/snippets/vue/my-component-play-function-alt-queries.ts.mdx index c177c34a853e..ebd37cb5c16e 100644 --- a/docs/snippets/vue/my-component-play-function-alt-queries.ts.mdx +++ b/docs/snippets/vue/my-component-play-function-alt-queries.ts.mdx @@ -1,10 +1,10 @@ ```ts // MyComponent.stories.ts -// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 -import type { Meta, Story } from '@storybook/vue'; +// import { Meta, StoryFn } from '@storybook/vue3'; for Vue 3 +import { Meta, StoryFn } from '@storybook/vue'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; @@ -17,20 +17,21 @@ export default { component: MyComponent, } as Meta; +const Template: StoryFn = (args) => ({ + components: { MyComponent }, + template: '', +}); + + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ - -export const ExampleWithRole: Story = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button', { name: / button label/i })); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleWithRole = Template.bind({}); +ExampleWithRole.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button', { name: / button label/i })); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-composition.js.mdx b/docs/snippets/vue/my-component-play-function-composition.js.mdx index f8476bdb8e60..d619bd74f3cc 100644 --- a/docs/snippets/vue/my-component-play-function-composition.js.mdx +++ b/docs/snippets/vue/my-component-play-function-composition.js.mdx @@ -1,54 +1,49 @@ ```js // MyComponent.stories.js -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'MyComponent', component: MyComponent, }; +const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const FirstStory = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - userEvent.type(screen.getByTestId('an-element'), 'example-value'); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FirstStory = Template.bind({}); +FirstStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.type(canvas.getByTestId('an-element'), 'example-value'); }; -export const SecondStory = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - await userEvent.type(screen.getByTestId('other-element'), 'another value'); - }, +export const SecondStory = Template.bind({}); +SecondStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.type(canvas.getByTestId('other-element'), 'another value'); }; -export const CombinedStories = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - // Runs the FirstStory and Second story play function before running this story's play function - await FirstStory.play(); - await SecondStory.play(); - await userEvent.type(screen.getByTestId('another-element'), 'random value'); - }, +export const CombinedStories = Template.bind({}); +CombinedStories.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Runs the FirstStory and Second story play function before running this story's play function + await FirstStory.play({ canvasElement }); + await SecondStory.play({ canvasElement }); + await userEvent.type(canvas.getByTestId('another-element'), 'random value'); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-composition.ts.mdx b/docs/snippets/vue/my-component-play-function-composition.ts.mdx index a51e86d8905a..11b443035fc4 100644 --- a/docs/snippets/vue/my-component-play-function-composition.ts.mdx +++ b/docs/snippets/vue/my-component-play-function-composition.ts.mdx @@ -1,58 +1,53 @@ ```ts // MyComponent.stories.ts -// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 -import type { Meta, Story } from '@storybook/vue'; +// import { Meta, StoryFn } from '@storybook/vue3'; for Vue 3 +import { Meta, StoryFn } from '@storybook/vue'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading * to learn how to generate automatic titles */ title: 'MyComponent', component: MyComponent, } as Meta; + +const Template: StoryFn = (args) => ({ + components: { MyComponent }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ - -export const FirstStory: Story = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - userEvent.type(screen.getByTestId('an-element'), 'example-value'); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FirstStory = Template.bind({}); +FirstStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.type(canvas.getByTestId('an-element'), 'example-value'); }; -export const SecondStory: Story = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - await userEvent.type(screen.getByTestId('other-element'), 'another value'); - }, +export const SecondStory = Template.bind({}); +SecondStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + await userEvent.type(canvas.getByTestId('other-element'), 'another value'); }; -export const CombinedStories: Story = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - // Runs the FirstStory and Second story play function before running this story's play function - await FirstStory.play(); - await SecondStory.play(); - await userEvent.type(screen.getByTestId('another-element'), 'random value'); - }, +export const CombinedStories = Template.bind({}); +CombinedStories.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Runs the FirstStory and Second story play function before running this story's play function + await FirstStory.play({ canvasElement }); + await SecondStory.play({ canvasElement }); + await userEvent.type(canvas.getByTestId('another-element'), 'random value'); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-query-findby.js.mdx b/docs/snippets/vue/my-component-play-function-query-findby.js.mdx index 3c2097674dc1..78c6917d7b44 100644 --- a/docs/snippets/vue/my-component-play-function-query-findby.js.mdx +++ b/docs/snippets/vue/my-component-play-function-query-findby.js.mdx @@ -1,7 +1,7 @@ ```js // MyComponent.stories.js -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; @@ -14,21 +14,22 @@ export default { component: MyComponent, }; +const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const AsyncExample = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - // Other steps +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const AsyncExample = Template.bind({}); +AsyncExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Other steps - // Waits for the component to be rendered before querying the element - await screen.findByRole('button', { name: / button label/i })); - }, + // Waits for the component to be rendered before querying the element + await canvas.findByRole('button', { name: / button label/i })); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-query-findby.mdx.mdx b/docs/snippets/vue/my-component-play-function-query-findby.mdx.mdx index 0109bc0d69b6..9323daf2addb 100644 --- a/docs/snippets/vue/my-component-play-function-query-findby.mdx.mdx +++ b/docs/snippets/vue/my-component-play-function-query-findby.mdx.mdx @@ -3,28 +3,31 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; - +export const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); + { + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + // Other steps // Waits for the component to be rendered before querying the element - await screen.findByRole('button', { name: / button label/i })); - }} - render={() => ({ - components: { MyComponent }, - template: '', - })} /> + await canvas.findByRole('button', { name: / button label/i })); + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-query-findby.ts.mdx b/docs/snippets/vue/my-component-play-function-query-findby.ts.mdx index 4b880a8ed4fb..2cfb27f211e6 100644 --- a/docs/snippets/vue/my-component-play-function-query-findby.ts.mdx +++ b/docs/snippets/vue/my-component-play-function-query-findby.ts.mdx @@ -1,10 +1,10 @@ ```js // MyComponent.stories.ts -// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 -import type { Meta, Story } from '@storybook/vue'; +// import { Meta, StoryFn } from '@storybook/vue3'; for Vue 3 +import { Meta, StoryFn } from '@storybook/vue'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; @@ -17,22 +17,22 @@ export default { component: MyComponent, } as Meta; +const Template: StoryFn = (args) => ({ + components: { MyComponent }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ - -export const AsyncExample: Story = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - // Other steps - - // Waits for the component to be rendered before querying the element - await screen.findByRole('button', { name: / button label/i })); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const AsyncExample = Template.bind({}); +AsyncExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Other steps + + // Waits for the component to be rendered before querying the element + await canvas.findByRole('button', { name: / button label/i })); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-waitfor.js.mdx b/docs/snippets/vue/my-component-play-function-waitfor.js.mdx index 824a51ce6c38..49b0f2c2dc00 100644 --- a/docs/snippets/vue/my-component-play-function-waitfor.js.mdx +++ b/docs/snippets/vue/my-component-play-function-waitfor.js.mdx @@ -1,45 +1,46 @@ ```js // MyComponent.stories.js -import { screen, userEvent, waitFor } from '@storybook/testing-library'; +import { userEvent, waitFor, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithAsync', component: MyComponent, }; +const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const ExampleAsyncStory = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - const exampleElement = screen.getByLabelText('Username', { - selector: 'input', - }); - - // The delay option set the ammount of milliseconds between characters being typed - await userEvent.type(exampleElement, 'WrongInput', { - delay: 100, - }); - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const Submit = screen.getByRole('button'); - await userEvent.click(Submit); - - await waitFor(async () => { - await userEvent.hover(screen.getByTestId('error')); - }); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleAsyncStory = Template.bind({}); +ExampleAsyncStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { + selector: 'input', + }); + + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + await userEvent.click(Submit); + + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('error')); + }); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-waitfor.mdx.mdx b/docs/snippets/vue/my-component-play-function-waitfor.mdx.mdx index b1622949bd40..6e95fd8d4c36 100644 --- a/docs/snippets/vue/my-component-play-function-waitfor.mdx.mdx +++ b/docs/snippets/vue/my-component-play-function-waitfor.mdx.mdx @@ -3,17 +3,27 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent, waitFor } from '@storybook/testing-library'; +import { userEvent, waitFor, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; +export const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); + { - const Input = screen.getByLabelText('Username', { + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { selector: 'input', }); @@ -21,16 +31,14 @@ import MyComponent from './MyComponent.vue'; delay: 100, }); - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const Submit = screen.getByRole('button'); + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); await userEvent.click(Submit); await waitFor(async () => { - await userEvent.hover(screen.getByTestId('error')); + await userEvent.hover(canvas.getByTestId('error')); }); - }} - render={() => ({ - components: { MyComponent }, - template: '', - })} /> + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-waitfor.ts.mdx b/docs/snippets/vue/my-component-play-function-waitfor.ts.mdx index 8fc40d53df67..c0e50e8ac9c4 100644 --- a/docs/snippets/vue/my-component-play-function-waitfor.ts.mdx +++ b/docs/snippets/vue/my-component-play-function-waitfor.ts.mdx @@ -1,10 +1,10 @@ ```ts // MyComponent.stories.ts -// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 -import type { Meta, Story } from '@storybook/vue'; +// import { Meta, StoryFn } from '@storybook/vue3'; for Vue 3 +import { Meta, StoryFn } from '@storybook/vue';; -import { screen, userEvent, waitFor } from '@storybook/testing-library'; +import { userEvent, waitFor, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; @@ -17,31 +17,34 @@ export default { component: MyComponent, } as Meta; + +const Template: StoryFn = (args) => ({ + components: { MyComponent }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ - -export const ExampleAsyncStory: Story = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - const Input = screen.getByLabelText('Username', { - selector: 'input', - }); - await userEvent.type(Input, 'WrongInput', { - delay: 100, - }); - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const Submit = screen.getByRole('button'); - await userEvent.click(Submit); - - await waitFor(async () => { - await userEvent.hover(screen.getByTestId('error')); - }); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleAsyncStory = Template.bind({}); +ExampleAsyncStory.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const Input = canvas.getByLabelText('Username', { + selector: 'input', + }); + + await userEvent.type(Input, 'WrongInput', { + delay: 100, + }); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + await userEvent.click(Submit); + + await waitFor(async () => { + await userEvent.hover(canvas.getByTestId('error')); + }); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-clickevent.js.mdx b/docs/snippets/vue/my-component-play-function-with-clickevent.js.mdx index c187bad1f38a..e5623dbba209 100644 --- a/docs/snippets/vue/my-component-play-function-with-clickevent.js.mdx +++ b/docs/snippets/vue/my-component-play-function-with-clickevent.js.mdx @@ -1,43 +1,41 @@ ```js // MyComponent.stories.js -import { fireEvent, screen, userEvent } from '@storybook/testing-library'; +import { fireEvent, userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'ClickExamples', component: MyComponent, }; +const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const ClickExample = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button')); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ClickExample = Template.bind({}); +ClickExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); }; -export const FireEventExample = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await fireEvent.click(screen.getByTestId('data-testid')); - }, +export const FireEventExample = Template.bind({}); +FireEventExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-clickevent.mdx.mdx b/docs/snippets/vue/my-component-play-function-with-clickevent.mdx.mdx index f0139a13bc10..6fb517a44c9e 100644 --- a/docs/snippets/vue/my-component-play-function-with-clickevent.mdx.mdx +++ b/docs/snippets/vue/my-component-play-function-with-clickevent.mdx.mdx @@ -3,37 +3,40 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { fireEvent, screen, userEvent } from '@storybook/testing-library'; +import { fireEvent, userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; - +export const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); + { - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button')); - }} - render={()=>({ - components: { MyComponent }, - template: '', - })} /> + play={async ({ canvasElement}) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); + }}> + {Template.bind({})} + { - // See https://storybook.js.org/docs/7.0/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await fireEvent.click(screen.getByTestId('data-testid')); - }} - render={()=>({ - components: { MyComponent }, - template: '', - })} /> + play={async ({ canvasElement}) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-clickevent.ts.mdx b/docs/snippets/vue/my-component-play-function-with-clickevent.ts.mdx index 0c11379e6fec..37fb7e2ee00a 100644 --- a/docs/snippets/vue/my-component-play-function-with-clickevent.ts.mdx +++ b/docs/snippets/vue/my-component-play-function-with-clickevent.ts.mdx @@ -1,47 +1,45 @@ ```ts // MyComponent.stories.ts -// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 -import type { Meta, Story } from '@storybook/vue'; +// import { Meta, Story } from '@storybook/vue3'; for Vue 3 +import { Meta, Story } from '@storybook/vue'; -import { fireEvent, screen, userEvent } from '@storybook/testing-library'; +import { fireEvent, userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading * to learn how to generate automatic titles */ title: 'ClickExamples', component: MyComponent, } as Meta; + +const Template: StoryFn = (args) => ({ + components: { MyComponent }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ - -export const ClickExample: Story = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await userEvent.click(screen.getByRole('button')); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ClickExample = Template.bind({}); +ClickExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await userEvent.click(canvas.getByRole('button')); }; -export const FireEventExample: Story = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - await fireEvent.click(screen.getByTestId('data-testid')); - }, +export const FireEventExample = Template.bind({}); +FireEventExample.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + await fireEvent.click(canvas.getByTestId('data-testid')); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-delay.js.mdx b/docs/snippets/vue/my-component-play-function-with-delay.js.mdx index f653741346ee..25885cb190fe 100644 --- a/docs/snippets/vue/my-component-play-function-with-delay.js.mdx +++ b/docs/snippets/vue/my-component-play-function-with-delay.js.mdx @@ -1,41 +1,42 @@ ```js // MyComponent.stories.js -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithDelay', component: MyComponent, }; +const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const DelayedStory = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - const exampleElement = screen.getByLabelText('example-element'); - - // The delay option set the ammount of milliseconds between characters being typed - await userEvent.type(exampleElement, 'random string', { - delay: 100, - }); - - const AnotherExampleElement = screen.getByLabelText('another-example-element'); - await userEvent.type(AnotherExampleElement, 'another random string', { - delay: 100, - }); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const DelayedStory = Template.bind({}); +DelayedStory.play = ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement= canvas.getByLabelText('example-element'); + + // The delay option set the amount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); + + const AnotherExampleElement= canvas.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-delay.mdx.mdx b/docs/snippets/vue/my-component-play-function-with-delay.mdx.mdx index b48c3eb4a727..69f9b2c21da9 100644 --- a/docs/snippets/vue/my-component-play-function-with-delay.mdx.mdx +++ b/docs/snippets/vue/my-component-play-function-with-delay.mdx.mdx @@ -3,35 +3,38 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; - +const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); + { - const exampleElement= screen.getByLabelText('example-element'); + play={async ({ canvasElement, args}) => { + const canvas = within(canvasElement); + + const exampleElement= canvas.getByLabelText('example-element'); // The delay option set the amount of milliseconds between characters being typed await userEvent.type(exampleElement, 'random string', { delay: 100, }); - const AnotherExampleElement= screen.getByLabelText('another-example-element'); + const AnotherExampleElement= canvas.getByLabelText('another-example-element'); await userEvent.type(AnotherExampleElement, 'another random string', { delay: 100, }); - }} - render={()=>({ - components: { MyComponent }, - template: '', - })} /> + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-delay.ts.mdx b/docs/snippets/vue/my-component-play-function-with-delay.ts.mdx index 3c70bff040dd..f0b5b578a900 100644 --- a/docs/snippets/vue/my-component-play-function-with-delay.ts.mdx +++ b/docs/snippets/vue/my-component-play-function-with-delay.ts.mdx @@ -1,10 +1,10 @@ ```ts // MyComponent.stories.ts -// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 -import type { Meta, Story } from '@storybook/vue'; +// import { Meta, StoryFn } from '@storybook/vue3'; for Vue 3 +import { Meta, StoryFn } from '@storybook/vue'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; @@ -17,28 +17,29 @@ export default { component: MyComponent, } as Meta; +const Template: StoryFn = (args) => ({ + components: { MyComponent }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const DelayedStory: Story = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - const exampleElement = screen.getByLabelText('example-element'); - - // The delay option set the ammount of milliseconds between characters being typed - await userEvent.type(exampleElement, 'random string', { - delay: 100, - }); - - const AnotherExampleElement = screen.getByLabelText('another-example-element'); - await userEvent.type(AnotherExampleElement, 'another random string', { - delay: 100, - }); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const DelayedStory = Template.bind({}); +DelayedStory.play = ({ canvasElement }) => { + const canvas = within(canvasElement); + + const exampleElement= canvas.getByLabelText('example-element'); + + // The delay option set the amount of milliseconds between characters being typed + await userEvent.type(exampleElement, 'random string', { + delay: 100, + }); + + const AnotherExampleElement= canvas.getByLabelText('another-example-element'); + await userEvent.type(AnotherExampleElement, 'another random string', { + delay: 100, + }); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-selectevent.js.mdx b/docs/snippets/vue/my-component-play-function-with-selectevent.js.mdx index f62f6b8b2058..b025bf3ca068 100644 --- a/docs/snippets/vue/my-component-play-function-with-selectevent.js.mdx +++ b/docs/snippets/vue/my-component-play-function-with-selectevent.js.mdx @@ -1,17 +1,18 @@ ```js // MyComponent.stories.js -import { userEvent, screen } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'WithSelectEvent', component: MyComponent, + }; // Custom function to emulate a pause @@ -19,26 +20,23 @@ function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } -/* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const ExampleChangeEvent = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - const select = screen.getByRole('listbox'); - - await userEvent.selectOptions(select, ['One Item']); - await sleep(2000); - - await userEvent.selectOptions(select, ['Another Item']); - await sleep(2000); - - await userEvent.selectOptions(select, ['Yet another item']); - }, +const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); + +export const ExampleChangeEvent = Template.bind({}); +ExampleChangeEvent.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const select = canvas.getByRole('listbox'); + + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Yet another item']); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-selectevent.mdx.mdx b/docs/snippets/vue/my-component-play-function-with-selectevent.mdx.mdx index edac1d7cd7cb..e7b10a31a94c 100644 --- a/docs/snippets/vue/my-component-play-function-with-selectevent.mdx.mdx +++ b/docs/snippets/vue/my-component-play-function-with-selectevent.mdx.mdx @@ -3,7 +3,7 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { userEvent, screen } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; @@ -15,16 +15,21 @@ export const sleep= (ms) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; - +export const Template = (args) => ({ + components: { MyComponent }, + template: '', +}); + { - const select = screen.getByRole('listbox'); + play={async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const select = canvas.getByRole('listbox'); await userEvent.selectOptions(select, ['One Item']); await sleep(2000); @@ -34,9 +39,7 @@ export const sleep= (ms) => { await userEvent.selectOptions(select, ['Yet another item']); - }} - render={()=>({ - components: { MyComponent }, - template: '', - })} /> + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/vue/my-component-play-function-with-selectevent.ts.mdx b/docs/snippets/vue/my-component-play-function-with-selectevent.ts.mdx index 88728586349f..856aa397eb5e 100644 --- a/docs/snippets/vue/my-component-play-function-with-selectevent.ts.mdx +++ b/docs/snippets/vue/my-component-play-function-with-selectevent.ts.mdx @@ -1,10 +1,10 @@ ```ts // MyComponent.stories.ts -// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 -import type { Meta, Story } from '@storybook/vue'; +// import { Meta, StoryFn } from '@storybook/vue3'; for Vue 3 +import { Meta, StoryFn } from '@storybook/vue'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import MyComponent from './MyComponent.vue'; @@ -22,27 +22,28 @@ function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } + +const Template: StoryFn = (args) => ({ + components: { MyComponent }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ - -export const ExampleChangeEvent: Story = { - render: () => ({ - components: { MyComponent }, - template: '', - }), - play: async () => { - const select = screen.getByRole('listbox'); - - await userEvent.selectOptions(select, ['One Item']); - await sleep(2000); - - await userEvent.selectOptions(select, ['Another Item']); - await sleep(2000); - - await userEvent.selectOptions(select, ['Yet another item']); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const ExampleChangeEvent = Template.bind({}); +ExampleChangeEvent.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const select = canvas.getByRole('listbox'); + + await userEvent.selectOptions(select, ['One Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Another Item']); + await sleep(2000); + + await userEvent.selectOptions(select, ['Yet another item']); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/register-component-with-play-function.js.mdx b/docs/snippets/vue/register-component-with-play-function.js.mdx index 9dc018d2ad58..9f39ad34a733 100644 --- a/docs/snippets/vue/register-component-with-play-function.js.mdx +++ b/docs/snippets/vue/register-component-with-play-function.js.mdx @@ -1,50 +1,50 @@ ```js // RegistrationForm.stories.js -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import RegistrationForm from './RegistrationForm.vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ title: 'RegistrationForm', component: RegistrationForm, }; +const Template = (args) => ({ + components: { RegistrationForm }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const FilledForm = { - render: () => ({ - components: { RegistrationForm }, - template: '', - }), - play: async () => { - const emailInput = screen.getByLabelText('email', { - selector: 'input', - }); - - await userEvent.type(emailInput, 'example-email@email.com', { - delay: 100, - }); - - const passwordInput = screen.getByLabelText('password', { - selector: 'input', - }); - - await userEvent.type(passwordInput, 'ExamplePassword', { - delay: 100, - }); - - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const submitButton = screen.getByRole('button'); - - await userEvent.click(submitButton); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const emailInput = canvas.getByLabelText('email', { + selector: 'input', + }); + + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); + + const passwordInput = canvas.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + await userEvent.click(Submit); }; ``` \ No newline at end of file diff --git a/docs/snippets/vue/register-component-with-play-function.mdx.mdx b/docs/snippets/vue/register-component-with-play-function.mdx.mdx index a77bf6f70344..64e614f23a7c 100644 --- a/docs/snippets/vue/register-component-with-play-function.mdx.mdx +++ b/docs/snippets/vue/register-component-with-play-function.mdx.mdx @@ -3,22 +3,27 @@ import { Meta, Story } from '@storybook/addon-docs'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import RegistrationForm from './RegistrationForm.vue'; - +export const Template = (args) => ({ + components: { RegistrationForm }, + template: '', +}); + { - const emailInput = screen.getByLabelText('email', { + play={ async ({ canvasElement }) => { + const canvas= within(canvasElement); + + const emailInput = canvas.getByLabelText('email', { selector: 'input', }); @@ -26,7 +31,7 @@ import RegistrationForm from './RegistrationForm.vue'; delay: 100, }); - const passwordInput = screen.getByLabelText('password', { + const passwordInput = canvas.getByLabelText('password', { selector: 'input', }); @@ -34,13 +39,10 @@ import RegistrationForm from './RegistrationForm.vue'; delay: 100, }); - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const submitButton = screen.getByRole('button'); - - await userEvent.click(submitButton); - }} - render={() => ({ - components: { RegistrationForm }, - template: '', - })} /> + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const Submit = canvas.getByRole('button'); + await userEvent.click(Submit); + }}> + {Template.bind({})} + ``` \ No newline at end of file diff --git a/docs/snippets/vue/register-component-with-play-function.ts.mdx b/docs/snippets/vue/register-component-with-play-function.ts.mdx index 4bb6bd2c4416..7b8f9e57cdde 100644 --- a/docs/snippets/vue/register-component-with-play-function.ts.mdx +++ b/docs/snippets/vue/register-component-with-play-function.ts.mdx @@ -1,52 +1,53 @@ ```ts // RegistrationForm.stories.ts -// import type { Meta, Story } from '@storybook/vue3'; for Vue 3 -import type { Meta, Story } from '@storybook/vue'; +// import { Meta, StoryFn } from '@storybook/vue3'; for Vue 3 +import { Meta, StoryFn } from '@storybook/vue'; -import { screen, userEvent } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/testing-library'; import RegistrationForm from './RegistrationForm.vue'; export default { /* πŸ‘‡ The title prop is optional. - * See https://storybook.js.org/docs/7.0/vue/configure/overview#configure-story-loading + * See https://storybook.js.org/docs/vue/configure/overview#configure-story-loading * to learn how to generate automatic titles */ title: 'RegistrationForm', component: RegistrationForm, } as Meta; +const Template: StoryFn = (args) => ({ + components: { RegistrationForm }, + template: '', +}); + /* - *πŸ‘‡ Render functions are a framework specific feature to allow you control on how the component renders. - * See https://storybook.js.org/docs/7.0/vue/api/csf - * to learn how to use render functions. - */ -export const FilledForm: Story = { - render: () => ({ - components: { RegistrationForm }, - template: '', - }), - play: async () => { - const emailInput = screen.getByLabelText('email', { - selector: 'input', - }); - - await userEvent.type(emailInput, 'example-email@email.com', { - delay: 100, - }); - - const passwordInput = screen.getByLabelText('password', { - selector: 'input', - }); - - await userEvent.type(passwordInput, 'ExamplePassword', { - delay: 100, - }); - - // See https://storybook.js.org/docs/7.0/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel - const submitButton = screen.getByRole('button'); - await userEvent.click(submitButton); - }, +* See https://storybook.js.org/docs/vue/writing-stories/play-function#working-with-the-canvas +* to learn more about using the canvasElement to query the DOM +*/ +export const FilledForm = Template.bind({}); +FilledForm.play = async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const emailInput = canvas.getByLabelText('email', { + selector: 'input', + }); + + await userEvent.type(emailInput, 'example-email@email.com', { + delay: 100, + }); + + const passwordInput = canvas.getByLabelText('password', { + selector: 'input', + }); + + await userEvent.type(passwordInput, 'ExamplePassword', { + delay: 100, + }); + + // See https://storybook.js.org/docs/vue/essentials/actions#automatically-matching-args to learn how to setup logging in the Actions panel + const submitButton = canvas.getByRole('button'); + await userEvent.click(submitButton); }; ``` \ No newline at end of file diff --git a/docs/writing-tests/importing-stories-in-tests.md b/docs/writing-tests/importing-stories-in-tests.md index ef93b2a6406b..59f5f205d8a0 100644 --- a/docs/writing-tests/importing-stories-in-tests.md +++ b/docs/writing-tests/importing-stories-in-tests.md @@ -109,7 +109,9 @@ An example of an end-to-end test with Cypress and Storybook is testing a login c 'react/login-form-with-play-function.ts.mdx', 'angular/login-form-with-play-function.ts.mdx', 'vue/login-form-with-play-function.2.js.mdx', + 'vue/login-form-with-play-function.ts-2.ts.mdx', 'vue/login-form-with-play-function.3.js.mdx', + 'vue/login-form-with-play-function.ts-3.ts.mdx', 'svelte/login-form-with-play-function.js.mdx', ]} /> @@ -151,7 +153,9 @@ A real-life scenario of user flow testing with Playwright would be how to test a 'react/login-form-with-play-function.ts.mdx', 'angular/login-form-with-play-function.ts.mdx', 'vue/login-form-with-play-function.2.js.mdx', + 'vue/login-form-with-play-function.ts-2.ts.mdx', 'vue/login-form-with-play-function.3.js.mdx', + 'vue/login-form-with-play-function.ts-3.ts.mdx', 'svelte/login-form-with-play-function.js.mdx', ]} /> diff --git a/docs/writing-tests/interaction-testing.md b/docs/writing-tests/interaction-testing.md index 03a23935c280..bbe7cc553c82 100644 --- a/docs/writing-tests/interaction-testing.md +++ b/docs/writing-tests/interaction-testing.md @@ -53,7 +53,6 @@ Update your Storybook configuration (in `.storybook/main.js|ts`) to include the The test itself is defined inside a `play` function connected to a story. Here's an example of how to set up an interaction test with Storybook and the `play` function: - `userEvent.type(await within(canvasElement).getByRole('my-input'),'Some text');` | | `unhover` | Unhovers out of element
`userEvent.unhover(await within(canvasElement).getByLabelText(/Example/i));` | -### Group interactions with the `step` function - -For complex flows, it can be worthwhile to group sets of related interactions together using the `step` function. This allows you to provide a custom label that describes a set of interactions: - - - - - - - -This will show your interactions nested in a collapsible group: - -![Interaction testing with labeled steps](./storybook-addon-interactions-steps.png) - ### Interactive debugger If you check your interactions panel, you'll see the step-by-step flow. It also offers a handy set of UI controls to pause, resume, rewind, and step through each interaction.