Booster
Booster

Reputation: 181

Mock Router in React testing library and jest

I'm writing unit test with React testing library and Jest and wants to check if my React Component is successfully able to navigate to next Page.

import { fireEvent, render, screen } from "@testing-library/react";
import React from 'react';
import { Provider } from 'react-redux';
import '@testing-library/jest-dom';
import appStore from '../../src/app/redux/store';
import { MemoryRouter, Route } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import { Router } from 'react-router';

const setup = (initialEntries = []) => {
      let inMemHistory = createMemoryHistory({ initialEntries });
      const utils = render(
        <Router history={inMemHistory}>
          <Provider store={appStore}>
            <Component-1 />
          
          </Provider>
        </Router>
      );
 
      const saveButtonElem = screen.getByRole('button', { name: "Save and Continue" });
      return {
            saveButtonElem,
            inMemHistory,
            ...utils,
      }
};

Test:

test('should be able to navigate', async () => {
            const {
                 saveButtonElem,
                  inMemHistory,
                  getByText,
                  queryByText,
                  queryAllByText,
            } = setup(["/component_add"]);

        // Content of Test

            // Saving Config
            fireEvent.click(saveButtonElem);
            console.info("Current Path", inMemHistory.location.pathname);
// Got /component_add on console
// Expected /component_data  after clicking on save button
   
      })

I've tried waiting for 5 second after clicking save button and then tried to print path, but results are same.

Upvotes: 7

Views: 21891

Answers (1)

Karthik R
Karthik R

Reputation: 5786

Assuming you use react-router, You can use the Memory router for the testing which is easier and performant. I might have typos or syntax errors as I type without IDE support. But it should help you with idea on what I propose.

Option 1:

it("should route to the expected page", () => {
  let mockHistory, mockLocation;
  render(
    <MemoryRouter initialEntries={["/currentUri"]}>
      <Component1 />
      // Dummy route that routes for all urls
      <Route
        path="*"
        render={({ history, location }) => {
          mockHistory= history;
          mockLocation= location;
          return null;
        }}
      />
    </MemoryRouter>
  );
  // navigate here on event
  userEvent.click(screen.getByRole('button', {name: /Save/}));
  expect(mockLocation.pathname).toBe("/expectedUri");
});

Option 2:

import { createMemoryHistory } from 'history';
import { Router } from 'react-router';

const renderWithHistory = (initialEntries= [], Component) => {
  let inMemHistory = createMemoryHistory({
    initialEntries
  });
  return { 
      ...render(
        <Router history={inMemHistory}>
          <Component />
        </Router >
      ), history };
};

it("should route to the expected page", () => {
      const { history } = renderWithHistory(['/currentUri'], Component1);
      // navigate here on event
      userEvent.click(screen.getByRole('button', {name: /Save/}));
      expect(history.location.pathname).toBe("/expectedUri");
});

Upvotes: 9

Related Questions