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?
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.
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.
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:
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:
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();
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With