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