Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I'm new to testing with jest and I want to test the following code.
import React from "react";
import "./ButtonLogin.css";
import { Link } from 'react-router-dom';
function ButtonLogin() {
return (
<Link to="/login"> <button className="button-login">Iniciar sesión</button></Link>
export default ButtonLogin;
import { MemoryRouter } from 'react-router-dom';
import { render, fireEvent, Link } from '@testing-library/react';
import { ButtonLogin } from './ButtonLogin';
it('routes to a new route', async () => {
ButtonLogin = jest.fn();
const { getByText } = render(
<MemoryRouter ButtonLogin={ButtonLogin}>
<Link to="/login">Iniciar sesión</Link>
</MemoryRouter>
fireEvent.click(getByText('Iniciar sesión'));
expect(ButtonLogin).toHaveBeenCalledWith('/login');
I have performed the following test but it fails and I get the following error in line 9.
routes to a new route
"ButtonLogin" is read-only.
–
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.
ButtonLogin.tsx
:
import React from 'react';
import { Link } from 'react-router-dom';
function ButtonLogin() {
return (
<Link to="/login">
<button className="button-login">Iniciar sesión</button>
</Link>
export default ButtonLogin;
ButtonLogin.test.tsx
:
import { fireEvent, render } from '@testing-library/react';
import React from 'react';
import { Router } from 'react-router-dom';
import ButtonLogin from './ButtonLogin';
import { createMemoryHistory } from 'history';
describe('ButtonLogin', () => {
test('should change current location to login when button is clicked', () => {
const history = createMemoryHistory({ initialEntries: ['/home'] });
const { getByText } = render(
<Router history={history}>
<ButtonLogin />
</Router>
expect(history.location.pathname).toBe('/home');
fireEvent.click(getByText('Iniciar sesión'));
expect(history.location.pathname).toBe('/login');
test result:
PASS examples/69878146/ButtonLogin.test.tsx (10.675 s)
ButtonLogin
✓ should pass (41 ms)
-----------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
ButtonLogin.tsx | 100 | 100 | 100 | 100 |
-----------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 11.722 s, estimated 12 s
package version: "react-router-dom": "^5.2.0"
–
Late to this, but React Router Dom v6 can handle tests this way.
import {BrowserRouter, MemoryRouter} from "react-router-dom";
const reactRouterContext = (children: any) => {
if (isTest) {
return <MemoryRouter initialEntries={['/']}>{children}</MemoryRouter>
return <BrowserRouter>{children}</BrowserRouter>
EDIT - adding implementation per request:
const reactRouterContext = (children: any) => {
if (isTest) {
return <MemoryRouter initialEntries={['/']}>{children}</MemoryRouter>
if (this.props.browserRouter ?? true) {
return <BrowserRouter>{children}</BrowserRouter>
return <HashRouter>{children}</HashRouter>
return reactRouterContext(<>
<Routes>
{'' === user_id
<Route path="/login" element={<Login/>}/>
<Route path="/register" element={<Register/>}/>
<Route path="/forgot-password" element={<ForgetPassword/>}/>
<Route path="/recover-password" element={<RecoverPassword/>}/>
<Route path="/*" element={<Navigate to={'/login'}/>}/>
: <Route path="/" element={<Main/>}>
<Route path="/sub-menu-2" element={<Blank/>}/>
<Route path="/sub-menu-1" element={<SubMenu/>}/>
<Route path="/blank" element={<Blank/>}/>
<Route path="/profile" element={<Profile/>}/>
<Route path="/" element={<Dashboard/>}/>
<Route path="/*" element={<Navigate to={'/'}/>}/>
</Route>}
</Routes>
<ToastContainer
autoClose={3000}
draggable={false}
position="top-right"
hideProgressBar={false}
newestOnTop
closeOnClick
rtl={false}
pauseOnHover
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.