javascriptreactjsjestjsreact-router-domreact-test-renderer

mock usePrompt in react-router-dom v6


Prompt.js

import { unstable_usePrompt as usePrompt } from 'react-router-dom';

// eslint-disable-next-line react/prop-types
export default function Prompt({ when, message }) {
  usePrompt({ when, message });
  return null;
}

Prompt.test.js

import {
  createMemoryRouter,
  RouterProvider,
} from 'react-router-dom';
import renderer from 'react-test-renderer';

import Prompt from '../Prompt';


const mockedUsePrompt = jest.fn();

jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'),
  unstable_usePrompt: () => mockedUsePrompt,
}));

describe('Prompt', () => {
  it('should call usePrompt with parameter', () => {
    const router = createMemoryRouter(
      [
        {
          path: '/',
          element: <Prompt when message="Are you sure?" />,
        },
      ],
      { initialEntries: ['/'] },
    );
    const component = renderer.create(
      <RouterProvider router={router} />,
    );
    const tree = component.toJSON();
    expect(tree).toMatchSnapshot();

    expect(mockedUsePrompt).toHaveBeenCalledWith({ when: true, message: 'Are you sure?' });
  });
});

How can I check calling usePrompt with arguments?

this line expect(mockedUsePrompt).toHaveBeenCalledWith({ when: true, message: 'Are you sure?' }); doesn't work


Solution

  • You didn't mock unstable_usePrompt correctly. See below working example:

    Prompt.js:

    import { unstable_usePrompt as usePrompt } from 'react-router-dom';
    
    console.log("🚀 ~ file: Prompt.js:2 ~ usePrompt:", usePrompt)
    
    export default function Prompt({ when, message }) {
      usePrompt({ when, message });
      return null;
    }
    

    Prompt.test.js:

    import { createMemoryRouter, RouterProvider, unstable_usePrompt } from 'react-router-dom';
    import renderer from 'react-test-renderer';
    import Prompt from './Prompt';
    
    jest.mock('react-router-dom', () => ({
      ...jest.requireActual('react-router-dom'),
      unstable_usePrompt: jest.fn(),
    }));
    
    describe('Prompt', () => {
      it('should call usePrompt with parameter', () => {
        const router = createMemoryRouter(
          [
            {
              path: '/',
              element: <Prompt when message="Are you sure?" />,
            },
          ],
          { initialEntries: ['/'] },
        );
        renderer.create(<RouterProvider router={router} />);
        expect(unstable_usePrompt).toHaveBeenCalledWith({ when: true, message: 'Are you sure?' });
      });
    });
    

    Test result:

      console.log
        🚀 ~ file: Prompt.js:2 ~ usePrompt: [Function: mockConstructor] {
          _isMockFunction: true,
          getMockImplementation: [Function (anonymous)],
          mock: [Getter/Setter],
          mockClear: [Function (anonymous)],
          mockReset: [Function (anonymous)],
          mockRestore: [Function (anonymous)],
          mockReturnValueOnce: [Function (anonymous)],
          mockResolvedValueOnce: [Function (anonymous)],
          mockRejectedValueOnce: [Function (anonymous)],
          mockReturnValue: [Function (anonymous)],
          mockResolvedValue: [Function (anonymous)],
          mockRejectedValue: [Function (anonymous)],
          mockImplementationOnce: [Function (anonymous)],
          mockImplementation: [Function (anonymous)],
          mockReturnThis: [Function (anonymous)],
          mockName: [Function (anonymous)],
          getMockName: [Function (anonymous)]
        }
    
          at Object.<anonymous> (src/Prompt/Prompt.js:2:9)
    
     PASS  src/Prompt/Prompt.test.js
      Prompt
        ✓ should call usePrompt with parameter (9 ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        0.176 s, estimated 1 s
    Ran all test suites matching /\/home\/lindu\/workspace\/mrdulin\/test_prompt_component\/src\/Prompt\/Prompt.test.js/i.
    
    Watch Usage: Press w to show more.