Skip to content

Commit 599135f

Browse files
authored
Merge pull request #11 from mpeyper/async-updates
Add `waitForNextUpdate` promise for testing async updates Resolves #10
2 parents e4853f3 + 6e627c8 commit 599135f

File tree

8 files changed

+98
-58
lines changed

8 files changed

+98
-58
lines changed

Diff for: .babelrc

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"@babel/react"
55
],
66
"plugins": [
7+
"@babel/plugin-transform-runtime",
78
"@babel/proposal-object-rest-spread",
89
["module-resolver", { "alias": { "src": "./src" } }],
910
"@babel/transform-modules-commonjs"

Diff for: README.md

+3
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ const useTheme = (initialTheme) => {
7777
}
7878
return useMemo(() => ({ ...themes[theme], toggleTheme }), [theme])
7979
}
80+
```
8081

82+
```js
8183
// useTheme.test.js
8284
import { renderHook, cleanup, act } from 'react-hooks-testing-library'
8385

@@ -152,6 +154,7 @@ Renders a test component that will call the provided `callback`, including any h
152154

153155
- `result` (`object`)
154156
- `current` (`any`) - the return value of the `callback` function
157+
- `waitForNextUpdate` (`function`) - returns a `Promise` that resolves the next time the hook renders, commonly when state is updated as the result of a asynchronous action.
155158
- `rerender` (`function([newProps])`) - function to rerender the test component including any hooks called in the `callback` function. If `newProps` are passed, the will replace the `initialProps` passed the the `callback` function for future renders.
156159
- `unmount` (`function()`) - function to unmount the test component, commonly used to trigger cleanup effects for `useEffect` hooks.
157160

Diff for: package-lock.json

+15-55
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@
2727
"contributors:add": "all-contributors add"
2828
},
2929
"dependencies": {
30+
"@babel/runtime": "^7.3.4",
3031
"react-testing-library": "^6.0.0"
3132
},
3233
"devDependencies": {
3334
"@babel/cli": "^7.2.3",
3435
"@babel/core": "^7.3.4",
3536
"@babel/plugin-proposal-object-rest-spread": "^7.3.4",
3637
"@babel/plugin-transform-modules-commonjs": "^7.2.0",
38+
"@babel/plugin-transform-runtime": "^7.3.4",
3739
"@babel/preset-env": "^7.3.4",
3840
"@babel/preset-react": "^7.0.0",
3941
"@types/react": "^16.8.5",
@@ -44,16 +46,13 @@
4446
"eslint": "^5.14.1",
4547
"eslint-config-prettier": "^4.0.0",
4648
"eslint-plugin-prettier": "^3.0.1",
47-
"fetch-mock": "^7.3.1",
4849
"husky": "^1.3.1",
4950
"jest": "^24.1.0",
5051
"lint-staged": "^8.1.4",
51-
"node-fetch": "^2.3.0",
5252
"prettier": "^1.16.4",
5353
"prettier-eslint": "^8.8.2",
5454
"prettier-eslint-cli": "^4.7.1",
5555
"react": "^16.8.3",
56-
"react-async": "^5.1.0",
5756
"react-dom": "^16.8.3",
5857
"typescript": "^3.3.3333",
5958
"typings-tester": "^0.3.2"

Diff for: src/index.js

+7
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,17 @@ function TestHook({ callback, hookProps, children }) {
99
function renderHook(callback, { initialProps, ...options } = {}) {
1010
const result = { current: null }
1111
const hookProps = { current: initialProps }
12+
const resolvers = []
13+
const waitForNextUpdate = () =>
14+
new Promise((resolve) => {
15+
resolvers.push(resolve)
16+
})
1217

1318
const toRender = () => (
1419
<TestHook callback={callback} hookProps={hookProps.current}>
1520
{(res) => {
1621
result.current = res
22+
resolvers.splice(0, resolvers.length).forEach((resolve) => resolve())
1723
}}
1824
</TestHook>
1925
)
@@ -22,6 +28,7 @@ function renderHook(callback, { initialProps, ...options } = {}) {
2228

2329
return {
2430
result,
31+
waitForNextUpdate,
2532
unmount,
2633
rerender: (newProps = hookProps.current) => {
2734
hookProps.current = newProps

Diff for: test/asyncHook.test.js

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { useState, useEffect } from 'react'
2+
import { renderHook, cleanup } from 'src'
3+
4+
describe('async hook tests', () => {
5+
const getSomeName = () => Promise.resolve('Betty')
6+
7+
const useName = (prefix) => {
8+
const [name, setName] = useState('nobody')
9+
10+
useEffect(() => {
11+
getSomeName().then((theName) => {
12+
setName(prefix ? `${prefix} ${theName}` : theName)
13+
})
14+
}, [prefix])
15+
16+
return name
17+
}
18+
19+
afterEach(cleanup)
20+
21+
test('should wait for next update', async () => {
22+
const { result, waitForNextUpdate } = renderHook(() => useName())
23+
24+
expect(result.current).toBe('nobody')
25+
26+
await waitForNextUpdate()
27+
28+
expect(result.current).toBe('Betty')
29+
})
30+
31+
test('should wait for multiple updates', async () => {
32+
const { result, waitForNextUpdate, rerender } = renderHook(({ prefix }) => useName(prefix), {
33+
initialProps: { prefix: 'Mrs.' }
34+
})
35+
36+
expect(result.current).toBe('nobody')
37+
38+
await waitForNextUpdate()
39+
40+
expect(result.current).toBe('Mrs. Betty')
41+
42+
rerender({ prefix: 'Ms.' })
43+
44+
await waitForNextUpdate()
45+
46+
expect(result.current).toBe('Ms. Betty')
47+
})
48+
49+
test('should resolve all when updating', async () => {
50+
const { result, waitForNextUpdate } = renderHook(({ prefix }) => useName(prefix), {
51+
initialProps: { prefix: 'Mrs.' }
52+
})
53+
54+
expect(result.current).toBe('nobody')
55+
56+
await Promise.all([waitForNextUpdate(), waitForNextUpdate(), waitForNextUpdate()])
57+
58+
expect(result.current).toBe('Mrs. Betty')
59+
})
60+
})

Diff for: test/typescript/renderHook.ts

+9
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,12 @@ function checkTypesWhenHookReturnsVoid() {
6464
const _unmount: () => boolean = unmount
6565
const _rerender: () => void = rerender
6666
}
67+
68+
async function checkTypesForWaitForNextUpdate() {
69+
const { waitForNextUpdate } = renderHook(() => {})
70+
71+
await waitForNextUpdate()
72+
73+
// check type
74+
const _waitForNextUpdate: () => Promise<void> = waitForNextUpdate
75+
}

Diff for: typings/index.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export function renderHook<P, R>(
99
readonly result: {
1010
current: R
1111
}
12+
readonly waitForNextUpdate: () => Promise<void>
1213
readonly unmount: RenderResult['unmount']
1314
readonly rerender: (hookProps?: P) => void
1415
}

0 commit comments

Comments
 (0)