Skip to content

Commit 7099f8b

Browse files
committed
add tests for params updates + race condition handling
1 parent 3312cd8 commit 7099f8b

File tree

1 file changed

+98
-4
lines changed

1 file changed

+98
-4
lines changed

test/useAsync.test.ts

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,35 @@
11
import { useAsync } from '../src';
22
import { renderHook } from '@testing-library/react-hooks';
33

4+
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
5+
46
interface StarwarsHero {
57
name: string;
68
}
79

8-
export const generateMockResponseData = (amount: number = 5): StarwarsHero[] =>
10+
export const generateFakeResults = (pageSize: number = 5): StarwarsHero[] =>
911
// @ts-ignore
10-
[...Array(amount).keys()].map(n => ({
12+
[...Array(pageSize).keys()].map(n => ({
1113
id: n + 1,
1214
name: `Starwars Hero ${n + 1}`,
1315
}));
1416

17+
export const generateFakeResultsAsync = async (
18+
pageSize: number = 5,
19+
delay = 100
20+
): Promise<StarwarsHero[]> => {
21+
await sleep(delay);
22+
return generateFakeResults(pageSize);
23+
};
24+
1525
describe('useAync', () => {
16-
const fakeResults = generateMockResponseData();
26+
const fakeResults = generateFakeResults();
1727

1828
it('should have a useAsync hook', () => {
1929
expect(useAsync).toBeDefined();
2030
});
2131

22-
it('should resolve a successful request', async () => {
32+
it('should resolve a successful resolved promise', async () => {
2333
const onSuccess = jest.fn();
2434
const onError = jest.fn();
2535

@@ -47,6 +57,90 @@ describe('useAync', () => {
4757
expect(onError).not.toHaveBeenCalled();
4858
});
4959

60+
it('should resolve a successful real-world request + handle params update', async () => {
61+
const onSuccess = jest.fn();
62+
const onError = jest.fn();
63+
64+
const { result, waitForNextUpdate, rerender } = renderHook(
65+
({ pageSize }: { pageSize: number }) =>
66+
useAsync(() => generateFakeResultsAsync(pageSize), [pageSize], {
67+
onSuccess: () => onSuccess(),
68+
onError: () => onError(),
69+
}),
70+
{
71+
initialProps: { pageSize: 5 },
72+
}
73+
);
74+
75+
expect(result.current.loading).toBe(true);
76+
await waitForNextUpdate();
77+
expect(result.current.result).toEqual(generateFakeResults(5));
78+
expect(result.current.loading).toBe(false);
79+
expect(result.current.error).toBeUndefined();
80+
expect(onSuccess).toHaveBeenCalledTimes(1);
81+
expect(onError).not.toHaveBeenCalled();
82+
83+
rerender({
84+
pageSize: 6,
85+
});
86+
87+
expect(result.current.loading).toBe(true);
88+
await waitForNextUpdate();
89+
expect(result.current.result).toEqual(generateFakeResults(6));
90+
expect(result.current.loading).toBe(false);
91+
expect(result.current.error).toBeUndefined();
92+
expect(onSuccess).toHaveBeenCalledTimes(2);
93+
expect(onError).not.toHaveBeenCalled();
94+
});
95+
96+
it('should resolve a successful real-world requests with potential race conditions', async () => {
97+
const onSuccess = jest.fn();
98+
const onError = jest.fn();
99+
100+
const { result, waitForNextUpdate, rerender } = renderHook(
101+
({ pageSize, delay }: { pageSize: number; delay: number }) =>
102+
useAsync(
103+
() => generateFakeResultsAsync(pageSize, delay),
104+
[pageSize, delay],
105+
{
106+
onSuccess: () => onSuccess(),
107+
onError: () => onError(),
108+
}
109+
),
110+
{
111+
initialProps: { pageSize: 5, delay: 200 },
112+
}
113+
);
114+
115+
rerender({
116+
pageSize: 6,
117+
delay: 100,
118+
});
119+
120+
rerender({
121+
pageSize: 7,
122+
delay: 0,
123+
});
124+
125+
expect(result.current.loading).toBe(true);
126+
await waitForNextUpdate();
127+
expect(result.current.result).toEqual(generateFakeResults(7));
128+
expect(result.current.loading).toBe(false);
129+
expect(result.current.error).toBeUndefined();
130+
expect(onSuccess).toHaveBeenCalledTimes(1);
131+
expect(onError).not.toHaveBeenCalled();
132+
133+
await sleep(100);
134+
expect(onSuccess).toHaveBeenCalledTimes(2);
135+
136+
await sleep(100);
137+
expect(onSuccess).toHaveBeenCalledTimes(3);
138+
139+
expect(result.current.result).toEqual(generateFakeResults(7));
140+
expect(result.current.loading).toBe(false);
141+
expect(result.current.error).toBeUndefined();
142+
});
143+
50144
// Test added because Jest mocks can return promises that arre not instances of Promises
51145
// This test ensures better testability of user code
52146
// See https://github.com/slorber/react-async-hook/issues/24

0 commit comments

Comments
 (0)