Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing react component enclosed in withRouter (preferably using jest/enzyme)

I have a React component which is enclosed within Higher Order Component withRouter as below:

module.exports = withRouter(ManageProfilePage); 

My routes are as below:

<Route path="/" component={AdrApp}>     <IndexRoute component={Login}/>     <Route component={CheckLoginStatus}>         <Route path="manage-profiles/:profileId" component=         {ManageProfilesPage}/>      </Route>     <Route path="*" component={notFoundPage}/> </Route> 

I need to use once of the Router lifecycle methods, that is why I need withRouter:

class ManageProfilePage extends React.Component {     componentDidMount() {     this.props.router.setRouteLeaveHook(this.props.route, () => {       ...     })     render(){     ...      } } 

I need to test this component using Jest/Enzyme and I wrote the test case as below:

describe('manage profile page test suite', () => {       it('snapshot test', () => {          const setRouteLeaveHook =jest.fn();          let wrapper = shallow(             <ManageProfilePage params={{id : 25, router:          setRouteLeaveHook}}/>         );       expect(wrapper).toMatchSnapshot();     })    })  

The issue is it is not rendering one level deep. I am pasting the snapshot below:

exports[`manage drug term page test suites snapshot test 1`] = ` <ManageProfilePage   params={     Object {       "id": 25,       "router": [Function],     }   } /> `; 

Is there any different way I can write my test case so that I am able to render ManageProfilePage atleast 1 level deep? It is not able to render as it is enclosed within WithRouter? How do we test these type of components?

like image 572
Amol Aggarwal Avatar asked May 26 '17 15:05

Amol Aggarwal


People also ask

How do you use withRouter in React?

React Router has an higher-order component called withRouter with which we can pass in the React Router's history, location, and match objects to our React components as props. To use withRouter , you should wrap your App component inside withRouter() as a parameter.

Should I use enzyme with jest?

Jest can be used without Enzyme, and snapshots can be created and tested perfectly fine. But the Enzyme adds additional functionality to it. An enzyme can also be used without Jest, but we need any other test runner paired with it. Jest:- Jest as a test runner, assertion library, and mocking library.

Why do we need enzymes with jest?

Many people choose to use Jest and Enzyme together to test their React web applications. They use Jest as a test runner and assertion library, then use Enzyme to build the tests for their UI. This results in slimmer, cleaner testing code that's also easier to debug when a test breaks.

Can you use jest with React?

Jest is a JavaScript testing framework that allows developers to run tests on JavaScript and TypeScript code and can be easily integrated with React JS.


2 Answers

Normally if we try to test such components we won’t be able to render it as it is wrapped within WithRouter (WithRouter is a wrapper over a component which provides Router props like match, route and history to be directly used within the component). module.exports = withRouter(ManageProfilePage);

To render such components, we have to explicitly tell it to render the wrapped component using WrappedComponent keyword. For Eg. we will use below code for snapshot test:

describe('manage profile page test suite', () => {       it('snapshot test', () => {          const setRouteLeaveHook =jest.fn();          let wrapper = shallow(             <ManageProfilePage.WrappedComponent params={{id : 25, router:          setRouteLeaveHook}}/>         );       expect(wrapper).toMatchSnapshot();     })    })  

This will tell enzyme to do shallow rendering (Shallow Rendering renders only that particular component and skips child components) for ManageProfilePage which is wrapped component within WithRouter.

like image 77
Amol Aggarwal Avatar answered Oct 06 '22 03:10

Amol Aggarwal


Shallow rendering will only render one level, that's part of the specs for it.

you can use Mount which will render the whole tree, but I don't think you can limit how many levels deep it will render.

In any case, when using High Order Components I usually just export the base component as well(before wrapping it), this way I can do all my tests without the wrapper, and simply pass mocks for the required providers.

same thing with a Connect component with redux, you export your regular component and test the different props on that, instead of the connected one.

also note that some with... wrappers do not expose the inner instance(some do, but some don't) , so testing on your own component instead of the wrapper helps there as well.

like image 33
Patrick Avatar answered Oct 06 '22 04:10

Patrick