/* eslint react/prop-types: 0, jsx-a11y/label-has-for: 0 */ import React, { createRef } from 'react' import { act, cleanup, fireEvent, render, waitFor } from '@testing-library/react' import { renderHook } from '@testing-library/react-hooks' import { fromEvent } from 'file-selector' import * as utils from './utils' import Dropzone, { useDropzone } from './index' describe('useDropzone() hook', () => { let files let images beforeEach(() => { files = [createFile('file1.pdf', 1111, 'application/pdf')] images = [createFile('cats.gif', 1234, 'image/gif'), createFile('dogs.gif', 2345, 'image/jpeg')] }) afterEach(cleanup) describe('behavior', () => { it('renders the root and input nodes with the necessary props', () => { const { container } = render( {({ getRootProps, getInputProps }) => (
)}
) expect(container.innerHTML).toMatchSnapshot() }) it('sets {accept} prop on the ', () => { const accept = 'image/jpeg' const { container } = render( {({ getRootProps, getInputProps }) => (
)}
) const input = container.querySelector('input') expect(input).toHaveAttribute('accept', accept) }) it('updates {multiple} prop on the when it changes', () => { const { container, rerender } = render( {({ getRootProps, getInputProps }) => (
)}
) expect(container.querySelector('input')).toHaveAttribute('accept', 'image/jpeg') rerender( {({ getRootProps, getInputProps }) => (
)}
) expect(container.querySelector('input')).toHaveAttribute('accept', 'image/png') }) it('sets {multiple} prop on the ', () => { const { container } = render( {({ getRootProps, getInputProps }) => (
)}
) const input = container.querySelector('input') expect(input).toHaveAttribute('multiple') }) it('updates {multiple} prop on the when it changes', () => { const { container, rerender } = render( {({ getRootProps, getInputProps }) => (
)}
) expect(container.querySelector('input')).not.toHaveAttribute('multiple') rerender( {({ getRootProps, getInputProps }) => (
)}
) expect(container.querySelector('input')).toHaveAttribute('multiple') }) it('sets any props passed to the input props getter on the ', () => { const name = 'dropzone-input' const { container } = render( {({ getRootProps, getInputProps }) => (
)}
) const input = container.querySelector('input') expect(input).toHaveAttribute('name', name) }) it('sets any props passed to the root props getter on the root node', () => { const ariaLabel = 'Dropzone area' const { container } = render( {({ getRootProps, getInputProps }) => (
)}
) const dropzone = container.querySelector('div') expect(dropzone).toHaveAttribute('aria-label', ariaLabel) }) it('runs the custom callback handlers provided to the root props getter', async () => { const event = createDtWithFiles(files) const rootProps = { onClick: jest.fn(), onKeyDown: jest.fn(), onFocus: jest.fn(), onBlur: jest.fn(), onDragEnter: jest.fn(), onDragOver: jest.fn(), onDragLeave: jest.fn(), onDrop: jest.fn() } const ui = ( {({ getRootProps, getInputProps }) => (
)}
) const { container, rerender } = render(ui) const dropzone = container.querySelector('div') fireEvent.click(dropzone) expect(rootProps.onClick).toHaveBeenCalled() fireEvent.focus(dropzone) fireEvent.keyDown(dropzone) expect(rootProps.onFocus).toHaveBeenCalled() expect(rootProps.onKeyDown).toHaveBeenCalled() fireEvent.blur(dropzone) expect(rootProps.onBlur).toHaveBeenCalled() fireEvent.dragEnter(dropzone, event) await flushPromises(rerender, ui) expect(rootProps.onDragEnter).toHaveBeenCalled() fireEvent.dragOver(dropzone, event) expect(rootProps.onDragOver).toHaveBeenCalled() fireEvent.dragLeave(dropzone, event) expect(rootProps.onDragLeave).toHaveBeenCalled() fireEvent.drop(dropzone, event) await flushPromises(rerender, ui) expect(rootProps.onDrop).toHaveBeenCalled() }) it('runs the custom callback handlers provided to the input props getter', async () => { const inputProps = { onClick: jest.fn(), onChange: jest.fn() } const ui = ( {({ getRootProps, getInputProps }) => (
)}
) const { container, rerender } = render(ui) const input = container.querySelector('input') fireEvent.click(input) await flushPromises(rerender, ui) expect(inputProps.onClick).toHaveBeenCalled() fireEvent.change(input) await flushPromises(rerender, ui) expect(inputProps.onChange).toHaveBeenCalled() }) it('runs no callback handlers if {disabled} is true', () => { const event = createDtWithFiles(files) const rootProps = { onClick: jest.fn(), onKeyDown: jest.fn(), onFocus: jest.fn(), onBlur: jest.fn(), onDragEnter: jest.fn(), onDragOver: jest.fn(), onDragLeave: jest.fn(), onDrop: jest.fn() } const inputProps = { onClick: jest.fn(), onChange: jest.fn() } const { container } = render( {({ getRootProps, getInputProps }) => (
)}
) const dropzone = container.querySelector('div') fireEvent.click(dropzone) expect(rootProps.onClick).not.toHaveBeenCalled() fireEvent.focus(dropzone) fireEvent.keyDown(dropzone) expect(rootProps.onFocus).not.toHaveBeenCalled() expect(rootProps.onKeyDown).not.toHaveBeenCalled() fireEvent.blur(dropzone) expect(rootProps.onBlur).not.toHaveBeenCalled() fireEvent.dragEnter(dropzone, event) expect(rootProps.onDragEnter).not.toHaveBeenCalled() fireEvent.dragOver(dropzone, event) expect(rootProps.onDragOver).not.toHaveBeenCalled() fireEvent.dragLeave(dropzone, event) expect(rootProps.onDragLeave).not.toHaveBeenCalled() fireEvent.drop(dropzone, event) expect(rootProps.onDrop).not.toHaveBeenCalled() const input = container.querySelector('input') fireEvent.click(input) expect(inputProps.onClick).not.toHaveBeenCalled() fireEvent.change(input) expect(inputProps.onChange).not.toHaveBeenCalled() }) test('{rootRef, inputRef} are exposed', () => { const { result } = renderHook(() => useDropzone()) const { rootRef, inputRef, getRootProps, getInputProps } = result.current const { container } = render(
) expect(container.querySelector('div')).toEqual(rootRef.current) expect(container.querySelector('input')).toEqual(inputRef.current) }) test(' exposes and sets the ref if using a ref object', () => { const dropzoneRef = createRef() const onClickSpy = jest.spyOn(HTMLInputElement.prototype, 'click') const ui = ( {({ getRootProps, getInputProps, isFocused }) => (
{isFocused &&
}
)} ) const { rerender } = render(ui) expect(dropzoneRef.current).not.toBeNull() expect(typeof dropzoneRef.current.open).toEqual('function') act(() => dropzoneRef.current.open()) expect(onClickSpy).toHaveBeenCalled() rerender(null) expect(dropzoneRef.current).toBeNull() }) test(' exposes and sets the ref if using a ref fn', () => { let dropzoneRef const setRef = ref => (dropzoneRef = ref) const onClickSpy = jest.spyOn(HTMLInputElement.prototype, 'click') const ui = ( {({ getRootProps, getInputProps, isFocused }) => (
{isFocused &&
}
)} ) const { rerender } = render(ui) expect(dropzoneRef).not.toBeNull() expect(typeof dropzoneRef.open).toEqual('function') act(() => dropzoneRef.open()) expect(onClickSpy).toHaveBeenCalled() rerender(null) expect(dropzoneRef).toBeNull() }) test(" doesn't invoke the ref fn if it hasn't changed", () => { const setRef = jest.fn() const { rerender } = render( {({ getRootProps, getInputProps }) => (
)}
) rerender( {({ getRootProps }) =>
} ) expect(setRef).toHaveBeenCalledTimes(1) }) it('sets {isFocused} to false if {disabled} is true', () => { const { container, rerender } = render( {({ getRootProps, getInputProps, isFocused }) => (
{isFocused &&
}
)} ) const dropzone = container.querySelector('div') fireEvent.focus(dropzone) expect(dropzone.querySelector('#focus')).not.toBeNull() rerender( {({ getRootProps, getInputProps, isFocused }) => (
{isFocused &&
}
)} ) expect(dropzone.querySelector('#focus')).toBeNull() }) test('{tabindex} is 0 if {disabled} is false', () => { const { container } = render( {({ getRootProps, getInputProps }) => (
)}
) expect(container.querySelector('div')).toHaveAttribute('tabindex', '0') }) test('{tabindex} is not set if {disabled} is true', () => { const { container, rerender } = render( {({ getRootProps, getInputProps }) => (
)}
) expect(container.querySelector('div')).toHaveAttribute('tabindex', '0') rerender( {({ getRootProps, getInputProps }) => (
)}
) expect(container.querySelector('div')).not.toHaveAttribute('tabindex') }) test('{tabindex} is not set if {noKeyboard} is true', () => { const { container, rerender } = render( {({ getRootProps, getInputProps }) => (
)}
) expect(container.querySelector('div')).toHaveAttribute('tabindex', '0') rerender( {({ getRootProps, getInputProps }) => (
)}
) expect(container.querySelector('div')).not.toHaveAttribute('tabindex') }) test('refs are set when {refKey} is set to a different value', done => { const data = createDtWithFiles(files) class MyView extends React.Component { render() { const { children, innerRef, ...rest } = this.props return (
{children}
) } } const ui = ( {({ getRootProps }) => ( Drop some files here ... )} ) const { container, rerender } = render(ui) const dropzone = container.querySelector('#dropzone') const fn = async () => { fireDrop(dropzone, data) await flushPromises(rerender, ui) done() } expect(fn).not.toThrow() }) test('click events originating from