Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing redirect after submit with React Testing Library

I'm trying to test a login component. Specifically that it redirects on a successful login. It works fine when testing it manually. But in my test it never does the redirect and it can therefor not find the "Logout" link:

test('successfully logs the in the user', async () => {
  const fakeUserResponse = {success: true, token: 'fake_user_token'}
  jest.spyOn(window, 'fetch').mockImplementationOnce(() => {
    return Promise.resolve({
      json: () => Promise.resolve(fakeUserResponse),
    })
  })
  const { getByText, getByLabelText, findByTestId } = render(<Router><Login /></Router>)

  fireEvent.change(getByLabelText(/email/i), {target: {value: '[email protected]'}})
  fireEvent.change(getByLabelText(/password/i), {target: {value: 'password1234'}})
  fireEvent.click(getByText(/submit/i))

  await waitForElement(() => getByText(/logout/i));
})

I'm redirecting with react-router version 4, like so:

{state.resolved ? <Redirect to="/" /> : null}

Am I going about this the wrong way?

like image 660
dan-klasson Avatar asked Oct 13 '19 11:10

dan-klasson


People also ask

How to check that a React component successfully redirects to another page?

You’ve set up react-testing-library with Jest and react-router. You want to check that a component successfully redirects to another page. But how? Your React application comes with a protected route. If a user is not authenticated, the app should redirect the user to the login screen.

How to test the form's submit flow?

Finally it's time to test the form's submit flow. In order to test it, we fill all the fields, submit the form and then validate that our mockSave function has been called with expected values.

How can I mock the redirect component's implementation?

You can mock the Redirect component's implementation to show some text including the path instead of redirecting to it: jest.mock ('react-router-dom', () => { return { Redirect: jest.fn ( ( { to }) => `Redirected to $ {to}`), }; }); and expect your component to display the text with the correct path:

What happens if a user is not authenticated in react?

Your React application comes with a protected route. If a user is not authenticated, the app should redirect the user to the login screen. You’ve managed to set up react-router-dom for your component. For example, here’s an excerpt from a UserStatus.jsx component that only an authenticated user should be able to access:


2 Answers

You can mock the Redirect component's implementation to show some text including the path instead of redirecting to it:

jest.mock('react-router-dom', () => {
  return {
    Redirect: jest.fn(({ to }) => `Redirected to ${to}`),
  };
});

and expect your component to display the text with the correct path:

expect(screen.getByText('Redirected to /')).toBeInTheDocument();
like image 57
Iwazaru Avatar answered Sep 22 '22 06:09

Iwazaru


Personally I mock the history.replace function that is used by the Redirect component.

const history = createBrowserHistory();
history.replace = jest.fn();

render(
  <Router history={history} >
    <Component />
  </Router>
);

// trigger redirect

expect(history.replace).toHaveBeenCalledWith(expect.objectContaining({
  "pathname": "/SamplePath",
  "search": "?SampleSearch",
  "state": { "Sample": "State" }
}));

This allows you to check for more than just the correct path. Please ensure you are using Router and not BrowserRouter in your test. The latter does not accept a history prop.

like image 34
4FCG Avatar answered Sep 23 '22 06:09

4FCG