Search code examples
reactjstypescriptreact-router-dom

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 from 'react';
import { useParams } from 'react-router-dom';

export const Guide = () => {

  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

  • 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());
    });