0
votes

I am unit testing a React 16 functional component that defines a callback and passes it as a property down to the next component to be invoked when a click event fires.

import React from 'react'

function OuterComponent() {

  const handleClick = useCallback(() => {
    openDialog() // <--- This code is inaccessible from my "OuterComponent.test.js" unit test 
  }

  return <MyDialog clickHandler={handleClick} />
}
export default OuterComponent

I am seeking 100% test coverage and would like to mock all other components/functions using jest that are not part of the "OuterComponent" component.

The problem I am having is that I can't seem to mock the MyDialog component in order to have it trigger the handleClick function.

I also tried to mock the component using this snippet but it still seems to try to load all the imports from MyDialog

jest.doMock('components/MyDialog', () => {
    return () => () => <div />
})
//... other mocks along with **openDialog**

//...and in my describe/it...
MyDialog.mockImplementation(() => {})

OuterComponent().handleClick()
expect(openDialog).toHaveBeenCalled()

The hope here was that I could render an empty div for MyDialog and just simply call the handleClick function to test it. Does anyone know what I could be doing wrong or have any other ideas of how to test it?

1
Out of curiosity: why not test that handleClick has been called, rather than openDialog? If what you want to test is that openDialog did what it was supposed to do (ie opening a dialog), why not simply test the (mocked) dialog is present rather than checking that the function has been called? Ie. don't be so preoccupied with implementations details and just test what the user would see. - Nicolas SEPTIER
@NicolasSEPTIER This would work for me as well, but I've not yet figured out a way to mock the dialog and call its clickHandler property function. - Barry

1 Answers

1
votes

I don't think you can mock a var in a closure. The best you can do is something along those lines:

import { fireEvent, render } from 'react-testing-library';

jest.mock(
  'components/MyDialog',
  () => ({ clickHandler }) => (
    <button
      onClick={clickHandler}
      test-id="button"
    >
      Click me
    </button>
  ),
);

it('should call clickHandler', () => {
  const onClick = jest.fn(() => null);
  const { queryByTestId } = render(<MyDialog clickHandler={onClick} />);
  fireEvent.click(queryByTestId('button'));
  expect(onClick.toHaveBeenCalledTimes(1));
});

You actually test the ability for you MyDialog to render something that can execute a callback.