Add test for componentDidUpdate with a bailout in the middle (#8525)
This is one of the cases where Fiber diverges.
Sebastian Markbåge committed
Dec 7, 2016 at 15:14 UTC
343fb958f1323139b18e14b77c5161675a59de2d
2 files changed
+87
scripts/fiber/tests-passing.txt
+1
@@ -1294,6 +1294,7 @@ src/renderers/shared/shared/__tests__/ReactCompositeComponentDOMMinimalism-test.
1294
1295
src/renderers/shared/shared/__tests__/ReactCompositeComponentState-test.js
1296
* should support setting state
1297
+* should call componentDidUpdate of children first
1298
* should batch unmounts
1299
1300
src/renderers/shared/shared/__tests__/ReactEmptyComponent-test.js
src/renderers/shared/shared/__tests__/ReactCompositeComponentState-test.js
+86
@@ -13,6 +13,7 @@
13
14
var React;
15
var ReactDOM;
16
+var ReactDOMFeatureFlags;
17
18
var TestComponent;
19
@@ -22,6 +23,7 @@ describe('ReactCompositeComponent-state', () => {
23
React = require('React');
24
25
ReactDOM = require('ReactDOM');
26
+ ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
27
28
TestComponent = React.createClass({
29
peekAtState: function(from, state) {
@@ -227,6 +229,90 @@ describe('ReactCompositeComponent-state', () => {
229
expect(stateListener.mock.calls.join('\n')).toEqual(expected.join('\n'));
230
});
231
232
+
233
+ it('should call componentDidUpdate of children first', () => {
234
+ var container = document.createElement('div');
235
+
236
+ var ops = [];
237
+
238
+ var child = null;
239
+ var parent = null;
240
+
241
+ class Child extends React.Component {
242
+ state = {bar:false};
243
+ componentDidMount() {
244
+ child = this;
245
+ }
246
+ componentDidUpdate() {
247
+ ops.push('child did update');
248
+ }
249
+ render() {
250
+ return <div />;
251
+ }
252
+ }
253
+
254
+ var shouldUpdate = true;
255
+
256
+ class Intermediate extends React.Component {
257
+ shouldComponentUpdate() {
258
+ return shouldUpdate;
259
+ }
260
+ render() {
261
+ return <Child />;
262
+ }
263
+ }
264
+
265
+ class Parent extends React.Component {
266
+ state = {foo:false};
267
+ componentDidMount() {
268
+ parent = this;
269
+ }
270
+ componentDidUpdate() {
271
+ ops.push('parent did update');
272
+ }
273
+ render() {
274
+ return <Intermediate />;
275
+ }
276
+ }
277
+
278
+ ReactDOM.render(<Parent />, container);
279
+
280
+ ReactDOM.unstable_batchedUpdates(() => {
281
+ parent.setState({ foo: true });
282
+ child.setState({ bar: true });
283
+ });
284
+ // When we render changes top-down in a batch, children's componentDidUpdate
285
+ // happens before the parent.
286
+ expect(ops).toEqual([
287
+ 'child did update',
288
+ 'parent did update',
289
+ ]);
290
+
291
+ shouldUpdate = false;
292
+
293
+ ops = [];
294
+
295
+ ReactDOM.unstable_batchedUpdates(() => {
296
+ parent.setState({ foo: false });
297
+ child.setState({ bar: false });
298
+ });
299
+ // We expect the same thing to happen if we bail out in the middle.
300
+ expect(ops).toEqual(
301
+ ReactDOMFeatureFlags.useFiber ?
302
+ [
303
+ // Fiber works as expected
304
+ 'child did update',
305
+ 'parent did update',
306
+ ] : [
307
+ // Stack treats these as two separate updates and therefore the order
308
+ // is inverse.
309
+ 'parent did update',
310
+ 'child did update',
311
+ ]
312
+ );
313
+
314
+ });
315
+
316
it('should batch unmounts', () => {
317
var outer;
318