@samitouri / QOS-React / commits / 99be3781ef

[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 });