score:5

Accepted answer

Your validateBeforeSave function is declared within SomeComponent making it a closed/private scope function not accessible outside. You can pass that function as a prop and you can then create spy and pass it as a prop value in your test and test for if the prop function passed (spy) was called or not

So you would modify your function somewhat like this:

// some validator function
function validateBeforeSave(){
  ...
}

// Some function Component

const SomeComponent = (props: IMyComponentProps) => {
  const { classes, validateBeforeSave } = props;

  // Component has state
  const [count, setCount] = useState(0);


  function handleClick() {
  validateBeforeSave();
  .
  .
  .
  }

  return (
   <div>
      <Button>
      className="saveBtn"
      onClick={handleClick}
      </Button>
    </div>
  );

};

And In your Unit test, something like this:

  // Unit test
  describe('SomeComponent' () => {
  it('validates model on button click', () => {
      const validateSpy = jest.fn();
      const wrapper = mount(
        <MuiThemeProvider theme={theme}>
          <SomeComponent validateSpy={validateSpy}/>
        </MuiThemeProvider>,
      );
      const instance = wrapper.instance();
      wrapper
        .find('.saveBtn')
        .at(0)
        .simulate('click');
      expect(validateSpy).toHaveBeenCalledTimes(1);
    });
  }

score:0

I had similar problem mocking callback prop method with React 16.x.x, enzyme instance method returns null, what you can do is pass directly jest.fn() as a prop.

EXAMPLE:

  it('should invoke callback with proper data upon checkbox click', () => {
    const spyCheckboxClick = jest.fn((id, item) => ({
      id,
      item,
    }))
    const component: any = enzyme.mount(
      <SectionColumn {...{
        ...mockProps,
        onCheckboxClick: spyCheckboxClick,
      }} />
    );
    expect(spyCheckboxClick).toHaveBeenCalledTimes(0);
    // perform click to checkbox
    const checkboxComponent = component.find('StyledCheckbox');
    const input = checkboxComponent.first().children();
    input.simulate('change');
    expect(spyCheckboxClick).toHaveBeenCalledTimes(1);
    expect(spyCheckboxClick()).toEqual(null)
 });

score:1

I was also facing the same issue - I did like below -

import * as React from 'react';

const SampleComponent = () => {
  const sampleMethod = () => {
    console.log('hello world');
  };

  return <button onClick={sampleMethod} type="button">Click Me</button>;
};

export default SampleComponent;

test -

import React from 'react';
import SampleComponent from './';
import { shallow } from 'enzyme';

describe('SampleComponent', () => {
  test('should handle click correctly', () => {
    const logSpy = jest.spyOn(console, 'log');
    const wrapper = shallow(<SampleComponent></SampleComponent>);
    const button = wrapper.find('button');
    expect(button.text()).toBe('Click Me');
    button.simulate('click');
    expect(logSpy).toBeCalledWith('hello world');
  });
});

We can spy on console.log, to assert it is to be called or not

Check - https://stackoverflow.com/a/58637912/10734622


Related Query

More Query from same tag