Skip to content

Commit

Permalink
Merge pull request #430 from storybookjs/yann/update-example-to-sb-8
Browse files Browse the repository at this point in the history
Update internal example to Storybook 8
  • Loading branch information
yannbf committed Jan 24, 2024
2 parents 2b22464 + ad09521 commit a3c9fb6
Show file tree
Hide file tree
Showing 4 changed files with 990 additions and 2,136 deletions.
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
"@storybook/addon-coverage": "^0.0.9",
"@storybook/addon-essentials": "^7.5.3",
"@storybook/addon-interactions": "^7.5.3",
"@storybook/react": "^7.5.3",
"@storybook/react-vite": "^7.5.3",
"@storybook/test": "^7.5.3",
"@storybook/addon-essentials": "next",
"@storybook/addon-interactions": "next",
"@storybook/react": "next",
"@storybook/react-vite": "next",
"@storybook/test": "next",
"@types/jest": "^29.0.0",
"@types/node": "^16.4.1",
"@vitejs/plugin-react": "^4.0.3",
Expand All @@ -76,7 +76,7 @@
"react-dom": "^17.0.1",
"rimraf": "^3.0.2",
"semver": "^7.5.4",
"storybook": "^7.5.3",
"storybook": "next",
"ts-jest": "^29.0.0",
"tsup": "^6.5.0",
"typescript": "~4.9.4",
Expand Down
202 changes: 108 additions & 94 deletions stories/atoms/Button.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { expect } from '@storybook/test';
import { within, waitFor, userEvent, waitForElementToBeRemoved } from '@storybook/test';
import { fn, expect, within, waitFor, userEvent, waitForElementToBeRemoved } from '@storybook/test';

import { isTestRunner } from '../../.storybook/is-test-runner';

Expand Down Expand Up @@ -34,108 +33,123 @@ export const Secondary: Story = {
},
};

export const Demo = (args) => (
<button type="button" onClick={() => args.onSubmit('clicked')}>
Click
</button>
);
Demo.argTypes = {
onSubmit: { action: true },
};
Demo.play = async ({ args, canvasElement }) => {
await userEvent.click(within(canvasElement).getByRole('button'));
await expect(args.onSubmit).toHaveBeenCalledWith(expect.stringMatching(/([A-Z])\w+/gi));
};

export const FindBy = (args) => {
const [isLoading, setIsLoading] = React.useState(true);
React.useEffect(() => {
setTimeout(() => setIsLoading(false), 500);
}, []);
return isLoading ? <div>Loading...</div> : <button type="button">Loaded!</button>;
};
FindBy.play = async ({ canvasElement }) => {
const canvas = within(canvasElement);
await canvas.findByRole('button');
await expect(true).toBe(true);
};

export const WaitFor = (args) => (
<button type="button" onClick={() => setTimeout(() => args.onSubmit('clicked'), 100)}>
Click
</button>
);
WaitFor.argTypes = Demo.argTypes;
WaitFor.play = async ({ args, canvasElement }) => {
await userEvent.click(await within(canvasElement).findByText('Click'));
await waitFor(async () => {
export const Demo = {
render: (args) => (
<button type="button" onClick={() => args.onSubmit('clicked')}>
Click
</button>
),
args: {
onSubmit: fn(),
},
play: async ({ args, canvasElement }) => {
await userEvent.click(within(canvasElement).getByRole('button'));
await expect(args.onSubmit).toHaveBeenCalledWith(expect.stringMatching(/([A-Z])\w+/gi));
await expect(true).toBe(true);
});
},
};

export const WaitForElementToBeRemoved = () => {
const [isLoading, setIsLoading] = React.useState(true);
React.useEffect(() => {
setTimeout(() => setIsLoading(false), 1500);
}, []);
return isLoading ? <div>Loading...</div> : <button type="button">Loaded!</button>;
};
WaitForElementToBeRemoved.play = async ({ canvasElement }) => {
const canvas = within(canvasElement);
await waitForElementToBeRemoved(await canvas.findByText('Loading...'), { timeout: 2000 });
const button = await canvas.findByText('Loaded!');
await expect(button).not.toBeNull();
export const FindBy = {
render: () => {
const [isLoading, setIsLoading] = React.useState(true);
React.useEffect(() => {
setTimeout(() => setIsLoading(false), 500);
}, []);
return isLoading ? <div>Loading...</div> : <button type="button">Loaded!</button>;
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await canvas.findByRole('button');
await expect(true).toBe(true);
},
};

export const WithLoaders = (args, { loaded: { todo } }) => {
return (
<button type="button" onClick={args.onSubmit(todo.title)}>
Todo: {todo.title}
export const WaitFor = {
render: (args) => (
<button type="button" onClick={() => setTimeout(() => args.onSubmit('clicked'), 100)}>
Click
</button>
);
),
args: Demo.args,
play: async ({ args, canvasElement }) => {
await userEvent.click(await within(canvasElement).findByText('Click'));
await waitFor(async () => {
await expect(args.onSubmit).toHaveBeenCalledWith(expect.stringMatching(/([A-Z])\w+/gi));
await expect(true).toBe(true);
});
},
};
WithLoaders.argTypes = Demo.argTypes;
WithLoaders.loaders = [
async () => {
// long fake timeout
await new Promise((resolve) => setTimeout(resolve, 2000));

return {
todo: {
userId: 1,
id: 1,
title: 'delectus aut autem',
completed: false,
},
};

export const WaitForElementToBeRemoved = {
render: () => {
const [isLoading, setIsLoading] = React.useState(true);
React.useEffect(() => {
setTimeout(() => setIsLoading(false), 1500);
}, []);
return isLoading ? <div>Loading...</div> : <button type="button">Loaded!</button>;
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await waitForElementToBeRemoved(await canvas.findByText('Loading...'), { timeout: 2000 });
const button = await canvas.findByText('Loaded!');
await expect(button).not.toBeNull();
},
];
WithLoaders.play = async ({ args, canvasElement }) => {
const canvas = within(canvasElement);
const todoItem = await canvas.findByText('Todo: delectus aut autem');
await userEvent.click(todoItem);
await expect(args.onSubmit).toHaveBeenCalledWith('delectus aut autem');
};

export const UserAgent = () => (
<div>
<p>
<strong>isTestRunner:</strong> {isTestRunner().toString()}
</p>
<p>
<strong>User agent:</strong> {window.navigator.userAgent}
</p>
</div>
);
UserAgent.play = async () => {
if (isTestRunner()) {
await expect(window.navigator.userAgent).toContain('StorybookTestRunner');
}
export const WithLoaders = {
render: (args, { loaded: { todo } }) => {
return (
<button type="button" onClick={args.onSubmit(todo.title)}>
Todo: {todo.title}
</button>
);
},
args: Demo.args,
loaders: [
async () => {
// long fake timeout
await new Promise((resolve) => setTimeout(resolve, 1000));

return {
todo: {
userId: 1,
id: 1,
title: 'delectus aut autem',
completed: false,
},
};
},
],

play: async ({ args, canvasElement }) => {
const canvas = within(canvasElement);
const todoItem = await canvas.findByText('Todo: delectus aut autem');
await userEvent.click(todoItem);
await expect(args.onSubmit).toHaveBeenCalledWith('delectus aut autem');
},
};
UserAgent.parameters = {
tests: {
skip: true,
disableSnapshots: true,

export const UserAgent = {
render: () => (
<div>
<p>
<strong>isTestRunner:</strong> {isTestRunner().toString()}
</p>
<p>
<strong>User agent:</strong> {window.navigator.userAgent}
</p>
</div>
),

play: async () => {
if (isTestRunner()) {
await expect(window.navigator.userAgent).toContain('StorybookTestRunner');
}
},

parameters: {
tests: {
skip: true,
disableSnapshots: true,
},
},
};
20 changes: 10 additions & 10 deletions stories/expected-failures/Failure.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ export default {
component: Page,
};

const Template = (args) => <Page {...args} />;

export const ComponentLogsErrors = () => {
console.error('Console error with a failure');
return <div>Hello world</div>;
Expand All @@ -19,14 +17,16 @@ export const ComponentThrowsErrors = () => {
throw new Error('Component has a failure');
};

export const PlayFnThrowsErrors = Template.bind({});
PlayFnThrowsErrors.play = () => {
throw new Error('Play function has a failure');
export const PlayFnThrowsErrors = {
play: () => {
throw new Error('Play function has a failure');
},
};

export const PlayFnAssertionFails = Template.bind({});
PlayFnAssertionFails.play = async ({ canvasElement }) => {
const canvas = within(canvasElement);
const unexistentButton = await canvas.getByRole('button', { name: /I do not exist/i });
await userEvent.click(unexistentButton);
export const PlayFnAssertionFails = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const unexistentButton = await canvas.getByRole('button', { name: /I do not exist/i });
await userEvent.click(unexistentButton);
},
};

0 comments on commit a3c9fb6

Please sign in to comment.