Fix MultiChild tests so they work with Fiber
Dropped the unnecessary use of findDOMNode. Dropped unnecessary arrow functions. Math.random() -> id counter, since this used to be non-deterministic which is not ideal for unit tests. getOriginalKeys() used to rely on implementation details to scan that the internal data structure maintained its structure, however, since that is unobservable we don't need to test the internal data structure itself. We're already testing refs and dom structure which is the only observable effect of the reorder.
Sebastian Markbage committed
Sep 13, 2016 at 01:43 UTC
c3310d3e326d241ec42e3db34586ce3d01cf554c
2 files changed
+39
-63
src/renderers/shared/stack/reconciler/__tests__/ReactMultiChildReconcile-test.js
+33
-57
@@ -13,13 +13,10 @@
13
14
var React = require('React');
15
var ReactDOM = require('ReactDOM');
16
-var ReactDOMComponentTree = require('ReactDOMComponentTree');
17
-var ReactInstanceMap = require('ReactInstanceMap');
16
17
var stripEmptyValues = function(obj) {
18
var ret = {};
21
- var name;
22
- for (name in obj) {
19
+ for (var name in obj) {
20
if (!obj.hasOwnProperty(name)) {
21
continue;
22
}
@@ -30,15 +27,7 @@ var stripEmptyValues = function(obj) {
27
return ret;
28
};
29
33
-/**
34
- * Child key names are wrapped like '.$key:0'. We strip the extra chars out
35
- * here. This relies on an implementation detail of the rendering system.
36
- */
37
-var getOriginalKey = function(childName) {
38
- var match = childName.match(/^\.\$([^.]+)$/);
39
- expect(match).not.toBeNull();
40
- return match[1];
41
-};
30
+var idCounter = 123;
31
32
/**
33
* Contains internal static internal state in order to test that updates to
@@ -46,15 +35,15 @@ var getOriginalKey = function(childName) {
35
* reusing existing DOM/memory resources.
36
*/
37
class StatusDisplay extends React.Component {
49
- state = {internalState: Math.random()};
38
+ state = {internalState: idCounter++};
39
51
- getStatus = () => {
40
+ getStatus() {
41
return this.props.status;
53
- };
42
+ }
43
55
- getInternalState = () => {
44
+ getInternalState() {
45
return this.state.internalState;
57
- };
46
+ }
47
48
componentDidMount() {
49
this.props.onFlush();
@@ -67,7 +56,7 @@ class StatusDisplay extends React.Component {
56
render() {
57
return (
58
<div>
70
- {this.state.internalState}
59
+ {this.props.contentKey}
60
</div>
61
);
62
}
@@ -82,39 +71,29 @@ class FriendsStatusDisplay extends React.Component {
71
* Refs are not maintained in the rendered order, and neither is
72
* `this._renderedChildren` (surprisingly).
73
*/
85
- getOriginalKeys = () => {
74
+ getOriginalKeys() {
75
var originalKeys = [];
87
- // TODO: Update this to a better test that doesn't rely so much on internal
88
- // implementation details.
89
- var statusDisplays =
90
- ReactInstanceMap.get(this)
91
- ._renderedComponent
92
- ._renderedChildren;
93
- var name;
94
- for (name in statusDisplays) {
95
- var child = statusDisplays[name];
96
- var isPresent = !!child;
97
- if (isPresent) {
98
- originalKeys[child._mountIndex] = getOriginalKey(name);
76
+ for (var key in this.props.usernameToStatus) {
77
+ if (this.props.usernameToStatus[key]) {
78
+ originalKeys.push(key);
79
}
80
}
81
return originalKeys;
102
- };
82
+ }
83
84
/**
85
* Retrieves the rendered children in a nice format for comparing to the input
86
* `this.props.usernameToStatus`.
87
*/
108
- getStatusDisplays = () => {
88
+ getStatusDisplays() {
89
var res = {};
110
- var i;
90
var originalKeys = this.getOriginalKeys();
112
- for (i = 0; i < originalKeys.length; i++) {
91
+ for (var i = 0; i < originalKeys.length; i++) {
92
var key = originalKeys[i];
93
res[key] = this.refs[key];
94
}
95
return res;
117
- };
96
+ }
97
98
/**
99
* Verifies that by the time a child is flushed, the refs that appeared
@@ -123,10 +102,9 @@ class FriendsStatusDisplay extends React.Component {
102
* but our internal layer API depends on this assumption. We need to change
103
* it to be more declarative before making ref resolution indeterministic.
104
*/
126
- verifyPreviousRefsResolved = (flushedKey) => {
127
- var i;
105
+ verifyPreviousRefsResolved(flushedKey) {
106
var originalKeys = this.getOriginalKeys();
129
- for (i = 0; i < originalKeys.length; i++) {
107
+ for (var i = 0; i < originalKeys.length; i++) {
108
var key = originalKeys[i];
109
if (key === flushedKey) {
110
// We are only interested in children up to the current key.
@@ -134,18 +112,18 @@ class FriendsStatusDisplay extends React.Component {
112
}
113
expect(this.refs[key]).toBeTruthy();
114
}
137
- };
115
+ }
116
117
render() {
118
var children = [];
141
- var key;
142
- for (key in this.props.usernameToStatus) {
119
+ for (var key in this.props.usernameToStatus) {
120
var status = this.props.usernameToStatus[key];
121
children.push(
122
!status ? null :
123
<StatusDisplay
124
key={key}
125
ref={key}
126
+ contentKey={key}
127
onFlush={this.verifyPreviousRefsResolved.bind(this, key)}
128
status={status}
129
/>
@@ -223,35 +201,33 @@ function verifyStatesPreserved(lastInternalStates, statusDisplays) {
201
* Verifies that the internal representation of a set of `renderedChildren`
202
* accurately reflects what is in the DOM.
203
*/
226
-function verifyDomOrderingAccurate(parentInstance, statusDisplays) {
227
- var containerNode = ReactDOM.findDOMNode(parentInstance);
204
+function verifyDomOrderingAccurate(outerContainer, statusDisplays) {
205
+ var containerNode = outerContainer.firstChild;
206
var statusDisplayNodes = containerNode.childNodes;
229
- var i;
230
- var orderedDomIDs = [];
231
- for (i = 0; i < statusDisplayNodes.length; i++) {
232
- var inst = ReactDOMComponentTree.getInstanceFromNode(statusDisplayNodes[i]);
233
- orderedDomIDs.push(inst._rootNodeID);
207
+ var orderedDomKeys = [];
208
+ for (var i = 0; i < statusDisplayNodes.length; i++) {
209
+ var contentKey = statusDisplayNodes[i].textContent;
210
+ orderedDomKeys.push(contentKey);
211
}
212
236
- var orderedLogicalIDs = [];
213
+ var orderedLogicalKeys = [];
214
var username;
215
for (username in statusDisplays) {
216
if (!statusDisplays.hasOwnProperty(username)) {
217
continue;
218
}
219
var statusDisplay = statusDisplays[username];
243
- orderedLogicalIDs.push(
244
- ReactInstanceMap.get(statusDisplay)._renderedComponent._rootNodeID
220
+ orderedLogicalKeys.push(
221
+ statusDisplay.props.contentKey
222
);
223
}
247
- expect(orderedDomIDs).toEqual(orderedLogicalIDs);
224
+ expect(orderedDomKeys).toEqual(orderedLogicalKeys);
225
}
226
227
/**
228
* Todo: Check that internal state is preserved across transitions
229
*/
230
function testPropsSequence(sequence) {
254
- var i;
231
var container = document.createElement('div');
232
var parentInstance = ReactDOM.render(
233
<FriendsStatusDisplay {...sequence[0]} />,
@@ -261,7 +237,7 @@ function testPropsSequence(sequence) {
237
var lastInternalStates = getInternalStateByUserName(statusDisplays);
238
verifyStatuses(statusDisplays, sequence[0]);
239
264
- for (i = 1; i < sequence.length; i++) {
240
+ for (var i = 1; i < sequence.length; i++) {
241
ReactDOM.render(
242
<FriendsStatusDisplay {...sequence[i]} />,
243
container
@@ -269,7 +245,7 @@ function testPropsSequence(sequence) {
245
statusDisplays = parentInstance.getStatusDisplays();
246
verifyStatuses(statusDisplays, sequence[i]);
247
verifyStatesPreserved(lastInternalStates, statusDisplays);
272
- verifyDomOrderingAccurate(parentInstance, statusDisplays);
248
+ verifyDomOrderingAccurate(container, statusDisplays);
249
250
lastInternalStates = getInternalStateByUserName(statusDisplays);
251
}
src/renderers/shared/stack/reconciler/__tests__/ReactMultiChildText-test.js
+6
-6
@@ -26,17 +26,17 @@ var testAllPermutations = function(testCases) {
26
var expectedResultAfterUpdate = testCases[j + 1];
27
28
var container = document.createElement('div');
29
- var d = ReactDOM.render(<div>{renderWithChildren}</div>, container);
30
- expectChildren(d, expectedResultAfterRender);
29
+ ReactDOM.render(<div>{renderWithChildren}</div>, container);
30
+ expectChildren(container, expectedResultAfterRender);
31
32
- d = ReactDOM.render(<div>{updateWithChildren}</div>, container);
33
- expectChildren(d, expectedResultAfterUpdate);
32
+ ReactDOM.render(<div>{updateWithChildren}</div>, container);
33
+ expectChildren(container, expectedResultAfterUpdate);
34
}
35
}
36
};
37
38
-var expectChildren = function(d, children) {
39
- var outerNode = ReactDOM.findDOMNode(d);
38
+var expectChildren = function(container, children) {
39
+ var outerNode = container.firstChild;
40
var textNode;
41
if (typeof children === 'string') {
42
textNode = outerNode.firstChild;