How can we ensure that a custom hook actually calls a method exposed by another hook?
Let's say, I have a custom hook useName
that internally leverages useState
.
import { useState } from 'react'
export const useName = () => {
const [name, setState] = useState()
const setName = (firstName: string, lastName: string) => setState([firstName, lastName].join(' '))
return {name, setName}
}
I need to assert that calling setName
actually calls `setState'. My test case is written as following:
/**
* @jest-environment jsdom
*/
import * as React from 'react'
import { renderHook, act } from '@testing-library/react-hooks'
import { useName } from './useName'
jest.mock('react')
const setState = jest.fn()
React.useState.mockReturnValue(['ignore', setState]) //overwriting useState
test('ensures that setState is called', () => {
const {result} = renderHook(() => useName())
act(() => {
result.current.setName("Kashif", "Nazar") //I am expecting this to hit jest.fn() declared above.
})
expect(setState).toBeCalled()
})
and I get the following result.
FAIL src/useName.test.ts
✕ ensures that setState is called (3 ms)
● ensures that setState is called
TypeError: Cannot read property 'setName' of undefined
18 |
19 | act(() => {
> 20 | result.current.setName("Kashif", "Nazar")
| ^
21 | })
22 |
23 | expect(setState).toBeCalled()
at src/useName.test.ts:20:24
at batchedUpdates$1 (node_modules/react-dom/cjs/react-dom.development.js:22380:12)
at act (node_modules/react-dom/cjs/react-dom-test-utils.development.js:1042:14)
at Object.<anonymous> (src/useName.test.ts:19:5)
at TestScheduler.scheduleTests (node_modules/@jest/core/build/TestScheduler.js:333:13)
at runJest (node_modules/@jest/core/build/runJest.js:404:19)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 0.32 s, estimated 1 s
Ran all test suites.
Is this possible, and am I doing it the right way?