Enzyme and Jest: How to simulate/test material-ui dropzone onChange handler when dropzone component is third party module?

Viewed 1576

I have a material-ui dropzone component which has a onChange handler attached to it. The handler is passed from the main component - two levels up as a prop.

So Main - 2nd component - dropzone. The main component houses the handler method, while the 2nd component is just a wrapper. Then eventually dropzone component has the onChange attached to it. All three are functional components.

Dropzone module --> https://github.com/Yuvaleros/material-ui-dropzone

Problem

I am not sure if I am going into testing implementation details area here but I want to simulate this onChange handler runs and passes a dummy csv file to it. When I try simulate("change) and expect the handler tobeCalled, I keep getting received 0, expected 1.

const DropzoneAreaExample = (props) => {
  const classes = useStyles();
  console.log(props);
  return (
    <Fragment>
      <DropzoneArea
        onChange={props.handleDropzoneChange}
        filesLimit={1}
        dropzoneText="Drop your csv file here"
        dropzoneClass={classes.dropzone}
        acceptedFiles={["text/csv", ".csv"]}
        initialFiles={[props.filename]}
        onDelete={props.handleDropzoneDelete}
        showAlerts={true}
        alertSnackbarProps={{
          anchorOrigin: { horizontal: "center", vertical: "bottom" },
          autoHideDuration: 6000,
        }}
        clearOnUnmount={true}
        previewGridClasses={{ container: classes.borderWidth }}
        data-test="component-dropzone"
      />
    </Fragment>
  );
};

From the main component this is the onChange handler that will be passed to dropzone as a prop

  const handleDropzoneChange = (files) => {
    if (files.length > 0) {
      if (props.originalFileObj) {
        setState({
          files: props.originalFileObj,
          filename: props.originalFileObj[0].name,
        });
      } else {
        setState({
          files: files,
          filename: files[0].name,
        });
      }
    }
  };

Here is the test information:

  it("should fire onChange handler", () => {
    const handleDropzoneChange = jest.fn();
    const dzwrapper = shallow(
      <DropZone handleDropzoneChange={handleDropzoneChange} />
    );
    console.log(dzwrapper.props().children.props);
    dzwrapper.simulate("change", {
      target: {
        files: ["dummyValue.something"],
      },
    });
    console.log(dzwrapper.debug())
  });

The console log you see in the test here is the output:

console.log(dzwrapper.debug()):

<WithStyles(DropzoneArea) onChange={[Function: mockConstructor]} filesLimit={1} dropzoneText="Drop your csv file here" dropzoneClass={[undefined]} acceptedFiles={{...}} initialFiles={{...}} onDelete={[undefined]} showAlerts={true} alertSnackbarProps={{...}} clearOnUnmount={true} previewGridClasses={{...}} data-test="component-dropzone" maxFileSize={3000000} previewText="Preview:" disableRejectionFeedback={false} showPreviews={false} showPreviewsInDropzone={true} showFileNames={false} showFileNamesInPreview={false} useChipsForPreview={false} previewChipProps={{...}} previewGridProps={{...}} getFileLimitExceedMessage={[Function: getFileLimitExceedMessage]} getFileAddedMessage={[Function: getFileAddedMessage]} getFileRemovedMessage={[Function: getFileRemovedMessage]} getDropRejectMessage={[Function: getDropRejectMessage]} />

console.log(dzwrapper.props().children.props):

  {
    onChange: [Function: mockConstructor] {
      _isMockFunction: true,
      getMockImplementation: [Function (anonymous)],
      mock: [Getter/Setter],
      mockClear: [Function (anonymous)],
      mockReset: [Function (anonymous)],
      mockRestore: [Function (anonymous)],
      mockReturnValueOnce: [Function (anonymous)],
      mockResolvedValueOnce: [Function (anonymous)],
      mockRejectedValueOnce: [Function (anonymous)],
      mockReturnValue: [Function (anonymous)],
      mockResolvedValue: [Function (anonymous)],
      mockRejectedValue: [Function (anonymous)],
      mockImplementationOnce: [Function (anonymous)],
      mockImplementation: [Function (anonymous)],
      mockReturnThis: [Function (anonymous)],
      mockName: [Function (anonymous)],
      getMockName: [Function (anonymous)]
    },
    filesLimit: 1,
    dropzoneText: 'Drop your csv file here',
    dropzoneClass: undefined,
    acceptedFiles: [ 'text/csv', '.csv' ],
    initialFiles: [ undefined ],
    onDelete: undefined,
    showAlerts: true,
    alertSnackbarProps: {
      anchorOrigin: { horizontal: 'center', vertical: 'bottom' },
      autoHideDuration: 6000
    },
    clearOnUnmount: true,
    previewGridClasses: { container: 'makeStyles-borderWidth-7' },
    'data-test': 'component-dropzone',
    maxFileSize: 3000000,
    previewText: 'Preview:',
    disableRejectionFeedback: false,
    showPreviews: false,
    showPreviewsInDropzone: true,
    showFileNames: false,
    showFileNamesInPreview: false,
    useChipsForPreview: false,
    previewChipProps: {},
    previewGridProps: {},
    getFileLimitExceedMessage: [Function: getFileLimitExceedMessage],
    getFileAddedMessage: [Function: getFileAddedMessage],
    getFileRemovedMessage: [Function: getFileRemovedMessage],
    getDropRejectMessage: [Function: getDropRejectMessage]
  }

This is how the component looks like. When I click next after adding a file, the contents of the file will get validated. So for test case I was thinking I just make sure the onChange handler is called. Then I will add another test case to test what happens when next button is clicked.

enter image description here

1 Answers

You could test it like this:

import DropzoneArea from 'DropzoneArea';

it("should fire onChange handler", () => {
  const handleDropzoneChange = jest.fn();
  const dzwrapper = shallow(
    <DropZone handleDropzoneChange={handleDropzoneChange} />
  );
  // find the DropzoneArea node
  const dropzoneAreaWrapper = dzwrapper.find(DropzoneArea);
  // call its onChange prop
  dropzoneAreaWrapper.prop('onChange')();
  // check handleDropzoneChange has been called
  expect(handleDropzoneChange).toHaveBeenCalled();
});
Related