hrtyy.dev

First Step of Testing React Form.

I want to write test codes for React forms. 'react-hook-form' is used in this React app. I will test it with 'jest' and 'testing-library'.

Library Versions

  • react: 17.0.2
  • typescript": "4.5.2
  • @testing-library/jest-dom: 5.11.4
  • @testing-library/react: 11.1.0
  • react-hook-form: 7.20.5
  • ts-jest: 27.0.3
  • jest: 27.0.3

react-hook-form

react-hook-form is a high performance wrapper library for React form embracing uncontrolled component. This is an example code.

1type FormData = {
2 loginId: string;
3}
4
5const LoginForm: React.VFC<{ onSubmit: (data: FormData) => void }> = ({ onSubmit }) => {
6 const form = useForm<FormData>()
7
8 return (
9 <form onSubmit={form.handleSubmit(onSubmit)}>
10 <p>Hello</p>
11 <label>
12 <span>Login ID</span>
13 <input {...form.register("loginId")} />
14 </label>
15 </form>
16 );
17}
18
19export const App: React.VFC = () => {
20 const onSubmit = ({ loginId }: FormData) => {
21 console.log(loginId)
22 }
23
24 return (
25 <div>
26 <LoginForm onSubmit={onSubmit}/>
27 </div>
28 );
29}

This app will show loginId on your console.

I want to test whether LoginForm component

  • can get value from input with name="loginId"
  • will pass data through onSubmit callback in submitting.

Test

First setup jest.config.js on your project root.

jest.config.js
1module.exports = {
2 preset: "ts-jest",
3 testEnvironment: "jsdom"
4}

Add the following test code in tests directory.

__tests__/LoginForm.test.tsx
1import { act, fireEvent, render } from "@testing-library/react";
2import { LoginForm } from "../src/App";
3
4describe("test for LoginForm", () => {
5 it("get value with name = loginId", async () => {
6 const onSubmit = jest.fn()
7 const result = render(<LoginForm onSubmit={onSubmit}/>)
8 const input = result.container.querySelector('input[name="loginId"]')!
9 const form = result.container.querySelector('form')!
10 await act(async () => {
11 fireEvent.input(input, {
12 target: {
13 value: "my_login_id"
14 }
15 })
16 fireEvent.submit(form)
17 })
18 const call = onSubmit.mock.calls[0][0];
19 expect(call.loginId).toBe("my_login_id")
20 })
21})

Run test using yarn run jest

1 PASS __tests__/LoginForm.test.tsx
2 test for LoginForm
3 ✓ get value with name = loginId (35 ms)
4
5Test Suites: 1 passed, 1 total

fireEvent can simulate interactions to forms. In this case, fireEvent.input will input my_login_id value to input element selected by query input[name="loginId"].

fireEvent.submit will submit form. After that, the passed mock function onSubmit will be called.

The results of call are stored in calls property of mock in the mock function.

The expected my_login_id value was stored in it.