React Router v4 Redirect unit test
Neither of these answers worked for me and took a fair bit of digging so I thought I'd chip in my experience here.
PrivateRoute.js
export const PrivateRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={(props) => (
auth.isAuthenticated
? <Component {...props} />
: <Redirect to={{
pathname: '/',
state: { from: props.location }
}} />
)} />
)
PrivateRoute.spec.js
This test worked for me with no problems whatsoever, it rendered the PrivateComponent
when auth.isAuthenticated
evaluated to true.
it('renders the component when the user is authorised', () => {
auth.login()
expect(auth.isAuthenticated).toBe(true)
const privateRoute = mount(
<MemoryRouter initialEntries={['/privateComponent']}>
<PrivateRoute path='/privateComponent' component={PrivateComponent} />
</MemoryRouter>
)
expect(privateRoute.find('PrivateComponent').length).toEqual(1)
})
This was the test that gave me a lot of issues. At first I was checking for the Redirect
component.
I tried to just do something like
expect(privateRoute.find('Redirect').length).toEqual(1)
But that just wouldn't work, no matter what I did, it just couldn't find the Redirect
component. In the end, I ended up checking the history but couldn't find any reliable documentation online and ended up looking at the React Router codebase.
In MemoryRouter.js (line 30) I saw that it rendered a Router
component. I noticed that it was also passing it's history
as a prop to Router
so I figured I would be able to grab it from there.
I ended up grabbing the history prop from Router
using privateRoute.find('Router').prop('history')
which then finally gave me evidence that a redirect had actually happened, to the correct location, no less.
it('renders a redirect when the user is not authorised', () => {
auth.logout()
expect(auth.isAuthenticated).toBe(false)
const privateRoute = mount(
<MemoryRouter initialEntries={['/privateComponent']}>
<PrivateRoute path='/privateComponent' component={PrivateComponent} />
</MemoryRouter>
)
expect(privateRoute.find('PrivateComponent').length).toEqual(0)
expect(
privateRoute.find('Router').prop('history').location.pathname
).toEqual('/')
})
With this test, you're testing the actual functionality of the PrivateRoute
component and ensuring that it goes where it's saying it's going.
The documentation leaves a lot to be desired. For example, it took a fair bit of digging for me to find out about initialEntries
as a prop for MemoryRouter
, you need this so it actually hits the route and executes the conditional, I spent too long trying to cover both branches only to realise this was what was needed.
Hope this helps someone.
Answering my own question. Basically I'm making a shallow render of my component and verifying that if authenticated is rendering the redirect component otherwise the App one. Here the code:
function setup() {
const enzymeWrapper = shallow(<AuthenticatedApp />);
return {
enzymeWrapper
};
}
describe("AuthenticatedApp component", () => {
it("renders Redirect when user NOT autheticated", () => {
authApi.isUserAuthenticated = jest.fn(() => false);
const { enzymeWrapper } = setup();
expect(enzymeWrapper.find(Redirect)).toHaveLength(1);
});
it("renders AppWithData when user autheticated", () => {
authApi.isUserAuthenticated = jest.fn(() => true);
const { enzymeWrapper } = setup();
expect(enzymeWrapper.find(AppWithData)).toHaveLength(1);
});
});