Description
Describe the feature you'd like:
I think it would be great to add a utility to make testing custom hooks easier. Right now, I recommend making a render prop component out of the hook and testing that component. I think we could do the same from within react-testing-library.
Suggested implementation:
Here's a working implementation/example
import React, {useState} from 'react'
import {render, cleanup} from 'react-testing-library'
afterEach(cleanup)
function useCounter({initialCount = 0, step = 1} = {}) {
const [count, setCount] = useState(initialCount)
const increment = () => setCount(c => c + step)
const decrement = () => setCount(c => c - step)
return {count, increment, decrement}
}
function testHook(useHook, props) {
const RenderProp = ({children, ...rest}) => children(useHook(rest))
const returnVal = {}
render(
<RenderProp {...props}>
{val => {
// may need some special treatment if the
// return value is not an object of values...
Object.assign(returnVal, val)
return null
}}
</RenderProp>,
)
return returnVal
}
// how to use this:
test('renders counter', () => {
const data = testHook(useCounter)
data.increment()
expect(data.count).toBe(1)
data.decrement()
expect(data.count).toBe(0)
})
Describe alternatives you've considered:
- Not providing the utility at all.
- Calling it
renderHook
rather thantestHook
, or just about anything else. I'm not sure I liketestHook
...
Teachability, Documentation, Adoption, Migration Strategy:
One really important consideration is that with render
we recommend that people destructure just what they need rather than assigning the return value an actual variable name. With testHook
however, if you destructure the return value it can have some pretty confusing issues (relating to the way JavaScript closures work, I explain it in the video I linked above). So all docs will need to call this out specially and all examples should not destructure anything from testHook
.
We should also make sure to document the fact that this should typically only be used for hooks that either have a lot of edge cases that need special unit testing or highly reused hooks. Typically custom hooks should just be covered by testing the components that use them.