From d4db93c9a778867e9299e13219c6f949d2dfe37e Mon Sep 17 00:00:00 2001 From: ybentz Date: Wed, 24 Jun 2020 18:48:18 -0700 Subject: [PATCH] fix: React onChange/onInput events not triggering on input type="file" file upload (#381) * fix: upload change/input events not bubbling up * test: upload function change/input event bubbling * test: updated upload with label test to reflect event bubbling Co-authored-by: Kent C. Dodds Closes #380 --- src/__tests__/upload.js | 38 +++++++++++++++++++++++++++++++++++++- src/upload.js | 14 +++++++------- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/__tests__/upload.js b/src/__tests__/upload.js index 223a6219..b658c60d 100644 --- a/src/__tests__/upload.js +++ b/src/__tests__/upload.js @@ -1,5 +1,5 @@ import userEvent from '../' -import {setup} from './helpers/utils' +import {setup, addListeners} from './helpers/utils' test('should fire the correct events for input', () => { const file = new File(['hello'], 'hello.png', {type: 'image/png'}) @@ -61,6 +61,8 @@ test('should fire the correct events with label', () => { label[for="element"] - click: Left (0) input#element[value=""] - click: Left (0) input#element[value=""] - focusin + input#element[value=""] - input + input#element[value=""] - change `) }) @@ -125,3 +127,37 @@ test('should not upload when is disabled', () => { expect(element.files.item(0)).toBeNull() expect(element.files).toHaveLength(0) }) + +test('should call onChange/input bubbling up the event when a file is selected', () => { + const file = new File(['hello'], 'hello.png', {type: 'image/png'}) + + const {element: form} = setup(` +
+ +
+ `) + const input = form.querySelector('input') + + const onChangeInput = jest.fn() + const onChangeForm = jest.fn() + const onInputInput = jest.fn() + const onInputForm = jest.fn() + addListeners(input, { + eventHandlers: {change: onChangeInput, input: onInputInput}, + }) + addListeners(form, { + eventHandlers: {change: onChangeForm, input: onInputForm}, + }) + + expect(onChangeInput).toHaveBeenCalledTimes(0) + expect(onChangeForm).toHaveBeenCalledTimes(0) + expect(onInputInput).toHaveBeenCalledTimes(0) + expect(onInputForm).toHaveBeenCalledTimes(0) + + userEvent.upload(input, file) + + expect(onChangeForm).toHaveBeenCalledTimes(1) + expect(onChangeInput).toHaveBeenCalledTimes(1) + expect(onInputInput).toHaveBeenCalledTimes(1) + expect(onInputForm).toHaveBeenCalledTimes(1) +}) diff --git a/src/upload.js b/src/upload.js index 4cecbba9..87bd447f 100644 --- a/src/upload.js +++ b/src/upload.js @@ -35,17 +35,17 @@ function upload(element, fileOrFiles, init) { input, createEvent('input', input, { target: {files: inputFiles}, + bubbles: true, + cancelable: false, + composed: true, ...init, }), ) - fireEvent( - input, - createEvent('change', input, { - target: {files: inputFiles}, - ...init, - }), - ) + fireEvent.change(input, { + target: {files: inputFiles}, + ...init, + }) } export {upload}