- Original source is https://github.com/rackt/react-router/blob/0.13.x/docs/guides/testing.md
- Requiring modules with relative paths on top of not using an absolute path (as http://webpack.github.io/docs/configuration.html#resolve-root states) will save you much painful debugging time
- When extracting the stub as a module to reuse across specs, the context of the
React.createClass.constructor
associated with the stubbed instance can get messed up when not following the above advice.
-
-
Save naganowl/ae563221414db3fbd545 to your computer and use it in GitHub Desktop.
Because the router relies heavily on the lesser known context
feature
of React, it can be a pain in the neck to test your components that have
things like <Link>
or rely on this.context.router
.
You simply have to stub out the context you need.
// this will yell at you if you have `<Link>` and friends
React.render(<IndividualComponent/>, testElement);
You'll get something like:
"Warning: Required context `router` was not specified in `Link`. Check the render method of `IndividualComponent`."
So we can just wrap up the thing we want to test in a different
component and stub out the context
stuff.
// add whichever router methods your component uses:
function RouterStub() { }
RouterStub.makePath = function () { }
// wrap it up:
var TestWrapper = React.createClass({
childContextTypes: {
router: React.PropTypes.func
},
getChildContext () {
return {
router: RouterStub
};
},
render () {
return <IndividualComponent/>
}
});
// okay, now it'll work:
React.render(<TestWrapper/>, testElement);
This is handy because now you can force the code down certain paths if you add some behavior to the stubbed context. But It's also a lot of junk to write.
Copy/paste this helper into your test utils to make things a bit easier:
var stubRouterContext = (Component, props, stubs) => {
function RouterStub() { }
Object.assign(RouterStub, {
makePath () {},
makeHref () {},
transitionTo () {},
replaceWith () {},
goBack () {},
getCurrentPath () {},
getCurrentRoutes () {},
getCurrentPathname () {},
getCurrentParams () {},
getCurrentQuery () {},
isActive () {},
getRouteAtDepth() {},
setRouteComponentAtDepth() {}
}, stubs)
return React.createClass({
childContextTypes: {
router: React.PropTypes.func,
routeDepth: React.PropTypes.number
},
getChildContext () {
return {
router: RouterStub,
routeDepth: 0
};
},
render () {
return <Component {...props} />
}
});
};
Now your tests are much simpler:
var stubRouterContext = require('./stubRouterContext');
var IndividualComponent = require('./IndividualComponent');
var Subject = stubRouterContext(IndividualComponent, {someProp: 'foo'});
React.render(<Subject/>, testElement);
You can also send code down certain paths if you'd like by supplying behavior to the stubbed context:
var Subject = stubRouterContext(IndividualComponent, {prop: 'foo'}, {
getCurrentQuery () {
return { modal: true };
}
});
Now your test will think it got ?modal=true
in the URL, even though
there is no URL in the test.
I dunno.