From d99ad24d2bbb69c025655e5fdfc7954a7d6b21e5 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Tue, 28 Mar 2023 17:24:54 -0400 Subject: [PATCH 01/24] docs(react): writing tests with testing-library --- docs/react/testing.md | 7 ----- docs/react/testing/examples.md | 45 +++++++++++++++++++++++++++ docs/react/testing/introduction.md | 37 ++++++++++++++++++++++ docs/react/testing/setup.md | 49 ++++++++++++++++++++++++++++++ sidebars.js | 10 +++++- 5 files changed, 140 insertions(+), 8 deletions(-) delete mode 100644 docs/react/testing.md create mode 100644 docs/react/testing/examples.md create mode 100644 docs/react/testing/introduction.md create mode 100644 docs/react/testing/setup.md diff --git a/docs/react/testing.md b/docs/react/testing.md deleted file mode 100644 index dd1f2d7d308..00000000000 --- a/docs/react/testing.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -sidebar_label: Testing ---- - -# Testing Ionic React - -When an `@ionic/react` application is generated using the Ionic CLI, it is automatically set up for unit testing and integration testing with [Jest](https://jestjs.io/) and [React Testing Library](https://testing-library.com/docs/react-testing-library/intro). The combo provides a great way to test your React components in isolation as well integrated together. For more information on how to get started testing an Ionic React app, see our article [Testing Ionic React Apps with Jest and React Testing Library](https://ionicframework.com/blog/testing-ionic-react-apps-with-jest-and-react-testing-library/). diff --git a/docs/react/testing/examples.md b/docs/react/testing/examples.md new file mode 100644 index 00000000000..5354a14042c --- /dev/null +++ b/docs/react/testing/examples.md @@ -0,0 +1,45 @@ +--- +sidebar_label: Examples +title: Ionic React Testing Examples +description: Learn how to test an Ionic React application. This document provides examples of how to test different types of components. +--- + +# Examples + +## Testing a modal presented from a trigger + +This example shows how to test a modal that is presented from a trigger. The modal is presented when the user clicks a button. + +### Example component + +```tsx title="src/Example.tsx" +import { IonButton, IonModal } from '@ionic/react'; + +export default function Example() { + return ( + <> + Open + Modal content + + ); +} +``` + +### Testing the modal + +```tsx title="src/Example.test.tsx" +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; + +import Example from './Example'; + +test('button presents a modal when clicked', async () => { + render(); + // Simulate a click on the button + fireEvent.click(screen.getByText('Open')); + // Wait for the modal to be presented + await waitFor(() => { + // Assert that the modal is present + expect(screen.getByText('Modal content')).toBeInTheDocument(); + }); +}); +``` diff --git a/docs/react/testing/introduction.md b/docs/react/testing/introduction.md new file mode 100644 index 00000000000..b9182ef10c5 --- /dev/null +++ b/docs/react/testing/introduction.md @@ -0,0 +1,37 @@ +--- +sidebar_label: Introduction +title: Ionic React Testing Introduction +description: Learn how to test an Ionic React application. This document provides an overview of how to test an application built with @ionic/react. +--- + +# Testing Ionic React + +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 used in `@ionic/react`. + +## Introduction + +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, and Cypress. + +## Tools and Libraries + +**Jest**: Jest is a popular testing framework for JavaScript applications. It's used to run unit tests and integration tests. + +**React Testing Library**: 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. + +**Cypress**: Cypress is a modern testing tool that's used to run end-to-end tests. It allows developers to test the entire application, including the user interface, in a simulated environment. + +## Types of Tests + +There are two types of tests that can be written: + +**Unit Tests**: Unit tests are used to test individual functions and components in isolation. They are typically written using Jest and React Testing Library. + +**Integration Tests**: Integration tests are used to test how different components work together. They are typically written using Cypress. + +## Conclusion + +Testing is an important part of the development process, and React provides a robust set of tools and libraries for testing applications. By writing and running tests, you can ensure that your application is working as intended and catch bugs before they reach production. + +### Additional Resources + +- [Testing Ionic React Apps with Jest and React Testing Library](https://ionicframework.com/blog/testing-ionic-react-apps-with-jest-and-react-testing-library/) diff --git a/docs/react/testing/setup.md b/docs/react/testing/setup.md new file mode 100644 index 00000000000..be505ab8d37 --- /dev/null +++ b/docs/react/testing/setup.md @@ -0,0 +1,49 @@ +--- +sidebar_label: Setup +title: Ionic React Unit Testing Setup +description: Learn how to set up unit tests for an Ionic React application. +--- + +# Setup + +Ionic requires a few additional steps to set up unit tests. + +## Install Jest + +### React Scripts + +If your React project is using `react-scripts`, jest is already installed. You can confirm the version of Jest by running: + +```bash +npm ls jest +``` + +Ionic recommends `react-scripts@5` and requires a minimum version of `jest@27`, which includes `jsdom@16`. If you are using an older version of `react-scripts`, you can update it by running: + +```bash +npm install react-scripts@latest +``` + +## Initialize Ionic React + +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. + +In `src/setupTest.ts`, add the following code: + +```tsx title="src/setupTest.ts" +import { setupIonicReact } from '@ionic/react'; + +setupIonicReact(); +``` + +## Test Environment + +Ionic requires a DOM environment to be available in order to render components. This is typically provided by the `jsdom` test environment. In Jest 27 and later, the default environment is `node`. + +### React Scripts + +To configure this behavior, update your `test` command to include `--env=jsdom`: + +```json title="package.json" +"test": "react-scripts test --env=jsdom --transformIgnorePatterns 'node_modules/(?!(@ionic/react|@ionic/react-router|@ionic/core|@stencil/core|ionicons)/)'", +``` diff --git a/sidebars.js b/sidebars.js index c08a43ada8f..9c8187548ae 100644 --- a/sidebars.js +++ b/sidebars.js @@ -120,7 +120,15 @@ module.exports = { 'react/pwa', 'react/overlays', 'react/storage', - 'react/testing', + { + type: 'category', + label: 'Testing', + items: [ + 'react/testing/introduction', + 'react/testing/setup', + 'react/testing/examples' + ], + }, 'react/performance', ], }, From 5ab70e6f60ca8c8ea1cd6f7a8fee5c09710f582d Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Tue, 28 Mar 2023 22:07:21 -0400 Subject: [PATCH 02/24] docs: installing react testing library --- docs/react/testing/setup.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/react/testing/setup.md b/docs/react/testing/setup.md index be505ab8d37..99c544f3509 100644 --- a/docs/react/testing/setup.md +++ b/docs/react/testing/setup.md @@ -24,6 +24,14 @@ Ionic recommends `react-scripts@5` and requires a minimum version of `jest@27`, npm install react-scripts@latest ``` +## Install React Testing Library + +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. + +```bash +npm install --save-dev @testing-library/react @testing-library/jest-dom @testing-library/user-event +``` + ## Initialize Ionic React 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. From a000173650e77a314297da4e5f6cc807469ffbe2 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Tue, 28 Mar 2023 22:43:44 -0400 Subject: [PATCH 03/24] docs: testing a modal presented from useIonModal --- docs/react/testing/examples.md | 69 ++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/docs/react/testing/examples.md b/docs/react/testing/examples.md index 5354a14042c..30798081b2b 100644 --- a/docs/react/testing/examples.md +++ b/docs/react/testing/examples.md @@ -43,3 +43,72 @@ test('button presents a modal when clicked', async () => { }); }); ``` + +## Testing a modal presented from useIonModal + +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. + +### Example component + +```tsx title="src/Example.tsx" +import { IonContent, useIonModal, IonHeader, IonToolbar, IonTitle, IonButton, IonPage } from '@ionic/react'; + +export const ModalContent: React.FC = () => { + return ( + +
Modal Content
+
+ ); +}; + +const Example: React.FC = () => { + const [present] = useIonModal(ModalContent); + return ( + + + + Blank + + + + present()}> + Open + + + + ); +}; + +export default Example; +``` + +### Testing the modal + +```tsx title="src/Example.test.tsx" +import { fireEvent, render, screen } from '@testing-library/react'; + +import Example, { ModalContent } from './Example'; + +const mockPresent = jest.fn(); +const mockUseIonModal = jest.fn(); + +jest.mock('@ionic/react', () => { + const rest = jest.requireActual('@ionic/react'); + return { + ...rest, + useIonModal: (component: any) => { + mockUseIonModal(component); + return [mockPresent]; + }, + }; +}); + +test('should present ModalContent when button is clicked', async () => { + render(); + + fireEvent.click(screen.getByText('Open')); + + expect(mockUseIonModal).toHaveBeenCalledWith(ModalContent); + expect(mockPresent).toHaveBeenCalled(); +}); +``` From d4263933a66120ed89b3c99754b886cb4cb2a029 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Tue, 28 Mar 2023 22:49:50 -0400 Subject: [PATCH 04/24] docs: remove unneeded async --- docs/react/testing/examples.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/react/testing/examples.md b/docs/react/testing/examples.md index 30798081b2b..1e56e337998 100644 --- a/docs/react/testing/examples.md +++ b/docs/react/testing/examples.md @@ -103,7 +103,7 @@ jest.mock('@ionic/react', () => { }; }); -test('should present ModalContent when button is clicked', async () => { +test('should present ModalContent when button is clicked', () => { render(); fireEvent.click(screen.getByText('Open')); From e2b1891bf39e6d56f0bef660ea2e3278e4e54f92 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Wed, 29 Mar 2023 13:23:35 -0400 Subject: [PATCH 05/24] docs: rework intro sections --- docs/react/testing/introduction.md | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/docs/react/testing/introduction.md b/docs/react/testing/introduction.md index b9182ef10c5..c752ca59093 100644 --- a/docs/react/testing/introduction.md +++ b/docs/react/testing/introduction.md @@ -10,23 +10,31 @@ This document provides an overview of how to test an application built with `@io ## Introduction -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, and Cypress. +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 Vitest, Jest, React Testing Library, Playwright or Cypress. + +## Types of Tests + +There are two types of tests that can be written: + +**Unit Tests**: Unit tests are used to test individual functions and components in isolation. They are typically written using [Jest](https://jestjs.io) and [React Testing Library](https://testing-library.com) or [Vitest](https://vitest.dev). + +**Integration Tests**: Integration tests are used to test how different components work together. They are typically written using [Cypress](https://www.cypress.io) or [Playwright](https://playwright.dev). ## Tools and Libraries -**Jest**: Jest is a popular testing framework for JavaScript applications. It's used to run unit tests and integration tests. +### Unit Testing -**React Testing Library**: 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. +[**Jest**](https://jestjs.io): Jest is a popular testing framework for JavaScript applications. It is included with `react-scripts` and is used to run unit tests. -**Cypress**: Cypress is a modern testing tool that's used to run end-to-end tests. It allows developers to test the entire application, including the user interface, in a simulated environment. +[**Vitest**](https://vitest.dev): Vitest is a modern testing framework powered by Vite. It is compatible with Jest and is used to run unit tests. -## Types of Tests +[**React Testing Library**](https://testing-library.com): 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. -There are two types of tests that can be written: +### Integration Testing -**Unit Tests**: Unit tests are used to test individual functions and components in isolation. They are typically written using Jest and React Testing Library. +[**Cypress**](https://www.cypress.io): Cypress is a modern testing tool that's used to run end-to-end tests. It allows developers to test the entire application, including the user interface, in a simulated environment. -**Integration Tests**: Integration tests are used to test how different components work together. They are typically written using Cypress. +[**Playwright**](https://playwright.dev): Playwright is a browser automation library that's used to run end-to-end tests. It allows developers to test the entire application, including the user interface, in a simulated environment. ## Conclusion From 7f2fd80a33ad918800695900fce7e781178b2247 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Fri, 31 Mar 2023 15:11:14 -0400 Subject: [PATCH 06/24] chore: restructure sections --- docs/react/testing/introduction.md | 6 +----- docs/react/testing/{ => unit-testing}/examples.md | 0 docs/react/testing/{ => unit-testing}/setup.md | 14 +++++--------- sidebars.js | 10 +++++++--- 4 files changed, 13 insertions(+), 17 deletions(-) rename docs/react/testing/{ => unit-testing}/examples.md (100%) rename docs/react/testing/{ => unit-testing}/setup.md (92%) diff --git a/docs/react/testing/introduction.md b/docs/react/testing/introduction.md index c752ca59093..05ba658d6b3 100644 --- a/docs/react/testing/introduction.md +++ b/docs/react/testing/introduction.md @@ -36,10 +36,6 @@ There are two types of tests that can be written: [**Playwright**](https://playwright.dev): Playwright is a browser automation library that's used to run end-to-end tests. It allows developers to test the entire application, including the user interface, in a simulated environment. -## Conclusion - -Testing is an important part of the development process, and React provides a robust set of tools and libraries for testing applications. By writing and running tests, you can ensure that your application is working as intended and catch bugs before they reach production. - -### Additional Resources +## Additional Resources - [Testing Ionic React Apps with Jest and React Testing Library](https://ionicframework.com/blog/testing-ionic-react-apps-with-jest-and-react-testing-library/) diff --git a/docs/react/testing/examples.md b/docs/react/testing/unit-testing/examples.md similarity index 100% rename from docs/react/testing/examples.md rename to docs/react/testing/unit-testing/examples.md diff --git a/docs/react/testing/setup.md b/docs/react/testing/unit-testing/setup.md similarity index 92% rename from docs/react/testing/setup.md rename to docs/react/testing/unit-testing/setup.md index 99c544f3509..a38d73af6ce 100644 --- a/docs/react/testing/setup.md +++ b/docs/react/testing/unit-testing/setup.md @@ -4,13 +4,11 @@ title: Ionic React Unit Testing Setup description: Learn how to set up unit tests for an Ionic React application. --- -# Setup +# Unit Testing Setup Ionic requires a few additional steps to set up unit tests. -## Install Jest - -### React Scripts +## Jest If your React project is using `react-scripts`, jest is already installed. You can confirm the version of Jest by running: @@ -24,7 +22,7 @@ Ionic recommends `react-scripts@5` and requires a minimum version of `jest@27`, npm install react-scripts@latest ``` -## Install React Testing Library +### Install React Testing Library 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. @@ -32,7 +30,7 @@ React Testing Library is a set of utilities that make it easier to test React co npm install --save-dev @testing-library/react @testing-library/jest-dom @testing-library/user-event ``` -## Initialize Ionic React +### Initialize Ionic React 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. @@ -44,12 +42,10 @@ import { setupIonicReact } from '@ionic/react'; setupIonicReact(); ``` -## Test Environment +### Test Environment Ionic requires a DOM environment to be available in order to render components. This is typically provided by the `jsdom` test environment. In Jest 27 and later, the default environment is `node`. -### React Scripts - To configure this behavior, update your `test` command to include `--env=jsdom`: ```json title="package.json" diff --git a/sidebars.js b/sidebars.js index 9c8187548ae..b6a1a526a39 100644 --- a/sidebars.js +++ b/sidebars.js @@ -124,9 +124,13 @@ module.exports = { type: 'category', label: 'Testing', items: [ - 'react/testing/introduction', - 'react/testing/setup', - 'react/testing/examples' + 'react/testing/introduction', + { + type: 'category', + label: 'Unit Testing', + collapsed: false, + items: ['react/testing/unit-testing/setup', 'react/testing/unit-testing/examples'], + }, ], }, 'react/performance', From 26d97a84f6d9169746ccb1f539e7f56b6479ee87 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Wed, 5 Apr 2023 14:17:39 -0400 Subject: [PATCH 07/24] chore: doc updates --- .../testing/unit-testing/best-practices.md | 46 ++++++++++++++++ docs/react/testing/unit-testing/examples.md | 52 ++++++++++--------- docs/react/testing/unit-testing/setup.md | 28 ++++++++++ sidebars.js | 2 +- 4 files changed, 103 insertions(+), 25 deletions(-) create mode 100644 docs/react/testing/unit-testing/best-practices.md diff --git a/docs/react/testing/unit-testing/best-practices.md b/docs/react/testing/unit-testing/best-practices.md new file mode 100644 index 00000000000..00869f99e75 --- /dev/null +++ b/docs/react/testing/unit-testing/best-practices.md @@ -0,0 +1,46 @@ +--- +sidebar_label: Best Practices +--- + +# Best Practices + +## IonApp is required for test templates + +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. + +```tsx title="Example.test.tsx" +import { IonApp } from '@ionic/react'; +import { render } from "@testing-library/react"; + +test('example', () => { + render( + + + + ); + ... +}); +``` + +## Use `user-event` for user interactions + +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. + +```tsx title="Example.test.tsx" +import { render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +test('example', async () => { + const user = userEvent.setup(); + + render( + + + + ); + + await user.click(screen.getByRole('button', { name: /click me!/i })); +}); +``` + +For more information on `user-event`, see the [user-event documentation](https://testing-library.com/docs/user-event/intro/). diff --git a/docs/react/testing/unit-testing/examples.md b/docs/react/testing/unit-testing/examples.md index 1e56e337998..ee300b9f202 100644 --- a/docs/react/testing/unit-testing/examples.md +++ b/docs/react/testing/unit-testing/examples.md @@ -29,11 +29,16 @@ export default function Example() { ```tsx title="src/Example.test.tsx" import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { IonApp } from '@ionic/react'; import Example from './Example'; test('button presents a modal when clicked', async () => { - render(); + render( + + + + ); // Simulate a click on the button fireEvent.click(screen.getByText('Open')); // Wait for the modal to be presented @@ -48,12 +53,18 @@ test('button presents a modal when clicked', async () => { 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. +:::warning + +You must mock `requestAnimationFrame` as described in the [setup section](./setup.md#mock-requestanimationframe). + +::: + ### Example component ```tsx title="src/Example.tsx" import { IonContent, useIonModal, IonHeader, IonToolbar, IonTitle, IonButton, IonPage } from '@ionic/react'; -export const ModalContent: React.FC = () => { +const ModalContent: React.FC = () => { return (
Modal Content
@@ -85,30 +96,23 @@ export default Example; ### Testing the modal ```tsx title="src/Example.test.tsx" -import { fireEvent, render, screen } from '@testing-library/react'; - -import Example, { ModalContent } from './Example'; - -const mockPresent = jest.fn(); -const mockUseIonModal = jest.fn(); - -jest.mock('@ionic/react', () => { - const rest = jest.requireActual('@ionic/react'); - return { - ...rest, - useIonModal: (component: any) => { - mockUseIonModal(component); - return [mockPresent]; - }, - }; -}); +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { IonApp } from '@ionic/react'; -test('should present ModalContent when button is clicked', () => { - render(); +import Example from './Example'; +test('should present ModalContent when button is clicked', () => { + render( + + + + ); + // Simulate a click on the button fireEvent.click(screen.getByText('Open')); - - expect(mockUseIonModal).toHaveBeenCalledWith(ModalContent); - expect(mockPresent).toHaveBeenCalled(); + // Wait for the modal to be presented + await waitFor(() => { + // Assert that the modal is present + expect(screen.getByText('Modal content')).toBeInTheDocument(); + }); }); ``` diff --git a/docs/react/testing/unit-testing/setup.md b/docs/react/testing/unit-testing/setup.md index a38d73af6ce..742204792c7 100644 --- a/docs/react/testing/unit-testing/setup.md +++ b/docs/react/testing/unit-testing/setup.md @@ -42,6 +42,28 @@ import { setupIonicReact } from '@ionic/react'; setupIonicReact(); ``` +### Mock `requestAnimationFrame` + +Either in `src/setupTest.ts` or in the individual test file, add the following code before any tests are run: + +```tsx title="src/setupTest.ts" +beforeEach(() => { + jest.useFakeTimers(); + jest.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => cb()); +}); + +afterEach(() => { + window.requestAnimationFrame.mockRestore(); + jest.clearAllMocks(); +}); +``` + +:::note + +This is required if your application is using features such as `useIonModal` or `useIonPopover`. + +::: + ### Test Environment Ionic requires a DOM environment to be available in order to render components. This is typically provided by the `jsdom` test environment. In Jest 27 and later, the default environment is `node`. @@ -51,3 +73,9 @@ To configure this behavior, update your `test` command to include `--env=jsdom`: ```json title="package.json" "test": "react-scripts test --env=jsdom --transformIgnorePatterns 'node_modules/(?!(@ionic/react|@ionic/react-router|@ionic/core|@stencil/core|ionicons)/)'", ``` + +:::note + +Starting in Ionic v6, the `--transformIgnorePatterns` flag is required. + +::: diff --git a/sidebars.js b/sidebars.js index b6a1a526a39..6540388808e 100644 --- a/sidebars.js +++ b/sidebars.js @@ -129,7 +129,7 @@ module.exports = { type: 'category', label: 'Unit Testing', collapsed: false, - items: ['react/testing/unit-testing/setup', 'react/testing/unit-testing/examples'], + items: ['react/testing/unit-testing/setup', 'react/testing/unit-testing/examples', 'react/testing/unit-testing/best-practices'], }, ], }, From 756876081a9bc3f5c44cec5a7f602181ea602bd1 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Wed, 5 Apr 2023 15:55:15 -0400 Subject: [PATCH 08/24] Update docs/react/testing/unit-testing/setup.md Co-authored-by: Liam DeBeasi --- docs/react/testing/unit-testing/setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/react/testing/unit-testing/setup.md b/docs/react/testing/unit-testing/setup.md index 742204792c7..f455345c199 100644 --- a/docs/react/testing/unit-testing/setup.md +++ b/docs/react/testing/unit-testing/setup.md @@ -44,7 +44,7 @@ setupIonicReact(); ### Mock `requestAnimationFrame` -Either in `src/setupTest.ts` or in the individual test file, add the following code before any tests are run: +Either in `src/setupTest.ts` or in the individual test file, add the following code before any tests run: ```tsx title="src/setupTest.ts" beforeEach(() => { From 1b23cda5cff4d50f73959d9d0ff42f1d4d97fa1f Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Wed, 5 Apr 2023 15:55:25 -0400 Subject: [PATCH 09/24] Update docs/react/testing/introduction.md Co-authored-by: Liam DeBeasi --- docs/react/testing/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/react/testing/introduction.md b/docs/react/testing/introduction.md index 05ba658d6b3..a7c7e67ce65 100644 --- a/docs/react/testing/introduction.md +++ b/docs/react/testing/introduction.md @@ -16,7 +16,7 @@ Testing is an important part of the development process, and it helps to ensure There are two types of tests that can be written: -**Unit Tests**: Unit tests are used to test individual functions and components in isolation. They are typically written using [Jest](https://jestjs.io) and [React Testing Library](https://testing-library.com) or [Vitest](https://vitest.dev). +**Unit Tests**: Unit tests are used to test individual functions and components in isolation. They can be written using tools such as [Jest](https://jestjs.io) and [React Testing Library](https://testing-library.com) or [Vitest](https://vitest.dev). **Integration Tests**: Integration tests are used to test how different components work together. They are typically written using [Cypress](https://www.cypress.io) or [Playwright](https://playwright.dev). From 71214cfc13da5dcad6a6d16aee5072707a45c190 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Wed, 5 Apr 2023 15:55:41 -0400 Subject: [PATCH 10/24] Update docs/react/testing/unit-testing/setup.md Co-authored-by: Liam DeBeasi --- docs/react/testing/unit-testing/setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/react/testing/unit-testing/setup.md b/docs/react/testing/unit-testing/setup.md index f455345c199..04917eb606c 100644 --- a/docs/react/testing/unit-testing/setup.md +++ b/docs/react/testing/unit-testing/setup.md @@ -10,7 +10,7 @@ Ionic requires a few additional steps to set up unit tests. ## Jest -If your React project is using `react-scripts`, jest is already installed. You can confirm the version of Jest by running: +If your React project uses `react-scripts`, then Jest is already installed. You can confirm the version of Jest by running: ```bash npm ls jest From 2e6afe394c4998d54f320e2666b460787264a281 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Wed, 5 Apr 2023 15:59:49 -0400 Subject: [PATCH 11/24] Update docs/react/testing/introduction.md Co-authored-by: Liam DeBeasi --- docs/react/testing/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/react/testing/introduction.md b/docs/react/testing/introduction.md index a7c7e67ce65..f8bb978286f 100644 --- a/docs/react/testing/introduction.md +++ b/docs/react/testing/introduction.md @@ -18,7 +18,7 @@ There are two types of tests that can be written: **Unit Tests**: Unit tests are used to test individual functions and components in isolation. They can be written using tools such as [Jest](https://jestjs.io) and [React Testing Library](https://testing-library.com) or [Vitest](https://vitest.dev). -**Integration Tests**: Integration tests are used to test how different components work together. They are typically written using [Cypress](https://www.cypress.io) or [Playwright](https://playwright.dev). +**Integration Tests**: Integration tests are used to test how different components work together. They can be written using tools such as [Cypress](https://www.cypress.io) or [Playwright](https://playwright.dev). ## Tools and Libraries From 7024a23f60f980b210641e7c2424b86734396207 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Wed, 5 Apr 2023 16:01:14 -0400 Subject: [PATCH 12/24] Update docs/react/testing/introduction.md Co-authored-by: Liam DeBeasi --- docs/react/testing/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/react/testing/introduction.md b/docs/react/testing/introduction.md index f8bb978286f..b521935aa32 100644 --- a/docs/react/testing/introduction.md +++ b/docs/react/testing/introduction.md @@ -28,7 +28,7 @@ There are two types of tests that can be written: [**Vitest**](https://vitest.dev): Vitest is a modern testing framework powered by Vite. It is compatible with Jest and is used to run unit tests. -[**React Testing Library**](https://testing-library.com): 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. +[**React Testing Library**](https://testing-library.com): React Testing Library is a set of utilities that make it easy to test React components. It's used to interact with components and test their behavior. ### Integration Testing From 74b905de9ac39821df8b0134f27c308a69c3ca7d Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Wed, 5 Apr 2023 16:51:09 -0400 Subject: [PATCH 13/24] chore: remove additional resources section --- docs/react/testing/introduction.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/react/testing/introduction.md b/docs/react/testing/introduction.md index b521935aa32..6ef7840765e 100644 --- a/docs/react/testing/introduction.md +++ b/docs/react/testing/introduction.md @@ -35,7 +35,3 @@ There are two types of tests that can be written: [**Cypress**](https://www.cypress.io): Cypress is a modern testing tool that's used to run end-to-end tests. It allows developers to test the entire application, including the user interface, in a simulated environment. [**Playwright**](https://playwright.dev): Playwright is a browser automation library that's used to run end-to-end tests. It allows developers to test the entire application, including the user interface, in a simulated environment. - -## Additional Resources - -- [Testing Ionic React Apps with Jest and React Testing Library](https://ionicframework.com/blog/testing-ionic-react-apps-with-jest-and-react-testing-library/) From d916fd78eb7cf00c7d109bfc1a4850a726889b0c Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Wed, 5 Apr 2023 16:52:27 -0400 Subject: [PATCH 14/24] chore: add react scripts section --- docs/react/testing/unit-testing/setup.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/react/testing/unit-testing/setup.md b/docs/react/testing/unit-testing/setup.md index 04917eb606c..7f0bf8afd52 100644 --- a/docs/react/testing/unit-testing/setup.md +++ b/docs/react/testing/unit-testing/setup.md @@ -8,7 +8,9 @@ description: Learn how to set up unit tests for an Ionic React application. Ionic requires a few additional steps to set up unit tests. -## Jest +## React Scripts + +### Install Jest If your React project uses `react-scripts`, then Jest is already installed. You can confirm the version of Jest by running: From 16902156913addad0e2485505d4887d355d09ea3 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Wed, 5 Apr 2023 16:53:34 -0400 Subject: [PATCH 15/24] chore: simplify --- docs/react/testing/introduction.md | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/docs/react/testing/introduction.md b/docs/react/testing/introduction.md index 6ef7840765e..b1595d981bd 100644 --- a/docs/react/testing/introduction.md +++ b/docs/react/testing/introduction.md @@ -19,19 +19,3 @@ There are two types of tests that can be written: **Unit Tests**: Unit tests are used to test individual functions and components in isolation. They can be written using tools such as [Jest](https://jestjs.io) and [React Testing Library](https://testing-library.com) or [Vitest](https://vitest.dev). **Integration Tests**: Integration tests are used to test how different components work together. They can be written using tools such as [Cypress](https://www.cypress.io) or [Playwright](https://playwright.dev). - -## Tools and Libraries - -### Unit Testing - -[**Jest**](https://jestjs.io): Jest is a popular testing framework for JavaScript applications. It is included with `react-scripts` and is used to run unit tests. - -[**Vitest**](https://vitest.dev): Vitest is a modern testing framework powered by Vite. It is compatible with Jest and is used to run unit tests. - -[**React Testing Library**](https://testing-library.com): React Testing Library is a set of utilities that make it easy to test React components. It's used to interact with components and test their behavior. - -### Integration Testing - -[**Cypress**](https://www.cypress.io): Cypress is a modern testing tool that's used to run end-to-end tests. It allows developers to test the entire application, including the user interface, in a simulated environment. - -[**Playwright**](https://playwright.dev): Playwright is a browser automation library that's used to run end-to-end tests. It allows developers to test the entire application, including the user interface, in a simulated environment. From c3ca12a57ea5d17f827e89de2f53d376912fd91e Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Fri, 28 Apr 2023 13:47:57 -0400 Subject: [PATCH 16/24] chore: remove vitest --- docs/react/testing/introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/react/testing/introduction.md b/docs/react/testing/introduction.md index b1595d981bd..22275ee788d 100644 --- a/docs/react/testing/introduction.md +++ b/docs/react/testing/introduction.md @@ -10,12 +10,12 @@ This document provides an overview of how to test an application built with `@io ## Introduction -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 Vitest, Jest, React Testing Library, Playwright or Cypress. +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. ## Types of Tests There are two types of tests that can be written: -**Unit Tests**: Unit tests are used to test individual functions and components in isolation. They can be written using tools such as [Jest](https://jestjs.io) and [React Testing Library](https://testing-library.com) or [Vitest](https://vitest.dev). +**Unit Tests**: Unit tests are used to test individual functions and components in isolation. They can be written using tools such as [Jest](https://jestjs.io) and [React Testing Library](https://testing-library.com). **Integration Tests**: Integration tests are used to test how different components work together. They can be written using tools such as [Cypress](https://www.cypress.io) or [Playwright](https://playwright.dev). From 788c28e4d8d8eb9bd9aebabce0cc130b141df8f5 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Fri, 28 Apr 2023 13:49:06 -0400 Subject: [PATCH 17/24] chore: fix import statements --- docs/react/testing/unit-testing/best-practices.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/react/testing/unit-testing/best-practices.md b/docs/react/testing/unit-testing/best-practices.md index 00869f99e75..ce1562d391f 100644 --- a/docs/react/testing/unit-testing/best-practices.md +++ b/docs/react/testing/unit-testing/best-practices.md @@ -12,6 +12,8 @@ In your test template when rendering with React Testing Library, you must wrap y import { IonApp } from '@ionic/react'; import { render } from "@testing-library/react"; +import Example from './Example'; + test('example', () => { render( @@ -27,9 +29,12 @@ test('example', () => { 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. ```tsx title="Example.test.tsx" +import { IonApp } from '@ionic/react'; import { render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import Example from './Example'; + test('example', async () => { const user = userEvent.setup(); From 0871187205f4ef69b98b1aeb186d2cb5775cb613 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Fri, 28 Apr 2023 13:49:53 -0400 Subject: [PATCH 18/24] chore: jsx syntax --- docs/react/testing/unit-testing/examples.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/react/testing/unit-testing/examples.md b/docs/react/testing/unit-testing/examples.md index ee300b9f202..747fab5d9f6 100644 --- a/docs/react/testing/unit-testing/examples.md +++ b/docs/react/testing/unit-testing/examples.md @@ -28,8 +28,8 @@ export default function Example() { ### Testing the modal ```tsx title="src/Example.test.tsx" -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { IonApp } from '@ionic/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import Example from './Example'; @@ -81,7 +81,7 @@ const Example: React.FC = () => { Blank - + present()}> Open @@ -96,8 +96,8 @@ export default Example; ### Testing the modal ```tsx title="src/Example.test.tsx" -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import { IonApp } from '@ionic/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import Example from './Example'; From 2b50a6912abc02b98e42dc8a441e2ef9c3ddfb5a Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Fri, 28 Apr 2023 13:50:56 -0400 Subject: [PATCH 19/24] chore: update description --- docs/react/testing/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/react/testing/introduction.md b/docs/react/testing/introduction.md index 22275ee788d..32f4cdbbe0b 100644 --- a/docs/react/testing/introduction.md +++ b/docs/react/testing/introduction.md @@ -6,7 +6,7 @@ description: Learn how to test an Ionic React application. This document provide # Testing Ionic React -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 used in `@ionic/react`. +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. ## Introduction From 3afcf59cc76a1e79f44ea157bdce743c03db11b3 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Fri, 28 Apr 2023 13:52:41 -0400 Subject: [PATCH 20/24] chore: adjust types of tests --- docs/react/testing/introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/react/testing/introduction.md b/docs/react/testing/introduction.md index 32f4cdbbe0b..a8cae30a467 100644 --- a/docs/react/testing/introduction.md +++ b/docs/react/testing/introduction.md @@ -16,6 +16,6 @@ Testing is an important part of the development process, and it helps to ensure There are two types of tests that can be written: -**Unit Tests**: Unit tests are used to test individual functions and components in isolation. They can be written using tools such as [Jest](https://jestjs.io) and [React Testing Library](https://testing-library.com). +**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. -**Integration Tests**: Integration tests are used to test how different components work together. They can be written using tools such as [Cypress](https://www.cypress.io) or [Playwright](https://playwright.dev). +**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. From abf4fdfca05145500d8fa163cb00e22f4b7ead90 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Thu, 21 Sep 2023 10:45:46 -0400 Subject: [PATCH 21/24] chore: update based on vitest --- docs/react/testing/unit-testing/examples.md | 10 +-- docs/react/testing/unit-testing/setup.md | 67 ++++----------------- 2 files changed, 14 insertions(+), 63 deletions(-) diff --git a/docs/react/testing/unit-testing/examples.md b/docs/react/testing/unit-testing/examples.md index 747fab5d9f6..39275eef669 100644 --- a/docs/react/testing/unit-testing/examples.md +++ b/docs/react/testing/unit-testing/examples.md @@ -53,12 +53,6 @@ test('button presents a modal when clicked', async () => { 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. -:::warning - -You must mock `requestAnimationFrame` as described in the [setup section](./setup.md#mock-requestanimationframe). - -::: - ### Example component ```tsx title="src/Example.tsx" @@ -101,7 +95,7 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import Example from './Example'; -test('should present ModalContent when button is clicked', () => { +test('should present ModalContent when button is clicked', async () => { render( @@ -112,7 +106,7 @@ test('should present ModalContent when button is clicked', () => { // Wait for the modal to be presented await waitFor(() => { // Assert that the modal is present - expect(screen.getByText('Modal content')).toBeInTheDocument(); + expect(screen.getByText('Modal Content')).toBeInTheDocument(); }); }); ``` diff --git a/docs/react/testing/unit-testing/setup.md b/docs/react/testing/unit-testing/setup.md index 7f0bf8afd52..ad7fd70d9f8 100644 --- a/docs/react/testing/unit-testing/setup.md +++ b/docs/react/testing/unit-testing/setup.md @@ -8,22 +8,6 @@ description: Learn how to set up unit tests for an Ionic React application. Ionic requires a few additional steps to set up unit tests. -## React Scripts - -### Install Jest - -If your React project uses `react-scripts`, then Jest is already installed. You can confirm the version of Jest by running: - -```bash -npm ls jest -``` - -Ionic recommends `react-scripts@5` and requires a minimum version of `jest@27`, which includes `jsdom@16`. If you are using an older version of `react-scripts`, you can update it by running: - -```bash -npm install react-scripts@latest -``` - ### Install React Testing Library 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. @@ -38,46 +22,19 @@ Ionic React requires the `setupIonicReact` function to be called before any test In `src/setupTest.ts`, add the following code: -```tsx title="src/setupTest.ts" -import { setupIonicReact } from '@ionic/react'; - -setupIonicReact(); -``` - -### Mock `requestAnimationFrame` - -Either in `src/setupTest.ts` or in the individual test file, add the following code before any tests run: - -```tsx title="src/setupTest.ts" -beforeEach(() => { - jest.useFakeTimers(); - jest.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => cb()); -}); - -afterEach(() => { - window.requestAnimationFrame.mockRestore(); - jest.clearAllMocks(); -}); -``` - -:::note +```diff +import '@testing-library/jest-dom/extend-expect'; -This is required if your application is using features such as `useIonModal` or `useIonPopover`. ++ import { setupIonicReact } from '@ionic/react'; -::: ++ setupIonicReact(); -### Test Environment - -Ionic requires a DOM environment to be available in order to render components. This is typically provided by the `jsdom` test environment. In Jest 27 and later, the default environment is `node`. - -To configure this behavior, update your `test` command to include `--env=jsdom`: - -```json title="package.json" -"test": "react-scripts test --env=jsdom --transformIgnorePatterns 'node_modules/(?!(@ionic/react|@ionic/react-router|@ionic/core|@stencil/core|ionicons)/)'", +// Mock matchmedia +window.matchMedia = window.matchMedia || function () { + return { + matches: false, + addListener: function () { }, + removeListener: function () { } + }; +}; ``` - -:::note - -Starting in Ionic v6, the `--transformIgnorePatterns` flag is required. - -::: From 66ab966d5e2b5a5af0a4cadcba735b33ab713f14 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Mon, 2 Oct 2023 14:47:36 -0400 Subject: [PATCH 22/24] chore: prettier formatting --- sidebars.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sidebars.js b/sidebars.js index 6540388808e..832bec09c8f 100644 --- a/sidebars.js +++ b/sidebars.js @@ -129,7 +129,11 @@ module.exports = { type: 'category', label: 'Unit Testing', collapsed: false, - items: ['react/testing/unit-testing/setup', 'react/testing/unit-testing/examples', 'react/testing/unit-testing/best-practices'], + items: [ + 'react/testing/unit-testing/setup', + 'react/testing/unit-testing/examples', + 'react/testing/unit-testing/best-practices', + ], }, ], }, From 6d668710b9484b5c154996d6968558404894029f Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Mon, 23 Oct 2023 11:21:40 -0400 Subject: [PATCH 23/24] chore: add redirect for old url to new --- vercel.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vercel.json b/vercel.json index 8bc50e73908..b7f986824c5 100644 --- a/vercel.json +++ b/vercel.json @@ -63,7 +63,8 @@ "source": "/docs/vue/your-first-app/6-deploying-mobile", "destination": "/docs/vue/your-first-app/deploying-mobile" }, - { "source": "/docs/vue/your-first-app/7-live-reload", "destination": "/docs/vue/your-first-app/live-reload" } + { "source": "/docs/vue/your-first-app/7-live-reload", "destination": "/docs/vue/your-first-app/live-reload" }, + { "source": "/docs/react/testing", "destination": "/docs/react/testing/introduction" } ], "rewrites": [ { "source": "/docs", "destination": "/" }, From 7a18197001b9a8253d743f90505c4c69fe393b61 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Mon, 23 Oct 2023 11:25:28 -0400 Subject: [PATCH 24/24] chore: note for ionic starters --- docs/react/testing/unit-testing/setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/react/testing/unit-testing/setup.md b/docs/react/testing/unit-testing/setup.md index ad7fd70d9f8..0e4cf3d1ed1 100644 --- a/docs/react/testing/unit-testing/setup.md +++ b/docs/react/testing/unit-testing/setup.md @@ -6,7 +6,7 @@ description: Learn how to set up unit tests for an Ionic React application. # Unit Testing Setup -Ionic requires a few additional steps to set up unit tests. +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. ### Install React Testing Library