67
jest.resetModules();
68
ReactFeatureFlags = require('shared/ReactFeatureFlags');
69
container = document.createElement('div');
70
+ ReactFeatureFlags.debugRenderPhaseSideEffectsForStrictMode = false;
71
ReactFeatureFlags.enableCreateRoot = true;
72
ReactDOM = require('react-dom');
73
});
306
expect(container.textContent).toEqual('ABCD');
307
expect(ops).toEqual(['BC', 'ABCD']);
308
});
309
+
310
+ it('flushControlled flushes updates before yielding to browser', () => {
311
+ let inst;
312
+ class Counter extends React.Component {
313
+ state = {counter: 0};
314
+ increment = () =>
315
+ this.setState(state => ({counter: state.counter + 1}));
316
+ render() {
317
+ inst = this;
318
+ return this.state.counter;
319
+ }
320
+ }
321
+ ReactDOM.render(
322
+ <AsyncMode>
323
+ <Counter />
324
+ </AsyncMode>,
325
+ container,
326
+ );
327
+ expect(container.textContent).toEqual('0');
328
+
329
+ // Test that a normal update is async
330
+ inst.increment();
331
+ expect(container.textContent).toEqual('0');
332
+ jest.runAllTimers();
333
+ expect(container.textContent).toEqual('1');
334
+
335
+ let ops = [];
336
+ ReactDOM.unstable_flushControlled(() => {
337
+ inst.increment();
338
+ ReactDOM.unstable_flushControlled(() => {
339
+ inst.increment();
340
+ ops.push('end of inner flush: ' + container.textContent);
341
+ });
342
+ ops.push('end of outer flush: ' + container.textContent);
343
+ });
344
+ ops.push('after outer flush: ' + container.textContent);
345
+ expect(ops).toEqual([
346
+ 'end of inner flush: 1',
347
+ 'end of outer flush: 1',
348
+ 'after outer flush: 3',
349
+ ]);
350
+ });
351
+
352
+ it('flushControlled does not flush until end of outermost batchedUpdates', () => {
353
+ let inst;
354
+ class Counter extends React.Component {
355
+ state = {counter: 0};
356
+ increment = () =>
357
+ this.setState(state => ({counter: state.counter + 1}));
358
+ render() {
359
+ inst = this;
360
+ return this.state.counter;
361
+ }
362
+ }
363
+ ReactDOM.render(<Counter />, container);
364
+
365
+ let ops = [];
366
+ ReactDOM.unstable_batchedUpdates(() => {
367
+ inst.increment();
368
+ ReactDOM.unstable_flushControlled(() => {
369
+ inst.increment();
370
+ ops.push('end of flushControlled fn: ' + container.textContent);
371
+ });
372
+ ops.push('end of batchedUpdates fn: ' + container.textContent);
373
+ });
374
+ ops.push('after batchedUpdates: ' + container.textContent);
375
+ expect(ops).toEqual([
376
+ 'end of flushControlled fn: 0',
377
+ 'end of batchedUpdates fn: 0',
378
+ 'after batchedUpdates: 2',
379
+ ]);
380
+ });
381
+
382
+ it('flushControlled returns nothing', () => {
383
+ // In the future, we may want to return a thenable "work" object.
384
+ let inst;
385
+ class Counter extends React.Component {
386
+ state = {counter: 0};
387
+ increment = () =>
388
+ this.setState(state => ({counter: state.counter + 1}));
389
+ render() {
390
+ inst = this;
391
+ return this.state.counter;
392
+ }
393
+ }
394
+ ReactDOM.render(<Counter />, container);
395
+ expect(container.textContent).toEqual('0');
396
+
397
+ const returnValue = ReactDOM.unstable_flushControlled(() => {
398
+ inst.increment();
399
+ return 'something';
400
+ });
401
+ expect(container.textContent).toEqual('1');
402
+ expect(returnValue).toBe(undefined);
403
+ });
404
});
405
});