@@ -79,7 +79,9 @@ If you're not using Jest, then you'll need to mock these modules according to th
79
79
80
80
We recommend using [ React Native Testing Library] ( https://callstack.github.io/react-native-testing-library/ ) along with [ ` jest-native ` ] ( https://github.com/testing-library/jest-native ) to write your tests.
81
81
82
- We are going to write example tests illustrating the difference between ` navigate ` and ` push ` functions using ` RootNavigator ` defined below:
82
+ We are going to write example tests illustrating the difference between ` navigate ` and ` push ` functions, drawer's screens ` preload ` and times functions in tests.
83
+
84
+ To show the difference between ` navigate ` and ` push ` functions, we will use ` RootNavigator ` defined below:
83
85
84
86
<Tabs groupId =" example " queryString =" example " >
85
87
<TabItem value =" static " label =" Static " default >
@@ -299,6 +301,285 @@ test('pushes settings screen twice', () => {
299
301
</TabItem >
300
302
</Tabs >
301
303
304
+ To show how drawer's screens ` preload ` works, we will compare two tests - with and without preloading.
305
+
306
+ Without preloading test example:
307
+
308
+ <Tabs groupId =" example " queryString =" example " >
309
+ <TabItem value =" static " label =" Static " default >
310
+
311
+ ``` js
312
+ import { expect , test } from ' @jest/globals' ;
313
+ import { createDrawerNavigator } from ' @react-navigation/drawer' ;
314
+ import {
315
+ createNavigationContainerRef ,
316
+ createStaticNavigation ,
317
+ useNavigation ,
318
+ } from ' @react-navigation/native' ;
319
+ import { fireEvent , render , screen } from ' @testing-library/react-native' ;
320
+ import { Button , Text , View } from ' react-native' ;
321
+
322
+ const Profile = () => {
323
+ const navigation = useNavigation ();
324
+ return (
325
+ < View>
326
+ < Text > Profile Screen< / Text >
327
+ < Button
328
+ onPress= {() => navigation .navigate (' Settings' )}
329
+ title= " Navigate to Settings"
330
+ / >
331
+ < / View>
332
+ );
333
+ };
334
+
335
+ let renderCounter = 0 ;
336
+
337
+ const Settings = () => {
338
+ renderCounter++ ;
339
+ return (
340
+ < View>
341
+ < Text > Settings Screen< / Text >
342
+ < / View>
343
+ );
344
+ };
345
+
346
+ const Drawer = createDrawerNavigator ({
347
+ screens: {
348
+ Profile,
349
+ Settings,
350
+ },
351
+ });
352
+
353
+ const DrawerNavigation = createStaticNavigation (Drawer);
354
+
355
+ test (' navigates to settings without previous preload' , () => {
356
+ const navigation = createNavigationContainerRef ();
357
+ render (< DrawerNavigation ref= {navigation} / > );
358
+
359
+ expect (screen .queryByText (' Profile Screen' )).toBeOnTheScreen ();
360
+ expect (screen .queryByText (' Settings Screen' )).not .toBeOnTheScreen ();
361
+ expect (renderCounter).toBe (0 );
362
+
363
+ fireEvent .press (screen .queryByText (' Navigate to Settings' ));
364
+
365
+ expect (screen .queryByText (' Profile Screen' )).not .toBeOnTheScreen ();
366
+ expect (screen .queryByText (' Settings Screen' )).toBeOnTheScreen ();
367
+ expect (renderCounter).toBe (1 );
368
+ });
369
+ ```
370
+
371
+ </TabItem >
372
+ <TabItem value =" dynamic " label =" Dynamic " >
373
+
374
+ ``` js
375
+ import { expect , test } from ' @jest/globals' ;
376
+ import { createDrawerNavigator } from ' @react-navigation/drawer' ;
377
+ import {
378
+ createNavigationContainerRef ,
379
+ NavigationContainer ,
380
+ } from ' @react-navigation/native' ;
381
+ import { fireEvent , render , screen } from ' @testing-library/react-native' ;
382
+ import { Button , Text , View } from ' react-native' ;
383
+
384
+ const Profile = ({ navigation }) => {
385
+ return (
386
+ < View>
387
+ < Text > Profile Screen< / Text >
388
+ < Button
389
+ onPress= {() => navigation .navigate (' Settings' )}
390
+ title= " Navigate to Settings"
391
+ / >
392
+ < / View>
393
+ );
394
+ };
395
+
396
+ let renderCounter = 0 ;
397
+
398
+ const Settings = () => {
399
+ renderCounter++ ;
400
+ return (
401
+ < View>
402
+ < Text > Settings Screen< / Text >
403
+ < / View>
404
+ );
405
+ };
406
+
407
+ const Drawer = createDrawerNavigator ();
408
+
409
+ const DrawerNavigation = () => {
410
+ return (
411
+ < Drawer .Navigator >
412
+ < Drawer .Screen name= " Profile" component= {Profile} / >
413
+ < Drawer .Screen name= " Settings" component= {Settings} / >
414
+ < / Drawer .Navigator >
415
+ );
416
+ };
417
+
418
+ test (' navigates to settings without previous preload' , () => {
419
+ const navigation = createNavigationContainerRef ();
420
+ render (
421
+ < NavigationContainer ref= {navigation}>
422
+ < DrawerNavigation / >
423
+ < / NavigationContainer>
424
+ );
425
+
426
+ expect (screen .queryByText (' Profile Screen' )).toBeOnTheScreen ();
427
+ expect (screen .queryByText (' Settings Screen' )).not .toBeOnTheScreen ();
428
+ expect (renderCounter).toBe (0 );
429
+
430
+ fireEvent .press (screen .queryByText (' Navigate to Settings' ));
431
+
432
+ expect (screen .queryByText (' Profile Screen' )).not .toBeOnTheScreen ();
433
+ expect (screen .queryByText (' Settings Screen' )).toBeOnTheScreen ();
434
+ expect (renderCounter).toBe (1 );
435
+ });
436
+ ```
437
+
438
+ </TabItem >
439
+ </Tabs >
440
+
441
+ With preloading test example:
442
+ <Tabs groupId =" example " queryString =" example " >
443
+ <TabItem value =" static " label =" Static " default >
444
+
445
+ ``` js
446
+ import { expect , test } from ' @jest/globals' ;
447
+ import { createDrawerNavigator } from ' @react-navigation/drawer' ;
448
+ import {
449
+ createNavigationContainerRef ,
450
+ createStaticNavigation ,
451
+ useNavigation ,
452
+ } from ' @react-navigation/native' ;
453
+ import { act , fireEvent , render , screen } from ' @testing-library/react-native' ;
454
+ import { Button , Text , View } from ' react-native' ;
455
+
456
+ const Profile = () => {
457
+ const navigation = useNavigation ();
458
+ return (
459
+ < View>
460
+ < Text > Profile Screen< / Text >
461
+ < Button
462
+ onPress= {() => navigation .navigate (' Settings' )}
463
+ title= " Navigate to Settings"
464
+ / >
465
+ < / View>
466
+ );
467
+ };
468
+
469
+ let renderCounter = 0 ;
470
+
471
+ const Settings = () => {
472
+ renderCounter++ ;
473
+ return (
474
+ < View>
475
+ < Text > Settings Screen< / Text >
476
+ < / View>
477
+ );
478
+ };
479
+
480
+ const Drawer = createDrawerNavigator ({
481
+ screens: {
482
+ Profile,
483
+ Settings,
484
+ },
485
+ });
486
+
487
+ const DrawerNavigation = createStaticNavigation (Drawer);
488
+
489
+ test (' navigates to settings with previous preload' , () => {
490
+ const navigation = createNavigationContainerRef ();
491
+ render (< DrawerNavigation ref= {navigation} / > );
492
+
493
+ expect (renderCounter).toBe (0 );
494
+
495
+ act (() => navigation .preload (' Settings' ));
496
+
497
+ expect (screen .queryByText (' Profile Screen' )).toBeOnTheScreen ();
498
+ expect (screen .queryByText (' Settings Screen' )).not .toBeOnTheScreen ();
499
+ expect (renderCounter).toBe (1 );
500
+
501
+ fireEvent .press (screen .queryByText (' Navigate to Settings' ));
502
+
503
+ expect (screen .queryByText (' Profile Screen' )).not .toBeOnTheScreen ();
504
+ expect (screen .queryByText (' Settings Screen' )).toBeOnTheScreen ();
505
+ expect (renderCounter).toBe (1 );
506
+ });
507
+ ```
508
+
509
+ </TabItem >
510
+ <TabItem value =" dynamic " label =" Dynamic " >
511
+
512
+ ``` js
513
+ import { expect , test } from ' @jest/globals' ;
514
+ import { createDrawerNavigator } from ' @react-navigation/drawer' ;
515
+ import {
516
+ createNavigationContainerRef ,
517
+ NavigationContainer ,
518
+ } from ' @react-navigation/native' ;
519
+ import { act , fireEvent , render , screen } from ' @testing-library/react-native' ;
520
+ import { Button , Text , View } from ' react-native' ;
521
+
522
+ const Profile = ({ navigation }) => {
523
+ return (
524
+ < View>
525
+ < Text > Profile Screen< / Text >
526
+ < Button
527
+ onPress= {() => navigation .navigate (' Settings' )}
528
+ title= " Navigate to Settings"
529
+ / >
530
+ < / View>
531
+ );
532
+ };
533
+
534
+ let renderCounter = 0 ;
535
+
536
+ const Settings = () => {
537
+ renderCounter++ ;
538
+ return (
539
+ < View>
540
+ < Text > Settings Screen< / Text >
541
+ < / View>
542
+ );
543
+ };
544
+
545
+ const Drawer = createDrawerNavigator ();
546
+
547
+ const DrawerNavigation = () => {
548
+ return (
549
+ < Drawer .Navigator >
550
+ < Drawer .Screen name= " Profile" component= {Profile} / >
551
+ < Drawer .Screen name= " Settings" component= {Settings} / >
552
+ < / Drawer .Navigator >
553
+ );
554
+ };
555
+
556
+ test (' navigates to settings with previous preload' , () => {
557
+ const navigation = createNavigationContainerRef ();
558
+ render (
559
+ < NavigationContainer ref= {navigation}>
560
+ < DrawerNavigation / >
561
+ < / NavigationContainer>
562
+ );
563
+
564
+ expect (renderCounter).toBe (0 );
565
+
566
+ act (() => navigation .preload (' Settings' ));
567
+
568
+ expect (screen .queryByText (' Profile Screen' )).toBeOnTheScreen ();
569
+ expect (screen .queryByText (' Settings Screen' )).not .toBeOnTheScreen ();
570
+ expect (renderCounter).toBe (1 );
571
+
572
+ fireEvent .press (screen .queryByText (' Navigate to Settings' ));
573
+
574
+ expect (screen .queryByText (' Profile Screen' )).not .toBeOnTheScreen ();
575
+ expect (screen .queryByText (' Settings Screen' )).toBeOnTheScreen ();
576
+ expect (renderCounter).toBe (1 );
577
+ });
578
+ ```
579
+
580
+ </TabItem >
581
+ </Tabs >
582
+
302
583
For writing tests that include times functions you will need to use [ Fake Timers] ( https://jestjs.io/docs/timer-mocks ) . They will replace times function implementation to use time from the fake clock.
303
584
304
585
Let's add another button to the Profile screen, which uses ` setTimeout ` :
0 commit comments