2

Attempting to test a basic react component that takes an event handler onClick. When passing in jest.fn() the tests fails on expect(myComponent).toHaveBeenCalledTimes(1). I'm attempting to simulate a user click with:

const button = document.querySelector("#calcButton");
button.dispatchEvent(new MouseEvent("click", { bubbles: true }));

Full code below.

The app works correctly in prod and dev and document.querySelector("#calcButton").dispatchEvent(new MouseEvent("click", { bubbles: true })); works in the chrome console.

EDIT: Same result if I replace dispatchEvent(...) with .click(). Passing in console.log("Call back activated") as clicked showed that the callback is indeed getting called.

// calculate-button.test.js
import React from "react";
import { act } from "react-dom/test-utils";
import { render, unmountComponentAtNode } from "react-dom";

import Button from "react-bootstrap/Button";
import CalculateButton from "./calculate-button";
let container = null;

beforeEach(() => {
  // setup a DOM element as a render target
  container = document.createElement("div");
  document.body.appendChild(container);
});

// Omitted afterEach and some other tests. The problem occurs with them commented out.

it("fires event when clicked.", () => {
  const clicked = jest.fn();
  act(() => {
    render(<CalculateButton onClick={clicked} />, container);
  });
  const button = document.querySelector("#calcButton");
  console.log(button); // Output indictates button is being selected as hoped.
  act(() => {
    button.dispatchEvent(new MouseEvent("click", { bubbles: true }));
  });

  expect(clicked).toHaveBeenCalledTimes(1);
  // This is where the error happens.
});

//calculate-button.js
import React from "react";
import Button from "react-bootstrap/Button";

function calculateButton(props) {
  return (
    <Button
      variant="primary"
      size="lg"
      id="calcButton"
      block
      onClick={props.handleClick}
    >
      Calculate!
    </Button>
  );
}

export default calculateButton;

The result of npm test

  ● Console

    console.log src/components/calculate-button/calculate-button.test.js:36
      HTMLButtonElement {
        '__reactInternalInstance$vwtourl9fj':
         FiberNode {
           tag: 5,
           key: null,
           elementType: 'button',
           type: 'button',
           stateNode: [Circular],
           return:
...OMITTED...

  ● fires event when clicked.

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

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

      39 |   });
      40 | 
    > 41 |   expect(clicked).toHaveBeenCalledTimes(1);
         |                   ^
      42 | });
      43 | 

      at Object.toHaveBeenCalledTimes (src/components/calculate-button/calculate-button.test.js:41:19)

Test Suites: 1 failed
Harry MW
  • 134
  • 1
  • 10

1 Answers1

1

Figured it out. Thanks for all the help.

In calculate-button.js I reference onClick={props.handleClick} but in calculate-button.test.js I was passing in the mockClickHandler as the prop onClick. Changing the mismatch by altering render(<CalculateButton onClick={clicked} />, container); to render(<CalculateButton hadleClick={clicked} />, container); fixed it.

That's what I get for sloppy naming. Thanks again.

Harry MW
  • 134
  • 1
  • 10