'How to test custom hook to and mock request api with react testing library
I'm trying to test custom hook that contains fetching api request
this is the code in useReportDownload.ts hook
import { useEffect, useState } from 'react'
import { useParams } from 'react-router'
import { fetchdownload } from '~/services'
export default function useReportDownload() {
const { id } = useParams()
const [list, setList] = useState<Array<any>>([])
const getList = async () => {
try {
if (id) {
const data = await fetchdownload(Number(id))
setList(data)
}
} catch (error) {
// eslint-disable-next-line no-console
console.debug('error', error)
}
}
useEffect(() => {
getList()
}, [id])
return {
list,
}
}
this is the test file listreports.spec.tsx:
import { render, screen } from '@testing-library/react'
import { renderHook } from '@testing-library/react-hooks'
import { rest } from 'msw'
import { setupServer } from 'msw/node'
import '@testing-library/jest-dom/extend-expect'
import useReportDownload from './useReportDownload'
import ReportDownload from '.'
const data = [
{
id: '1',
name: 'Test',
url: 'https://test.com',
actions: [
{
buttonType: 'icon',
event: 'download',
icon: 'download',
label: 'Download',
},
],
},
{
id: '2',
name: 'Test2',
url: 'https://test2.com',
actions: [
{
buttonType: 'icon',
event: 'download',
icon: 'download',
label: 'Download',
},
],
},
]
const server = setupServer(
rest.get('campaigns/1/proof-execution', async (req, res, ctx) =>
res(ctx.json(data))
)
)
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
describe('useReportDownload', () => {
it('should return the expected result', () => {
const { result } = renderHook(() => useReportDownload())
expect(result.current.list).toEqual([])
expect(result.current.handleAction).toBeInstanceOf(Function)
expect(result.current.handlePage).toBeInstanceOf(Function)
expect(result.current.handleSelectedReports).toBeInstanceOf(Function)
expect(result.current.handleSelectAllReports).toBeInstanceOf(Function)
expect(result.current.selectedReports).toEqual([])
})
it('should return the expected result', async () => {
render(<ReportDownload />)
const text = await screen.findByText('Test')
// eslint-disable-next-line no-console
console.log(text)
})
})
this is the listreports.tsx component that uses the above hook :
import React from 'react'
import { Box } from '@mui/material'
import useReportDownload from './useReportDownload'
import NoResults from '~/components/NoResults'
import { ReactComponent as NoResultsImage } from '~/images/noResults.svg'
import TableList from '~/TableList'
import { tableColumns } from '~/constants'
import * as Styled from '~/styles'
import { cosmosService } from '~/services/cosmos'
import { i18n } from '~/i18n'
interface Props {
isHeaderBarAvailable?: boolean;
headComponent?: React.ReactNode;
}
const ReportDownload = ({
isHeaderBarAvailable = true,
headComponent,
}: Props) => {
const {
list,
handleAction,
handlePage,
handleSelectedReports,
handleSelectAllReports,
selectedReports,
} = useReportDownload()
const listContainer = () => (
<>
{list.length === 0 ? (
<NoResults
title={i18n.t('noResults.title')}
description={i18n.t('noResults.description')}
image={<NoResultsImage />}
/>
) : (
<TableList
enableCheckBox
enableBulkSelect
loading={false}
columns={tableColumns}
page={1}
perPage={1}
totalNumRows={list.length}
enablePagination={false}
rows={list}
sortBy="id"
orderBy="desc"
selectedOptions={selectedReports}
onCheckBoxChange={handleSelectedReports}
onCheckBoxChangeAll={handleSelectAllReports}
onPageChange={handlePage}
onNumRowsChange={handlePage}
onOrderChange={handlePage}
onAction={handleAction}
/>
)}
</>
)
const fileComponent = () => (
<Styled.Grid>
<Styled.SelectedItemsBox>
{i18n.t('reports.details.selectedItems')}
<b>{selectedReports?.length}</b>
</Styled.SelectedItemsBox>
<Styled.Button
onClick={() => cosmosService.downloadMedias(list, selectedReports)}
>
{i18n.t('reports.details.exportButton')}
</Styled.Button>
</Styled.Grid>
)
return (
<Box>
{headComponent}
{isHeaderBarAvailable && <Box height="10%" />}
{selectedReports?.length > 0 && fileComponent()}
<Box height="100%">{listContainer()}</Box>
</Box>
)
}
export default ReportDownload
the problem is the mock data is not working, I want to test that when fetching data the list should have the data, but I have this error
✕ should return the expected result (1037 ms)
● useReportDownload › should return the expected result
Unable to find an element with the text: Test. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
<body>
<div>
<div
class="MuiBox-root css-0"
>
<div
class="MuiBox-root css-1w5i5lh"
/>
<div
class="MuiBox-root css-10klw3m"
>
<div
class="MuiBox-root css-32vdxk"
>
<div
class="MuiBox-root css-24os1g"
>
<svg>
noResults.svg
</svg>
</div>
<div
class="MuiBox-root css-xi606m"
>
<p
class="MuiTypography-root MuiTypography-body1 css-eflgtu-MuiTypography-root"
>
No Results
</p>
<p
class="MuiTypography-root MuiTypography-body1 css-66p3eu-MuiTypography-root"
>
Your search has not returned any results
</p>
</div>
</div>
</div>
</div>
</div>
</body>
61 | it('should return the expected result', async () => {
62 | render(<ReportDownload />)
> 63 | const text = await screen.findByText('Test')
| ^
64 | // eslint-disable-next-line no-console
65 | console.log(text)
66 | })
at waitForWrapper (node_modules/@testing-library/dom/dist/wait-for.js:173:27)
at findByText (node_modules/@testing-library/dom/dist/query-helpers.js:101:33)
at Object.<anonymous> (src/components/ReportDownload/UseReportDownload.spec.tsx:63:31)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 passed, 2 total
Snapshots: 0 total
Time: 3.977 s, estimated 4 s
so what is wrong?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
