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