How to test react-router with enzyme
You can wrap your router inside a component in order to test it.
Routes.jsx
export default props => (
<Router history={browserHistory}>
...
<Route path="nurse/authorization" component{NurseAuthorization}/>
...
</Route>
)
index.js
import Routes from './Routes.jsx';
...
ReactDOM.render(<Routes />, document.getElementById('root'));
Then you have to shallow render your Routes
component, and you are able to create an object map to check the correspondance between path and related component.
Routes.test.js
import { shallow } from 'enzyme';
import { Route } from 'react-router';
import Routes from './Routes.jsx';
import NurseAuthorization from './NurseAuthorization.jsx';
it('renders correct routes', () => {
const wrapper = shallow(<Routes />);
const pathMap = wrapper.find(Route).reduce((pathMap, route) => {
const routeProps = route.props();
pathMap[routeProps.path] = routeProps.component;
return pathMap;
}, {});
// { 'nurse/authorization' : NurseAuthorization, ... }
expect(pathMap['nurse/authorization']).toBe(NurseAuthorization);
});
EDIT
In case you want to additionally handle the case of render props:
const pathMap = wrapper.find(Route).reduce((pathMap, route) => {
const routeProps = route.props();
if (routeProps.component) {
pathMap[routeProps.path] = routeProps.component;
} else if (routeProps.render) {
pathMap[routeProps.path] = routeProps.render({}).type;
}
return pathMap;
}, {});
It will work only in case you render directly the component you want to test (without extra wrapper).
<Route path="nurse/authorization" render{() => <NurseAuthorization />}/>
This will only pass if the component is rendered successfully: It works with Redux and react-router including hooks.
import React from "react";
import { expect } from "chai";
import { mount } from "enzyme";
import { MemoryRouter, Route } from "react-router-dom";
import { createMockStore } from "redux-test-utils";
import { Provider } from "react-redux";
...
describe("<MyComponent />", () => {
it("renders the component", () => {
let props = {
index: 1,
value: 1
};
let state = {};
const wrapper = mount(
<Provider store={createMockStore(state)}>
<MemoryRouter initialEntries={["/s/parameter1"]}>
<Route path="/s/:camera">
<MyComponent {...props} />
</Route>
</MemoryRouter>
</Provider>
);
expect(wrapper.find(ProcessedFrames.WrappedComponent)).to.have.lengthOf(1);
});
});
I had my paths defined in another file for the dynamic router, so I am also testing that all the routes I am rendering as Routes are defined in my paths.js constants:
it('Routes should only have paths declared in src/routing/paths.js', () => {
const isDeclaredInPaths = (element, index, array) => {
return pathsDefined.indexOf(array[index]) >= 0;
}
expect(routesDefined.every(isDeclaredInPaths)).to.be.true;
});