I have a simple NotFound.tsx
that I would like to cover with a first test.
import React from "react";
import {Button} from "devextreme-react";
import "./NotFound.scss";
import {useHistory as UseHistory} from "react-router";
export default function NotFound(): JSX.Element {
const history = UseHistory();
function onClickOk() {
history.replace("/home");
}
return (
<div className={'not-found-container'}>
<h1 className={'not-found-header'}>404</h1>
<p className={'not-found-text'}>Page not found.</p>
<p className={'not-found-description'}>The page you are looking for might have been removed.</p>
<Button type="default"
text="Ok"
onClick={onClickOk} />
</div>
);
}
Now I would like to use the MemoryHistory so I can check if it navigates around. My NotFound.test.tsx
:
Without Memoryhistory
import React from "react";
import {shallow} from "enzyme";
import {NotFound} from "../index";
import {useHistory as UseHistory} from "react-router";
test('test the not found page', () => {
const history = UseHistory();
history.push('/page1');
history.push('/page2');
const component = shallow(<NotFound />);
component.find('Ok').simulate('click');
expect(history.length).toMatch('2');
expect(history.location.pathname).toMatch('/home');
history.goBack();
expect(history.location.pathname).toMatch('/page1');
});
This doesnt work because then he actually tries to navigate around as it seems.
Now I tried to mock it:
import React from "react";
import {shallow} from "enzyme";
import {NotFound} from "../index";
import {createMemoryHistory} from "history";
import {useHistory as UseHistory} from "react-router";
jest.mock('react-router-dom', () => ({
useHistory: () => createMemoryHistory({ initialEntries: ['/page1', '/page2'] })
}));
test('test the not found page', () => {
const history = UseHistory();
const component = shallow(<NotFound />);
component.find('Ok').simulate('click');
expect(history.length).toMatch('2');
expect(history.location.pathname).toMatch('/home');
history.goBack();
expect(history.location.pathname).toMatch('/page1');
});
This gives me an error:
ReferenceError: C:\[...]src\Pages\NotFound\NotFound.test.tsx: The module factory of 'jest.mock()' is not allowed to reference any out-of-scope variables.
Other solutions I have already seen are:
1. Taking the history as an argument. I don't like this solution because I would prefer not having to modify my code for a test.
2. Creating somewhat like a history factory and importing that instead using the UseHistory()
https://blog.logrocket.com/testing-the-react-router-usehistory-hook-with-react-testing-library/:
import { createBrowserHistory, createMemoryHistory } from "history";
import { Urls } from "../types/urls";
const isTest = process.env.NODE_ENV === "test";
export const history = isTest
? createMemoryHistory({ initialEntries: ['/'] })
: createBrowserHistory();
Don't like this solution for the same reason
3. Creating a custom history
jest.mock('react-router-dom', () => ({
useHistory: () => ({
push: jest.fn(),
}),
}));
As far as I understand MemoryHistory is there for scenarios like testing, so creating a own mock object should be unneccessary.
Maybe my approach is wrong but I don't know how else I could test a component like this.