2 * jQuery File Upload Test
3 * https://github.com/blueimp/JavaScript-Load-Image
5 * Copyright 2010, Sebastian Tschan
8 * Licensed under the MIT license:
9 * https://opensource.org/licenses/MIT
12 /* global beforeEach, afterEach, describe, it */
13 /* eslint-disable new-cap */
15 (function (expect, $) {
18 var canCreateBlob = !!window.dataURLtoBlob;
19 // 80x60px GIF image (color black, base64 data):
21 'R0lGODdhUAA8AIABAAAAAP///ywAAAAAUAA8AAACS4SPqcvtD6' +
22 'OctNqLs968+w+G4kiW5omm6sq27gvH8kzX9o3n+s73/g8MCofE' +
23 'ovGITCqXzKbzCY1Kp9Sq9YrNarfcrvcLDovH5PKsAAA7';
24 var imageUrlGIF = 'data:image/gif;base64,' + b64DataGIF;
25 var blobGIF = canCreateBlob && window.dataURLtoBlob(imageUrlGIF);
27 // 2x1px JPEG (color white, with the Exif orientation flag set to 6 and the
28 // IPTC ObjectName (2:5) set to 'objectname'):
30 '/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAASUkqAAgAAAABABIBAwABAAAA' +
31 'BgASAAAAAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAA8cAgUACm9iamVj' +
32 'dG5hbWUA/9sAQwABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB' +
33 'AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB/9sAQwEBAQEBAQEBAQEBAQEBAQEB' +
34 'AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB' +
35 '/8AAEQgAAQACAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYH' +
36 'CAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGh' +
37 'CCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldY' +
38 'WVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1' +
39 'tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8B' +
40 'AAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAEC' +
41 'dwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBka' +
42 'JicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWG' +
43 'h4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ' +
44 '2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A/v4ooooA/9k=';
45 var imageUrlJPEG = 'data:image/jpeg;base64,' + b64DataJPEG;
46 var blobJPEG = canCreateBlob && window.dataURLtoBlob(imageUrlJPEG);
48 var fileGIF, fileJPEG, files, items, eventObject;
50 var uploadURL = '../server/php/';
53 * Creates a fileupload form and adds it to the DOM
55 * @returns {object} jQuery node
57 function createFileuploadForm() {
58 return $('<form><input type="file" name="files[]" multiple></form>')
62 enctype: 'multipart/form-data'
64 .css({ display: 'none' })
65 .appendTo(document.body);
69 * Deletes all files from the upload server
71 * @param {Array} files Response files list
72 * @param {Function} callback Callback function
74 function deleteFiles(files, callback) {
76 files.map(function (file) {
78 type: file.deleteType,
82 ).always(function () {
87 beforeEach(function () {
88 fileGIF = new File([blobGIF], 'example.gif', { type: 'image/gif' });
89 fileJPEG = new File([blobJPEG], 'example.jpg', { type: 'image/jpeg' });
90 files = [fileGIF, fileJPEG];
93 getAsFile: function () {
98 getAsFile: function () {
105 dataTransfer: { files: files, types: ['Files'] },
106 clipboardData: { items: items }
111 afterEach(function (done) {
112 $.getJSON(uploadURL).then(function (result) {
113 deleteFiles(result.files, done);
117 describe('Initialization', function () {
120 beforeEach(function () {
121 form = createFileuploadForm();
124 afterEach(function () {
128 it('widget', function () {
130 expect(form.data('blueimp-fileupload')).to.be.an('object');
133 it('file input', function () {
135 expect(form.fileupload('option', 'fileInput').length).to.equal(1);
138 it('drop zone', function () {
140 expect(form.fileupload('option', 'dropZone').length).to.equal(1);
143 it('paste zone', function () {
144 form.fileupload({ pasteZone: document });
145 expect(form.fileupload('option', 'pasteZone').length).to.equal(1);
148 it('data attributes', function () {
149 form.attr('data-url', 'https://example.org');
151 expect(form.fileupload('option', 'url')).to.equal('https://example.org');
152 expect(form.data('blueimp-fileupload')).to.be.an('object');
155 it('event listeners', function () {
160 dragover: function () {
161 eventsData.dragover = true;
163 dragenter: function () {
164 eventsData.dragenter = true;
166 dragleave: function () {
167 eventsData.dragleave = true;
169 drop: function (e, data) {
170 eventsData.drop = data;
172 paste: function (e, data) {
173 eventsData.paste = data;
175 change: function () {
176 eventsData.change = true;
180 .fileupload('option', 'fileInput')
181 .trigger($.Event('change', eventObject));
182 expect(eventsData.change).to.equal(true);
184 .fileupload('option', 'dropZone')
185 .trigger($.Event('dragover', eventObject))
186 .trigger($.Event('dragenter', eventObject))
187 .trigger($.Event('dragleave', eventObject))
188 .trigger($.Event('drop', eventObject));
189 expect(eventsData.dragover).to.equal(true);
190 expect(eventsData.dragenter).to.equal(true);
191 expect(eventsData.dragleave).to.equal(true);
192 expect(eventsData.drop.files).to.deep.equal(files);
194 .fileupload('option', 'pasteZone')
195 .trigger($.Event('paste', eventObject));
196 expect(eventsData.paste.files).to.deep.equal(files);
200 describe('API', function () {
203 beforeEach(function () {
204 form = createFileuploadForm().fileupload({
210 afterEach(function () {
214 it('destroy', function () {
216 form.fileupload('option', {
218 dragover: function () {
219 eventsData.dragover = true;
221 dragenter: function () {
222 eventsData.dragenter = true;
224 dragleave: function () {
225 eventsData.dragleave = true;
227 drop: function (e, data) {
228 eventsData.drop = data;
230 paste: function (e, data) {
231 eventsData.paste = data;
233 change: function () {
234 eventsData.change = true;
237 var fileInput = form.fileupload('option', 'fileInput');
238 var dropZone = form.fileupload('option', 'dropZone');
239 var pasteZone = form.fileupload('option', 'pasteZone');
240 form.fileupload('destroy');
241 expect(form.data('blueimp-fileupload')).to.equal();
242 fileInput.trigger($.Event('change', eventObject));
243 expect(eventsData.change).to.equal();
245 .trigger($.Event('dragover', eventObject))
246 .trigger($.Event('dragenter', eventObject))
247 .trigger($.Event('dragleave', eventObject))
248 .trigger($.Event('drop', eventObject));
249 expect(eventsData.dragover).to.equal();
250 expect(eventsData.dragenter).to.equal();
251 expect(eventsData.dragleave).to.equal();
252 expect(eventsData.drop).to.equal();
253 pasteZone.trigger($.Event('paste', eventObject));
254 expect(eventsData.paste).to.equal();
257 it('disable', function () {
259 form.fileupload('option', {
261 dragover: function () {
262 eventsData.dragover = true;
264 dragenter: function () {
265 eventsData.dragenter = true;
267 dragleave: function () {
268 eventsData.dragleave = true;
270 drop: function (e, data) {
271 eventsData.drop = data;
273 paste: function (e, data) {
274 eventsData.paste = data;
276 change: function () {
277 eventsData.change = true;
280 form.fileupload('disable');
282 .fileupload('option', 'fileInput')
283 .trigger($.Event('change', eventObject));
284 expect(eventsData.change).to.equal();
286 .fileupload('option', 'dropZone')
287 .trigger($.Event('dragover', eventObject))
288 .trigger($.Event('dragenter', eventObject))
289 .trigger($.Event('dragleave', eventObject))
290 .trigger($.Event('drop', eventObject));
291 expect(eventsData.dragover).to.equal();
292 expect(eventsData.dragenter).to.equal();
293 expect(eventsData.dragleave).to.equal();
294 expect(eventsData.drop).to.equal();
296 .fileupload('option', 'pasteZone')
297 .trigger($.Event('paste', eventObject));
298 expect(eventsData.paste).to.equal();
301 it('enable', function () {
303 form.fileupload('option', {
305 dragover: function () {
306 eventsData.dragover = true;
308 dragenter: function () {
309 eventsData.dragenter = true;
311 dragleave: function () {
312 eventsData.dragleave = true;
314 drop: function (e, data) {
315 eventsData.drop = data;
317 paste: function (e, data) {
318 eventsData.paste = data;
320 change: function () {
321 eventsData.change = true;
324 form.fileupload('disable');
325 form.fileupload('enable');
327 .fileupload('option', 'fileInput')
328 .trigger($.Event('change', eventObject));
329 expect(eventsData.change).to.equal(true);
331 .fileupload('option', 'dropZone')
332 .trigger($.Event('dragover', eventObject))
333 .trigger($.Event('dragenter', eventObject))
334 .trigger($.Event('dragleave', eventObject))
335 .trigger($.Event('drop', eventObject));
336 expect(eventsData.dragover).to.equal(true);
337 expect(eventsData.dragenter).to.equal(true);
338 expect(eventsData.dragleave).to.equal(true);
339 expect(eventsData.drop.files).to.deep.equal(files);
341 .fileupload('option', 'pasteZone')
342 .trigger($.Event('paste', eventObject));
343 expect(eventsData.paste.files).to.deep.equal(files);
346 it('option', function () {
348 form.fileupload('option', 'drop', function (e, data) {
349 eventsData.drop = data;
352 .fileupload('option', 'dropZone')
353 .trigger($.Event('drop', eventObject));
354 expect(eventsData.drop.files).to.deep.equal(files);
355 delete eventsData.drop;
356 form.fileupload('option', 'dropZone', null);
357 dropZone.trigger($.Event('drop', eventObject));
358 expect(eventsData.drop).to.equal();
359 form.fileupload('option', {
362 dropZone.trigger($.Event('drop', eventObject));
363 expect(eventsData.drop.files).to.deep.equal(files);
366 it('add', function () {
368 form.fileupload('option', 'add', function (e, data) {
369 eventData.push(data);
371 form.fileupload('add', { files: files });
372 expect(eventData.length).to.equal(2);
373 expect(eventData[0].files[0]).to.equal(files[0]);
374 expect(eventData[1].files[0]).to.equal(files[1]);
377 it('send', function (done) {
379 form.fileupload('send', { files: files }).complete(function (result) {
380 var uploadedFiles = result.responseJSON.files;
381 expect(uploadedFiles.length).to.equal(2);
382 expect(uploadedFiles[0].type).to.equal(files[0].type);
383 expect(uploadedFiles[0].error).to.equal();
384 expect(uploadedFiles[1].type).to.equal(files[1].type);
385 expect(uploadedFiles[1].error).to.equal();
391 describe('Callbacks', function () {
394 beforeEach(function () {
395 form = createFileuploadForm().fileupload({ dataType: 'json' });
398 afterEach(function () {
402 it('add', function () {
404 form.fileupload('option', 'add', function (e, data) {
405 eventData.push(data);
407 form.fileupload('add', { files: files });
408 expect(eventData.length).to.equal(2);
409 expect(eventData[0].files[0]).to.equal(files[0]);
410 expect(eventData[1].files[0]).to.equal(files[1]);
413 it('submit', function (done) {
416 form.fileupload('option', {
417 submit: function (e, data) {
418 eventData.push(data);
421 if (eventData.length < 2) return;
422 expect(eventData[0].files[0]).to.equal(files[0]);
423 expect(eventData[1].files[0]).to.equal(files[1]);
427 form.fileupload('add', { files: files });
430 it('send', function (done) {
433 form.fileupload('option', {
434 send: function (e, data) {
435 eventData.push(data);
438 expect(eventData.length).to.equal(1);
439 expect(eventData[0].files).to.deep.equal(files);
443 form.fileupload('send', { files: files });
446 it('done', function (done) {
449 form.fileupload('option', {
450 done: function (e, data) {
451 eventData.push(data);
454 if (eventData.length < 2) return;
455 expect(eventData[0].result.files.length).to.equal(1);
456 expect(eventData[1].result.files.length).to.equal(1);
460 form.fileupload('add', { files: files });
463 it('fail', function (done) {
466 form.fileupload('option', {
467 url: uploadURL + '404',
468 fail: function (e, data) {
469 eventData.push(data);
472 if (eventData.length < 2) return;
473 expect(eventData[0].result).to.equal();
474 expect(eventData[1].result).to.equal();
478 form.fileupload('add', { files: files });
481 it('always', function (done) {
484 form.fileupload('option', {
485 always: function (e, data) {
486 eventData.push(data);
489 if (eventData.length < 2) {
490 expect(eventData[0].result).to.equal();
491 form.fileupload('add', { files: [fileGIF] });
494 expect(eventData[1].result.files.length).to.equal(1);
498 form.fileupload('add', { files: [fileGIF], url: uploadURL + '404' });
501 it('progress', function (done) {
505 form.fileupload('option', {
506 progress: function (e, data) {
507 loaded = data.loaded;
509 expect(loaded).to.be.at.most(total);
512 expect(loaded).to.equal(total);
516 form.fileupload('add', { files: [fileGIF] });
519 it('progressall', function (done) {
524 form.fileupload('option', {
525 progressall: function (e, data) {
526 loaded = data.loaded;
528 expect(loaded).to.be.at.most(total);
530 always: function () {
534 if (completed < 2) return;
535 expect(loaded).to.equal(total);
539 form.fileupload('add', { files: files });
542 it('start', function (done) {
545 form.fileupload('option', {
550 expect(started).to.equal(true);
554 form.fileupload('add', { files: [fileGIF] });
557 it('stop', function (done) {
559 form.fileupload('option', {
564 form.fileupload('add', { files: [fileGIF] });
567 it('dragover', function () {
569 form.fileupload('option', {
571 dragover: function () {
572 eventsData.dragover = true;
576 .fileupload('option', 'dropZone')
577 .trigger($.Event('dragover', eventObject));
578 expect(eventsData.dragover).to.equal(true);
581 it('dragenter', function () {
583 form.fileupload('option', {
585 dragenter: function () {
586 eventsData.dragenter = true;
590 .fileupload('option', 'dropZone')
591 .trigger($.Event('dragenter', eventObject));
592 expect(eventsData.dragenter).to.equal(true);
595 it('dragleave', function () {
597 form.fileupload('option', {
599 dragleave: function () {
600 eventsData.dragleave = true;
604 .fileupload('option', 'dropZone')
605 .trigger($.Event('dragleave', eventObject));
606 expect(eventsData.dragleave).to.equal(true);
609 it('drop', function () {
611 form.fileupload('option', {
613 drop: function (e, data) {
614 eventsData.drop = data;
618 .fileupload('option', 'dropZone')
619 .trigger($.Event('drop', eventObject));
620 expect(eventsData.drop.files).to.deep.equal(files);
623 it('paste', function () {
625 form.fileupload('option', {
628 paste: function (e, data) {
629 eventsData.paste = data;
633 .fileupload('option', 'pasteZone')
634 .trigger($.Event('paste', eventObject));
635 expect(eventsData.paste.files).to.deep.equal(files);
638 it('change', function () {
640 form.fileupload('option', {
642 change: function () {
643 eventsData.change = true;
647 .fileupload('option', 'fileInput')
648 .trigger($.Event('change', eventObject));
649 expect(eventsData.change).to.equal(true);
653 describe('Options', function () {
656 beforeEach(function () {
657 form = createFileuploadForm();
660 afterEach(function () {
664 it('paramName', function (done) {
666 send: function (e, data) {
667 expect(data.paramName[0]).to.equal(
668 form.fileupload('option', 'fileInput').prop('name')
674 form.fileupload('add', { files: [fileGIF] });
677 it('url', function (done) {
679 send: function (e, data) {
680 expect(data.url).to.equal(form.prop('action'));
685 form.fileupload('add', { files: [fileGIF] });
688 it('type', function (done) {
691 send: function (e, data) {
692 expect(data.type).to.equal('PUT');
697 form.fileupload('add', { files: [fileGIF] });
700 it('replaceFileInput', function () {
702 var fileInput = form.fileupload('option', 'fileInput');
703 fileInput.trigger($.Event('change', eventObject));
704 expect(form.fileupload('option', 'fileInput')[0]).to.not.equal(
707 form.fileupload('option', 'replaceFileInput', false);
708 fileInput = form.fileupload('option', 'fileInput');
709 fileInput.trigger($.Event('change', eventObject));
710 expect(form.fileupload('option', 'fileInput')[0]).to.equal(fileInput[0]);
713 it('forceIframeTransport', function (done) {
715 forceIframeTransport: 'PUT',
716 send: function (e, data) {
717 expect(data.dataType.substr(0, 6)).to.equal('iframe');
722 form.fileupload('add', { files: [fileGIF] });
725 it('singleFileUploads', function (done) {
727 singleFileUploads: false,
728 send: function (e, data) {
729 expect(data.files).to.deep.equal(files);
734 form.fileupload('add', { files: files });
737 it('limitMultiFileUploads', function (done) {
740 singleFileUploads: false,
741 limitMultiFileUploads: 2,
742 send: function (e, data) {
743 expect(data.files).to.deep.equal(files);
745 if (completed < 2) return;
750 form.fileupload('add', { files: files.concat(files) });
753 it('limitMultiFileUploadSize', function (done) {
756 singleFileUploads: false,
757 limitMultiFileUploadSize: files[0].size + files[1].size,
758 limitMultiFileUploadSizeOverhead: 0,
759 send: function (e, data) {
760 expect(data.files).to.deep.equal(files);
762 if (completed < 2) return;
767 form.fileupload('add', { files: files.concat(files) });
770 it('sequentialUploads', function (done) {
775 sequentialUploads: true,
780 always: function () {
781 events.push('complete');
785 if (completed === 4) {
786 expect(events.join(',')).to.equal(
802 form.fileupload('add', { files: files.concat(files) });
805 it('limitConcurrentUploads', function (done) {
810 limitConcurrentUploads: 2,
814 expect(loadCount).to.be.at.most(2);
816 always: function () {
821 if (completed === 8) {
826 form.fileupload('add', {
827 files: files.concat(files).concat(files).concat(files)
831 it('multipart', function (done) {
834 send: function (e, data) {
835 expect(data.contentType).to.equal(fileGIF.type);
836 expect(data.headers['Content-Disposition']).to.equal(
837 'attachment; filename="' + fileGIF.name + '"'
843 form.fileupload('add', { files: [fileGIF] });
846 it('uniqueFilenames', function (done) {
849 send: function (e, data) {
850 var formFiles = data.data.getAll('files[]');
851 expect(formFiles[0].name).to.equal(fileGIF.name);
852 expect(formFiles[1].name).to.equal(
853 fileGIF.name.replace('.gif', ' (1).gif')
855 expect(formFiles[2].name).to.equal(
856 fileGIF.name.replace('.gif', ' (2).gif')
862 form.fileupload('send', { files: [fileGIF, fileGIF, fileGIF] });
865 it('maxChunkSize', function (done) {
871 chunkbeforesend: function () {
872 events.push('chunkbeforesend');
874 chunksend: function () {
875 events.push('chunksend');
877 chunkdone: function () {
878 events.push('chunkdone');
880 done: function (e, data) {
881 var uploadedFile = data.result.files[0];
882 expect(uploadedFile.type).to.equal(fileGIF.type);
883 expect(uploadedFile.size).to.equal(fileGIF.size);
886 expect(events.join(',')).to.equal(
905 form.fileupload('send', { files: [fileGIF] });
908 it('acceptFileTypes', function (done) {
911 acceptFileTypes: /^image\/gif$/,
912 singleFileUploads: false,
913 processalways: function (e, data) {
916 processstop: function () {
917 expect(processData.files[0].error).to.equal();
918 expect(processData.files[1].error).to.equal(
919 form.fileupload('option').i18n('acceptFileTypes')
924 form.fileupload('add', { files: files });
927 it('maxFileSize', function (done) {
931 singleFileUploads: false,
932 processalways: function (e, data) {
935 processstop: function () {
936 expect(processData.files[0].error).to.equal();
937 expect(processData.files[1].error).to.equal(
938 form.fileupload('option').i18n('maxFileSize')
943 form.fileupload('add', { files: files });
946 it('minFileSize', function (done) {
950 singleFileUploads: false,
951 processalways: function (e, data) {
954 processstop: function () {
955 expect(processData.files[0].error).to.equal(
956 form.fileupload('option').i18n('minFileSize')
958 expect(processData.files[1].error).to.equal();
962 form.fileupload('add', { files: files });
965 it('maxNumberOfFiles', function (done) {
969 getNumberOfFiles: function () {
972 singleFileUploads: false,
973 processalways: function (e, data) {
976 processstop: function () {
977 expect(processData.files[0].error).to.equal(
978 form.fileupload('option').i18n('maxNumberOfFiles')
980 expect(processData.files[1].error).to.equal(
981 form.fileupload('option').i18n('maxNumberOfFiles')
986 form.fileupload('add', { files: files });
989 })(this.chai.expect, this.jQuery);