UNPKG

12.3 kBPlain TextView Raw
1import * as fse from "fs-extra";
2import { expect } from "chai";
3import path from "./assert_path";
4import helper from "./helper";
5import * as jetpack from "..";
6import { InspectTreeResult } from "../types";
7
8describe("inspectTree", () => {
9 beforeEach(helper.setCleanTestCwd);
10 afterEach(helper.switchBackToCorrectCwd);
11
12 describe("inspects whole tree of files", () => {
13 const preparations = () => {
14 fse.outputFileSync("dir/file.txt", "abc");
15 fse.outputFileSync("dir/subdir/file.txt", "defg");
16 };
17
18 const expectations = (data: InspectTreeResult) => {
19 expect(data).to.eql({
20 name: "dir",
21 type: "dir",
22 size: 7,
23 children: [
24 {
25 name: "file.txt",
26 type: "file",
27 size: 3
28 },
29 {
30 name: "subdir",
31 type: "dir",
32 size: 4,
33 children: [
34 {
35 name: "file.txt",
36 type: "file",
37 size: 4
38 }
39 ]
40 }
41 ]
42 });
43 };
44
45 it("sync", () => {
46 preparations();
47 expectations(jetpack.inspectTree("dir"));
48 });
49
50 it("async", done => {
51 preparations();
52 jetpack.inspectTreeAsync("dir").then(tree => {
53 expectations(tree);
54 done();
55 });
56 });
57 });
58
59 describe("can calculate size of a whole tree", () => {
60 const preparations = () => {
61 fse.mkdirsSync("dir/empty");
62 fse.outputFileSync("dir/empty.txt", "");
63 fse.outputFileSync("dir/file.txt", "abc");
64 fse.outputFileSync("dir/subdir/file.txt", "defg");
65 };
66
67 const expectations = (data: InspectTreeResult) => {
68 // dir
69 expect(data.size).to.equal(7);
70 // dir/empty
71 expect(data.children[0].size).to.equal(0);
72 // dir/empty.txt
73 expect(data.children[1].size).to.equal(0);
74 // dir/file.txt
75 expect(data.children[2].size).to.equal(3);
76 // dir/subdir
77 expect(data.children[3].size).to.equal(4);
78 // dir/subdir/file.txt
79 expect(data.children[3].children[0].size).to.equal(4);
80 };
81
82 it("sync", () => {
83 preparations();
84 expectations(jetpack.inspectTree("dir"));
85 });
86
87 it("async", done => {
88 preparations();
89 jetpack.inspectTreeAsync("dir").then(tree => {
90 expectations(tree);
91 done();
92 });
93 });
94 });
95
96 describe("can output relative path for every tree node", () => {
97 const preparations = () => {
98 fse.outputFileSync("dir/subdir/file.txt", "defg");
99 };
100
101 const expectations = (data: InspectTreeResult) => {
102 // data will look like...
103 // {
104 // name: 'dir',
105 // relativePath: '.',
106 // children: [
107 // {
108 // name: 'subdir',
109 // relativePath: './subdir',
110 // children: [
111 // {
112 // name: 'file.txt',
113 // relativePath: './subdir/file.txt'
114 // }
115 // ]
116 // }
117 // ]
118 // }
119 expect(data.relativePath).to.equal(".");
120 expect(data.children[0].relativePath).to.equal("./subdir");
121 expect(data.children[0].children[0].relativePath).to.equal(
122 "./subdir/file.txt"
123 );
124 };
125
126 it("sync", () => {
127 preparations();
128 expectations(jetpack.inspectTree("dir", { relativePath: true }));
129 });
130
131 it("async", done => {
132 preparations();
133 jetpack.inspectTreeAsync("dir", { relativePath: true }).then(tree => {
134 expectations(tree);
135 done();
136 });
137 });
138 });
139
140 describe("if given path is a file just inspects that file", () => {
141 const preparations = () => {
142 fse.outputFileSync("dir/file.txt", "abc");
143 };
144
145 const expectations = (data: InspectTreeResult) => {
146 expect(data).to.eql({
147 name: "file.txt",
148 type: "file",
149 size: 3
150 });
151 };
152
153 it("sync", () => {
154 preparations();
155 expectations(jetpack.inspectTree("dir/file.txt"));
156 });
157
158 it("async", done => {
159 preparations();
160 jetpack.inspectTreeAsync("dir/file.txt").then(tree => {
161 expectations(tree);
162 done();
163 });
164 });
165 });
166
167 describe("behaves ok with empty directory", () => {
168 const preparations = () => {
169 fse.mkdirsSync("empty");
170 };
171
172 const expectations = (data: InspectTreeResult) => {
173 expect(data).to.eql({
174 name: "empty",
175 type: "dir",
176 size: 0,
177 children: []
178 });
179 };
180
181 it("sync", () => {
182 preparations();
183 expectations(jetpack.inspectTree("empty"));
184 });
185
186 it("async", done => {
187 preparations();
188 jetpack.inspectTreeAsync("empty").then(tree => {
189 expectations(tree);
190 done();
191 });
192 });
193 });
194
195 describe("returns undefined if path doesn't exist", () => {
196 const expectations = (data: InspectTreeResult) => {
197 expect(data).to.equal(undefined);
198 };
199
200 it("sync", () => {
201 expectations(jetpack.inspectTree("nonexistent"));
202 });
203
204 it("async", done => {
205 jetpack.inspectTreeAsync("nonexistent").then(dataAsync => {
206 expectations(dataAsync);
207 done();
208 });
209 });
210 });
211
212 describe("respects internal CWD of jetpack instance", () => {
213 const preparations = () => {
214 fse.outputFileSync("a/b.txt", "abc");
215 };
216
217 const expectations = (data: InspectTreeResult) => {
218 expect(data.name).to.equal("b.txt");
219 };
220
221 it("sync", () => {
222 const jetContext = jetpack.cwd("a");
223 preparations();
224 expectations(jetContext.inspectTree("b.txt"));
225 });
226
227 it("async", done => {
228 const jetContext = jetpack.cwd("a");
229 preparations();
230 jetContext.inspectTreeAsync("b.txt").then(data => {
231 expectations(data);
232 done();
233 });
234 });
235 });
236
237 describe("reports symlinks by default", () => {
238 const preparations = () => {
239 fse.outputFileSync("dir/file.txt", "abc");
240 fse.symlinkSync("file.txt", "dir/symlinked_file.txt");
241 };
242
243 const expectations = (data: InspectTreeResult) => {
244 expect(data).to.eql({
245 name: "dir",
246 type: "dir",
247 size: 3,
248 children: [
249 {
250 name: "file.txt",
251 type: "file",
252 size: 3
253 },
254 {
255 name: "symlinked_file.txt",
256 type: "symlink",
257 pointsAt: "file.txt"
258 }
259 ]
260 });
261 };
262
263 it("sync", () => {
264 preparations();
265 expectations(jetpack.inspectTree("dir")); // implicit
266 expectations(jetpack.inspectTree("dir", { symlinks: "report" })); // explicit
267 });
268
269 it("async", done => {
270 preparations();
271 jetpack
272 .inspectTreeAsync("dir") // implicit
273 .then(tree => {
274 expectations(tree);
275 return jetpack.inspectTreeAsync("dir", { symlinks: "report" }); // explicit
276 })
277 .then(tree => {
278 expectations(tree);
279 done();
280 })
281 .catch(done);
282 });
283 });
284
285 describe("follows symlinks when option specified", () => {
286 const preparations = () => {
287 fse.outputFileSync("dir/file.txt", "abc");
288 fse.symlinkSync("file.txt", "dir/symlinked_file.txt");
289 };
290
291 const expectations = (data: InspectTreeResult) => {
292 expect(data).to.eql({
293 name: "dir",
294 type: "dir",
295 size: 6,
296 children: [
297 {
298 name: "file.txt",
299 type: "file",
300 size: 3
301 },
302 {
303 name: "symlinked_file.txt",
304 type: "file",
305 size: 3
306 }
307 ]
308 });
309 };
310
311 it("sync", () => {
312 preparations();
313 expectations(jetpack.inspectTree("dir", { symlinks: "follow" }));
314 });
315
316 it("async", done => {
317 preparations();
318 jetpack
319 .inspectTreeAsync("dir", { symlinks: "follow" })
320 .then(tree => {
321 expectations(tree);
322 done();
323 })
324 .catch(done);
325 });
326 });
327
328 describe("can compute checksum of a whole tree", () => {
329 const preparations = () => {
330 fse.outputFileSync("dir/a.txt", "abc");
331 fse.outputFileSync("dir/b.txt", "defg");
332 };
333
334 const expectations = (data: InspectTreeResult) => {
335 // md5 of
336 // 'a.txt' + '900150983cd24fb0d6963f7d28e17f72' +
337 // 'b.txt' + '025e4da7edac35ede583f5e8d51aa7ec'
338 expect(data.md5).to.equal("b0ff9df854172efe752cb36b96c8bccd");
339 // md5 of 'abc'
340 expect(data.children[0].md5).to.equal("900150983cd24fb0d6963f7d28e17f72");
341 // md5 of 'defg'
342 expect(data.children[1].md5).to.equal("025e4da7edac35ede583f5e8d51aa7ec");
343 };
344
345 it("sync", () => {
346 preparations();
347 expectations(jetpack.inspectTree("dir", { checksum: "md5" }));
348 });
349
350 it("async", done => {
351 preparations();
352 jetpack.inspectTreeAsync("dir", { checksum: "md5" }).then(tree => {
353 expectations(tree);
354 done();
355 });
356 });
357 });
358
359 describe("can count checksum of empty directory", () => {
360 const preparations = () => {
361 fse.mkdirsSync("empty_dir");
362 };
363
364 const expectations = (data: InspectTreeResult) => {
365 // md5 of empty string
366 expect(data.md5).to.equal("d41d8cd98f00b204e9800998ecf8427e");
367 };
368
369 // SYNC
370 it("sync", () => {
371 preparations();
372 expectations(jetpack.inspectTree("empty_dir", { checksum: "md5" }));
373 });
374
375 it("async", done => {
376 preparations();
377 jetpack.inspectTreeAsync("empty_dir", { checksum: "md5" }).then(tree => {
378 expectations(tree);
379 done();
380 });
381 });
382 });
383
384 describe("input validation", () => {
385 const tests = [
386 {
387 type: "sync",
388 method: jetpack.inspectTree as any,
389 methodName: "inspectTree"
390 },
391 {
392 type: "async",
393 method: jetpack.inspectTreeAsync as any,
394 methodName: "inspectTreeAsync"
395 }
396 ];
397
398 describe('"path" argument', () => {
399 tests.forEach(test => {
400 it(test.type, () => {
401 expect(() => {
402 test.method(undefined);
403 }).to.throw(
404 `Argument "path" passed to ${
405 test.methodName
406 }(path, [options]) must be a string. Received undefined`
407 );
408 });
409 });
410 });
411
412 describe('"options" object', () => {
413 describe('"checksum" argument', () => {
414 tests.forEach(test => {
415 it(test.type, () => {
416 expect(() => {
417 test.method("abc", { checksum: 1 });
418 }).to.throw(
419 `Argument "options.checksum" passed to ${
420 test.methodName
421 }(path, [options]) must be a string. Received number`
422 );
423 });
424 it(test.type, () => {
425 expect(() => {
426 test.method("abc", { checksum: "foo" });
427 }).to.throw(
428 `Argument "options.checksum" passed to ${
429 test.methodName
430 }(path, [options]) must have one of values: md5, sha1, sha256`
431 );
432 });
433 });
434 });
435 describe('"relativePath" argument', () => {
436 tests.forEach(test => {
437 it(test.type, () => {
438 expect(() => {
439 test.method("abc", { relativePath: 1 });
440 }).to.throw(
441 `Argument "options.relativePath" passed to ${
442 test.methodName
443 }(path, [options]) must be a boolean. Received number`
444 );
445 });
446 });
447 });
448 describe('"symlinks" argument', () => {
449 tests.forEach(test => {
450 it(test.type, () => {
451 expect(() => {
452 test.method("abc", { symlinks: 1 });
453 }).to.throw(
454 `Argument "options.symlinks" passed to ${
455 test.methodName
456 }(path, [options]) must be a string. Received number`
457 );
458 });
459 it(test.type, () => {
460 expect(() => {
461 test.method("abc", { symlinks: "foo" });
462 }).to.throw(
463 `Argument "options.symlinks" passed to ${
464 test.methodName
465 }(path, [options]) must have one of values: report, follow`
466 );
467 });
468 });
469 });
470 });
471 });
472});