Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react-testing-library - how to simulate file upload to a <input type="file" /> element?

Tags:

I am using user-event to try to have more 'realistic' user interactions. However, after I click on the input, it will not fire the onChange function because by default it would only bring up the file explorer for the user to upload a file. How do I simulate the user uploading a file?

My code:

// Component
const FileInputComponent = ({ handleFileUpload }) => (
  <div>
    <input type="file" id="testing" accept=".png,.jpg" onChange={handleFileUpload} />
    <label htmlFor="testing">Input File Here</label>
  </div>
);
// Test file
test("Clicking on the label button calls the `handleFileUpload` function", () => {
  const handleFileUploadMockFn = jest.fn();
  const { getByLabelText } = render(<FileInputComponent handleFileUpload={handleFileUploadMockFn} />
  userEvent.click(getByLabelText("Input File Here"));
  expect(handleFileUploadMockFn).toHaveBeenCalledTimes(1);
});
like image 451
inbtw33n Avatar asked Apr 08 '20 15:04

inbtw33n


People also ask

How do I handle a file upload in react?

In order to upload files, the 'content-type' header must be set to 'multipart/form-data'. new FormData() creates a new empty formData object that we send as the payload in our POST request. Our POST request assumes there is an API endpoint on our backend server at http://localhost:3000/uploadFile. We're done!

Should I use userEvent or fireEvent?

The answer to this question is easy: we should always try to use userEvent over fireEvent whenever we are able to, except in very specific situations. Those exepctions can be scenarios in which some of those events inside the interaction chain make impossible to test correctly the logic we want to test.


1 Answers

I found a bit hacky solution and I'm not sure if it match the best practises in testing but I will share it with you it might help

describe("Upload files", () => {
  let file;

  beforeEach(() => {
    file = new File(["(⌐□_□)"], "chucknorris.png", { type: "image/png" });
  });

  test("cover photo upload", async () => {
    // render the component
    const { getByTestId } = render(<YourComponent />);

    // get the upload button
    let uploader = getByTestId("photo-uploader");

    // simulate ulpoad event and wait until finish
    await waitFor(() =>
      fireEvent.change(uploader, {
        target: { files: [file] },
      })
    );
    // get the same uploader from the dom
    let image = document.getElementById("photo-uploader");
    // check if the file is there
    expect(image.files[0].name).toBe("chucknorris.png");
    expect(image.files.length).toBe(1);
  });
});
like image 102
Ili Avatar answered Sep 20 '22 17:09

Ili