[Fiber] Add more tests for scheduling (#8183)
* Add more tests for scheduling * Remove ambiguous terms
Dan Abramov committed
Nov 2, 2016 at 17:49 UTC
99be3781ef9021e75614498dd72cc1d348bd1c15
9 files changed
+516
-5
scripts/fiber/tests-passing.txt
+21
-3
@@ -795,9 +795,27 @@ src/renderers/shared/fiber/__tests__/ReactIncrementalReflection-test.js
795
* finds no node before insertion and correct node before deletion
796
797
src/renderers/shared/fiber/__tests__/ReactIncrementalScheduling-test.js
798
-* schedules multiple roots
799
-* works on deferred roots in the order they were scheduled
800
-* works on roots with animation priority before deferred work
798
+* schedules and flushes hi-pri work
799
+* schedules and flushes hi-pri work for many roots
800
+* flushes all scheduled hi-pri work
801
+* flushes all scheduled hi-pri work for many roots
802
+* schedules and flushes lo-pri work
803
+* schedules and flushes lo-pri work for many roots
804
+* flushes scheduled lo-pri work fitting within deadline
805
+* flushes scheduled lo-pri work fitting within deadline for many roots
806
+* schedules more lo-pri work if it runs out of time
807
+* schedules more lo-pri work if it runs out of time with many roots
808
+* FIXME: flushes late hi-pri work in a lo-pri callback if it wins
809
+* FIXME: flushes late hi-pri work in a lo-pri callback if it wins with many roots
810
+* FIXME: ignores late hi-pri work in a hi-pri callback if it wins
811
+* FIXME: ignores late hi-pri work in a hi-pri callback if it wins with many roots
812
+* FIXME: ignores all work in a lo-pri callback if it wins
813
+* FIXME: ignores all work in a lo-pri callback if it wins with many roots
814
+* flushes root with late lo-pri work in a hi-pri callback if it wins
815
+* flushes all roots with hi-pri work in a hi-pri callback if it wins
816
+* splits lo-pri work on multiple roots
817
+* works on lo-pri roots in the order they were scheduled
818
+* handles interleaved lo-pri and hi-pri work
819
820
src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
821
* can update child nodes of a host instance
src/renderers/noop/ReactNoop.js
+20
@@ -136,10 +136,22 @@ var NoopRenderer = ReactFiberReconciler({
136
},
137
138
scheduleAnimationCallback(callback) {
139
+ if (scheduledAnimationCallback) {
140
+ throw new Error(
141
+ 'Scheduling an animation callback twice is excessive. ' +
142
+ 'Instead, keep track of whether the callback has already been scheduled.'
143
+ );
144
+ }
145
scheduledAnimationCallback = callback;
146
},
147
148
scheduleDeferredCallback(callback) {
149
+ if (scheduledDeferredCallback) {
150
+ throw new Error(
151
+ 'Scheduling deferred callback twice is excessive. ' +
152
+ 'Instead, keep track of whether the callback has already been scheduled.'
153
+ );
154
+ }
155
scheduledDeferredCallback = callback;
156
},
157
@@ -160,6 +172,14 @@ var ReactNoop = {
172
}
173
},
174
175
+ hasScheduledDeferredCallback() {
176
+ return Boolean(scheduledDeferredCallback);
177
+ },
178
+
179
+ hasScheduledAnimationCallback() {
180
+ return Boolean(scheduledAnimationCallback);
181
+ },
182
+
183
// Shortcut for testing a single root
184
render(element : ReactElement<any>, callback: ?Function) {
185
ReactNoop.renderToRootWithID(element, DEFAULT_ROOT_ID, callback);
src/renderers/shared/fiber/__tests__/ReactCoroutine-test.js
+1
@@ -17,6 +17,7 @@ var ReactCoroutine;
17
18
describe('ReactCoroutine', () => {
19
beforeEach(() => {
20
+ jest.resetModuleRegistry();
21
React = require('React');
22
ReactNoop = require('ReactNoop');
23
ReactCoroutine = require('ReactCoroutine');
src/renderers/shared/fiber/__tests__/ReactIncremental-test.js
+1
@@ -16,6 +16,7 @@ var ReactNoop;
16
17
describe('ReactIncremental', () => {
18
beforeEach(() => {
19
+ jest.resetModuleRegistry();
20
React = require('React');
21
ReactNoop = require('ReactNoop');
22
});
src/renderers/shared/fiber/__tests__/ReactIncrementalReflection-test.js
+1
@@ -16,6 +16,7 @@ var ReactNoop;
16
17
describe('ReactIncrementalReflection', () => {
18
beforeEach(() => {
19
+ jest.resetModuleRegistry();
20
React = require('React');
21
ReactNoop = require('ReactNoop');
22
});
src/renderers/shared/fiber/__tests__/ReactIncrementalScheduling-test.js
+469
-2
@@ -16,6 +16,7 @@ var ReactNoop;
16
17
describe('ReactIncrementalScheduling', () => {
18
beforeEach(() => {
19
+ jest.resetModuleRegistry();
20
React = require('React');
21
ReactNoop = require('ReactNoop');
22
});
@@ -24,7 +25,473 @@ describe('ReactIncrementalScheduling', () => {
25
return { type: 'span', children: [], prop };
26
}
27
27
- it('schedules multiple roots', () => {
28
+ it('schedules and flushes animation work', () => {
29
+ ReactNoop.performAnimationWork(() => {
30
+ ReactNoop.render(<span prop="1" />);
31
+ });
32
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
33
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
34
+ expect(ReactNoop.getChildren()).toEqual([]);
35
+
36
+ ReactNoop.flushAnimationPri();
37
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
38
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
39
+ expect(ReactNoop.getChildren()).toEqual([span('1')]);
40
+ });
41
+
42
+ it('schedules and flushes animation work for many roots', () => {
43
+ ReactNoop.performAnimationWork(() => {
44
+ ReactNoop.renderToRootWithID(<span prop="a:1" />, 'a');
45
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
46
+ ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
47
+ });
48
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
49
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
50
+ expect(ReactNoop.getChildren('a')).toEqual([]);
51
+ expect(ReactNoop.getChildren('b')).toEqual([]);
52
+ expect(ReactNoop.getChildren('c')).toEqual([]);
53
+
54
+ ReactNoop.flushAnimationPri();
55
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
56
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
57
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
58
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
59
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:1')]);
60
+ });
61
+
62
+ it('flushes all scheduled animation work', () => {
63
+ ReactNoop.performAnimationWork(() => {
64
+ ReactNoop.render(<span prop="1" />);
65
+ });
66
+ ReactNoop.performAnimationWork(() => {
67
+ ReactNoop.render(<span prop="2" />);
68
+ });
69
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
70
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
71
+ expect(ReactNoop.getChildren()).toEqual([]);
72
+
73
+ ReactNoop.flushAnimationPri();
74
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
75
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
76
+ expect(ReactNoop.getChildren()).toEqual([span('2')]);
77
+ });
78
+
79
+ it('flushes all scheduled animation work for many roots', () => {
80
+ ReactNoop.performAnimationWork(() => {
81
+ ReactNoop.renderToRootWithID(<span prop="a:1" />, 'a');
82
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
83
+ ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
84
+ });
85
+ ReactNoop.performAnimationWork(() => {
86
+ ReactNoop.renderToRootWithID(<span prop="a:2" />, 'a');
87
+ ReactNoop.renderToRootWithID(<span prop="b:2" />, 'b');
88
+ ReactNoop.renderToRootWithID(<span prop="c:2" />, 'c');
89
+ });
90
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
91
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
92
+ expect(ReactNoop.getChildren('a')).toEqual([]);
93
+ expect(ReactNoop.getChildren('b')).toEqual([]);
94
+ expect(ReactNoop.getChildren('c')).toEqual([]);
95
+
96
+ ReactNoop.flushAnimationPri();
97
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
98
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
99
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:2')]);
100
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
101
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
102
+ });
103
+
104
+ it('schedules and flushes deferred work', () => {
105
+ ReactNoop.render(<span prop="1" />);
106
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
107
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
108
+ expect(ReactNoop.getChildren()).toEqual([]);
109
+
110
+ ReactNoop.flushDeferredPri();
111
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
112
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
113
+ expect(ReactNoop.getChildren()).toEqual([span('1')]);
114
+ });
115
+
116
+ it('schedules and flushes deferred work for many roots', () => {
117
+ ReactNoop.renderToRootWithID(<span prop="a:1" />, 'a');
118
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
119
+ ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
120
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
121
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
122
+ expect(ReactNoop.getChildren('a')).toEqual([]);
123
+ expect(ReactNoop.getChildren('b')).toEqual([]);
124
+ expect(ReactNoop.getChildren('c')).toEqual([]);
125
+
126
+ ReactNoop.flushDeferredPri();
127
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
128
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
129
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
130
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]);
131
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:1')]);
132
+ });
133
+
134
+ it('flushes scheduled deferred work fitting within deadline', () => {
135
+ ReactNoop.render(<span prop="1" />);
136
+ ReactNoop.render(<span prop="2" />);
137
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
138
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
139
+ expect(ReactNoop.getChildren()).toEqual([]);
140
+
141
+ ReactNoop.flushDeferredPri();
142
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
143
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
144
+ expect(ReactNoop.getChildren()).toEqual([span('2')]);
145
+ });
146
+
147
+ it('flushes scheduled deferred work fitting within deadline for many roots', () => {
148
+ ReactNoop.renderToRootWithID(<span prop="a:1" />, 'a');
149
+ ReactNoop.renderToRootWithID(<span prop="a:2" />, 'a');
150
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
151
+ ReactNoop.renderToRootWithID(<span prop="b:2" />, 'b');
152
+ ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
153
+ ReactNoop.renderToRootWithID(<span prop="c:2" />, 'c');
154
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
155
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
156
+ expect(ReactNoop.getChildren('a')).toEqual([]);
157
+ expect(ReactNoop.getChildren('b')).toEqual([]);
158
+ expect(ReactNoop.getChildren('c')).toEqual([]);
159
+
160
+ ReactNoop.flushDeferredPri();
161
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
162
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
163
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:2')]);
164
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
165
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
166
+ });
167
+
168
+ it('schedules more deferred work if it runs out of time', () => {
169
+ ReactNoop.render(<span prop="1" />);
170
+ ReactNoop.render(<span prop="2" />);
171
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
172
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
173
+ expect(ReactNoop.getChildren()).toEqual([]);
174
+
175
+ ReactNoop.flushDeferredPri(5);
176
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
177
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
178
+ expect(ReactNoop.getChildren()).toEqual([]);
179
+
180
+ ReactNoop.flushDeferredPri(10);
181
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
182
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
183
+ expect(ReactNoop.getChildren()).toEqual([]);
184
+
185
+ ReactNoop.flushDeferredPri(10);
186
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
187
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
188
+ expect(ReactNoop.getChildren()).toEqual([span('2')]);
189
+ });
190
+
191
+ it('schedules more deferred work if it runs out of time with many roots', () => {
192
+ ReactNoop.renderToRootWithID(<span prop="a:1" />, 'a');
193
+ ReactNoop.renderToRootWithID(<span prop="a:2" />, 'a');
194
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
195
+ ReactNoop.renderToRootWithID(<span prop="b:2" />, 'b');
196
+ ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
197
+ ReactNoop.renderToRootWithID(<span prop="c:2" />, 'c');
198
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
199
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
200
+ expect(ReactNoop.getChildren('a')).toEqual([]);
201
+ expect(ReactNoop.getChildren('b')).toEqual([]);
202
+ expect(ReactNoop.getChildren('c')).toEqual([]);
203
+
204
+ ReactNoop.flushDeferredPri(15);
205
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
206
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
207
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:2')]);
208
+ expect(ReactNoop.getChildren('b')).toEqual([]);
209
+ expect(ReactNoop.getChildren('c')).toEqual([]);
210
+
211
+ ReactNoop.flushDeferredPri(15);
212
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
213
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
214
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:2')]);
215
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
216
+ expect(ReactNoop.getChildren('c')).toEqual([]);
217
+
218
+ ReactNoop.flushDeferredPri(15);
219
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
220
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
221
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:2')]);
222
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
223
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
224
+ });
225
+
226
+ it('FIXME: flushes late animation work in a deferred callback if it wins', () => {
227
+ // Schedule early deferred
228
+ ReactNoop.render(<span prop="1" />);
229
+ // Schedule late animation
230
+ ReactNoop.performAnimationWork(() => {
231
+ ReactNoop.render(<span prop="2" />);
232
+ });
233
+
234
+ // FIXME: I would expect true here because we should have scheduled an animation callback:
235
+ // expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
236
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
237
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
238
+ expect(ReactNoop.getChildren()).toEqual([]);
239
+
240
+ // We only scheduled deferred callback so that's what we get.
241
+ // It will flush everything.
242
+ ReactNoop.flushDeferredPri();
243
+ // TODO: I would expect true here because we should have tried to schedule animation sooner:
244
+ // expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
245
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
246
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
247
+ expect(ReactNoop.getChildren()).toEqual([span('2')]);
248
+ });
249
+
250
+ it('FIXME: flushes late animation work in a deferred callback if it wins with many roots', () => {
251
+ // Schedule early deferred
252
+ ReactNoop.renderToRootWithID(<span prop="a:1" />, 'a');
253
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
254
+ // Schedule late animation
255
+ ReactNoop.performAnimationWork(() => {
256
+ ReactNoop.renderToRootWithID(<span prop="b:2" />, 'b');
257
+ ReactNoop.renderToRootWithID(<span prop="c:2" />, 'c');
258
+ });
259
+
260
+ // FIXME: I would expect true here because we should have scheduled an animation callback:
261
+ // expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
262
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
263
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
264
+ expect(ReactNoop.getChildren('a')).toEqual([]);
265
+ expect(ReactNoop.getChildren('b')).toEqual([]);
266
+ expect(ReactNoop.getChildren('c')).toEqual([]);
267
+
268
+ // We only scheduled deferred callback so that's what we get.
269
+ // It will flush everything.
270
+ ReactNoop.flushDeferredPri();
271
+ // TODO: I would expect true here because we tried to schedule animation sooner, and so it would still be scheduled:
272
+ // expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
273
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
274
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
275
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
276
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
277
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
278
+ });
279
+
280
+ // This test documents the existing behavior. Desired behavior:
281
+ // it('flushes late animation work in an animation callback if it wins', () => {
282
+ it('FIXME: ignores late animation work in an animation callback if it wins', () => {
283
+ // Schedule early deferred
284
+ ReactNoop.render(<span prop="1" />);
285
+ // Schedule late animation
286
+ ReactNoop.performAnimationWork(() => {
287
+ ReactNoop.render(<span prop="2" />);
288
+ });
289
+
290
+ // FIXME: I would expect true here because we should have scheduled an animation callback:
291
+ // expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
292
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
293
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
294
+ expect(ReactNoop.getChildren()).toEqual([]);
295
+
296
+ // Flushing animation should have flushed the animation.
297
+ // FIXME: But it currently doesn't.
298
+ // Technically we didn't schedule this callback. This test is valid because we should have scheduled it.
299
+ ReactNoop.flushAnimationPri();
300
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
301
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
302
+ // TODO: I would expect [span('2')] here because it was scheduled as animation:
303
+ // expect(ReactNoop.getChildren()).toEqual([span('2')]);
304
+ expect(ReactNoop.getChildren()).toEqual([]);
305
+
306
+ // TODO: I wouldn't expect this flush to be necessary for animation work to kick in.
307
+ ReactNoop.flushDeferredPri();
308
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
309
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
310
+ expect(ReactNoop.getChildren()).toEqual([span('2')]);
311
+ });
312
+
313
+ // This test documents the existing behavior. Desired behavior:
314
+ // it('flushes late animation work in an animation callback if it wins with many roots', () => {
315
+ it('FIXME: ignores late animation work in an animation callback if it wins with many roots', () => {
316
+ // Schedule early deferred
317
+ ReactNoop.renderToRootWithID(<span prop="a:1" />, 'a');
318
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
319
+ // Schedule late animation
320
+ ReactNoop.performAnimationWork(() => {
321
+ ReactNoop.renderToRootWithID(<span prop="b:2" />, 'b');
322
+ ReactNoop.renderToRootWithID(<span prop="c:2" />, 'c');
323
+ });
324
+
325
+ // FIXME: I would expect true here because we should have scheduled an animation callback:
326
+ // expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
327
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
328
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
329
+ expect(ReactNoop.getChildren('a')).toEqual([]);
330
+ expect(ReactNoop.getChildren('b')).toEqual([]);
331
+ expect(ReactNoop.getChildren('c')).toEqual([]);
332
+
333
+ // Flushing animation should have flushed the animation.
334
+ // FIXME: But it currently doesn't.
335
+ // Technically we didn't schedule this callback. This test is valid because we should have scheduled it.
336
+ ReactNoop.flushAnimationPri();
337
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
338
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
339
+ // TODO: I would expect this here because they were scheduled as animation:
340
+ // expect(ReactNoop.getChildren('a')).toEqual([]);
341
+ // expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
342
+ // expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
343
+ expect(ReactNoop.getChildren('a')).toEqual([]);
344
+ expect(ReactNoop.getChildren('b')).toEqual([]);
345
+ expect(ReactNoop.getChildren('c')).toEqual([]);
346
+
347
+ // TODO: I wouldn't expect this flush to be necessary for animation work to kick in.
348
+ ReactNoop.flushDeferredPri();
349
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
350
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
351
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
352
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
353
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
354
+ });
355
+
356
+ // This test documents the existing behavior. Desired behavior:
357
+ // it('flushes all work in a deferred callback if it wins', () => {
358
+ it('FIXME: ignores all work in a deferred callback if it wins', () => {
359
+ // Schedule early animation
360
+ ReactNoop.performAnimationWork(() => {
361
+ ReactNoop.render(<span prop="1" />);
362
+ });
363
+ // Schedule late deferred
364
+ ReactNoop.render(<span prop="2" />);
365
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
366
+ // 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);
369
+ expect(ReactNoop.getChildren()).toEqual([]);
370
+
371
+ // Flushing deferred should have flushed both early animation and late deferred work that invalidated it.
372
+ // This is not a common case, as animation should generally be flushed before deferred work.
373
+ // FIXME: Instead, it currently doesn't do anything.
374
+ // TODO: is this even a valid test? Technically we didn't schedule this callback.
375
+ ReactNoop.flushDeferredPri();
376
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
377
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
378
+ // TODO: I would expect [span('2')] here because we should have flushed everything by now:
379
+ // expect(ReactNoop.getChildren()).toEqual([span('2')]);
380
+ expect(ReactNoop.getChildren()).toEqual([]);
381
+
382
+ // Flushing animation should have been a no-op
383
+ ReactNoop.flushAnimationPri();
384
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
385
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
386
+ expect(ReactNoop.getChildren()).toEqual([span('2')]);
387
+ });
388
+
389
+ // This test documents the existing behavior. Desired behavior:
390
+ // it('flushes all work in a deferred callback if it wins with many roots', () => {
391
+ it('FIXME: ignores all work in a deferred callback if it wins with many roots', () => {
392
+ // Schedule early animation
393
+ ReactNoop.performAnimationWork(() => {
394
+ ReactNoop.renderToRootWithID(<span prop="a:1" />, 'a');
395
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
396
+ });
397
+ // Schedule late deferred
398
+ ReactNoop.renderToRootWithID(<span prop="b:2" />, 'b');
399
+ ReactNoop.renderToRootWithID(<span prop="c:2" />, 'c');
400
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
401
+ // 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);
404
+ expect(ReactNoop.getChildren('a')).toEqual([]);
405
+ expect(ReactNoop.getChildren('b')).toEqual([]);
406
+ expect(ReactNoop.getChildren('c')).toEqual([]);
407
+
408
+ // Flushing deferred should have flushed both early animation and late deferred work that invalidated it.
409
+ // This is not a common case, as animation should generally be flushed before deferred work.
410
+ // FIXME: Instead, it currently doesn't do anything.
411
+ // TODO: is this even a valid test? Technically we didn't schedule this callback.
412
+ ReactNoop.flushDeferredPri();
413
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
414
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
415
+ // TODO: I would expect this here because we should have flushed everything:
416
+ // expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
417
+ // expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
418
+ // expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
419
+ expect(ReactNoop.getChildren('a')).toEqual([]);
420
+ expect(ReactNoop.getChildren('b')).toEqual([]);
421
+ expect(ReactNoop.getChildren('c')).toEqual([]);
422
+
423
+ // Flushing animation should have been a no-op.
424
+ ReactNoop.flushAnimationPri();
425
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
426
+ // FIXME: this deferred work should have been handled earlier.
427
+ // expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
428
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
429
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
430
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
431
+ // FIXME: this deferred work should have been handled earlier.
432
+ // expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
433
+ expect(ReactNoop.getChildren('c')).toEqual([]);
434
+
435
+ // FIXME: it should be unnecessary to flush one more time:
436
+ ReactNoop.flushDeferredPri();
437
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
438
+ });
439
+
440
+ it('flushes root with late deferred work in an animation callback if it wins', () => {
441
+ // Schedule early animation
442
+ ReactNoop.performAnimationWork(() => {
443
+ ReactNoop.render(<span prop="1" />);
444
+ });
445
+ // Schedule late deferred
446
+ ReactNoop.render(<span prop="2" />);
447
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
448
+ // We don't need a deferred callback because the root already has animation work
449
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
450
+ expect(ReactNoop.getChildren()).toEqual([]);
451
+
452
+ // Flushing animation work flushes everything on this root.
453
+ ReactNoop.flushAnimationPri();
454
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
455
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
456
+ expect(ReactNoop.getChildren()).toEqual([span('2')]);
457
+ });
458
+
459
+ it('flushes all roots with animation work in an animation callback if it wins', () => {
460
+ // Schedule early animation
461
+ ReactNoop.performAnimationWork(() => {
462
+ ReactNoop.renderToRootWithID(<span prop="a:1" />, 'a');
463
+ ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
464
+ });
465
+ // Schedule late deferred
466
+ ReactNoop.renderToRootWithID(<span prop="b:2" />, 'b');
467
+ ReactNoop.renderToRootWithID(<span prop="c:2" />, 'c');
468
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(true);
469
+ // 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);
472
+ expect(ReactNoop.getChildren('a')).toEqual([]);
473
+ expect(ReactNoop.getChildren('b')).toEqual([]);
474
+ expect(ReactNoop.getChildren('c')).toEqual([]);
475
+
476
+ // Flushing animation work flushes all roots with animation work.
477
+ ReactNoop.flushAnimationPri();
478
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
479
+ // Now we know we also need a deferred update. Should we have scheduled it earlier?
480
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(true);
481
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
482
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
483
+ expect(ReactNoop.getChildren('c')).toEqual([]);
484
+
485
+ // Flushing deferred work flushes the root with only deferred work.
486
+ ReactNoop.flushDeferredPri();
487
+ expect(ReactNoop.hasScheduledAnimationCallback()).toBe(false);
488
+ expect(ReactNoop.hasScheduledDeferredCallback()).toBe(false);
489
+ expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]);
490
+ expect(ReactNoop.getChildren('b')).toEqual([span('b:2')]);
491
+ expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
492
+ });
493
+
494
+ it('splits deferred work on multiple roots', () => {
495
// Schedule one root
496
ReactNoop.renderToRootWithID(<span prop="a:1" />, 'a');
497
ReactNoop.flushDeferredPri(15);
@@ -100,7 +567,7 @@ describe('ReactIncrementalScheduling', () => {
567
expect(ReactNoop.getChildren('c')).toEqual([span('c:2')]);
568
});
569
103
- it('works on roots with animation priority before deferred work', () => {
570
+ it('handles interleaved deferred and animation work', () => {
571
ReactNoop.renderToRootWithID(<span prop="a:1" />, 'a');
572
ReactNoop.renderToRootWithID(<span prop="b:1" />, 'b');
573
ReactNoop.renderToRootWithID(<span prop="c:1" />, 'c');
src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
+1
@@ -16,6 +16,7 @@ var ReactNoop;
16
17
describe('ReactIncrementalSideEffects', () => {
18
beforeEach(() => {
19
+ jest.resetModuleRegistry();
20
React = require('React');
21
ReactNoop = require('ReactNoop');
22
});
src/renderers/shared/fiber/__tests__/ReactTopLevelFragment-test.js
+1
@@ -18,6 +18,7 @@ var ReactNoop;
18
// probably move to one of the other test files once it is official.
19
describe('ReactTopLevelFragment', function() {
20
beforeEach(function() {
21
+ jest.resetModuleRegistry();
22
React = require('React');
23
ReactNoop = require('ReactNoop');
24
});
src/renderers/shared/fiber/__tests__/ReactTopLevelText-test.js
+1
@@ -18,6 +18,7 @@ var ReactNoop;
18
// probably move to one of the other test files once it is official.
19
describe('ReactTopLevelText', () => {
20
beforeEach(() => {
21
+ jest.resetModuleRegistry();
22
React = require('React');
23
ReactNoop = require('ReactNoop');
24
});