Search code examples
reactjsjestjsreact-testing-library

Testing a function has been clicked in RTL that has not been passed as a prop


I have a simple component with a function that is executed when clicking a button:

const ButtonComponent = () => {
  const [clickCount, setClickCount] = useState(0);

  const handleClick = () => {
    setClickCount(clickCount + 1);
  };

  return (
    <div>
      <button onClick={handleClick}>Click Me</button>
      <p>Click count: {clickCount}</p>
    </div>
  );
};

How can I create a simple test in RTL specifically testing that the function has been executed after clicking the button? Note that I do not want to pass the handleClick function as a prop, or test that the clickCount has changed, because in my real app there are other use cases where I just want to test that the function has actually been called.

The closest I could come with is this:

test('should call handleClick function on button click', () => {
  const { getByText } = render(<ButtonComponent />);
  const button = getByText('Click Me');

  const componentInstance = button.parentNode._reactInternalFiber.child.stateNode; // Access the component instance

  const handleClickSpy = jest.spyOn(componentInstance, 'handleClick');

  expect(handleClickSpy).not.toHaveBeenCalled();

  userEvent.click(button);

  expect(handleClickSpy).toHaveBeenCalledTimes(1);

  handleClickSpy.mockRestore(); // Restore the original handleClick function
});

Solution

  • I don't think you should test implementation details. It would be better to test what behaviour user sees after they click on the button.

    const { getByText } = render(<ButtonComponent />);
    const button = getByText('Click Me');
    
    userEvent.click(button);
    
    // Expect some behaviour