Skip to content

Commit e2f0a64

Browse files
committed
change descriptions of examples
1 parent 2184041 commit e2f0a64

File tree

1 file changed

+46
-47
lines changed

1 file changed

+46
-47
lines changed

versioned_docs/version-7.x/testing.md

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -215,14 +215,28 @@ test('navigates to settings by tab bar button press', async () => {
215215
</TabItem>
216216
</Tabs>
217217

218-
We get the settings tab bar button using a `testID` assigned to it, press it using `fireEvent` and check if rendered content is correct.
218+
First, we need to create a User Event object instance from `react-native-testing-library` in order to be able to trigger user events.
219219

220-
Tab bar buttons `handlePress` function expects to receive `GestureResponderEvent`. To avoid error you should pass `event` object as the second argument of `fireEvent`.
220+
```js
221+
// Create User Event object instance
222+
const user = userEvent.setup();
223+
```
224+
225+
After we create and render our tabs, we get the settings tab bar button using an accessibility label assigned to it and press it using `user.press(button)`.
226+
227+
```js
228+
// Get the setting tab bar button
229+
const button = screen.getByRole('button', { name: 'Settings, tab, 2 of 2' });
230+
231+
// Simulate user pressing the button
232+
await user.press(button);
233+
```
234+
235+
We expect that after pressing the button, the screen will change and `'Settings screen'` will be visible.
221236

222237
```js
223-
// Pass event object to avoid error
224-
const event = {};
225-
fireEvent.press(button, event);
238+
// Assert that Settings screen is visible
239+
expect(screen.getByText('Settings screen')).toBeVisible();
226240
```
227241

228242
### Example 2 - Reacting to navigation events
@@ -358,7 +372,7 @@ import { expect, jest, test } from '@jest/globals';
358372
import { NavigationContainer } from '@react-navigation/native';
359373
import { act, render, screen, userEvent } from '@testing-library/react-native';
360374

361-
// import { MyStack } from './MyStack';
375+
import { MyStack } from './MyStack';
362376

363377
jest.useFakeTimers();
364378

@@ -382,9 +396,9 @@ test('surprise text appears after transition to surprise screen is complete', as
382396
</TabItem>
383397
</Tabs>
384398

385-
We press the "Click here!" button using `fireEvent` and check that the text does not appear right away but only after the transition between screens ends.
399+
We press the "Click here!" button using `user.press()` and check that the text does not appear right away but only after the transition between screens ends.
386400

387-
While writing tests containing navigation with animations (in this example we have a `StackNavigator`, which uses an animation for the transition based on the platform and OS version) you need to wait until animations finish before proceeding further. To do so, you have to use `fake timers`. [`Fake Timers`](https://jestjs.io/docs/timer-mocks) replace real implementation of times function to use fake clock. They allow you to instantly skip animation time. To avoid getting state change error, wrap `runAllTimers` in `act`.
401+
<!-- When writing tests containing navigation with animations (in this example we have a `StackNavigator`, which uses an animation for the transition based on the platform and OS version) you need to wait until animations finish before proceeding further. To do so, you have to use `fake timers`. [`Fake Timers`](https://jestjs.io/docs/timer-mocks) replace real implementation of times function to use fake clock. They allow you to instantly skip animation time. To avoid getting state change error, wrap `runAllTimers` in `act`.
388402
389403
```js
390404
// Enable fake timers
@@ -399,7 +413,7 @@ act(() => jest.runAllTimers());
399413
400414
If we hadn't used fake timers in this example, the test would have failed.
401415
402-
In the previous example we didn't use fake timers because `BottomTabNavigator` by default does not use any transition animations.
416+
In the previous example we didn't use fake timers because `BottomTabNavigator` by default does not use any transition animations. -->
403417

404418
### Example 3 - Enforce navigator state in response to navigation event
405419

@@ -632,13 +646,13 @@ test('displays settings screen after settings tab bar button press', async () =>
632646
</TabItem>
633647
</Tabs>
634648

635-
We get tab bar buttons, press buttons and check if rendered screens are correct.
649+
We get tab bar buttons, press them and check if rendered screens are correct.
636650

637-
In this example, we don't need to use fake timers because text from the next screen is available using `getByText` even before the animation ends.
651+
<!-- In this example, we don't need to use fake timers because text from the next screen is available using `getByText` even before the animation ends. -->
638652

639653
### Example 4 - `useFocusEffect` hook and data fetching
640654

641-
On every profile screen focus, display loading state while waiting for data and then show fetched profile.
655+
On profile screen focus, display loading state while waiting for data and then show fetched profile on every refocus.
642656

643657
<Tabs groupId="example" queryString="example">
644658
<TabItem value="static" label="Static" default>
@@ -816,6 +830,25 @@ export function MyTabs() {
816830
</TabItem>
817831
</Tabs>
818832

833+
To make the test deterministic and isolate it from the real backend, you can mock the `fetch` function. For this purpose you can use [Mock Service Worker](https://mswjs.io/). Please refer to the documentation of the library to learn more about setting it up in your project ([Getting started](https://mswjs.io/docs/getting-started), [React Native integration](https://mswjs.io/docs/integrations/react-native)).
834+
835+
```js
836+
import { delay, http, HttpResponse } from 'msw';
837+
838+
export const handlers = [
839+
http.get('https://pokeapi.co/api/v2/pokemon/ditto', async () => {
840+
await delay(1000);
841+
842+
return HttpResponse.json({
843+
id: 132,
844+
name: 'ditto',
845+
});
846+
}),
847+
];
848+
```
849+
850+
Before writing the test, we setup a handler that mocks responses from the API (for this example we're using [PokéAPI](https://pokeapi.co/)). Additionally, we `delay` the response by 1000 ms.
851+
819852
<Tabs groupId="example" queryString="example">
820853
<TabItem value="static" label="Static" default>
821854

@@ -908,41 +941,7 @@ test('on profile screen focus, displays loading state while waiting for data and
908941
</TabItem>
909942
</Tabs>
910943

911-
We query tab buttons and mock fetch function using `spyOn` and `mockImplementation`. We navigate to profile screen and check if loading state is rendered correctly. Then, to check if fetched data is displayed, we use `findByText` - we need to wait for the fetch to finish before checking its result. To ensure that operation will succeed not only on the first focus, we navigate back to home, then to settings and check loading state and fetched data again.
912-
913-
To make test deterministic and isolate it from the real backend you can mock fetch function. You can use `spyOn` to override real implementation of fetch with `mockedFetch`.
914-
915-
```js
916-
// Mock implementation of fetch function
917-
async function mockedFetch() {
918-
const mockResponse = {
919-
profile: {
920-
nick: 'CookieDough',
921-
},
922-
};
923-
return {
924-
ok: true,
925-
status: 200,
926-
json: async () => {
927-
return mockResponse;
928-
},
929-
};
930-
}
931-
932-
test('on every profile screen focus, displays loading state while waiting for data and then shows fetched profile', async () => {
933-
// ...
934-
935-
// Replace fetch implementation with mock
936-
const spy = jest.spyOn(window, 'fetch').mockImplementation(mockedFetch);
937-
938-
// ...
939-
940-
// Check if mock fetch was called
941-
expect(spy).toHaveBeenCalled();
942-
943-
// ...
944-
});
945-
```
944+
We navigate to profile screen and check if loading state is rendered correctly. Then we use fake timers to skip the delay and check if fetched data is displayed on the screen. To ensure expected behavior not only on the first focus, we navigate back to home, then to settings and check that the data is present without unnecessary fetch.
946945

947946
## Best practices
948947

0 commit comments

Comments
 (0)