-
Notifications
You must be signed in to change notification settings - Fork 0
/
use-promise.test.tsx
113 lines (87 loc) · 3.16 KB
/
use-promise.test.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import React from 'react';
import { usePromise } from '../src/index';
import {
render,
cleanup,
waitForDomChange,
Matcher,
act,
} from '@testing-library/react';
describe('usePromise tests', () => {
afterEach(cleanup);
type Props = {
promise: (() => Promise<any>) | Promise<any>;
initialValue: any;
};
const errorToString = (error: string | Error) =>
error instanceof Error ? error.message : error.toString();
function HookTester({ promise, initialValue }: Props) {
const [value, error] = usePromise(promise, initialValue);
return !error ? value : errorToString(error);
}
function renderHookTest(promise: Props['promise']) {
return render(<HookTester promise={promise} initialValue={'loading...'} />);
}
async function testAssertions(
getByText: (text: Matcher) => HTMLElement,
expected: string
) {
getByText('loading...');
await waitForDomChange();
getByText(expected);
}
describe('passing an async function', () => {
it('updates the value when the promise resolves', async () => {
const { getByText } = renderHookTest(() => Promise.resolve('success!'));
await testAssertions(getByText, 'success!');
});
it('updates the error with the rejection reason when the promise is rejected', async () => {
const { getByText } = renderHookTest(() => Promise.reject('epic fail!'));
await testAssertions(getByText, 'epic fail!');
});
it('the async function is called only once, even after re-rendering', async () => {
const asyncFunction = jest.fn(() => Promise.resolve('success!'));
const { getByText, rerender } = render(
<HookTester promise={asyncFunction} initialValue={'loading...'} />
);
await waitForDomChange();
getByText('success!');
rerender(
<HookTester promise={asyncFunction} initialValue={'loading...'} />
);
rerender(
<HookTester promise={asyncFunction} initialValue={'loading...'} />
);
expect(asyncFunction).toHaveBeenCalledTimes(1);
getByText('success!');
});
it('the async function is called only twice, if we re-render with new props once', async () => {
const asyncFunction = jest.fn(() => Promise.resolve('success!'));
const { getByText, rerender } = render(
<HookTester promise={asyncFunction} initialValue={'loading...'} />
);
await waitForDomChange();
getByText('success!');
await act(async () => {
rerender(
<HookTester
promise={asyncFunction}
initialValue={'extra loading...'}
/>
);
});
expect(asyncFunction).toHaveBeenCalledTimes(2);
getByText('success!');
});
});
describe('passing a promise', () => {
it('updates the value when the promise resolves', async () => {
const { getByText } = renderHookTest(Promise.resolve('success!'));
await testAssertions(getByText, 'success!');
});
it('it updates the error with the rejection reason when the promise is rejected', async () => {
const { getByText } = renderHookTest(Promise.reject('epic fail!'));
await testAssertions(getByText, 'epic fail!');
});
});
});