vendredi 8 janvier 2021

How to mock a function inside react hook

I was trying to test form submission. Here is what my form looks like.

const AccountForm = () => {
  const account = useAccount(null);
  const accountName = useInput("");
  const accountAmount = useInput(0);
  const [isLoading, setIsLoading] = useState(false);

  const onSubmit = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setIsLoading(true);
    try {
      const acc: IAccount = {
        id: String(Date.now()),
        name: String(accountName.value),
        amount: Number(accountAmount.value),
        date: new Date().toLocaleDateString(),
      };
      await account.add(acc);
    } catch (error) {
      console.error(error);
    }
    setIsLoading(false);
  };

  return (
    <div data-testid="account-form-wrapper">
      <h2>Create new account</h2>
      <div>
        <form onSubmit={onSubmit}>
          <fieldset disabled={isLoading}>
            <label htmlFor="name">Name</label>
            <input
              type="text"
              name="name"
              id="name"
              autoComplete="off"
              value={accountName.value}
              onChange={accountName.onChange}
            />
          </fieldset>
          <fieldset disabled={isLoading}>
            <label htmlFor="amount">Amount</label>
            <input
              type="number"
              name="amount"
              id="amount"
              value={accountAmount.value}
              onChange={accountAmount.onChange}
            />
          </fieldset>
          <button
            type="submit"
            data-testid="submit-button"
            disabled={isLoading}
          >
            Create Account
          </button>
        </form>
      </div>
    </div>
  );
};

The form itself is pretty simple. It uses the custom hook called useAccount which returns { value, add, set, edit }. The methods in returns makes the api call to the firebase. I was wondering how I can test(mock) the account.add with React Testing library.

Here's what I have tried: I tried to mock const mockAdd = jest.fn(hookWrapper.result.current.add); like this. But it doesn't get called!

import {
  toBeInTheDocument,
  toBeDisabled,
  toBeEnabled,
} from "@testing-library/jest-dom";
import { renderHook } from "@testing-library/react-hooks";
import { fireEvent, render, waitFor, act } from "@testing-library/react";
import AccountForm from "./form";
import useAccount from "../../hooks/useAccounts";

describe("./form.tsx", () => {
  test("renders <AccountForm />", async () => {
    const component = render(<AccountForm />);
    const hookWrapper = renderHook(useAccount);
    const submitBtn = component.getByText(/create account/i);
    const accountNameInput = component.getByLabelText(/name/i);
    const amountInput = component.getByLabelText(/amount/i);

    fireEvent.change(accountNameInput, { target: { value: "bank" } });
    fireEvent.change(amountInput, { target: { value: 200 } });

    expect(submitBtn).toBeInTheDocument();
    expect(submitBtn).toBeEnabled();

    const mockAdd = jest.fn(hookWrapper.result.current.add);

    waitFor(() => fireEvent.click(submitBtn));
    expect(mockAdd).toHaveBeenCalledTimes(1);
    expect(submitBtn).toBeDisabled();
  });
});

This is what my code coverage looks like:

enter image description here

Line 24 being the catch block and Line 26 being the setIsLoading.

Aucun commentaire:

Enregistrer un commentaire