Search code examples
reactjsreact-routerreact-router-dom

Setting routes for BrowserRouter in tests


I have a test case where I need to start on the Signup page (/signup), and on successful signup, the application should navigate to the Home page (/). I am currently using the MemoryRouter to set the initial route to /signup and everything works well. See below:

import React from 'react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter } from 'react-router';
import { Route, Routes } from 'react-router-dom';
import { render, screen } from '../../test/test-utils';
import { SignUpPage } from './SignUpPage';

const MockHomePage = () => <div>MockHomePage</div>;

describe('<SignUp />', () => {
  test('navigates to Home page on successful signup', async () => {
    render(
      <MemoryRouter initialEntries={['/signup']}>
        <Routes>
          <Route path="/" element={<MockHomePage />} />
          <Route path="/signup" element={<SignUpPage />} />
        </Routes>
      </MemoryRouter>
    );

    // Enter valid user info and submit form
    userEvent.type(screen.getByLabelText('Full Name'), 'John Smith');
    userEvent.type(screen.getByLabelText('Email'), 'johnsmith@gmail.com');
    userEvent.type(screen.getByLabelText('Password'), 'let-me-in');
    userEvent.type(screen.getByLabelText('Confirm Password'), 'let-me-in');
    userEvent.click(screen.getByText('Sign up'));

    // Expect to see the Home page
    expect(await screen.findByText('MockHomePage')).toBeInTheDocument();
  });
});

However, I'd like to use BrowserRouter in my tests instead of MemoryRouter (I understand that it is the recommended way since it is closer to what the real app would use). Unfortunately, BrowserRouter does not have the initialEntries prop (I am using React Router v6 beta.7). Is there a way to force BrowserRouter to start at /signup?

I tried the location API like this:

window.location.href = 'http://localhost:3000/signup';

However I get a jsdom error saying that this API is not implemented:

Error: Not implemented: navigation (except hash changes)
  at module.exports (/Users/naresh/projects/accelerated-news/node_modules/jsdom/lib/jsdom/browser/not-implemented.js:9:17)

Is there any other way?

Using react-router-dom v6.


Solution

  • I believe you need to use window.history.pushState() so it would look something like this:

    test('navigates to Home page on successful signup', async () => {
      window.history.pushState({}, '', '/signup')
    
      render(
        <BrowserRouter>
          <Routes>
            <Route path="/" element={<MockHomePage />} />
            <Route path="/signup" element={<SignUpPage />} />
          </Routes>
        </BrowserRouter>
      );
    
      // etc..
    });