@samitouri / QOS-React / commits / f85f429d55

Use `act()` in ReactFabric tests (#21839) (#21841)

Co-authored-by: Timothy Yung <yungsters@fb.com>

Andrew Clark committed Jul 8, 2021 at 22:35 UTC f85f429d55f3f13bd741b4e4a06e3fcc54f2330c
1 file changed +273 -188
packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js
+273 -188
@@ -16,6 +16,7 @@ let createReactNativeComponentClass;
16 let UIManager;
17 let StrictMode;
18 let TextInputState;
19 +let act;
20
21 const SET_NATIVE_PROPS_NOT_SUPPORTED_MESSAGE =
22 'Warning: setNativeProps is not currently supported in Fabric';
@@ -47,6 +48,8 @@ describe('ReactFabric', () => {
48 .ReactNativeViewConfigRegistry.register;
49 TextInputState = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
50 .TextInputState;
51 +
52 + act = require('jest-react').act;
53 });
54
55 it('should be able to create and render a native component', () => {
@@ -55,7 +58,9 @@ describe('ReactFabric', () => {
58 uiViewClassName: 'RCTView',
59 }));
60
58 - ReactFabric.render(<View foo="test" />, 1);
61 + act(() => {
62 + ReactFabric.render(<View foo="test" />, 1);
63 + });
64 expect(nativeFabricUIManager.createNode).toBeCalled();
65 expect(nativeFabricUIManager.appendChild).not.toBeCalled();
66 expect(nativeFabricUIManager.completeRoot).toBeCalled();
@@ -71,11 +76,15 @@ describe('ReactFabric', () => {
76
77 nativeFabricUIManager.createNode.mockReturnValue(firstNode);
78
74 - ReactFabric.render(<View foo="foo" />, 11);
79 + act(() => {
80 + ReactFabric.render(<View foo="foo" />, 11);
81 + });
82
83 expect(nativeFabricUIManager.createNode).toHaveBeenCalledTimes(1);
84
78 - ReactFabric.render(<View foo="bar" />, 11);
85 + act(() => {
86 + ReactFabric.render(<View foo="bar" />, 11);
87 + });
88
89 expect(nativeFabricUIManager.createNode).toHaveBeenCalledTimes(1);
90 expect(nativeFabricUIManager.cloneNodeWithNewProps).toHaveBeenCalledTimes(
@@ -97,7 +106,9 @@ describe('ReactFabric', () => {
106 uiViewClassName: 'RCTText',
107 }));
108
100 - ReactFabric.render(<Text foo="a">1</Text>, 11);
109 + act(() => {
110 + ReactFabric.render(<Text foo="a">1</Text>, 11);
111 + });
112 expect(nativeFabricUIManager.cloneNode).not.toBeCalled();
113 expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled();
114 expect(nativeFabricUIManager.cloneNodeWithNewProps).not.toBeCalled();
@@ -106,7 +117,9 @@ describe('ReactFabric', () => {
117 ).not.toBeCalled();
118
119 // If no properties have changed, we shouldn't call cloneNode.
109 - ReactFabric.render(<Text foo="a">1</Text>, 11);
120 + act(() => {
121 + ReactFabric.render(<Text foo="a">1</Text>, 11);
122 + });
123 expect(nativeFabricUIManager.cloneNode).not.toBeCalled();
124 expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled();
125 expect(nativeFabricUIManager.cloneNodeWithNewProps).not.toBeCalled();
@@ -115,7 +128,9 @@ describe('ReactFabric', () => {
128 ).not.toBeCalled();
129
130 // Only call cloneNode for the changed property (and not for text).
118 - ReactFabric.render(<Text foo="b">1</Text>, 11);
131 + act(() => {
132 + ReactFabric.render(<Text foo="b">1</Text>, 11);
133 + });
134 expect(nativeFabricUIManager.cloneNode).not.toBeCalled();
135 expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled();
136 expect(nativeFabricUIManager.cloneNodeWithNewProps).toHaveBeenCalledTimes(
@@ -126,7 +141,9 @@ describe('ReactFabric', () => {
141 ).not.toBeCalled();
142
143 // Only call cloneNode for the changed text (and no other properties).
129 - ReactFabric.render(<Text foo="b">2</Text>, 11);
144 + act(() => {
145 + ReactFabric.render(<Text foo="b">2</Text>, 11);
146 + });
147 expect(nativeFabricUIManager.cloneNode).not.toBeCalled();
148 expect(
149 nativeFabricUIManager.cloneNodeWithNewChildren,
@@ -139,7 +156,9 @@ describe('ReactFabric', () => {
156 ).not.toBeCalled();
157
158 // Call cloneNode for both changed text and properties.
142 - ReactFabric.render(<Text foo="c">3</Text>, 11);
159 + act(() => {
160 + ReactFabric.render(<Text foo="c">3</Text>, 11);
161 + });
162 expect(nativeFabricUIManager.cloneNode).not.toBeCalled();
163 expect(
164 nativeFabricUIManager.cloneNodeWithNewChildren,
@@ -158,12 +177,14 @@ describe('ReactFabric', () => {
177 uiViewClassName: 'RCTText',
178 }));
179
161 - ReactFabric.render(
162 - <Text foo="a" bar="a">
163 - 1
164 - </Text>,
165 - 11,
166 - );
180 + act(() => {
181 + ReactFabric.render(
182 + <Text foo="a" bar="a">
183 + 1
184 + </Text>,
185 + 11,
186 + );
187 + });
188 expect(nativeFabricUIManager.cloneNode).not.toBeCalled();
189 expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled();
190 expect(nativeFabricUIManager.cloneNodeWithNewProps).not.toBeCalled();
@@ -171,12 +192,14 @@ describe('ReactFabric', () => {
192 nativeFabricUIManager.cloneNodeWithNewChildrenAndProps,
193 ).not.toBeCalled();
194
174 - ReactFabric.render(
175 - <Text foo="a" bar="b">
176 - 1
177 - </Text>,
178 - 11,
179 - );
195 + act(() => {
196 + ReactFabric.render(
197 + <Text foo="a" bar="b">
198 + 1
199 + </Text>,
200 + 11,
201 + );
202 + });
203 expect(
204 nativeFabricUIManager.cloneNodeWithNewProps.mock.calls[0][1],
205 ).toEqual({
@@ -186,12 +209,14 @@ describe('ReactFabric', () => {
209 nativeFabricUIManager.__dumpHierarchyForJestTestsOnly(),
210 ).toMatchSnapshot();
211
189 - ReactFabric.render(
190 - <Text foo="b" bar="b">
191 - 2
192 - </Text>,
193 - 11,
194 - );
212 + act(() => {
213 + ReactFabric.render(
214 + <Text foo="b" bar="b">
215 + 2
216 + </Text>,
217 + 11,
218 + );
219 + });
220 expect(
221 nativeFabricUIManager.cloneNodeWithNewChildrenAndProps.mock.calls[0][1],
222 ).toEqual({
@@ -211,15 +236,17 @@ describe('ReactFabric', () => {
236 UIManager.updateView.mockReset();
237
238 let viewRef;
214 - ReactFabric.render(
215 - <View
216 - foo="bar"
217 - ref={ref => {
218 - viewRef = ref;
219 - }}
220 - />,
221 - 11,
222 - );
239 + act(() => {
240 + ReactFabric.render(
241 + <View
242 + foo="bar"
243 + ref={ref => {
244 + viewRef = ref;
245 + }}
246 + />,
247 + 11,
248 + );
249 + });
250 expect(UIManager.updateView).not.toBeCalled();
251
252 expect(() => {
@@ -247,14 +274,16 @@ describe('ReactFabric', () => {
274 nativeFabricUIManager.dispatchCommand.mockClear();
275
276 let viewRef;
250 - ReactFabric.render(
251 - <View
252 - ref={ref => {
253 - viewRef = ref;
254 - }}
255 - />,
256 - 11,
257 - );
277 + act(() => {
278 + ReactFabric.render(
279 + <View
280 + ref={ref => {
281 + viewRef = ref;
282 + }}
283 + />,
284 + 11,
285 + );
286 + });
287
288 expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
289 ReactFabric.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
@@ -274,14 +303,16 @@ describe('ReactFabric', () => {
303 nativeFabricUIManager.dispatchCommand.mockReset();
304
305 let viewRef;
277 - ReactFabric.render(
278 - <BasicClass
279 - ref={ref => {
280 - viewRef = ref;
281 - }}
282 - />,
283 - 11,
284 - );
306 + act(() => {
307 + ReactFabric.render(
308 + <BasicClass
309 + ref={ref => {
310 + viewRef = ref;
311 + }}
312 + />,
313 + 11,
314 + );
315 + });
316
317 expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
318 expect(() => {
@@ -302,14 +333,16 @@ describe('ReactFabric', () => {
333 nativeFabricUIManager.sendAccessibilityEvent.mockClear();
334
335 let viewRef;
305 - ReactFabric.render(
306 - <View
307 - ref={ref => {
308 - viewRef = ref;
309 - }}
310 - />,
311 - 11,
312 - );
336 + act(() => {
337 + ReactFabric.render(
338 + <View
339 + ref={ref => {
340 + viewRef = ref;
341 + }}
342 + />,
343 + 11,
344 + );
345 + });
346
347 expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();
348 ReactFabric.sendAccessibilityEvent(viewRef, 'focus');
@@ -332,14 +365,16 @@ describe('ReactFabric', () => {
365 nativeFabricUIManager.sendAccessibilityEvent.mockReset();
366
367 let viewRef;
335 - ReactFabric.render(
336 - <BasicClass
337 - ref={ref => {
338 - viewRef = ref;
339 - }}
340 - />,
341 - 11,
342 - );
368 + act(() => {
369 + ReactFabric.render(
370 + <BasicClass
371 + ref={ref => {
372 + viewRef = ref;
373 + }}
374 + />,
375 + 11,
376 + );
377 + });
378
379 expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();
380 expect(() => {
@@ -360,14 +395,16 @@ describe('ReactFabric', () => {
395 nativeFabricUIManager.measure.mockClear();
396
397 let viewRef;
363 - ReactFabric.render(
364 - <View
365 - ref={ref => {
366 - viewRef = ref;
367 - }}
368 - />,
369 - 11,
370 - );
398 + act(() => {
399 + ReactFabric.render(
400 + <View
401 + ref={ref => {
402 + viewRef = ref;
403 + }}
404 + />,
405 + 11,
406 + );
407 + });
408
409 expect(nativeFabricUIManager.measure).not.toBeCalled();
410 const successCallback = jest.fn();
@@ -386,14 +423,16 @@ describe('ReactFabric', () => {
423 nativeFabricUIManager.measureInWindow.mockClear();
424
425 let viewRef;
389 - ReactFabric.render(
390 - <View
391 - ref={ref => {
392 - viewRef = ref;
393 - }}
394 - />,
395 - 11,
396 - );
426 + act(() => {
427 + ReactFabric.render(
428 + <View
429 + ref={ref => {
430 + viewRef = ref;
431 + }}
432 + />,
433 + 11,
434 + );
435 + });
436
437 expect(nativeFabricUIManager.measureInWindow).not.toBeCalled();
438 const successCallback = jest.fn();
@@ -413,22 +452,24 @@ describe('ReactFabric', () => {
452
453 let viewRef;
454 let otherRef;
416 - ReactFabric.render(
417 - <View>
418 - <View
419 - foo="bar"
420 - ref={ref => {
421 - viewRef = ref;
422 - }}
423 - />
424 - <View
425 - ref={ref => {
426 - otherRef = ref;
427 - }}
428 - />
429 - </View>,
430 - 11,
431 - );
455 + act(() => {
456 + ReactFabric.render(
457 + <View>
458 + <View
459 + foo="bar"
460 + ref={ref => {
461 + viewRef = ref;
462 + }}
463 + />
464 + <View
465 + ref={ref => {
466 + otherRef = ref;
467 + }}
468 + />
469 + </View>,
470 + 11,
471 + );
472 + });
473
474 expect(nativeFabricUIManager.measureLayout).not.toBeCalled();
475 const successCallback = jest.fn();
@@ -483,12 +524,16 @@ describe('ReactFabric', () => {
524 const before = 'abcdefghijklmnopqrst';
525 const after = 'mxhpgwfralkeoivcstzy';
526
486 - ReactFabric.render(<Component chars={before} />, 11);
527 + act(() => {
528 + ReactFabric.render(<Component chars={before} />, 11);
529 + });
530 expect(
531 nativeFabricUIManager.__dumpHierarchyForJestTestsOnly(),
532 ).toMatchSnapshot();
533
491 - ReactFabric.render(<Component chars={after} />, 11);
534 + act(() => {
535 + ReactFabric.render(<Component chars={after} />, 11);
536 + });
537 expect(
538 nativeFabricUIManager.__dumpHierarchyForJestTestsOnly(),
539 ).toMatchSnapshot();
@@ -521,12 +566,14 @@ describe('ReactFabric', () => {
566
567 const ref = React.createRef();
568 // Wrap in a host node.
524 - ReactFabric.render(
525 - <View>
526 - <Component ref={ref} />
527 - </View>,
528 - 11,
529 - );
569 + act(() => {
570 + ReactFabric.render(
571 + <View>
572 + <Component ref={ref} />
573 + </View>,
574 + 11,
575 + );
576 + });
577 expect(
578 nativeFabricUIManager.__dumpHierarchyForJestTestsOnly(),
579 ).toMatchSnapshot();
@@ -552,7 +599,9 @@ describe('ReactFabric', () => {
599 }
600 }
601
555 - ReactFabric.render(<Component />, 11);
602 + act(() => {
603 + ReactFabric.render(<Component />, 11);
604 + });
605 expect(mockArgs.length).toEqual(0);
606 });
607
@@ -572,12 +621,14 @@ describe('ReactFabric', () => {
621 );
622 });
623
575 - ReactFabric.render(
576 - <View foo="a">
577 - <View foo="b" />
578 - </View>,
579 - 22,
580 - );
624 + act(() => {
625 + ReactFabric.render(
626 + <View foo="a">
627 + <View foo="b" />
628 + </View>,
629 + 22,
630 + );
631 + });
632 expect(snapshots).toMatchSnapshot();
633 });
634
@@ -595,19 +646,23 @@ describe('ReactFabric', () => {
646 uiViewClassName: 'RCTView',
647 }));
648
598 - ReactFabric.render(
599 - <Text>
600 - <View />
601 - </Text>,
602 - 11,
603 - );
649 + act(() => {
650 + ReactFabric.render(
651 + <Text>
652 + <View />
653 + </Text>,
654 + 11,
655 + );
656 + });
657
605 - ReactFabric.render(
606 - <Text>
607 - <Image />
608 - </Text>,
609 - 11,
610 - );
658 + act(() => {
659 + ReactFabric.render(
660 + <Text>
661 + <Image />
662 + </Text>,
663 + 11,
664 + );
665 + });
666 });
667
668 it('should throw for text not inside of a <Text> ancestor', () => {
@@ -624,18 +679,22 @@ describe('ReactFabric', () => {
679 uiViewClassName: 'RCTView',
680 }));
681
627 - expect(() => ReactFabric.render(<View>this should warn</View>, 11)).toThrow(
628 - 'Text strings must be rendered within a <Text> component.',
629 - );
682 + expect(() => {
683 + act(() => {
684 + ReactFabric.render(<View>this should warn</View>, 11);
685 + });
686 + }).toThrow('Text strings must be rendered within a <Text> component.');
687
631 - expect(() =>
632 - ReactFabric.render(
633 - <Text>
634 - <ScrollView>hi hello hi</ScrollView>
635 - </Text>,
636 - 11,
637 - ),
638 - ).toThrow('Text strings must be rendered within a <Text> component.');
688 + expect(() => {
689 + act(() => {
690 + ReactFabric.render(
691 + <Text>
692 + <ScrollView>hi hello hi</ScrollView>
693 + </Text>,
694 + 11,
695 + );
696 + });
697 + }).toThrow('Text strings must be rendered within a <Text> component.');
698 });
699
700 it('should not throw for text inside of an indirect <Text> ancestor', () => {
@@ -646,12 +705,14 @@ describe('ReactFabric', () => {
705
706 const Indirection = () => 'Hi';
707
649 - ReactFabric.render(
650 - <Text>
651 - <Indirection />
652 - </Text>,
653 - 11,
654 - );
708 + act(() => {
709 + ReactFabric.render(
710 + <Text>
711 + <Indirection />
712 + </Text>,
713 + 11,
714 + );
715 + });
716 });
717
718 it('dispatches events to the last committed props', () => {
@@ -668,7 +729,9 @@ describe('ReactFabric', () => {
729 const touchStart = jest.fn();
730 const touchStart2 = jest.fn();
731
671 - ReactFabric.render(<View onTouchStart={touchStart} />, 11);
732 + act(() => {
733 + ReactFabric.render(<View onTouchStart={touchStart} />, 11);
734 + });
735
736 expect(nativeFabricUIManager.createNode.mock.calls.length).toBe(1);
737 expect(nativeFabricUIManager.registerEventHandler.mock.calls.length).toBe(
@@ -698,7 +761,9 @@ describe('ReactFabric', () => {
761 expect(touchStart).toBeCalled();
762 expect(touchStart2).not.toBeCalled();
763
701 - ReactFabric.render(<View onTouchStart={touchStart2} />, 11);
764 + act(() => {
765 + ReactFabric.render(<View onTouchStart={touchStart2} />, 11);
766 + });
767
768 // Intentionally dispatch to the same instanceHandle again.
769 dispatchEvent(instanceHandle, 'topTouchStart', touchEvent);
@@ -742,33 +807,35 @@ describe('ReactFabric', () => {
807 const ref1 = React.createRef();
808 const ref2 = React.createRef();
809
745 - ReactFabric.render(
746 - <View id="parent">
747 - <View
748 - ref={ref1}
749 - id="one"
750 - onResponderStart={event => {
751 - expect(ref1.current).not.toBeNull();
752 - // Check for referential equality
753 - expect(ref1.current).toBe(event.target);
754 - expect(ref1.current).toBe(event.currentTarget);
755 - }}
756 - onStartShouldSetResponder={() => true}
757 - />
758 - <View
759 - ref={ref2}
760 - id="two"
761 - onResponderStart={event => {
762 - expect(ref2.current).not.toBeNull();
763 - // Check for referential equality
764 - expect(ref2.current).toBe(event.target);
765 - expect(ref2.current).toBe(event.currentTarget);
766 - }}
767 - onStartShouldSetResponder={() => true}
768 - />
769 - </View>,
770 - 1,
771 - );
810 + act(() => {
811 + ReactFabric.render(
812 + <View id="parent">
813 + <View
814 + ref={ref1}
815 + id="one"
816 + onResponderStart={event => {
817 + expect(ref1.current).not.toBeNull();
818 + // Check for referential equality
819 + expect(ref1.current).toBe(event.target);
820 + expect(ref1.current).toBe(event.currentTarget);
821 + }}
822 + onStartShouldSetResponder={() => true}
823 + />
824 + <View
825 + ref={ref2}
826 + id="two"
827 + onResponderStart={event => {
828 + expect(ref2.current).not.toBeNull();
829 + // Check for referential equality
830 + expect(ref2.current).toBe(event.target);
831 + expect(ref2.current).toBe(event.currentTarget);
832 + }}
833 + onStartShouldSetResponder={() => true}
834 + />
835 + </View>,
836 + 1,
837 + );
838 + });
839
840 const [
841 dispatchEvent,
@@ -823,7 +890,12 @@ describe('ReactFabric', () => {
890 }
891 }
892
826 - ReactFabric.render(<ContainsStrictModeChild ref={n => (parent = n)} />, 11);
893 + act(() => {
894 + ReactFabric.render(
895 + <ContainsStrictModeChild ref={n => (parent = n)} />,
896 + 11,
897 + );
898 + });
899
900 let match;
901 expect(
@@ -855,12 +927,14 @@ describe('ReactFabric', () => {
927 }
928 }
929
858 - ReactFabric.render(
859 - <StrictMode>
860 - <IsInStrictMode ref={n => (parent = n)} />
861 - </StrictMode>,
862 - 11,
863 - );
930 + act(() => {
931 + ReactFabric.render(
932 + <StrictMode>
933 + <IsInStrictMode ref={n => (parent = n)} />
934 + </StrictMode>,
935 + 11,
936 + );
937 + });
938
939 let match;
940 expect(
@@ -896,7 +970,12 @@ describe('ReactFabric', () => {
970 }
971 }
972
899 - ReactFabric.render(<ContainsStrictModeChild ref={n => (parent = n)} />, 11);
973 + act(() => {
974 + ReactFabric.render(
975 + <ContainsStrictModeChild ref={n => (parent = n)} />,
976 + 11,
977 + );
978 + });
979
980 let match;
981 expect(() => (match = ReactFabric.findNodeHandle(parent))).toErrorDev([
@@ -926,12 +1005,14 @@ describe('ReactFabric', () => {
1005 }
1006 }
1007
929 - ReactFabric.render(
930 - <StrictMode>
931 - <IsInStrictMode ref={n => (parent = n)} />
932 - </StrictMode>,
933 - 11,
934 - );
1008 + act(() => {
1009 + ReactFabric.render(
1010 + <StrictMode>
1011 + <IsInStrictMode ref={n => (parent = n)} />
1012 + </StrictMode>,
1013 + 11,
1014 + );
1015 + });
1016
1017 let match;
1018 expect(() => (match = ReactFabric.findNodeHandle(parent))).toErrorDev([
@@ -953,7 +1034,9 @@ describe('ReactFabric', () => {
1034 }));
1035
1036 const viewRef = React.createRef();
956 - ReactFabric.render(<View ref={viewRef} />, 11);
1037 + act(() => {
1038 + ReactFabric.render(<View ref={viewRef} />, 11);
1039 + });
1040
1041 expect(TextInputState.blurTextInput).not.toBeCalled();
1042
@@ -970,7 +1053,9 @@ describe('ReactFabric', () => {
1053 }));
1054
1055 const viewRef = React.createRef();
973 - ReactFabric.render(<View ref={viewRef} />, 11);
1056 + act(() => {
1057 + ReactFabric.render(<View ref={viewRef} />, 11);
1058 + });
1059
1060 expect(TextInputState.focusTextInput).not.toBeCalled();
1061