diff --git a/CHANGES.md b/CHANGES.md index 70dd493805a..c1895d94fc3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Fixed Issues: * [#13142](http://dev.ckeditor.com/ticket/13142): [Edge] Fixed: CTRL+A, backspace results in an empty div. * [#13599](http://dev.ckeditor.com/ticket/13599): Fixed: Cross-editor D&D of inline widget ends up in error/artifacts. * [#13640](http://dev.ckeditor.com/ticket/13640): [IE] Fixed: Dropping a widget outside body is not handled correctly. +* [#13533](http://dev.ckeditor.com/ticket/13533): Fixed: No progress during upload. Other Changes: diff --git a/plugins/filetools/plugin.js b/plugins/filetools/plugin.js index 57173f76514..41bb17830cf 100644 --- a/plugins/filetools/plugin.js +++ b/plugins/filetools/plugin.js @@ -276,6 +276,7 @@ } this.uploaded = 0; + this.uploadTotal = null; this.status = 'created'; @@ -343,6 +344,23 @@ * @property {Number} total */ + /** + * The total size of upload data in bytes. + * If `xhr.upload` object is present this value will indicate total size of the request payload, not only the file + * size itself. If `xhr.upload` object is not available and real upload size cannot be obtained - this value will + * be equal to {@link #total}. It has null value until upload size is known. + * + * loader.on( 'update', function() { + * // Wait till uploadTotal is present. + * if ( loader.uploadTotal ) { + * console.log( 'uploadTotal: ' + loader.uploadTotal ); + * } + * }); + * + * @readonly + * @property {Number} uploadTotal + */ + /** * The error message or additional information received from the server. * @@ -518,22 +536,43 @@ xhr.abort(); }; - xhr.onabort = function() { - loader.changeStatus( 'abort' ); - }; + xhr.onerror = onError; + xhr.onabort = onAbort; + + // #13533 - When xhr.upload is present attach onprogress, onerror and onabort functions to get actual upload + // information. + if ( xhr.upload ) { + xhr.upload.onprogress = function( evt ) { + if ( evt.lengthComputable ) { + // Set uploadTotal with correct data. + if ( !loader.uploadTotal ) { + loader.uploadTotal = evt.total; + } + loader.uploaded = evt.loaded; + loader.update(); + } + }; - xhr.onerror = function() { - loader.message = loader.lang.filetools.networkError; - loader.changeStatus( 'error' ); - }; + xhr.upload.onerror = onError; + xhr.upload.onabort = onAbort; - xhr.onprogress = function( evt ) { - loader.uploaded = evt.loaded; + } else { + // #13533 - If xhr.upload is not supported - fire update event anyway and set uploadTotal to file size. + loader.uploadTotal = loader.total; loader.update(); - }; + } xhr.onload = function() { - loader.uploaded = loader.total; + // #13433 - Call update at the end of the upload. When xhr.upload object is not supported there will be + // no update events fired during the whole process. + loader.update(); + + // #13433 - Check if loader was not aborted during last update. + if ( loader.status == 'abort' ) { + return; + } + + loader.uploaded = loader.uploadTotal; if ( xhr.status < 200 || xhr.status > 299 ) { loader.message = loader.lang.filetools[ 'httpError' + xhr.status ]; @@ -563,6 +602,24 @@ } } }; + + function onError() { + // Prevent changing status twice, when HHR.error and XHR.upload.onerror could be called together. + if ( loader.status == 'error' ) { + return; + } + + loader.message = loader.lang.filetools.networkError; + loader.changeStatus( 'error' ); + } + + function onAbort() { + // Prevent changing status twice, when HHR.onabort and XHR.upload.onabort could be called together. + if ( loader.status == 'abort' ) { + return; + } + loader.changeStatus( 'abort' ); + } }, /** diff --git a/plugins/uploadwidget/plugin.js b/plugins/uploadwidget/plugin.js index 163c9d4ac59..2bbc987e5e6 100644 --- a/plugins/uploadwidget/plugin.js +++ b/plugins/uploadwidget/plugin.js @@ -442,33 +442,16 @@ * @param {CKEDITOR.fileTools.fileLoader} loader The file loader instance. */ function bindNotifications( editor, loader ) { - var aggregator = editor._.uploadWidgetNotificaionAggregator; - - // Create one notification agregator for all types of upload widgets for the editor. - if ( !aggregator || aggregator.isFinished() ) { - aggregator = editor._.uploadWidgetNotificaionAggregator = new CKEDITOR.plugins.notificationAggregator( - editor, editor.lang.uploadwidget.uploadMany, editor.lang.uploadwidget.uploadOne ); - - aggregator.once( 'finished', function() { - var tasks = aggregator.getTaskCount(); - - if ( tasks === 0 ) { - aggregator.notification.hide(); - } else { - aggregator.notification.update( { - message: tasks == 1 ? - editor.lang.uploadwidget.doneOne : - editor.lang.uploadwidget.doneMany.replace( '%1', tasks ), - type: 'success', - important: 1 - } ); - } - } ); - } - - var task = aggregator.createTask( { weight: loader.total } ); + var aggregator, + task = null; loader.on( 'update', function() { + // Value of uploadTotal is known after upload start. Task will be created when uploadTotal is present. + if ( !task && loader.uploadTotal ) { + createAggregator(); + task = aggregator.createTask( { weight: loader.uploadTotal } ); + } + if ( task && loader.status == 'uploading' ) { task.update( loader.uploaded ); } @@ -487,6 +470,32 @@ task && task.cancel(); editor.showNotification( editor.lang.uploadwidget.abort, 'info' ); } ); + + function createAggregator() { + aggregator = editor._.uploadWidgetNotificaionAggregator; + + // Create one notification aggregator for all types of upload widgets for the editor. + if ( !aggregator || aggregator.isFinished() ) { + aggregator = editor._.uploadWidgetNotificaionAggregator = new CKEDITOR.plugins.notificationAggregator( + editor, editor.lang.uploadwidget.uploadMany, editor.lang.uploadwidget.uploadOne ); + + aggregator.once( 'finished', function() { + var tasks = aggregator.getTaskCount(); + + if ( tasks === 0 ) { + aggregator.notification.hide(); + } else { + aggregator.notification.update( { + message: tasks == 1 ? + editor.lang.uploadwidget.doneOne : + editor.lang.uploadwidget.doneMany.replace( '%1', tasks ), + type: 'success', + important: 1 + } ); + } + } ); + } + } } // Two plugins extend this object. diff --git a/tests/plugins/filetools/fileloader.js b/tests/plugins/filetools/fileloader.js index 0caf37f0cc3..e6d97791601 100644 --- a/tests/plugins/filetools/fileloader.js +++ b/tests/plugins/filetools/fileloader.js @@ -72,6 +72,8 @@ open: function() { }, + upload: {}, + send: function( formData ) { lastFormData = formData; @@ -85,16 +87,23 @@ switch ( scenario[ i ] ) { case 'progress': - evt = { loaded: 41 }; + // Report total upload size larger than file size. It will happen + // when file will be embedded in FormData. + evt = { loaded: 41, total: 100, lengthComputable: true }; + xhr.upload.onprogress( evt ); break; case 'load': xhr.status = ( response && response.responseStatus ) ? response.responseStatus : 200; xhr.responseText = ( response && response.responseText ) ? response.responseText : '{"fileName":"name2.png","uploaded":1,"url":"http:\/\/url\/name2.png"}'; + xhr.onload( evt ); + break; + case 'error': + xhr.onerror( evt ); break; } - xhr[ 'on' + scenario[ i ] ]( evt ); + }; } else { action = scenario[ i ]; @@ -132,7 +141,7 @@ observer.events += evt.name + '[' + loader.status + ',' + loader.fileName + ',' + - loader.uploaded + '/' + loader.loaded + '/' + loader.total + ',' + + loader.uploaded + '/' + loader.loaded + '/' + loader.total + '/' + loader.uploadTotal + ',' + message + ',' + data + ',' + url + ']|'; } @@ -304,11 +313,11 @@ resumeAfter( loader, 'loaded', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/41/82,-,-,-]', - 'loaded[loaded,name.png,0/82/82,-,result,-]', - 'update[loaded,name.png,0/82/82,-,result,-]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/41/82/null,-,-,-]', + 'loaded[loaded,name.png,0/82/82/null,-,result,-]', + 'update[loaded,name.png,0/82/82/null,-,result,-]' ] ); }, 3 ); loader.load(); @@ -324,11 +333,12 @@ resumeAfter( loader, 'uploaded', function() { observer.assert( [ - 'uploading[uploading,name.png,0/82/82,-,data:image/png;base64,-]', - 'update[uploading,name.png,0/82/82,-,data:image/png;base64,-]', - 'update[uploading,name.png,41/82/82,-,data:image/png;base64,-]', - 'uploaded[uploaded,name2.png,82/82/82,-,data:image/png;base64,http://url/name2.png]', - 'update[uploaded,name2.png,82/82/82,-,data:image/png;base64,http://url/name2.png]' ] ); + 'uploading[uploading,name.png,0/82/82/null,-,data:image/png;base64,-]', + 'update[uploading,name.png,0/82/82/null,-,data:image/png;base64,-]', + 'update[uploading,name.png,41/82/82/100,-,data:image/png;base64,-]', + 'update[uploading,name.png,41/82/82/100,-,data:image/png;base64,-]', + 'uploaded[uploaded,name2.png,100/82/82/100,-,data:image/png;base64,http://url/name2.png]', + 'update[uploaded,name2.png,100/82/82/100,-,data:image/png;base64,http://url/name2.png]' ] ); }, 3 ); loader.upload( 'http:\/\/url\/' ); @@ -348,11 +358,12 @@ resumeAfter( loader, 'uploaded', function() { observer.assert( [ - 'uploading[uploading,na me.png,0/82/82,-,data:image/png;base64,-]', - 'update[uploading,na me.png,0/82/82,-,data:image/png;base64,-]', - 'update[uploading,na me.png,41/82/82,-,data:image/png;base64,-]', - 'uploaded[uploaded,na me2.png,82/82/82,-,data:image/png;base64,http://url/na me2.png]', - 'update[uploaded,na me2.png,82/82/82,-,data:image/png;base64,http://url/na me2.png]' ] ); + 'uploading[uploading,na me.png,0/82/82/null,-,data:image/png;base64,-]', + 'update[uploading,na me.png,0/82/82/null,-,data:image/png;base64,-]', + 'update[uploading,na me.png,41/82/82/100,-,data:image/png;base64,-]', + 'update[uploading,na me.png,41/82/82/100,-,data:image/png;base64,-]', + 'uploaded[uploaded,na me2.png,100/82/82/100,-,data:image/png;base64,http://url/na me2.png]', + 'update[uploaded,na me2.png,100/82/82/100,-,data:image/png;base64,http://url/na me2.png]' ] ); }, 3 ); loader.upload( 'http:\/\/url\/' ); @@ -371,14 +382,15 @@ resumeAfter( loader, 'uploaded', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/41/82,-,-,-]', - 'uploading[uploading,name.png,0/82/82,-,result,-]', - 'update[uploading,name.png,0/82/82,-,result,-]', - 'update[uploading,name.png,41/82/82,-,result,-]', - 'uploaded[uploaded,name2.png,82/82/82,-,result,http://url/name2.png]', - 'update[uploaded,name2.png,82/82/82,-,result,http://url/name2.png]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/41/82/null,-,-,-]', + 'uploading[uploading,name.png,0/82/82/null,-,result,-]', + 'update[uploading,name.png,0/82/82/null,-,result,-]', + 'update[uploading,name.png,41/82/82/100,-,result,-]', + 'update[uploading,name.png,41/82/82/100,-,result,-]', + 'uploaded[uploaded,name2.png,100/82/82/100,-,result,http://url/name2.png]', + 'update[uploaded,name2.png,100/82/82/100,-,result,http://url/name2.png]' ] ); } ); loader.loadAndUpload( 'http:\/\/url\/' ); @@ -392,8 +404,8 @@ resumeAfter( loader, 'abort', function() { observer.assert( [ - 'abort[abort,name.png,0/0/82,-,-,-]', - 'update[abort,name.png,0/0/82,-,-,-]' ] ); + 'abort[abort,name.png,0/0/82/null,-,-,-]', + 'update[abort,name.png,0/0/82/null,-,-,-]' ] ); } ); loader.abort(); @@ -412,10 +424,10 @@ resumeAfter( loader, 'abort', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'abort[abort,name.png,0/0/82,-,-,-]', - 'update[abort,name.png,0/0/82,-,-,-]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'abort[abort,name.png,0/0/82/null,-,-,-]', + 'update[abort,name.png,0/0/82/null,-,-,-]' ] ); } ); loader.loadAndUpload( 'http:\/\/url\/' ); @@ -434,11 +446,11 @@ resumeAfter( loader, 'abort', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/41/82,-,-,-]', - 'abort[abort,name.png,0/41/82,-,-,-]', - 'update[abort,name.png,0/41/82,-,-,-]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/41/82/null,-,-,-]', + 'abort[abort,name.png,0/41/82/null,-,-,-]', + 'update[abort,name.png,0/41/82/null,-,-,-]' ] ); } ); loader.loadAndUpload( 'http:\/\/url\/' ); @@ -457,11 +469,11 @@ resumeAfter( loader, 'loaded', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/41/82,-,-,-]', - 'loaded[loaded,name.png,0/82/82,-,result,-]', - 'update[loaded,name.png,0/82/82,-,result,-]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/41/82/null,-,-,-]', + 'loaded[loaded,name.png,0/82/82/null,-,result,-]', + 'update[loaded,name.png,0/82/82/null,-,result,-]' ] ); } ); loader.load(); @@ -481,13 +493,13 @@ resumeAfter( loader, 'abort', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/41/82,-,-,-]', - 'uploading[uploading,name.png,0/82/82,-,result,-]', - 'update[uploading,name.png,0/82/82,-,result,-]', - 'abort[abort,name.png,0/82/82,-,result,-]', - 'update[abort,name.png,0/82/82,-,result,-]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/41/82/null,-,-,-]', + 'uploading[uploading,name.png,0/82/82/null,-,result,-]', + 'update[uploading,name.png,0/82/82/null,-,result,-]', + 'abort[abort,name.png,0/82/82/null,-,result,-]', + 'update[abort,name.png,0/82/82/null,-,result,-]' ] ); } ); loader.loadAndUpload( 'http:\/\/url\/' ); @@ -507,14 +519,14 @@ resumeAfter( loader, 'abort', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/41/82,-,-,-]', - 'uploading[uploading,name.png,0/82/82,-,result,-]', - 'update[uploading,name.png,0/82/82,-,result,-]', - 'update[uploading,name.png,41/82/82,-,result,-]', - 'abort[abort,name.png,41/82/82,-,result,-]', - 'update[abort,name.png,41/82/82,-,result,-]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/41/82/null,-,-,-]', + 'uploading[uploading,name.png,0/82/82/null,-,result,-]', + 'update[uploading,name.png,0/82/82/null,-,result,-]', + 'update[uploading,name.png,41/82/82/100,-,result,-]', + 'abort[abort,name.png,41/82/82/100,-,result,-]', + 'update[abort,name.png,41/82/82/100,-,result,-]' ] ); } ); loader.loadAndUpload( 'http:\/\/url\/' ); @@ -534,14 +546,15 @@ resumeAfter( loader, 'uploaded', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/41/82,-,-,-]', - 'uploading[uploading,name.png,0/82/82,-,result,-]', - 'update[uploading,name.png,0/82/82,-,result,-]', - 'update[uploading,name.png,41/82/82,-,result,-]', - 'uploaded[uploaded,name2.png,82/82/82,-,result,http://url/name2.png]', - 'update[uploaded,name2.png,82/82/82,-,result,http://url/name2.png]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/41/82/null,-,-,-]', + 'uploading[uploading,name.png,0/82/82/null,-,result,-]', + 'update[uploading,name.png,0/82/82/null,-,result,-]', + 'update[uploading,name.png,41/82/82/100,-,result,-]', + 'update[uploading,name.png,41/82/82/100,-,result,-]', + 'uploaded[uploaded,name2.png,100/82/82/100,-,result,http://url/name2.png]', + 'update[uploaded,name2.png,100/82/82/100,-,result,http://url/name2.png]' ] ); } ); loader.loadAndUpload( 'http:\/\/url\/' ); @@ -562,11 +575,11 @@ resumeAfter( loader, 'error', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/41/82,-,-,-]', - 'error[error,name.png,0/41/82,errorMsg,-,-]', - 'update[error,name.png,0/41/82,errorMsg,-,-]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/41/82/null,-,-,-]', + 'error[error,name.png,0/41/82/null,errorMsg,-,-]', + 'update[error,name.png,0/41/82/null,errorMsg,-,-]' ] ); } ); loader.load(); @@ -587,11 +600,11 @@ resumeAfter( loader, 'abort', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/41/82,-,-,-]', - 'abort[abort,name.png,0/41/82,-,-,-]', - 'update[abort,name.png,0/41/82,-,-,-]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/41/82/null,-,-,-]', + 'abort[abort,name.png,0/41/82/null,-,-,-]', + 'update[abort,name.png,0/41/82/null,-,-,-]' ] ); } ); loader.load(); @@ -609,11 +622,11 @@ resumeAfter( loader, 'error', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/41/82,-,-,-]', - 'error[error,name.png,0/41/82,loadError,-,-]', - 'update[error,name.png,0/41/82,loadError,-,-]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/41/82/null,-,-,-]', + 'error[error,name.png,0/41/82/null,loadError,-,-]', + 'update[error,name.png,0/41/82/null,loadError,-,-]' ] ); } ); loader.load(); @@ -632,14 +645,14 @@ resumeAfter( loader, 'error', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/41/82,-,-,-]', - 'uploading[uploading,name.png,0/82/82,-,result,-]', - 'update[uploading,name.png,0/82/82,-,result,-]', - 'update[uploading,name.png,41/82/82,-,result,-]', - 'error[error,name.png,41/82/82,networkError,result,-]', - 'update[error,name.png,41/82/82,networkError,result,-]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/41/82/null,-,-,-]', + 'uploading[uploading,name.png,0/82/82/null,-,result,-]', + 'update[uploading,name.png,0/82/82/null,-,result,-]', + 'update[uploading,name.png,41/82/82/100,-,result,-]', + 'error[error,name.png,41/82/82/100,networkError,result,-]', + 'update[error,name.png,41/82/82/100,networkError,result,-]' ] ); } ); loader.loadAndUpload( 'http:\/\/url\/' ); @@ -658,11 +671,11 @@ resumeAfter( loader, 'error', function() { observer.assert( [ - 'loading[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/0/82,-,-,-]', - 'update[loading,name.png,0/41/82,-,-,-]', - 'error[error,name.png,0/82/82,noUrlError,result,-]', - 'update[error,name.png,0/82/82,noUrlError,result,-]' ] ); + 'loading[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/0/82/null,-,-,-]', + 'update[loading,name.png,0/41/82/null,-,-,-]', + 'error[error,name.png,0/82/82/null,noUrlError,result,-]', + 'update[error,name.png,0/82/82/null,noUrlError,result,-]' ] ); } ); loader.loadAndUpload(); @@ -680,11 +693,12 @@ resumeAfter( loader, 'error', function() { observer.assert( [ - 'uploading[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,41/0/82,-,-,-]', - 'error[error,name.png,82/0/82,responseError,-,-]', - 'update[error,name.png,82/0/82,responseError,-,-]' ] ); + 'uploading[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'error[error,name.png,100/0/82/100,responseError,-,-]', + 'update[error,name.png,100/0/82/100,responseError,-,-]' ] ); } ); loader.upload( 'http:\/\/url\/' ); @@ -710,11 +724,12 @@ resumeAfter( loader, 'error', function() { observer.assert( [ - 'uploading[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,41/0/82,-,-,-]', - 'error[error,name.png,82/0/82,errorFromServer,-,-]', - 'update[error,name.png,82/0/82,errorFromServer,-,-]' ] ); + 'uploading[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'error[error,name.png,100/0/82/100,errorFromServer,-,-]', + 'update[error,name.png,100/0/82/100,errorFromServer,-,-]' ] ); } ); loader.upload( 'http:\/\/url\/' ); @@ -740,11 +755,12 @@ resumeAfter( loader, 'uploaded', function() { observer.assert( [ - 'uploading[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,41/0/82,-,-,-]', - 'uploaded[uploaded,name2.png,82/0/82,messageFromServer,-,http://url/name2.png]', - 'update[uploaded,name2.png,82/0/82,messageFromServer,-,http://url/name2.png]' ] ); + 'uploading[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'uploaded[uploaded,name2.png,100/0/82/100,messageFromServer,-,http://url/name2.png]', + 'update[uploaded,name2.png,100/0/82/100,messageFromServer,-,http://url/name2.png]' ] ); } ); loader.upload( 'http:\/\/url\/' ); @@ -762,11 +778,12 @@ resumeAfter( loader, 'error', function() { observer.assert( [ - 'uploading[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,41/0/82,-,-,-]', - 'error[error,name.png,82/0/82,httpError404,-,-]', - 'update[error,name.png,82/0/82,httpError404,-,-]' ] ); + 'uploading[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'error[error,name.png,100/0/82/100,httpError404,-,-]', + 'update[error,name.png,100/0/82/100,httpError404,-,-]' ] ); } ); loader.upload( 'http:\/\/url\/' ); @@ -784,11 +801,12 @@ resumeAfter( loader, 'error', function() { observer.assert( [ - 'uploading[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,41/0/82,-,-,-]', - 'error[error,name.png,82/0/82,httpError 404,-,-]', - 'update[error,name.png,82/0/82,httpError 404,-,-]' ] ); + 'uploading[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'error[error,name.png,100/0/82/100,httpError 404,-,-]', + 'update[error,name.png,100/0/82/100,httpError 404,-,-]' ] ); } ); loader.upload( 'http:\/\/url\/' ); @@ -804,11 +822,12 @@ resumeAfter( loader, 'uploaded', function() { observer.assert( [ - 'uploading[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,41/0/82,-,-,-]', - 'uploaded[uploaded,name2.png,82/0/82,-,-,http://url/name2.png]', - 'update[uploaded,name2.png,82/0/82,-,-,http://url/name2.png]' ] ); + 'uploading[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'uploaded[uploaded,name2.png,100/0/82/100,-,-,http://url/name2.png]', + 'update[uploaded,name2.png,100/0/82/100,-,-,http://url/name2.png]' ] ); } ); loader.upload( 'http:\/\/url\/' ); @@ -829,14 +848,15 @@ // Wait for all update events. wait( function() { observer.assert( [ - 'update[created,name.png,0/0/82,-,-,-]', - 'uploading[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,41/0/82,-,-,-]', - 'update[uploading,name.png,41/0/82,-,-,-]', - 'uploaded[uploaded,name2.png,82/0/82,-,-,http://url/name2.png]', - 'update[uploaded,name2.png,82/0/82,-,-,http://url/name2.png]', - 'update[uploaded,name2.png,82/0/82,-,-,http://url/name2.png]' ] ); + 'update[created,name.png,0/0/82/null,-,-,-]', + 'uploading[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'uploaded[uploaded,name2.png,100/0/82/100,-,-,http://url/name2.png]', + 'update[uploaded,name2.png,100/0/82/100,-,-,http://url/name2.png]', + 'update[uploaded,name2.png,100/0/82/100,-,-,http://url/name2.png]' ] ); }, 5 ); } ); @@ -881,11 +901,12 @@ assert.areSame( 'custom form', lastFormData ); observer.assert( [ - 'uploading[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,41/0/82,-,-,-]', - 'uploaded[uploaded,customName.png,82/0/82,customMessage,-,customUrl]', - 'update[uploaded,customName.png,82/0/82,customMessage,-,customUrl]' ] ); + 'uploading[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'uploaded[uploaded,customName.png,100/0/82/100,customMessage,-,customUrl]', + 'update[uploaded,customName.png,100/0/82/100,customMessage,-,customUrl]' ] ); } ); loader.upload( 'http:\/\/url\/' ); @@ -925,11 +946,12 @@ resumeAfter( loader, 'error', function() { observer.assert( [ - 'uploading[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,0/0/82,-,-,-]', - 'update[uploading,name.png,41/0/82,-,-,-]', - 'error[error,name.png,82/0/82,-,-,-]', - 'update[error,name.png,82/0/82,-,-,-]' ] ); + 'uploading[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,0/0/82/null,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'update[uploading,name.png,41/0/82/100,-,-,-]', + 'error[error,name.png,100/0/82/100,-,-,-]', + 'update[error,name.png,100/0/82/100,-,-,-]' ] ); } ); loader.upload( 'http:\/\/url\/' ); diff --git a/tests/plugins/uploadimage/uploadimage.js b/tests/plugins/uploadimage/uploadimage.js index c74c3ba40a1..72ac10986b2 100644 --- a/tests/plugins/uploadimage/uploadimage.js +++ b/tests/plugins/uploadimage/uploadimage.js @@ -96,6 +96,7 @@ var loader = editor.uploadRepository.loaders[ 0 ]; loader.data = bender.tools.pngBase64; + loader.uploadTotal = 10; loader.changeStatus( 'uploading' ); assertUploadingWidgets( editor, LOADED_IMG ); @@ -123,6 +124,7 @@ var loader = editor.uploadRepository.loaders[ 0 ]; loader.data = bender.tools.pngBase64; + loader.uploadTotal = 10; loader.changeStatus( 'uploading' ); var area = editor._.notificationArea; diff --git a/tests/plugins/uploadwidget/bindnotifications.js b/tests/plugins/uploadwidget/bindnotifications.js index 56c363234b6..2af12ae8c00 100644 --- a/tests/plugins/uploadwidget/bindnotifications.js +++ b/tests/plugins/uploadwidget/bindnotifications.js @@ -60,7 +60,9 @@ bender.test( { bindNotifications( editor, loader ); loader.fire( 'uploading' ); - + loader.uploadTotal = 4; + loader.uploaded = 1; + loader.fire( 'update' ); loader.fire( 'uploaded' ); assert.areSame( 1, notificationShowStub.callCount ); @@ -81,6 +83,7 @@ bender.test( { loader.status = 'uploading'; loader.uploaded = 1; + loader.uploadTotal = 4; loader.fire( 'update' ); assert.areSame( 1, notificationShowStub.callCount, 'show' ); @@ -114,7 +117,13 @@ bender.test( { bindNotifications( editor, loader ); + + loader.fire( 'uploading' ); + loader.uploaded = 1; + loader.uploadTotal = 4; + loader.fire( 'update' ); + loader.fire( 'upload' ); loader.message = 'foo'; loader.fire( 'error' ); @@ -134,7 +143,7 @@ bender.test( { loader.message = 'foo'; loader.fire( 'error' ); - assert.areSame( 2, notificationShowStub.callCount ); + assert.areSame( 1, notificationShowStub.callCount ); this.assertNotification( { message: 'foo', type: 'warning' }, notificationShowStub.lastCall.args[ 0 ].data.notification ); @@ -147,6 +156,9 @@ bender.test( { bindNotifications( editor, loader ); loader.fire( 'uploading' ); + loader.uploaded = 1; + loader.uploadTotal = 4; + loader.fire( 'update' ); loader.fire( 'abort' ); @@ -165,7 +177,7 @@ bender.test( { loader.fire( 'abort' ); - assert.areSame( 2, notificationShowStub.callCount ); + assert.areSame( 1, notificationShowStub.callCount ); this.assertNotification( { message: 'Upload aborted by the user.', type: 'info' }, notificationShowStub.lastCall.args[ 0 ].data.notification, @@ -188,24 +200,27 @@ bender.test( { loader1.total = 10; loader1.status = 'uploading'; - loader1.uploaded = 1; + loader1.uploaded = 0; + loader1.uploadTotal = 10; loader1.fire( 'update' ); loader2.total = 10; loader2.status = 'uploading'; - loader2.uploaded = 1; + loader2.uploaded = 0; + loader2.uploadTotal = 10; loader2.fire( 'update' ); loader3.total = 10; loader3.status = 'uploading'; - loader3.uploaded = 1; + loader3.uploaded = 0; + loader3.uploadTotal = 10; loader3.fire( 'update' ); loader1.fire( 'uploaded' ); assert.areSame( 1, notificationShowStub.callCount ); this.assertNotification( - { message: 'Uploading files, 1 of 3 done (34%)...', type: 'progress' }, + { message: 'Uploading files, 1 of 3 done (33%)...', type: 'progress' }, notificationShowStub.lastCall.args[ 0 ].data.notification ); loader2.fire( 'uploaded' ); @@ -239,24 +254,27 @@ bender.test( { loader1.total = 10; loader1.status = 'uploading'; - loader1.uploaded = 1; + loader1.uploaded = 0; + loader1.uploadTotal = 10; loader1.fire( 'update' ); loader2.total = 10; loader2.status = 'uploading'; - loader2.uploaded = 1; + loader2.uploaded = 0; + loader2.uploadTotal = 10; loader2.fire( 'update' ); loader3.total = 10; loader3.status = 'uploading'; - loader3.uploaded = 1; + loader3.uploaded = 0; + loader3.uploadTotal = 10; loader3.fire( 'update' ); loader1.fire( 'uploaded' ); assert.areSame( 1, notificationShowStub.callCount ); this.assertNotification( - { message: 'Uploading files, 1 of 3 done (34%)...', type: 'progress' }, + { message: 'Uploading files, 1 of 3 done (33%)...', type: 'progress' }, notificationShowStub.lastCall.args[ 0 ].data.notification ); loader2.message = 'foo'; @@ -264,7 +282,7 @@ bender.test( { assert.areSame( 2, notificationShowStub.callCount ); this.assertNotification( - { message: 'Uploading files, 1 of 2 done (51%)...', type: 'progress' }, + { message: 'Uploading files, 1 of 2 done (50%)...', type: 'progress' }, notificationShowStub.firstCall.args[ 0 ].data.notification ); this.assertNotification( { message: 'foo', type: 'warning' }, @@ -280,4 +298,4 @@ bender.test( { { message: 'foo', type: 'warning' }, notificationShowStub.lastCall.args[ 0 ].data.notification ); } -} ); \ No newline at end of file +} ); diff --git a/tests/plugins/uploadwidget/manual/_helpers/xhr.js b/tests/plugins/uploadwidget/manual/_helpers/xhr.js index e2b716a4395..5b75e89f78b 100644 --- a/tests/plugins/uploadwidget/manual/_helpers/xhr.js +++ b/tests/plugins/uploadwidget/manual/_helpers/xhr.js @@ -30,12 +30,14 @@ window.XMLHttpRequest = function() { return { open: function() {}, + upload: {}, + send: function( formData ) { var total = formData.getTotal(), loaded = 0, step = Math.round( total / 10 ), xhr = this, - onprogress = this.onprogress, + onprogress = this.upload.onprogress, onload = this.onload; // Wait 400 ms for every step. @@ -48,7 +50,7 @@ window.XMLHttpRequest = function() { // If file is not loaded call onprogress. if ( loaded < total ) { - onprogress( { loaded: loaded } ); + onprogress( { loaded: loaded, total: total, lengthComputable: true } ); } // If file is loaded call onload. else { diff --git a/tests/plugins/uploadwidget/manual/_helpers/xhrerror.js b/tests/plugins/uploadwidget/manual/_helpers/xhrerror.js index 2f4fadeb552..2f20510eea8 100644 --- a/tests/plugins/uploadwidget/manual/_helpers/xhrerror.js +++ b/tests/plugins/uploadwidget/manual/_helpers/xhrerror.js @@ -27,12 +27,14 @@ window.XMLHttpRequest = function() { return { open: function() {}, + upload: {}, + send: function( formData ) { // Total file size. var total = formData.getTotal(), loaded = 0, step = Math.round( total / 10 ), - onprogress = this.onprogress, + onprogress = this.upload.onprogress, onerror = this.onerror, interval; @@ -43,7 +45,7 @@ window.XMLHttpRequest = function() { // If less then 50% of file is loaded call onprogress. if ( loaded < step * 5 ) { - onprogress( { loaded: loaded } ); + onprogress( { loaded: loaded, total: total, lengthComputable: true } ); } // If 50% of file is loaded call onerror and stop loading. else { @@ -58,4 +60,4 @@ window.XMLHttpRequest = function() { this.onabort(); } }; -}; \ No newline at end of file +}; diff --git a/tests/plugins/uploadwidget/manual/_helpers/xhrnoupload.js b/tests/plugins/uploadwidget/manual/_helpers/xhrnoupload.js new file mode 100644 index 00000000000..1dd582e81f9 --- /dev/null +++ b/tests/plugins/uploadwidget/manual/_helpers/xhrnoupload.js @@ -0,0 +1,63 @@ +/** + * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or http://ckeditor.com/license + */ + +'use strict'; + +// Mock the real XMLHttpRequest without upload object support. + +window.FormData = function() { + var total, filename; + return { + append: function( name, file, filename ) { + total = file.size; + filename = filename; + }, + getTotal: function() { + return total; + }, + getFileName: function() { + return filename; + } + }; +}; + +window.XMLHttpRequest = function() { + var basePath = bender.config.tests[ bender.testData.group ].basePath, + timeout; + + return { + open: function() {}, + + send: function( formData ) { + var xhr = this, + onload = this.onload; + + // Wait 1s and report onload without reporting progress during upload. + timeout = setTimeout( function() { + var responseData = { + fileName: formData.getFileName(), + uploaded: 1, + url: '\/' + basePath + '_assets\/lena.jpg', + error: { + number: 201, + message: '' + } + }; + CKEDITOR.tools.extend( responseData, XMLHttpRequest.responseData, true ); + + xhr.status = 200; + xhr.responseText = JSON.stringify( responseData ); + onload(); + }, 1000 ); + }, + + // Abort should call onabort. + abort: function() { + clearTimeout( timeout ); + this.status = 0; + this.onabort(); + } + }; +}; diff --git a/tests/plugins/uploadwidget/manual/nouploadprogress.md b/tests/plugins/uploadwidget/manual/nouploadprogress.md new file mode 100644 index 00000000000..e7ce5c9e01c --- /dev/null +++ b/tests/plugins/uploadwidget/manual/nouploadprogress.md @@ -0,0 +1,13 @@ +@bender-tags: 4.5.4,tc,13553,clipboard,widget,filetools +@bender-ui: collapsed +@bender-ckeditor-plugins: wysiwygarea, toolbar, undo, uploadwidget, basicstyles, image2, uploadimage, font, stylescombo, basicstyles, format, maximize, blockquote, list, table, resize, elementspath, justify +@bender-include: _helpers/xhrnoupload.js + +This test emulates situation when xhr.upload object is not present, so upload progress cannot be monitored. + + * Drop an image. + * Check if `upload widget` is displayed. + * Upload progress will not be reported - it will jump from 0% to upload success. + * Check if upload is complete and test image is visible. + +**Note:** This test use upload mock which will show you *Lena* instead of the real uploaded image.