2 function similar(actual, expected, mistakes) {
3 // actual is the generated zip, expected is what we got from the xhr.
4 // Be sure to have a well formatted string
5 expected = JSZip.utils.string2binary(expected);
7 if (actual.length !== expected.length) {
8 mistakes -= Math.abs((actual.length||0) - (expected.length||0));
11 for (var i = 0; i < Math.min(actual.length, expected.length); i++) {
12 if (actual.charAt(i) !== expected.charAt(i)) {
24 * bytes -> JSZip -> bytes
26 function reload(bytesStream) {
27 return new JSZip(bytesStream, {checkCRC32:true}).generate({type:"string"});
33 function testZipFile(testName, zipName, testFunction) {
34 test(testName, function () {
35 if (refZips[zipName]) {
36 testFunction.call(this, refZips[zipName]);
39 JSZipTestUtils.loadZipFile(zipName, function (file) {
41 refZips[zipName] = file;
42 testFunction.call(this, file);
44 if (QUnit.config.semaphore) {
56 test("JSZip", function(){
57 ok(JSZip, "JSZip exists");
59 var zip = new JSZip();
60 ok(zip, "Constructor works");
63 QUnit.module("Essential"); // {{{
65 test("JSZip.utils.transformTo", function () {
66 var supportedArgs = ['string', 'array'];
67 if (JSZip.support.arraybuffer) {
68 supportedArgs.push("arraybuffer");
70 if (JSZip.support.uint8array) {
71 supportedArgs.push("uint8array");
73 if (JSZip.support.nodebuffer) {
74 supportedArgs.push("nodebuffer");
77 var txt = 'test text !';
79 for (var i = 0; i < supportedArgs.length; i++) {
80 for (var j = 0; j < supportedArgs.length; j++) {
81 var step1 = JSZip.utils.transformTo(supportedArgs[i], txt);
82 var step2 = JSZip.utils.transformTo(supportedArgs[j], step1);
83 var result = JSZip.utils.transformTo("string", step2);
84 equal(result, txt, "The transformation string -> " + supportedArgs[i] + " -> " + supportedArgs[j] + " -> string works");
89 testZipFile("Zip text file !", "ref/text.zip", function(expected) {
90 var zip = new JSZip();
91 zip.file("Hello.txt", "Hello World\n");
92 var content = zip.generate();
94 var actual = JSZip.base64.decode(content);
97 Expected differing bytes:
100 4 central dir version numbers
101 4 central dir date/time
102 4 external file attributes
106 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
107 equal(reload(actual), actual, "Generated ZIP can be parsed");
110 testZipFile("Add a file to overwrite", "ref/text.zip", function(expected) {
111 var zip = new JSZip();
112 zip.file("Hello.txt", "hello ?");
113 zip.file("Hello.txt", "Hello World\n");
114 var content = zip.generate();
116 var actual = JSZip.base64.decode(content);
119 Expected differing bytes:
122 4 central dir version numbers
123 4 central dir date/time
124 4 external file attributes
128 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
129 equal(reload(actual), actual, "Generated ZIP can be parsed");
132 // zip -X -0 utf8.zip amount.txt
133 testZipFile("Zip text file with UTF-8 characters", "ref/utf8.zip", function(expected) {
134 var zip = new JSZip();
135 zip.file("amount.txt", "€15\n");
136 var actual = zip.generate({type:"string"});
138 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
139 equal(reload(actual), actual, "Generated ZIP can be parsed");
142 // zip -X -0 utf8_in_name.zip €15.txt
143 testZipFile("Zip text file with UTF-8 characters in filename", "ref/utf8_in_name.zip", function(expected) {
144 var zip = new JSZip();
145 zip.file("€15.txt", "€15\n");
146 var actual = zip.generate({type:"string"});
148 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
149 equal(reload(actual), actual, "Generated ZIP can be parsed");
152 testZipFile("Zip text file with date", "ref/text.zip", function(expected) {
153 var zip = new JSZip();
154 zip.file("Hello.txt", "Hello World\n", {date : new Date("July 17, 2009 14:36:57")});
155 var content = zip.generate();
157 var actual = JSZip.base64.decode(content);
160 Expected differing bytes:
162 4 central dir version numbers
163 4 external file attributes
167 ok(similar(actual, expected, 10) , "Generated ZIP matches reference ZIP");
168 equal(reload(actual), actual, "Generated ZIP can be parsed");
172 testZipFile("Zip image file", "ref/image.zip", function(expected) {
173 var zip = new JSZip();
174 zip.file("smile.gif", "R0lGODdhBQAFAIACAAAAAP/eACwAAAAABQAFAAACCIwPkWerClIBADs=", {base64: true});
175 var content = zip.generate();
177 var actual = JSZip.base64.decode(content);
179 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
180 equal(reload(actual), actual, "Generated ZIP can be parsed");
183 test("Zip folder() shouldn't throw an exception", function(expected) {
184 var zip = new JSZip();
187 ok(true, "no exception thrown");
189 ok(false, e.message||e);
193 testZipFile("Zip empty folder", "ref/folder.zip", function(expected) {
194 var zip = new JSZip();
195 zip.folder("folder");
196 var content = zip.generate();
198 var actual = JSZip.base64.decode(content);
200 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
201 equal(reload(actual), actual, "Generated ZIP can be parsed");
204 testZipFile("Zip text, folder and image", "ref/all.zip", function(expected) {
205 var zip = new JSZip();
206 zip.file("Hello.txt", "Hello World\n");
207 zip.folder("images").file("smile.gif", "R0lGODdhBQAFAIACAAAAAP/eACwAAAAABQAFAAACCIwPkWerClIBADs=", {base64: true});
208 var content = zip.generate();
210 var actual = JSZip.base64.decode(content);
213 Expected differing bytes:
216 4 central dir version numbers
217 4 central dir date/time
218 4 external file attributes
224 ok(similar(actual, expected, 54) , "Generated ZIP matches reference ZIP");
225 equal(reload(actual), actual, "Generated ZIP can be parsed");
228 test("Finding a file", function() {
229 var zip = new JSZip();
230 zip.file("Readme", "Hello World!\n");
231 zip.file("Readme.French", "Bonjour tout le monde!\n");
232 zip.file("Readme.Pirate", "Ahoy m'hearty!\n");
234 equal(zip.file("Readme.French").asText(), "Bonjour tout le monde!\n", "Exact match found");
235 equal(zip.file("Readme.Deutch"), null, "Match exactly nothing");
236 equal(zip.file(/Readme\../).length, 2, "Match regex free text");
237 equal(zip.file(/pirate/i).length, 1, "Match regex 1 result");
240 testZipFile("Finding a file : modifying the result doesn't alter the zip", "ref/text.zip", function(expected) {
241 var zip = new JSZip();
242 zip.file("Hello.txt", "Hello World\n");
243 zip.file("Hello.txt").name = "Hello2.txt";
244 zip.file("Hello.txt").options.dir = true;
245 // these changes won't be used
246 var content = zip.generate();
248 var actual = JSZip.base64.decode(content);
250 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
253 test("Finding a file (text search) with a relative folder", function() {
254 var zip = new JSZip();
255 zip.folder("files/default").file("Readme", "Hello World!\n");
256 zip.folder("files/translation").file("Readme.French", "Bonjour tout le monde!\n");
257 zip.folder("files").folder("translation").file("Readme.Pirate", "Ahoy m'hearty!\n");
259 equal(zip.file("files/translation/Readme.French").asText(), "Bonjour tout le monde!\n", "finding file with the full path");
260 equal(zip.folder("files").file("translation/Readme.French").asText(), "Bonjour tout le monde!\n", "finding file with a relative path");
261 equal(zip.folder("files/translation").file("Readme.French").asText(), "Bonjour tout le monde!\n", "finding file with a relative path");
264 test("Finding files (regex) with a relative folder", function() {
265 var zip = new JSZip();
266 zip.folder("files/default").file("Readme", "Hello World!\n");
267 zip.folder("files/translation").file("Readme.French", "Bonjour tout le monde!\n");
268 zip.folder("files").folder("translation").file("Readme.Pirate", "Ahoy m'hearty!\n");
270 equal(zip.file(/Readme/).length, 3, "match files in subfolders");
271 equal(zip.folder("files/translation").file(/Readme/).length, 2, "regex match only in subfolders");
272 equal(zip.folder("files").folder("translation").file(/Readme/).length, 2, "regex match only in subfolders");
273 equal(zip.folder("files/translation").file(/pirate/i).length, 1, "regex match only in subfolders");
274 equal(zip.folder("files/translation").file(/^readme/i).length, 2, "regex match only with the relative path");
275 equal(zip.folder("files/default").file(/pirate/i).length, 0, "regex match only in subfolders");
278 test("Finding folders", function () {
279 var zip = new JSZip();
280 zip.folder("root/").folder("sub1/");
281 zip.folder("root/sub2/subsub1");
283 equal(zip.folder(/sub2\/$/).length, 1, "unique result");
284 equal(zip.folder(/sub1/).length, 2, "multiple results");
285 equal(zip.folder(/root/).length, 4, "match on whole path");
288 test("Finding folders with relative path", function () {
289 var zip = new JSZip();
290 zip.folder("root/").folder("sub1/");
291 zip.folder("root/sub2/subsub1");
292 var root = zip.folder("root/sub2");
294 equal(root.folder(/sub2\/$/).length, 0, "current folder is not matched");
295 equal(root.folder(/sub1/).length, 1, "sub folder is matched");
296 equal(root.folder(/^subsub1/).length, 1, "relative folder path is used");
297 equal(root.folder(/root/).length, 0, "parent folder is not matched");
299 // }}} module Essential
301 QUnit.module("More advanced"); // {{{
303 testZipFile("Delete file", "ref/text.zip", function(expected) {
304 var zip = new JSZip();
305 zip.file("Remove.txt", "This file should be deleted\n");
306 zip.file("Hello.txt", "Hello World\n");
307 zip.remove("Remove.txt");
308 var content = zip.generate();
310 var actual = JSZip.base64.decode(content);
312 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
316 testZipFile("Delete file in folder", "ref/folder.zip", function(expected) {
317 var zip = new JSZip();
318 zip.folder("folder").file("Remove.txt", "This folder and file should be deleted\n");
319 zip.remove("folder/Remove.txt");
320 var content = zip.generate();
322 var actual = JSZip.base64.decode(content);
324 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
327 testZipFile("Delete file in folder, with a relative path", "ref/folder.zip", function(expected) {
328 var zip = new JSZip();
329 var folder = zip.folder("folder");
330 folder.file("Remove.txt", "This folder and file should be deleted\n");
331 folder.remove("Remove.txt");
332 var content = zip.generate();
334 var actual = JSZip.base64.decode(content);
336 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
339 testZipFile("Delete folder", "ref/text.zip", function(expected) {
340 var zip = new JSZip();
341 zip.folder("remove").file("Remove.txt", "This folder and file should be deleted\n");
342 zip.file("Hello.txt", "Hello World\n");
343 zip.remove("remove");
344 var content = zip.generate();
346 var actual = JSZip.base64.decode(content);
348 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
351 testZipFile("Delete folder with a final /", "ref/text.zip", function(expected) {
352 var zip = new JSZip();
353 zip.folder("remove").file("Remove.txt", "This folder and file should be deleted\n");
354 zip.file("Hello.txt", "Hello World\n");
355 zip.remove("remove/");
356 var content = zip.generate();
358 var actual = JSZip.base64.decode(content);
360 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
363 testZipFile("Delete unknown path", "ref/text.zip", function(expected) {
364 var zip = new JSZip();
365 zip.file("Hello.txt", "Hello World\n");
366 zip.remove("unknown_file");
367 zip.remove("unknown_folder/Hello.txt");
368 var content = zip.generate();
370 var actual = JSZip.base64.decode(content);
372 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
375 testZipFile("Delete nested folders", "ref/text.zip", function(expected) {
376 var zip = new JSZip();
377 zip.folder("remove").file("Remove.txt", "This folder and file should be deleted\n");
378 zip.folder("remove/second").file("Sub.txt", "This should be removed");
379 zip.file("remove/second/another.txt", "Another file");
380 zip.file("Hello.txt", "Hello World\n");
381 zip.remove("remove");
382 var content = zip.generate();
384 var actual = JSZip.base64.decode(content);
386 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
390 testZipFile("Delete nested folders from relative path", "ref/folder.zip", function(expected) {
391 var zip = new JSZip();
392 zip.folder("folder");
393 zip.folder("folder/1/2/3");
394 zip.folder("folder").remove("1");
395 var content = zip.generate();
397 var actual = JSZip.base64.decode(content);
399 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
400 equal(reload(actual), actual, "Generated ZIP can be parsed");
403 testZipFile("add file: from XHR (with bytes > 255)", "ref/text.zip", function(textZip) {
404 var zip = new JSZip();
405 zip.file("text.zip", textZip, {binary:true});
406 var actual = zip.generate({base64:false});
408 equal(reload(actual), actual, "high-order byte is discarded and won't mess up the result");
411 function testFileDataGetters (opts) {
412 if (typeof opts.rawData === "undefined") {
413 opts.rawData = opts.textData;
415 _actualTestFileDataGetters.asText(opts);
416 _actualTestFileDataGetters.asBinary(opts);
417 _actualTestFileDataGetters.asArrayBuffer(opts);
418 _actualTestFileDataGetters.asUint8Array(opts);
419 _actualTestFileDataGetters.asNodeBuffer(opts);
421 var reload = function () {
423 name : "reloaded, " + opts.name,
424 // no check of crc32, we want to test the CompressedObject code.
425 zip : new JSZip(opts.zip.generate({type:"string"}, {checkCRC32:false})),
426 textData : opts.textData,
427 rawData : opts.rawData
431 _actualTestFileDataGetters.asText(reload());
432 _actualTestFileDataGetters.asBinary(reload());
433 _actualTestFileDataGetters.asArrayBuffer(reload());
434 _actualTestFileDataGetters.asUint8Array(reload());
435 _actualTestFileDataGetters.asNodeBuffer(reload());
438 var _actualTestFileDataGetters = {
439 asText : function (opts) {
440 equal(opts.zip.file("file.txt").asText(), opts.textData, opts.name + " : asText()");
442 asBinary : function (opts) {
443 equal(opts.zip.file("file.txt").asBinary(), opts.rawData, opts.name + " : asBinary()");
445 asArrayBuffer : function (opts) {
446 if (JSZip.support.arraybuffer) {
447 var buffer = opts.zip.file("file.txt").asArrayBuffer();
448 ok(buffer instanceof ArrayBuffer, opts.name + " : the result is a instance of ArrayBuffer");
449 var actual = String.fromCharCode.apply(null, new Uint8Array(buffer));
450 equal(actual, opts.rawData, opts.name + " : asArrayBuffer()");
453 opts.zip.file("file.txt").asArrayBuffer();
454 ok(false, "no exception thrown");
456 ok(e.message.match("not supported by this browser"), opts.name + " : the error message is useful");
460 asUint8Array : function (opts) {
461 if (JSZip.support.uint8array) {
462 var bufferView = opts.zip.file("file.txt").asUint8Array();
463 ok(bufferView instanceof Uint8Array, opts.name + " : the result is a instance of Uint8Array");
464 var actual = String.fromCharCode.apply(null, bufferView);
465 equal(actual, opts.rawData, opts.name + " : asUint8Array()");
468 opts.zip.file("file.txt").asUint8Array();
469 ok(false, "no exception thrown");
471 ok(e.message.match("not supported by this browser"), opts.name + " : the error message is useful");
475 asNodeBuffer : function (opts) {
476 if (JSZip.support.nodebuffer) {
477 var buffer = opts.zip.file("file.txt").asNodeBuffer();
478 ok(buffer instanceof Buffer, opts.name + " : the result is a instance of Buffer");
479 var actual = String.fromCharCode.apply(null, buffer);
480 equal(actual, opts.rawData, opts.name + " : .asNodeBuffer()");
483 opts.zip.file("file.txt").asNodeBuffer();
484 ok(false, "no exception thrown");
486 ok(e.message.match("not supported by this browser"), opts.name + " : the error message is useful");
492 test("add file: file(name, undefined)", function() {
493 var zip = new JSZip(), undef;
494 zip.file("file.txt", undef);
495 testFileDataGetters({name : "undefined", zip : zip, textData : ""});
497 zip.file("file.txt", undef, {binary:true});
498 testFileDataGetters({name : "undefined", zip : zip, textData : ""});
500 zip.file("file.txt", undef, {base64:true});
501 testFileDataGetters({name : "undefined", zip : zip, textData : ""});
504 test("add file: file(name, null)", function() {
505 var zip = new JSZip();
506 zip.file("file.txt", null);
507 testFileDataGetters({name : "null", zip : zip, textData : ""});
509 zip.file("file.txt", null, {binary:true});
510 testFileDataGetters({name : "null", zip : zip, textData : ""});
512 zip.file("file.txt", null, {base64:true});
513 testFileDataGetters({name : "null", zip : zip, textData : ""});
516 test("add file: file(name, stringAsText)", function() {
517 var zip = new JSZip();
518 zip.file("file.txt", "€15\n", {binary:false});
519 testFileDataGetters({name : "utf8", zip : zip, textData : "€15\n", rawData : "\xE2\x82\xAC15\n"});
521 zip.file("file.txt", "test\r\ntest\r\n", {binary:false});
522 testFileDataGetters({name : "\\r\\n", zip : zip, textData : "test\r\ntest\r\n"});
525 test("add file: file(name, stringAsBinary)", function() {
526 var zip = new JSZip();
527 zip.file("file.txt", "\xE2\x82\xAC15\n", {binary:true});
528 testFileDataGetters({name : "utf8", zip : zip, textData : "€15\n", rawData : "\xE2\x82\xAC15\n"});
530 zip.file("file.txt", "test\r\ntest\r\n", {binary:true});
531 testFileDataGetters({name : "\\r\\n", zip : zip, textData : "test\r\ntest\r\n"});
534 test("add file: file(name, base64)", function() {
535 var zip = new JSZip();
536 zip.file("file.txt", "4oKsMTUK", {base64:true});
537 testFileDataGetters({name : "utf8", zip : zip, textData : "€15\n", rawData : "\xE2\x82\xAC15\n"});
539 zip.file("file.txt", "dGVzdA0KdGVzdA0K", {base64:true});
540 testFileDataGetters({name : "\\r\\n", zip : zip, textData : "test\r\ntest\r\n"});
543 test("add file: file(name, unsupported)", function() {
544 var zip = new JSZip();
546 zip.file("test.txt", new Date());
547 ok(false, "An unsupported object was added, but no exception thrown");
549 ok(e.message.match("unsupported format"), "the error message is useful");
551 if (JSZip.support.blob) {
552 var blob = zip.generate({type:"blob"});
554 zip.file("test.txt", blob);
555 ok(false, "An blob was added, but no exception thrown");
557 ok(e.message.match("unsupported format"), "the error message is useful");
562 if (JSZip.support.uint8array) {
563 test("add file: file(name, Uint8Array)", function() {
564 var str2array = function (str) {
565 var array = new Uint8Array(str.length);
566 for(var i = 0; i < str.length; i++) {
567 array[i] = str.charCodeAt(i);
571 var zip = new JSZip();
572 zip.file("file.txt", str2array("\xE2\x82\xAC15\n"));
573 testFileDataGetters({name : "utf8", zip : zip, textData : "€15\n", rawData : "\xE2\x82\xAC15\n"});
575 zip.file("file.txt", str2array("test\r\ntest\r\n"));
576 testFileDataGetters({name : "\\r\\n", zip : zip, textData : "test\r\ntest\r\n"});
578 zip.file("file.txt", str2array(""));
579 testFileDataGetters({name : "empty content", zip : zip, textData : ""});
583 if (JSZip.support.arraybuffer) {
584 test("add file: file(name, ArrayBuffer)", function() {
585 var str2buffer = function (str) {
586 var array = new Uint8Array(str.length);
587 for(var i = 0; i < str.length; i++) {
588 array[i] = str.charCodeAt(i);
592 var zip = new JSZip();
593 zip.file("file.txt", str2buffer("\xE2\x82\xAC15\n"));
594 testFileDataGetters({name : "utf8", zip : zip, textData : "€15\n", rawData : "\xE2\x82\xAC15\n"});
596 zip.file("file.txt", str2buffer("test\r\ntest\r\n"));
597 testFileDataGetters({name : "\\r\\n", zip : zip, textData : "test\r\ntest\r\n"});
599 zip.file("file.txt", str2buffer(""));
600 testFileDataGetters({name : "empty content", zip : zip, textData : ""});
604 if (JSZip.support.nodebuffer) {
605 test("add file: file(name, Buffer)", function() {
606 var str2buffer = function (str) {
607 var array = new Buffer(str.length);
608 for(var i = 0; i < str.length; i++) {
609 array[i] = str.charCodeAt(i);
613 var zip = new JSZip();
614 zip.file("file.txt", str2buffer("\xE2\x82\xAC15\n"));
615 testFileDataGetters({name : "utf8", zip : zip, textData : "€15\n", rawData : "\xE2\x82\xAC15\n"});
617 zip.file("file.txt", str2buffer("test\r\ntest\r\n"));
618 testFileDataGetters({name : "\\r\\n", zip : zip, textData : "test\r\ntest\r\n"});
620 zip.file("file.txt", str2buffer(""));
621 testFileDataGetters({name : "empty content", zip : zip, textData : ""});
625 testZipFile("generate : base64:false. Deprecated, but it still works", "ref/text.zip", function(expected) {
626 var zip = new JSZip();
627 zip.file("Hello.txt", "Hello World\n");
628 var actual = zip.generate({base64:false});
630 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
633 testZipFile("generate : base64:true. Deprecated, but it still works", "ref/text.zip", function(expected) {
634 var zip = new JSZip();
635 zip.file("Hello.txt", "Hello World\n");
636 var content = zip.generate({base64:true});
637 var actual = JSZip.base64.decode(content);
639 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
642 testZipFile("generate : type:string", "ref/text.zip", function(expected) {
643 var zip = new JSZip();
644 zip.file("Hello.txt", "Hello World\n");
645 var actual = zip.generate({type:"string"});
647 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
650 testZipFile("generate : type:base64", "ref/text.zip", function(expected) {
651 var zip = new JSZip();
652 zip.file("Hello.txt", "Hello World\n");
653 var content = zip.generate({type:"base64"});
655 var actual = JSZip.base64.decode(content);
657 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
660 if (JSZip.support.uint8array) {
661 testZipFile("generate : type:uint8array", "ref/text.zip", function(expected) {
662 var zip = new JSZip();
663 zip.file("Hello.txt", "Hello World\n");
664 var array = zip.generate({type:"uint8array"});
665 ok(array instanceof Uint8Array, "The result is a instance of Uint8Array");
666 equal(array.length, expected.length);
668 var actual = String.fromCharCode.apply(null, array);
670 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
673 testZipFile("generate : type:uint8array", "ref/text.zip", function(expected) {
674 var zip = new JSZip();
675 zip.file("Hello.txt", "Hello World\n");
677 var blob = zip.generate({type:"uint8array"});
678 ok(false, "Uint8Array is not supported, but no exception thrown");
680 ok(e.message.match("not supported by this browser"), "the error message is useful");
685 if (JSZip.support.arraybuffer) {
686 testZipFile("generate : type:arraybuffer", "ref/text.zip", function(expected) {
687 var zip = new JSZip();
688 zip.file("Hello.txt", "Hello World\n");
689 var buffer = zip.generate({type:"arraybuffer"});
690 ok(buffer instanceof ArrayBuffer, "The result is a instance of ArrayBuffer");
692 var actual = String.fromCharCode.apply(null, new Uint8Array(buffer));
694 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
697 testZipFile("generate : type:arraybuffer", "ref/text.zip", function(expected) {
698 var zip = new JSZip();
699 zip.file("Hello.txt", "Hello World\n");
701 var blob = zip.generate({type:"arraybuffer"});
702 ok(false, "ArrayBuffer is not supported, but no exception thrown");
704 ok(e.message.match("not supported by this browser"), "the error message is useful");
709 if (JSZip.support.nodebuffer) {
710 testZipFile("generate : type:nodebuffer", "ref/text.zip", function(expected) {
711 var zip = new JSZip();
712 zip.file("Hello.txt", "Hello World\n");
713 var buffer = zip.generate({type:"nodebuffer"});
714 ok(buffer instanceof Buffer, "The result is a instance of ArrayBuffer");
717 for (var i = 0; i < buffer.length; i++) {
718 actual += String.fromCharCode(buffer[i]);
721 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
724 testZipFile("generate : type:nodebuffer", "ref/text.zip", function(expected) {
725 var zip = new JSZip();
726 zip.file("Hello.txt", "Hello World\n");
728 var blob = zip.generate({type:"nodebuffer"});
729 ok(false, "Buffer is not supported, but no exception thrown");
731 ok(e.message.match("not supported by this browser"), "the error message is useful");
736 if (JSZip.support.blob) {
737 testZipFile("generate : type:blob", "ref/text.zip", function(expected) {
738 var zip = new JSZip();
739 zip.file("Hello.txt", "Hello World\n");
740 var blob = zip.generate({type:"blob"});
741 ok(blob instanceof Blob, "The result is a instance of Blob");
742 equal(blob.type, "application/zip");
743 equal(blob.size, expected.length);
746 testZipFile("generate : type:blob", "ref/text.zip", function(expected) {
747 var zip = new JSZip();
748 zip.file("Hello.txt", "Hello World\n");
750 var blob = zip.generate({type:"blob"});
751 ok(false, "Blob is not supported, but no exception thrown");
753 ok(e.message.match("not supported by this browser"), "the error message is useful");
758 test("Filtering a zip", function() {
759 var zip = new JSZip();
760 zip.file("1.txt", "1\n");
761 zip.file("2.txt", "2\n");
762 zip.file("3.log", "3\n");
763 var result = zip.filter(function (relativeFilename, file){
764 return relativeFilename.indexOf(".txt") != -1;
766 equal(result.length, 2, "filter has filtered");
767 ok(result[0].name.indexOf(".txt") != -1, "filter has filtered the good file");
768 ok(result[1].name.indexOf(".txt") != -1, "filter has filtered the good file");
771 test("Filtering a zip from a relative path", function() {
772 var zip = new JSZip();
773 zip.file("foo/1.txt", "1\n");
774 zip.file("foo/2.txt", "2\n");
775 zip.file("foo/3.log", "3\n");
776 zip.file("1.txt", "1\n");
777 zip.file("2.txt", "2\n");
778 zip.file("3.log", "3\n");
780 var result = zip.folder("foo").filter(function (relativeFilename, file) {
781 return relativeFilename.indexOf("3") != -1;
783 equal(result.length, 1, "filter has filtered");
784 equal(result[0].name, "foo/3.log", "filter has filtered the good file");
787 test("Filtering a zip : the full path is still accessible", function() {
788 var zip = new JSZip();
789 zip.file("foo/1.txt", "1\n");
790 zip.file("foo/2.txt", "2\n");
791 zip.file("foo/3.log", "3\n");
792 zip.file("1.txt", "1\n");
793 zip.file("2.txt", "2\n");
794 zip.file("3.log", "3\n");
796 var result = zip.folder("foo").filter(function (relativeFilename, file) {
797 return file.name.indexOf("3") != -1;
799 equal(result.length, 1, "the filter only match files/folders in the current folder");
800 equal(result[0].name, "foo/3.log", "filter has filtered the good file");
803 testZipFile("Filtering a zip : the filter function can't alter the data", "ref/text.zip", function(expected) {
804 var zip = new JSZip();
805 zip.file("Hello.txt", "Hello World\n");
806 zip.filter(function (relativeFilename, file) {
807 file.name = "bye.txt";
808 file.data = "good bye";
809 file.options.dir = true;
811 var content = zip.generate();
813 var actual = JSZip.base64.decode(content);
815 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
819 testZipFile("STORE is the default method", "ref/text.zip", function(expected) {
820 var zip = new JSZip();
821 zip.file("Hello.txt", "Hello World\n");
822 var content = zip.generate({compression:'STORE'});
824 var actual = JSZip.base64.decode(content);
826 // no difference with the "Zip text file" test.
827 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
830 // zip -0 -X store.zip Hello.txt
831 testZipFile("STORE doesn't compress", "ref/store.zip", function(expected) {
832 var zip = new JSZip();
833 zip.file("Hello.txt", "This a looong file : we need to see the difference between the different compression methods.\n");
834 var content = zip.generate({compression:'STORE'});
836 var actual = JSZip.base64.decode(content);
838 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
842 // commented because the new implementation of DEFLATE produces different results from the old one.
844 // zip -6 -X deflate.zip Hello.txt
845 testZipFile("DEFLATE compress", "ref/deflate.zip", function(expected) {
846 var zip = new JSZip();
847 zip.file("Hello.txt", "This a looong file : we need to see the difference between the different compression methods.\n");
848 var content = zip.generate({compression:'DEFLATE'});
850 var actual = JSZip.base64.decode(content);
852 ok(similar(actual, expected, 18) , "Generated ZIP matches reference ZIP");
855 test("Lazy decompression works", function () {
856 var zip = new JSZip();
857 zip.folder("test/").file("Hello.txt", "hello !");
859 var expected = zip.generate({type:"string", compression:"STORE"});
861 zip = new JSZip(expected); // lazy
862 equal(zip.generate({type:"string", compression:"STORE"}), expected, "Reloading file, same compression");
864 zip = new JSZip(zip.generate({type:"string", compression:"DEFLATE"}));
865 zip = new JSZip(zip.generate({type:"string", compression:"STORE"}));
867 var zipData = zip.generate({type:"string", compression:"STORE"});
868 equal(zipData, expected, "Reloading file, different compression");
871 new JSZip(zipData, {checkCRC32:true}).generate({type:"string"});
874 test("Empty files / folders are not compressed", function() {
875 var zip = new JSZip();
876 zip.file("Hello.txt", "This a looong file : we need to see the difference between the different compression methods.\n");
877 zip.folder("folder").file("empty", "");
879 var deflateCount = 0, emptyDeflateCount = 0;
880 var oldDeflateCompress = JSZip.compressions.DEFLATE.compress;
881 JSZip.compressions.DEFLATE.compress = function (str) {
888 zip.generate({compression:'DEFLATE'});
890 equal(deflateCount, 1, "The file has been compressed");
891 equal(emptyDeflateCount, 0, "The file without content and the folder has not been compressed.");
893 JSZip.compressions.DEFLATE.compress = oldDeflateCompress;
896 test("unknown compression throws an exception", function () {
897 var zip = new JSZip().file("file.txt", "test");
899 zip.generate({compression:'MAYBE'});
900 ok(false, "no exception");
902 ok(true, "an exception were thrown");
907 QUnit.module("Load file, not supported features"); // {{{
909 // zip -0 -X -e encrypted.zip Hello.txt
910 testZipFile("basic encryption", "ref/encrypted.zip", function(file) {
912 var zip = new JSZip(file);
913 ok(false, "Encryption is not supported, but no exception were thrown");
915 equal(e.message, "Encrypted zip are not supported", "the error message is useful");
918 // }}} Load file, not supported features
920 QUnit.module("Load file, corrupted zip"); // {{{
922 testZipFile("bad compression method", "ref/invalid/compression.zip", function(file) {
924 var zip = new JSZip(file);
925 ok(false, "no exception were thrown");
927 ok(e.message.match("Corrupted zip"), "the error message is useful");
931 testZipFile("invalid crc32 but no check", "ref/invalid/crc32.zip", function(file) {
933 var zip = new JSZip(file, {checkCRC32:false});
934 ok(true, "no exception were thrown");
936 ok(false, "An exception were thrown but the check should have been disabled.");
940 testZipFile("invalid crc32", "ref/invalid/crc32.zip", function(file) {
942 var zip = new JSZip(file, {checkCRC32:true});
943 ok(false, "no exception were thrown");
945 ok(e.message.match("Corrupted zip"), "the error message is useful");
949 testZipFile("bad offset", "ref/invalid/bad_offset.zip", function(file) {
951 var zip = new JSZip(file);
952 ok(false, "no exception were thrown");
954 ok(e.message.match("Corrupted zip"), "the error message is useful");
957 // }}} Load file, corrupted zip
959 QUnit.module("Load file"); // {{{
961 testZipFile("load(string) works", "ref/all.zip", function(file) {
962 ok(typeof file === "string");
963 var zip = new JSZip(file);
964 equal(zip.file("Hello.txt").asText(), "Hello World\n", "the zip was correctly read.");
967 testZipFile("load(string) handles bytes > 255", "ref/all.zip", function(file) {
968 // the method used to load zip with ajax will remove the extra bits.
969 // adding extra bits :)
970 var updatedFile = "";
971 for (var i = 0; i < file.length; i++) {
972 updatedFile += String.fromCharCode((file.charCodeAt(i) & 0xff) + 0x4200);
974 var zip = new JSZip(updatedFile);
976 equal(zip.file("Hello.txt").asText(), "Hello World\n", "the zip was correctly read.");
979 if (JSZip.support.arraybuffer) {
980 testZipFile("load(ArrayBuffer) works", "ref/all.zip", function(fileAsString) {
981 var file = new ArrayBuffer(fileAsString.length);
982 var bufferView = new Uint8Array(file);
983 for( var i = 0; i < fileAsString.length; ++i ) {
984 bufferView[i] = fileAsString.charCodeAt(i);
987 ok(file instanceof ArrayBuffer);
989 // when reading an arraybuffer, the CompressedObject mechanism will keep it and subarray() a Uint8Array.
990 // if we request a file in the same format, we might get the same Uint8Array or its ArrayBuffer (the original zip file).
991 equal(new JSZip(file).file("Hello.txt").asArrayBuffer().byteLength, 12, "don't get the original buffer");
992 equal(new JSZip(file).file("Hello.txt").asUint8Array().buffer.byteLength, 12, "don't get a view of the original buffer");
994 equal(new JSZip(file).file("Hello.txt").asText(), "Hello World\n", "the zip was correctly read.");
998 if (JSZip.support.nodebuffer) {
999 testZipFile("load(Buffer) works", "ref/all.zip", function(fileAsString) {
1000 var file = new Buffer(fileAsString.length);
1001 for( var i = 0; i < fileAsString.length; ++i ) {
1002 file[i] = fileAsString.charCodeAt(i);
1005 equal(new JSZip(file).file("Hello.txt").asText(), "Hello World\n", "the zip was correctly read.");
1009 if (JSZip.support.uint8array) {
1010 testZipFile("load(Uint8Array) works", "ref/all.zip", function(fileAsString) {
1011 var file = new Uint8Array(fileAsString.length);
1012 for( var i = 0; i < fileAsString.length; ++i ) {
1013 file[i] = fileAsString.charCodeAt(i);
1016 ok(file instanceof Uint8Array);
1018 // when reading an arraybuffer, the CompressedObject mechanism will keep it and subarray() a Uint8Array.
1019 // if we request a file in the same format, we might get the same Uint8Array or its ArrayBuffer (the original zip file).
1020 equal(new JSZip(file).file("Hello.txt").asArrayBuffer().byteLength, 12, "don't get the original buffer");
1021 equal(new JSZip(file).file("Hello.txt").asUint8Array().buffer.byteLength, 12, "don't get a view of the original buffer");
1023 equal(new JSZip(file).file("Hello.txt").asText(), "Hello World\n", "the zip was correctly read.");
1027 // zip -6 -X deflate.zip Hello.txt
1028 testZipFile("zip with DEFLATE", "ref/deflate.zip", function(file) {
1029 var zip = new JSZip(file);
1030 equal(zip.file("Hello.txt").asText(), "This a looong file : we need to see the difference between the different compression methods.\n", "the zip was correctly read.");
1033 // zip -0 -z -c archive_comment.zip Hello.txt
1034 testZipFile("zip with comment", "ref/archive_comment.zip", function(file) {
1035 var zip = new JSZip(file);
1036 equal(zip.file("Hello.txt").asText(), "Hello World\n", "the zip was correctly read.");
1039 // zip -0 extra_attributes.zip Hello.txt
1040 testZipFile("zip with extra attributes", "ref/extra_attributes.zip", function(file) {
1041 var zip = new JSZip(file);
1042 equal(zip.file("Hello.txt").asText(), "Hello World\n", "the zip was correctly read.");
1045 // use -fz to force use of Zip64 format
1046 // zip -fz -0 zip64.zip Hello.txt
1047 testZipFile("zip 64", "ref/zip64.zip", function(file) {
1048 var zip = new JSZip(file);
1049 equal(zip.file("Hello.txt").asText(), "Hello World\n", "the zip was correctly read.");
1052 // use -fd to force data descriptors as if streaming
1053 // zip -fd -0 data_descriptor.zip Hello.txt
1054 testZipFile("zip with data descriptor", "ref/data_descriptor.zip", function(file) {
1055 var zip = new JSZip(file);
1056 equal(zip.file("Hello.txt").asText(), "Hello World\n", "the zip was correctly read.");
1059 // combo of zip64 and data descriptors :
1060 // zip -fz -fd -0 data_descriptor_zip64.zip Hello.txt
1061 // this generate a corrupted zip file :(
1062 // TODO : find how to get the two features
1064 // zip -0 -X zip_within_zip.zip Hello.txt && zip -0 -X nested.zip Hello.txt zip_within_zip.zip
1065 testZipFile("nested zip", "ref/nested.zip", function(file) {
1066 var zip = new JSZip(file);
1067 equal(zip.file("Hello.txt").asText(), "Hello World\n", "the zip was correctly read.");
1068 var nested = new JSZip(zip.file("zip_within_zip.zip").asBinary());
1069 equal(nested.file("Hello.txt").asText(), "Hello World\n", "the inner zip was correctly read.");
1072 // zip -fd -0 nested_data_descriptor.zip data_descriptor.zip
1073 testZipFile("nested zip with data descriptors", "ref/nested_data_descriptor.zip", function(file) {
1074 var zip = new JSZip(file);
1075 var nested = new JSZip(zip.file("data_descriptor.zip").asBinary());
1076 equal(nested.file("Hello.txt").asText(), "Hello World\n", "the inner zip was correctly read.");
1079 // zip -fz -0 nested_zip64.zip zip64.zip
1080 testZipFile("nested zip 64", "ref/nested_zip64.zip", function(file) {
1081 var zip = new JSZip(file);
1082 var nested = new JSZip(zip.file("zip64.zip").asBinary());
1083 equal(nested.file("Hello.txt").asText(), "Hello World\n", "the inner zip was correctly read.");
1086 // nested zip 64 with data descriptors
1087 // zip -fz -fd -0 nested_data_descriptor_zip64.zip data_descriptor_zip64.zip
1088 // this generate a corrupted zip file :(
1089 // TODO : find how to get the two features
1091 // zip -X -0 utf8_in_name.zip €15.txt
1092 testZipFile("Zip text file with UTF-8 characters in filename", "ref/utf8_in_name.zip", function(file) {
1093 var zip = new JSZip(file);
1094 ok(zip.file("€15.txt") !== null, "the utf8 file is here.");
1095 equal(zip.file("€15.txt").asText(), "€15\n", "the utf8 content was correctly read (with file().asText).");
1096 equal(zip.files["€15.txt"].asText(), "€15\n", "the utf8 content was correctly read (with files[].astext).");
1099 // zip backslash.zip -0 -X Hel\\lo.txt
1100 testZipFile("Zip text file with backslash in filename", "ref/backslash.zip", function(file) {
1101 var zip = new JSZip(file);
1102 equal(zip.file("Hel\\lo.txt").asText(), "Hello World\n", "the utf8 content was correctly read.");
1105 // use izarc to generate a zip file on windows
1106 testZipFile("Zip text file from windows with \\ in central dir", "ref/slashes_and_izarc.zip", function(file) {
1107 var zip = new JSZip(file);
1108 equal(zip.folder("test").file("Hello.txt").asText(), "Hello world\r\n", "the content was correctly read.");
1111 test("A folder stays a folder", function () {
1112 var zip = new JSZip();
1113 zip.folder("folder/");
1114 ok(zip.files['folder/'].options.dir, "the folder is marked as a folder");
1115 var reloaded = new JSZip(zip.generate({base64:false}));
1116 ok(reloaded.files['folder/'].options.dir, "the folder is marked as a folder");
1121 QUnit.module("Load complex files"); // {{{
1123 if (QUnit.urlParams.complexfiles) {
1125 // http://www.feedbooks.com/book/8/the-metamorphosis
1126 testZipFile("Franz Kafka - The Metamorphosis.epub", "ref/complex_files/Franz Kafka - The Metamorphosis.epub", function(file) {
1127 var zip = new JSZip(file);
1128 equal(zip.filter(function(){return true;}).length, 26, "the zip contains the good number of elements.");
1129 equal(zip.file("mimetype").asText(), "application/epub+zip\r\n", "the zip was correctly read.");
1130 // the .ncx file tells us that the first chapter is in the main0.xml file.
1131 ok(zip.file("OPS/main0.xml").asText().indexOf("One morning, as Gregor Samsa was waking up from anxious dreams") !== -1, "the zip was correctly read.");
1134 // a showcase in http://msdn.microsoft.com/en-us/windows/hardware/gg463429
1135 testZipFile("Outlook2007_Calendar.xps", "ref/complex_files/Outlook2007_Calendar.xps", function(file) {
1136 var zip = new JSZip(file);
1137 // the zip file contains 15 entries, but we get 23 when creating all the sub-folders.
1138 equal(zip.filter(function(){return true;}).length, 23, "the zip contains the good number of elements.");
1139 ok(zip.file("[Content_Types].xml").asText().indexOf("application/vnd.ms-package.xps-fixeddocument+xml") !== -1, "the zip was correctly read.");
1142 // an example file in http://cheeso.members.winisp.net/srcview.aspx?dir=js-unzip
1143 // the data come from http://www.antarctica.ac.uk/met/READER/upper_air/
1144 testZipFile("AntarcticaTemps.xlsx", "ref/complex_files/AntarcticaTemps.xlsx", function(file) {
1145 var zip = new JSZip(file);
1146 // the zip file contains 16 entries, but we get 27 when creating all the sub-folders.
1147 equal(zip.filter(function(){return true;}).length, 27, "the zip contains the good number of elements.");
1148 ok(zip.file("[Content_Types].xml").asText().indexOf("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml") !== -1, "the zip was correctly read.");
1151 // same as above, but in the Open Document format
1152 testZipFile("AntarcticaTemps.ods", "ref/complex_files/AntarcticaTemps.ods", function(file) {
1153 var zip = new JSZip(file);
1154 // the zip file contains 19 entries, but we get 27 when creating all the sub-folders.
1155 equal(zip.filter(function(){return true;}).length, 27, "the zip contains the good number of elements.");
1156 ok(zip.file("META-INF/manifest.xml").asText().indexOf("application/vnd.oasis.opendocument.spreadsheet") !== -1, "the zip was correctly read.");
1159 // }}} Load complex files
1162 // enforcing Stuk's coding style
1163 // vim: set shiftwidth=3 softtabstop=3: