Skip to content

Commit afb6d66

Browse files
authored
docs(react): writing tests with testing-library (#2861)
1 parent 49bdd97 commit afb6d66

File tree

7 files changed

+243
-9
lines changed

7 files changed

+243
-9
lines changed

docs/react/testing.md

-7
This file was deleted.

docs/react/testing/introduction.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
sidebar_label: Introduction
3+
title: Ionic React Testing Introduction
4+
description: Learn how to test an Ionic React application. This document provides an overview of how to test an application built with @ionic/react.
5+
---
6+
7+
# Testing Ionic React
8+
9+
This document provides an overview of how to test an application built with `@ionic/react`. It covers the basics of testing with React, as well as the specific tools and libraries developers can use to test their applications.
10+
11+
## Introduction
12+
13+
Testing is an important part of the development process, and it helps to ensure that an application is working as intended. In `@ionic/react`, testing is done using a combination of tools and libraries, including Jest, React Testing Library, Playwright or Cypress.
14+
15+
## Types of Tests
16+
17+
There are two types of tests that can be written:
18+
19+
**Unit Tests**: Unit tests are used to test individual functions and components in isolation. [Jest](https://jestjs.io) and [React Testing Library](https://testing-library.com) are commonly used for unit testing.
20+
21+
**Integration Tests**: Integration tests are used to test how different components work together. [Cypress](https://www.cypress.io) or [Playwright](https://playwright.dev) are commonly used for integration testing.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
sidebar_label: Best Practices
3+
---
4+
5+
# Best Practices
6+
7+
## IonApp is required for test templates
8+
9+
In your test template when rendering with React Testing Library, you must wrap your component with an `IonApp` component. This is required for the component to be rendered correctly.
10+
11+
```tsx title="Example.test.tsx"
12+
import { IonApp } from '@ionic/react';
13+
import { render } from "@testing-library/react";
14+
15+
import Example from './Example';
16+
17+
test('example', () => {
18+
render(
19+
<IonApp>
20+
<Example />
21+
</IonApp>
22+
);
23+
...
24+
});
25+
```
26+
27+
## Use `user-event` for user interactions
28+
29+
React Testing Library recommends using the `user-event` library for simulating user interactions. This library provides a more realistic simulation of user interactions than the `fireEvent` function provided by React Testing Library.
30+
31+
```tsx title="Example.test.tsx"
32+
import { IonApp } from '@ionic/react';
33+
import { render } from '@testing-library/react';
34+
import userEvent from '@testing-library/user-event';
35+
36+
import Example from './Example';
37+
38+
test('example', async () => {
39+
const user = userEvent.setup();
40+
41+
render(
42+
<IonApp>
43+
<Example />
44+
</IonApp>
45+
);
46+
47+
await user.click(screen.getByRole('button', { name: /click me!/i }));
48+
});
49+
```
50+
51+
For more information on `user-event`, see the [user-event documentation](https://testing-library.com/docs/user-event/intro/).
+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
---
2+
sidebar_label: Examples
3+
title: Ionic React Testing Examples
4+
description: Learn how to test an Ionic React application. This document provides examples of how to test different types of components.
5+
---
6+
7+
# Examples
8+
9+
## Testing a modal presented from a trigger
10+
11+
This example shows how to test a modal that is presented from a trigger. The modal is presented when the user clicks a button.
12+
13+
### Example component
14+
15+
```tsx title="src/Example.tsx"
16+
import { IonButton, IonModal } from '@ionic/react';
17+
18+
export default function Example() {
19+
return (
20+
<>
21+
<IonButton id="open-modal">Open</IonButton>
22+
<IonModal trigger="open-modal">Modal content</IonModal>
23+
</>
24+
);
25+
}
26+
```
27+
28+
### Testing the modal
29+
30+
```tsx title="src/Example.test.tsx"
31+
import { IonApp } from '@ionic/react';
32+
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
33+
34+
import Example from './Example';
35+
36+
test('button presents a modal when clicked', async () => {
37+
render(
38+
<IonApp>
39+
<Example />
40+
</IonApp>
41+
);
42+
// Simulate a click on the button
43+
fireEvent.click(screen.getByText('Open'));
44+
// Wait for the modal to be presented
45+
await waitFor(() => {
46+
// Assert that the modal is present
47+
expect(screen.getByText('Modal content')).toBeInTheDocument();
48+
});
49+
});
50+
```
51+
52+
## Testing a modal presented from useIonModal
53+
54+
This example shows how to test a modal that is presented using the `useIonModal` hook. The modal is presented when the user clicks a button.
55+
56+
### Example component
57+
58+
```tsx title="src/Example.tsx"
59+
import { IonContent, useIonModal, IonHeader, IonToolbar, IonTitle, IonButton, IonPage } from '@ionic/react';
60+
61+
const ModalContent: React.FC = () => {
62+
return (
63+
<IonContent>
64+
<div>Modal Content</div>
65+
</IonContent>
66+
);
67+
};
68+
69+
const Example: React.FC = () => {
70+
const [present] = useIonModal(ModalContent);
71+
return (
72+
<IonPage>
73+
<IonHeader>
74+
<IonToolbar>
75+
<IonTitle>Blank</IonTitle>
76+
</IonToolbar>
77+
</IonHeader>
78+
<IonContent fullscreen={true}>
79+
<IonButton expand="block" className="ion-margin" onClick={() => present()}>
80+
Open
81+
</IonButton>
82+
</IonContent>
83+
</IonPage>
84+
);
85+
};
86+
87+
export default Example;
88+
```
89+
90+
### Testing the modal
91+
92+
```tsx title="src/Example.test.tsx"
93+
import { IonApp } from '@ionic/react';
94+
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
95+
96+
import Example from './Example';
97+
98+
test('should present ModalContent when button is clicked', async () => {
99+
render(
100+
<IonApp>
101+
<Example />
102+
</IonApp>
103+
);
104+
// Simulate a click on the button
105+
fireEvent.click(screen.getByText('Open'));
106+
// Wait for the modal to be presented
107+
await waitFor(() => {
108+
// Assert that the modal is present
109+
expect(screen.getByText('Modal Content')).toBeInTheDocument();
110+
});
111+
});
112+
```
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
sidebar_label: Setup
3+
title: Ionic React Unit Testing Setup
4+
description: Learn how to set up unit tests for an Ionic React application.
5+
---
6+
7+
# Unit Testing Setup
8+
9+
Ionic requires a few additional steps to set up unit tests. If you are using an Ionic starter project, these steps have already been completed for you.
10+
11+
### Install React Testing Library
12+
13+
React Testing Library is a set of utilities that make it easier to test React components. It's used to interact with components and test their behavior.
14+
15+
```bash
16+
npm install --save-dev @testing-library/react @testing-library/jest-dom @testing-library/user-event
17+
```
18+
19+
### Initialize Ionic React
20+
21+
Ionic React requires the `setupIonicReact` function to be called before any tests are run. Failing to do so will result in mode-based classes and platform behaviors not being applied to your components.
22+
23+
In `src/setupTest.ts`, add the following code:
24+
25+
```diff
26+
import '@testing-library/jest-dom/extend-expect';
27+
28+
+ import { setupIonicReact } from '@ionic/react';
29+
30+
+ setupIonicReact();
31+
32+
// Mock matchmedia
33+
window.matchMedia = window.matchMedia || function () {
34+
return {
35+
matches: false,
36+
addListener: function () { },
37+
removeListener: function () { }
38+
};
39+
};
40+
```

sidebars.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,23 @@ module.exports = {
122122
'react/pwa',
123123
'react/overlays',
124124
'react/storage',
125-
'react/testing',
125+
{
126+
type: 'category',
127+
label: 'Testing',
128+
items: [
129+
'react/testing/introduction',
130+
{
131+
type: 'category',
132+
label: 'Unit Testing',
133+
collapsed: false,
134+
items: [
135+
'react/testing/unit-testing/setup',
136+
'react/testing/unit-testing/examples',
137+
'react/testing/unit-testing/best-practices',
138+
],
139+
},
140+
],
141+
},
126142
'react/performance',
127143
],
128144
},

vercel.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@
6363
"source": "/docs/vue/your-first-app/6-deploying-mobile",
6464
"destination": "/docs/vue/your-first-app/deploying-mobile"
6565
},
66-
{ "source": "/docs/vue/your-first-app/7-live-reload", "destination": "/docs/vue/your-first-app/live-reload" }
66+
{ "source": "/docs/vue/your-first-app/7-live-reload", "destination": "/docs/vue/your-first-app/live-reload" },
67+
{ "source": "/docs/react/testing", "destination": "/docs/react/testing/introduction" }
6768
],
6869
"rewrites": [
6970
{ "source": "/docs", "destination": "/" },

0 commit comments

Comments
 (0)