I have a component that uses useLocation hook to get the path from the URL.
const { pathname } = useLocation();
useEffect(() => { }, [pathname]);
While I am trying to mock the location using ,
import React from 'react';
import ExampleComponent from './ExampleComponent';
import { fireEvent, render } from '@testing-library/react';
import { shallow } from 'enzyme';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: () => ({
pathname: 'https://URL/'
})
}));
describe('<ExampleComponent />', () => {
it('should render correctly', () => {
shallow(<ExampleComponent />);
});
});
I am getting this error while I run the test, TypeError: Cannot read property 'location' of undefined
I have a component that uses useLocation hook to get the path from the URL.
const { pathname } = useLocation();
useEffect(() => { }, [pathname]);
While I am trying to mock the location using ,
import React from 'react';
import ExampleComponent from './ExampleComponent';
import { fireEvent, render } from '@testing-library/react';
import { shallow } from 'enzyme';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: () => ({
pathname: 'https://URL/'
})
}));
describe('<ExampleComponent />', () => {
it('should render correctly', () => {
shallow(<ExampleComponent />);
});
});
I am getting this error while I run the test, TypeError: Cannot read property 'location' of undefined
Share Improve this question edited Jun 14, 2021 at 5:22 Vegeta asked Jun 14, 2021 at 5:01 VegetaVegeta 1191 gold badge2 silver badges9 bronze badges 2- I would suggest you don't mock it, mount the component in e.g. a MemoryRouter or create a history for testing purposes; see stackoverflow.com/a/65275037/3001761, reactrouter.com/web/guides/testing – jonrsharpe Commented Jun 14, 2021 at 8:34
- the correct way is to use MemoryRouter as below in the answer stackoverflow.com/a/74820547/6127865 – Abasaheb Gaware Commented Dec 16, 2022 at 5:43
6 Answers
Reset to default 6Below is how I have done this in my tests. * Note I am using typescript
import routeData from 'react-router';
describe('Login Page UnitTests', () => {
const useLocation = jest.spyOn(routeData, 'useLocation');
beforeEach(() => {
useLocation.mockReturnValue({ search: 'testQueryParameters'} as any);
});
// Add unit tests
}
Ensure that you clear the mock to avoid issue with data in subsequent tests
Try mocking the useLocation as jest.fn().mockImplementation
jest.mock('react-router', () => ({
...jest.requireActual("react-router") as {},
useLocation: jest.fn().mockImplementation(() => {
return { pathname: "/testroute" };
})
}));
The correct way to mock useLocation
is below:
import React from 'react';
import ExampleComponent from './ExampleComponent';
import { fireEvent, render } from '@testing-library/react';
import { MemoryRouter} from 'react-router-dom';
import { shallow } from 'enzyme';
const renderComponent = () => {
return (
<MemoryRouter
initialEntries={["/one", "/two", { pathname: 'https://URL/' }]}
initialIndex={1}>
<ExampleComponent />
</MemoryRouter>
);
}
describe('<ExampleComponent />', () => {
it('should render correctly', () => {
shallow(renderComponent());
});
});
Finally found the simplest way to mock useLocation
:
import { useLocation } from 'react-router-dom';
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: jest.fn()
}));
const mockUseLocation = useLocation as jest.MockedFunction<typeof useLocation>;
Now you can mock the return value inside any test case. For example:
it('should render', () => {
mockUseLocation.mockReturnValue({
search: '?param=1'
});
// ...
});
If you're using typescript, you can set a const to define the default values of all the properties:
const defaultUseLocationResult = { pathname: '', search: '', state: {}, hash: '' };
and apply it as follows:
mockUseLocation.mockReturnValue({
...defaultUseLocationResult,
search: '?param=1'
});
This works for me
import * as router from 'react-router';
jest
.spyOn(router, 'useLocation')
.mockReturnValue({ pathname: '/department/details/1213', search: '', state: {}, hash: '' });
I'll post something additional here where you want mock useLocation with state variables.
Code
Here I'm navigating from page1 to page2 and I want to pass a state variable to new route.
navigate('/another/page2', {state: {name: 'john'}});
Then inside page to I can read the location state.
const location = useLocation();
const locationState = location.state as { name?: string };
Test
I can mock useLocation with location state as below.
const mockUseLocation = {
pathname: '/another/page2',
key: '',
search: '',
hash: '',
state: { name: 'mock name' },
};
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useLocation: () => mockUseLocation,
}));
it('test1', async () => {
// write your test here
});