Skip to content

Commit e88c96b

Browse files
gaearonzpao
authored andcommitted
Merge pull request #6362 from gaearon/no-owner-in-test-utils
Elements from functional components in TestUtils should have no owner (cherry picked from commit ae56910)
1 parent 3655e30 commit e88c96b

File tree

3 files changed

+62
-36
lines changed

3 files changed

+62
-36
lines changed

src/renderers/shared/reconciler/ReactCompositeComponent.js

+40-36
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ function warnIfInvalidElement(Component, element) {
6060
}
6161
}
6262

63+
function shouldConstruct(Component) {
64+
return Component.prototype && Component.prototype.isReactComponent;
65+
}
66+
6367
/**
6468
* ------------------ The Life-Cycle of a Composite Component ------------------
6569
*
@@ -158,44 +162,22 @@ var ReactCompositeComponentMixin = {
158162
var Component = this._currentElement.type;
159163

160164
// Initialize the public class
161-
var inst;
165+
var inst = this._constructComponent(publicProps, publicContext);
162166
var renderedElement;
163167

164-
if (Component.prototype && Component.prototype.isReactComponent) {
165-
if (__DEV__) {
166-
ReactCurrentOwner.current = this;
167-
try {
168-
inst = new Component(publicProps, publicContext, ReactUpdateQueue);
169-
} finally {
170-
ReactCurrentOwner.current = null;
171-
}
172-
} else {
173-
inst = new Component(publicProps, publicContext, ReactUpdateQueue);
174-
}
175-
} else {
176-
if (__DEV__) {
177-
ReactCurrentOwner.current = this;
178-
try {
179-
inst = Component(publicProps, publicContext, ReactUpdateQueue);
180-
} finally {
181-
ReactCurrentOwner.current = null;
182-
}
183-
} else {
184-
inst = Component(publicProps, publicContext, ReactUpdateQueue);
185-
}
186-
if (inst == null || inst.render == null) {
187-
renderedElement = inst;
188-
warnIfInvalidElement(Component, renderedElement);
189-
invariant(
190-
inst === null ||
191-
inst === false ||
192-
ReactElement.isValidElement(inst),
193-
'%s(...): A valid React element (or null) must be returned. You may have ' +
194-
'returned undefined, an array or some other invalid object.',
195-
Component.displayName || Component.name || 'Component'
196-
);
197-
inst = new StatelessComponent(Component);
198-
}
168+
// Support functional components
169+
if (!shouldConstruct(Component) && (inst == null || inst.render == null)) {
170+
renderedElement = inst;
171+
warnIfInvalidElement(Component, renderedElement);
172+
invariant(
173+
inst === null ||
174+
inst === false ||
175+
ReactElement.isValidElement(inst),
176+
'%s(...): A valid React element (or null) must be returned. You may have ' +
177+
'returned undefined, an array or some other invalid object.',
178+
Component.displayName || Component.name || 'Component'
179+
);
180+
inst = new StatelessComponent(Component);
199181
}
200182

201183
if (__DEV__) {
@@ -323,6 +305,28 @@ var ReactCompositeComponentMixin = {
323305
return markup;
324306
},
325307

308+
_constructComponent: function(publicProps, publicContext) {
309+
if (__DEV__) {
310+
ReactCurrentOwner.current = this;
311+
try {
312+
return this._constructComponentWithoutOwner(publicProps, publicContext);
313+
} finally {
314+
ReactCurrentOwner.current = null;
315+
}
316+
} else {
317+
return this._constructComponentWithoutOwner(publicProps, publicContext);
318+
}
319+
},
320+
321+
_constructComponentWithoutOwner: function(publicProps, publicContext) {
322+
var Component = this._currentElement.type;
323+
if (shouldConstruct(Component)) {
324+
return new Component(publicProps, publicContext, ReactUpdateQueue);
325+
} else {
326+
return Component(publicProps, publicContext, ReactUpdateQueue);
327+
}
328+
},
329+
326330
performInitialMountWithErrorHandling: function(
327331
renderedElement,
328332
nativeParent,

src/test/ReactTestUtils.js

+2
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@ var ShallowComponentWrapper = function(element) {
399399
Object.assign(
400400
ShallowComponentWrapper.prototype,
401401
ReactCompositeComponent.Mixin, {
402+
_constructComponent:
403+
ReactCompositeComponent.Mixin._constructComponentWithoutOwner,
402404
_instantiateReactComponent: function(element) {
403405
return new NoopInternalComponent(element);
404406
},

src/test/__tests__/ReactTestUtils-test.js

+20
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,26 @@ describe('ReactTestUtils', function() {
4747
]);
4848
});
4949

50+
it('should shallow render a functional component', function() {
51+
function SomeComponent() {
52+
return (
53+
<div>
54+
<span className="child1" />
55+
<span className="child2" />
56+
</div>
57+
);
58+
}
59+
60+
var shallowRenderer = ReactTestUtils.createRenderer();
61+
var result = shallowRenderer.render(<SomeComponent />);
62+
63+
expect(result.type).toBe('div');
64+
expect(result.props.children).toEqual([
65+
<span className="child1" />,
66+
<span className="child2" />,
67+
]);
68+
});
69+
5070
it('should throw for invalid elements', function() {
5171
var SomeComponent = React.createClass({
5272
render: function() {

0 commit comments

Comments
 (0)