How to test react-hook-form with react-native-testing-library
I use react-hook-form for both web and react native without a single problem. Great library. When using react-hook-form v6. I encountered an issue where the validation works perfectly in code, but in test, the errors
object is always empty even for wrong value. Let’s see how to solve it. In this blog, I will demostrate how to test react-hook-form
with react-native-testing-library
for both iOS and Android within one test through jest-expo
, and yes, we will use jest
as the test runner.
1. Setup the project
I will use expo
for a quick demonstration.
1 | # select blank template, JS or TS |
jest-expo
is a library from the Expo team to do universal testing here, it will run your tests for every platform you setup, here, because react-native-testing-library
only supports native device, we will not use web setup, via expo
‘s file extension pick up and the similarities between react-native-testing-library
and @testing-library/react
, share one single test file for both web and native devices should be easy, will try them later.
In package.json
:
- add a
script
:"test": "node_modules/.bin/jest"
- add
jest
settings:
1 | "jest": { |
If you want to rewrite any jest
rules, you have to write the new rule for each platform like the above example.
create jestAfterEnvSetup.js
:
1 | global.window = {}; |
If you are using Typescript, you might need to
// @ts-ignore
the above lines
2. The application to test
Change App.js
to the following:
1 | import React from "react"; |
We have a simple form here, one text input for name, and it is required, one submit button for submit the values.
expo start
, you will see this ugly application, press the submit button with a blank input will lead to an error.
We extract the errorText
from errors["name"]?.message
, than use Boolean(errorText)
to check, if there is an error text, then there is an error.
3. The test
Create the file App.test.js
at the same level of App.js
with the following content:
1 | import * as React from "react"; |
We have 2 tests here, one for happy path, and one for unhappy path.
We will mimic the user’s behaviour.
For the happy path: If we have a value, the nameErrorText
should not been displayed.
For the unhappy path: If we don’t have a value, then the application should show the nameErrorText
.
The test should be quite easy to read. I won’t explain them here.
The interesting part is:
1 | await act(async () => { |
Why we need to await act(async()=>{})
the pressing button event? It is because the validation in react-hook-form is always async, so you have to wait until it is finished. (Which is good, because real-world validation could be costy).
If you forget to wrap the act()
, you will see a red warning: Warning: An update to App inside a test was not wrapped in act(...)
4. End
Run yarn test
, you will see all tests pass.
Thanks for reading! Hope it helps.
Follow me (albertgao) on twitter, if you want to hear more about my interesting ideas.