Skip to content

Commit

Permalink
Merge pull request #89 from zenoplex/test/use-async-tracker-story
Browse files Browse the repository at this point in the history
Test: Add interaction test for use async tracker
  • Loading branch information
zenoplex committed Jun 10, 2023
2 parents c632b5f + 8eb6e4f commit 64c23fb
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 0 deletions.
1 change: 1 addition & 0 deletions apps/workshop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"test:storybook": "test-storybook"
},
"dependencies": {
"@gen/use-async-tracker": "*",
"@gen/use-image": "*",
"@gen/use-pagination": "*",
"@gen/use-pdf-canvas": "*",
Expand Down
59 changes: 59 additions & 0 deletions apps/workshop/src/stories/UseAsyncTracker.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import type { Meta, StoryObj } from '@storybook/react';

import { userEvent, waitFor, within } from '@storybook/testing-library';
import { expect } from '@storybook/jest';
import { UseAsyncTracker } from './UseAsyncTracker';
import { sleep } from './sleep';

const meta = {
component: UseAsyncTracker,
} satisfies Meta<typeof UseAsyncTracker>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
play: async ({ canvasElement }) => {
await sleep();
const canvas = within(canvasElement);

expect(canvas.getByTestId('global-count').textContent).toBe(
'Global count: 0'
);
expect(canvas.getByTestId('other-count').textContent).toBe(
'Other count: 0'
);

await userEvent.click(canvas.getByText('load other 2'));
await waitFor(() => {
expect(canvas.getByTestId('other-count').textContent).toBe(
'Other count: 1'
);
expect(canvas.getByText('loading...')).toBeDisabled();
});
await waitFor(
() => {
expect(canvas.getByTestId('other-count').textContent).toBe(
'Other count: 0'
);
},
{ timeout: 5000 }
);

await userEvent.click(canvas.getByText('load global'));
await waitFor(() => {
expect(canvas.getByTestId('global-count').textContent).toBe(
'Global count: 1'
);
expect(canvas.getByText('loading...')).toBeDisabled();
});
await waitFor(
() => {
expect(canvas.getByTestId('global-count').textContent).toBe(
'Global count: 0'
);
},
{ timeout: 5000 }
);
},
};
73 changes: 73 additions & 0 deletions apps/workshop/src/stories/UseAsyncTracker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from 'react';
import createContext from '@gen/use-async-tracker';

const { useAsyncTracker, Provider } = createContext({ global: 0, other: 0 });

const wait = async (ms = 1000): Promise<void> =>
new Promise((resolve) => setTimeout(resolve, ms));

const Second: React.FC = () => {
const [count, trackAsync] = useAsyncTracker((store) => store.other);

const handleClick = async (): Promise<void> => {
await trackAsync(wait(), 'other');
};
return (
<div className="bg-slate-200">
<div data-testid="other-count">Other count: {count}</div>
<button disabled={count > 0} onClick={() => void handleClick()}>
{count > 0 ? 'loading...' : 'load other'}
</button>
</div>
);
};

const First: React.FC = () => {
const [count, trackAsync] = useAsyncTracker((store) => store.global);

const handleClick = async (): Promise<void> => {
await trackAsync(wait(), 'global');
};

return (
<div>
<div data-testid="global-count">Global count: {count}</div>
<div>
<button disabled={count > 0} onClick={() => void handleClick()}>
{count > 0 ? 'loading...' : 'load global'}
</button>
</div>
</div>
);
};

const Buttons: React.FC = () => {
const [, trackAsync] = useAsyncTracker((store) => store.global);

const handleClick: React.MouseEventHandler<HTMLButtonElement> = (e) => {
const { value } = e.currentTarget;
if (value !== 'global' && value !== 'other') return;
void trackAsync(wait(), value);
};

return (
<div className="flex flex-col items-start">
<button value="global" onClick={handleClick}>
load global 2
</button>
<button value="other" onClick={handleClick}>
load other 2
</button>
</div>
);
};

export const UseAsyncTracker: React.FC = () => {
return (
<Provider>
<First />
<Second />
<Buttons />
</Provider>
);
};
10 changes: 10 additions & 0 deletions apps/workshop/src/stories/sleep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Sleep for a given number of milliseconds.
* Sometimes play function plays too fast that userEvent doesn't seem to work as intended.
* https://github.com/storybookjs/storybook/issues/18258
*
* @param ms milliseconds to sleep
* @returns Promise<void>
*/
export const sleep = (ms = 100): Promise<void> =>
new Promise((resolve) => setTimeout(resolve, ms));
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 64c23fb

Please sign in to comment.