From 3a9e84adb47a65037ff3259332b311f417985f64 Mon Sep 17 00:00:00 2001 From: Vladimir Airikh Date: Fri, 12 Apr 2019 15:01:01 +0300 Subject: [PATCH] fix `The `change` event shouldn't be raised on an upload input if the value wasn't changed after `setFilesToUpload `` (close #1844) (#1979) * fix `The `change` event shouldn't be raised on an upload input if the value wasn't changed after `setFilesToUpload `` (close #1844) * add macOS cases, naming * fix test * requested changes * fix test variable naming * requested changes --- src/client/sandbox/upload/index.ts | 34 +++++++++++++-- test/client/fixtures/sandbox/upload-test.js | 46 ++++++++++++++++++++- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/client/sandbox/upload/index.ts b/src/client/sandbox/upload/index.ts index db604ec80..c4bd7a783 100644 --- a/src/client/sandbox/upload/index.ts +++ b/src/client/sandbox/upload/index.ts @@ -2,7 +2,7 @@ import INTERNAL_PROPS from '../../../processing/dom/internal-properties'; import SandboxBase from '../base'; import UploadInfoManager from './info-manager'; import { isFileInput } from '../../utils/dom'; -import { isIE, isFirefox, version as browserVersion } from '../../utils/browser'; +import { isIE, isFirefox, isChrome, isMacPlatform, isSafari, version as browserVersion } from '../../utils/browser'; import { stopPropagation, preventDefault } from '../../utils/event'; import { get as getSandboxBackup } from '../backup'; import nativeMethods from '../native-methods'; @@ -104,6 +104,28 @@ export default class UploadSandbox extends SandboxBase { return value; } + // GH-1844 + static _needToRaiseChangeEvent (filesToUpload, currentFiles) : boolean { + if (isFirefox || (isMacPlatform && isChrome || isSafari)) + return true; + + for (const file of filesToUpload) { + let found = false; + + for (const currentFile of currentFiles) { + if (file.name === currentFile.name) { + found = true; + break; + } + } + + if (found === false) + return true; + } + + return false; + } + doUpload (input: HTMLInputElement, filePaths: string | Array) { const currentInfoManager = UploadSandbox._getCurrentInfoManager(input); @@ -113,10 +135,16 @@ export default class UploadSandbox extends SandboxBase { .then(filesInfo => UploadInfoManager.prepareFileListWrapper(filesInfo)) .then(data => { if (!data.errs.length) { - const value = UploadInfoManager.formatValue(filePaths); + const value = UploadInfoManager.formatValue(filePaths); + const inputInfo = currentInfoManager.getUploadInfo(input); currentInfoManager.setUploadInfo(input, data.fileList, value); - this._riseChangeEvent(input); + + /*eslint-disable no-restricted-properties*/ + if (!inputInfo || data.fileList.length !== inputInfo.files.length || + UploadSandbox._needToRaiseChangeEvent(data.fileList, inputInfo.files)) + this._riseChangeEvent(input); + /*eslint-enable no-restricted-properties*/ } return data.errs; diff --git a/test/client/fixtures/sandbox/upload-test.js b/test/client/fixtures/sandbox/upload-test.js index e1ff2e1d9..1605a9d25 100644 --- a/test/client/fixtures/sandbox/upload-test.js +++ b/test/client/fixtures/sandbox/upload-test.js @@ -6,12 +6,17 @@ var INTERNAL_PROPS = hammerhead.get('../processing/dom/internal-properties'); var Promise = hammerhead.Promise; var transport = hammerhead.transport; -var browserUtils = hammerhead.utils.browser; var uploadSandbox = hammerhead.sandbox.upload; var infoManager = hammerhead.sandbox.upload.infoManager; var eventSimulator = hammerhead.sandbox.event.eventSimulator; var nativeMethods = hammerhead.nativeMethods; +var browserUtils = hammerhead.utils.browser; +var isChrome = browserUtils.isChrome; +var isFirefox = browserUtils.isFirefox; +var isSafari = browserUtils.isSafari; +var isMacPlatform = browserUtils.isMacPlatform; + // ----- Server API mock --------- // Virtual file system: // - file.txt @@ -538,6 +543,45 @@ asyncTest('change event', function () { uploadSandbox.doUpload(fileInput, './file.txt'); }); +test('change event in the case of the same file/files selection (GH-1844)', function () { + var needToRaiseChangeEvent = isFirefox || (isMacPlatform && isChrome || isSafari); + var assertionsCount = needToRaiseChangeEvent ? 4 : 0; + + expect(assertionsCount); + + var fileInput = $('')[0]; + + var changeHandler = function () { + ok(needToRaiseChangeEvent); + }; + + return uploadSandbox.doUpload(fileInput, './file.txt') + .then(function () { + fileInput.onchange = changeHandler; + + return uploadSandbox.doUpload(fileInput, './file.txt'); + }) + .then(function () { + return uploadSandbox.doUpload(fileInput, ['./file.txt']); + }) + .then(function () { + fileInput.onchange = null; + + return uploadSandbox.doUpload(fileInput, ['folder/file.png', './file.txt']); + }) + .then(function () { + fileInput.onchange = changeHandler; + + return uploadSandbox.doUpload(fileInput, ['folder/file.png', './file.txt']); + }) + .then(function () { + return uploadSandbox.doUpload(fileInput, ['./file.txt', 'folder/file.png']); + }) + .then(function () { + fileInput.onchange = null; + }); +}); + test('multi-select files', function () { var fileInput = $('')[0]; var value = '';