Home > other >  fireEvent.change does not trigger onChange listener
fireEvent.change does not trigger onChange listener

Time:01-14

I am building a React component that has an input "file" type element.

export default function NavBar() {
    return (
       <label htmlFor='upload-image' className={classes.label}> Upload </label>
       <input type='file' 
              id='upload-image'
              onChange={ (e) => { uploadImage(e) } } />
    )
}

uploadImage is a standalone function, exported from uploadImage.js:

// uploadImage.js

const uploadImage = async (e) => {
    // some code to upload the image to a cloud database
}

export { uploadImage };

With Jest and React Testing Library, I am trying to test whether uploadImage is triggered whenever the input "file" type element is changed. Below is my work so far:

import * as uploadImage from '../api/uploadImage';

test("when user changes the file input, uploadImage function is called once", () => {
    render( <NavBar /> );

    const fileInput = screen.getByLabelText(/Upload/i);

    fireEvent.change(fileInput, {
        target: {
            files: [new File(['(⌐□_□)'], 'chucknorris.png', {type: 'image/png'})],
        },
    });

    const mock = jest.spyOn(uploadImage, 'uploadImage');
    expect(mock).toBeCalled();
});

I expect the test to pass. When fireEvent.change() is initiated, uploadImage should be initiated. However, the test fails, showing that uploadImage was not initated as follows:

expect(jest.fn()).toBeCalled()

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

I suspect that fireEvent.change() is not working, but I am not sure. \

  1. Can you give an explanation why the test did not pass?
  2. For uploadImage.js, instead of writing export { uploadImage }, how should I use jest to mock uploadImage if I use export default, i.e export default uploadImage?

Thank you very much!

CodePudding user response:

The problem is that spyOn is called after the event is fired.

Change the test code to:

test('when user changes the file input, uploadImage function is called once', () => {
  render(<NavBar />);
  const mock = jest.spyOn(uploadImage, 'uploadImage');
  const fileInput = screen.getByLabelText(/Upload/i);

  fireEvent.change(fileInput, {
    target: {
      files: [new File(['(⌐□_□)'], 'chucknorris.png', { type: 'image/png' })],
    },
  });

  expect(mock).toBeCalled();
});

so that the mock function is created and ready before it gets called.

  •  Tags:  
  • Related