hjg
2024-07-09 30304784e82d4bba24121328da8eb8490aec4f4f
提交 | 用户 | 时间
58d006 1 /*
A 2  * jQuery File Upload Plugin Test 8.8.3
3  * https://github.com/blueimp/jQuery-File-Upload
4  *
5  * Copyright 2010, Sebastian Tschan
6  * https://blueimp.net
7  *
8  * Licensed under the MIT license:
9  * http://www.opensource.org/licenses/MIT
10  */
11
12 /*jslint nomen: true, unparam: true */
13 /*global $, QUnit, window, document, expect, module, test, asyncTest, start, ok, strictEqual, notStrictEqual */
14
15 $(function () {
16     'use strict';
17
18     QUnit.done = function () {
19         // Delete all uploaded files:
20         var url = $('#fileupload').prop('action');
21         $.getJSON(url, function (result) {
22             $.each(result.files, function (index, file) {
23                 $.ajax({
24                     url: url + '?file=' + encodeURIComponent(file.name),
25                     type: 'DELETE'
26                 });
27             });
28         });
29     };
30
31     var lifecycle = {
32             setup: function () {
33                 // Set the .fileupload method to the basic widget method:
34                 $.widget('blueimp.fileupload', window.testBasicWidget, {});
35             },
36             teardown: function () {
37                 // Remove all remaining event listeners:
38                 $(document).unbind();
39             }
40         },
41         lifecycleUI = {
42             setup: function () {
43                 // Set the .fileupload method to the UI widget method:
44                 $.widget('blueimp.fileupload', window.testUIWidget, {});
45             },
46             teardown: function () {
47                 // Remove all remaining event listeners:
48                 $(document).unbind();
49             }
50         };
51
52     module('Initialization', lifecycle);
53
54     test('Widget initialization', function () {
55         var fu = $('#fileupload').fileupload();
56         ok(fu.data('blueimp-fileupload') || fu.data('fileupload'));
57     });
58
59     test('Data attribute options', function () {
60         $('#fileupload').attr('data-url', 'http://example.org');
61         $('#fileupload').fileupload();
62         strictEqual(
63             $('#fileupload').fileupload('option', 'url'),
64             'http://example.org'
65         );
66     });
67
68     test('File input initialization', function () {
69         var fu = $('#fileupload').fileupload();
70         ok(
71             fu.fileupload('option', 'fileInput').length,
72             'File input field inside of the widget'
73         );
74         ok(
75             fu.fileupload('option', 'fileInput').length,
76             'Widget element as file input field'
77         );
78     });
79
80     test('Drop zone initialization', function () {
81         ok($('#fileupload').fileupload()
82             .fileupload('option', 'dropZone').length);
83     });
84
85     test('Paste zone initialization', function () {
86         ok($('#fileupload').fileupload()
87             .fileupload('option', 'pasteZone').length);
88     });
89
90     test('Event listeners initialization', function () {
91         expect(
92             $.support.xhrFormDataFileUpload ? 4 : 1
93         );
94         var eo = {
95                 originalEvent: {
96                     dataTransfer: {files: [{}]},
97                     clipboardData: {items: [{}]}
98                 }
99             },
100             fu = $('#fileupload').fileupload({
101                 dragover: function () {
102                     ok(true, 'Triggers dragover callback');
103                     return false;
104                 },
105                 drop: function () {
106                     ok(true, 'Triggers drop callback');
107                     return false;
108                 },
109                 paste: function () {
110                     ok(true, 'Triggers paste callback');
111                     return false;
112                 },
113                 change: function () {
114                     ok(true, 'Triggers change callback');
115                     return false;
116                 }
117             }),
118             fileInput = fu.fileupload('option', 'fileInput'),
119             dropZone = fu.fileupload('option', 'dropZone'),
120             pasteZone = fu.fileupload('option', 'pasteZone');
121         fileInput.trigger($.Event('change', eo));
122         dropZone.trigger($.Event('dragover', eo));
123         dropZone.trigger($.Event('drop', eo));
124         pasteZone.trigger($.Event('paste', eo));
125     });
126
127     module('API', lifecycle);
128
129     test('destroy', function () {
130         expect(4);
131         var eo = {
132                 originalEvent: {
133                     dataTransfer: {files: [{}]},
134                     clipboardData: {items: [{}]}
135                 }
136             },
137             options = {
138                 dragover: function () {
139                     ok(true, 'Triggers dragover callback');
140                     return false;
141                 },
142                 drop: function () {
143                     ok(true, 'Triggers drop callback');
144                     return false;
145                 },
146                 paste: function () {
147                     ok(true, 'Triggers paste callback');
148                     return false;
149                 },
150                 change: function () {
151                     ok(true, 'Triggers change callback');
152                     return false;
153                 }
154             },
155             fu = $('#fileupload').fileupload(options),
156             fileInput = fu.fileupload('option', 'fileInput'),
157             dropZone = fu.fileupload('option', 'dropZone'),
158             pasteZone = fu.fileupload('option', 'pasteZone');
159         dropZone.bind('dragover', options.dragover);
160         dropZone.bind('drop', options.drop);
161         pasteZone.bind('paste', options.paste);
162         fileInput.bind('change', options.change);
163         fu.fileupload('destroy');
164         fileInput.trigger($.Event('change', eo));
165         dropZone.trigger($.Event('dragover', eo));
166         dropZone.trigger($.Event('drop', eo));
167         pasteZone.trigger($.Event('paste', eo));
168     });
169
170     test('disable/enable', function () {
171         expect(
172             $.support.xhrFormDataFileUpload ? 4 : 1
173         );
174         var eo = {
175                 originalEvent: {
176                     dataTransfer: {files: [{}]},
177                     clipboardData: {items: [{}]}
178                 }
179             },
180             fu = $('#fileupload').fileupload({
181                 dragover: function () {
182                     ok(true, 'Triggers dragover callback');
183                     return false;
184                 },
185                 drop: function () {
186                     ok(true, 'Triggers drop callback');
187                     return false;
188                 },
189                 paste: function () {
190                     ok(true, 'Triggers paste callback');
191                     return false;
192                 },
193                 change: function () {
194                     ok(true, 'Triggers change callback');
195                     return false;
196                 }
197             }),
198             fileInput = fu.fileupload('option', 'fileInput'),
199             dropZone = fu.fileupload('option', 'dropZone'),
200             pasteZone = fu.fileupload('option', 'pasteZone');
201         fu.fileupload('disable');
202         fileInput.trigger($.Event('change', eo));
203         dropZone.trigger($.Event('dragover', eo));
204         dropZone.trigger($.Event('drop', eo));
205         pasteZone.trigger($.Event('paste', eo));
206         fu.fileupload('enable');
207         fileInput.trigger($.Event('change', eo));
208         dropZone.trigger($.Event('dragover', eo));
209         dropZone.trigger($.Event('drop', eo));
210         pasteZone.trigger($.Event('paste', eo));
211     });
212
213     test('option', function () {
214         expect(
215             $.support.xhrFormDataFileUpload ? 10 : 7
216         );
217         var eo = {
218                 originalEvent: {
219                     dataTransfer: {files: [{}]},
220                     clipboardData: {items: [{}]}
221                 }
222             },
223             fu = $('#fileupload').fileupload({
224                 dragover: function () {
225                     ok(true, 'Triggers dragover callback');
226                     return false;
227                 },
228                 drop: function () {
229                     ok(true, 'Triggers drop callback');
230                     return false;
231                 },
232                 paste: function () {
233                     ok(true, 'Triggers paste callback');
234                     return false;
235                 },
236                 change: function () {
237                     ok(true, 'Triggers change callback');
238                     return false;
239                 }
240             }),
241             fileInput = fu.fileupload('option', 'fileInput'),
242             dropZone = fu.fileupload('option', 'dropZone'),
243             pasteZone = fu.fileupload('option', 'pasteZone');
244         fu.fileupload('option', 'fileInput', null);
245         fu.fileupload('option', 'dropZone', null);
246         fu.fileupload('option', 'pasteZone', null);
247         fileInput.trigger($.Event('change', eo));
248         dropZone.trigger($.Event('dragover', eo));
249         dropZone.trigger($.Event('drop', eo));
250         pasteZone.trigger($.Event('paste', eo));
251         fu.fileupload('option', 'dropZone', 'body');
252         strictEqual(
253             fu.fileupload('option', 'dropZone')[0],
254             document.body,
255             'Allow a query string as parameter for the dropZone option'
256         );
257         fu.fileupload('option', 'dropZone', document);
258         strictEqual(
259             fu.fileupload('option', 'dropZone')[0],
260             document,
261             'Allow a document element as parameter for the dropZone option'
262         );
263         fu.fileupload('option', 'pasteZone', 'body');
264         strictEqual(
265             fu.fileupload('option', 'pasteZone')[0],
266             document.body,
267             'Allow a query string as parameter for the pasteZone option'
268         );
269         fu.fileupload('option', 'pasteZone', document);
270         strictEqual(
271             fu.fileupload('option', 'pasteZone')[0],
272             document,
273             'Allow a document element as parameter for the pasteZone option'
274         );
275         fu.fileupload('option', 'fileInput', ':file');
276         strictEqual(
277             fu.fileupload('option', 'fileInput')[0],
278             $(':file')[0],
279             'Allow a query string as parameter for the fileInput option'
280         );
281         fu.fileupload('option', 'fileInput', $(':file')[0]);
282         strictEqual(
283             fu.fileupload('option', 'fileInput')[0],
284             $(':file')[0],
285             'Allow a document element as parameter for the fileInput option'
286         );
287         fu.fileupload('option', 'fileInput', fileInput);
288         fu.fileupload('option', 'dropZone', dropZone);
289         fu.fileupload('option', 'pasteZone', pasteZone);
290         fileInput.trigger($.Event('change', eo));
291         dropZone.trigger($.Event('dragover', eo));
292         dropZone.trigger($.Event('drop', eo));
293         pasteZone.trigger($.Event('paste', eo));
294     });
295
296     asyncTest('add', function () {
297         expect(2);
298         var param = {files: [{name: 'test'}]};
299         $('#fileupload').fileupload({
300             add: function (e, data) {
301                 strictEqual(
302                     data.files[0].name,
303                     param.files[0].name,
304                     'Triggers add callback'
305                 );
306             }
307         }).fileupload('add', param).fileupload(
308             'option',
309             'add',
310             function (e, data) {
311                 data.submit().complete(function () {
312                     ok(true, 'data.submit() Returns a jqXHR object');
313                     start();
314                 });
315             }
316         ).fileupload('add', param);
317     });
318
319     asyncTest('send', function () {
320         expect(3);
321         var param = {files: [{name: 'test'}]};
322         $('#fileupload').fileupload({
323             send: function (e, data) {
324                 strictEqual(
325                     data.files[0].name,
326                     'test',
327                     'Triggers send callback'
328                 );
329             }
330         }).fileupload('send', param).fail(function () {
331             ok(true, 'Allows to abort the request');
332         }).complete(function () {
333             ok(true, 'Returns a jqXHR object');
334             start();
335         }).abort();
336     });
337
338     module('Callbacks', lifecycle);
339
340     asyncTest('add', function () {
341         expect(1);
342         var param = {files: [{name: 'test'}]};
343         $('#fileupload').fileupload({
344             add: function (e, data) {
345                 ok(true, 'Triggers add callback');
346                 start();
347             }
348         }).fileupload('add', param);
349     });
350
351     asyncTest('submit', function () {
352         expect(1);
353         var param = {files: [{name: 'test'}]};
354         $('#fileupload').fileupload({
355             submit: function (e, data) {
356                 ok(true, 'Triggers submit callback');
357                 start();
358                 return false;
359             }
360         }).fileupload('add', param);
361     });
362
363     asyncTest('send', function () {
364         expect(1);
365         var param = {files: [{name: 'test'}]};
366         $('#fileupload').fileupload({
367             send: function (e, data) {
368                 ok(true, 'Triggers send callback');
369                 start();
370                 return false;
371             }
372         }).fileupload('send', param);
373     });
374
375     asyncTest('done', function () {
376         expect(1);
377         var param = {files: [{name: 'test'}]};
378         $('#fileupload').fileupload({
379             done: function (e, data) {
380                 ok(true, 'Triggers done callback');
381                 start();
382             }
383         }).fileupload('send', param);
384     });
385
386     asyncTest('fail', function () {
387         expect(1);
388         var param = {files: [{name: 'test'}]},
389             fu = $('#fileupload').fileupload({
390                 url: '404',
391                 fail: function (e, data) {
392                     ok(true, 'Triggers fail callback');
393                     start();
394                 }
395             });
396         (fu.data('blueimp-fileupload') || fu.data('fileupload'))
397             ._isXHRUpload = function () {
398                 return true;
399             };
400         fu.fileupload('send', param);
401     });
402
403     asyncTest('always', function () {
404         expect(2);
405         var param = {files: [{name: 'test'}]},
406             counter = 0,
407             fu = $('#fileupload').fileupload({
408                 always: function (e, data) {
409                     ok(true, 'Triggers always callback');
410                     if (counter === 1) {
411                         start();
412                     } else {
413                         counter += 1;
414                     }
415                 }
416             });
417         (fu.data('blueimp-fileupload') || fu.data('fileupload'))
418             ._isXHRUpload = function () {
419                 return true;
420             };
421         fu.fileupload('add', param).fileupload(
422             'option',
423             'url',
424             '404'
425         ).fileupload('add', param);
426     });
427
428     asyncTest('progress', function () {
429         expect(1);
430         var param = {files: [{name: 'test'}]},
431             counter = 0;
432         $('#fileupload').fileupload({
433             forceIframeTransport: true,
434             progress: function (e, data) {
435                 ok(true, 'Triggers progress callback');
436                 if (counter === 0) {
437                     start();
438                 } else {
439                     counter += 1;
440                 }
441             }
442         }).fileupload('send', param);
443     });
444
445     asyncTest('progressall', function () {
446         expect(1);
447         var param = {files: [{name: 'test'}]},
448             counter = 0;
449         $('#fileupload').fileupload({
450             forceIframeTransport: true,
451             progressall: function (e, data) {
452                 ok(true, 'Triggers progressall callback');
453                 if (counter === 0) {
454                     start();
455                 } else {
456                     counter += 1;
457                 }
458             }
459         }).fileupload('send', param);
460     });
461
462     asyncTest('start', function () {
463         expect(1);
464         var param = {files: [{name: '1'}, {name: '2'}]},
465             active = 0;
466         $('#fileupload').fileupload({
467             send: function (e, data) {
468                 active += 1;
469             },
470             start: function (e, data) {
471                 ok(!active, 'Triggers start callback before uploads');
472                 start();
473             }
474         }).fileupload('send', param);
475     });
476
477     asyncTest('stop', function () {
478         expect(1);
479         var param = {files: [{name: '1'}, {name: '2'}]},
480             active = 0;
481         $('#fileupload').fileupload({
482             send: function (e, data) {
483                 active += 1;
484             },
485             always: function (e, data) {
486                 active -= 1;
487             },
488             stop: function (e, data) {
489                 ok(!active, 'Triggers stop callback after uploads');
490                 start();
491             }
492         }).fileupload('send', param);
493     });
494
495     test('change', function () {
496         var fu = $('#fileupload').fileupload(),
497             fuo = fu.data('blueimp-fileupload') || fu.data('fileupload'),
498             fileInput = fu.fileupload('option', 'fileInput');
499         expect(2);
500         fu.fileupload({
501             change: function (e, data) {
502                 ok(true, 'Triggers change callback');
503                 strictEqual(
504                     data.files.length,
505                     0,
506                     'Returns empty files list'
507                 );
508             },
509             add: $.noop
510         });
511         fuo._onChange({
512             data: {fileupload: fuo},
513             target: fileInput[0]
514         });
515     });
516
517     test('paste', function () {
518         var fu = $('#fileupload').fileupload(),
519             fuo = fu.data('blueimp-fileupload') || fu.data('fileupload');
520         expect(1);
521         fu.fileupload({
522             paste: function (e, data) {
523                 ok(true, 'Triggers paste callback');
524             },
525             add: $.noop
526         });
527         fuo._onPaste({
528             data: {fileupload: fuo},
529             originalEvent: {
530                 dataTransfer: {files: [{}]},
531                 clipboardData: {items: [{}]}
532             },
533             preventDefault: $.noop
534         });
535     });
536
537     test('drop', function () {
538         var fu = $('#fileupload').fileupload(),
539             fuo = fu.data('blueimp-fileupload') || fu.data('fileupload');
540         expect(1);
541         fu.fileupload({
542             drop: function (e, data) {
543                 ok(true, 'Triggers drop callback');
544             },
545             add: $.noop
546         });
547         fuo._onDrop({
548             data: {fileupload: fuo},
549             originalEvent: {
550                 dataTransfer: {files: [{}]},
551                 clipboardData: {items: [{}]}
552             },
553             preventDefault: $.noop
554         });
555     });
556
557     test('dragover', function () {
558         var fu = $('#fileupload').fileupload(),
559             fuo = fu.data('blueimp-fileupload') || fu.data('fileupload');
560         expect(1);
561         fu.fileupload({
562             dragover: function (e, data) {
563                 ok(true, 'Triggers dragover callback');
564             },
565             add: $.noop
566         });
567         fuo._onDragOver({
568             data: {fileupload: fuo},
569             originalEvent: {dataTransfer: {}},
570             preventDefault: $.noop
571         });
572     });
573
574     module('Options', lifecycle);
575
576     test('paramName', function () {
577         expect(1);
578         var param = {files: [{name: 'test'}]};
579         $('#fileupload').fileupload({
580             paramName: null,
581             send: function (e, data) {
582                 strictEqual(
583                     data.paramName[0],
584                     data.fileInput.prop('name'),
585                     'Takes paramName from file input field if not set'
586                 );
587                 return false;
588             }
589         }).fileupload('send', param);
590     });
591
592     test('url', function () {
593         expect(1);
594         var param = {files: [{name: 'test'}]};
595         $('#fileupload').fileupload({
596             url: null,
597             send: function (e, data) {
598                 strictEqual(
599                     data.url,
600                     $(data.fileInput.prop('form')).prop('action'),
601                     'Takes url from form action if not set'
602                 );
603                 return false;
604             }
605         }).fileupload('send', param);
606     });
607
608     test('type', function () {
609         expect(2);
610         var param = {files: [{name: 'test'}]};
611         $('#fileupload').fileupload({
612             type: null,
613             send: function (e, data) {
614                 strictEqual(
615                     data.type,
616                     'POST',
617                     'Request type is "POST" if not set to "PUT"'
618                 );
619                 return false;
620             }
621         }).fileupload('send', param);
622         $('#fileupload').fileupload({
623             type: 'PUT',
624             send: function (e, data) {
625                 strictEqual(
626                     data.type,
627                     'PUT',
628                     'Request type is "PUT" if set to "PUT"'
629                 );
630                 return false;
631             }
632         }).fileupload('send', param);
633     });
634
635     test('replaceFileInput', function () {
636         var fu = $('#fileupload').fileupload(),
637             fuo = fu.data('blueimp-fileupload') || fu.data('fileupload'),
638             fileInput = fu.fileupload('option', 'fileInput'),
639             fileInputElement = fileInput[0];
640         expect(2);
641         fu.fileupload({
642             replaceFileInput: false,
643             change: function (e, data) {
644                 strictEqual(
645                     fu.fileupload('option', 'fileInput')[0],
646                     fileInputElement,
647                     'Keeps file input with replaceFileInput: false'
648                 );
649             },
650             add: $.noop
651         });
652         fuo._onChange({
653             data: {fileupload: fuo},
654             target: fileInput[0]
655         });
656         fu.fileupload({
657             replaceFileInput: true,
658             change: function (e, data) {
659                 notStrictEqual(
660                     fu.fileupload('option', 'fileInput')[0],
661                     fileInputElement,
662                     'Replaces file input with replaceFileInput: true'
663                 );
664             },
665             add: $.noop
666         });
667         fuo._onChange({
668             data: {fileupload: fuo},
669             target: fileInput[0]
670         });
671     });
672
673     asyncTest('forceIframeTransport', function () {
674         expect(1);
675         var param = {files: [{name: 'test'}]};
676         $('#fileupload').fileupload({
677             forceIframeTransport: true,
678             done: function (e, data) {
679                 strictEqual(
680                     data.dataType.substr(0, 6),
681                     'iframe',
682                     'Iframe Transport is used'
683                 );
684                 start();
685             }
686         }).fileupload('send', param);
687     });
688
689     test('singleFileUploads', function () {
690         expect(3);
691         var fu = $('#fileupload').fileupload(),
692             param = {files: [{name: '1'}, {name: '2'}]},
693             index = 1;
694         (fu.data('blueimp-fileupload') || fu.data('fileupload'))
695             ._isXHRUpload = function () {
696                 return true;
697             };
698         $('#fileupload').fileupload({
699             singleFileUploads: true,
700             add: function (e, data) {
701                 ok(true, 'Triggers callback number ' + index.toString());
702                 index += 1;
703             }
704         }).fileupload('add', param).fileupload(
705             'option',
706             'singleFileUploads',
707             false
708         ).fileupload('add', param);
709     });
710
711     test('limitMultiFileUploads', function () {
712         expect(3);
713         var fu = $('#fileupload').fileupload(),
714             param = {files: [
715                 {name: '1'},
716                 {name: '2'},
717                 {name: '3'},
718                 {name: '4'},
719                 {name: '5'}
720             ]},
721             index = 1;
722         (fu.data('blueimp-fileupload') || fu.data('fileupload'))
723             ._isXHRUpload = function () {
724                 return true;
725             };
726         $('#fileupload').fileupload({
727             singleFileUploads: false,
728             limitMultiFileUploads: 2,
729             add: function (e, data) {
730                 ok(true, 'Triggers callback number ' + index.toString());
731                 index += 1;
732             }
733         }).fileupload('add', param);
734     });
735
736     asyncTest('sequentialUploads', function () {
737         expect(6);
738         var param = {files: [
739                 {name: '1'},
740                 {name: '2'},
741                 {name: '3'},
742                 {name: '4'},
743                 {name: '5'},
744                 {name: '6'}
745             ]},
746             addIndex = 0,
747             sendIndex = 0,
748             loadIndex = 0,
749             fu = $('#fileupload').fileupload({
750                 sequentialUploads: true,
751                 add: function (e, data) {
752                     addIndex += 1;
753                     if (addIndex === 4) {
754                         data.submit().abort();
755                     } else {
756                         data.submit();
757                     }
758                 },
759                 send: function (e, data) {
760                     sendIndex += 1;
761                 },
762                 done: function (e, data) {
763                     loadIndex += 1;
764                     strictEqual(sendIndex, loadIndex, 'upload in order');
765                 },
766                 fail: function (e, data) {
767                     strictEqual(data.errorThrown, 'abort', 'upload aborted');
768                 },
769                 stop: function (e) {
770                     start();
771                 }
772             });
773         (fu.data('blueimp-fileupload') || fu.data('fileupload'))
774             ._isXHRUpload = function () {
775                 return true;
776             };
777         fu.fileupload('add', param);
778     });
779
780     asyncTest('limitConcurrentUploads', function () {
781         expect(12);
782         var param = {files: [
783                 {name: '1'},
784                 {name: '2'},
785                 {name: '3'},
786                 {name: '4'},
787                 {name: '5'},
788                 {name: '6'},
789                 {name: '7'},
790                 {name: '8'},
791                 {name: '9'},
792                 {name: '10'},
793                 {name: '11'},
794                 {name: '12'}
795             ]},
796             addIndex = 0,
797             sendIndex = 0,
798             loadIndex = 0,
799             fu = $('#fileupload').fileupload({
800                 limitConcurrentUploads: 3,
801                 add: function (e, data) {
802                     addIndex += 1;
803                     if (addIndex === 4) {
804                         data.submit().abort();
805                     } else {
806                         data.submit();
807                     }
808                 },
809                 send: function (e, data) {
810                     sendIndex += 1;
811                 },
812                 done: function (e, data) {
813                     loadIndex += 1;
814                     ok(sendIndex - loadIndex < 3);
815                 },
816                 fail: function (e, data) {
817                     strictEqual(data.errorThrown, 'abort', 'upload aborted');
818                 },
819                 stop: function (e) {
820                     start();
821                 }
822             });
823         (fu.data('blueimp-fileupload') || fu.data('fileupload'))
824             ._isXHRUpload = function () {
825                 return true;
826             };
827         fu.fileupload('add', param);
828     });
829
830     if ($.support.xhrFileUpload) {
831         asyncTest('multipart', function () {
832             expect(2);
833             var param = {files: [{
834                     name: 'test.png',
835                     size: 123,
836                     type: 'image/png'
837                 }]},
838                 fu = $('#fileupload').fileupload({
839                     multipart: false,
840                     always: function (e, data) {
841                         strictEqual(
842                             data.contentType,
843                             param.files[0].type,
844                             'non-multipart upload sets file type as contentType'
845                         );
846                         strictEqual(
847                             data.headers['Content-Disposition'],
848                             'attachment; filename="' + param.files[0].name + '"',
849                             'non-multipart upload sets Content-Disposition header'
850                         );
851                         start();
852                     }
853                 });
854             fu.fileupload('send', param);
855         });
856     }
857
858     module('UI Initialization', lifecycleUI);
859
860     test('Widget initialization', function () {
861         var fu = $('#fileupload').fileupload();
862         ok(fu.data('blueimp-fileupload') || fu.data('fileupload'));
863         ok(
864             $('#fileupload').fileupload('option', 'uploadTemplate').length,
865             'Initialized upload template'
866         );
867         ok(
868             $('#fileupload').fileupload('option', 'downloadTemplate').length,
869             'Initialized download template'
870         );
871     });
872
873     test('Buttonbar event listeners', function () {
874         var buttonbar = $('#fileupload .fileupload-buttonbar'),
875             files = [{name: 'test'}];
876         expect(4);
877         $('#fileupload').fileupload({
878             send: function (e, data) {
879                 ok(true, 'Started file upload via global start button');
880             },
881             fail: function (e, data) {
882                 ok(true, 'Canceled file upload via global cancel button');
883                 data.context.remove();
884             },
885             destroy: function (e, data) {
886                 ok(true, 'Delete action called via global delete button');
887             }
888         });
889         $('#fileupload').fileupload('add', {files: files});
890         buttonbar.find('.cancel').click();
891         $('#fileupload').fileupload('add', {files: files});
892         buttonbar.find('.start').click();
893         buttonbar.find('.cancel').click();
894         files[0].deleteUrl = 'http://example.org/banana.jpg';
895         ($('#fileupload').data('blueimp-fileupload') ||
896                 $('#fileupload').data('fileupload'))
897             ._renderDownload(files)
898             .appendTo($('#fileupload .files')).show()
899             .find('.toggle').click();
900         buttonbar.find('.delete').click();
901     });
902
903     module('UI API', lifecycleUI);
904
905     test('destroy', function () {
906         var buttonbar = $('#fileupload .fileupload-buttonbar'),
907             files = [{name: 'test'}];
908         expect(1);
909         $('#fileupload').fileupload({
910             send: function (e, data) {
911                 ok(true, 'This test should not run');
912                 return false;
913             }
914         })
915             .fileupload('add', {files: files})
916             .fileupload('destroy');
917         buttonbar.find('.start').click(function () {
918             ok(true, 'Clicked global start button');
919             return false;
920         }).click();
921     });
922
923     test('disable/enable', function () {
924         var buttonbar = $('#fileupload .fileupload-buttonbar');
925         $('#fileupload').fileupload();
926         $('#fileupload').fileupload('disable');
927         strictEqual(
928             buttonbar.find('input[type=file], button').not(':disabled').length,
929             0,
930             'Disables the buttonbar buttons'
931         );
932         $('#fileupload').fileupload('enable');
933         strictEqual(
934             buttonbar.find('input[type=file], button').not(':disabled').length,
935             4,
936             'Enables the buttonbar buttons'
937         );
938     });
939
940     module('UI Callbacks', lifecycleUI);
941
942     test('destroy', function () {
943         expect(3);
944         $('#fileupload').fileupload({
945             destroy: function (e, data) {
946                 ok(true, 'Triggers destroy callback');
947                 strictEqual(
948                     data.url,
949                     'test',
950                     'Passes over deletion url parameter'
951                 );
952                 strictEqual(
953                     data.type,
954                     'DELETE',
955                     'Passes over deletion request type parameter'
956                 );
957             }
958         });
959         ($('#fileupload').data('blueimp-fileupload') ||
960                 $('#fileupload').data('fileupload'))
961             ._renderDownload([{
962                 name: 'test',
963                 deleteUrl: 'test',
964                 deleteType: 'DELETE'
965             }])
966             .appendTo($('#fileupload .files'))
967             .show()
968             .find('.toggle').click();
969         $('#fileupload .fileupload-buttonbar .delete').click();
970     });
971
972     asyncTest('added', function () {
973         expect(1);
974         var param = {files: [{name: 'test'}]};
975         $('#fileupload').fileupload({
976             added: function (e, data) {
977                 start();
978                 strictEqual(
979                     data.files[0].name,
980                     param.files[0].name,
981                     'Triggers added callback'
982                 );
983             },
984             send: function () {
985                 return false;
986             }
987         }).fileupload('add', param);
988     });
989
990     asyncTest('started', function () {
991         expect(1);
992         var param = {files: [{name: 'test'}]};
993         $('#fileupload').fileupload({
994             started: function (e) {
995                 start();
996                 ok('Triggers started callback');
997                 return false;
998             },
999             sent: function (e, data) {
1000                 return false;
1001             }
1002         }).fileupload('send', param);
1003     });
1004
1005     asyncTest('sent', function () {
1006         expect(1);
1007         var param = {files: [{name: 'test'}]};
1008         $('#fileupload').fileupload({
1009             sent: function (e, data) {
1010                 start();
1011                 strictEqual(
1012                     data.files[0].name,
1013                     param.files[0].name,
1014                     'Triggers sent callback'
1015                 );
1016                 return false;
1017             }
1018         }).fileupload('send', param);
1019     });
1020
1021     asyncTest('completed', function () {
1022         expect(1);
1023         var param = {files: [{name: 'test'}]};
1024         $('#fileupload').fileupload({
1025             completed: function (e, data) {
1026                 start();
1027                 ok('Triggers completed callback');
1028                 return false;
1029             }
1030         }).fileupload('send', param);
1031     });
1032
1033     asyncTest('failed', function () {
1034         expect(1);
1035         var param = {files: [{name: 'test'}]};
1036         $('#fileupload').fileupload({
1037             failed: function (e, data) {
1038                 start();
1039                 ok('Triggers failed callback');
1040                 return false;
1041             }
1042         }).fileupload('send', param).abort();
1043     });
1044
1045     asyncTest('stopped', function () {
1046         expect(1);
1047         var param = {files: [{name: 'test'}]};
1048         $('#fileupload').fileupload({
1049             stopped: function (e, data) {
1050                 start();
1051                 ok('Triggers stopped callback');
1052                 return false;
1053             }
1054         }).fileupload('send', param);
1055     });
1056
1057     asyncTest('destroyed', function () {
1058         expect(1);
1059         $('#fileupload').fileupload({
1060             destroyed: function (e, data) {
1061                 start();
1062                 ok(true, 'Triggers destroyed callback');
1063             }
1064         });
1065         ($('#fileupload').data('blueimp-fileupload') ||
1066                 $('#fileupload').data('fileupload'))
1067             ._renderDownload([{
1068                 name: 'test',
1069                 deleteUrl: '.',
1070                 deleteType: 'GET'
1071             }])
1072             .appendTo($('#fileupload .files'))
1073             .show()
1074             .find('.toggle').click();
1075         $('#fileupload .fileupload-buttonbar .delete').click();
1076     });
1077
1078     module('UI Options', lifecycleUI);
1079
1080     test('autoUpload', function () {
1081         expect(1);
1082         $('#fileupload')
1083             .fileupload({
1084                 autoUpload: true,
1085                 send: function (e, data) {
1086                     ok(true, 'Started file upload automatically');
1087                     return false;
1088                 }
1089             })
1090             .fileupload('add', {files: [{name: 'test'}]})
1091             .fileupload('option', 'autoUpload', false)
1092             .fileupload('add', {files: [{name: 'test'}]});
1093     });
1094
1095     test('maxNumberOfFiles', function () {
1096         expect(3);
1097         var addIndex = 0,
1098             sendIndex = 0;
1099         $('#fileupload')
1100             .fileupload({
1101                 autoUpload: true,
1102                 maxNumberOfFiles: 3,
1103                 singleFileUploads: false,
1104                 send: function (e, data) {
1105                     strictEqual(
1106                         sendIndex += 1,
1107                         addIndex
1108                     );
1109                 },
1110                 progress: $.noop,
1111                 progressall: $.noop,
1112                 done: $.noop,
1113                 stop: $.noop
1114             })
1115             .fileupload('add', {files: [{name: (addIndex += 1)}]})
1116             .fileupload('add', {files: [{name: (addIndex += 1)}]})
1117             .fileupload('add', {files: [{name: (addIndex += 1)}]})
1118             .fileupload('add', {files: [{name: 'test'}]});
1119     });
1120
1121     test('maxFileSize', function () {
1122         expect(2);
1123         var addIndex = 0,
1124             sendIndex = 0;
1125         $('#fileupload')
1126             .fileupload({
1127                 autoUpload: true,
1128                 maxFileSize: 1000,
1129                 send: function (e, data) {
1130                     strictEqual(
1131                         sendIndex += 1,
1132                         addIndex
1133                     );
1134                     return false;
1135                 }
1136             })
1137             .fileupload('add', {files: [{
1138                 name: (addIndex += 1)
1139             }]})
1140             .fileupload('add', {files: [{
1141                 name: (addIndex += 1),
1142                 size: 999
1143             }]})
1144             .fileupload('add', {files: [{
1145                 name: 'test',
1146                 size: 1001
1147             }]})
1148             .fileupload({
1149                 send: function (e, data) {
1150                     ok(
1151                         !$.blueimp.fileupload.prototype.options
1152                             .send.call(this, e, data)
1153                     );
1154                     return false;
1155                 }
1156             });
1157     });
1158
1159     test('minFileSize', function () {
1160         expect(2);
1161         var addIndex = 0,
1162             sendIndex = 0;
1163         $('#fileupload')
1164             .fileupload({
1165                 autoUpload: true,
1166                 minFileSize: 1000,
1167                 send: function (e, data) {
1168                     strictEqual(
1169                         sendIndex += 1,
1170                         addIndex
1171                     );
1172                     return false;
1173                 }
1174             })
1175             .fileupload('add', {files: [{
1176                 name: (addIndex += 1)
1177             }]})
1178             .fileupload('add', {files: [{
1179                 name: (addIndex += 1),
1180                 size: 1001
1181             }]})
1182             .fileupload('add', {files: [{
1183                 name: 'test',
1184                 size: 999
1185             }]})
1186             .fileupload({
1187                 send: function (e, data) {
1188                     ok(
1189                         !$.blueimp.fileupload.prototype.options
1190                             .send.call(this, e, data)
1191                     );
1192                     return false;
1193                 }
1194             });
1195     });
1196
1197     test('acceptFileTypes', function () {
1198         expect(2);
1199         var addIndex = 0,
1200             sendIndex = 0;
1201         $('#fileupload')
1202             .fileupload({
1203                 autoUpload: true,
1204                 acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
1205                 disableImageMetaDataLoad: true,
1206                 send: function (e, data) {
1207                     strictEqual(
1208                         sendIndex += 1,
1209                         addIndex
1210                     );
1211                     return false;
1212                 }
1213             })
1214             .fileupload('add', {files: [{
1215                 name: (addIndex += 1) + '.jpg'
1216             }]})
1217             .fileupload('add', {files: [{
1218                 name: (addIndex += 1),
1219                 type: 'image/jpeg'
1220             }]})
1221             .fileupload('add', {files: [{
1222                 name: 'test.txt',
1223                 type: 'text/plain'
1224             }]})
1225             .fileupload({
1226                 send: function (e, data) {
1227                     ok(
1228                         !$.blueimp.fileupload.prototype.options
1229                             .send.call(this, e, data)
1230                     );
1231                     return false;
1232                 }
1233             });
1234     });
1235
1236     test('acceptFileTypes as HTML5 data attribute', function () {
1237         expect(2);
1238         var regExp = /(\.|\/)(gif|jpe?g|png)$/i;
1239         $('#fileupload')
1240             .attr('data-accept-file-types', regExp.toString())
1241             .fileupload();
1242         strictEqual(
1243             $.type($('#fileupload').fileupload('option', 'acceptFileTypes')),
1244             $.type(regExp)
1245         );
1246         strictEqual(
1247             $('#fileupload').fileupload('option', 'acceptFileTypes').toString(),
1248             regExp.toString()
1249         );
1250     });
1251
1252 });