Remove support for passing badly typed elements to shallow renderer (#11442)
Dan Abramov committed
Nov 3, 2017 at 16:16 UTC
fd47129ce6e8af37004686262bd27fa787af37fc
2 files changed
+46
-11
packages/react-test-renderer/src/ReactShallowRenderer.js
+11
-8
@@ -47,6 +47,7 @@ class ReactShallowRenderer {
47
'it by passing it to React.createElement.'
48
: '',
49
);
50
+ // Show a special message for host elements since it's a common case.
51
invariant(
52
typeof element.type !== 'string',
53
'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
@@ -54,6 +55,14 @@ class ReactShallowRenderer {
55
'inspecting the rendered output, look at `el.props` directly instead.',
56
element.type,
57
);
58
+ invariant(
59
+ typeof element.type === 'function',
60
+ 'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
61
+ 'components, but the provided element type was `%s`.',
62
+ Array.isArray(element.type)
63
+ ? 'array'
64
+ : element.type === null ? 'null' : typeof element.type,
65
+ );
66
67
if (this._rendering) {
68
return;
@@ -144,12 +153,8 @@ class ReactShallowRenderer {
153
) {
154
this._instance.componentWillReceiveProps(props, context);
155
}
147
-
156
// Read state after cWRP in case it calls setState
149
- // Fallback to previous instance state to support rendering React.cloneElement()
150
- // TODO: the cloneElement() use case is broken and should be removed
151
- // https://github.com/facebook/react/issues/11441
152
- const state = this._newState || this._instance.state || emptyObject;
157
+ const state = this._newState || oldState;
158
159
let shouldUpdate = true;
160
if (this._forcedUpdate) {
@@ -161,9 +166,7 @@ class ReactShallowRenderer {
166
state,
167
context,
168
);
164
- } else if (type && type.prototype && type.prototype.isPureReactComponent) {
165
- // TODO: we can remove the type existence check when we fix this:
166
- // https://github.com/facebook/react/issues/11441
169
+ } else if (type.prototype && type.prototype.isPureReactComponent) {
170
shouldUpdate =
171
!shallowEqual(oldProps, props) || !shallowEqual(oldState, state);
172
}
packages/react-test-renderer/src/__tests__/ReactShallowRenderer-test.js
+35
-3
@@ -844,12 +844,44 @@ describe('ReactShallowRenderer', () => {
844
}
845
846
const shallowRenderer = createRenderer();
847
- let result = shallowRenderer.render(<SimpleComponent foo="foo" />);
847
+ const el = <SimpleComponent foo="foo" />;
848
+ let result = shallowRenderer.render(el);
849
expect(result).toEqual(<div>foo:bar</div>);
850
850
- const instance = shallowRenderer.getMountedInstance();
851
- const cloned = React.cloneElement(instance, {foo: 'baz'});
851
+ const cloned = React.cloneElement(el, {foo: 'baz'});
852
result = shallowRenderer.render(cloned);
853
expect(result).toEqual(<div>baz:bar</div>);
854
});
855
+
856
+ it('throws usefully when rendering badly-typed elements', () => {
857
+ spyOn(console, 'error');
858
+ const shallowRenderer = createRenderer();
859
+
860
+ var Undef = undefined;
861
+ expect(() => shallowRenderer.render(<Undef />)).toThrowError(
862
+ 'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
863
+ 'components, but the provided element type was `undefined`.',
864
+ );
865
+
866
+ var Null = null;
867
+ expect(() => shallowRenderer.render(<Null />)).toThrowError(
868
+ 'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
869
+ 'components, but the provided element type was `null`.',
870
+ );
871
+
872
+ var Arr = [];
873
+ expect(() => shallowRenderer.render(<Arr />)).toThrowError(
874
+ 'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
875
+ 'components, but the provided element type was `array`.',
876
+ );
877
+
878
+ var Obj = {};
879
+ expect(() => shallowRenderer.render(<Obj />)).toThrowError(
880
+ 'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
881
+ 'components, but the provided element type was `object`.',
882
+ );
883
+
884
+ // One warning for each element creation
885
+ expectDev(console.error.calls.count()).toBe(4);
886
+ });
887
});