@@ -302,6 +302,136 @@ test('pushes settings screen twice', () => {
302
302
</TabItem >
303
303
</Tabs >
304
304
305
+ For writing tests that include times functions we will have to use [ Fake Timers] ( https://jestjs.io/docs/timer-mocks ) . They will replace times function implementation to use time from the fake clock.
306
+
307
+ Let's add another button, which uses ` setTimeout ` , to the previously defined ` Profile ` screen:
308
+
309
+ <Tabs groupId =" example " queryString =" example " >
310
+ <TabItem value =" static " label =" Static " default >
311
+
312
+ ``` js
313
+ const ProfileScreen = () => {
314
+ const navigation = useNavigation ();
315
+ return (
316
+ < View>
317
+ < Text > Profile Screen< / Text >
318
+ < Button
319
+ onPress= {() => navigation .navigate (' Settings' )}
320
+ title= " Navigate to Settings"
321
+ / >
322
+ < Button
323
+ onPress= {() => navigation .push (' Settings' )}
324
+ title= " Push Settings"
325
+ / >
326
+ {/* Added button */ }
327
+ < Button
328
+ onPress= {() => setTimeout (() => navigation .navigate (' Settings' ), 10000 )}
329
+ title= " Navigate to Settings with 10000 ms delay"
330
+ / >
331
+ < / View>
332
+ );
333
+ };
334
+ ```
335
+
336
+ </TabItem >
337
+ <TabItem value =" dynamic " label =" Dynamic " >
338
+
339
+ ``` js
340
+ const ProfileScreen = ({ navigation }) => {
341
+ return (
342
+ < View>
343
+ < Text > Profile Screen< / Text >
344
+ < Button
345
+ onPress= {() => navigation .navigate (' Settings' )}
346
+ title= " Navigate to Settings"
347
+ / >
348
+ < Button
349
+ onPress= {() => navigation .push (' Settings' )}
350
+ title= " Push Settings"
351
+ / >
352
+ {/* Added button */ }
353
+ < Button
354
+ onPress= {() => setTimeout (() => navigation .navigate (' Settings' ), 10000 )}
355
+ title= " Navigate to Settings with 10000 ms delay"
356
+ / >
357
+ < / View>
358
+ );
359
+ };
360
+ ```
361
+
362
+ </TabItem >
363
+ </Tabs >
364
+
365
+ Fake timers test example:
366
+
367
+ <Tabs groupId =" example " queryString =" example " >
368
+ <TabItem value =" static " label =" Static " default >
369
+
370
+ ``` js
371
+ import { expect , jest , test } from ' @jest/globals' ;
372
+ import { act , fireEvent , render , screen } from ' @testing-library/react-native' ;
373
+ import { createStaticNavigation } from ' @react-navigation/native' ;
374
+ import { RootNavigator } from ' ./RootNavigator' ;
375
+
376
+ test (' navigates to settings screen after 10000 ms delay' , () => {
377
+ // Enable fake timers
378
+ jest .useFakeTimers ();
379
+
380
+ const RootNavigation = createStaticNavigation (RootNavigator);
381
+ render (< RootNavigation / > );
382
+
383
+ fireEvent .press (screen .getByText (' Navigate to Settings with 10000 ms delay' ));
384
+
385
+ act (() => jest .advanceTimersByTime (5000 ));
386
+
387
+ expect (screen .queryByText (' Profile Screen' )).toBeOnTheScreen ();
388
+ expect (screen .queryByText (' Settings Screen' )).not .toBeOnTheScreen ();
389
+
390
+ act (() => jest .advanceTimersByTime (5000 ));
391
+
392
+ expect (screen .queryByText (' Profile Screen' )).not .toBeOnTheScreen ();
393
+ expect (screen .queryByText (' Settings Screen' )).toBeOnTheScreen ();
394
+ });
395
+ ```
396
+
397
+ </TabItem >
398
+ <TabItem value =" dynamic " label =" Dynamic " >
399
+
400
+ ``` js
401
+ import { expect , jest , test } from ' @jest/globals' ;
402
+ import { act , fireEvent , render , screen } from ' @testing-library/react-native' ;
403
+ import { NavigationContainer } from ' @react-navigation/native' ;
404
+ import { RootNavigator } from ' ./RootNavigator' ;
405
+
406
+ test (' navigates to settings screen after 10000 ms delay' , () => {
407
+ // Enable fake timers
408
+ jest .useFakeTimers ();
409
+
410
+ render (
411
+ < NavigationContainer>
412
+ < RootNavigator / >
413
+ < / NavigationContainer>
414
+ );
415
+
416
+ fireEvent .press (screen .getByText (' Navigate to Settings with 10000 ms delay' ));
417
+
418
+ // jest.advanceTimersByTime causes React state updates
419
+ // So it should be wrapped into act
420
+ act (() => jest .advanceTimersByTime (5000 ));
421
+
422
+ expect (screen .queryByText (' Profile Screen' )).toBeOnTheScreen ();
423
+ expect (screen .queryByText (' Settings Screen' )).not .toBeOnTheScreen ();
424
+
425
+ act (() => jest .advanceTimersByTime (5000 ));
426
+
427
+ expect (screen .queryByText (' Profile Screen' )).not .toBeOnTheScreen ();
428
+ expect (screen .queryByText (' Settings Screen' )).toBeOnTheScreen ();
429
+ });
430
+ ```
431
+
432
+ </TabItem >
433
+ </Tabs >
434
+
305
435
To show how drawer's screens ` preload ` works, we will compare two tests - with and without preloading.
306
436
307
437
Without preloading test example:
@@ -580,138 +710,6 @@ test('navigates to settings with previous preload', () => {
580
710
</TabItem >
581
711
</Tabs >
582
712
583
- For writing tests that include times functions we will have to use [ Fake Timers] ( https://jestjs.io/docs/timer-mocks ) . They will replace times function implementation to use time from the fake clock.
584
-
585
- Let's add another button to the Profile screen, which uses ` setTimeout ` :
586
-
587
- <Tabs groupId =" example " queryString =" example " >
588
- <TabItem value =" static " label =" Static " default >
589
-
590
- ``` js
591
- const ProfileScreen = () => {
592
- const navigation = useNavigation ();
593
- return (
594
- < View>
595
- < Text > Profile Screen< / Text >
596
- < Button
597
- onPress= {() => navigation .navigate (' Settings' )}
598
- title= " Navigate to Settings"
599
- / >
600
- < Button
601
- onPress= {() => navigation .push (' Settings' )}
602
- title= " Push Settings"
603
- / >
604
- {/* Added button */ }
605
- < Button
606
- onPress= {() => setTimeout (() => navigation .navigate (' Settings' ), 10000 )}
607
- title= " Navigate to Settings with 10000 ms delay"
608
- / >
609
- < / View>
610
- );
611
- };
612
- ```
613
-
614
- </TabItem >
615
- <TabItem value =" dynamic " label =" Dynamic " >
616
-
617
- ``` js
618
- const ProfileScreen = ({ navigation }) => {
619
- return (
620
- < View>
621
- < Text > Profile Screen< / Text >
622
- < Button
623
- onPress= {() => navigation .navigate (' Settings' )}
624
- title= " Navigate to Settings"
625
- / >
626
- < Button
627
- onPress= {() => navigation .push (' Settings' )}
628
- title= " Push Settings"
629
- / >
630
- {/* Added button */ }
631
- < Button
632
- onPress= {() => setTimeout (() => navigation .navigate (' Settings' ), 10000 )}
633
- title= " Navigate to Settings with 10000 ms delay"
634
- / >
635
- < / View>
636
- );
637
- };
638
- ```
639
-
640
- </TabItem >
641
- </Tabs >
642
-
643
- Fake timers test example:
644
-
645
- <Tabs groupId =" example " queryString =" example " >
646
- <TabItem value =" static " label =" Static " default >
647
-
648
- ``` js
649
- import { expect , jest , test } from ' @jest/globals' ;
650
- import { act , fireEvent , render , screen } from ' @testing-library/react-native' ;
651
- import { createStaticNavigation } from ' @react-navigation/native' ;
652
- import { RootNavigator } from ' ./RootNavigator' ;
653
-
654
- test (' navigates to settings screen after 10000 ms delay' , () => {
655
- // Enable fake timers
656
- jest .useFakeTimers ();
657
-
658
- const RootNavigation = createStaticNavigation (RootNavigator);
659
- render (< RootNavigation / > );
660
-
661
- fireEvent .press (screen .getByText (' Navigate to Settings with 10000 ms delay' ));
662
-
663
- // jest.advanceTimersByTime causes React state updates
664
- // So it should be wrapped into act
665
- act (() => jest .advanceTimersByTime (5000 ));
666
-
667
- expect (screen .queryByText (' Profile Screen' )).toBeOnTheScreen ();
668
- expect (screen .queryByText (' Settings Screen' )).not .toBeOnTheScreen ();
669
-
670
- act (() => jest .advanceTimersByTime (5000 ));
671
-
672
- expect (screen .queryByText (' Profile Screen' )).not .toBeOnTheScreen ();
673
- expect (screen .queryByText (' Settings Screen' )).toBeOnTheScreen ();
674
- });
675
- ```
676
-
677
- </TabItem >
678
- <TabItem value =" dynamic " label =" Dynamic " >
679
-
680
- ``` js
681
- import { expect , jest , test } from ' @jest/globals' ;
682
- import { act , fireEvent , render , screen } from ' @testing-library/react-native' ;
683
- import { NavigationContainer } from ' @react-navigation/native' ;
684
- import { RootNavigator } from ' ./RootNavigator' ;
685
-
686
- test (' navigates to settings screen after 10000 ms delay' , () => {
687
- // Enable fake timers
688
- jest .useFakeTimers ();
689
-
690
- render (
691
- < NavigationContainer>
692
- < RootNavigator / >
693
- < / NavigationContainer>
694
- );
695
-
696
- fireEvent .press (screen .getByText (' Navigate to Settings with 10000 ms delay' ));
697
-
698
- // jest.advanceTimersByTime causes React state updates
699
- // So it should be wrapped into act
700
- act (() => jest .advanceTimersByTime (5000 ));
701
-
702
- expect (screen .queryByText (' Profile Screen' )).toBeOnTheScreen ();
703
- expect (screen .queryByText (' Settings Screen' )).not .toBeOnTheScreen ();
704
-
705
- act (() => jest .advanceTimersByTime (5000 ));
706
-
707
- expect (screen .queryByText (' Profile Screen' )).not .toBeOnTheScreen ();
708
- expect (screen .queryByText (' Settings Screen' )).toBeOnTheScreen ();
709
- });
710
- ```
711
-
712
- </TabItem >
713
- </Tabs >
714
-
715
713
## Best practices
716
714
717
715
There are a couple of things to keep in mind when writing tests for components using React Navigation:
0 commit comments