# [JEST] TEST ## React-router ### useNavigate ```jsx! import * as router from 'react-router' const navigate = jest.fn() beforeEach(() => { jest.spyOn(router, 'useNavigate').mockImplementation(() => navigate) }) it('...', () => { ... expect(navigate).toHaveBeenCalledWith('/path') }) ``` > <https://stackoverflow.com/a/72289488> --- ## toast ```typescript! import { toast } from 'react-hot-toast' jest.mock('react-hot-toast') jest.spyOn(toast, 'promise').mockImplementation(promise => promise) ``` --- ## SWR ```typescript! jest .spyOn(SWR, 'default') .mockImplementation(() => ({ data: identifyProfile, isValidating: false, mutate: () => Promise.resolve() })); ``` > > <https://stackoverflow.com/a/76376168> > > <https://jestjs.io/docs/jest-object#jestspyonobject-methodname> > --- ### useSWR ```typescript! import { useSWRConfig } from 'swr'; jest.mock('swr', () => ({ ...jest.requireActual('swr'), useSWRConfig: jest.fn(() => ({ mutate: () => {}, })), })); it('should mutate data', async () => { const mockMutate = jest.fn(); useSWRConfig.mockImplementationOnce(() => ({ mutate: mockMutate })); expect(mockMutate).toHaveBeenCalledWith('swrKey'); ... }); ``` > > <https://stackoverflow.com/a/76421717> > --- ```typescript! jest.mock("swr"); useSWRInfinite.mockReturnValue({ "data": [{ data: [] }], "error": null }); ``` > > <https://github.com/vercel/swr/discussions/711#discussioncomment-110076> > --- ```typescript! const mockedMutate = jest.fn(); jest.mock('swr', () => ({ __esModule: true, ...jest.requireActual('swr'), useSWR: jest.fn(() => ({ mutate: () => mockedMutate, })), })); fireEvent.click(disableUser); await waitFor(() => { expect(mockedMutate).toBeCalledTimes(10); }); ``` > > <https://github.com/vercel/swr/discussions/2077#discussioncomment-6384044> > --- ## Custom Hooks > > <https://engineering.mobalab.net/2022/12/13/test-react-custom-hooks-with-jest-and-testing-library/> > > <https://pjchender.dev/npm/npm-jest-tip/> > ```typescript! import { renderHook, act } from '@testing-library/react' import { toast } from 'react-hot-toast' import { useUploadFile } from './index' jest.mock('react-hot-toast') const mockUploadService = { upload: jest.fn(), } jest.mock('@/service/upload', () => ({ useCreate: () => ({ trigger: mockUploadService.upload, isMutating: false, }), })) describe('useUploadFile', () => { afterEach(() => { jest.clearAllMocks() }) it('should return correct hook values', () => { const { result } = renderHook(() => useUploadFile()) expect(result.current).toHaveProperty('isMutating') expect(result.current).toHaveProperty('handleUploadFile') }) it('should not trigger upload when no file is selected', async () => { const { result } = renderHook(() => useUploadFile()) const mockFileList = { length: 0, item: (_: number) => null, } await act(async () => { await result.current.handleUploadFile(mockFileList as FileList) }) expect(mockUploadService.upload).not.toHaveBeenCalled() }) it('should trigger upload and return correct URL when file is selected', async () => { const file = new File(['hello'], 'hello.txt', { type: 'text/plain' }) const url = 'https://example.com/hello.txt' const mockResolvedValue = { url } mockUploadService.upload.mockResolvedValueOnce(mockResolvedValue) jest.spyOn(toast, 'promise').mockImplementation(promise => promise) const { result } = renderHook(() => useUploadFile()) const mockFileList = { 0: file, length: 1, item: (_: number) => file } await act(async () => { const uploadedUrl = await result.current.handleUploadFile(mockFileList as unknown as FileList) expect(uploadedUrl).toBe(url) expect(mockUploadService.upload).toHaveBeenCalledWith(expect.any(FormData)) expect(toast.promise).toHaveBeenCalled() }) }) }) ``` --- ## React-hook-form > <https://claritydev.net/blog/testing-react-hook-form-with-react-testing-library> - have to install userEvent ```jsx! import userEvent from "@testing-library/user-event"; ``` > > <https://codesandbox.io/p/sandbox/react-hook-form-reset-test-75qqh> > --- ### useForm > <https://github.com/orgs/react-hook-form/discussions/8303#discussioncomment-2687629> > <https://github.com/orgs/react-hook-form/discussions/8061#discussioncomment-5906803>