xref: /expo/docs/pages/router/reference/testing.mdx (revision a16ac082)
1---
2title: Testing
3description: Learn how to create integration tests for your app when using Expo Router.
4---
5
6import { APIBox } from '~/components/plugins/APIBox';
7
8Expo Router relies on your file system, which can present challenges when setting up mocks for integration tests. Expo Router's submodule, `expo-router/testing-library`, is a set of testing utilities built on top of the popular [`@testing-library/react-native`](https://callstack.github.io/react-native-testing-library/) and allows you to quickly create in-memory Expo Router apps that are pre-configured for testing.
9
10## Configuration
11
12Before you proceed, ensure you've set up `jest-expo` according to the [Unit Testing](/develop/unit-testing/) and [`@testing-library/react-native`](https://callstack.github.io/react-native-testing-library/docs/getting-started).
13
14## `renderRouter`
15
16`renderRouter` extends the functionality of [`render`](https://callstack.github.io/react-native-testing-library/docs/api#render) to simplify testing with Expo Router. It returns the same query object as [`render`](https://callstack.github.io/react-native-testing-library/docs/api#render), and is compatible with [`screen`](https://callstack.github.io/react-native-testing-library/docs/api#screen), allowing you to use the standard [query API](https://callstack.github.io/react-native-testing-library/docs/api-queries) to locate components.
17
18`renderRouter` accepts the same [options](https://callstack.github.io/react-native-testing-library/docs/api#render-options) as `render` and introduces an additional option `initialRoute`, which sets an initial route for simulating deep-linking.
19
20<APIBox header="Inline file system">
21
22`renderRouter(mock: Record<string, ReactComponent>, options: RenderOptions)`
23
24`renderRouter` can provide inline-mocking of a file system by passing an object to this function as the first parameter. The keys of the object are the mock filesystem paths. **Do not use leading relative (`./`) or absolute (`/`) notation when defining these paths and exclude file extension.**
25
26```tsx app.test.tsx
27import { renderRouter, screen } from 'expo-router/testing-library';
28
29it('my-test', async () => {
30  const MockComponent = jest.fn(() => <View />);
31
32  renderRouter(
33    {
34      index: MockComponent,
35      'folder/a': MockComponent,
36      '(group)/b': MockComponent,
37    },
38    {
39      initialRoute: '/folder/a',
40    }
41  );
42
43  expect(screen).toHavePathname('/folder/a');
44});
45```
46
47</APIBox>
48
49<APIBox header="Path to fixture">
50
51`renderRouter(fixturePath: string, options: RenderOptions)`
52
53`renderRouter` can accept a directory path to mock an existing fixture. Ensure that the provided path is relative to the current test file.
54
55```tsx app.test.js
56it('my-test', async () => {
57  const MockComponent = jest.fn(() => <View />);
58  renderRouter('./my-test-fixture');
59});
60```
61
62</APIBox>
63
64<APIBox header="Path to the fixture with overrides">
65
66`renderRouter({ appDir: string, overrides: Record<string, ReactComponent>}, options: RenderOptions)`
67
68For more intricate testing scenarios, `renderRouter` can leverage both directory path and inline-mocking methods simultaneously. The `appDir` parameter takes a string representing a pathname to a folder. The overrides parameter is an inline mock that can be used to override specific paths within the `appDir`. This combination allows for fine-tuned control over the mock environment.
69
70```tsx app.test.js
71it('my-test', async () => {
72  const MockAuthLayout = jest.fn(() => <View />);
73  renderRouter({
74    appDir: './my-test-fixture',
75    overrides: {
76      'folder/(auth)/_layout': MockAuthLayout,
77    },
78  });
79});
80```
81
82</APIBox>
83
84## Jest matchers
85
86The following matches have been added to `expect` and can be used to asset values on `screen`.
87
88<APIBox header="toHavePathname()">
89
90Assert the current pathname against a given string. The matcher uses the value of the [`usePathname`](/router/reference/hooks/#usepathname) hook on the current `screen`.
91
92```tsx app.test.ts
93expect(screen).toHavePathname('/my-router');
94```
95
96</APIBox>
97<APIBox header="toHaveSegments()">
98
99Assert the current segments against an array of strings. The matcher uses the value of the [`useSegments`](/router/reference/hooks/#usesegments) hook on the current `screen`.
100
101```tsx app.test.ts
102expect(screen).toHaveSegments(['[id]']);
103```
104
105</APIBox>
106<APIBox header="useLocalSearchParams">
107
108Assert the current local search parameters against an object. The matcher uses the value of the [`useLocalSearchParams`](/router/reference/hooks/#uselocalsearchparams) hook on the current `screen`.
109
110```tsx app.test.ts
111expect(screen).useLocalSearchParams({ first: 'abc' });
112```
113
114</APIBox>
115<APIBox header="useGlobalSearchParams">
116
117Assert the current screen's pathname that matches a value. Compares using the value of [`useGlobalSearchParams`](/router/reference/hooks/#useglobalsearchparams) hook.
118
119Assert the current global search parameters against an object. The matcher uses the value of the [`useGlobalSearchParams`](/router/reference/hooks/#useglobalsearchparams) hook on the current `screen`.
120
121```tsx app.test.ts
122expect(screen).useGlobalSearchParams({ first: 'abc' });
123```
124
125</APIBox>
126