Testing react router v4 with jest enzyme
Why are you calling console.log inside of shallow
? I've never seen this before...
Try to wrap your <App />
component in <Route />
, and search for some tag inside it.
For example. Assuming you have this simple component:
<App>
<h1>Hi there!</h1>
</App>
Test can look like that:
describe('<App />', () => {
it('renders a static text', () => {
const wrapper = shallow(
<MemoryRouter initialEntries={['/']} initialIndex={0}>
<Route path="/" render={() => <App />} />
</MemoryRouter>
);
console.log(wrapper.find(App).html());
});
});
UPDATE It happens that react-boilerplate adds way too much wrappers and dependencies. So for successfull test we need to overcome them in different ways...
This is how I got it done(full content of my react-boilerplate/app/tests/simple.test.js
):
import React from 'react';
import { mount } from 'enzyme';
import { MemoryRouter, Route, browserHistory } from 'react-router-dom';
import { IntlProvider } from 'react-intl';
import { Provider } from 'react-redux';
import configureStore from '../configureStore';
import App from '../containers/App';
import { HomePage } from '../containers/HomePage';
describe('test of initial load', () => {
it('test', () => {
const store = configureStore({}, browserHistory);
const wrapper = mount(
<MemoryRouter initialEntries={['/']} initialIndex={0}>
<IntlProvider locale="en"> // to add Intl support
<Provider store={store} > // to provide store for numeric connected components
<Route path="/" render={() => <App />} />
</Provider>
</IntlProvider>
</MemoryRouter>
);
process.nextTick(() => { // to wait for loadible component will be imported
console.log(wrapper.find(HomePage).html());
});
});
});
I think that this is rather integration and not unit test...
Output of console.log
:
console.log app/tests/simple.test.js:24
<article><!-- react-empty: 38 --><div><section class="sc-bxivhb jwizic"><h2 class="H2__H2-dhGylN kpbCLA"><span>Start your next react project in seconds</span></h2><p><span>A highly scalable, offline-first foundation with the best DX and a focus on performance and best practices</span></p></section><section class="Section__Section-jEbZoY eivjmS"><h2 class="H2__H2-dhGylN kpbCLA"><span>Try me!</span></h2><form class="Form__Form-PASBS cEpjmP"><label for="username"><span>Show Github repositories by</span><span class="AtPrefix__AtPrefix-ivHByA dZcxpA"><span>@</span></span><input type="text" class="Input__Input-ixjKAz jCPlXI" id="username" placeholder="mxstbr" value=""></label></form><!-- react-empty: 54 --></section></div></article>
johnwick0831
Updated on June 16, 2022Comments
-
johnwick0831 over 1 year
I'm trying to do a simple test with react router v4 and jest enzyme.
describe('<App />', () => { it('renders a static text', () => { const wrapper = shallow( <MemoryRouter initialEntries={['/']} initialIndex={0}> <App/> </MemoryRouter> console.log(wrapper.html()); ); }); });
When I try to console.log(wrapper.html()), I get:
Invariant Violation: [React Intl] Could not find required `intl` object. <IntlProvider> needs to exist in the component ancestry.
I am using the react-boiler-plate project. All I want to do is test that when I give it a path of '/' then the home page renders some text.
Any help appreciated! Thanks!
EDIT:
This is the test:
it('test', () => { const wrapper = shallow( <MemoryRouter initialEntries={['/']} initialIndex={0}> <Route path="/" render={() => <App/>}/> </MemoryRouter>, ); console.log(wrapper.find(App).html()); });
This is the App class:
export default function App() { return ( <AppWrapper> <Helmet titleTemplate="%s - React.js Boilerplate" defaultTitle="React.js Boilerplate" > <meta name="description" content="A React.js Boilerplate application"/> </Helmet> <Header/> <Switch> <Route exact path="/" component={HomePage}/> <Route path="/features" component={FeaturePage}/> <Route path="/catalog" render={() => <div>hi</div>} /> <Route path="" component={NotFoundPage}/> </Switch> <Footer/> </AppWrapper> ); }
This is the error message when running the test:
**Error: Method “html” is only meant to be run on a single node. 0 found instead.**
I am expecting that this page would match and I would be able to console.log the output of it:
<Route exact path="/" component={HomePage}/>
-
johnwick0831 over 5 yearsApologies, that was a typo - console.log isn't supposed to be in the shallow. I've updated the question and wrapped <App> around a <Route> and I got a new error message. I'm using the react-boiler-plate (/App/tests/index.test.js)
-
Andrew Miroshnichenko over 5 years@johnwick0831 thanks for edit! Can you please try to use
mount
instead ofshallow
as rendering method? I thinkshallow
needs to be used in very simple tests, and test that includes routing isn't simple. -
johnwick0831 over 5 yearsUsing mount introduces many new problems. To reproduce the problem, clone react-boiler-plate. And in the /app/tests/ create the test from above. You will notice if you use mount, it will provide some error message about "Could not find required
intl
object. <IntlProvider> needs to exist in the component ancestry." Not really sure what the problem is, I hope someone can clone the project and give this test a shot if they have extra time on their hands... -
johnwick0831 over 5 yearsthanks for your detailed answer. I agree this seems overly complex for a unit test and has too many injected dependencies. What would your recommendation be to test the <App> class so that given certain initialEntries it routes to the correct component ?
-
Andrew Miroshnichenko over 5 years@johnwick0831 I think that by setting a task in such way you are trying to test not the <App> class, but functionality of the react router itself:) In my practice, I leave to router responsibility to route, and just test my components with different props, supplied by router(like
this.props.match.params
), by mocking such props. -
johnwick0831 over 5 yearsHi Andrew, I agree with what you say. Would you be able to provide an example of what you said for everybody to benefit from and I'll mark that as an answer. Thank you!
-
Andrew Miroshnichenko over 5 yearsLet us continue this discussion in chat.
-
Leon over 4 yearsSuper late reply, but I think he wants to confirm that the router renders what is expected
-
Alan Yong about 2 yearsnone of your code testing react-router