Skip to content

Commit e1ff342

Browse files
jquensebvaughn
authored andcommitted
Support ForwardRef type of work in TestRenderer (#12392)
* Support ForwardRef type of work in TestRenderer and ShallowRenderer. * Release script now updates inter-package dependencies too (e.g. react-test-renderer depends on react-is).
1 parent 7e87df8 commit e1ff342

File tree

7 files changed

+88
-16
lines changed

7 files changed

+88
-16
lines changed

packages/react-is/src/ReactIs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export function typeOf(object: any) {
3434
case REACT_STRICT_MODE_TYPE:
3535
return type;
3636
default:
37-
const $$typeofType = type.$$typeof;
37+
const $$typeofType = type && type.$$typeof;
3838

3939
switch ($$typeofType) {
4040
case REACT_CONTEXT_TYPE:

packages/react-test-renderer/package.json

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@
44
"description": "React package for snapshot testing.",
55
"main": "index.js",
66
"repository": "facebook/react",
7-
"keywords": [
8-
"react",
9-
"react-native",
10-
"react-testing"
11-
],
7+
"keywords": ["react", "react-native", "react-testing"],
128
"license": "MIT",
139
"bugs": {
1410
"url": "https://github.com/facebook/react/issues"
@@ -17,16 +13,11 @@
1713
"dependencies": {
1814
"fbjs": "^0.8.16",
1915
"object-assign": "^4.1.1",
20-
"prop-types": "^15.6.0"
16+
"prop-types": "^15.6.0",
17+
"react-is": "^16.3.0-alpha.2"
2118
},
2219
"peerDependencies": {
2320
"react": "^16.0.0 || 16.3.0-alpha.2"
2421
},
25-
"files": [
26-
"LICENSE",
27-
"README.md",
28-
"index.js",
29-
"shallow.js",
30-
"cjs/"
31-
]
22+
"files": ["LICENSE", "README.md", "index.js", "shallow.js", "cjs/"]
3223
}

packages/react-test-renderer/src/ReactShallowRenderer.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import React from 'react';
10+
import {isForwardRef} from 'react-is';
1011
import {warnAboutDeprecatedLifecycles} from 'shared/ReactFeatureFlags';
1112
import describeComponentFrame from 'shared/describeComponentFrame';
1213
import getComponentName from 'shared/getComponentName';
@@ -77,7 +78,7 @@ class ReactShallowRenderer {
7778
element.type,
7879
);
7980
invariant(
80-
typeof element.type === 'function',
81+
isForwardRef(element) || typeof element.type === 'function',
8182
'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
8283
'components, but the provided element type was `%s`.',
8384
Array.isArray(element.type)
@@ -96,7 +97,9 @@ class ReactShallowRenderer {
9697
if (this._instance) {
9798
this._updateClassComponent(element, this._context);
9899
} else {
99-
if (shouldConstruct(element.type)) {
100+
if (isForwardRef(element)) {
101+
this._rendered = element.type.render(element.props, element.ref);
102+
} else if (shouldConstruct(element.type)) {
100103
this._instance = new element.type(
101104
element.props,
102105
this._context,

packages/react-test-renderer/src/ReactTestRenderer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
ContextConsumer,
2626
ContextProvider,
2727
Mode,
28+
ForwardRef,
2829
} from 'shared/ReactTypeOfWork';
2930
import invariant from 'fbjs/lib/invariant';
3031

@@ -372,6 +373,7 @@ function toTree(node: ?Fiber) {
372373
case ContextProvider:
373374
case ContextConsumer:
374375
case Mode:
376+
case ForwardRef:
375377
return childrenToTree(node.child);
376378
default:
377379
invariant(
@@ -472,6 +474,7 @@ class ReactTestInstance {
472474
case ContextProvider:
473475
case ContextConsumer:
474476
case Mode:
477+
case ForwardRef:
475478
descend = true;
476479
break;
477480
default:

packages/react-test-renderer/src/__tests__/ReactShallowRenderer-test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,28 @@ describe('ReactShallowRenderer', () => {
168168
]);
169169
});
170170

171+
it('should handle ForwardRef', () => {
172+
const testRef = React.createRef();
173+
const SomeComponent = React.forwardRef((props, ref) => {
174+
expect(ref).toEqual(testRef);
175+
return (
176+
<div>
177+
<span className="child1" />
178+
<span className="child2" />
179+
</div>
180+
);
181+
});
182+
183+
const shallowRenderer = createRenderer();
184+
const result = shallowRenderer.render(<SomeComponent ref={testRef} />);
185+
186+
expect(result.type).toBe('div');
187+
expect(result.props.children).toEqual([
188+
<span className="child1" />,
189+
<span className="child2" />,
190+
]);
191+
});
192+
171193
it('should enable shouldComponentUpdate to prevent a re-render', () => {
172194
let renderCounter = 0;
173195
class SimpleComponent extends React.Component {

packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.internal.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ describe('ReactTestRenderer', () => {
404404
log.push('Angry render');
405405
throw new Error('Please, do not render me.');
406406
}
407+
407408
componentDidMount() {
408409
log.push('Angry componentDidMount');
409410
}
@@ -957,4 +958,46 @@ describe('ReactTestRenderer', () => {
957958
}),
958959
);
959960
});
961+
962+
it('supports forwardRef', () => {
963+
const InnerRefed = React.forwardRef((props, ref) => (
964+
<div>
965+
<span ref={ref} />
966+
</div>
967+
));
968+
969+
class App extends React.Component {
970+
render() {
971+
return <InnerRefed ref={r => (this.ref = r)} />;
972+
}
973+
}
974+
975+
const renderer = ReactTestRenderer.create(<App />);
976+
const tree = renderer.toTree();
977+
cleanNodeOrArray(tree);
978+
979+
expect(prettyFormat(tree)).toEqual(
980+
prettyFormat({
981+
instance: null,
982+
nodeType: 'component',
983+
props: {},
984+
rendered: {
985+
instance: null,
986+
nodeType: 'host',
987+
props: {},
988+
rendered: [
989+
{
990+
instance: null,
991+
nodeType: 'host',
992+
props: {},
993+
rendered: [],
994+
type: 'span',
995+
},
996+
],
997+
type: 'div',
998+
},
999+
type: App,
1000+
}),
1001+
);
1002+
});
9601003
});

scripts/release/build-commands/update-package-versions.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ const update = async ({cwd, dry, packages, version}) => {
7878
if (prerelease) {
7979
json.peerDependencies.react += ` || ${version}`;
8080
}
81+
82+
// Update inter-package dependencies as well.
83+
// e.g. react-test-renderer depends on react-is
84+
if (json.dependencies) {
85+
Object.keys(json.dependencies).forEach(dependency => {
86+
if (packages.indexOf(dependency) >= 0) {
87+
json.dependencies[dependency] = `^${version}`;
88+
}
89+
});
90+
}
8191
}
8292

8393
await writeJson(path, json, {spaces: 2});

0 commit comments

Comments
 (0)