How to Test HashRouter in React

Testing routing in React applications is crucial for ensuring a seamless user experience, but testing components that rely on HashRouter can be tricky due to how it manages the URL hash. This article provides a straightforward guide on how to test React components wrapped in a HashRouter using React Testing Library and Jest. You will learn the industry-standard approach of using MemoryRouter for unit tests, as well as how to test actual HashRouter behavior by manipulating the window location hash directly.

The most reliable and recommended way to test components that use HashRouter is to substitute it with MemoryRouter in your test environment. Because HashRouter relies on the browser’s window history, it can introduce side effects and state leakage between tests. MemoryRouter, on the other hand, stores its locations in memory, making it ideal for isolated unit tests.

Here is how you can test your routed components using MemoryRouter:

import { render, screen } from '@testing-library/react';
import { MemoryRouter, Routes, Route } from 'react-router-dom';
import AboutPage from './AboutPage';

test('renders the AboutPage component when navigating to /about', () => {
  render(
    <MemoryRouter initialEntries={['/about']}>
      <Routes>
        <Route path="/about" element={<AboutPage />} />
      </Routes>
    </MemoryRouter>
  );

  // Assert that the element unique to the About Page is in the document
  expect(screen.getByText(/about us/i)).toBeInTheDocument();
});

By using MemoryRouter and passing the target route to the initialEntries prop, you can simulate any application state without touching the actual browser URL.

Method 2: Testing HashRouter Directly

If your test suite strictly requires you to verify the actual behavior of HashRouter and how it interacts with the window object, you can test it directly by manually updating the window.location.hash before rendering the component.

import { render, screen } from '@testing-library/react';
import { HashRouter, Routes, Route } from 'react-router-dom';
import AboutPage from './AboutPage';

describe('HashRouter Integration', () => {
  afterEach(() => {
    // Clean up the hash after each test to prevent test cross-contamination
    window.location.hash = '';
  });

  test('navigates to the correct route based on window hash', () => {
    // Set the hash manually before rendering
    window.location.hash = '#/about';

    render(
      <HashRouter>
        <Routes>
          <Route path="/about" element={<AboutPage />} />
        </Routes>
      </HashRouter>
    );

    expect(screen.getByText(/about us/i)).toBeInTheDocument();
  });
});

Important Considerations for Direct Testing