b&&(this.b.length=b),a=this.b);return this.buffer=a};function V(a){a=a||{};this.files=[];this.v=a.comment}V.prototype.M=function(a){this.j=a};V.prototype.s=function(a){var b=a[2]&65535|2;return b*(b^1)>>8&255};V.prototype.k=function(a,b){a[0]=(B[(a[0]^b)&255]^a[0]>>>8)>>>0;a[1]=(6681*(20173*(a[1]+(a[0]&255))>>>0)>>>0)+1>>>0;a[2]=(B[(a[2]^a[1]>>>24)&255]^a[2]>>>8)>>>0};V.prototype.U=function(a){var b=[305419896,591751049,878082192],c,d;w&&(b=new Uint32Array(b));c=0;for(d=a.length;c>>0;this.z=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.J=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.h=a[b++]|a[b++]<<
+8;this.g=a[b++]|a[b++]<<8;this.F=a[b++]|a[b++]<<8;this.fa=a[b++]|a[b++]<<8;this.ha=a[b++]|a[b++]<<8;this.ga=a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24;this.aa=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.filename=String.fromCharCode.apply(null,w?a.subarray(b,b+=this.h):a.slice(b,b+=this.h));this.Y=w?a.subarray(b,b+=this.g):a.slice(b,b+=this.g);this.v=w?a.subarray(b,b+this.F):a.slice(b,b+this.F);this.length=b-this.offset};function pa(a,b){this.input=a;this.offset=b}var qa={O:1,da:8,ea:2048};
+pa.prototype.parse=function(){var a=this.input,b=this.offset;(a[b++]!==Y[0]||a[b++]!==Y[1]||a[b++]!==Y[2]||a[b++]!==Y[3])&&m(Error("invalid local file header signature"));this.$=a[b++]|a[b++]<<8;this.I=a[b++]|a[b++]<<8;this.A=a[b++]|a[b++]<<8;this.time=a[b++]|a[b++]<<8;this.V=a[b++]|a[b++]<<8;this.p=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.z=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.J=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.h=a[b++]|a[b++]<<8;this.g=a[b++]|a[b++]<<8;this.filename=
+String.fromCharCode.apply(null,w?a.subarray(b,b+=this.h):a.slice(b,b+=this.h));this.Y=w?a.subarray(b,b+=this.g):a.slice(b,b+=this.g);this.length=b-this.offset};
+function $(a){var b=[],c={},d,f,h,k;if(!a.i){if(a.o===q){var e=a.input,g;if(!a.D)a:{var l=a.input,p;for(p=l.length-12;0>>0;a.o=(e[g++]|
+e[g++]<<8|e[g++]<<16|e[g++]<<24)>>>0;a.w=e[g++]|e[g++]<<8;a.v=w?e.subarray(g,g+a.w):e.slice(g,g+a.w)}d=a.o;h=0;for(k=a.ba;h>>8^B[(n^l[t])&255];for(N=ka>>3;N--;t+=8)n=n>>>8^B[(n^l[t])&255],n=n>>>8^B[(n^l[t+1])&255],n=n>>>8^B[(n^l[t+2])&255],n=n>>>8^B[(n^l[t+3])&255],n=n>>>8^B[(n^l[t+4])&255],n=n>>>8^B[(n^l[t+5])&255],n=n>>>8^B[(n^l[t+6])&255],n=n>>>8^B[(n^l[t+7])&255];p=(n^4294967295)>>>0;k.p!==p&&m(Error("wrong crc: file=0x"+
+k.p.toString(16)+", data=0x"+p.toString(16)))}return l};u.M=function(a){this.j=a};function ra(a,b,c){c^=a.s(b);a.k(b,c);return c}u.k=V.prototype.k;u.T=V.prototype.U;u.s=V.prototype.s;v("Zlib.Unzip",W);v("Zlib.Unzip.prototype.decompress",W.prototype.r);v("Zlib.Unzip.prototype.getFilenames",W.prototype.Z);v("Zlib.Unzip.prototype.setPassword",W.prototype.M);}).call(this);
diff --git a/lib/zip.js b/lib/zip.js
new file mode 100644
index 0000000..e9e56a8
--- /dev/null
+++ b/lib/zip.js
@@ -0,0 +1,37 @@
+/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var n=void 0,y=!0,aa=this;function G(e,b){var a=e.split("."),d=aa;!(a[0]in d)&&d.execScript&&d.execScript("var "+a[0]);for(var c;a.length&&(c=a.shift());)!a.length&&b!==n?d[c]=b:d=d[c]?d[c]:d[c]={}};var H="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function ba(e,b){this.index="number"===typeof b?b:0;this.f=0;this.buffer=e instanceof(H?Uint8Array:Array)?e:new (H?Uint8Array:Array)(32768);if(2*this.buffer.length<=this.index)throw Error("invalid index");this.buffer.length<=this.index&&ca(this)}function ca(e){var b=e.buffer,a,d=b.length,c=new (H?Uint8Array:Array)(d<<1);if(H)c.set(b);else for(a=0;a>>8&255]<<16|L[e>>>16&255]<<8|L[e>>>24&255])>>32-b:L[e]>>8-b);if(8>b+f)l=l<>b-p-1&1,8===++f&&(f=0,d[c++]=L[l],l=0,c===d.length&&(d=ca(this)));d[c]=l;this.buffer=d;this.f=f;this.index=c};ba.prototype.finish=function(){var e=this.buffer,b=this.index,a;0ha;++ha){for(var U=ha,ja=U,ka=7,U=U>>>1;U;U>>>=1)ja<<=1,ja|=U&1,--ka;da[ha]=(ja<>>0}var L=da;function la(e){var b=n,a,d="number"===typeof b?b:b=0,c=e.length;a=-1;for(d=c&7;d--;++b)a=a>>>8^V[(a^e[b])&255];for(d=c>>3;d--;b+=8)a=a>>>8^V[(a^e[b])&255],a=a>>>8^V[(a^e[b+1])&255],a=a>>>8^V[(a^e[b+2])&255],a=a>>>8^V[(a^e[b+3])&255],a=a>>>8^V[(a^e[b+4])&255],a=a>>>8^V[(a^e[b+5])&255],a=a>>>8^V[(a^e[b+6])&255],a=a>>>8^V[(a^e[b+7])&255];return(a^4294967295)>>>0}
+var ma=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
+2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
+2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,
+2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,
+3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,
+936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],V=H?new Uint32Array(ma):ma;function na(e){this.buffer=new (H?Uint16Array:Array)(2*e);this.length=0}na.prototype.getParent=function(e){return 2*((e-2)/4|0)};na.prototype.push=function(e,b){var a,d,c=this.buffer,f;a=this.length;c[this.length++]=b;for(c[this.length++]=e;0c[d])f=c[a],c[a]=c[d],c[d]=f,f=c[a+1],c[a+1]=c[d+1],c[d+1]=f,a=d;else break;return this.length};
+na.prototype.pop=function(){var e,b,a=this.buffer,d,c,f;b=a[0];e=a[1];this.length-=2;a[0]=a[this.length];a[1]=a[this.length+1];for(f=0;;){c=2*f+2;if(c>=this.length)break;c+2a[c]&&(c+=2);if(a[c]>a[f])d=a[f],a[f]=a[c],a[c]=d,d=a[f+1],a[f+1]=a[c+1],a[c+1]=d;else break;f=c}return{index:e,value:b,length:this.length}};function pa(e,b){this.k=qa;this.l=0;this.input=H&&e instanceof Array?new Uint8Array(e):e;this.e=0;b&&(b.lazy&&(this.l=b.lazy),"number"===typeof b.compressionType&&(this.k=b.compressionType),b.outputBuffer&&(this.c=H&&b.outputBuffer instanceof Array?new Uint8Array(b.outputBuffer):b.outputBuffer),"number"===typeof b.outputIndex&&(this.e=b.outputIndex));this.c||(this.c=new (H?Uint8Array:Array)(32768))}var qa=2,sa=[],Y;
+for(Y=0;288>Y;Y++)switch(y){case 143>=Y:sa.push([Y+48,8]);break;case 255>=Y:sa.push([Y-144+400,9]);break;case 279>=Y:sa.push([Y-256+0,7]);break;case 287>=Y:sa.push([Y-280+192,8]);break;default:throw"invalid literal: "+Y;}
+pa.prototype.g=function(){var e,b,a,d,c=this.input;switch(this.k){case 0:a=0;for(d=c.length;a>>8&255;m[h++]=q&255;m[h++]=q>>>8&255;if(H)m.set(f,h),h+=f.length,m=m.subarray(0,h);else{w=0;for(u=f.length;wx)for(;0x?x:138,E>x-3&&E=E?(M[K++]=17,M[K++]=E-3,S[17]++):(M[K++]=18,M[K++]=E-11,S[18]++),x-=E;else if(M[K++]=P[v],S[P[v]]++,x--,3>x)for(;0x?x:6,E>x-3&&ED;D++)oa[D]=X[g[D]];for(C=19;4=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,
+a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:throw"invalid length: "+a;}}var b=[],a,d;for(a=3;258>=a;a++)d=e(a),b[a]=d[2]<<24|
+d[1]<<16|d[0];return b}(),Ja=H?new Uint32Array(xa):xa;
+function ta(e,b){function a(a,c){var b=a.n,d=[],e=0,f;f=Ja[a.length];d[e++]=f&65535;d[e++]=f>>16&255;d[e++]=f>>24;var g;switch(y){case 1===b:g=[0,b-1,0];break;case 2===b:g=[1,b-2,0];break;case 3===b:g=[2,b-3,0];break;case 4===b:g=[3,b-4,0];break;case 6>=b:g=[4,b-5,1];break;case 8>=b:g=[5,b-7,1];break;case 12>=b:g=[6,b-9,2];break;case 16>=b:g=[7,b-13,2];break;case 24>=b:g=[8,b-17,3];break;case 32>=b:g=[9,b-25,3];break;case 48>=b:g=[10,b-33,4];break;case 64>=b:g=[11,b-49,4];break;case 96>=b:g=[12,b-
+65,5];break;case 128>=b:g=[13,b-97,5];break;case 192>=b:g=[14,b-129,6];break;case 256>=b:g=[15,b-193,6];break;case 384>=b:g=[16,b-257,7];break;case 512>=b:g=[17,b-385,7];break;case 768>=b:g=[18,b-513,8];break;case 1024>=b:g=[19,b-769,8];break;case 1536>=b:g=[20,b-1025,9];break;case 2048>=b:g=[21,b-1537,9];break;case 3072>=b:g=[22,b-2049,10];break;case 4096>=b:g=[23,b-3073,10];break;case 6144>=b:g=[24,b-4097,11];break;case 8192>=b:g=[25,b-6145,11];break;case 12288>=b:g=[26,b-8193,12];break;case 16384>=
+b:g=[27,b-12289,12];break;case 24576>=b:g=[28,b-16385,13];break;case 32768>=b:g=[29,b-24577,13];break;default:throw"invalid distance";}f=g;d[e++]=f[0];d[e++]=f[1];d[e++]=f[2];var k,l;k=0;for(l=d.length;k=f;)t[f++]=0;for(f=0;29>=f;)r[f++]=0}t[256]=1;d=0;for(c=b.length;d=c){u&&a(u,-1);f=0;for(l=c-d;fl&&b+lf&&(c=d,f=l);if(258===l)break}return new wa(f,b-c)}
+function ua(e,b){var a=e.length,d=new na(572),c=new (H?Uint8Array:Array)(a),f,l,p,k,q;if(!H)for(k=0;k2*c[h-1]+f[h]&&(c[h]=2*c[h-1]+f[h]),p[h]=Array(c[h]),k[h]=Array(c[h]);for(m=0;me[m]?(p[h][s]=t,k[h][s]=b,r+=2):(p[h][s]=e[m],k[h][s]=m,++m);q[h]=0;1===f[h]&&d(h)}return l}
+function va(e){var b=new (H?Uint16Array:Array)(e.length),a=[],d=[],c=0,f,l,p,k;f=0;for(l=e.length;f>>=1}return b};function $(e){e=e||{};this.files=[];this.d=e.comment}var Ma=[80,75,1,2],Na=[80,75,3,4],Oa=[80,75,5,6];$.prototype.m=function(e,b){b=b||{};var a,d=e.length,c=0;H&&e instanceof Array&&(e=new Uint8Array(e));"number"!==typeof b.compressionMethod&&(b.compressionMethod=8);if(b.compress)switch(b.compressionMethod){case 0:break;case 8:c=la(e);e=(new pa(e,b.deflateOption)).g();a=y;break;default:throw Error("unknown compression method:"+b.compressionMethod);}this.files.push({buffer:e,a:b,j:a,r:!1,size:d,h:c})};
+$.prototype.q=function(e){this.i=e};
+$.prototype.g=function(){var e=this.files,b,a,d,c,f,l=0,p=0,k,q,w,u,m,h,s,t,r,Q,z,A,F,I,N,B,C,g,J;B=0;for(C=e.length;Bg;++g)F[g]=Qa(N,11===B?b.h&255:256*Math.random()|0);for(J=F.length;g>8&255;w=b.a.compressionMethod;a[d++]=a[c++]=w&255;a[d++]=a[c++]=w>>8&255;u=b.a.date||new Date;a[d++]=a[c++]=(u.getMinutes()&7)<<5|u.getSeconds()/2|0;a[d++]=a[c++]=u.getHours()<<3|u.getMinutes()>>3;a[d++]=a[c++]=(u.getMonth()+1&7)<<5|u.getDate();a[d++]=a[c++]=(u.getFullYear()-
+1980&127)<<1|u.getMonth()+1>>3;m=b.h;a[d++]=a[c++]=m&255;a[d++]=a[c++]=m>>8&255;a[d++]=a[c++]=m>>16&255;a[d++]=a[c++]=m>>24&255;h=b.buffer.length;a[d++]=a[c++]=h&255;a[d++]=a[c++]=h>>8&255;a[d++]=a[c++]=h>>16&255;a[d++]=a[c++]=h>>24&255;s=b.size;a[d++]=a[c++]=s&255;a[d++]=a[c++]=s>>8&255;a[d++]=a[c++]=s>>16&255;a[d++]=a[c++]=s>>24&255;a[d++]=a[c++]=t&255;a[d++]=a[c++]=t>>8&255;a[d++]=a[c++]=0;a[d++]=a[c++]=0;a[c++]=r&255;a[c++]=r>>8&255;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=
+0;a[c++]=0;a[c++]=k&255;a[c++]=k>>8&255;a[c++]=k>>16&255;a[c++]=k>>24&255;if(Q=b.a.filename)if(H)a.set(Q,d),a.set(Q,c),d+=t,c+=t;else for(g=0;g>8&255;a[f++]=C&255;a[f++]=C>>8&255;a[f++]=p&255;a[f++]=p>>8&255;a[f++]=p>>16&255;a[f++]=p>>24&255;a[f++]=l&255;a[f++]=l>>8&255;a[f++]=l>>16&255;a[f++]=l>>24&255;r=this.d?this.d.length:0;a[f++]=r&255;a[f++]=r>>8&255;if(this.d)if(H)a.set(this.d,f);else{g=0;for(J=r;g>8&255;Pa(e,b);return a^b}
+function Pa(e,b){e[0]=(V[(e[0]^b)&255]^e[0]>>>8)>>>0;e[1]=(6681*(20173*(e[1]+(e[0]&255))>>>0)>>>0)+1>>>0;e[2]=(V[(e[2]^e[1]>>>24)&255]^e[2]>>>8)>>>0};function Ra(e,b){var a,d,c,f;if(Object.keys)a=Object.keys(b);else for(d in a=[],c=0,b)a[c++]=d;c=0;for(f=a.length;c -1) {
+ return it.skip(test, callback);
+ }
+ it(test, callback);
+ }
+
+ describe('FileSystemShell.zip() and unzip()', function() {
+ beforeEach(util.setup);
+ afterEach(util.cleanup);
+
+ it('should be a function', function() {
+ var shell = util.shell();
+ expect(shell.zip).to.be.a('function');
+ expect(shell.unzip).to.be.a('function');
+ });
+
+ it('should fail when path argument is absent', function(done) {
+ var fs = util.fs();
+ var shell = fs.Shell();
+
+ shell.unzip(null, function(err) {
+ expect(err).to.exist;
+ done();
+ });
+ });
+
+ itShouldWorkInPhantomJSButDoesNot('should download and unzip the contents of a zip file', function(done) {
+ var fs = util.fs();
+ var shell = fs.Shell();
+ var url = "test-file.txt.zip";
+ var contents = "This is a test file used in some of the tests.\n";
+
+ fs.writeFile('/original', contents, function(err) {
+ if(err) throw err;
+
+ shell.wget(url, {filename: url}, function(err, path) {
+ if(err) throw err;
+
+ shell.unzip(path, function(err) {
+ if(err) throw err;
+
+ fs.readFile('/original', function(err, originalData) {
+ if(err) throw err;
+
+
+ fs.readFile('/test-file.txt', function(err, data) {
+ if(err) throw err;
+ expect(util.typedArrayEqual(data, originalData)).to.be.true;
+ done();
+ });
+ });
+ });
+ });
+ });
+ });
+
+ itShouldWorkInPhantomJSButDoesNot('should download and unzip the contents of a zip file with a specified destination', function(done) {
+ var fs = util.fs();
+ var shell = fs.Shell();
+ var Path = Filer.Path;
+ var url = "test-file.txt.zip";
+ var contents = "This is a test file used in some of the tests.\n";
+
+ fs.writeFile('/original', contents, function(err) {
+ if(err) throw err;
+
+ shell.wget(url, {filename: url}, function(err, path) {
+ if(err) throw err;
+
+ shell.tempDir(function(err, tmp) {
+ if (err) throw err;
+
+ shell.unzip(path, { destination: tmp }, function(err) {
+ if(err) throw err;
+
+ fs.readFile('/original', function(err, originalData) {
+ if(err) throw err;
+
+ fs.readFile(Path.join(tmp, 'test-file.txt'), function(err, data) {
+ if(err) throw err;
+ expect(util.typedArrayEqual(data, originalData)).to.be.true;
+ done();
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+
+ itShouldWorkInPhantomJSButDoesNot('should be able to zip and unzip a file', function(done) {
+ var fs = util.fs();
+ var file = '/test-file.txt';
+ var zipfile = file + '.zip';
+ var shell = fs.Shell();
+ var Path = Filer.Path;
+ var contents = "This is a test file used in some of the tests.\n";
+
+ fs.writeFile(file, contents, function(err) {
+ if(err) throw err;
+
+ shell.zip(zipfile, file, function(err) {
+ if(err) throw err;
+
+ fs.stat(zipfile, function(err, stats) {
+ if(err) throw err;
+ expect(stats.isFile()).to.be.true;
+
+ shell.rm(file, function(err) {
+ if(err) throw err;
+
+ shell.unzip(zipfile, function(err) {
+ if(err) throw err;
+
+ fs.stat(file, function(err, stats) {
+ if(err) throw err;
+ expect(stats.isFile()).to.be.true;
+
+ fs.readFile(Path.join('/', file), 'utf8', function(err, data) {
+ if(err) throw err;
+ expect(data).to.equal(contents);
+ done();
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+
+ itShouldWorkInPhantomJSButDoesNot('should be able to handle a deep tree structure in a zip', function(done) {
+ // test-dir.zip has the following structure:
+ //
+ // test-dir/
+ // ├── test-dir2
+ // │ └── test-file.txt
+ // ├── test-file.txt
+ // └── test-file2.txt
+
+ var fs = util.fs();
+ var shell = fs.Shell();
+ var url = "test-dir.zip";
+ var Path = Filer.Path;
+ var contents = "This is a test file used in some of the tests.\n";
+
+ function confirmFile(filename, callback) {
+ filename = Path.join('/', filename);
+ fs.readFile(filename, 'utf8', function(err, data) {
+ if(err) {
+ console.error('Expected ' + filename + ' to exist.');
+ expect(false).to.be.true;
+ return callback(err);
+ }
+ expect(data).to.equal(contents);
+ callback();
+ });
+ }
+
+ function confirmDir(dirname, callback) {
+ dirname = Path.join('/', dirname);
+ fs.stat(dirname, function(err, stats) {
+ if(err) {
+ console.error('Expected ' + dirname + ' to exist.');
+ expect(false).to.be.true;
+ return callback(err);
+ }
+ expect(stats.isDirectory()).to.be.true;
+ callback();
+ });
+ }
+
+ shell.wget(url, {filename: url}, function(err, path) {
+ if(err) throw err;
+
+ shell.unzip(path, function(err) {
+ if(err) throw err;
+
+ // Forgive the crazy indenting, trying to match tree structure ;)
+ confirmDir('test-dir', function() {
+ confirmDir('test-dir/test-dir2', function() {
+ confirmFile('test-dir/test-dir2/test-file.txt', function() {
+ confirmFile('test-dir/test-file.txt', function() {
+ confirmFile('test-dir/test-file2.txt', function() {
+ done();
+ });});});});});
+
+ });
+ });
+ });
+
+ itShouldWorkInPhantomJSButDoesNot('should be able to re-create (unzip/zip) a deep tree structure in a zip', function(done) {
+ // test-dir.zip has the following structure:
+ //
+ // test-dir/
+ // ├── test-dir2
+ // │ └── test-file.txt
+ // ├── test-file.txt
+ // └── test-file2.txt
+
+ var fs = util.fs();
+ var shell = fs.Shell();
+ var url = "test-dir.zip";
+ var Path = Filer.Path;
+ var contents = "This is a test file used in some of the tests.\n";
+
+ function confirmFile(filename, callback) {
+ filename = Path.join('/unzipped', filename);
+ fs.readFile(filename, 'utf8', function(err, data) {
+ if(err) {
+ console.error('Expected ' + filename + ' to exist.');
+ expect(false).to.be.true;
+ return callback(err);
+ }
+ expect(data).to.equal(contents);
+ callback();
+ });
+ }
+
+ function confirmDir(dirname, callback) {
+ dirname = Path.join('/unzipped', dirname);
+ fs.stat(dirname, function(err, stats) {
+ if(err) {
+ console.error('Expected ' + dirname + ' to exist.');
+ expect(false).to.be.true;
+ return callback(err);
+ }
+ expect(stats.isDirectory()).to.be.true;
+ callback();
+ });
+ }
+
+ shell.wget(url, {filename: url}, function(err, path) {
+ if(err) throw err;
+
+ shell.unzip(path, function(err) {
+ if(err) throw err;
+
+ shell.zip('/test-dir2.zip', '/test-dir', { recursive: true }, function(err) {
+ if(err) throw err;
+
+ shell.mkdirp('/unzipped', function(err) {
+ if(err) throw err;
+
+ shell.unzip('/test-dir2.zip', { destination: '/unzipped' }, function(err) {
+ if(err) throw err;
+
+ // Forgive the crazy indenting, trying to match tree structure ;)
+ confirmDir('test-dir', function() {
+ confirmDir('test-dir/test-dir2', function() {
+ confirmFile('test-dir/test-dir2/test-file.txt', function() {
+ confirmFile('test-dir/test-file.txt', function() {
+ confirmFile('test-dir/test-file2.txt', function() {
+ done();
+ });});});});});
+
+ });
+ });
+ });
+ });
+ });
+ });
+
+ itShouldWorkInPhantomJSButDoesNot('should fail if the zipfile already exists', function(done) {
+ var fs = util.fs();
+ var shell = fs.Shell();
+ var file = "/file";
+ var zipfile = "/zipfile.zip";
+ var contents = "This is a test file used in some of the tests.\n";
+
+ fs.writeFile(file, contents, function(err) {
+ if(err) throw err;
+
+ shell.zip(zipfile, file, function(err) {
+ if(err) throw err;
+ shell.zip(zipfile, file, function(err) {
+ expect(err).to.exist;
+ expect(err.code).to.equal('EEXIST');
+ done();
+ });
+ });
+ });
+ });
+
+ });
+});
diff --git a/tests/test-dir.zip b/tests/test-dir.zip
new file mode 100644
index 0000000..0e41eca
Binary files /dev/null and b/tests/test-dir.zip differ
diff --git a/tests/test-file.txt b/tests/test-file.txt
new file mode 100644
index 0000000..a5c0182
--- /dev/null
+++ b/tests/test-file.txt
@@ -0,0 +1 @@
+This is a test file used in some of the tests.
diff --git a/tests/test-file.txt.zip b/tests/test-file.txt.zip
new file mode 100644
index 0000000..e6bf443
Binary files /dev/null and b/tests/test-file.txt.zip differ
diff --git a/tests/test-manifest.js b/tests/test-manifest.js
index 1e5a908..e6e7dd1 100644
--- a/tests/test-manifest.js
+++ b/tests/test-manifest.js
@@ -57,6 +57,8 @@ define([
"spec/shell/rm.spec",
"spec/shell/env.spec",
"spec/shell/mkdirp.spec",
+ "spec/shell/wget.spec",
+ "spec/shell/zip-unzip.spec",
// Ported node.js tests (filenames match names in https://github.com/joyent/node/tree/master/test)
"spec/node-js/simple/test-fs-mkdir",