[Fiber] Add tests for scheduling inside callbacks (#8186)
* Add tests for scheduling inside callbacks * Don't test implementation details
Dan Abramov committed
Nov 2, 2016 at 20:11 UTC
eb674e47c85e4af20fe07753508eb43a1ac2fb64
3 files changed
+397
-101
scripts/fiber/tests-passing.txt
+12
@@ -819,6 +819,18 @@ src/renderers/shared/fiber/__tests__/ReactIncrementalScheduling-test.js
819
* splits deferred work on multiple roots
820
* works on deferred roots in the order they were scheduled
821
* handles interleaved deferred and animation work
822
+* performs animation work in animation callback
823
+* schedules deferred work in animation callback
824
+* schedules deferred work and performs animation work in animation callback
825
+* performs animation work and schedules deferred work in animation callback
826
+* performs deferred work in deferred callback if it has time
827
+* schedules deferred work in deferred callback if it runs out of time
828
+* performs animated work in deferred callback if it has time
829
+* performs animated work and deferred work in deferred callback if it has time
830
+* performs deferred and animated work work in deferred callback if it has time
831
+* FIXME: schedules animated work as if it was deferred in deferred callback if it runs out of time
832
+* schedules animated work and deferred work in deferred callback if it runs out of time
833
+* schedules deferred work and animated work in deferred callback if it runs out of time
834
835
src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
836
* can update child nodes of a host instance
src/renderers/noop/ReactNoop.js
-8
@@ -172,14 +172,6 @@ var ReactNoop = {
172
}
173
},
174
175
- hasScheduledDeferredCallback() {
176
- return Boolean(scheduledDeferredCallback);
177
- },
178
-
179
- hasScheduledAnimationCallback() {
180
- return Boolean(scheduledAnimationCallback);
181
- },
182
-
175
// Shortcut for testing a single root
176
render(element : ReactElement<any>, callback: ?Function) {
177
ReactNoop.renderToRootWithID(element, DEFAULT_ROOT_ID, callback);
src/renderers/shared/fiber/__tests__/ReactIncrementalScheduling-test.js
+385
-93
@@ -29,13 +29,9 @@ describe('ReactIncrementalScheduling', () => {
29
ReactNoop.performAnimationWork(() => {
30
ReactNoop.render(<span prop="1" />);
31
});
32
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
33
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
32
expect(ReactNoop.getChildren()).toEqual([]);
33
34
ReactNoop.flushAnimationPri();
37
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
38
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
35
expect(ReactNoop.getChildren()).toEqual([span('1')]);
36
});
37
@@ -45,15 +41,11 @@ describe('ReactIncrementalScheduling', () => {
41
ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
42
ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
43
});
48
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
49
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
44
expect(ReactNoop.getChildren('a')).toEqual([]);
45
expect(ReactNoop.getChildren('b')).toEqual([]);
46
expect(ReactNoop.getChildren('c')).toEqual([]);
47
48
ReactNoop.flushAnimationPri();
55
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
56
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
49
expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
50
expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
51
expect(ReactNoop.getChildren('c')).toEqual([span('c:1')]);
@@ -66,13 +58,9 @@ describe('ReactIncrementalScheduling', () => {
58
ReactNoop.performAnimationWork(() => {
59
ReactNoop.render(<span prop="2" />);
60
});
69
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
70
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
61
expect(ReactNoop.getChildren()).toEqual([]);
62
63
ReactNoop.flushAnimationPri();
74
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
75
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
64
expect(ReactNoop.getChildren()).toEqual([span('2')]);
65
});
66
@@ -87,15 +75,11 @@ describe('ReactIncrementalScheduling', () => {
75
ReactNoop.renderToRootWithID(<span prop="b:2" />, 'b');
76
ReactNoop.renderToRootWithID(<span prop="c:2" />, 'c');
77
});
90
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
91
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
78
expect(ReactNoop.getChildren('a')).toEqual([]);
79
expect(ReactNoop.getChildren('b')).toEqual([]);
80
expect(ReactNoop.getChildren('c')).toEqual([]);
81
82
ReactNoop.flushAnimationPri();
97
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
98
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
83
expect(ReactNoop.getChildren('a')).toEqual([span('a:2')]);
84
expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
85
expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
@@ -103,13 +87,9 @@ describe('ReactIncrementalScheduling', () => {
87
88
it('schedules and flushes deferred work', () => {
89
ReactNoop.render(<span prop="1" />);
106
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
107
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
90
expect(ReactNoop.getChildren()).toEqual([]);
91
92
ReactNoop.flushDeferredPri();
111
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
112
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
93
expect(ReactNoop.getChildren()).toEqual([span('1')]);
94
});
95
@@ -117,15 +97,11 @@ describe('ReactIncrementalScheduling', () => {
97
ReactNoop.renderToRootWithID(<span prop="a:1" />, 'a');
98
ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
99
ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
120
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
121
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
100
expect(ReactNoop.getChildren('a')).toEqual([]);
101
expect(ReactNoop.getChildren('b')).toEqual([]);
102
expect(ReactNoop.getChildren('c')).toEqual([]);
103
104
ReactNoop.flushDeferredPri();
127
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
128
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
105
expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
106
expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
107
expect(ReactNoop.getChildren('c')).toEqual([span('c:1')]);
@@ -134,13 +110,9 @@ describe('ReactIncrementalScheduling', () => {
110
it('flushes scheduled deferred work fitting within deadline', () => {
111
ReactNoop.render(<span prop="1" />);
112
ReactNoop.render(<span prop="2" />);
137
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
138
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
113
expect(ReactNoop.getChildren()).toEqual([]);
114
115
ReactNoop.flushDeferredPri();
142
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
143
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
116
expect(ReactNoop.getChildren()).toEqual([span('2')]);
117
});
118
@@ -151,15 +123,11 @@ describe('ReactIncrementalScheduling', () => {
123
ReactNoop.renderToRootWithID(<span prop="b:2" />, 'b');
124
ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
125
ReactNoop.renderToRootWithID(<span prop="c:2" />, 'c');
154
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
155
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
126
expect(ReactNoop.getChildren('a')).toEqual([]);
127
expect(ReactNoop.getChildren('b')).toEqual([]);
128
expect(ReactNoop.getChildren('c')).toEqual([]);
129
130
ReactNoop.flushDeferredPri();
161
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
162
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
131
expect(ReactNoop.getChildren('a')).toEqual([span('a:2')]);
132
expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
133
expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
@@ -168,23 +136,15 @@ describe('ReactIncrementalScheduling', () => {
136
it('schedules more deferred work if it runs out of time', () => {
137
ReactNoop.render(<span prop="1" />);
138
ReactNoop.render(<span prop="2" />);
171
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
172
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
139
expect(ReactNoop.getChildren()).toEqual([]);
140
141
ReactNoop.flushDeferredPri(5);
176
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
177
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
142
expect(ReactNoop.getChildren()).toEqual([]);
143
144
ReactNoop.flushDeferredPri(10);
181
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
182
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
145
expect(ReactNoop.getChildren()).toEqual([]);
146
147
ReactNoop.flushDeferredPri(10);
186
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
187
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
148
expect(ReactNoop.getChildren()).toEqual([span('2')]);
149
});
150
@@ -195,29 +155,21 @@ describe('ReactIncrementalScheduling', () => {
155
ReactNoop.renderToRootWithID(<span prop="b:2" />, 'b');
156
ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
157
ReactNoop.renderToRootWithID(<span prop="c:2" />, 'c');
198
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
199
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
158
expect(ReactNoop.getChildren('a')).toEqual([]);
159
expect(ReactNoop.getChildren('b')).toEqual([]);
160
expect(ReactNoop.getChildren('c')).toEqual([]);
161
162
ReactNoop.flushDeferredPri(15);
205
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
206
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
163
expect(ReactNoop.getChildren('a')).toEqual([span('a:2')]);
164
expect(ReactNoop.getChildren('b')).toEqual([]);
165
expect(ReactNoop.getChildren('c')).toEqual([]);
166
167
ReactNoop.flushDeferredPri(15);
212
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
213
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
168
expect(ReactNoop.getChildren('a')).toEqual([span('a:2')]);
169
expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
170
expect(ReactNoop.getChildren('c')).toEqual([]);
171
172
ReactNoop.flushDeferredPri(15);
219
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
220
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
173
expect(ReactNoop.getChildren('a')).toEqual([span('a:2')]);
174
expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
175
expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
@@ -233,8 +185,6 @@ describe('ReactIncrementalScheduling', () => {
185
186
// FIXME: I would expect true here because we should have scheduled an animation callback:
187
// expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
236
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
237
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
188
expect(ReactNoop.getChildren()).toEqual([]);
189
190
// We only scheduled deferred callback so that's what we get.
@@ -242,8 +192,6 @@ describe('ReactIncrementalScheduling', () => {
192
ReactNoop.flushDeferredPri();
193
// TODO: I would expect true here because we should have tried to schedule animation sooner:
194
// expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
245
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
246
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
195
expect(ReactNoop.getChildren()).toEqual([span('2')]);
196
});
197
@@ -259,8 +207,6 @@ describe('ReactIncrementalScheduling', () => {
207
208
// FIXME: I would expect true here because we should have scheduled an animation callback:
209
// expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
262
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
263
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
210
expect(ReactNoop.getChildren('a')).toEqual([]);
211
expect(ReactNoop.getChildren('b')).toEqual([]);
212
expect(ReactNoop.getChildren('c')).toEqual([]);
@@ -270,8 +216,6 @@ describe('ReactIncrementalScheduling', () => {
216
ReactNoop.flushDeferredPri();
217
// TODO: I would expect true here because we tried to schedule animation sooner, and so it would still be scheduled:
218
// expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
273
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
274
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
219
expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
220
expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
221
expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
@@ -289,24 +233,18 @@ describe('ReactIncrementalScheduling', () => {
233
234
// FIXME: I would expect true here because we should have scheduled an animation callback:
235
// expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
292
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
293
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
236
expect(ReactNoop.getChildren()).toEqual([]);
237
238
// Flushing animation should have flushed the animation.
239
// FIXME: But it currently doesn't.
240
// Technically we didn't schedule this callback. This test is valid because we should have scheduled it.
241
ReactNoop.flushAnimationPri();
300
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
301
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
242
// TODO: I would expect [span('2')] here because it was scheduled as animation:
243
// expect(ReactNoop.getChildren()).toEqual([span('2')]);
244
expect(ReactNoop.getChildren()).toEqual([]);
245
246
// TODO: I wouldn't expect this flush to be necessary for animation work to kick in.
247
ReactNoop.flushDeferredPri();
308
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
309
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
248
expect(ReactNoop.getChildren()).toEqual([span('2')]);
249
});
250
@@ -324,8 +262,6 @@ describe('ReactIncrementalScheduling', () => {
262
263
// FIXME: I would expect true here because we should have scheduled an animation callback:
264
// expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
327
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
328
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
265
expect(ReactNoop.getChildren('a')).toEqual([]);
266
expect(ReactNoop.getChildren('b')).toEqual([]);
267
expect(ReactNoop.getChildren('c')).toEqual([]);
@@ -334,8 +270,6 @@ describe('ReactIncrementalScheduling', () => {
270
// FIXME: But it currently doesn't.
271
// Technically we didn't schedule this callback. This test is valid because we should have scheduled it.
272
ReactNoop.flushAnimationPri();
337
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
338
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
273
// TODO: I would expect this here because they were scheduled as animation:
274
// expect(ReactNoop.getChildren('a')).toEqual([]);
275
// expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
@@ -346,8 +280,6 @@ describe('ReactIncrementalScheduling', () => {
280
281
// TODO: I wouldn't expect this flush to be necessary for animation work to kick in.
282
ReactNoop.flushDeferredPri();
349
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
350
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
283
expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
284
expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
285
expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
@@ -362,10 +294,7 @@ describe('ReactIncrementalScheduling', () => {
294
});
295
// Schedule late deferred
296
ReactNoop.render(<span prop="2" />);
365
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
297
// We could also make this true because we know we have a deferred update coming.
367
- // expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
368
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
298
expect(ReactNoop.getChildren()).toEqual([]);
299
300
// Flushing deferred should have flushed both early animation and late deferred work that invalidated it.
@@ -373,16 +302,12 @@ describe('ReactIncrementalScheduling', () => {
302
// FIXME: Instead, it currently doesn't do anything.
303
// TODO: is this even a valid test? Technically we didn't schedule this callback.
304
ReactNoop.flushDeferredPri();
376
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
377
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
305
// TODO: I would expect [span('2')] here because we should have flushed everything by now:
306
// expect(ReactNoop.getChildren()).toEqual([span('2')]);
307
expect(ReactNoop.getChildren()).toEqual([]);
308
309
// Flushing animation should have been a no-op
310
ReactNoop.flushAnimationPri();
384
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
385
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
311
expect(ReactNoop.getChildren()).toEqual([span('2')]);
312
});
313
@@ -397,10 +322,7 @@ describe('ReactIncrementalScheduling', () => {
322
// Schedule late deferred
323
ReactNoop.renderToRootWithID(<span prop="b:2" />, 'b');
324
ReactNoop.renderToRootWithID(<span prop="c:2" />, 'c');
400
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
325
// We could also make this true because we know we have a deferred update coming.
402
- // expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
403
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
326
expect(ReactNoop.getChildren('a')).toEqual([]);
327
expect(ReactNoop.getChildren('b')).toEqual([]);
328
expect(ReactNoop.getChildren('c')).toEqual([]);
@@ -410,8 +332,6 @@ describe('ReactIncrementalScheduling', () => {
332
// FIXME: Instead, it currently doesn't do anything.
333
// TODO: is this even a valid test? Technically we didn't schedule this callback.
334
ReactNoop.flushDeferredPri();
413
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
414
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
335
// TODO: I would expect this here because we should have flushed everything:
336
// expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
337
// expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
@@ -422,10 +342,8 @@ describe('ReactIncrementalScheduling', () => {
342
343
// Flushing animation should have been a no-op.
344
ReactNoop.flushAnimationPri();
425
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
345
// FIXME: this deferred work should have been handled earlier.
346
// expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
428
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
347
expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
348
expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
349
// FIXME: this deferred work should have been handled earlier.
@@ -444,15 +362,11 @@ describe('ReactIncrementalScheduling', () => {
362
});
363
// Schedule late deferred
364
ReactNoop.render(<span prop="2" />);
447
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
365
// We don't need a deferred callback because the root already has animation work
449
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
366
expect(ReactNoop.getChildren()).toEqual([]);
367
368
// Flushing animation work flushes everything on this root.
369
ReactNoop.flushAnimationPri();
454
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
455
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
370
expect(ReactNoop.getChildren()).toEqual([span('2')]);
371
});
372
@@ -465,27 +379,20 @@ describe('ReactIncrementalScheduling', () => {
379
// Schedule late deferred
380
ReactNoop.renderToRootWithID(<span prop="b:2" />, 'b');
381
ReactNoop.renderToRootWithID(<span prop="c:2" />, 'c');
468
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
382
// TODO: I would expect this to be true because we know we have a deferred update coming.
470
- // expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
471
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
383
expect(ReactNoop.getChildren('a')).toEqual([]);
384
expect(ReactNoop.getChildren('b')).toEqual([]);
385
expect(ReactNoop.getChildren('c')).toEqual([]);
386
387
// Flushing animation work flushes all roots with animation work.
388
ReactNoop.flushAnimationPri();
478
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
389
// Now we know we also need a deferred update. Should we have scheduled it earlier?
480
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
390
expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
391
expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
392
expect(ReactNoop.getChildren('c')).toEqual([]);
393
394
// Flushing deferred work flushes the root with only deferred work.
395
ReactNoop.flushDeferredPri();
487
- expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
488
- expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
396
expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
397
expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
398
expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
@@ -614,4 +521,389 @@ describe('ReactIncrementalScheduling', () => {
521
expect(ReactNoop.getChildren('b')).toEqual([span('b:3')]);
522
expect(ReactNoop.getChildren('c')).toEqual([span('c:3')]);
523
});
524
+
525
+ it('performs animation work in animation callback', () => {
526
+ class Foo extends React.Component {
527
+ componentDidMount() {
528
+ // Animation work that will get performed during animation callback
529
+ ReactNoop.performAnimationWork(() => {
530
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
531
+ });
532
+ }
533
+ render() {
534
+ return <span prop="a:1" />;
535
+ }
536
+ }
537
+
538
+ // Schedule animation work
539
+ ReactNoop.performAnimationWork(() => {
540
+ ReactNoop.renderToRootWithID(<Foo />, 'a');
541
+ });
542
+
543
+ // Flushing animation work should flush animation work scheduled inside it
544
+ ReactNoop.flushAnimationPri();
545
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
546
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
547
+ });
548
+
549
+ it('schedules deferred work in animation callback', () => {
550
+ class Foo extends React.Component {
551
+ componentDidMount() {
552
+ // Deferred work that will get scheduled during animation callback
553
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
554
+ }
555
+ render() {
556
+ return <span prop="a:1" />;
557
+ }
558
+ }
559
+
560
+ // Schedule animation work
561
+ ReactNoop.performAnimationWork(() => {
562
+ ReactNoop.renderToRootWithID(<Foo />, 'a');
563
+ });
564
+
565
+ // Flushing animation work should not flush the deferred work
566
+ ReactNoop.flushAnimationPri();
567
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
568
+ expect(ReactNoop.getChildren('b')).toEqual([]);
569
+
570
+ // Flush the deferred work
571
+ ReactNoop.flushDeferredPri();
572
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
573
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
574
+ });
575
+
576
+ it('schedules deferred work and performs animation work in animation callback', () => {
577
+ let hasScheduled = false;
578
+ class Foo extends React.Component {
579
+ componentDidMount() {
580
+ // Deferred work that will get scheduled during animation callback
581
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
582
+ // Animation work that will get performed during animation callback
583
+ ReactNoop.performAnimationWork(() => {
584
+ ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
585
+ });
586
+ // Deferred work that will get scheduled during animation callback
587
+ ReactNoop.renderToRootWithID(<span prop="d:1" />, 'd');
588
+ hasScheduled = true;
589
+ }
590
+ render() {
591
+ return <span prop="a:1" />;
592
+ }
593
+ }
594
+
595
+ // Schedule animation work
596
+ ReactNoop.performAnimationWork(() => {
597
+ ReactNoop.renderToRootWithID(<Foo />, 'a');
598
+ });
599
+
600
+ // Flushing animation work should flush animation work scheduled inside it
601
+ ReactNoop.flushAnimationPri();
602
+ expect(hasScheduled).toBe(true);
603
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
604
+ expect(ReactNoop.getChildren('b')).toEqual([]);
605
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:1')]);
606
+ expect(ReactNoop.getChildren('d')).toEqual([]);
607
+
608
+ // Flush the deferred work
609
+ ReactNoop.flushDeferredPri();
610
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
611
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
612
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:1')]);
613
+ expect(ReactNoop.getChildren('d')).toEqual([span('d:1')]);
614
+ });
615
+
616
+ it('performs animation work and schedules deferred work in animation callback', () => {
617
+ let hasScheduled = false;
618
+ class Foo extends React.Component {
619
+ componentDidMount() {
620
+ // Animation work that will get performed during animation callback
621
+ ReactNoop.performAnimationWork(() => {
622
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
623
+ });
624
+ // Deferred work that will get scheduled during animation callback
625
+ ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
626
+ // Animation work that will get performed during animation callback
627
+ ReactNoop.performAnimationWork(() => {
628
+ ReactNoop.renderToRootWithID(<span prop="d:1" />, 'd');
629
+ });
630
+ hasScheduled = true;
631
+ }
632
+ render() {
633
+ return <span prop="a:1" />;
634
+ }
635
+ }
636
+
637
+ // Schedule animation work
638
+ ReactNoop.performAnimationWork(() => {
639
+ ReactNoop.renderToRootWithID(<Foo />, 'a');
640
+ });
641
+
642
+ // Flushing animation work should flush animation work scheduled inside it
643
+ ReactNoop.flushAnimationPri();
644
+ expect(hasScheduled).toBe(true);
645
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
646
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
647
+ expect(ReactNoop.getChildren('c')).toEqual([]);
648
+ expect(ReactNoop.getChildren('d')).toEqual([span('d:1')]);
649
+
650
+ // Flush the deferred work
651
+ ReactNoop.flushDeferredPri();
652
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
653
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
654
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:1')]);
655
+ expect(ReactNoop.getChildren('d')).toEqual([span('d:1')]);
656
+ });
657
+
658
+ it('performs deferred work in deferred callback if it has time', () => {
659
+ class Foo extends React.Component {
660
+ componentDidMount() {
661
+ // Deferred work that will get performed during deferred callback
662
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
663
+ }
664
+ render() {
665
+ return <span prop="a:1" />;
666
+ }
667
+ }
668
+
669
+ // Schedule deferred work
670
+ ReactNoop.renderToRootWithID(<Foo />, 'a');
671
+
672
+ // Flushing deferred work should flush deferred work scheduled inside it
673
+ ReactNoop.flushDeferredPri();
674
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
675
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
676
+ });
677
+
678
+ it('schedules deferred work in deferred callback if it runs out of time', () => {
679
+ let hasScheduled = false;
680
+ class Foo extends React.Component {
681
+ componentDidMount() {
682
+ // Deferred work that will get scheduled during deferred callback
683
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
684
+ hasScheduled = true;
685
+ }
686
+ render() {
687
+ return <span prop="a:1" />;
688
+ }
689
+ }
690
+
691
+ // Schedule deferred work
692
+ ReactNoop.renderToRootWithID(<Foo />, 'a');
693
+
694
+ // Flush just enough deferred work to schedule more deferred work
695
+ ReactNoop.flushDeferredPri(20);
696
+ expect(hasScheduled).toBe(true);
697
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
698
+ expect(ReactNoop.getChildren('b')).toEqual([]);
699
+
700
+ // Flush the rest of the deferred work
701
+ ReactNoop.flushDeferredPri(15);
702
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
703
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
704
+ });
705
+
706
+ it('performs animated work in deferred callback if it has time', () => {
707
+ class Foo extends React.Component {
708
+ componentDidMount() {
709
+ // Animated work that will get performed during deferred callback
710
+ ReactNoop.performAnimationWork(() => {
711
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
712
+ });
713
+ }
714
+ render() {
715
+ return <span prop="a:1" />;
716
+ }
717
+ }
718
+
719
+ // Schedule deferred work
720
+ ReactNoop.renderToRootWithID(<Foo />, 'a');
721
+
722
+ // Flushing deferred work should flush animated work scheduled inside it
723
+ ReactNoop.flushDeferredPri();
724
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
725
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
726
+ });
727
+
728
+ it('performs animated work and deferred work in deferred callback if it has time', () => {
729
+ class Foo extends React.Component {
730
+ componentDidMount() {
731
+ // Deferred work that will get performed during deferred callback
732
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
733
+ // Animation work that will get performed during deferred callback
734
+ ReactNoop.performAnimationWork(() => {
735
+ ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
736
+ });
737
+ // Deferred work that will get performed during deferred callback
738
+ ReactNoop.renderToRootWithID(<span prop="d:1" />, 'd');
739
+ }
740
+ render() {
741
+ return <span prop="a:1" />;
742
+ }
743
+ }
744
+
745
+ // Schedule deferred work
746
+ ReactNoop.renderToRootWithID(<Foo />, 'a');
747
+
748
+ // Flushing deferred work should flush both deferred and animated work scheduled inside it
749
+ ReactNoop.flushDeferredPri();
750
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
751
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
752
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:1')]);
753
+ expect(ReactNoop.getChildren('d')).toEqual([span('d:1')]);
754
+ });
755
+
756
+ it('performs deferred and animated work work in deferred callback if it has time', () => {
757
+ class Foo extends React.Component {
758
+ componentDidMount() {
759
+ // Animation work that will get performed during deferred callback
760
+ ReactNoop.performAnimationWork(() => {
761
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
762
+ });
763
+ // Deferred work that will get performed during deferred callback
764
+ ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
765
+ // Animation work that will get performed during deferred callback
766
+ ReactNoop.performAnimationWork(() => {
767
+ ReactNoop.renderToRootWithID(<span prop="d:1" />, 'd');
768
+ });
769
+ }
770
+ render() {
771
+ return <span prop="a:1" />;
772
+ }
773
+ }
774
+
775
+ // Schedule deferred work
776
+ ReactNoop.renderToRootWithID(<Foo />, 'a');
777
+
778
+ // Flushing deferred work should flush both deferred and animated work scheduled inside it
779
+ ReactNoop.flushDeferredPri();
780
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
781
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
782
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:1')]);
783
+ expect(ReactNoop.getChildren('d')).toEqual([span('d:1')]);
784
+ });
785
+
786
+ // This test documents the existing behavior. Desired behavior:
787
+ // it('schedules animated work in deferred callback if it runs out of time', () => {
788
+ it('FIXME: schedules animated work as if it was deferred in deferred callback if it runs out of time', () => {
789
+ let hasScheduled = false;
790
+ class Foo extends React.Component {
791
+ componentDidMount() {
792
+ // Animated work that will get scheduled during deferred callback
793
+ ReactNoop.performAnimationWork(() => {
794
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
795
+ });
796
+ hasScheduled = true;
797
+ }
798
+ render() {
799
+ return <span prop="a:1" />;
800
+ }
801
+ }
802
+
803
+ // Schedule deferred work
804
+ ReactNoop.renderToRootWithID(<Foo />, 'a');
805
+
806
+ // Flush just enough deferred work to schedule animated work
807
+ ReactNoop.flushDeferredPri(20);
808
+ expect(hasScheduled).toBe(true);
809
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
810
+ expect(ReactNoop.getChildren('b')).toEqual([]);
811
+ // FIXME: I would expect these to be flipped because animation work was scheduled.
812
+ // expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
813
+ // expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
814
+
815
+ // Flush the rest of work in an animated callback.
816
+ // Technically we didn't schedule this callback. This test is valid because we should have scheduled it.
817
+ ReactNoop.flushAnimationPri();
818
+ // FIXME: we should have flushed everything here.
819
+ // expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
820
+ // expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
821
+ // expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
822
+ // expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
823
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
824
+ expect(ReactNoop.getChildren('b')).toEqual([]);
825
+
826
+ // FIXME: it should be unnecessary to flush the deferred work:
827
+ ReactNoop.flushDeferredPri();
828
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
829
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
830
+ });
831
+
832
+ it('schedules animated work and deferred work in deferred callback if it runs out of time', () => {
833
+ let isScheduled = false;
834
+ class Foo extends React.Component {
835
+ componentDidMount() {
836
+ // Deferred work that will get performed during deferred callback
837
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
838
+ // Animation work that will get performed during deferred callback
839
+ ReactNoop.performAnimationWork(() => {
840
+ ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
841
+ });
842
+ // Deferred work that will get performed during deferred callback
843
+ ReactNoop.renderToRootWithID(<span prop="d:1" />, 'd');
844
+ isScheduled = true;
845
+ }
846
+ render() {
847
+ return <span prop="a:1" />;
848
+ }
849
+ }
850
+
851
+ // Schedule deferred work
852
+ ReactNoop.renderToRootWithID(<Foo />, 'a');
853
+
854
+ // Flushing deferred work should schedule both deferred and animated work
855
+ ReactNoop.flushDeferredPri(20);
856
+ expect(isScheduled).toBe(true);
857
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
858
+ expect(ReactNoop.getChildren('b')).toEqual([]);
859
+ expect(ReactNoop.getChildren('c')).toEqual([]);
860
+ expect(ReactNoop.getChildren('d')).toEqual([]);
861
+
862
+ // Flush the rest of the work
863
+ ReactNoop.flushDeferredPri();
864
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
865
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
866
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:1')]);
867
+ expect(ReactNoop.getChildren('d')).toEqual([span('d:1')]);
868
+ });
869
+
870
+ it('schedules deferred work and animated work in deferred callback if it runs out of time', () => {
871
+ let isScheduled = false;
872
+ class Foo extends React.Component {
873
+ componentDidMount() {
874
+ // Animation work that will get performed during deferred callback
875
+ ReactNoop.performAnimationWork(() => {
876
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
877
+ });
878
+ // Deferred work that will get performed during deferred callback
879
+ ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
880
+ // Animation work that will get performed during deferred callback
881
+ ReactNoop.performAnimationWork(() => {
882
+ ReactNoop.renderToRootWithID(<span prop="d:1" />, 'd');
883
+ });
884
+ isScheduled = true;
885
+ }
886
+ render() {
887
+ return <span prop="a:1" />;
888
+ }
889
+ }
890
+
891
+ // Schedule deferred work
892
+ ReactNoop.renderToRootWithID(<Foo />, 'a');
893
+
894
+ // Flushing deferred work should schedule both deferred and animated work
895
+ ReactNoop.flushDeferredPri(20);
896
+ expect(isScheduled).toBe(true);
897
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
898
+ expect(ReactNoop.getChildren('b')).toEqual([]);
899
+ expect(ReactNoop.getChildren('c')).toEqual([]);
900
+ expect(ReactNoop.getChildren('d')).toEqual([]);
901
+
902
+ // Flush the rest of the work
903
+ ReactNoop.flushDeferredPri();
904
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
905
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
906
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:1')]);
907
+ expect(ReactNoop.getChildren('d')).toEqual([span('d:1')]);
908
+ });
909
});