React : Testing file upload using testing library

06 Feb 2024

In this post, we will look into writing a test case for file upload using the React testing library

Select accepted file type

In order to simulate file upload in test case, we will be using upload method from @testing-library/user-event.

upload method will accept input element as the first argument and File object as the second.

import userEvent from '@testing-library/user-event';
import { render, screen } from '@testing-library/react';


test("select accepted file", async () => {
  const user = userEvent.setup();
  render(
    <>
      <label htmlFor='file'>Select file</label>
      <input type="file" name='file' id="file" accept='text/csv' />
    </>
  );

  const fileInput = screen.getByLabelText(/Select file/i);
  const content = '';

  const file = new File([str], 'upload.csv', {
    type: 'text/csv',
  });

  await user.upload(fileInput, file);
  expect(fileInput.files[0]).toBe(file)
  expect(fileInput.files[0].size).toBe(0)
});

Select unaccepted file type

In the below example, the input element will accept only text/csv file, but in the test case for validation, we should be able to select non CSV file.

In order to do this, we need to pass {applyAccept: false} to userEvent.setup method. By default, applyAccept is true.

import userEvent from '@testing-library/user-event';
import { render, screen } from '@testing-library/react';

test("select unaccepted file", async () => {
  const user = userEvent.setup({applyAccept: false});
  render(
    <>
      <label htmlFor='file'>Select file</label>
      <input type="file" name='file' id="file" accept='text/csv' />
    </>
  );

  const fileInput = screen.getByLabelText(/Select file/i);
  const content = '{}';

  const file = new File([content], 'upload.json', {
    type: 'application/json',
  });

  await user.upload(fileInput, file);
  expect(fileInput.files[0]).toBe(file)
  expect(fileInput.files[0].size).toBe(2)
});

Select multiple files

To select multiple files in the test case, we can pass an array of file object as second argument to upload method

import userEvent from '@testing-library/user-event';
import { render, screen } from '@testing-library/react';


test("select mulitple file", async () => {
  const user = userEvent.setup();
  render(
    <>
      <label htmlFor='file'>Select file</label>
      <input type="file" name='file' id="file" accept='text/csv' multiple />
    </>
  );

  const fileInput = screen.getByLabelText(/Select file/i);
  const content0 = '';

  const file0 = new File([content0], 'upload0.csv', {
    type: 'text/csv',
  });

  
  const file1 = new File(['a,b,c'], 'upload1.csv', {
    type: 'text/csv',
  });

  await user.upload(fileInput, [file0,file1]);

  expect(fileInput.files[0]).toBe(file0)
  expect(fileInput.files[0].size).toBe(0)

  expect(fileInput.files[1]).toBe(file1)
  expect(fileInput.files[1].size).toBe(5)
});

Hope that helped.
Happy coding.

Versions of Language/packages used in this post.

Library/Language Version
@testing-library/react 14.2.1
@testing-library/user-event 14.5.2
If you find my work helpful, You can buy me a coffee.