ShallowRenderer should filter context by contextTypes (#11922)
Toru Kobayashi committed
Jan 6, 2018 at 03:49 UTC
9d310e0bc7b9d5ce39d82536dfcb67f98462a346
2 files changed
+41
-6
packages/react-test-renderer/src/ReactShallowRenderer.js
+17
-6
@@ -70,15 +70,15 @@ class ReactShallowRenderer {
70
71
this._rendering = true;
72
this._element = element;
73
- this._context = context;
73
+ this._context = getMaskedContext(element.type.contextTypes, context);
74
75
if (this._instance) {
76
- this._updateClassComponent(element.type, element.props, context);
76
+ this._updateClassComponent(element.type, element.props, this._context);
77
} else {
78
if (shouldConstruct(element.type)) {
79
this._instance = new element.type(
80
element.props,
81
- context,
81
+ this._context,
82
this._updater,
83
);
84
@@ -87,7 +87,7 @@ class ReactShallowRenderer {
87
88
checkPropTypes(
89
element.type.contextTypes,
90
- context,
90
+ this._context,
91
'context',
92
getName(element.type, this._instance),
93
getStackAddendum,
@@ -96,9 +96,9 @@ class ReactShallowRenderer {
96
currentlyValidatingElement = null;
97
}
98
99
- this._mountClassComponent(element.props, context);
99
+ this._mountClassComponent(element.props, this._context);
100
} else {
101
- this._rendered = element.type(element.props, context);
101
+ this._rendered = element.type(element.props, this._context);
102
}
103
}
104
@@ -290,4 +290,15 @@ function shouldConstruct(Component) {
290
return !!(Component.prototype && Component.prototype.isReactComponent);
291
}
292
293
+function getMaskedContext(contextTypes, unmaskedContext) {
294
+ if (!contextTypes) {
295
+ return emptyObject;
296
+ }
297
+ const context = {};
298
+ for (let key in contextTypes) {
299
+ context[key] = unmaskedContext[key];
300
+ }
301
+ return context;
302
+}
303
+
304
export default ReactShallowRenderer;
packages/react-test-renderer/src/__tests__/ReactShallowRenderer-test.js
+24
@@ -216,6 +216,9 @@ describe('ReactShallowRenderer', () => {
216
</div>
217
);
218
}
219
+ SomeComponent.contextTypes = {
220
+ bar: PropTypes.string,
221
+ };
222
223
const shallowRenderer = createRenderer();
224
const result = shallowRenderer.render(<SomeComponent foo={'FOO'} />, {
@@ -428,6 +431,9 @@ describe('ReactShallowRenderer', () => {
431
super(props, context);
432
this.state = initialState;
433
}
434
+ static contextTypes = {
435
+ context: PropTypes.string,
436
+ };
437
componentDidUpdate(...args) {
438
componentDidUpdateParams.push(...args);
439
}
@@ -770,6 +776,24 @@ describe('ReactShallowRenderer', () => {
776
expect(result).toEqual(<div>foo:baz</div>);
777
});
778
779
+ it('should filter context by contextTypes', () => {
780
+ class SimpleComponent extends React.Component {
781
+ static contextTypes = {
782
+ foo: PropTypes.string,
783
+ };
784
+ render() {
785
+ return <div>{`${this.context.foo}:${this.context.bar}`}</div>;
786
+ }
787
+ }
788
+
789
+ const shallowRenderer = createRenderer();
790
+ let result = shallowRenderer.render(<SimpleComponent />, {
791
+ foo: 'foo',
792
+ bar: 'bar',
793
+ });
794
+ expect(result).toEqual(<div>foo:undefined</div>);
795
+ });
796
+
797
it('can fail context when shallowly rendering', () => {
798
class SimpleComponent extends React.Component {
799
static contextTypes = {