@samitouri / QOS-React / commits / 214fe84f53

Convert ReactMultiChildReconcile to createRoot (#28169)

Sebastian Silbermann committed Feb 4, 2024 at 15:44 UTC 214fe84f53c5ba9d40c3427b72c5e6fb9be830e5
1 file changed +185 -126
packages/react-dom/src/__tests__/ReactMultiChildReconcile-test.js
+185 -126
@@ -10,7 +10,8 @@
10 'use strict';
11
12 const React = require('react');
13 -const ReactDOM = require('react-dom');
13 +const ReactDOMClient = require('react-dom/client');
14 +const act = require('internal-test-utils').act;
15
16 const stripEmptyValues = function (obj) {
17 const ret = {};
@@ -221,24 +222,40 @@ function verifyDomOrderingAccurate(outerContainer, statusDisplays) {
222 expect(orderedDomKeys).toEqual(orderedLogicalKeys);
223 }
224
224 -function testPropsSequenceWithPreparedChildren(sequence, prepareChildren) {
225 +async function testPropsSequenceWithPreparedChildren(
226 + sequence,
227 + prepareChildren,
228 +) {
229 const container = document.createElement('div');
226 - const parentInstance = ReactDOM.render(
227 - <FriendsStatusDisplay {...sequence[0]} prepareChildren={prepareChildren} />,
228 - container,
229 - );
230 + const root = ReactDOMClient.createRoot(container);
231 + let parentInstance;
232 + await act(() => {
233 + root.render(
234 + <FriendsStatusDisplay
235 + {...sequence[0]}
236 + prepareChildren={prepareChildren}
237 + ref={current => {
238 + if (parentInstance === undefined) {
239 + parentInstance = current;
240 + }
241 + }}
242 + />,
243 + );
244 + });
245 let statusDisplays = parentInstance.getStatusDisplays();
246 let lastInternalStates = getInternalStateByUserName(statusDisplays);
247 verifyStatuses(statusDisplays, sequence[0]);
248
249 for (let i = 1; i < sequence.length; i++) {
235 - ReactDOM.render(
236 - <FriendsStatusDisplay
237 - {...sequence[i]}
238 - prepareChildren={prepareChildren}
239 - />,
240 - container,
241 - );
250 + await act(() => {
251 + root.render(
252 + <FriendsStatusDisplay
253 + {...sequence[i]}
254 + prepareChildren={prepareChildren}
255 + />,
256 + );
257 + });
258 +
259 statusDisplays = parentInstance.getStatusDisplays();
260 verifyStatuses(statusDisplays, sequence[i]);
261 verifyStatesPreserved(lastInternalStates, statusDisplays);
@@ -274,13 +291,13 @@ function prepareChildrenModernIterable(childrenArray) {
291 };
292 }
293
277 -function testPropsSequence(sequence) {
278 - testPropsSequenceWithPreparedChildren(sequence, prepareChildrenArray);
279 - testPropsSequenceWithPreparedChildren(
294 +async function testPropsSequence(sequence) {
295 + await testPropsSequenceWithPreparedChildren(sequence, prepareChildrenArray);
296 + await testPropsSequenceWithPreparedChildren(
297 sequence,
298 prepareChildrenLegacyIterable,
299 );
283 - testPropsSequenceWithPreparedChildren(
300 + await testPropsSequenceWithPreparedChildren(
301 sequence,
302 prepareChildrenModernIterable,
303 );
@@ -291,7 +308,7 @@ describe('ReactMultiChildReconcile', () => {
308 jest.resetModules();
309 });
310
294 - it('should reset internal state if removed then readded in an array', () => {
311 + it('should reset internal state if removed then readded in an array', async () => {
312 // Test basics.
313 const props = {
314 usernameToStatus: {
@@ -300,32 +317,44 @@ describe('ReactMultiChildReconcile', () => {
317 };
318
319 const container = document.createElement('div');
303 - const parentInstance = ReactDOM.render(
304 - <FriendsStatusDisplay
305 - {...props}
306 - prepareChildren={prepareChildrenArray}
307 - />,
308 - container,
309 - );
320 + const root = ReactDOMClient.createRoot(container);
321 + let parentInstance;
322 + await act(() => {
323 + root.render(
324 + <FriendsStatusDisplay
325 + {...props}
326 + prepareChildren={prepareChildrenArray}
327 + ref={current => {
328 + if (parentInstance === undefined) {
329 + parentInstance = current;
330 + }
331 + }}
332 + />,
333 + );
334 + });
335 let statusDisplays = parentInstance.getStatusDisplays();
336 const startingInternalState = statusDisplays.jcw.getInternalState();
337
338 // Now remove the child.
314 - ReactDOM.render(
315 - <FriendsStatusDisplay prepareChildren={prepareChildrenArray} />,
316 - container,
317 - );
339 + await act(() => {
340 + root.render(
341 + <FriendsStatusDisplay prepareChildren={prepareChildrenArray} />,
342 + );
343 + });
344 +
345 statusDisplays = parentInstance.getStatusDisplays();
346 expect(statusDisplays.jcw).toBeFalsy();
347
348 // Now reset the props that cause there to be a child
322 - ReactDOM.render(
323 - <FriendsStatusDisplay
324 - {...props}
325 - prepareChildren={prepareChildrenArray}
326 - />,
327 - container,
328 - );
349 + await act(() => {
350 + root.render(
351 + <FriendsStatusDisplay
352 + {...props}
353 + prepareChildren={prepareChildrenArray}
354 + />,
355 + );
356 + });
357 +
358 statusDisplays = parentInstance.getStatusDisplays();
359 expect(statusDisplays.jcw).toBeTruthy();
360 expect(statusDisplays.jcw.getInternalState()).not.toBe(
@@ -333,7 +362,7 @@ describe('ReactMultiChildReconcile', () => {
362 );
363 });
364
336 - it('should reset internal state if removed then readded in a legacy iterable', () => {
365 + it('should reset internal state if removed then readded in a legacy iterable', async () => {
366 // Test basics.
367 const props = {
368 usernameToStatus: {
@@ -342,32 +371,47 @@ describe('ReactMultiChildReconcile', () => {
371 };
372
373 const container = document.createElement('div');
345 - const parentInstance = ReactDOM.render(
346 - <FriendsStatusDisplay
347 - {...props}
348 - prepareChildren={prepareChildrenLegacyIterable}
349 - />,
350 - container,
351 - );
374 + const root = ReactDOMClient.createRoot(container);
375 + let parentInstance;
376 + await act(() => {
377 + root.render(
378 + <FriendsStatusDisplay
379 + {...props}
380 + prepareChildren={prepareChildrenLegacyIterable}
381 + ref={current => {
382 + if (parentInstance === undefined) {
383 + parentInstance = current;
384 + }
385 + }}
386 + />,
387 + );
388 + });
389 +
390 let statusDisplays = parentInstance.getStatusDisplays();
391 const startingInternalState = statusDisplays.jcw.getInternalState();
392
393 // Now remove the child.
356 - ReactDOM.render(
357 - <FriendsStatusDisplay prepareChildren={prepareChildrenLegacyIterable} />,
358 - container,
359 - );
394 + await act(() => {
395 + root.render(
396 + <FriendsStatusDisplay
397 + prepareChildren={prepareChildrenLegacyIterable}
398 + />,
399 + );
400 + });
401 +
402 statusDisplays = parentInstance.getStatusDisplays();
403 expect(statusDisplays.jcw).toBeFalsy();
404
405 // Now reset the props that cause there to be a child
364 - ReactDOM.render(
365 - <FriendsStatusDisplay
366 - {...props}
367 - prepareChildren={prepareChildrenLegacyIterable}
368 - />,
369 - container,
370 - );
406 + await act(() => {
407 + root.render(
408 + <FriendsStatusDisplay
409 + {...props}
410 + prepareChildren={prepareChildrenLegacyIterable}
411 + />,
412 + );
413 + });
414 +
415 statusDisplays = parentInstance.getStatusDisplays();
416 expect(statusDisplays.jcw).toBeTruthy();
417 expect(statusDisplays.jcw.getInternalState()).not.toBe(
@@ -375,7 +419,7 @@ describe('ReactMultiChildReconcile', () => {
419 );
420 });
421
378 - it('should reset internal state if removed then readded in a modern iterable', () => {
422 + it('should reset internal state if removed then readded in a modern iterable', async () => {
423 // Test basics.
424 const props = {
425 usernameToStatus: {
@@ -384,32 +428,47 @@ describe('ReactMultiChildReconcile', () => {
428 };
429
430 const container = document.createElement('div');
387 - const parentInstance = ReactDOM.render(
388 - <FriendsStatusDisplay
389 - {...props}
390 - prepareChildren={prepareChildrenModernIterable}
391 - />,
392 - container,
393 - );
431 + const root = ReactDOMClient.createRoot(container);
432 + let parentInstance;
433 + await act(() => {
434 + root.render(
435 + <FriendsStatusDisplay
436 + {...props}
437 + prepareChildren={prepareChildrenModernIterable}
438 + ref={current => {
439 + if (parentInstance === undefined) {
440 + parentInstance = current;
441 + }
442 + }}
443 + />,
444 + );
445 + });
446 +
447 let statusDisplays = parentInstance.getStatusDisplays();
448 const startingInternalState = statusDisplays.jcw.getInternalState();
449
450 // Now remove the child.
398 - ReactDOM.render(
399 - <FriendsStatusDisplay prepareChildren={prepareChildrenModernIterable} />,
400 - container,
401 - );
451 + await act(() => {
452 + root.render(
453 + <FriendsStatusDisplay
454 + prepareChildren={prepareChildrenModernIterable}
455 + />,
456 + );
457 + });
458 +
459 statusDisplays = parentInstance.getStatusDisplays();
460 expect(statusDisplays.jcw).toBeFalsy();
461
462 // Now reset the props that cause there to be a child
406 - ReactDOM.render(
407 - <FriendsStatusDisplay
408 - {...props}
409 - prepareChildren={prepareChildrenModernIterable}
410 - />,
411 - container,
412 - );
463 + await act(() => {
464 + root.render(
465 + <FriendsStatusDisplay
466 + {...props}
467 + prepareChildren={prepareChildrenModernIterable}
468 + />,
469 + );
470 + });
471 +
472 statusDisplays = parentInstance.getStatusDisplays();
473 expect(statusDisplays.jcw).toBeTruthy();
474 expect(statusDisplays.jcw.getInternalState()).not.toBe(
@@ -417,7 +476,7 @@ describe('ReactMultiChildReconcile', () => {
476 );
477 });
478
420 - it('should create unique identity', () => {
479 + it('should create unique identity', async () => {
480 // Test basics.
481 const usernameToStatus = {
482 jcw: 'jcwStatus',
@@ -425,10 +484,10 @@ describe('ReactMultiChildReconcile', () => {
484 bob: 'bobStatus',
485 };
486
428 - testPropsSequence([{usernameToStatus: usernameToStatus}]);
487 + await testPropsSequence([{usernameToStatus: usernameToStatus}]);
488 });
489
431 - it('should preserve order if children order has not changed', () => {
490 + it('should preserve order if children order has not changed', async () => {
491 const PROPS_SEQUENCE = [
492 {
493 usernameToStatus: {
@@ -443,10 +502,10 @@ describe('ReactMultiChildReconcile', () => {
502 },
503 },
504 ];
446 - testPropsSequence(PROPS_SEQUENCE);
505 + await testPropsSequence(PROPS_SEQUENCE);
506 });
507
449 - it('should transition from zero to one children correctly', () => {
508 + it('should transition from zero to one children correctly', async () => {
509 const PROPS_SEQUENCE = [
510 {usernameToStatus: {}},
511 {
@@ -455,10 +514,10 @@ describe('ReactMultiChildReconcile', () => {
514 },
515 },
516 ];
458 - testPropsSequence(PROPS_SEQUENCE);
517 + await testPropsSequence(PROPS_SEQUENCE);
518 });
519
461 - it('should transition from one to zero children correctly', () => {
520 + it('should transition from one to zero children correctly', async () => {
521 const PROPS_SEQUENCE = [
522 {
523 usernameToStatus: {
@@ -467,11 +526,11 @@ describe('ReactMultiChildReconcile', () => {
526 },
527 {usernameToStatus: {}},
528 ];
470 - testPropsSequence(PROPS_SEQUENCE);
529 + await testPropsSequence(PROPS_SEQUENCE);
530 });
531
473 - it('should transition from one child to null children', () => {
474 - testPropsSequence([
532 + it('should transition from one child to null children', async () => {
533 + await testPropsSequence([
534 {
535 usernameToStatus: {
536 first: 'firstStatus',
@@ -481,8 +540,8 @@ describe('ReactMultiChildReconcile', () => {
540 ]);
541 });
542
484 - it('should transition from null children to one child', () => {
485 - testPropsSequence([
543 + it('should transition from null children to one child', async () => {
544 + await testPropsSequence([
545 {},
546 {
547 usernameToStatus: {
@@ -492,8 +551,8 @@ describe('ReactMultiChildReconcile', () => {
551 ]);
552 });
553
495 - it('should transition from zero children to null children', () => {
496 - testPropsSequence([
554 + it('should transition from zero children to null children', async () => {
555 + await testPropsSequence([
556 {
557 usernameToStatus: {},
558 },
@@ -501,8 +560,8 @@ describe('ReactMultiChildReconcile', () => {
560 ]);
561 });
562
504 - it('should transition from null children to zero children', () => {
505 - testPropsSequence([
563 + it('should transition from null children to zero children', async () => {
564 + await testPropsSequence([
565 {},
566 {
567 usernameToStatus: {},
@@ -514,7 +573,7 @@ describe('ReactMultiChildReconcile', () => {
573 * `FriendsStatusDisplay` renders nulls as empty children (it's a convention
574 * of `FriendsStatusDisplay`, nothing related to React or these test cases.
575 */
517 - it('should remove nulled out children at the beginning', () => {
576 + it('should remove nulled out children at the beginning', async () => {
577 const PROPS_SEQUENCE = [
578 {
579 usernameToStatus: {
@@ -529,10 +588,10 @@ describe('ReactMultiChildReconcile', () => {
588 },
589 },
590 ];
532 - testPropsSequence(PROPS_SEQUENCE);
591 + await testPropsSequence(PROPS_SEQUENCE);
592 });
593
535 - it('should remove nulled out children at the end', () => {
594 + it('should remove nulled out children at the end', async () => {
595 const PROPS_SEQUENCE = [
596 {
597 usernameToStatus: {
@@ -547,10 +606,10 @@ describe('ReactMultiChildReconcile', () => {
606 },
607 },
608 ];
550 - testPropsSequence(PROPS_SEQUENCE);
609 + await testPropsSequence(PROPS_SEQUENCE);
610 });
611
553 - it('should reverse the order of two children', () => {
612 + it('should reverse the order of two children', async () => {
613 const PROPS_SEQUENCE = [
614 {
615 usernameToStatus: {
@@ -565,10 +624,10 @@ describe('ReactMultiChildReconcile', () => {
624 },
625 },
626 ];
568 - testPropsSequence(PROPS_SEQUENCE);
627 + await testPropsSequence(PROPS_SEQUENCE);
628 });
629
571 - it('should reverse the order of more than two children', () => {
630 + it('should reverse the order of more than two children', async () => {
631 const PROPS_SEQUENCE = [
632 {
633 usernameToStatus: {
@@ -585,10 +644,10 @@ describe('ReactMultiChildReconcile', () => {
644 },
645 },
646 ];
588 - testPropsSequence(PROPS_SEQUENCE);
647 + await testPropsSequence(PROPS_SEQUENCE);
648 });
649
591 - it('should cycle order correctly', () => {
650 + it('should cycle order correctly', async () => {
651 const PROPS_SEQUENCE = [
652 {
653 usernameToStatus: {
@@ -632,10 +691,10 @@ describe('ReactMultiChildReconcile', () => {
691 },
692 },
693 ];
635 - testPropsSequence(PROPS_SEQUENCE);
694 + await testPropsSequence(PROPS_SEQUENCE);
695 });
696
638 - it('should cycle order correctly in the other direction', () => {
697 + it('should cycle order correctly in the other direction', async () => {
698 const PROPS_SEQUENCE = [
699 {
700 usernameToStatus: {
@@ -679,10 +738,10 @@ describe('ReactMultiChildReconcile', () => {
738 },
739 },
740 ];
682 - testPropsSequence(PROPS_SEQUENCE);
741 + await testPropsSequence(PROPS_SEQUENCE);
742 });
743
685 - it('should remove nulled out children and ignore new null children', () => {
744 + it('should remove nulled out children and ignore new null children', async () => {
745 const PROPS_SEQUENCE = [
746 {
747 usernameToStatus: {
@@ -698,10 +757,10 @@ describe('ReactMultiChildReconcile', () => {
757 },
758 },
759 ];
701 - testPropsSequence(PROPS_SEQUENCE);
760 + await testPropsSequence(PROPS_SEQUENCE);
761 });
762
704 - it('should remove nulled out children and reorder remaining', () => {
763 + it('should remove nulled out children and reorder remaining', async () => {
764 const PROPS_SEQUENCE = [
765 {
766 usernameToStatus: {
@@ -719,10 +778,10 @@ describe('ReactMultiChildReconcile', () => {
778 },
779 },
780 ];
722 - testPropsSequence(PROPS_SEQUENCE);
781 + await testPropsSequence(PROPS_SEQUENCE);
782 });
783
725 - it('should append children to the end', () => {
784 + it('should append children to the end', async () => {
785 const PROPS_SEQUENCE = [
786 {
787 usernameToStatus: {
@@ -738,10 +797,10 @@ describe('ReactMultiChildReconcile', () => {
797 },
798 },
799 ];
741 - testPropsSequence(PROPS_SEQUENCE);
800 + await testPropsSequence(PROPS_SEQUENCE);
801 });
802
744 - it('should append multiple children to the end', () => {
803 + it('should append multiple children to the end', async () => {
804 const PROPS_SEQUENCE = [
805 {
806 usernameToStatus: {
@@ -758,10 +817,10 @@ describe('ReactMultiChildReconcile', () => {
817 },
818 },
819 ];
761 - testPropsSequence(PROPS_SEQUENCE);
820 + await testPropsSequence(PROPS_SEQUENCE);
821 });
822
764 - it('should prepend children to the beginning', () => {
823 + it('should prepend children to the beginning', async () => {
824 const PROPS_SEQUENCE = [
825 {
826 usernameToStatus: {
@@ -777,10 +836,10 @@ describe('ReactMultiChildReconcile', () => {
836 },
837 },
838 ];
780 - testPropsSequence(PROPS_SEQUENCE);
839 + await testPropsSequence(PROPS_SEQUENCE);
840 });
841
783 - it('should prepend multiple children to the beginning', () => {
842 + it('should prepend multiple children to the beginning', async () => {
843 const PROPS_SEQUENCE = [
844 {
845 usernameToStatus: {
@@ -797,10 +856,10 @@ describe('ReactMultiChildReconcile', () => {
856 },
857 },
858 ];
800 - testPropsSequence(PROPS_SEQUENCE);
859 + await testPropsSequence(PROPS_SEQUENCE);
860 });
861
803 - it('should not prepend an empty child to the beginning', () => {
862 + it('should not prepend an empty child to the beginning', async () => {
863 const PROPS_SEQUENCE = [
864 {
865 usernameToStatus: {
@@ -816,10 +875,10 @@ describe('ReactMultiChildReconcile', () => {
875 },
876 },
877 ];
819 - testPropsSequence(PROPS_SEQUENCE);
878 + await testPropsSequence(PROPS_SEQUENCE);
879 });
880
822 - it('should not append an empty child to the end', () => {
881 + it('should not append an empty child to the end', async () => {
882 const PROPS_SEQUENCE = [
883 {
884 usernameToStatus: {
@@ -835,10 +894,10 @@ describe('ReactMultiChildReconcile', () => {
894 },
895 },
896 ];
838 - testPropsSequence(PROPS_SEQUENCE);
897 + await testPropsSequence(PROPS_SEQUENCE);
898 });
899
841 - it('should not insert empty children in the middle', () => {
900 + it('should not insert empty children in the middle', async () => {
901 const PROPS_SEQUENCE = [
902 {
903 usernameToStatus: {
@@ -856,10 +915,10 @@ describe('ReactMultiChildReconcile', () => {
915 },
916 },
917 ];
859 - testPropsSequence(PROPS_SEQUENCE);
918 + await testPropsSequence(PROPS_SEQUENCE);
919 });
920
862 - it('should insert one new child in the middle', () => {
921 + it('should insert one new child in the middle', async () => {
922 const PROPS_SEQUENCE = [
923 {
924 usernameToStatus: {
@@ -875,10 +934,10 @@ describe('ReactMultiChildReconcile', () => {
934 },
935 },
936 ];
878 - testPropsSequence(PROPS_SEQUENCE);
937 + await testPropsSequence(PROPS_SEQUENCE);
938 });
939
881 - it('should insert multiple new truthy children in the middle', () => {
940 + it('should insert multiple new truthy children in the middle', async () => {
941 const PROPS_SEQUENCE = [
942 {
943 usernameToStatus: {
@@ -896,10 +955,10 @@ describe('ReactMultiChildReconcile', () => {
955 },
956 },
957 ];
899 - testPropsSequence(PROPS_SEQUENCE);
958 + await testPropsSequence(PROPS_SEQUENCE);
959 });
960
902 - it('should insert non-empty children in middle where nulls were', () => {
961 + it('should insert non-empty children in middle where nulls were', async () => {
962 const PROPS_SEQUENCE = [
963 {
964 usernameToStatus: {
@@ -920,6 +979,6 @@ describe('ReactMultiChildReconcile', () => {
979 },
980 },
981 ];
923 - testPropsSequence(PROPS_SEQUENCE);
982 + await testPropsSequence(PROPS_SEQUENCE);
983 });
984 });