Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simplest test for react-router's Link with @testing-library/react

I'm trying to understand how to best test that react-router behaves as expected with @testing-library/react.

The simplest test I can think of, is to verify that clicking a link changes the URL. I know that ideally I should test that clicking on a link renders a new component, but that adds a lot of boilerplate to the test.

So here's my failing example:

import { MemoryRouter } from 'react-router-dom';
import { render } from '@testing-library/react';
import { createMemoryHistory } from 'history';

it('routes to a new route', async () => {
  const history = createMemoryHistory();
  const { getByText } = render(
    <MemoryRouter history={history}>
      <Link to="/hello">Click me</Link>
    </MemoryRouter>
  );

  fireEvent.click(getByText('Click me'));
  await waitFor(() => expect(history.location.pathname).to.equal('/hello')); // Fails
});
like image 399
Florian Bienefelt Avatar asked May 18 '20 12:05

Florian Bienefelt


People also ask

How do I test my Router Jest?

You can use the createMemoryHistory function and Router component to test it. Create a memory history with initial entries to simulate the current location, this way we don't rely on the real browser environment. After firing the click event, assert the pathname is changed correctly or not.

How do I test a link in React?

Link.test.js import React from 'react'; import renderer from 'react-test-renderer'; import { Link } from 'react-router-dom'; test('Link matches snapshot', () => { const component = renderer. create( <Link to="#" /> ); let tree = component. toJSON(); expect(tree). toMatchSnapshot(); });

How do I use Router link in React?

To add the link in the menu, use the <NavLink /> component by react-router-dom . The NavLink component provides a declarative way to navigate around the application. It is similar to the Link component, except it can apply an active style to the link if it is active.

What is react router and why do I need It?

So your React app, like a lot of modern apps, uses React Router to get users from one page to another. And you, like any thorough tester, want to account for React Router in your testing.

Does jest need testing library for react router?

No wonder Jest is confused. As luck would have it, Testing Library makes it easy to adapt its render function to wrap with whatever your UI elements might need — be it the React Router provider, or any other type of provider (see “Including the Router and other Providers” below for rendering with multiple providers).

What is testing library in react?

As luck would have it, Testing Library makes it easy to adapt its render function to wrap with whatever your UI elements might need — be it the React Router provider, or any other type of provider (see “Including the Router and other Providers” below for rendering with multiple providers).

Why can’t I find the match object in react router switch?

It turns out, when you remove components from the React Router Switch component, you don’t have access to the match object (which contains the URL params, along with other route information). You can fix this by using useRouteMatch in Locations.jsx instead of useParams:


1 Answers

This is how I do it : mocking history.push, then spy on its calls.

import { MemoryRouter } from 'react-router-dom';
import { render } from '@testing-library/react';
import { createMemoryHistory } from 'history';

it('routes to a new route', async () => {
  const history = createMemoryHistory();

  // mock push function
  history.push = jest.fn();

  const { getByText } = render(
    <MemoryRouter history={history}>
      <Link to="/hello">Click me</Link>
    </MemoryRouter>
  );

  // could be userEvent.click
  // https://testing-library.com/docs/ecosystem-user-event/#clickelement-eventinit-options
  fireEvent.click(getByText('Click me'));

  // spy on push calls, assert on url (parameter)
  expect(history.push).toHaveBeenCalledWith('/hello');
});
like image 64
Florian Motteau Avatar answered Oct 10 '22 17:10

Florian Motteau