Skip to content

Commit 0f93c98

Browse files
committed
feat: Add renderHook
1 parent d8c6b4d commit 0f93c98

File tree

2 files changed

+91
-1
lines changed

2 files changed

+91
-1
lines changed

src/__tests__/renderHook.js

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import React from 'react'
2+
import {renderHook} from '../pure'
3+
4+
test('gives comitted result', () => {
5+
const {result} = renderHook(() => {
6+
const [state, setState] = React.useState(1)
7+
8+
React.useEffect(() => {
9+
setState(2)
10+
}, [])
11+
12+
return [state, setState]
13+
})
14+
15+
expect(result.current).toEqual([2, expect.any(Function)])
16+
})
17+
18+
test('allows rerendering', () => {
19+
const {result, rerender} = renderHook(
20+
({branch}) => {
21+
const [left, setLeft] = React.useState('left')
22+
const [right, setRight] = React.useState('right')
23+
24+
// eslint-disable-next-line jest/no-if
25+
switch (branch) {
26+
case 'left':
27+
return [left, setLeft]
28+
case 'right':
29+
return [right, setRight]
30+
31+
default:
32+
throw new Error(
33+
'No Props passed. This is a bug in the implementation',
34+
)
35+
}
36+
},
37+
{initialProps: {branch: 'left'}},
38+
)
39+
40+
expect(result.current).toEqual(['left', expect.any(Function)])
41+
42+
rerender({branch: 'right'})
43+
44+
expect(result.current).toEqual(['right', expect.any(Function)])
45+
})
46+
47+
test('allows wrapper components', async () => {
48+
const Context = React.createContext('default')
49+
function Wrapper({children}) {
50+
return <Context.Provider value="provided">{children}</Context.Provider>
51+
}
52+
const {result} = renderHook(
53+
() => {
54+
return React.useContext(Context)
55+
},
56+
{
57+
wrapper: Wrapper,
58+
},
59+
)
60+
61+
expect(result.current).toEqual('provided')
62+
})

src/pure.js

+29-1
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,37 @@ function cleanup() {
232232
mountedContainers.clear()
233233
}
234234

235+
function renderHook(renderCallback, options = {}) {
236+
const {initialProps, wrapper} = options
237+
const result = React.createRef()
238+
239+
function TestComponent({renderCallbackProps}) {
240+
const renderResult = renderCallback(renderCallbackProps)
241+
242+
React.useEffect(() => {
243+
result.current = renderResult
244+
})
245+
246+
return null
247+
}
248+
249+
const {rerender: baseRerender, unmount} = render(
250+
<TestComponent renderCallbackProps={initialProps} />,
251+
{wrapper},
252+
)
253+
254+
function rerender(rerenderCallbackProps) {
255+
return baseRerender(
256+
<TestComponent renderCallbackProps={rerenderCallbackProps} />,
257+
)
258+
}
259+
260+
return {result, rerender, unmount}
261+
}
262+
235263
// just re-export everything from dom-testing-library
236264
export * from '@testing-library/dom'
237-
export {render, cleanup, act, fireEvent}
265+
export {render, renderHook, cleanup, act, fireEvent}
238266

239267
// NOTE: we're not going to export asyncAct because that's our own compatibility
240268
// thing for people using [email protected]. Anyone else doesn't need it and

0 commit comments

Comments
 (0)