react-dropzone 5.0.0 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.spec.js CHANGED
@@ -1,9 +1,18 @@
1
+ /* eslint jsx-a11y/click-events-have-key-events: 0 */
2
+ /* eslint jsx-a11y/no-static-element-interactions: 0 */
3
+
1
4
  import React from 'react'
2
5
  import { mount, render } from 'enzyme'
3
- import { spy, stub } from 'sinon'
4
6
  import { onDocumentDragOver } from './utils'
5
7
 
6
- const Dropzone = require(process.env.JEST_TARGET ? process.env.JEST_TARGET : './index') // eslint-disable-line import/no-dynamic-require
8
+ const flushPromises = wrapper =>
9
+ new Promise(resolve =>
10
+ global.setImmediate(() => {
11
+ wrapper.update()
12
+ resolve(wrapper)
13
+ })
14
+ )
15
+ const Dropzone = require('./index')
7
16
  const DummyChildComponent = () => null
8
17
 
9
18
  let files
@@ -85,14 +94,15 @@ describe('Dropzone', () => {
85
94
 
86
95
  it('applies the accept prop to the child input', () => {
87
96
  const component = render(<Dropzone className="my-dropzone" accept="image/jpeg" />)
88
- expect(component.find('.my-dropzone').attr()).not.toContain('accept')
97
+
98
+ expect(component.attr()).not.toContain('accept')
89
99
  expect(Object.keys(component.find('input').attr())).toContain('accept')
90
100
  expect(component.find('input').attr('accept')).toEqual('image/jpeg')
91
101
  })
92
102
 
93
103
  it('applies the name prop to the child input', () => {
94
104
  const component = render(<Dropzone className="my-dropzone" name="test-file-input" />)
95
- expect(component.find('.my-dropzone').attr()).not.toContain('name')
105
+ expect(component.attr()).not.toContain('name')
96
106
  expect(Object.keys(component.find('input').attr())).toContain('name')
97
107
  expect(component.find('input').attr('name')).toEqual('test-file-input')
98
108
  })
@@ -106,40 +116,30 @@ describe('Dropzone', () => {
106
116
  })
107
117
 
108
118
  describe('document drop protection', () => {
109
- let dropzone
110
- let addEventCalls
111
- let savedAddEventListener
112
- let savedRemoveEventListener
113
-
114
- beforeEach(() => {
115
- savedAddEventListener = document.addEventListener
116
- savedRemoveEventListener = document.removeEventListener
117
- document.addEventListener = spy()
118
- document.removeEventListener = spy()
119
- })
120
-
121
- afterEach(() => {
122
- document.addEventListener = savedAddEventListener
123
- document.removeEventListener = savedRemoveEventListener
124
- })
119
+ const event = { preventDefault: jest.fn() }
120
+ const onAddEventListener = jest.spyOn(document, 'addEventListener')
121
+ const onRemoveEventListener = jest.spyOn(document, 'removeEventListener')
125
122
 
126
123
  // Collect the list of addEventListener/removeEventListener spy calls into an object keyed by event name.
127
124
  function collectEventListenerCalls(calls) {
128
- return calls.reduce((acc, [eventName, ...rest]) => {
129
- acc[eventName] = rest // eslint-disable-line no-param-reassign
130
- return acc
131
- }, {})
125
+ return calls.reduce(
126
+ (acc, [eventName, ...rest]) => ({
127
+ ...acc,
128
+ [eventName]: rest
129
+ }),
130
+ {}
131
+ )
132
132
  }
133
133
 
134
134
  it('installs hooks to prevent stray drops from taking over the browser window', () => {
135
- dropzone = mount(
135
+ const dropzone = mount(
136
136
  <Dropzone>
137
137
  <p>Content</p>
138
138
  </Dropzone>
139
139
  )
140
140
  expect(dropzone.html()).toMatchSnapshot()
141
- expect(document.addEventListener.callCount).toEqual(2)
142
- addEventCalls = collectEventListenerCalls(document.addEventListener.args)
141
+ expect(onAddEventListener).toHaveBeenCalledTimes(2)
142
+ const addEventCalls = collectEventListenerCalls(onAddEventListener.mock.calls)
143
143
  Object.keys(addEventCalls).forEach(eventName => {
144
144
  expect(addEventCalls[eventName][0]).toBeDefined()
145
145
  expect(addEventCalls[eventName][1]).toBe(false)
@@ -147,71 +147,82 @@ describe('Dropzone', () => {
147
147
  })
148
148
 
149
149
  it('terminates drags and drops on elements outside our dropzone', () => {
150
- const event = { preventDefault: spy() }
150
+ const dropzone = mount(
151
+ <Dropzone>
152
+ <p>Content</p>
153
+ </Dropzone>
154
+ )
155
+
151
156
  onDocumentDragOver(event)
152
- expect(event.preventDefault.callCount).toEqual(1)
153
- event.preventDefault.reset()
157
+ expect(event.preventDefault).toHaveBeenCalledTimes(1)
158
+ event.preventDefault.mockClear()
154
159
 
155
- dropzone.getNode().onDocumentDrop(event)
156
- expect(event.preventDefault.callCount).toEqual(1)
160
+ dropzone.instance().onDocumentDrop(event)
161
+ expect(event.preventDefault).toHaveBeenCalledTimes(1)
157
162
  })
158
163
 
159
164
  it('permits drags and drops on elements inside our dropzone', () => {
165
+ const dropzone = mount(
166
+ <Dropzone>
167
+ <p>Content</p>
168
+ </Dropzone>
169
+ )
170
+
160
171
  const instanceEvent = {
161
- preventDefault: spy(),
172
+ preventDefault: jest.fn(),
162
173
  target: dropzone.getDOMNode()
163
174
  }
164
- dropzone.getNode().onDocumentDrop(instanceEvent)
165
- expect(instanceEvent.preventDefault.callCount).toEqual(0)
175
+ dropzone.instance().onDocumentDrop(instanceEvent)
176
+ expect(instanceEvent.preventDefault).not.toHaveBeenCalled()
166
177
  })
167
178
 
168
179
  it('removes document hooks when unmounted', () => {
180
+ const dropzone = mount(
181
+ <Dropzone>
182
+ <p>Content</p>
183
+ </Dropzone>
184
+ )
169
185
  dropzone.unmount()
170
- expect(document.removeEventListener.callCount).toEqual(2)
171
- const removeEventCalls = collectEventListenerCalls(document.removeEventListener.args)
186
+ expect(onRemoveEventListener).toHaveBeenCalledTimes(2)
187
+ const addEventCalls = collectEventListenerCalls(onAddEventListener.mock.calls)
188
+ const removeEventCalls = collectEventListenerCalls(onRemoveEventListener.mock.calls)
172
189
  Object.keys(addEventCalls).forEach(eventName => {
173
190
  expect(removeEventCalls[eventName][0]).toEqual(addEventCalls[eventName][0])
174
191
  })
175
192
  })
176
193
 
177
194
  it('does not prevent stray drops when preventDropOnDocument is false', () => {
178
- dropzone = mount(<Dropzone preventDropOnDocument={false} />)
195
+ const dropzone = mount(<Dropzone preventDropOnDocument={false} />)
179
196
  expect(dropzone.html()).toMatchSnapshot()
180
- expect(document.addEventListener.callCount).toEqual(0)
197
+ expect(onAddEventListener).not.toHaveBeenCalled()
181
198
 
182
199
  dropzone.unmount()
183
- expect(document.removeEventListener.callCount).toEqual(0)
200
+ expect(onRemoveEventListener).not.toHaveBeenCalled()
184
201
  })
185
202
  })
186
203
 
187
204
  describe('onClick', () => {
188
- it('should call `open` method', done => {
205
+ it('should call `open` method', () => {
189
206
  const dropzone = mount(<Dropzone />)
190
- spy(dropzone.instance(), 'open')
207
+ const open = jest.spyOn(dropzone.instance(), 'open')
191
208
  dropzone.simulate('click')
192
- setTimeout(() => {
193
- expect(dropzone.instance().open.callCount).toEqual(1)
194
- done()
195
- }, 0)
209
+ expect(open).toHaveBeenCalled()
196
210
  })
197
211
 
198
212
  it('should not call `open` if disableClick prop is true', () => {
199
213
  const dropzone = mount(<Dropzone disableClick />)
200
- spy(dropzone.instance(), 'open')
214
+ const open = jest.spyOn(dropzone.instance(), 'open')
201
215
  dropzone.simulate('click')
202
- expect(dropzone.instance().open.callCount).toEqual(0)
216
+ expect(open).not.toHaveBeenCalled()
203
217
  })
204
218
 
205
- it('should call `onClick` callback if provided', done => {
206
- const clickSpy = spy()
207
- const dropzone = mount(<Dropzone onClick={clickSpy} />)
208
- spy(dropzone.instance(), 'open')
219
+ it('should call `onClick` callback if provided', () => {
220
+ const onClick = jest.fn()
221
+ const dropzone = mount(<Dropzone onClick={onClick} />)
222
+ const open = jest.spyOn(dropzone.instance(), 'open')
209
223
  dropzone.simulate('click')
210
- setTimeout(() => {
211
- expect(dropzone.instance().open.callCount).toEqual(1)
212
- expect(clickSpy.callCount).toEqual(1)
213
- done()
214
- }, 0)
224
+ expect(open).toHaveBeenCalled()
225
+ expect(onClick).toHaveBeenCalled()
215
226
  })
216
227
 
217
228
  it('should reset the value of input', () => {
@@ -237,97 +248,82 @@ describe('Dropzone', () => {
237
248
  ).toBeUndefined()
238
249
  })
239
250
 
240
- it('should trigger click even on the input', done => {
251
+ it('should trigger click even on the input', () => {
241
252
  const dropzone = mount(<Dropzone />)
242
- const clickSpy = spy(dropzone.instance().fileInputEl, 'click')
253
+ const onFileInputClick = jest.spyOn(dropzone.instance().fileInputEl, 'click')
243
254
  dropzone.simulate('click')
244
255
  dropzone.simulate('click')
245
- setTimeout(() => {
246
- expect(clickSpy.callCount).toEqual(2)
247
- done()
248
- }, 0)
256
+ expect(onFileInputClick).toHaveBeenCalledTimes(2)
249
257
  })
250
258
 
251
259
  it('should not invoke onClick on the wrapper', () => {
252
- const onClickOuterSpy = spy()
253
- const onClickInnerSpy = spy()
260
+ const onClickOuter = jest.fn()
261
+ const onClickInner = jest.fn()
254
262
  const component = mount(
255
- <div onClick={onClickOuterSpy}>
256
- <Dropzone onClick={onClickInnerSpy} />
263
+ <div onClick={onClickOuter}>
264
+ <Dropzone onClick={onClickInner} />
257
265
  </div>
258
266
  )
259
267
 
260
268
  component.simulate('click')
261
- expect(onClickOuterSpy.callCount).toEqual(1)
262
- expect(onClickInnerSpy.callCount).toEqual(0)
269
+ expect(onClickOuter).toHaveBeenCalled()
270
+ expect(onClickInner).not.toHaveBeenCalled()
263
271
 
264
- onClickOuterSpy.reset()
265
- onClickInnerSpy.reset()
272
+ onClickOuter.mockClear()
273
+ onClickInner.mockClear()
266
274
 
267
275
  component.find(Dropzone).simulate('click')
268
- expect(onClickOuterSpy.callCount).toEqual(0)
269
- expect(onClickInnerSpy.callCount).toEqual(1)
276
+ expect(onClickOuter).not.toHaveBeenCalled()
277
+ expect(onClickInner).toHaveBeenCalled()
270
278
  })
271
279
 
272
280
  it('should invoke onClick on the wrapper if disableClick is set', () => {
273
- const onClickOuterSpy = spy()
281
+ const onClick = jest.fn()
274
282
  const component = mount(
275
- <div onClick={onClickOuterSpy}>
283
+ <div onClick={onClick}>
276
284
  <Dropzone disableClick />
277
285
  </div>
278
286
  )
279
287
 
280
288
  component.find(Dropzone).simulate('click')
281
- expect(onClickOuterSpy.callCount).toEqual(1)
289
+ expect(onClick).toHaveBeenCalled()
282
290
  })
283
291
 
284
- it('should invoke inputProps onClick if provided', done => {
285
- const inputPropsClickSpy = spy()
286
- const component = mount(<Dropzone inputProps={{ onClick: inputPropsClickSpy }} />)
292
+ it('should invoke inputProps onClick if provided', () => {
293
+ const onClick = jest.fn()
294
+ const component = mount(<Dropzone inputProps={{ onClick }} />)
287
295
 
288
296
  component.simulate('click')
289
- setTimeout(() => {
290
- expect(inputPropsClickSpy.callCount).toEqual(1)
291
- done()
292
- }, 0)
297
+ expect(onClick).toHaveBeenCalled()
293
298
  })
294
299
  })
295
300
 
296
301
  describe('drag-n-drop', () => {
297
302
  it('should override onDrag* methods', () => {
298
- const dragStartSpy = spy()
299
- const dragEnterSpy = spy()
300
- const dragOverSpy = spy()
301
- const dragLeaveSpy = spy()
302
- const component = mount(
303
- <Dropzone
304
- onDragStart={dragStartSpy}
305
- onDragEnter={dragEnterSpy}
306
- onDragOver={dragOverSpy}
307
- onDragLeave={dragLeaveSpy}
308
- />
309
- )
303
+ const props = {
304
+ onDragStart: jest.fn(),
305
+ onDragEnter: jest.fn(),
306
+ onDragOver: jest.fn(),
307
+ onDragLeave: jest.fn()
308
+ }
309
+ const component = mount(<Dropzone {...props} />)
310
310
  component.simulate('dragStart')
311
+ expect(props.onDragStart).toHaveBeenCalled()
311
312
  component.simulate('dragEnter', { dataTransfer: { items: files } })
313
+ expect(props.onDragEnter).toHaveBeenCalled()
312
314
  component.simulate('dragOver', { dataTransfer: { items: files } })
315
+ expect(props.onDragOver).toHaveBeenCalled()
313
316
  component.simulate('dragLeave', { dataTransfer: { items: files } })
314
- expect(dragStartSpy.callCount).toEqual(1)
315
- expect(dragEnterSpy.callCount).toEqual(1)
316
- expect(dragOverSpy.callCount).toEqual(1)
317
- expect(dragLeaveSpy.callCount).toEqual(1)
317
+ expect(props.onDragLeave).toHaveBeenCalled()
318
318
  })
319
319
 
320
320
  it('should guard dropEffect in onDragOver for IE', () => {
321
- const dragStartSpy = spy()
322
- const dragEnterSpy = spy()
323
- const dragLeaveSpy = spy()
324
- const component = mount(
325
- <Dropzone
326
- onDragStart={dragStartSpy}
327
- onDragEnter={dragEnterSpy}
328
- onDragLeave={dragLeaveSpy}
329
- />
330
- )
321
+ const props = {
322
+ onDragStart: jest.fn(),
323
+ onDragEnter: jest.fn(),
324
+ onDragLeave: jest.fn()
325
+ }
326
+ const component = mount(<Dropzone {...props} />)
331
327
 
332
328
  // Using Proxy we'll emulate IE throwing when setting dataTransfer.dropEffect
333
329
  const eventProxy = new Proxy(
@@ -345,26 +341,29 @@ describe('Dropzone', () => {
345
341
  )
346
342
 
347
343
  // And using then we'll call the onDragOver with the proxy instead of event
348
- const dragOverSpy = stub(component.instance(), 'onDragOver').callsFake(
349
- component.instance().onDragOver(eventProxy)
350
- )
344
+ const componentOnDragOver = component.instance().onDragOver
345
+ const onDragOver = jest
346
+ .spyOn(component.instance(), 'onDragOver')
347
+ .mockImplementation(() => componentOnDragOver(eventProxy))
351
348
 
352
349
  component.simulate('dragStart', { dataTransfer: { items: files } })
350
+ expect(props.onDragStart).toHaveBeenCalled()
353
351
  component.simulate('dragEnter', { dataTransfer: { items: files } })
354
- component.simulate('dragOver', { dataTransfer: { items: files } })
352
+ expect(props.onDragEnter).toHaveBeenCalled()
355
353
  component.simulate('dragLeave', { dataTransfer: { items: files } })
356
- expect(dragStartSpy.callCount).toEqual(1)
357
- expect(dragEnterSpy.callCount).toEqual(1)
358
- expect(dragLeaveSpy.callCount).toEqual(1)
354
+ expect(props.onDragLeave).toHaveBeenCalled()
359
355
  // It should not throw the error
360
- expect(dragOverSpy).not.toThrow()
361
- dragOverSpy.restore()
356
+ component.simulate('dragOver', { dataTransfer: { items: files } })
357
+ expect(onDragOver).not.toThrow()
362
358
  })
363
359
 
364
360
  it('should set proper dragActive state on dragEnter', async () => {
365
361
  const dropzone = mount(<Dropzone>{props => <DummyChildComponent {...props} />}</Dropzone>)
366
- const child = dropzone.find(DummyChildComponent)
367
- await dropzone.simulate('dragEnter', { dataTransfer: { files } })
362
+ dropzone.simulate('dragEnter', { dataTransfer: { files } })
363
+
364
+ const updatedDropzone = await flushPromises(dropzone)
365
+ const child = updatedDropzone.find(DummyChildComponent)
366
+
368
367
  expect(child).toHaveProp('isDragActive', true)
369
368
  expect(child).toHaveProp('isDragAccept', true)
370
369
  expect(child).toHaveProp('isDragReject', false)
@@ -374,10 +373,11 @@ describe('Dropzone', () => {
374
373
  const dropzone = mount(
375
374
  <Dropzone accept="image/*">{props => <DummyChildComponent {...props} />}</Dropzone>
376
375
  )
377
- const child = dropzone.find(DummyChildComponent)
378
- await dropzone.simulate('dragEnter', {
376
+ dropzone.simulate('dragEnter', {
379
377
  dataTransfer: { files: files.concat(images) }
380
378
  })
379
+ const updatedDropzone = await flushPromises(dropzone)
380
+ const child = updatedDropzone.find(DummyChildComponent)
381
381
  expect(child).toHaveProp('isDragActive', true)
382
382
  expect(child).toHaveProp('isDragAccept', false)
383
383
  expect(child).toHaveProp('isDragReject', true)
@@ -389,8 +389,9 @@ describe('Dropzone', () => {
389
389
  {props => <DummyChildComponent {...props} />}
390
390
  </Dropzone>
391
391
  )
392
- const child = dropzone.find(DummyChildComponent)
393
- await dropzone.simulate('dragEnter', { dataTransfer: { files } })
392
+ dropzone.simulate('dragEnter', { dataTransfer: { files } })
393
+ const updatedDropzone = await flushPromises(dropzone)
394
+ const child = updatedDropzone.find(DummyChildComponent)
394
395
  expect(child).toHaveProp('isDragActive', true)
395
396
  expect(child).toHaveProp('isDragAccept', false)
396
397
  expect(child).toHaveProp('isDragReject', true)
@@ -402,8 +403,9 @@ describe('Dropzone', () => {
402
403
  {props => <DummyChildComponent {...props} />}
403
404
  </Dropzone>
404
405
  )
405
- const child = dropzone.find(DummyChildComponent)
406
- await dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
406
+ dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
407
+ const updatedDropzone = await flushPromises(dropzone)
408
+ const child = updatedDropzone.find(DummyChildComponent)
407
409
  expect(child).toHaveProp('isDragActive', true)
408
410
  expect(child).toHaveProp('isDragAccept', true)
409
411
  expect(child).toHaveProp('isDragReject', true)
@@ -415,10 +417,16 @@ describe('Dropzone', () => {
415
417
  {props => <DummyChildComponent {...props} />}
416
418
  </Dropzone>
417
419
  )
418
- const child = dropzone.find(DummyChildComponent)
419
- await dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
420
+ dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
421
+ const updatedDropzone = await flushPromises(dropzone)
422
+ const child = updatedDropzone.find(DummyChildComponent)
420
423
  expect(child).toHaveProp('isDragActive', true)
421
- expect(dropzone.hasClass('👏')).toBe(true)
424
+ expect(
425
+ dropzone
426
+ .children()
427
+ .first()
428
+ .hasClass('👏')
429
+ ).toBe(true)
422
430
  })
423
431
 
424
432
  it('should set rejectClassName properly', async () => {
@@ -427,10 +435,16 @@ describe('Dropzone', () => {
427
435
  {props => <DummyChildComponent {...props} />}
428
436
  </Dropzone>
429
437
  )
430
- const child = dropzone.find(DummyChildComponent)
431
- await dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
438
+ dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
439
+ const updatedDropzone = await flushPromises(dropzone)
440
+ const child = updatedDropzone.find(DummyChildComponent)
432
441
  expect(child).toHaveProp('isDragReject', true)
433
- expect(dropzone.hasClass('👎')).toBe(true)
442
+ expect(
443
+ dropzone
444
+ .children()
445
+ .first()
446
+ .hasClass('👎')
447
+ ).toBe(true)
434
448
  })
435
449
 
436
450
  it('should set acceptClassName properly', async () => {
@@ -439,14 +453,20 @@ describe('Dropzone', () => {
439
453
  {props => <DummyChildComponent {...props} />}
440
454
  </Dropzone>
441
455
  )
442
- const child = dropzone.find(DummyChildComponent)
443
- await dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
456
+ dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
457
+ const updatedDropzone = await flushPromises(dropzone)
458
+ const child = updatedDropzone.find(DummyChildComponent)
444
459
  expect(child).toHaveProp('isDragAccept', true)
445
- expect(dropzone.hasClass('👍')).toBe(true)
460
+ expect(
461
+ updatedDropzone
462
+ .children()
463
+ .first()
464
+ .hasClass('👍')
465
+ ).toBe(true)
446
466
  })
447
467
 
448
468
  it('should set disabledClassName properly', () => {
449
- const dropzone = mount(
469
+ const dropzone = render(
450
470
  <Dropzone disabled disabledClassName="🤐">
451
471
  {props => <DummyChildComponent {...props} />}
452
472
  </Dropzone>
@@ -474,8 +494,9 @@ describe('Dropzone', () => {
474
494
  {props => <DummyChildComponent {...props} />}
475
495
  </Dropzone>
476
496
  )
477
- await dropzone.simulate('dragEnter', { dataTransfer: { files: [images[0]] } })
478
- const mainDiv = dropzone.find('div').at(0)
497
+ dropzone.simulate('dragEnter', { dataTransfer: { files: [images[0]] } })
498
+ const updatedDropzone = await flushPromises(dropzone)
499
+ const mainDiv = updatedDropzone.find('div').at(0)
479
500
  expect(mainDiv).toHaveProp('style', { position: 'relative', ...acceptStyle })
480
501
  })
481
502
 
@@ -490,8 +511,9 @@ describe('Dropzone', () => {
490
511
  {props => <DummyChildComponent {...props} />}
491
512
  </Dropzone>
492
513
  )
493
- await dropzone.simulate('dragEnter', { dataTransfer: { files: [files[0]] } })
494
- const mainDiv = dropzone.find('div').at(0)
514
+ dropzone.simulate('dragEnter', { dataTransfer: { files: [files[0]] } })
515
+ const updatedDropzone = await flushPromises(dropzone)
516
+ const mainDiv = updatedDropzone.find('div').at(0)
495
517
  expect(mainDiv).toHaveProp('style', { position: 'relative', ...rejectStyle })
496
518
  })
497
519
 
@@ -506,8 +528,9 @@ describe('Dropzone', () => {
506
528
  {props => <DummyChildComponent {...props} />}
507
529
  </Dropzone>
508
530
  )
509
- await dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
510
- const mainDiv = dropzone.find('div').at(0)
531
+ dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
532
+ const updatedDropzone = await flushPromises(dropzone)
533
+ const mainDiv = updatedDropzone.find('div').at(0)
511
534
  const expectedStyle = {
512
535
  position: 'relative',
513
536
  ...acceptStyle,
@@ -520,16 +543,16 @@ describe('Dropzone', () => {
520
543
  const dropzone = mount(
521
544
  <Dropzone accept="image/*">{props => <DummyChildComponent {...props} />}</Dropzone>
522
545
  )
523
- const child = dropzone.find(DummyChildComponent)
524
- await dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
525
- expect(child).toHaveProp('isDragActive', true)
526
- expect(child).toHaveProp('isDragAccept', true)
527
- expect(child).toHaveProp('isDragReject', false)
546
+ dropzone.simulate('dragEnter', { dataTransfer: { files: images } })
547
+ const updatedDropzone = await flushPromises(dropzone)
548
+ expect(updatedDropzone.find(DummyChildComponent)).toHaveProp('isDragActive', true)
549
+ expect(updatedDropzone.find(DummyChildComponent)).toHaveProp('isDragAccept', true)
550
+ expect(updatedDropzone.find(DummyChildComponent)).toHaveProp('isDragReject', false)
528
551
 
529
552
  dropzone.setProps({ accept: 'text/*' })
530
- expect(child).toHaveProp('isDragActive', true)
531
- expect(child).toHaveProp('isDragAccept', false)
532
- expect(child).toHaveProp('isDragReject', true)
553
+ expect(updatedDropzone.find(DummyChildComponent)).toHaveProp('isDragActive', true)
554
+ expect(updatedDropzone.find(DummyChildComponent)).toHaveProp('isDragAccept', false)
555
+ expect(updatedDropzone.find(DummyChildComponent)).toHaveProp('isDragReject', true)
533
556
  })
534
557
 
535
558
  it('should expose state to children', async () => {
@@ -575,87 +598,76 @@ describe('Dropzone', () => {
575
598
  // make sure we handle any duplicate dragEnter events that the browser may send us
576
599
  await dropzone.simulate('dragEnter', { dataTransfer: { files } })
577
600
  const dragActiveChild = dropzone.find(DragActiveComponent)
578
- expect(dragActiveChild).toBePresent()
601
+ expect(dragActiveChild).toExist()
579
602
  expect(dragActiveChild).toHaveProp('isDragAccept', true)
580
603
  expect(dragActiveChild).toHaveProp('isDragReject', false)
581
604
 
582
605
  dropzone.simulate('dragLeave', { dataTransfer: { files } })
583
- expect(dropzone.find(DragActiveComponent)).toBeEmpty()
584
- expect(child).toHaveProp('isDragAccept', false)
585
- expect(child).toHaveProp('isDragReject', false)
606
+ expect(dropzone.find(DragActiveComponent).children()).toHaveLength(0)
607
+ expect(dropzone.find(ChildComponent)).toHaveProp('isDragAccept', false)
608
+ expect(dropzone.find(ChildComponent)).toHaveProp('isDragReject', false)
586
609
  })
587
610
  })
588
611
 
589
612
  describe('onDrop', () => {
590
- let dropSpy
591
- let dropAcceptedSpy
592
- let dropRejectedSpy
613
+ const expectedEvent = expect.anything()
614
+ const onDrop = jest.fn()
615
+ const onDropAccepted = jest.fn()
616
+ const onDropRejected = jest.fn()
593
617
 
594
- beforeEach(() => {
595
- dropSpy = spy()
596
- dropAcceptedSpy = spy()
597
- dropRejectedSpy = spy()
598
- })
618
+ it('should update the acceptedFiles/rejectedFiles state', async () => {
619
+ let dropzone = mount(
620
+ <Dropzone accept="image/*">{props => <DummyChildComponent {...props} />}</Dropzone>
621
+ )
622
+ dropzone.simulate('drop', { dataTransfer: { files } })
623
+ dropzone = await flushPromises(dropzone)
624
+ expect(dropzone.find(DummyChildComponent)).toHaveProp('acceptedFiles', [])
625
+ expect(dropzone.find(DummyChildComponent)).toHaveProp('rejectedFiles', files)
599
626
 
600
- afterEach(() => {
601
- dropSpy.reset()
602
- dropAcceptedSpy.reset()
603
- dropRejectedSpy.reset()
627
+ dropzone.simulate('drop', { dataTransfer: { files: images } })
628
+ dropzone = await flushPromises(dropzone)
629
+ expect(dropzone.find(DummyChildComponent)).toHaveProp('acceptedFiles', images)
630
+ expect(dropzone.find(DummyChildComponent)).toHaveProp('rejectedFiles', [])
604
631
  })
605
632
 
606
633
  it('should reset the dragActive/dragReject state', async () => {
607
- const dropzone = mount(
608
- <Dropzone
609
- onDrop={dropSpy}
610
- onDropAccepted={dropAcceptedSpy}
611
- onDropRejected={dropRejectedSpy}
612
- >
613
- {props => <DummyChildComponent {...props} />}
614
- </Dropzone>
615
- )
616
- const child = dropzone.find(DummyChildComponent)
617
- await dropzone.simulate('dragEnter', { dataTransfer: { files } })
618
- expect(child).toHaveProp('isDragActive', true)
619
- expect(child).toHaveProp('isDragReject', false)
634
+ let dropzone = mount(<Dropzone>{props => <DummyChildComponent {...props} />}</Dropzone>)
635
+ dropzone.simulate('dragEnter', { dataTransfer: { files } })
636
+ dropzone = await flushPromises(dropzone)
637
+ expect(dropzone.find(DummyChildComponent)).toHaveProp('isDragActive', true)
638
+ expect(dropzone.find(DummyChildComponent)).toHaveProp('isDragReject', false)
620
639
  dropzone.simulate('drop', { dataTransfer: { files } })
621
- expect(child).toHaveProp('isDragActive', false)
622
- expect(child).toHaveProp('isDragReject', false)
640
+ dropzone = await flushPromises(dropzone)
641
+ expect(dropzone.find(DummyChildComponent)).toHaveProp('isDragActive', false)
642
+ expect(dropzone.find(DummyChildComponent)).toHaveProp('isDragReject', false)
623
643
  })
624
644
 
625
645
  it('should reject invalid file when multiple is false', async () => {
626
- const dropzone = mount(<Dropzone accept="image/*" onDrop={dropSpy} multiple={false} />)
646
+ const dropzone = mount(<Dropzone accept="image/*" onDrop={onDrop} multiple={false} />)
627
647
  await dropzone.simulate('drop', {
628
648
  dataTransfer: { files }
629
649
  })
630
- const [accepted, rejected] = dropSpy.firstCall.args
631
- expect(rejected.length).toEqual(1)
632
- expect(accepted.length).toEqual(0)
650
+ expect(onDrop).toHaveBeenCalledWith([], files, expectedEvent)
633
651
  })
634
652
 
635
653
  it('should allow single files to be dropped if multiple is false', async () => {
636
- const dropzone = mount(<Dropzone accept="image/*" onDrop={dropSpy} multiple={false} />)
654
+ const dropzone = mount(<Dropzone accept="image/*" onDrop={onDrop} multiple={false} />)
637
655
 
638
656
  await dropzone.simulate('drop', { dataTransfer: { files: [images[0]] } })
639
- const [accepted, rejected] = dropSpy.firstCall.args
640
- expect(accepted.length).toEqual(1)
641
- expect(rejected.length).toEqual(0)
657
+ expect(onDrop).toHaveBeenCalledWith([images[0]], [], expectedEvent)
642
658
  })
643
659
 
644
660
  it('should reject multiple files to be dropped if multiple is false', async () => {
645
- const dropzone = mount(<Dropzone accept="image/*" onDrop={dropSpy} multiple={false} />)
661
+ const dropzone = mount(<Dropzone accept="image/*" onDrop={onDrop} multiple={false} />)
646
662
 
647
663
  await dropzone.simulate('drop', { dataTransfer: { files: images } })
648
- const [accepted, rejected] = dropSpy.firstCall.args
649
- expect(accepted.length).toEqual(0)
650
- expect(rejected.length).toEqual(2)
664
+ expect(onDrop).toHaveBeenCalledWith([], images, expectedEvent)
651
665
  })
652
666
 
653
667
  it('should take all dropped files if multiple is true', async () => {
654
- const dropzone = mount(<Dropzone onDrop={dropSpy} multiple />)
668
+ const dropzone = mount(<Dropzone onDrop={onDrop} multiple />)
655
669
  await dropzone.simulate('drop', { dataTransfer: { files: images } })
656
- expect(dropSpy.firstCall.args[0]).toHaveLength(2)
657
- expect(dropSpy.firstCall.args[0][0].name).toEqual(images[0].name)
658
- expect(dropSpy.firstCall.args[0][1].name).toEqual(images[1].name)
670
+ expect(onDrop).toHaveBeenCalledWith(images, [], expectedEvent)
659
671
  })
660
672
 
661
673
  it('should set this.isFileDialogActive to false', async () => {
@@ -666,112 +678,90 @@ describe('Dropzone', () => {
666
678
  })
667
679
 
668
680
  it('should always call onDrop callback with accepted and rejected arguments', async () => {
669
- const dropzone = mount(
670
- <Dropzone
671
- onDrop={dropSpy}
672
- onDropAccepted={dropAcceptedSpy}
673
- onDropRejected={dropRejectedSpy}
674
- accept="image/*"
675
- />
676
- )
681
+ const dropzone = mount(<Dropzone onDrop={onDrop} accept="image/*" />)
677
682
  await dropzone.simulate('drop', { dataTransfer: { files } })
678
- expect(dropSpy.callCount).toEqual(1)
679
- expect(dropSpy.firstCall.args[0]).toEqual([], [...files])
683
+ expect(onDrop).toHaveBeenCalledWith([], files, expectedEvent)
684
+ onDrop.mockClear()
685
+
680
686
  await dropzone.simulate('drop', { dataTransfer: { files: images } })
681
- expect(dropSpy.callCount).toEqual(2)
682
- expect(dropSpy.lastCall.args[0]).toEqual([...images], [])
687
+ expect(onDrop).toHaveBeenCalledWith(images, [], expectedEvent)
688
+ onDrop.mockClear()
689
+
683
690
  await dropzone.simulate('drop', {
684
691
  dataTransfer: { files: files.concat(images) }
685
692
  })
686
- expect(dropSpy.callCount).toEqual(3)
687
- expect(dropSpy.lastCall.args[0]).toEqual([...images], [...files])
693
+ expect(onDrop).toHaveBeenCalledWith(images, files, expectedEvent)
688
694
  })
689
695
 
690
696
  it('should call onDropAccepted callback if some files were accepted', async () => {
691
- const dropzone = mount(
692
- <Dropzone
693
- onDrop={dropSpy}
694
- onDropAccepted={dropAcceptedSpy}
695
- onDropRejected={dropRejectedSpy}
696
- accept="image/*"
697
- />
698
- )
697
+ const dropzone = mount(<Dropzone onDropAccepted={onDropAccepted} accept="image/*" />)
699
698
  await dropzone.simulate('drop', { dataTransfer: { files } })
700
- expect(dropAcceptedSpy.callCount).toEqual(0)
699
+ expect(onDropAccepted).not.toHaveBeenCalled()
700
+ onDropAccepted.mockClear()
701
+
701
702
  await dropzone.simulate('drop', { dataTransfer: { files: images } })
702
- expect(dropAcceptedSpy.callCount).toEqual(1)
703
- expect(dropAcceptedSpy.lastCall.args[0]).toEqual([...images])
703
+ expect(onDropAccepted).toHaveBeenCalledWith(images, expectedEvent)
704
+ onDropAccepted.mockClear()
705
+
704
706
  await dropzone.simulate('drop', {
705
707
  dataTransfer: { files: files.concat(images) }
706
708
  })
707
- expect(dropAcceptedSpy.callCount).toEqual(2)
708
- expect(dropAcceptedSpy.lastCall.args[0]).toEqual([...images])
709
+ expect(onDropAccepted).toHaveBeenCalledWith(images, expectedEvent)
709
710
  })
710
711
 
711
712
  it('should call onDropRejected callback if some files were rejected', async () => {
712
- const dropzone = mount(
713
- <Dropzone
714
- onDrop={dropSpy}
715
- onDropAccepted={dropAcceptedSpy}
716
- onDropRejected={dropRejectedSpy}
717
- accept="image/*"
718
- />
719
- )
720
- await dropzone.simulate('drop', { dataTransfer: { files } })
721
- expect(dropRejectedSpy.callCount).toEqual(1)
722
- expect(dropRejectedSpy.lastCall.args[0]).toEqual([...files])
713
+ const dropzone = mount(<Dropzone onDropRejected={onDropRejected} accept="image/*" />)
723
714
  await dropzone.simulate('drop', { dataTransfer: { files: images } })
724
- expect(dropRejectedSpy.callCount).toEqual(1)
715
+ expect(onDropRejected).not.toHaveBeenCalled()
716
+ onDropRejected.mockClear()
717
+
718
+ await dropzone.simulate('drop', { dataTransfer: { files } })
719
+ expect(onDropRejected).toHaveBeenCalledWith(files, expectedEvent)
720
+ onDropRejected.mockClear()
721
+
725
722
  await dropzone.simulate('drop', {
726
723
  dataTransfer: { files: files.concat(images) }
727
724
  })
728
- expect(dropRejectedSpy.callCount).toEqual(2)
729
- expect(dropRejectedSpy.lastCall.args[0]).toEqual([...files])
725
+ expect(onDropRejected).toHaveBeenCalledWith(files, expectedEvent)
730
726
  })
731
727
 
732
728
  it('applies the accept prop to the dropped files', async () => {
733
729
  const dropzone = mount(
734
730
  <Dropzone
735
- onDrop={dropSpy}
736
- onDropAccepted={dropAcceptedSpy}
737
- onDropRejected={dropRejectedSpy}
731
+ onDrop={onDrop}
732
+ onDropAccepted={onDropAccepted}
733
+ onDropRejected={onDropRejected}
738
734
  accept="image/*"
739
735
  />
740
736
  )
741
737
  await dropzone.simulate('drop', { dataTransfer: { files } })
742
- expect(dropSpy.callCount).toEqual(1)
743
- expect(dropSpy.firstCall.args[0]).toHaveLength(0)
744
- expect(dropSpy.firstCall.args[1]).toHaveLength(1)
745
- expect(dropAcceptedSpy.callCount).toEqual(0)
746
- expect(dropRejectedSpy.callCount).toEqual(1)
747
- expect(dropRejectedSpy.firstCall.args[0]).toHaveLength(1)
738
+ expect(onDrop).toHaveBeenCalledWith([], files, expectedEvent)
739
+ expect(onDropAccepted).not.toHaveBeenCalled()
740
+ expect(onDropRejected).toHaveBeenCalledWith(files, expectedEvent)
748
741
  })
749
742
 
750
743
  it('applies the accept prop to the dropped images', async () => {
751
744
  const dropzone = mount(
752
745
  <Dropzone
753
- onDrop={dropSpy}
754
- onDropAccepted={dropAcceptedSpy}
755
- onDropRejected={dropRejectedSpy}
746
+ onDrop={onDrop}
747
+ onDropAccepted={onDropAccepted}
748
+ onDropRejected={onDropRejected}
756
749
  accept="image/*"
757
750
  />
758
751
  )
759
752
 
760
753
  await dropzone.simulate('drop', { dataTransfer: { files: images } })
761
- expect(dropSpy.callCount).toEqual(1)
762
- expect(dropSpy.firstCall.args[0]).toHaveLength(2)
763
- expect(dropSpy.firstCall.args[1]).toHaveLength(0)
764
- expect(dropAcceptedSpy.callCount).toEqual(1)
765
- expect(dropAcceptedSpy.firstCall.args[0]).toHaveLength(2)
766
- expect(dropRejectedSpy.callCount).toEqual(0)
754
+ expect(onDrop).toHaveBeenCalledWith(images, [], expectedEvent)
755
+ expect(onDropAccepted).toHaveBeenCalledWith(images, expectedEvent)
756
+ expect(onDropRejected).not.toHaveBeenCalled()
767
757
  })
768
758
 
769
759
  it('accepts a dropped image when Firefox provides a bogus file type', async () => {
770
760
  const dropzone = mount(
771
761
  <Dropzone
772
- onDrop={dropSpy}
773
- onDropAccepted={dropAcceptedSpy}
774
- onDropRejected={dropRejectedSpy}
762
+ onDrop={onDrop}
763
+ onDropAccepted={onDropAccepted}
764
+ onDropRejected={onDropRejected}
775
765
  accept="image/*"
776
766
  />
777
767
  )
@@ -784,246 +774,236 @@ describe('Dropzone', () => {
784
774
  ]
785
775
 
786
776
  await dropzone.simulate('drop', { dataTransfer: { files: bogusImages } })
787
- expect(dropSpy.callCount).toEqual(1)
788
- expect(dropSpy.firstCall.args[0]).toHaveLength(1)
789
- expect(dropSpy.firstCall.args[1]).toHaveLength(0)
790
- expect(dropAcceptedSpy.callCount).toEqual(1)
791
- expect(dropAcceptedSpy.firstCall.args[0]).toHaveLength(1)
792
- expect(dropRejectedSpy.callCount).toEqual(0)
777
+ expect(onDrop).toHaveBeenCalledWith(bogusImages, [], expectedEvent)
778
+ expect(onDropAccepted).toHaveBeenCalledWith(bogusImages, expectedEvent)
779
+ expect(onDropRejected).not.toHaveBeenCalled()
793
780
  })
794
781
 
795
782
  it('accepts all dropped files and images when no accept prop is specified', async () => {
796
783
  const dropzone = mount(
797
- <Dropzone
798
- onDrop={dropSpy}
799
- onDropAccepted={dropAcceptedSpy}
800
- onDropRejected={dropRejectedSpy}
801
- />
784
+ <Dropzone onDrop={onDrop} onDropAccepted={onDropAccepted} onDropRejected={onDropRejected} />
802
785
  )
803
786
  await dropzone.simulate('drop', {
804
787
  dataTransfer: { files: files.concat(images) }
805
788
  })
806
- expect(dropSpy.callCount).toEqual(1)
807
- expect(dropSpy.firstCall.args[0]).toHaveLength(3)
808
- expect(dropSpy.firstCall.args[1]).toHaveLength(0)
809
- expect(dropAcceptedSpy.callCount).toEqual(1)
810
- expect(dropAcceptedSpy.firstCall.args[0]).toHaveLength(3)
811
- expect(dropRejectedSpy.callCount).toEqual(0)
789
+ expect(onDrop).toHaveBeenCalledWith(files.concat(images), [], expectedEvent)
790
+ expect(onDropAccepted).toHaveBeenCalledWith(files.concat(images), expectedEvent)
791
+ expect(onDropRejected).not.toHaveBeenCalled()
812
792
  })
813
793
 
814
794
  it('applies the maxSize prop to the dropped files', async () => {
815
795
  const dropzone = mount(
816
796
  <Dropzone
817
- onDrop={dropSpy}
818
- onDropAccepted={dropAcceptedSpy}
819
- onDropRejected={dropRejectedSpy}
797
+ onDrop={onDrop}
798
+ onDropAccepted={onDropAccepted}
799
+ onDropRejected={onDropRejected}
820
800
  maxSize={1111}
821
801
  />
822
802
  )
823
803
 
824
804
  await dropzone.simulate('drop', { dataTransfer: { files } })
825
- expect(dropSpy.callCount).toEqual(1)
826
- expect(dropSpy.firstCall.args[0]).toHaveLength(1)
827
- expect(dropSpy.firstCall.args[1]).toHaveLength(0)
828
- expect(dropAcceptedSpy.callCount).toEqual(1)
829
- expect(dropAcceptedSpy.firstCall.args[0]).toHaveLength(1)
830
- expect(dropRejectedSpy.callCount).toEqual(0)
805
+ expect(onDrop).toHaveBeenCalledWith(files, [], expectedEvent)
806
+ expect(onDropAccepted).toHaveBeenCalledWith(files, expectedEvent)
807
+ expect(onDropRejected).not.toHaveBeenCalled()
831
808
  })
832
809
 
833
810
  it('applies the maxSize prop to the dropped images', async () => {
834
811
  const dropzone = mount(
835
812
  <Dropzone
836
- onDrop={dropSpy}
837
- onDropAccepted={dropAcceptedSpy}
838
- onDropRejected={dropRejectedSpy}
813
+ onDrop={onDrop}
814
+ onDropAccepted={onDropAccepted}
815
+ onDropRejected={onDropRejected}
839
816
  maxSize={1111}
840
817
  />
841
818
  )
842
819
  await dropzone.simulate('drop', { dataTransfer: { files: images } })
843
- expect(dropSpy.callCount).toEqual(1)
844
- expect(dropSpy.firstCall.args[0]).toHaveLength(0)
845
- expect(dropSpy.firstCall.args[1]).toHaveLength(2)
846
- expect(dropAcceptedSpy.callCount).toEqual(0)
847
- expect(dropRejectedSpy.callCount).toEqual(1)
848
- expect(dropRejectedSpy.firstCall.args[0]).toHaveLength(2)
820
+ expect(onDrop).toHaveBeenCalledWith([], images, expectedEvent)
821
+ expect(onDropAccepted).not.toHaveBeenCalled()
822
+ expect(onDropRejected).toHaveBeenCalledWith(images, expectedEvent)
849
823
  })
850
824
 
851
825
  it('applies the minSize prop to the dropped files', async () => {
852
826
  const dropzone = mount(
853
827
  <Dropzone
854
- onDrop={dropSpy}
855
- onDropAccepted={dropAcceptedSpy}
856
- onDropRejected={dropRejectedSpy}
828
+ onDrop={onDrop}
829
+ onDropAccepted={onDropAccepted}
830
+ onDropRejected={onDropRejected}
857
831
  minSize={1112}
858
832
  />
859
833
  )
860
834
  await dropzone.simulate('drop', { dataTransfer: { files } })
861
- expect(dropSpy.callCount).toEqual(1)
862
- expect(dropSpy.firstCall.args[0]).toHaveLength(0)
863
- expect(dropSpy.firstCall.args[1]).toHaveLength(1)
864
- expect(dropAcceptedSpy.callCount).toEqual(0)
865
- expect(dropRejectedSpy.callCount).toEqual(1)
866
- expect(dropRejectedSpy.firstCall.args[0]).toHaveLength(1)
835
+ expect(onDrop).toHaveBeenCalledWith([], files, expectedEvent)
836
+ expect(onDropAccepted).not.toHaveBeenCalled()
837
+ expect(onDropRejected).toHaveBeenCalledWith(files, expectedEvent)
867
838
  })
868
839
 
869
840
  it('applies the minSize prop to the dropped images', async () => {
870
841
  const dropzone = mount(
871
842
  <Dropzone
872
- onDrop={dropSpy}
873
- onDropAccepted={dropAcceptedSpy}
874
- onDropRejected={dropRejectedSpy}
843
+ onDrop={onDrop}
844
+ onDropAccepted={onDropAccepted}
845
+ onDropRejected={onDropRejected}
875
846
  minSize={1112}
876
847
  />
877
848
  )
878
849
  await dropzone.simulate('drop', { dataTransfer: { files: images } })
879
- expect(dropSpy.callCount).toEqual(1)
880
- expect(dropSpy.firstCall.args[0]).toHaveLength(2)
881
- expect(dropSpy.firstCall.args[1]).toHaveLength(0)
882
- expect(dropAcceptedSpy.callCount).toEqual(1)
883
- expect(dropAcceptedSpy.firstCall.args[0]).toHaveLength(2)
884
- expect(dropRejectedSpy.callCount).toEqual(0)
850
+ expect(onDrop).toHaveBeenCalledWith(images, [], expectedEvent)
851
+ expect(onDropAccepted).toHaveBeenCalledWith(images, expectedEvent)
852
+ expect(onDropRejected).not.toHaveBeenCalled()
885
853
  })
886
854
 
887
855
  it('accepts all dropped files and images when no size prop is specified', async () => {
888
856
  const dropzone = mount(
889
- <Dropzone
890
- onDrop={dropSpy}
891
- onDropAccepted={dropAcceptedSpy}
892
- onDropRejected={dropRejectedSpy}
893
- />
857
+ <Dropzone onDrop={onDrop} onDropAccepted={onDropAccepted} onDropRejected={onDropRejected} />
894
858
  )
895
859
  await dropzone.simulate('drop', {
896
860
  dataTransfer: { files: files.concat(images) }
897
861
  })
898
- expect(dropSpy.callCount).toEqual(1)
899
- expect(dropSpy.firstCall.args[0]).toHaveLength(3)
900
- expect(dropSpy.firstCall.args[1]).toHaveLength(0)
901
- expect(dropAcceptedSpy.callCount).toEqual(1)
902
- expect(dropAcceptedSpy.firstCall.args[0]).toHaveLength(3)
903
- expect(dropRejectedSpy.callCount).toEqual(0)
862
+ expect(onDrop).toHaveBeenCalledWith(files.concat(images), [], expectedEvent)
863
+ expect(onDropAccepted).toHaveBeenCalledWith(files.concat(images), expectedEvent)
864
+ expect(onDropRejected).not.toHaveBeenCalled()
904
865
  })
905
866
  })
906
867
 
907
868
  describe('preview', () => {
869
+ const expectedEvent = expect.anything()
870
+
908
871
  it('should generate previews for non-images', async () => {
909
- const dropSpy = spy()
910
- const dropzone = mount(<Dropzone onDrop={dropSpy} />)
872
+ const onDrop = jest.fn()
873
+ const dropzone = mount(<Dropzone onDrop={onDrop} />)
911
874
  await dropzone.simulate('drop', { dataTransfer: { files } })
912
- expect(Object.keys(dropSpy.firstCall.args[0][0])).toContain('preview')
913
- expect(dropSpy.firstCall.args[0][0].preview).toContain('data://file1.pdf')
875
+ expect(onDrop).toHaveBeenCalledWith(
876
+ expect.arrayContaining([expect.objectContaining({ preview: 'data://file1.pdf' })]),
877
+ [],
878
+ expectedEvent
879
+ )
914
880
  })
915
881
 
916
882
  it('should generate previews for images', async () => {
917
- const dropSpy = spy()
918
- const dropzone = mount(<Dropzone onDrop={dropSpy} />)
883
+ const onDrop = jest.fn()
884
+ const dropzone = mount(<Dropzone onDrop={onDrop} />)
919
885
  await dropzone.simulate('drop', { dataTransfer: { files: images } })
920
- expect(Object.keys(dropSpy.firstCall.args[0][0])).toContain('preview')
921
- expect(dropSpy.firstCall.args[0][0].preview).toContain('data://cats.gif')
886
+ expect(onDrop).toHaveBeenCalledWith(
887
+ expect.arrayContaining([expect.objectContaining({ preview: 'data://cats.gif' })]),
888
+ [],
889
+ expectedEvent
890
+ )
922
891
  })
923
892
 
924
893
  it('should not throw error when preview cannot be created', async () => {
925
- const dropSpy = spy()
926
- const dropzone = mount(<Dropzone onDrop={dropSpy} />)
894
+ const onDrop = jest.fn()
895
+ const onConsoleError = jest.fn()
896
+ jest.spyOn(console, 'error').mockImplementationOnce(onConsoleError)
927
897
 
898
+ const dropzone = mount(<Dropzone onDrop={onDrop} />)
928
899
  await dropzone.simulate('drop', { dataTransfer: { files: ['bad_val'] } })
929
900
 
930
- expect(Object.keys(dropSpy.firstCall.args[1][0])).not.toContain('preview')
901
+ expect(onConsoleError).toHaveBeenCalled()
902
+ expect(onDrop).not.toHaveBeenCalledWith(
903
+ expect.arrayContaining([expect.objectContaining({ preview: expect.anything() })]),
904
+ [],
905
+ expectedEvent
906
+ )
931
907
  })
932
908
 
933
909
  it('should not generate previews if disablePreview is true', async () => {
934
- const dropSpy = spy()
935
- const dropzone = mount(<Dropzone disablePreview onDrop={dropSpy} />)
910
+ const onDrop = jest.fn()
911
+ const dropzone = mount(<Dropzone disablePreview onDrop={onDrop} />)
936
912
  await dropzone.simulate('drop', { dataTransfer: { files: images } })
913
+ expect(onDrop).not.toHaveBeenCalledWith(
914
+ expect.arrayContaining([expect.objectContaining({ preview: expect.anything() })]),
915
+ [],
916
+ expectedEvent
917
+ )
918
+ onDrop.mockClear()
919
+
937
920
  await dropzone.simulate('drop', { dataTransfer: { files } })
938
- expect(dropSpy.callCount).toEqual(2)
939
- expect(Object.keys(dropSpy.firstCall.args[0][0])).not.toContain('preview')
940
- expect(Object.keys(dropSpy.lastCall.args[0][0])).not.toContain('preview')
921
+ expect(onDrop).not.toHaveBeenCalledWith(
922
+ expect.arrayContaining([expect.objectContaining({ preview: expect.anything() })]),
923
+ [],
924
+ expectedEvent
925
+ )
941
926
  })
942
927
  })
943
928
 
944
929
  describe('onClick', () => {})
945
930
 
946
931
  describe('onCancel', () => {
947
- it('should not invoke onFileDialogCancel everytime window receives focus', done => {
948
- const onCancelSpy = spy()
949
- mount(<Dropzone id="on-cancel-example" onFileDialogCancel={onCancelSpy} />)
932
+ beforeEach(() => {
933
+ jest.useFakeTimers(true)
934
+ })
935
+
936
+ afterEach(() => {
937
+ jest.useFakeTimers(false)
938
+ })
939
+
940
+ it('should not invoke onFileDialogCancel everytime window receives focus', () => {
941
+ const onFileDialogCancel = jest.fn()
942
+ mount(<Dropzone id="on-cancel-example" onFileDialogCancel={onFileDialogCancel} />)
950
943
  // Simulated DOM event - onfocus
951
944
  document.body.addEventListener('focus', () => {})
952
945
  const evt = document.createEvent('HTMLEvents')
953
946
  evt.initEvent('focus', false, true)
954
947
  document.body.dispatchEvent(evt)
955
- // setTimeout to match the event callback from actual Component
956
- setTimeout(() => {
957
- expect(onCancelSpy.callCount).toEqual(0)
958
- done()
959
- }, 300)
948
+ jest.runAllTimers()
949
+ expect(onFileDialogCancel).not.toHaveBeenCalled()
960
950
  })
961
951
 
962
- it('should invoke onFileDialogCancel when window receives focus via cancel button', done => {
963
- const onCancelSpy = spy()
952
+ it('should invoke onFileDialogCancel when window receives focus via cancel button', () => {
953
+ const onFileDialogCancel = jest.fn()
964
954
  const component = mount(
965
- <Dropzone className="dropzone-content" onFileDialogCancel={onCancelSpy} />
955
+ <Dropzone className="dropzone-content" onFileDialogCancel={onFileDialogCancel} />
966
956
  )
967
957
 
968
958
  // Test / invoke the click event
969
- spy(component.instance(), 'open')
959
+ const open = jest.spyOn(component.instance(), 'open')
970
960
  component.simulate('click')
971
961
 
972
- setTimeout(() => {
973
- expect(component.instance().open.callCount).toEqual(1)
962
+ expect(open).toHaveBeenCalled()
974
963
 
975
- // Simulated DOM event - onfocus
976
- window.addEventListener('focus', () => {})
977
- const evt = document.createEvent('HTMLEvents')
978
- evt.initEvent('focus', false, true)
979
- window.dispatchEvent(evt)
964
+ // Simulated DOM event - onfocus
965
+ window.addEventListener('focus', () => {})
966
+ const evt = document.createEvent('HTMLEvents')
967
+ evt.initEvent('focus', false, true)
968
+ window.dispatchEvent(evt)
980
969
 
981
- // setTimeout to match the event callback from actual Component
982
- setTimeout(() => {
983
- expect(onCancelSpy.callCount).toEqual(1)
984
- done()
985
- }, 300)
986
- }, 0)
970
+ jest.runAllTimers()
971
+ expect(onFileDialogCancel).toHaveBeenCalled()
987
972
  })
988
973
 
989
- it('should restore isFileDialogActive to false after the FileDialog was closed', done => {
974
+ it('should restore isFileDialogActive to false after the FileDialog was closed', () => {
990
975
  const component = mount(<Dropzone />)
991
976
 
992
- spy(component.instance(), 'open')
993
977
  component.simulate('click')
994
978
 
995
- setTimeout(() => {
996
- expect(component.instance().isFileDialogActive).toEqual(true)
979
+ expect(component.instance().isFileDialogActive).toEqual(true)
997
980
 
998
- const evt = document.createEvent('HTMLEvents')
999
- evt.initEvent('focus', false, true)
1000
- window.dispatchEvent(evt)
981
+ const evt = document.createEvent('HTMLEvents')
982
+ evt.initEvent('focus', false, true)
983
+ window.dispatchEvent(evt)
1001
984
 
1002
- setTimeout(() => {
1003
- expect(component.instance().isFileDialogActive).toEqual(false)
1004
- done()
1005
- }, 300)
1006
- }, 0)
985
+ jest.runAllTimers()
986
+ expect(component.instance().isFileDialogActive).toEqual(false)
1007
987
  })
1008
988
  })
1009
989
 
1010
990
  describe('nested Dropzone component behavior', () => {
1011
- let outerDropzone
1012
- let innerDropzone
1013
- let outerDropSpy
1014
- let outerDropAcceptedSpy
1015
- let outerDropRejectedSpy
1016
- let innerDropSpy
1017
- let innerDropAcceptedSpy
1018
- let innerDropRejectedSpy
991
+ const expectedEvent = expect.anything()
992
+ const onOuterDrop = jest.fn()
993
+ const onOuterDropAccepted = jest.fn()
994
+ const onOuterDropRejected = jest.fn()
995
+
996
+ const onInnerDrop = jest.fn()
997
+ const onInnerDropAccepted = jest.fn()
998
+ const onInnerDropRejected = jest.fn()
1019
999
 
1020
1000
  const InnerDragAccepted = () => <p>Accepted</p>
1021
1001
  const InnerDragRejected = () => <p>Rejected</p>
1022
1002
  const InnerDropzone = () => (
1023
1003
  <Dropzone
1024
- onDrop={innerDropSpy}
1025
- onDropAccepted={innerDropAcceptedSpy}
1026
- onDropRejected={innerDropRejectedSpy}
1004
+ onDrop={onInnerDrop}
1005
+ onDropAccepted={onInnerDropAccepted}
1006
+ onDropRejected={onInnerDropRejected}
1027
1007
  accept="image/*"
1028
1008
  >
1029
1009
  {({ isDragActive, isDragReject }) => {
@@ -1035,62 +1015,76 @@ describe('Dropzone', () => {
1035
1015
  )
1036
1016
 
1037
1017
  describe('dropping on the inner dropzone', () => {
1038
- it('mounts both dropzones', () => {
1039
- outerDropSpy = spy()
1040
- outerDropAcceptedSpy = spy()
1041
- outerDropRejectedSpy = spy()
1042
- innerDropSpy = spy()
1043
- innerDropAcceptedSpy = spy()
1044
- innerDropRejectedSpy = spy()
1045
- outerDropzone = mount(
1018
+ it('does dragEnter on both dropzones', async () => {
1019
+ const outerDropzone = mount(
1020
+ <Dropzone accept="image/*">{props => <InnerDropzone {...props} />}</Dropzone>
1021
+ )
1022
+ outerDropzone.find(InnerDropzone).simulate('dragEnter', {
1023
+ dataTransfer: { files: images }
1024
+ })
1025
+ const updatedOuterDropzone = await flushPromises(outerDropzone)
1026
+ const innerDropzone = updatedOuterDropzone.find(InnerDropzone)
1027
+
1028
+ expect(innerDropzone).toHaveProp('isDragActive', true)
1029
+ expect(innerDropzone).toHaveProp('isDragReject', false)
1030
+ expect(innerDropzone.find(InnerDragAccepted)).toExist()
1031
+ expect(innerDropzone.find(InnerDragRejected)).not.toExist()
1032
+ })
1033
+
1034
+ it('accepts the drop on the inner dropzone', async () => {
1035
+ const outerDropzone = mount(
1046
1036
  <Dropzone
1047
- onDrop={outerDropSpy}
1048
- onDropAccepted={outerDropAcceptedSpy}
1049
- onDropRejected={outerDropRejectedSpy}
1037
+ onDrop={onOuterDrop}
1038
+ onDropAccepted={onOuterDropAccepted}
1039
+ onDropRejected={onOuterDropRejected}
1050
1040
  accept="image/*"
1051
1041
  >
1052
1042
  {props => <InnerDropzone {...props} />}
1053
1043
  </Dropzone>
1054
1044
  )
1055
- innerDropzone = outerDropzone.find(InnerDropzone)
1056
- })
1057
1045
 
1058
- it('does dragEnter on both dropzones', async () => {
1059
- await innerDropzone.simulate('dragEnter', {
1060
- dataTransfer: { files: images }
1046
+ outerDropzone.find(InnerDropzone).simulate('drop', {
1047
+ dataTransfer: { files: files.concat(images) }
1061
1048
  })
1062
- expect(innerDropzone).toHaveProp('isDragActive', true)
1063
- expect(innerDropzone).toHaveProp('isDragReject', false)
1064
- expect(innerDropzone.find(InnerDragAccepted).exists()).toEqual(true)
1065
- expect(innerDropzone.find(InnerDragRejected).exists()).toEqual(false)
1049
+ const updatedOuterDropzone = await flushPromises(outerDropzone)
1050
+ const innerDropzone = updatedOuterDropzone.find(InnerDropzone)
1051
+
1052
+ expect(onInnerDrop).toHaveBeenCalledTimes(1)
1053
+ expect(onInnerDrop).toHaveBeenCalledWith(images, files, expectedEvent)
1054
+ expect(onInnerDropAccepted).toHaveBeenCalledTimes(1)
1055
+ expect(onInnerDropAccepted).toHaveBeenCalledWith(images, expectedEvent)
1056
+ expect(onInnerDropRejected).toHaveBeenCalledTimes(1)
1057
+ expect(onInnerDropRejected).toHaveBeenCalledWith(files, expectedEvent)
1058
+
1059
+ expect(innerDropzone.find(InnerDragAccepted)).not.toExist()
1060
+ expect(innerDropzone.find(InnerDragRejected)).not.toExist()
1066
1061
  })
1067
1062
 
1068
- it('drops on the child dropzone', () => {
1069
- innerDropzone.simulate('drop', {
1063
+ it('also accepts the drop on the outer dropzone', async () => {
1064
+ const outerDropzone = mount(
1065
+ <Dropzone
1066
+ onDrop={onOuterDrop}
1067
+ onDropAccepted={onOuterDropAccepted}
1068
+ onDropRejected={onOuterDropRejected}
1069
+ accept="image/*"
1070
+ >
1071
+ {props => <InnerDropzone {...props} />}
1072
+ </Dropzone>
1073
+ )
1074
+
1075
+ outerDropzone.simulate('drop', {
1070
1076
  dataTransfer: { files: files.concat(images) }
1071
1077
  })
1072
- })
1078
+ const updatedOuterDropzone = await flushPromises(outerDropzone)
1073
1079
 
1074
- it('accepts the drop on the inner dropzone', () => {
1075
- expect(innerDropSpy.callCount).toEqual(1)
1076
- expect(innerDropSpy.firstCall.args[0]).toHaveLength(2)
1077
- expect(innerDropSpy.firstCall.args[1]).toHaveLength(1)
1078
- expect(innerDropAcceptedSpy.callCount).toEqual(1)
1079
- expect(innerDropAcceptedSpy.firstCall.args[0]).toHaveLength(2)
1080
- expect(innerDropRejectedSpy.callCount).toEqual(1)
1081
- expect(innerDropRejectedSpy.firstCall.args[0]).toHaveLength(1)
1082
- expect(innerDropzone.find(InnerDragAccepted).exists()).toEqual(false)
1083
- expect(innerDropzone.find(InnerDragRejected).exists()).toEqual(false)
1084
- })
1080
+ const innerDropzone = updatedOuterDropzone.find(InnerDropzone)
1085
1081
 
1086
- it('also accepts the drop on the outer dropzone', () => {
1087
- expect(outerDropSpy.callCount).toEqual(1)
1088
- expect(outerDropSpy.firstCall.args[0]).toHaveLength(2)
1089
- expect(outerDropSpy.firstCall.args[1]).toHaveLength(1)
1090
- expect(outerDropAcceptedSpy.callCount).toEqual(1)
1091
- expect(outerDropAcceptedSpy.firstCall.args[0]).toHaveLength(2)
1092
- expect(outerDropRejectedSpy.callCount).toEqual(1)
1093
- expect(outerDropRejectedSpy.firstCall.args[0]).toHaveLength(1)
1082
+ expect(onOuterDrop).toHaveBeenCalledTimes(1)
1083
+ expect(onOuterDrop).toHaveBeenCalledWith(images, files, expectedEvent)
1084
+ expect(onOuterDropAccepted).toHaveBeenCalledTimes(1)
1085
+ expect(onOuterDropAccepted).toHaveBeenCalledWith(images, expectedEvent)
1086
+ expect(onOuterDropRejected).toHaveBeenCalledTimes(1)
1087
+ expect(onOuterDropRejected).toHaveBeenCalledWith(files, expectedEvent)
1094
1088
  expect(innerDropzone).toHaveProp('isDragActive', false)
1095
1089
  expect(innerDropzone).toHaveProp('isDragReject', false)
1096
1090
  })
@@ -1105,28 +1099,22 @@ describe('Dropzone', () => {
1105
1099
  expect(fn).not.toThrow()
1106
1100
  })
1107
1101
 
1108
- it('does not allow actions when disabled props is true', done => {
1102
+ it('does not allow actions when disabled props is true', () => {
1109
1103
  const dropzone = mount(<Dropzone disabled />)
1110
1104
 
1111
- spy(dropzone.instance(), 'open')
1105
+ const open = jest.spyOn(dropzone.instance(), 'open')
1112
1106
  dropzone.simulate('click')
1113
- setTimeout(() => {
1114
- expect(dropzone.instance().open.callCount).toEqual(0)
1115
- done()
1116
- }, 0)
1107
+ expect(open).not.toHaveBeenCalled()
1117
1108
  })
1118
1109
 
1119
- it('when toggle disabled props, Dropzone works as expected', done => {
1110
+ it('when toggle disabled props, Dropzone works as expected', () => {
1120
1111
  const dropzone = mount(<Dropzone disabled />)
1121
- spy(dropzone.instance(), 'open')
1112
+ const open = jest.spyOn(dropzone.instance(), 'open')
1122
1113
 
1123
1114
  dropzone.setProps({ disabled: false })
1124
1115
 
1125
1116
  dropzone.simulate('click')
1126
- setTimeout(() => {
1127
- expect(dropzone.instance().open.callCount).toEqual(1)
1128
- done()
1129
- }, 0)
1117
+ expect(open).toHaveBeenCalled()
1130
1118
  })
1131
1119
  })
1132
1120
  })