@samitouri / QOS-React / commits / 343fb958f1

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