0
votes

I've been trying to mock my submit function in jest but I always received this error:

expect(jest.fn()).toHaveBeenCalled()

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

How can I solve this kind of error?

Here is my test file.

it('checks the function submitTodo', () => {
    const submitTodo = jest.fn();
    const { getByTestId } = render(<InputField />);
    const input = getByTestId('input');
    fireEvent.change(input, { target: { value: 'test' } })

    fireEvent.submit(getByTestId('form'))
    expect(submitTodo).toHaveBeenCalled()
})

and here is my functional component where I'm calling my async function.

import { useState } from 'react';
import { firestore } from 'firebase/firebaseConfig';
import firebase from 'firebase/firebaseConfig';
import styles from 'theme/main.module.scss';

const InputField = () => {
  const [todo, setTodo] = useState('');

  const submitTodo = async (e) => {
    e.preventDefault();
    try {
      await firestore.collection('todo').add({
        todo,
        timestamp: firebase.firestore.FieldValue.serverTimestamp(),
      });
    } catch (error) {
      alert(error);
    }
    setTodo('');
  };
  return (
    <form
      data-testid='form'
      className={styles.inputFieldContainer}
      onSubmit={(e) => submitTodo(e)}
    >
      <input
        data-testid='input'
        className={styles.inputFieldContainer__input}
        placeholder='Please enter a todo.'
        required
        value={todo}
        onChange={(e) => setTodo(e.target.value)}
      />
      <button
        data-testid='submitBtn'
        className={styles.inputFieldContainer__btn}
        type='submit'
      >
        Submit
      </button>
    </form>
  );
};

export default InputField;
1

1 Answers

0
votes

submitTodo is an inner function of InputField . you can't mock it directly using jest.fn(). If you just want to test whether the submitTodo function is called then you can do this .

it('checks the function submitTodo', () => {
    const submitTodoForTest = jest.fn();
    const { getByTestId } = render(<InputField submitTodoForTest={submitTodoForTest} />);
    const input = getByTestId('input');
    fireEvent.change(input, { target: { value: 'test' } })

    fireEvent.submit(getByTestId('form'))
    expect(submitTodoForTest).toHaveBeenCalled()
})

// In your component
  const InputField = ({submitTodoForTest = null}) => {
  const [todo, setTodo] = useState('');

  const submitTodo = async (e) => {
  submitTodoForTest && submitTodoForTest();
    e.preventDefault();
    try {
      await firestore.collection('todo').add({
        todo,
        timestamp: firebase.firestore.FieldValue.serverTimestamp(),
      });
    } catch (error) {
      alert(error);
    }
    setTodo('');
  };
  return (
    ....
  );
};

But if you need to test whether the fireStore is called, then you need to mock the fireStore as well .