Skip to content

Commit 6388adf

Browse files
donavonKent C. Dodds
authored and
Kent C. Dodds
committed
feat(testHook): add testHook utility for Testing custom hooks 🎣 (#274)
1 parent 14b567f commit 6388adf

File tree

8 files changed

+119
-20
lines changed

8 files changed

+119
-20
lines changed

.all-contributorsrc

+12
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,18 @@
615615
"contributions": [
616616
"code"
617617
]
618+
},
619+
{
620+
"login": "donavon",
621+
"name": "Donavon West",
622+
"avatar_url": "https://avatars3.githubusercontent.com/u/887639?v=4",
623+
"profile": "http://donavon.com",
624+
"contributions": [
625+
"code",
626+
"doc",
627+
"ideas",
628+
"test"
629+
]
618630
}
619631
]
620632
}

README.md

+18-17
Large diffs are not rendered by default.

examples/__tests__/react-hooks.js

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import {testHook, cleanup} from 'react-testing-library'
2+
3+
import useCounter from '../react-hooks'
4+
5+
afterEach(cleanup)
6+
7+
test('accepts default initial values', () => {
8+
let count
9+
testHook(() => ({count} = useCounter()))
10+
11+
expect(count).toBe(0)
12+
})
13+
14+
test('accepts a default initial value for `count`', () => {
15+
let count
16+
testHook(() => ({count} = useCounter({})))
17+
18+
expect(count).toBe(0)
19+
})
20+
21+
test('provides an `increment` function', () => {
22+
let count, increment
23+
testHook(() => ({count, increment} = useCounter({step: 2})))
24+
25+
expect(count).toBe(0)
26+
increment()
27+
expect(count).toBe(2)
28+
})
29+
30+
test('provides an `decrement` function', () => {
31+
let count, decrement
32+
testHook(() => ({count, decrement} = useCounter({step: 2})))
33+
34+
expect(count).toBe(0)
35+
decrement()
36+
expect(count).toBe(-2)
37+
})
38+
39+
test('accepts a default initial value for `step`', () => {
40+
let count, increment
41+
testHook(() => ({count, increment} = useCounter({})))
42+
43+
expect(count).toBe(0)
44+
increment()
45+
expect(count).toBe(1)
46+
})

examples/react-hooks.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import {useState} from 'react'
2+
3+
function useCounter({initialCount = 0, step = 1} = {}) {
4+
const [count, setCount] = useState(initialCount)
5+
const increment = () => setCount(c => c + step)
6+
const decrement = () => setCount(c => c - step)
7+
return {count, increment, decrement}
8+
}
9+
10+
export default useCounter

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,16 @@
4848
"jest-dom": "^2.0.4",
4949
"jest-in-case": "^1.0.2",
5050
"kcd-scripts": "^0.44.0",
51-
"react": "^16.5.2",
52-
"react-dom": "^16.5.2",
51+
"react": "16.8.0",
52+
"react-dom": "16.8.0",
5353
"react-redux": "^5.0.7",
5454
"react-router": "^4.3.1",
5555
"react-router-dom": "^4.3.1",
5656
"react-transition-group": "^2.5.0",
5757
"redux": "^4.0.0"
5858
},
5959
"peerDependencies": {
60+
"react": "*",
6061
"react-dom": "*"
6162
},
6263
"eslintConfig": {

src/__tests__/testHook.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import {useState} from 'react'
2+
import 'jest-dom/extend-expect'
3+
import {testHook, cleanup} from '../'
4+
5+
afterEach(cleanup)
6+
7+
test('testHook calls the callback', () => {
8+
const spy = jest.fn()
9+
testHook(spy)
10+
expect(spy).toHaveBeenCalledTimes(1)
11+
})
12+
test('confirm we can safely call a React Hook from within the callback', () => {
13+
testHook(() => useState())
14+
})

src/index.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import React from 'react'
12
import ReactDOM from 'react-dom'
23
import {getQueriesForElement, prettyDOM, fireEvent} from 'dom-testing-library'
34

@@ -51,6 +52,15 @@ function render(
5152
}
5253
}
5354

55+
function TestHook({callback}) {
56+
callback()
57+
return null
58+
}
59+
60+
function testHook(callback) {
61+
render(<TestHook callback={callback} />)
62+
}
63+
5464
function cleanup() {
5565
mountedContainers.forEach(cleanupAtContainer)
5666
}
@@ -92,6 +102,6 @@ fireEvent.select = (node, init) => {
92102

93103
// just re-export everything from dom-testing-library
94104
export * from 'dom-testing-library'
95-
export {render, cleanup, flushEffects}
105+
export {render, testHook, cleanup, flushEffects}
96106

97107
/* eslint func-name-matching:0 */

typings/index.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ export function render<Q extends Queries>(
4040
options: RenderOptions<Q>,
4141
): RenderResult<Q>
4242

43+
/**
44+
* Renders a test component that calls back to the test.
45+
*/
46+
export function testHook(callback: () => void): void
47+
4348
/**
4449
* Unmounts React trees that were mounted with render.
4550
*/

0 commit comments

Comments
 (0)