Environment
- Next.js v14 Pages Router
- jest v29.7
- @tanstack/react-query v5.36.0
Overview
There is a custom hook called useUserInfo
that wraps useQuery
from tanstack-query
, and It fetches user information.
I want to test the useAccountMenu
custom hook that uses that useUserInfo
(each role of custom hooks will be explained later).
The return value of useUserInfo
, that will be stored in data
property of returend object (convention of tanstack-query
), has the following type.
// type.ts
type ActiveUserInfo = {
id: number,
name: string,
age: number,
}
And this is the implementation of the useUserInfo
custom hook that wraps the useQuery
.
// useUserInfo.ts
export const useUserInfo = () => {
// assume fetchLoggedInUser is simple fetch()
return useQuery(['loggedInUser'], fetchLoggedInUser);
};
And this is the useAccountMenu
custom hook, which uses the useUserInfo
custom hook to return data for the account menu link.
The return value of useAccountMenu
changes depending on the value returned from useUserInfo
.
// useAccountMenu.ts
export const useAccountMenu = () => {
const {data} = useUserInfo();
if (data.id > 100) { // this is example condition
return {
menuItems: [
{menuLabel: 'User Setting', to: 'setting/user'},
{menuLabel: 'Language', to: 'setting/language'},
]
};
};
return {
menuItems: [
{menuLabel: 'User Setting', to: 'setting/user'},
{menuLabel: 'Language', to: 'setting/language'},
{menuLabel: 'Organization', to: 'setting/organization'},
]
};
};
Test code that doesn’t work well.
// useAccountMenu.test.ts
jest.mock('./useAccountMenu');
describe.concurrent('useAccountMenu', () => {
it('returns all menu objects', async () => {
const mockData = {
id: 3,
name: 'John',
age: 25,
};
jest.mocked(useUserInfo).mockReturnValueOnce({ data: mockData }); // type Error!!
const { result } = renderHook(() => useAccountMenu(), { wrapper });
await waitFor(() => {
expect(result.current.menuItems).toEqual([
{menuLabel: 'User Setting', to: 'setting/user'},
{menuLabel: 'Language', to: 'setting/language'},
{menuLabel: 'Organization', to: 'setting/organization'},
]);
});
});
// and here below will be test for the case of data.id > 100.
// ...
})
The line mockReturnValueOnce
is executed, I got a TypeError: Type '{ data: { id: string; name: string; age: number; }; }' is missing the following properties from type 'QueryObserverSuccessResult<ActiveUserInfo, Error>': error, isError, isPending, isLoading, and 19 more.ts(2345)
.
In this case, do I have to hardcode isError
, isPending
, etc. every time and create mock data?
Or is there a smarter solution or a different way of testing for useAccountMenu
?
If this error can be fixed, it will relieve me of the stress I have been suffering from the last few days…
Thank you very much for your time.