@@ -79,7 +79,9 @@ If you're not using Jest, then you'll need to mock these modules according to th
7979
8080We 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.
8181
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:
8385
8486<Tabs groupId =" example " queryString =" example " >
8587<TabItem value =" static " label =" Static " default >
@@ -299,6 +301,285 @@ test('pushes settings screen twice', () => {
299301</TabItem >
300302</Tabs >
301303
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+
302583For 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.
303584
304585Let's add another button to the Profile screen, which uses ` setTimeout ` :
0 commit comments