I have a <UserListComponent />
which outputs one <Contact />
component and list of contacts presentated by <Contacts />
.
The problem is that in the test for <UserListComponent />
when I try to mount it, test outputs an error Invariant Violation: You should not use <Route> or withRouter() outside a <Router>
withRouter()
is used in <Contacts />
component.
How can I mock ContactsComponent
without router in test of parent component?
I found some similar issue https://www.bountysource.com/issues/49297944-invariant-violation-you-should-not-use-route-or-withrouter-outside-a-router
but it only describes situation when component is cover by withRouter()
itself, not children.
UserList.test.jsx
const mockResp = {
count: 2,
items: [
{
_id: 1,
name: 'User1',
email: 'email1@gmail.com',
phone: '+123456',
online: false
},
{
_id: 2,
name: 'User2',
email: 'email2@gmail.com',
phone: '+789123',
online: false
},
{
_id: 3,
name: 'User3',
email: 'email3@gmail.com',
phone: '+258369147',
online: false
}
],
next: null
}
describe('UserList', () => {
beforeEach(() => {
fetch.resetMocks()
});
test('should output list of users', () => {
fetch.mockResponseOnce(JSON.stringify(mockResp));
const wrapper = mount(<UserListComponent user={mockResp.items[2]} />);
expect(wrapper.find('.contact_small')).to.have.length(3);
});
})
UserList.jsx
export class UserListComponent extends PureComponent {
render() {
const { users, error } = this.state;
return (
<React.Fragment>
<Contact
userName={this.props.user.name}
content={this.props.user.phone}
/>
{error ? <p>{error.message}</p> : <Contacts type="contactList" user={this.props.user} contacts={users} />}
</React.Fragment>
);
}
}
Contacts.jsx
class ContactsComponent extends Component {
constructor() {
super();
this.state = {
error: null,
};
}
render() {
return (
<React.Fragment>
<SectionTitle title="Contacts" />
<div className="contacts">
//contacts
</div>
</React.Fragment>
);
}
}
export const Contacts = withRouter(ContactsComponent);
You need to wrap the
App
with aBrowserRouter
or an equivalent, see the below example of simple test case a component App that uses React RouterTo test a component (with Jest) that contains
<Route>
andwithRouter
you need to import Router in you test, not in your componentand use it like this
Utility Function To Wrap Mount With Context
Wrapping mount with Router in tests works, but there are situations where you don't want Router to be the parent component in your mount. Therefore I'm currently injecting context into mount using a wrapper function:
This could be in a file called, say contextWrap.js, in a test helpers directory.
Example describe block:
You can also use this pattern to wrap subcomponents in other types of context, for example if you are using react-intl, material-ui or your own context types.
A keeps the history of your "URL" in memory (does not read or write to the address bar). Useful in tests and non-browser environments like React Native.
I got similar error solution is wrapping component with the help of Memory router
i had same problem, and first comment helped me, but there are a lot of code i have better way how to resolve this problem. See my solution below: