Testing Library / React Dropzone basic test failure

29 views Asked by At

For some reason, my Jest mock is not being invoked. All relevant bits of logic are indeed being accessed/invoked and, in fact, if I pass a handler of my own--something like () => { console.log('blah') }--it will indeed be invoked and I see the console.log in my terminal. Does anyone know why expect(mockOnSuccess).toHaveBeenCalled() and expect(mockOnFailure).toHaveBeenCalled() are returning false despite the fact that I know the handler is being invoked?

// file-upload.tsx

import { useDropzone } from 'react-dropzone';
import type {
  DropzoneOptions as ComponentProps,
  FileRejection,
} from 'react-dropzone';

export function FileUpload({
  maxSize = 100000000,
  onSuccess,
  onFailure,
}: FileUploadDropzoneProps) {
  const { getRootProps, getInputProps } = useDropzone({
    validator,
    accept,
    onDropAccepted: (acceptedFiles) => {
      onSuccess(acceptedFiles);
    },
    onDropRejected: (fileRejections) => {
      onFailure(fileRejections);
    },
  });

  return (
    <div {...getRootProps()}>
      <input
        {...getInputProps()}
        data-testid='file-upload'
      />
      <p className='border-dashed'>
        Drag 'n' drop some files here, or click to select files
      </p>
    </div>
  );

  function validator(file: File) {
    if (fileSizeIsTooLarge(file)) {
      return {
        code: 'file-too-large',
        message: `File size is larger than ${maxSize}`,
      };
    }

    return null;
  }

  function fileSizeIsTooLarge(file: File) {
    return maxSize && file.size > maxSize;
  }
}

/* Accepted file types */
const accept = {
  'text/csv': [],
  'application/vnd.ms-excel': [],
  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': [],
  'application/vnd.openxmlformats-officedocument.spreadsheetml.template': [],
  'application/vnd.ms-excel.sheet.macroEnabled.12': [],
  'application/vnd.ms-excel.template.macroEnabled.12': [],
  'application/vnd.ms-excel.addin.macroEnabled.12': [],
  'application/vnd.ms-excel.sheet.binary.macroEnabled.12': [],
};

type FileUploadDropzoneProps = Partial<Pick<ComponentProps, 'maxSize'>> & {
  onSuccess: (files: File[]) => void;
  onFailure: (files: FileRejection[]) => void;
};

// file-upload.test.tsx

import '@testing-library/jest-dom';

import { fireEvent, render, screen, waitFor } from '@testing-library/react';

import { FileUpload } from '../';

describe('FileUpload', () => {
  const mockOnSuccess = jest.fn();
  const mockOnFailure = jest.fn();

  afterEach(() => {
    mockOnSuccess.mockReset();
    mockOnFailure.mockReset();
  });

  describe('In general', () => {
    test('It should render', () => {
      render(
        <FileUpload
          onSuccess={mockOnSuccess}
          onFailure={mockOnFailure}
        />,
      );

      expect(
        screen.getByText(
          "Drag 'n' drop some files here, or click to select files",
        ),
      ).toBeInTheDocument();
    });
  });

  describe('When the uploaded file is accepted', () => {
    test('It should invoke the onSuccess handler', async () => {
      const maxSize = 100000000;
      render(
        <FileUpload
          onSuccess={mockOnSuccess}
          onFailure={mockOnFailure}
          maxSize={maxSize}
        />,
      );

      const validFile = createMockFile('file.csv', maxSize, 'text/csv');
      const input = screen.getByTestId('file-upload');
      fireEvent.drop(input, { target: { files: [validFile] } });

      await waitFor(() => {
        expect(mockOnSuccess).toHaveBeenCalled();
        expect(mockOnFailure).not.toHaveBeenCalledWith([validFile]);
      });
    });
  });

  describe('Failure scenarios', () => {
    test('The onFailure handler should be invoked if the file is too large', async () => {
      const maxSize = 100000000;
      const overMaxSize = 100000001;
      render(
        <FileUpload
          onSuccess={mockOnSuccess}
          onFailure={mockOnFailure}
          maxSize={maxSize}
        />,
      );

      const invalidFile = createMockFile('file.txt', overMaxSize, 'text/plain');
      const input = screen.getByTestId('file-upload');
      fireEvent.drop(input, { target: { files: [invalidFile] } });

      await waitFor(() => {
        expect(mockOnSuccess).not.toHaveBeenCalled();
        expect(mockOnFailure).toHaveBeenCalled();
      });
    });

    /*
    test('It should not allow inappropriate file types', () => {
      const maxSize = 100000000;
      render(
        <FileUpload
          onSuccess={mockOnSuccess}
          onFailure={mockOnFailure}
          maxSize={maxSize}
        />,
      );

      const invalidFile = createMockFile('file.csv', maxSize, 'text/plain');
      const input = screen.getByTestId('file-upload');
      fireEvent.drop(input, { target: { files: [invalidFile] } });

      expect(mockOnSuccess).not.toHaveBeenCalled();
      expect(mockOnFailure).toHaveBeenCalled();
    });
     */
  });
});

function createMockFile(name: string, size: number, mimeType: string) {
  const blob = new Blob(['a'.repeat(size)], { type: mimeType });
  return new File([blob], name, { type: mimeType });
}

Error:

 FileUpload › When the uploaded file is accepted › It should invoke the onSuccess handler

           thrown: "Exceeded timeout of 5000 ms for a test.
           Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

             32 |
             33 |   describe('When the uploaded file is accepted', () => {
           > 34 |     test('It should invoke the onSuccess handler', async () => {
                |     ^
             35 |       const maxSize = 100000000;
             36 |       render(
             37 |         <FileUpload

             at src/lib/components/__tests__/file-upload.test.tsx:34:5
             at src/lib/components/__tests__/file-upload.test.tsx:33:3
             at Object.<anonymous> (src/lib/components/__tests__/file-upload.test.tsx:7:1)

         ● FileUpload › Failure scenarios › The onFailure handler should be invoked if the file is too large

           thrown: "Exceeded timeout of 5000 ms for a test.
           Add a timeout value to this test to increase the timeout, if this is a long-running test. See https://jestjs.io/docs/api#testname-fn-timeout."

             54 |
             55 |   describe('Failure scenarios', () => {
           > 56 |     test('The onFailure handler should be invoked if the file is too large', async () => {
                |     ^
             57 |       const maxSize = 100000000;
             58 |       const overMaxSize = 100000001;
             59 |       render(

             at src/lib/components/__tests__/file-upload.test.tsx:56:5
             at src/lib/components/__tests__/file-upload.test.tsx:55:3
             at Object.<anonymous> (src/lib/components/__tests__/file-upload.test.tsx:7:1)

Test Suites: 1 failed, 1 total
       Tests:       2 failed, 1 passed, 3 total
       Snapshots:   0 total
       Time:        18.756 s
       Ran all test suites.
    ```


0

There are 0 answers