Problem:
I am new to react unit testing world. I have a component like this that is showing a report component that is using @splidejs/react-splide.
const Incident = () => {
const { t } = useTranslation()
const navigate = useNavigate()
const { Id } = useParams()
const theme = useTheme()
const { fetch, ...dataFetchResult } =
useReportDataFetch("incidents/GetById")
useEffect(() => {
fetch({ id: Id })
return ()=>{
localStorage.removeItem("vehicle")
}
}, [Id, fetch])
const data = dataFetchResult.data
const photos = useMemo(
() =>
data?.photos
? data.photos.map(photo => ({
...photo,
original: `${process.env.REACT_APP_PHOTO_SOURCE}${photo.fileName}.jpg`,
thumbnail: `${process.env.REACT_APP_PHOTO_SOURCE}${photo.thumbnail}.jpg`,
}))
: [],
[data.photos]
)
const location = useLocation()
const from = location.state?.from?.pathname || "/"
const renderLink = () => {
if (from === "/Incidents") {
return (
<Grid
container
justifyContent="space-between"
alignContent="center"
alignItems="center"
sx={{ paddingRight: theme.spacing(3) }}
>
<Grid item lg="auto">
<Link
style={{ fontWeight: "bold" }}
href="#"
onClick={() => navigate(-1)}
underline="none"
>
{t("incident.all_incidents")}
</Link>
</Grid>
<Grid item>
<TopIconButtonContainer>
<TopIconLabelContainer>
<TopIconContainer>
<TopIcon icon={faShareFromSquare} />
</TopIconContainer>
<Box sx={{ fontWeight: "500" }}>
{t("incident.share")}
</Box>
</TopIconLabelContainer>
<TopIconLabelContainer>
<TopIconContainer>
<TopIcon icon={faClock} />
</TopIconContainer>
<Box sx={{ fontWeight: "500" }}>
{t("incident.schedule")}
</Box>
</TopIconLabelContainer>
<TopIconLabelContainer>
<TopIconContainer>
<TopIcon icon={faPrint} />
</TopIconContainer>
<Box sx={{ fontWeight: "500" }}>
{t("incident.print")}
</Box>
</TopIconLabelContainer>
<TopIconLabelContainer>
<TopIconContainer>
<TopIcon icon={faDownToLine} />
</TopIconContainer>
<Box sx={{ fontWeight: "500" }}>
{t("incident.export")}
</Box>
</TopIconLabelContainer>
<TopIconLabelContainer>
<TopIconContainer>
<TopIcon icon={faQuestion} />
</TopIconContainer>
<Box sx={{ fontWeight: "500" }}>
{t("incident.help")}
</Box>
</TopIconLabelContainer>
</TopIconButtonContainer>
</Grid>
</Grid>
)
}
}
return (
<>
<ErrorBoundary>
<ReportDataLayout dataFetchResult={dataFetchResult} noCancel>
<Container>{renderLink()}</Container>
<Grid container sx={{ paddingRight: theme.spacing(3) }}>
<Grid item xs={12} lg={6} md={6} xl={6} sm={12}>
<BoxContainer>
<Box>
<h4>{t("incident.incident_details")}</h4>
<DataContainer>
{dataFetchResult.hasData && (
<AssetLabel asset={data.asset} />
)}
</DataContainer>
<DataContainer>
{dataFetchResult.hasData && (
<span>
{shortDateTime(
data.dateAndTime
)}
</span>
)}
</DataContainer>
<DataContainer>
<span>Driver {data.driver}</span>
</DataContainer>
<DataContainer>
<div>{data.details}</div>
</DataContainer>
</Box>
<Box>
<h4>
{t("incident.other_driver_details")}
</h4>
<DataContainer>
<span>{data?.otherDriver?.driver}</span>
</DataContainer>
<DataContainer>
{data?.otherDriver?.registration}
</DataContainer>
<DataContainer>
{data?.otherDriver?.insurance}
</DataContainer>
</Box>
</BoxContainer>
</Grid>
<Grid item xs={12} lg={6} md={6} xl={6} sm={12}>
<MapContainer>
<h4>{t("incident.incident_location")}</h4>
{dataFetchResult.hasData && (
<Map
center={{
lat: data.locationLat,
lng: data.locationLong,
}}
zoom={8}
defaultZoom={8}
onZoomChange={(lat, lng, scale) => {}}
>
<IncidentMapMarker
data={data}
></IncidentMapMarker>
</Map>
)}
<LocationContainer sx={{ display: "flex" }}>
<LocationIconContainer
color={theme.palette.primary.main}
icon={faLocationDot}
/>
<div>{data?.location}</div>
</LocationContainer>
</MapContainer>
</Grid>
</Grid>
<PhotoTitleContainer>
<h4 style={{ marginTop: 70 }}>
{t("incident.photos")}
</h4>
<div
style={{
flexDirection: "row",
display: "flex",
flexWrap: "wrap",
}}
>
{photos.length >= 1 &&
photos?.map((item, index) => (
<img
style={{
width: 100,
margin: 10,
height: 75,
}}
key={index}
src={item?.thumbnail}
alt={`Image ${index}`}
/>
))}
</div>
</PhotoTitleContainer>
<PhotoContainer>
<Splide
options={{
rewind: true,
gap: "1rem",
perPage: 2,
fixedWidth: "50%",
snap: true,
lazyLoad: "nearby",
}}
>
{photos.length >= 1 &&
photos?.map((item, index) => (
<SplideSlide key={index}>
<img
style={{
width: "100%",
height: 400,
}}
src={item?.original}
alt={`Image ${index}`}
/>
</SplideSlide>
))}
</Splide>
</PhotoContainer>
</ReportDataLayout>
</ErrorBoundary>
</>
)
}
Error boundary component is like this.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { hasError: false }
}
static getDerivedStateFromError(error) {
return { hasError: true }
}
// Not used at the moment but for logging etc...
// We might be able to store it for "raise a support case"
componentDidCatch(error, errorInfo) {}
render() {
if (this.state.hasError) {
return <Error />
}
return this.props.children
}
}
And report data layout is look like this.
const ReportDataLayout = ({
dataFetchResult,
noCancel,
noDataMessage,
children,
}) => {
if (dataFetchResult.isError) throw new Error()
if (dataFetchResult.isFetching) {
if (noCancel) {
return (
<Container>
<Progress size="large" />
</Container>
)
} else {
return (
<Container>
<ProgressWithCancel
size="large"
onCancel={dataFetchResult.cancel}
/>
</Container>
)
}
}
if (dataFetchResult.isCanceled) {
return (
<Container>
<UserCanceled />
</Container>
)
}
if (!dataFetchResult.hasData && !dataFetchResult.isIdle) {
return (
<Container>
<NoData message={noDataMessage} />
</Container>
)
}
return <div>{children}</div>
}
After that I wrote an unit testing for this component like this.
Before I adding splideJs it was working like charm after I added that package when I run unit test it is failing. This is how I have wrote it.
import React from "react"
import {
render,
screen,
fireEvent,
waitFor,
within,
} from "@testing-library/react"
import axios from "axios"
import MockAdapter from "axios-mock-adapter"
import { BrowserRouter, Routes, Route } from "react-router-dom"
import * as HTTP_STATUS from "../../../data-fetch/constants/httpStatuses"
import Incident from "./Incident"
jest.mock("react-i18next", () => ({
useTranslation: () => {
return {
t: str => str,
}
},
}))
const mock_refresh = jest.fn()
jest.mock("../../../framework/useApplication", () => ({
useApplication: () => {
return {
refresh: () => mock_refresh(),
}
},
}))
jest.mock("../../../utilities/date-formats", () => ({
mediumDateTime: dateTime => dateTime.toString(),
}))
const renderTestDom = () => {
window.history.pushState({}, "Incident", "/Incident")
render(
<BrowserRouter>
<Routes>
<Route path="/Incident" element={<Incident />} />
</Routes>
</BrowserRouter>
)
}
const reportData = {
id: 1,
driver: "David Smith",
locationLat: 52.504897,
locationLong: -2.080205,
location: "Prospect Row, Dudley",
dateAndTime: "2022-07-12T09:06:18.47",
details: "The car was hit by another driver while being parked",
otherDriver: {
driver: "Jack Smith",
registration: "Vehicle registration",
insurance: "Name of insurance",
},
asset: {
id: 471319,
description: "170633 Ginsters",
icon: "largevan_green",
aspectRatio: 2.5,
site: 0,
groups: [],
},
photos: [
{
fileName: "VehAccident-1",
thumbnail: "VehAccident-1-thumb",
},
{
fileName: "VehAccident-2",
thumbnail: "VehAccident-2-thumb",
},
],
}
describe("Incident", () => {
let mock_axios
beforeAll(() => {
mock_axios = new MockAdapter(axios)
Object.defineProperty(window, "matchMedia", {
writable: true,
value: jest.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // Deprecated
removeListener: jest.fn(), // Deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
})
})
beforeEach(() => {
mock_axios
.onGet("incidents/GetById", {
params: {
id: 1,
},
})
.reply(HTTP_STATUS.OK, reportData)
})
test("should render title", async () => {
renderTestDom()
await waitFor(async () => {
expect(screen.getByText(/incident.incident_details/)).not.toBeNull()
})
})
})
But After I wruuning this test it is showing me this issue.
console.error
Error: Uncaught [TypeError: Cannot read properties of undefined (reading 'matches')]
at reportException (E:\Freelance\webclient-fleettacking\node_modules\jsdom\lib\jsdom\living\helpers\runtime-script-errors.js:66:24)
at innerInvokeEventListeners (E:\Freelance\webclient-fleettacking\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:341:9)
at invokeEventListeners (E:\Freelance\webclient-fleettacking\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:274:3)
at HTMLUnknownElementImpl._dispatch (E:\Freelance\webclient-fleettacking\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:221:9)
at HTMLUnknownElementImpl.dispatchEvent (E:\Freelance\webclient-fleettacking\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:94:17)
at HTMLUnknownElement.dispatchEvent (E:\Freelance\webclient-fleettacking\node_modules\jsdom\lib\jsdom\living\generated\EventTarget.js:231:34)
at Object.invokeGuardedCallbackDev (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:3994:16)
at invokeGuardedCallback (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:4056:31)
at commitRootImpl (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:23151:9)
at unstable_runWithPriority (E:\Freelance\webclient-fleettacking\node_modules\scheduler\cjs\scheduler.development.js:468:12) TypeError: Cannot read properties of undefined (reading 'matches')
at E:\Freelance\webclient-fleettacking\node_modules\@splidejs\react-splide\dist\js\react-splide.cjs.js:537:38
at Array.reduce (<anonymous>)
at update (E:\Freelance\webclient-fleettacking\node_modules\@splidejs\react-splide\dist\js\react-splide.cjs.js:536:26)
at Object.setup (E:\Freelance\webclient-fleettacking\node_modules\@splidejs\react-splide\dist\js\react-splide.cjs.js:521:5)
at E:\Freelance\webclient-fleettacking\node_modules\@splidejs\react-splide\dist\js\react-splide.cjs.js:2471:36
at forOwn (E:\Freelance\webclient-fleettacking\node_modules\@splidejs\react-splide\dist\js\react-splide.cjs.js:154:13)
at _Splide2.mount (E:\Freelance\webclient-fleettacking\node_modules\@splidejs\react-splide\dist\js\react-splide.cjs.js:2468:5)
at Splide2.componentDidMount (E:\Freelance\webclient-fleettacking\node_modules\@splidejs\react-splide\dist\js\react-splide.cjs.js:2691:19)
at commitLifeCycles (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:20663:24)
at commitLayoutEffects (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:23426:7)
at HTMLUnknownElement.callCallback (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:3945:14)
at HTMLUnknownElement.callTheUserObjectsOperation (E:\Freelance\webclient-fleettacking\node_modules\jsdom\lib\jsdom\living\generated\EventListener.js:26:30)
at innerInvokeEventListeners (E:\Freelance\webclient-fleettacking\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:338:25)
at invokeEventListeners (E:\Freelance\webclient-fleettacking\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:274:3)
at HTMLUnknownElementImpl._dispatch (E:\Freelance\webclient-fleettacking\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:221:9)
at HTMLUnknownElementImpl.dispatchEvent (E:\Freelance\webclient-fleettacking\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:94:17)
at HTMLUnknownElement.dispatchEvent (E:\Freelance\webclient-fleettacking\node_modules\jsdom\lib\jsdom\living\generated\EventTarget.js:231:34)
at Object.invokeGuardedCallbackDev (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:3994:16)
at invokeGuardedCallback (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:4056:31)
at commitRootImpl (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:23151:9)
at unstable_runWithPriority (E:\Freelance\webclient-fleettacking\node_modules\scheduler\cjs\scheduler.development.js:468:12)
at runWithPriority$1 (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:11276:10)
at commitRoot (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:22990:3)
at performSyncWorkOnRoot (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:22329:3)
at scheduleUpdateOnFiber (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:21881:7)
at updateContainer (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:25482:3)
at E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:26021:7
at unbatchedUpdates (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:22431:12)
at legacyRenderSubtreeIntoContainer (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:26020:5)
at Object.render (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:26103:10)
at E:\Freelance\webclient-fleettacking\node_modules\@testing-library\react\dist\pure.js:101:25
at batchedUpdates$1 (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom.development.js:22380:12)
at act (E:\Freelance\webclient-fleettacking\node_modules\react-dom\cjs\react-dom-test-utils.development.js:1042:14)
at render (E:\Freelance\webclient-fleettacking\node_modules\@testing-library\react\dist\pure.js:97:26)
at renderTestDom (E:\Freelance\webclient-fleettacking\src\reports\incident\incidentDetailPage\Incident.test.js:38:2)
at Object.<anonymous> (E:\Freelance\webclient-fleettacking\src\reports\incident\incidentDetailPage\Incident.test.js:110:3)
at Promise.then.completed (E:\Freelance\webclient-fleettacking\node_modules\jest-circus\build\utils.js:391:28)
at new Promise (<anonymous>)
at callAsyncCircusFn (E:\Freelance\webclient-fleettacking\node_modules\jest-circus\build\utils.js:316:10)
at _callCircusTest (E:\Freelance\webclient-fleettacking\node_modules\jest-circus\build\run.js:218:40)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at _runTest (E:\Freelance\webclient-fleettacking\node_modules\jest-circus\build\run.js:155:3)
at _runTestsForDescribeBlock (E:\Freelance\webclient-fleettacking\node_modules\jest-circus\build\run.js:66:9)
at _runTestsForDescribeBlock (E:\Freelance\webclient-fleettacking\node_modules\jest-circus\build\run.js:60:9)
at run (E:\Freelance\webclient-fleettacking\node_modules\jest-circus\build\run.js:25:3)
at runAndTransformResultsToJestFormat (E:\Freelance\webclient-fleettacking\node_modules\jest-circus\build\legacy-code-todo-rewrite\jestAdapterInit.js:170:21)
at jestAdapter (E:\Freelance\webclient-fleettacking\node_modules\jest-circus\build\legacy-code-todo-rewrite\jestAdapter.js:82:19)
at runTestInternal (E:\Freelance\webclient-fleettacking\node_modules\jest-runner\build\runTest.js:389:16)
at runTest (E:\Freelance\webclient-fleettacking\node_modules\jest-runner\build\runTest.js:475:34)
at Object.worker (E:\Freelance\webclient-fleettacking\node_modules\jest-runner\build\testWorker.js:133:12)
at VirtualConsole.<anonymous> (node_modules/jsdom/lib/jsdom/virtual-console.js:29:45)
at reportException (node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:70:28)
at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:341:9)
at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:274:3)
at HTMLUnknownElementImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:221:9)
at HTMLUnknownElementImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:94:17)
at HTMLUnknownElement.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:231:34)
console.error
The above error occurred in the <Splide2> component:
at Splide2 (E:\Freelance\webclient-fleettacking\node_modules\@splidejs\react-splide\dist\js\react-splide.cjs.js:2681:5)
at div
at I (E:\Freelance\webclient-fleettacking\node_modules\styled-components\src\models\StyledComponent.js:252:3)
at div
at ReportDataLayout (E:\Freelance\webclient-fleettacking\src\data-fetch\ReportDataLayout.js:14:2)
at ErrorBoundary (E:\Freelance\webclient-fleettacking\src\framework\elements\ErrorBoundary.js:10:3)
at Incident (E:\Freelance\webclient-fleettacking\src\reports\incident\incidentDetailPage\Incident.js:114:19)
at Routes (E:\Freelance\packages\react-router\index.tsx:336:3)
at Router (E:\Freelance\packages\react-router\index.tsx:256:13)
at BrowserRouter (E:\Freelance\packages\react-router-dom\index.tsx:136:3)
React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary.
I tried a lot to find out a solution for this one but I was unable to do so. Can someone help me to solve this. This issue was stopping me for two days now. It would be great if anyone could help me regarding this issue.Thank you