Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing PrivateRoute in react-router-dom

https://reacttraining.com/react-router/web/example/auth-workflow

My implementtaion of the Private-Route in the react-router-dom docs

function PrivateRoute({ authenticated, ownProps }) {

    let {component:Component, ...rest} = ownProps


     //PrivateRoute, If  not authenicated ie  false, redirect
    return (
      <Route
      //  JSX Spread sttributes to get path for Route
        {...rest}
        render={() =>  authenticated ? (
            <Component />
          ) : 
          <Redirect
              to={{pathname: "/" }}
            />
        }
      />
    );
  }

  export default PrivateRoute

PrivateRoute been a connected component getting authentication status from Redux-Store.

I am trying to test the connected component, using redux-mock-store and mount from enzyme.

import configureStore from 'redux-mock-store'
const mockStore = configureStore()
const authStateTrue = {auth: {AUTHENTICATED: true}}; 

 test('Private path renders a component when auntentication is true', () => {

    const store = mockStore(authStateTrue)
    const AComponent = () => <div>AComponent</div>
    const props = {path:"/aprivatepath" ,component:<AComponent/>};

    let enzymeWrapper = mount(<Provider store={store}>
                                    <BrowserRouter>
                                    <PrivateRoute path="/aprivatepath" component={AComponent}/>
                                    </BrowserRouter>                              
                          </Provider>);


    expect(enzymeWrapper.exists(AComponent)).toBe(true)
  });

The test is failing enter image description here

Seems the component passed to the PrivateRoute is not existing even if the authentication in state is true.

How do I test a component is rendered or redirected in PrivateRoute.

like image 303
Shorn Jacob Avatar asked Jun 24 '19 05:06

Shorn Jacob


People also ask

How do you find the current path in react Dom router?

Use the useLocation() hook to get the current route with React Router, e.g. const location = useLocation() . The hook returns the current location object. For example, you can access the pathname as location. pathname .

What are the public and private routes in react router?

The /, /pricing, and /login routes will be publicly accessible while our /dashboard and /settings route will be private. For now, we’ll just render them like normal Route s though. At this point we’re not doing anything fancy. We’ve successfully mapped the app’s location to a few components, typical React Router stuff.

How to test the routes in react using jest?

One advantage is that we can test the 404 route easily by passing a pathname in initial entry array which is not handled by any component, and assert that the NoMatch is present. So we saw both the ways to test the routes in react using jest - mapping the routes and creating the object, or using the memory router.

How do I set up a route in react?

You could use auth-react-router package npmjs.com/package/auth-react-router It provides a really simple API to define your routes and few more configurations (like redirect routes for authorized and unauthorized routes, fallback component for each of the routes) Just define your routes path and pages component and it will work

How to render a route component in react-router-Dom 6?

In react-router-dom version 6 there is no render prop for the Route component. You can also simplify your PrivateRoute wrapper component a bit, it doesn't need to render more Routes and Route components. Conditionally render the component's children or navigate to log in.


1 Answers

Here is the unit test solution:

privateRoute.tsx

import React from 'react';
import { Route, Redirect } from 'react-router';

function PrivateRoute({ authenticated, ownProps }) {
  const { component: Component, ...rest } = ownProps;
  return <Route {...rest} render={() => (authenticated ? <Component /> : <Redirect to={{ pathname: '/' }} />)} />;
}

export default PrivateRoute;

privateRoute.test.tsx:

import PrivateRoute from './privateRoute';
import React from 'react';
import { mount } from 'enzyme';
import { MemoryRouter, Redirect } from 'react-router';

describe('56730186', () => {
  it('should render component if user has been authenticated', () => {
    const AComponent = () => <div>AComponent</div>;
    const props = { path: '/aprivatepath', component: AComponent };

    const enzymeWrapper = mount(
      <MemoryRouter initialEntries={[props.path]}>
        <PrivateRoute authenticated={true} ownProps={props} />
      </MemoryRouter>,
    );

    expect(enzymeWrapper.exists(AComponent)).toBe(true);
  });

  it('should redirect if user is not authenticated', () => {
    const AComponent = () => <div>AComponent</div>;
    const props = { path: '/aprivatepath', component: AComponent };

    const enzymeWrapper = mount(
      <MemoryRouter initialEntries={[props.path]}>
        <PrivateRoute authenticated={false} ownProps={props} />
      </MemoryRouter>,
    );
    const history: any = enzymeWrapper.find('Router').prop('history');
    expect(history.location.pathname).toBe('/');
  });
});

Unit test results with 100% coverage:

 PASS  src/stackoverflow/56730186/privateRoute.test.tsx (15.063s)
  56730186
    ✓ should render component if user has been authenticated (96ms)
    ✓ should redirect if user is not authenticated (23ms)

------------------|----------|----------|----------|----------|-------------------|
File              |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
------------------|----------|----------|----------|----------|-------------------|
All files         |      100 |      100 |      100 |      100 |                   |
 privateRoute.tsx |      100 |      100 |      100 |      100 |                   |
------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        17.053s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/56730186

like image 111
slideshowp2 Avatar answered Sep 22 '22 13:09

slideshowp2