Skip to content

Commit

Permalink
fix: fix regression in PRs #673 and #695
Browse files Browse the repository at this point in the history
- do not use synthetic default imports in typings, close #696
- invoke onDrop when called from input change, close #698
- add more tests to increase coverage
  • Loading branch information
rolandjitsu committed Oct 14, 2018
1 parent bb26403 commit 4578f1b
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/index.js
Expand Up @@ -248,7 +248,7 @@ class Dropzone extends React.Component {
// this is so react can handle state changes in the onClick prop above above
// see: https://github.com/react-dropzone/react-dropzone/issues/450
if (isIeOrEdge()) {
setTimeout(this.open.bind(this), 0)
setTimeout(this.open, 0)
} else {
this.open()
}
Expand Down
42 changes: 40 additions & 2 deletions src/index.spec.js
Expand Up @@ -5,7 +5,7 @@ import React from 'react'
import { mount, render } from 'enzyme'
import { fromEvent } from 'file-selector'
import styles from './utils/styles'
import { onDocumentDragOver } from './utils'
import * as utils from './utils'

const flushPromises = wrapper =>
new Promise(resolve =>
Expand Down Expand Up @@ -170,7 +170,7 @@ describe('Dropzone', () => {
</Dropzone>
)

onDocumentDragOver(event)
utils.onDocumentDragOver(event)
expect(event.preventDefault).toHaveBeenCalledTimes(1)
event.preventDefault.mockClear()

Expand Down Expand Up @@ -331,6 +331,20 @@ describe('Dropzone', () => {
component.simulate('click')
expect(onClick).toHaveBeenCalledWith(expect.any(MouseEvent))
})

it('should schedule open() on next tick when Edge', () => {
const isIeOrEdgeSpy = jest.spyOn(utils, 'isIeOrEdge').mockReturnValueOnce(true)
const setTimeoutSpy = jest.spyOn(window, 'setTimeout').mockImplementationOnce(open => open())

const dropzone = mount(<Dropzone />)
const open = jest.spyOn(dropzone.instance(), 'open')
dropzone.simulate('click')

expect(setTimeoutSpy).toHaveBeenCalled()
expect(open).toHaveBeenCalled()
isIeOrEdgeSpy.mockClear()
setTimeoutSpy.mockClear()
})
})

describe('drag-n-drop', async () => {
Expand Down Expand Up @@ -763,6 +777,30 @@ describe('Dropzone', () => {
expect(click).toHaveBeenCalled()
})

it('invokes onDop cb when native file section occurs', async () => {
const props = {
onDrop: jest.fn(),
onDropAccepted: jest.fn(),
onDropRejected: jest.fn()
}

const component = mount(<Dropzone {...props} />)

const input = component.find('input')
const evt = {
target: { files },
preventDefault() {},
persist() {}
}
input.props().onChange(evt)

await flushPromises(component)

expect(props.onDrop).toHaveBeenCalledWith(evt.target.files, [], evt)
expect(props.onDropAccepted).toHaveBeenCalledWith(evt.target.files, evt)
expect(props.onDropRejected).not.toHaveBeenCalled()
})

describe('onDrop', () => {
const expectedEvent = expect.anything()
const onDrop = jest.fn()
Expand Down
5 changes: 4 additions & 1 deletion src/utils/index.js
Expand Up @@ -42,6 +42,9 @@ export function allFilesAccepted(files, accept) {
}

export function isDragDataWithFiles(evt) {
if (!evt.dataTransfer) {
return true
}
// https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/types
// https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types#file
return Array.prototype.every.call(
Expand All @@ -51,7 +54,7 @@ export function isDragDataWithFiles(evt) {
}

export function isKindFile(item) {
return typeof item === 'object' && item.kind === 'file'
return typeof item === 'object' && item !== null && item.kind === 'file'
}

// allow the entire document to be a drag target
Expand Down
15 changes: 14 additions & 1 deletion src/utils/index.spec.js
@@ -1,4 +1,4 @@
import { getDataTransferItems, isIeOrEdge, isDragDataWithFiles } from './'
import { getDataTransferItems, isIeOrEdge, isKindFile, isDragDataWithFiles } from './'

const files = [
{
Expand Down Expand Up @@ -124,6 +124,15 @@ describe('isIeOrEdge', () => {
})
})

describe('isKindFile()', () => {
it('should return true for DataTransferItem of kind "file"', () => {
expect(isKindFile({ kind: 'file' })).toBe(true)
expect(isKindFile({ kind: 'text/html' })).toBe(false)
expect(isKindFile({})).toBe(false)
expect(isKindFile(null)).toBe(false)
})
})

describe('isDragDataWithFiles()', () => {
it('should return true if every dragged type is a file', () => {
expect(isDragDataWithFiles({ dataTransfer: { types: ['Files'] } })).toBe(true)
Expand All @@ -142,4 +151,8 @@ describe('isDragDataWithFiles()', () => {
})
).toBe(false)
})

it('should return true if {dataTransfer} is not defined', () => {
expect(isDragDataWithFiles({})).toBe(true)
})
})
27 changes: 10 additions & 17 deletions typings/react-dropzone.d.ts
@@ -1,11 +1,4 @@
import React, {
CSSProperties,
Component,
InputHTMLAttributes,
HTMLProps,
ReactNode,
Ref
} from "react";
import * as React from "react";

export interface FileWithPreview extends File {
preview?: string;
Expand Down Expand Up @@ -35,31 +28,31 @@ export type DropzoneRenderFunction = (x: DropzoneRenderArgs) => JSX.Element;

type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;

export type DropzoneProps = Omit<HTMLProps<HTMLDivElement>, "onDrop" | "ref"> & {
export type DropzoneProps = Omit<React.HTMLProps<HTMLDivElement>, "onDrop" | "ref"> & {
disableClick?: boolean;
disabled?: boolean;
disablePreview?: boolean;
preventDropOnDocument?: boolean;
inputProps?: InputHTMLAttributes<HTMLInputElement>;
inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
maxSize?: number;
minSize?: number;
activeClassName?: string;
acceptClassName?: string;
rejectClassName?: string;
disabledClassName?: string;
activeStyle?: CSSProperties;
acceptStyle?: CSSProperties;
rejectStyle?: CSSProperties;
disabledStyle?: CSSProperties;
activeStyle?: React.CSSProperties;
acceptStyle?: React.CSSProperties;
rejectStyle?: React.CSSProperties;
disabledStyle?: React.CSSProperties;
onDrop?: DropFilesEventHandler;
onDropAccepted?: DropFileEventHandler;
onDropRejected?: DropFileEventHandler;
onFileDialogCancel?(): void;
getDataTransferItems?(event: React.DragEvent<HTMLDivElement> | DragEvent): Promise<Array<File | DataTransferItem>>;
children?: ReactNode | DropzoneRenderFunction;
ref?: Ref<Dropzone>;
children?: React.ReactNode | DropzoneRenderFunction;
ref?: React.Ref<Dropzone>;
};

export default class Dropzone extends Component<DropzoneProps> {
export default class Dropzone extends React.Component<DropzoneProps> {
open: () => void;
}

0 comments on commit 4578f1b

Please sign in to comment.