diff options
author | Vincent Petry <pvince81@owncloud.com> | 2015-12-16 17:35:53 +0100 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2016-10-24 21:45:00 +0200 |
commit | 59c5be1cc572793a8d50e87ab589e1cc4cf2ed12 (patch) | |
tree | 97b096fee075115bac45d69f2e0da7af5ffb41f2 /apps/files/tests | |
parent | 4d01f23978549c2a33e9fdfdc3b9308cc9dc1078 (diff) | |
download | nextcloud-server-59c5be1cc572793a8d50e87ab589e1cc4cf2ed12.tar.gz nextcloud-server-59c5be1cc572793a8d50e87ab589e1cc4cf2ed12.zip |
Use Webdav PUT for uploads in the web browser
- uses PUT method with jquery.fileupload for regular and public file
lists
- for IE and browsers that don't support it, use POST with iframe
transport
- implemented Sabre plugin to handle iframe transport and redirect the
embedded PUT request to the proper handler
- added RFC5995 POST to file collection with "add-member" property to
make it possible to auto-rename conflicting file names
- remove obsolete ajax/upload.php and obsolete ajax routes
Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
Diffstat (limited to 'apps/files/tests')
-rw-r--r-- | apps/files/tests/js/fileUploadSpec.js | 141 | ||||
-rw-r--r-- | apps/files/tests/js/filelistSpec.js | 208 |
2 files changed, 257 insertions, 92 deletions
diff --git a/apps/files/tests/js/fileUploadSpec.js b/apps/files/tests/js/fileUploadSpec.js index 0483d4649d4..bfaf0a9fe57 100644 --- a/apps/files/tests/js/fileUploadSpec.js +++ b/apps/files/tests/js/fileUploadSpec.js @@ -19,11 +19,11 @@ * */ -/* global FileList */ - describe('OC.Upload tests', function() { var $dummyUploader; var testFile; + var uploader; + var failStub; beforeEach(function() { testFile = { @@ -46,59 +46,64 @@ describe('OC.Upload tests', function() { '</div>' ); $dummyUploader = $('#file_upload_start'); + uploader = new OC.Uploader($dummyUploader); + failStub = sinon.stub(); + $dummyUploader.on('fileuploadfail', failStub); }); afterEach(function() { - delete window.file_upload_param; $dummyUploader = undefined; + failStub = undefined; }); - describe('Adding files for upload', function() { - var params; - var failStub; - beforeEach(function() { - params = OC.Upload.init(); - failStub = sinon.stub(); - $dummyUploader.on('fileuploadfail', failStub); - }); - afterEach(function() { - params = undefined; - failStub = undefined; - }); - - /** - * Add file for upload - * @param file file data - */ - function addFile(file) { - return params.add.call( + /** + * Add file for upload + * @param {Array.<File>} files array of file data to simulate upload + * @return {Array.<Object>} array of uploadinfo or null if add() returned false + */ + function addFiles(uploader, files) { + return _.map(files, function(file) { + var jqXHR = {status: 200}; + var uploadInfo = { + originalFiles: files, + files: [file], + jqXHR: jqXHR, + response: sinon.stub.returns(jqXHR), + submit: sinon.stub() + }; + if (uploader.fileUploadParam.add.call( $dummyUploader[0], {}, - { - originalFiles: {}, - files: [file] - }); - } + uploadInfo + )) { + return uploadInfo; + } + return null; + }); + } + describe('Adding files for upload', function() { it('adds file when size is below limits', function() { - var result = addFile(testFile); - expect(result).toEqual(true); + var result = addFiles(uploader, [testFile]); + expect(result[0]).not.toEqual(null); + expect(result[0].submit.calledOnce).toEqual(true); }); it('adds file when free space is unknown', function() { var result; $('#free_space').val(-2); - result = addFile(testFile); + result = addFiles(uploader, [testFile]); - expect(result).toEqual(true); + expect(result[0]).not.toEqual(null); + expect(result[0].submit.calledOnce).toEqual(true); expect(failStub.notCalled).toEqual(true); }); it('does not add file if it exceeds upload limit', function() { var result; $('#upload_limit').val(1000); - result = addFile(testFile); + result = addFiles(uploader, [testFile]); - expect(result).toEqual(false); + expect(result[0]).toEqual(null); expect(failStub.calledOnce).toEqual(true); expect(failStub.getCall(0).args[1].textStatus).toEqual('sizeexceedlimit'); expect(failStub.getCall(0).args[1].errorThrown).toEqual( @@ -109,9 +114,9 @@ describe('OC.Upload tests', function() { var result; $('#free_space').val(1000); - result = addFile(testFile); + result = addFiles(uploader, [testFile]); - expect(result).toEqual(false); + expect(result[0]).toEqual(null); expect(failStub.calledOnce).toEqual(true); expect(failStub.getCall(0).args[1].textStatus).toEqual('notenoughspace'); expect(failStub.getCall(0).args[1].errorThrown).toEqual( @@ -120,12 +125,10 @@ describe('OC.Upload tests', function() { }); }); describe('Upload conflicts', function() { - var oldFileList; var conflictDialogStub; - var callbacks; + var fileList; beforeEach(function() { - oldFileList = FileList; $('#testArea').append( '<div id="tableContainer">' + '<table id="filestable">' + @@ -145,74 +148,56 @@ describe('OC.Upload tests', function() { '</table>' + '</div>' ); - FileList = new OCA.Files.FileList($('#tableContainer')); + fileList = new OCA.Files.FileList($('#tableContainer')); - FileList.add({name: 'conflict.txt', mimetype: 'text/plain'}); - FileList.add({name: 'conflict2.txt', mimetype: 'text/plain'}); + fileList.add({name: 'conflict.txt', mimetype: 'text/plain'}); + fileList.add({name: 'conflict2.txt', mimetype: 'text/plain'}); conflictDialogStub = sinon.stub(OC.dialogs, 'fileexists'); - callbacks = { - onNoConflicts: sinon.stub() - }; + + uploader = new OC.Uploader($dummyUploader, { + fileList: fileList + }); }); afterEach(function() { conflictDialogStub.restore(); - FileList.destroy(); - FileList = oldFileList; + fileList.destroy(); }); it('does not show conflict dialog when no client side conflict', function() { - var selection = { - // yes, the format of uploads is weird... - uploads: [ - {files: [{name: 'noconflict.txt'}]}, - {files: [{name: 'noconflict2.txt'}]} - ] - }; - - OC.Upload.checkExistingFiles(selection, callbacks); + var result = addFiles(uploader, [{name: 'noconflict.txt'}, {name: 'noconflict2.txt'}]); expect(conflictDialogStub.notCalled).toEqual(true); - expect(callbacks.onNoConflicts.calledOnce).toEqual(true); - expect(callbacks.onNoConflicts.calledWith(selection)).toEqual(true); + expect(result[0].submit.calledOnce).toEqual(true); + expect(result[1].submit.calledOnce).toEqual(true); }); it('shows conflict dialog when no client side conflict', function() { - var selection = { - // yes, the format of uploads is weird... - uploads: [ - {files: [{name: 'conflict.txt'}]}, - {files: [{name: 'conflict2.txt'}]}, - {files: [{name: 'noconflict.txt'}]} - ] - }; - var deferred = $.Deferred(); conflictDialogStub.returns(deferred.promise()); deferred.resolve(); - OC.Upload.checkExistingFiles(selection, callbacks); + var result = addFiles(uploader, [ + {name: 'conflict.txt'}, + {name: 'conflict2.txt'}, + {name: 'noconflict.txt'} + ]); expect(conflictDialogStub.callCount).toEqual(3); - expect(conflictDialogStub.getCall(1).args[0]) - .toEqual({files: [ { name: 'conflict.txt' } ]}); + expect(conflictDialogStub.getCall(1).args[0].getFileName()) + .toEqual('conflict.txt'); expect(conflictDialogStub.getCall(1).args[1]) .toEqual({ name: 'conflict.txt', mimetype: 'text/plain', directory: '/' }); expect(conflictDialogStub.getCall(1).args[2]).toEqual({ name: 'conflict.txt' }); // yes, the dialog must be called several times... - expect(conflictDialogStub.getCall(2).args[0]).toEqual({ - files: [ { name: 'conflict2.txt' } ] - }); + expect(conflictDialogStub.getCall(2).args[0].getFileName()).toEqual('conflict2.txt'); expect(conflictDialogStub.getCall(2).args[1]) .toEqual({ name: 'conflict2.txt', mimetype: 'text/plain', directory: '/' }); expect(conflictDialogStub.getCall(2).args[2]).toEqual({ name: 'conflict2.txt' }); - expect(callbacks.onNoConflicts.calledOnce).toEqual(true); - expect(callbacks.onNoConflicts.calledWith({ - uploads: [ - {files: [{name: 'noconflict.txt'}]} - ] - })).toEqual(true); + expect(result[0].submit.calledOnce).toEqual(false); + expect(result[1].submit.calledOnce).toEqual(false); + expect(result[2].submit.calledOnce).toEqual(true); }); }); }); diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index 304f8438a59..55ab2c535af 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -159,7 +159,8 @@ describe('OCA.Files.FileList tests', function() { pageSizeStub = sinon.stub(OCA.Files.FileList.prototype, 'pageSize').returns(20); fileList = new OCA.Files.FileList($('#app-content-files'), { filesClient: filesClient, - config: filesConfig + config: filesConfig, + enableUpload: true }); }); afterEach(function() { @@ -2441,7 +2442,7 @@ describe('OCA.Files.FileList tests', function() { deferredInfo.resolve( 200, - new FileInfo({ + new FileInfo({ path: '/subdir', name: 'test.txt', mimetype: 'text/plain' @@ -2501,12 +2502,70 @@ describe('OCA.Files.FileList tests', function() { // TODO: error cases // TODO: unique name cases }); + describe('addAndFetchFileInfo', function() { + var getFileInfoStub; + var getFileInfoDeferred; + + beforeEach(function() { + getFileInfoDeferred = $.Deferred(); + getFileInfoStub = sinon.stub(OC.Files.Client.prototype, 'getFileInfo'); + getFileInfoStub.returns(getFileInfoDeferred.promise()); + }); + afterEach(function() { + getFileInfoStub.restore(); + }); + it('does not fetch if the given folder is not the current one', function() { + var promise = fileList.addAndFetchFileInfo('testfile.txt', '/another'); + expect(getFileInfoStub.notCalled).toEqual(true); + + expect(promise.state()).toEqual('resolved'); + }); + it('fetches info when folder is the current one', function() { + fileList.addAndFetchFileInfo('testfile.txt', '/subdir'); + expect(getFileInfoStub.calledOnce).toEqual(true); + expect(getFileInfoStub.getCall(0).args[0]).toEqual('/subdir/testfile.txt'); + }); + it('adds file data to list when fetching is done', function() { + fileList.addAndFetchFileInfo('testfile.txt', '/subdir'); + getFileInfoDeferred.resolve(200, { + name: 'testfile.txt', + size: 100 + }); + expect(fileList.findFileEl('testfile.txt').attr('data-size')).toEqual('100'); + }); + it('replaces file data to list when fetching is done', function() { + fileList.addAndFetchFileInfo('testfile.txt', '/subdir', {replace: true}); + fileList.add({ + name: 'testfile.txt', + size: 95 + }); + getFileInfoDeferred.resolve(200, { + name: 'testfile.txt', + size: 100 + }); + expect(fileList.findFileEl('testfile.txt').attr('data-size')).toEqual('100'); + }); + it('resolves promise with file data when fetching is done', function() { + var promise = fileList.addAndFetchFileInfo('testfile.txt', '/subdir', {replace: true}); + getFileInfoDeferred.resolve(200, { + name: 'testfile.txt', + size: 100 + }); + expect(promise.state()).toEqual('resolved'); + promise.then(function(status, data) { + expect(status).toEqual(200); + expect(data.name).toEqual('testfile.txt'); + expect(data.size).toEqual(100); + }); + }); + }); /** * Test upload mostly by testing the code inside the event handlers * that were registered on the magic upload object */ describe('file upload', function() { var $uploader; + var uploadData; beforeEach(function() { // note: this isn't the real blueimp file uploader from jquery.fileupload @@ -2514,14 +2573,52 @@ describe('OCA.Files.FileList tests', function() { // test the response of the handlers $uploader = $('#file_upload_start'); fileList.setFiles(testFiles); + // simulate data structure from jquery.upload + uploadData = { + files: [{ + name: 'upload.txt' + }] + }; }); afterEach(function() { $uploader = null; + uploadData = null; }); + describe('enableupload', function() { + it('sets up uploader when enableUpload is true', function() { + expect(fileList._uploader).toBeDefined(); + }); + it('does not sets up uploader when enableUpload is false', function() { + fileList.destroy(); + fileList = new OCA.Files.FileList($('#app-content-files'), { + filesClient: filesClient + }); + expect(fileList._uploader).toBeFalsy(); + }); + }); + + describe('adding files for upload', function() { + /** + * Simulate add event on the given target + * + * @return event object including the result + */ + function addFile(data) { + var ev = new $.Event('fileuploadadd', {}); + // using triggerHandler instead of trigger so we can pass + // extra data + $uploader.triggerHandler(ev, data || {}); + return ev; + } + + it('sets target dir to the current directory', function() { + addFile(uploadData); + expect(uploadData.targetDir).toEqual('/subdir'); + }); + }); describe('dropping external files', function() { - var uploadData; /** * Simulate drop event on the given target @@ -2540,17 +2637,6 @@ describe('OCA.Files.FileList tests', function() { return ev; } - beforeEach(function() { - // simulate data structure from jquery.upload - uploadData = { - files: [{ - relativePath: 'fileToUpload.txt' - }] - }; - }); - afterEach(function() { - uploadData = null; - }); it('drop on a tr or crumb outside file list does not trigger upload', function() { var $anotherTable = $('<table><tbody><tr><td>outside<div class="crumb">crumb</div></td></tr></table>'); var ev; @@ -2574,12 +2660,14 @@ describe('OCA.Files.FileList tests', function() { ev = dropOn(fileList.$fileList.find('th:first'), uploadData); expect(ev.result).not.toEqual(false); + expect(uploadData.targetDir).toEqual('/subdir'); }); it('drop on an element on the table container triggers upload', function() { var ev; ev = dropOn($('#app-content-files'), uploadData); expect(ev.result).not.toEqual(false); + expect(uploadData.targetDir).toEqual('/subdir'); }); it('drop on an element inside the table does not trigger upload if no upload permission', function() { $('#permissions').val(0); @@ -2603,6 +2691,7 @@ describe('OCA.Files.FileList tests', function() { ev = dropOn(fileList.findFileEl('One.txt').find('td:first'), uploadData); expect(ev.result).not.toEqual(false); + expect(uploadData.targetDir).toEqual('/subdir'); }); it('drop on a folder row inside the table triggers upload to target folder', function() { var ev; @@ -2635,6 +2724,97 @@ describe('OCA.Files.FileList tests', function() { expect(fileList.findFileEl('afile.txt').find('.uploadtext').length).toEqual(0); }); }); + + describe('after folder creation due to folder upload', function() { + it('fetches folder info', function() { + var fetchInfoStub = sinon.stub(fileList, 'addAndFetchFileInfo'); + + var ev = new $.Event('fileuploadcreatedfolder', {}); + $uploader.triggerHandler(ev, '/subdir/newfolder'); + + expect(fetchInfoStub.calledOnce).toEqual(true); + expect(fetchInfoStub.getCall(0).args[0]).toEqual('newfolder'); + expect(fetchInfoStub.getCall(0).args[1]).toEqual('/subdir'); + + fetchInfoStub.restore(); + }); + }); + + describe('after upload', function() { + var fetchInfoStub; + + beforeEach(function() { + fetchInfoStub = sinon.stub(fileList, 'addAndFetchFileInfo'); + + }); + afterEach(function() { + fetchInfoStub.restore(); + }); + + + function createUpload(name, dir) { + var data = { + files: [{ + name: name + }], + upload: { + getFileName: sinon.stub().returns(name), + getFullPath: sinon.stub().returns(dir) + }, + jqXHR: { + status: 200 + } + } + return data; + } + + /** + * Simulate add event on the given target + * + * @return event object including the result + */ + function addFile(data) { + var ev = new $.Event('fileuploaddone', {}); + // using triggerHandler instead of trigger so we can pass + // extra data + var deferred = $.Deferred(); + fetchInfoStub.returns(deferred.promise()); + $uploader.triggerHandler(ev, data || {}); + return deferred; + } + + it('fetches file info', function() { + addFile(createUpload('upload.txt', '/subdir')); + expect(fetchInfoStub.calledOnce).toEqual(true); + expect(fetchInfoStub.getCall(0).args[0]).toEqual('upload.txt'); + expect(fetchInfoStub.getCall(0).args[1]).toEqual('/subdir'); + }); + it('highlights all uploaded files after all fetches are done', function() { + var highlightStub = sinon.stub(fileList, 'highlightFiles'); + var def1 = addFile(createUpload('upload.txt', '/subdir')); + var def2 = addFile(createUpload('upload2.txt', '/subdir')); + var def3 = addFile(createUpload('upload3.txt', '/another')); + $uploader.triggerHandler(new $.Event('fileuploadstop')); + + expect(highlightStub.notCalled).toEqual(true); + def1.resolve(); + expect(highlightStub.notCalled).toEqual(true); + def2.resolve(); + def3.resolve(); + expect(highlightStub.calledOnce).toEqual(true); + expect(highlightStub.getCall(0).args[0]).toEqual(['upload.txt', 'upload2.txt']); + + highlightStub.restore(); + }); + it('queries storage stats', function() { + var statStub = sinon.stub(fileList, 'updateStorageStatistics'); + addFile(createUpload('upload.txt', '/subdir')); + expect(statStub.notCalled).toEqual(true); + $uploader.triggerHandler(new $.Event('fileuploadstop')); + expect(statStub.calledOnce).toEqual(true); + statStub.restore(); + }); + }); }); describe('Handling errors', function () { var deferredList; |