Description
Do you want to request a feature or report a bug?
Bug
What is the current behavior?
ShallowRenderer not considering contextTypes.
**Note: I was not able to easily include react-test-renderer in a fiddle so I include a unit test.
//Context used in shallow and normal rendering
const context = { appName: 'abc', mode: 'def' };
class TopLevelComponent extends React.Component {
render() { return <div>{this.props.children}</div>; }
getChildContext() { return context; }
}
TopLevelComponent.childContextTypes = { appName: PropTypes.string, mode: PropTypes.string };
class Component1 extends React.Component {
render() { return <div mode={this.context.mode} appname={this.context.appName}/>; }
}
Component1.contextTypes = { appName: PropTypes.string };
//Use shallow renderer and assert that we got appName but not mode
const shallowComponent1 = new ShallowRenderer().render(<Component1/>, context);
expect(shallowComponent1.props.appname).toBe('abc'); //Pass
expect(shallowComponent1.props.mode).toBeUndefined(); //This expectation fails
//Render Component1 under a component with childContext
const wrappedEl = React.createElement(() => <TopLevelComponent><Component1/></TopLevelComponent>);
const domNode = document.createElement('div');
ReactDOM.render(wrappedEl, domNode);
const html = domNode.innerHTML;
expect(html).toContain('abc'); //Pass
expect(html).not.toContain('def'); //Pass: As you can see this property is undefined
What is the expected behavior?
I would expect that when rendering Component1 with ShallowRenderer, render method would check Component1.contextTypes and mask any property that is not specified there just like function getMaskedContext(workInProgress, unmaskedContext) does in react-dom library.
I fixed this behavior by changing render method like this: (inpired again by getMaskedContext)
const oldRender = ShallowRenderer.prototype.render;
ShallowRenderer.prototype.render = function render(element) {
const unmaskedContext = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (element && element.type && unmaskedContext) {
if (element.type.hasOwnProperty('contextTypes')) {
const context = {};
for (const key in element.type.contextTypes) {
context[key] = unmaskedContext[key];
}
arguments[1] = context;
}
}
return oldRender.apply(this, arguments);
};
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
This bug is for version 16. We are upgrading from React 15, we were using enzyme shallow rendering and this wasn't the behavior. It is difficult to say which part of the code has changed between React 15 and enzyme at this point but my code sample includes only code from react libraries.