GameAtrix1
GameAtrix1

Reputation: 369

Not getting expected result from .toHaveBeenCalledTimes() in react-testing-library

Anyhow, trying to test if a function has been called after its fired. The fireEvent is working as I get a console.log from that function. But the .toHaveBeenCalledTimes(1) returns 0. What have i missed?

If I have the handleLoginSubmit function in the parent and pass it as a prop down to the child and in the test everything passes. But if it's in the same component it fails. Using typescript if that has any meaning.

This is tested

import React, { FC } from 'react';

type Event = React.FormEvent<HTMLFormElement>;

interface Login {
  handleLoginSubmit?: (event: Event) => React.ReactNode;
}

const Login: FC<Login> = () => {
  const handleLoginSubmit = (_event: Event) => {
    console.log('Firing' ); // This is logged
  };

  return (
    <form data-testid='form' onSubmit={(event) => handleLoginSubmit(event)}>
      <input data-testid='email'/>
      <input data-testid='password'/>
      <button data-testid='login-button'>login</button>
    </form>
  );
};

export default Login;

My test for submiting

  it('should handle ClickEvents', () => {

    const handleLoginSubmit = jest.fn();

    const { getByTestId } = render(<Login/>);

    expect(getByTestId('login-button')).toBeTruthy();

    fireEvent.submit(getByTestId('form'));

    expect(handleLoginSubmit).toHaveBeenCalledTimes(1);

  });

Error message

 ● Login page › should handle ClickEvents

    expect(jest.fn()).toHaveBeenCalledTimes(expected)

    Expected number of calls: 1
    Received number of calls: 0

      32 |     fireEvent.submit(getByTestId('form'));
      33 | 
    > 34 |     expect(handleLoginSubmit).toHaveBeenCalledTimes(1);
         |                               ^
      35 | 
      36 |   });
      37 | });

      at Object.it (__tests__/components/Login.test.tsx:34:31)

Upvotes: 7

Views: 16623

Answers (1)

Lin Du
Lin Du

Reputation: 102207

You can't assert if the handleLoginSubmit function is to be called directly. Since it's defined in the private scope of Login SFC. You can't mock or spy on this function because you can't access it. So, you need to test it indirectly. Since you are using console.log in this function, we can spy console.log. If it's been called, that means the handleLoginSubmit function has been called.

E.g.

index.tsx:

import React, { FC } from "react";

type Event = React.FormEvent<HTMLFormElement>;

interface Login {
  handleLoginSubmit?: (event: Event) => React.ReactNode;
}

const Login: FC<Login> = () => {
  const handleLoginSubmit = (_event: Event) => {
    console.log("Firing");
  };

  return (
    <form data-testid="form" onSubmit={event => handleLoginSubmit(event)}>
      <input data-testid="email" />
      <input data-testid="password" />
      <button data-testid="login-button">login</button>
    </form>
  );
};

export default Login;

index.spec.tsx:

import { render, fireEvent } from "@testing-library/react";
import Login from "./";
import React from "react";

it("should handle ClickEvents", () => {
  const logSpy = jest.spyOn(console, "log");
  const { getByTestId } = render(<Login />);
  expect(getByTestId("login-button")).toBeTruthy();
  fireEvent.submit(getByTestId("form"));
  expect(logSpy).toHaveBeenCalledTimes(1);
});

Unit test result with 100% coverage:

 PASS  src/stackoverflow/59162138/index.spec.tsx
  ✓ should handle ClickEvents (42ms)

  console.log node_modules/jest-mock/build/index.js:860
    Firing

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 index.tsx |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.987s, estimated 9s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59162138

Upvotes: 8

Related Questions