import React from 'react'; import { fireEvent, createEvent } from '@testing-library/react'; import renderWithTheme from '../../../../testUtils/renderWithTheme'; import FileDnD from '..'; const fireDropFileEvent = ( element: HTMLElement, files: { name: string; size: number; type: string; }[] ): void => { const mockFiles = files.map(file => { const mockFile = new File([file.name], file.name, { type: file.type, }); Object.defineProperty(mockFile, 'size', { value: file.size, }); return mockFile; }); const fileDropEvent = createEvent.drop(element, { dataTransfer: { files: mockFiles }, }); fireEvent(element, fileDropEvent); }; describe('rendering', () => { it('shows dropzone content', () => { const { getByText } = renderWithTheme( ); expect(getByText('Drap and Drop files here')).toBeInTheDocument(); expect( getByText( 'Please only use these following file formats: .JPG, .JPEG, .PNG' ) ).toBeInTheDocument(); }); }); describe('interaction', () => { describe('dropping valid files', () => { it('allows to drop valid files into the dropzone', () => { const onAccept = jest.fn(); const onReject = jest.fn(); const { getByText } = renderWithTheme( ); fireDropFileEvent(getByText('Drap and Drop files here'), [ { name: 'test.png', type: 'image/png', size: 100 * 1024, }, ]); expect(onAccept).toHaveBeenCalledWith([expect.any(File)]); expect(onReject).not.toHaveBeenCalled(); }); it('allows to drop MULTIPLE valid files into the dropzone', () => { const onAccept = jest.fn(); const onReject = jest.fn(); const { getByText } = renderWithTheme( ); fireDropFileEvent(getByText('Drap and Drop files here'), [ { name: 'test1.png', type: 'image/jpg', size: 100 * 1024, }, { name: 'test2.png', type: 'image/jpg', size: 200 * 1024, }, ]); expect(onAccept).toHaveBeenCalledWith([ expect.any(File), expect.any(File), ]); expect(onReject).not.toHaveBeenCalled(); }); it('selects ONE file when dropping multiple files into single dropzone file input', () => { const onAccept = jest.fn(); const onReject = jest.fn(); const { getByText } = renderWithTheme( ); fireDropFileEvent(getByText('Drap and Drop files here'), [ { name: 'test1.png', type: 'image/jpg', size: 100 * 1024, }, { name: 'test2.png', type: 'image/jpg', size: 200 * 1024, }, ]); expect(onAccept).toHaveBeenCalledWith([expect.any(File)]); expect(onReject).not.toHaveBeenCalled(); }); }); describe('dropping invalid files', () => { it('DOES NOT allow to drop invalid file type into the dropzone', () => { const onAccept = jest.fn(); const onReject = jest.fn(); const { getByText } = renderWithTheme( ); fireDropFileEvent(getByText('Drap and Drop files here'), [ { name: 'test.gzip', type: 'application/gzip', size: 100 * 1024, }, ]); expect(onReject).toHaveBeenCalledWith([ expect.objectContaining({ file: expect.any(File), reason: 'format-not-allowed', }), ]); expect(onAccept).not.toHaveBeenCalled(); }); it('DOES NOT allow to drop invalid file size into the dropzone', () => { const onAccept = jest.fn(); const onReject = jest.fn(); const { getByText } = renderWithTheme( ); fireDropFileEvent(getByText('Drap and Drop files here'), [ { name: 'test.png', type: 'image/png', size: 1025, }, ]); expect(onReject).toHaveBeenCalledWith([ expect.objectContaining({ file: expect.any(File), reason: 'size-limit-exceeded', }), ]); expect(onAccept).not.toHaveBeenCalled(); }); }); describe('dropping mixing invalid & valid files', () => { it('allows to drop valid files but NOT invalid ones type into the dropzone', () => { const onAccept = jest.fn(); const onReject = jest.fn(); const { getByText } = renderWithTheme( ); fireDropFileEvent(getByText('Drap and Drop files here'), [ { name: 'test.gzip', type: 'application/gzip', size: 1024, }, { name: 'test.jpg', type: 'image/jpg', size: 1024, }, { name: 'test.gzip', type: 'application/gzip', size: 1025, }, { name: 'test.png', type: 'image/png', size: 1025, }, ]); expect(onReject).toHaveBeenCalledWith([ expect.objectContaining({ file: expect.any(File), reason: 'format-not-allowed', }), expect.objectContaining({ file: expect.any(File), reason: 'format-not-allowed', }), expect.objectContaining({ file: expect.any(File), reason: 'size-limit-exceeded', }), ]); expect(onAccept).toHaveBeenCalledWith([expect.any(File)]); }); }); });