'How to use MemoryRouter in order to test useParams call
I have a hypothetic React component named Component.ts
with a code structure similar to that:
import React, { FC } from 'react';
import { useParams } from 'react-router-dom';
export const Guide: FC<{}> = () => {
const { serviceId } = useParams();
return (
<p>{serviceId}</p>
)
}
In order to test the behaviour of this component I was trying to do something similar to the following in my Component.test.ts
file:
import React from 'react';
import { render } from '@testing-library/react';
import { Component } from './Component';
import { Route, MemoryRouter } from 'react-router-dom';
test('my Component test', async () => {
const someServiceId = 'some-service-id';
const { findByText } = render(
<MemoryRouter initialEntries={[`guides/${someServiceId}`]}>
<Route path='guides/:serviceId'>
<Guide />
</Route>
</MemoryRouter>
);
expect(await findByText(someServiceId)).toBeInTheDocument();
});
My tests were working when I was using version 5.2.2
of react-router-dom
but it is failing since I updated to 6.0.0-beta.0
. Jest is showing up the following message when running the tests:
Relative pathnames are not supported in createMemoryHistory({ initialEntries }) (invalid entry: "guides/some-service-id")
Solution 1:[1]
After much searching, I found the answer in the test suite.
The trick in 6.0.0-beta.0 is to wrap your <Route />
's in <Routes />
. Also note the components are imported from react-router
instead of react-router-dom
:
import {
MemoryRouter,
Routes,
Route,
} from 'react-router';
test('my Component test', async () => {
const someServiceId = 'some-service-id';
const { findByText } = render(
<MemoryRouter initialEntries={[`guides/${someServiceId}`]}>
<Routes>
<Route path='guides/:serviceId'>
<Guide />
</Route>
</Routes>
</MemoryRouter>
);
await waitFor(() => expect(findByText(someServiceId)).toBeInTheDocument());
});
Solution 2:[2]
this worked for me
import WarehouseDetailsComponent from '../../containers/WarehouseDetailsPage'
import { render} from '@testing-library/react'
import { Route, MemoryRouter, Routes } from 'react-router-dom'
describe('WarehouseDetails', () => {
test('should display warehouse and user details', async () => {
render(
<MemoryRouter initialEntries={['explore/1234']}>
<Routes>
<Route path="/explore/:id" element={<WarehouseDetailsComponent />} />
</Routes>
</MemoryRouter>
)
// assertions
})
Solution 3:[3]
MemoryRouter didn't worked for me
I was receiving this as warn:
- Relative pathnames are not supported in createMemoryHistory({ initialEntries }) (invalid entry: "my-route/15")
- No routes matched location "my-route/15"
So I figured it as a good option and worked for me.
import { render, screen, waitFor } from '@testing-library/react';
import { BrowserRouter as Router, Navigate, Route, Routes } from 'react-router-dom';
import { Provider } from 'react-redux';
import { store } from '../../Redux/store';
import MyComponent from './index';
describe('My component test', () => {
it('should access right route', async () => {
render(
<Provider store={store}>
<Router>
<Routes>
<Route path="/" element={<Navigate to="/my-route/15" replace />} />
<Route path="/my-route/:id" element={<MyComponent />} />
</Routes>
</Router>
</Provider>,
);
await waitFor(() => {
expect(screen.getByText('Something should be rendered')).toBeInTheDocument();
});
});
});
Solution 4:[4]
MemoryRouter worked for me. See the example below.
import { cleanup, render, screen } from "@testing-library/react"
import { QueryClient, QueryClientProvider } from "react-query";
import Card from "../../../components/Card"
import { MemoryRouter } from "react-router-dom";
import { Route } from "react-router-dom";
import { create } from "react-test-renderer";
describe("test card component", () => {
afterEach(() => {
cleanup();
});
const mockItem = {
name: "Test",
summary: "This is test summary",
}
const MockComponent = () => {
const queryClient = new QueryClient();
const id = '12';
return (
<QueryClientProvider client={queryClient}>
<MemoryRouter initialEntries={[`post/${id}`]}>
<Route path='post/:id'>
<Card data={mockItem} />
</Route>
</MemoryRouter>
</QueryClientProvider>
)
}
const setup = () => {
return render(<MockComponent />);
}
it("should render the component", () => {
setup()
const cardElement = screen.getByTestId('card')
expect(cardElement).toBeInTheDocument();
expect(cardElement).toHaveTextContent(mockItem.name)
expect(cardElement).toHaveTextContent(mockItem.summary)
})
it("should match the snapshot", () => {
const tree = create(<MockComponent />).toJSON();
expect(tree).toMatchSnapshot();
})
})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | likesalmon |
Solution 2 | |
Solution 3 | Felipe Ernesto Schmidt |
Solution 4 | shreejana |