How to test components using new react router hooks?

后端 未结 6 492
庸人自扰
庸人自扰 2020-12-08 01:52

Until now, in unit tests, react router match params were retrieved as props of component. So testing a component considering some specific match, with specific url parameter

相关标签:
6条回答
  • 2020-12-08 02:29

    If using the enzyme library, I found a much less verbose way to solve the problem (using this section from the react-router-dom docs):

    import React from 'react'
    import { shallow } from 'enzyme'
    import { MemoryRouter } from 'react-router-dom'
    import Navbar from './Navbar'
    
    it('renders Navbar component', () => {
      expect(
        shallow(
          <MemoryRouter>
            <Navbar />
          </MemoryRouter>
        )
      ).toMatchSnapshot()
    })

    0 讨论(0)
  • 2020-12-08 02:36

    I am trying to get if the push function in useHistory is called by doing that but I can't get the mocked function calls...

    const mockHistoryPush = jest.fn();
    
    jest.mock('react-router-dom', () => ({
        ...jest.requireActual('react-router-dom'),
        useHistory: () => ({
          push: mockHistoryPush,
        }),
      }));
    
    fireEvent.click(getByRole('button'));
    expect(mockHistoryPush).toHaveBeenCalledWith('/help');
    

    It says that mockHistoryPush is not called when the button has onClick={() => history.push('/help')}

    0 讨论(0)
  • 2020-12-08 02:42

    I looked at the tests for hooks in the react-router repo and it looks like you have to wrap your component inside a MemoryRouter and Route. I ended up doing something like this to make my tests work:

    import {Route, MemoryRouter} from 'react-router-dom';
    
    ...
    
    const renderWithRouter = ({children}) => (
      render(
        <MemoryRouter initialEntries={['blogs/1']}>
          <Route path='blogs/:blogId'>
            {children}
          </Route>
        </MemoryRouter>
      )
    )
    

    Hope that helps!

    0 讨论(0)
  • 2020-12-08 02:43

    The way I ended up solving it was by mocking the hooks in my tests using jest.mock:

    // TeamPage.test.js
    jest.mock('react-router-dom', () => ({
      ...jest.requireActual('react-router-dom'), // use actual for all non-hook parts
      useParams: () => ({
        companyId: 'company-id1',
        teamId: 'team-id1',
      }),
      useRouteMatch: () => ({ url: '/company/company-id1/team/team-id1' }),
    }));
    

    I use jest.requireActual to use the real parts of react-router-dom for everything except the hooks I'm interested in mocking.

    0 讨论(0)
  • 2020-12-08 02:45

    In your component use hooks as below

    import {useLocation} from 'react-router';
    
    const location = useLocation()
    

    In your test spy on reactRouter Object as below

    import routeData from 'react-router';
    
    const mockLocation = {
      pathname: '/welcome',
      hash: '',
      search: '',
      state: ''
    }
    beforeEach(() => {
      jest.spyOn(routeData, 'useLocation').mockReturnValue(mockLocation)
    });
    
    0 讨论(0)
  • 2020-12-08 02:52

    If you're using react-testing-library for testing, you can get this mock to work like so.

    jest.mock('react-router-dom', () => ({
        ...jest.requireActual('react-router-dom'),
        useLocation: () => ({ state: { email: 'school@edu.ng' } }),
    }));
    
    export const withReduxNRouter = (
        ui,
        { store = createStore(rootReducer, {}) } = {},
        {
        route = '/',
        history = createMemoryHistory({ initialEntries: [ route ] }),
        } = {}
    ) => {
        return {
        ...render(
            <Provider store={store}>
            <Router history={history}>{ui}</Router>
            </Provider>
        ),
        history,
        store,
        };
    };
    

    You should have mocked react-router-dom before it has been used to render your component. I'm exploring ways to make this reusable

    0 讨论(0)
提交回复
热议问题