UNPKG

11.7 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 { FSJetpack } from "../types";
7
8describe("file", () => {
9 beforeEach(helper.setCleanTestCwd);
10 afterEach(helper.switchBackToCorrectCwd);
11
12 describe("creates file if it doesn't exist", () => {
13 const expectations = () => {
14 path("file.txt").shouldBeFileWithContent("");
15 };
16
17 it("sync", () => {
18 jetpack.file("file.txt");
19 expectations();
20 });
21
22 it("async", done => {
23 jetpack
24 .fileAsync("file.txt")
25 .then(() => {
26 expectations();
27 done();
28 })
29 .catch(done);
30 });
31 });
32
33 describe("leaves file intact if it already exists", () => {
34 const preparations = () => {
35 fse.outputFileSync("file.txt", "abc");
36 };
37
38 const expectations = () => {
39 path("file.txt").shouldBeFileWithContent("abc");
40 };
41
42 it("sync", () => {
43 preparations();
44 jetpack.file("file.txt");
45 expectations();
46 });
47
48 it("async", done => {
49 preparations();
50 jetpack
51 .fileAsync("file.txt")
52 .then(() => {
53 expectations();
54 done();
55 })
56 .catch(done);
57 });
58 });
59
60 describe("can save file content given as string", () => {
61 const expectations = () => {
62 path("file.txt").shouldBeFileWithContent("ąbć");
63 };
64
65 it("sync", () => {
66 jetpack.file("file.txt", { content: "ąbć" });
67 expectations();
68 });
69
70 it("async", done => {
71 jetpack
72 .fileAsync("file.txt", { content: "ąbć" })
73 .then(() => {
74 expectations();
75 done();
76 })
77 .catch(done);
78 });
79 });
80
81 describe("can save file content given as buffer", () => {
82 const expectations = () => {
83 path("file").shouldBeFileWithContent(new Buffer([11, 22]));
84 };
85
86 it("sync", () => {
87 jetpack.file("file", { content: new Buffer([11, 22]) });
88 expectations();
89 });
90
91 it("async", done => {
92 jetpack
93 .fileAsync("file", { content: new Buffer([11, 22]) })
94 .then(() => {
95 expectations();
96 done();
97 })
98 .catch(done);
99 });
100 });
101
102 describe("can save file content given as plain JS object (will be saved as JSON)", () => {
103 const obj = {
104 a: "abc",
105 b: 123
106 };
107
108 const expectations = () => {
109 const data = JSON.parse(fse.readFileSync("file.txt", "utf8"));
110 expect(data).to.eql(obj);
111 };
112
113 it("sync", () => {
114 jetpack.file("file.txt", { content: obj });
115 expectations();
116 });
117
118 it("async", done => {
119 jetpack
120 .fileAsync("file.txt", { content: obj })
121 .then(() => {
122 expectations();
123 done();
124 })
125 .catch(done);
126 });
127 });
128
129 describe("written JSON data can be indented", () => {
130 const obj = {
131 a: "abc",
132 b: 123
133 };
134
135 const expectations = () => {
136 const sizeA = fse.statSync("a.json").size;
137 const sizeB = fse.statSync("b.json").size;
138 const sizeC = fse.statSync("c.json").size;
139 expect(sizeB).to.be.above(sizeA);
140 expect(sizeC).to.be.above(sizeB);
141 };
142
143 it("sync", () => {
144 jetpack.file("a.json", { content: obj, jsonIndent: 0 });
145 jetpack.file("b.json", { content: obj }); // Default indent = 2
146 jetpack.file("c.json", { content: obj, jsonIndent: 4 });
147 expectations();
148 });
149
150 it("async", done => {
151 jetpack
152 .fileAsync("a.json", { content: obj, jsonIndent: 0 })
153 .then(() => {
154 return jetpack.fileAsync("b.json", { content: obj }); // Default indent = 2
155 })
156 .then(() => {
157 return jetpack.fileAsync("c.json", { content: obj, jsonIndent: 4 });
158 })
159 .then(() => {
160 expectations();
161 done();
162 })
163 .catch(done);
164 });
165 });
166
167 describe("replaces content of already existing file", () => {
168 const preparations = () => {
169 fse.writeFileSync("file.txt", "abc");
170 };
171
172 const expectations = () => {
173 path("file.txt").shouldBeFileWithContent("123");
174 };
175
176 it("sync", () => {
177 preparations();
178 jetpack.file("file.txt", { content: "123" });
179 expectations();
180 });
181
182 it("async", done => {
183 preparations();
184 jetpack
185 .fileAsync("file.txt", { content: "123" })
186 .then(() => {
187 expectations();
188 done();
189 })
190 .catch(done);
191 });
192 });
193
194 describe("throws if given path is not a file", () => {
195 const preparations = () => {
196 fse.mkdirsSync("a");
197 };
198
199 const expectations = (err: any) => {
200 expect(err.message).to.have.string("exists but is not a file.");
201 };
202
203 it("sync", () => {
204 preparations();
205 try {
206 jetpack.file("a");
207 throw new Error("Expected error to be thrown");
208 } catch (err) {
209 expectations(err);
210 }
211 });
212
213 it("async", done => {
214 preparations();
215 jetpack
216 .fileAsync("a")
217 .catch(err => {
218 expectations(err);
219 done();
220 })
221 .catch(done);
222 });
223 });
224
225 describe("if directory for file doesn't exist creates it as well", () => {
226 const expectations = () => {
227 path("a/b/c.txt").shouldBeFileWithContent("");
228 };
229
230 it("sync", () => {
231 jetpack.file("a/b/c.txt");
232 expectations();
233 });
234
235 it("async", done => {
236 jetpack
237 .fileAsync("a/b/c.txt")
238 .then(() => {
239 expectations();
240 done();
241 })
242 .catch(done);
243 });
244 });
245
246 describe("returns currently used jetpack instance", () => {
247 const expectations = (jetpackContext: FSJetpack) => {
248 expect(jetpackContext).to.equal(jetpack);
249 };
250
251 it("sync", () => {
252 expectations(jetpack.file("file.txt"));
253 });
254
255 it("async", done => {
256 jetpack
257 .fileAsync("file.txt")
258 .then(jetpackContext => {
259 expectations(jetpackContext);
260 done();
261 })
262 .catch(done);
263 });
264 });
265
266 describe("respects internal CWD of jetpack instance", () => {
267 const expectations = () => {
268 path("a/b.txt").shouldBeFileWithContent("");
269 };
270
271 it("sync", () => {
272 const jetContext = jetpack.cwd("a");
273 jetContext.file("b.txt");
274 expectations();
275 });
276
277 it("async", done => {
278 const jetContext = jetpack.cwd("a");
279 jetContext
280 .fileAsync("b.txt")
281 .then(() => {
282 expectations();
283 done();
284 })
285 .catch(done);
286 });
287 });
288
289 if (process.platform !== "win32") {
290 describe("sets mode of newly created file (unix only)", () => {
291 const expectations = () => {
292 path("file.txt").shouldHaveMode("711");
293 };
294
295 it("sync, mode passed as string", () => {
296 jetpack.file("file.txt", { mode: "711" });
297 expectations();
298 });
299
300 it("sync, mode passed as number", () => {
301 jetpack.file("file.txt", { mode: 0o711 });
302 expectations();
303 });
304
305 it("async, mode passed as string", done => {
306 jetpack
307 .fileAsync("file.txt", { mode: "711" })
308 .then(() => {
309 expectations();
310 done();
311 })
312 .catch(done);
313 });
314
315 it("async, mode passed as number", done => {
316 jetpack
317 .fileAsync("file.txt", { mode: 0o711 })
318 .then(() => {
319 expectations();
320 done();
321 })
322 .catch(done);
323 });
324 });
325
326 describe("changes mode of existing file if it doesn't match (unix only)", () => {
327 const preparations = () => {
328 fse.writeFileSync("file.txt", "abc", { mode: "700" });
329 };
330
331 const expectations = () => {
332 path("file.txt").shouldHaveMode("511");
333 };
334
335 it("sync", () => {
336 preparations();
337 jetpack.file("file.txt", { mode: "511" });
338 expectations();
339 });
340
341 it("async", done => {
342 preparations();
343 jetpack
344 .fileAsync("file.txt", { mode: "511" })
345 .then(() => {
346 expectations();
347 done();
348 })
349 .catch(done);
350 });
351 });
352
353 describe("leaves mode of file intact if not explicitly specified (unix only)", () => {
354 const preparations = () => {
355 fse.writeFileSync("file.txt", "abc", { mode: "700" });
356 };
357
358 const expectations = () => {
359 path("file.txt").shouldHaveMode("700");
360 };
361
362 it("sync, ensure exists", () => {
363 preparations();
364 jetpack.file("file.txt");
365 expectations();
366 });
367
368 it("sync, ensure content", () => {
369 preparations();
370 jetpack.file("file.txt", { content: "abc" });
371 expectations();
372 });
373
374 it("async, ensure exists", done => {
375 preparations();
376 jetpack
377 .fileAsync("file.txt")
378 .then(() => {
379 expectations();
380 done();
381 })
382 .catch(done);
383 });
384
385 it("async, ensure content", done => {
386 preparations();
387 jetpack
388 .fileAsync("file.txt", { content: "abc" })
389 .then(() => {
390 expectations();
391 done();
392 })
393 .catch(done);
394 });
395 });
396 } else {
397 describe("specyfying mode have no effect and throws no error (windows only)", () => {
398 it("sync", () => {
399 jetpack.file("file.txt", { mode: "711" });
400 });
401
402 it("async", done => {
403 jetpack
404 .fileAsync("file.txt", { mode: "711" })
405 .then(() => {
406 done();
407 })
408 .catch(done);
409 });
410 });
411 }
412
413 describe("input validation", () => {
414 const tests = [
415 { type: "sync", method: jetpack.file as any, methodName: "file" },
416 {
417 type: "async",
418 method: jetpack.fileAsync as any,
419 methodName: "fileAsync"
420 }
421 ];
422
423 describe('"path" argument', () => {
424 tests.forEach(test => {
425 it(test.type, () => {
426 expect(() => {
427 test.method(undefined);
428 }).to.throw(
429 `Argument "path" passed to ${
430 test.methodName
431 }(path, [criteria]) must be a string. Received undefined`
432 );
433 });
434 });
435 });
436
437 describe('"criteria" object', () => {
438 describe('"content" argument', () => {
439 tests.forEach(test => {
440 it(test.type, () => {
441 expect(() => {
442 test.method("abc", { content: 1 });
443 }).to.throw(
444 `Argument "criteria.content" passed to ${
445 test.methodName
446 }(path, [criteria]) must be a string or a buffer or an object or an array. Received number`
447 );
448 });
449 });
450 });
451 describe('"jsonIndent" argument', () => {
452 tests.forEach(test => {
453 it(test.type, () => {
454 expect(() => {
455 test.method("abc", { jsonIndent: true });
456 }).to.throw(
457 `Argument "criteria.jsonIndent" passed to ${
458 test.methodName
459 }(path, [criteria]) must be a number. Received boolean`
460 );
461 });
462 });
463 });
464 describe('"mode" argument', () => {
465 tests.forEach(test => {
466 it(test.type, () => {
467 expect(() => {
468 test.method("abc", { mode: true });
469 }).to.throw(
470 `Argument "criteria.mode" passed to ${
471 test.methodName
472 }(path, [criteria]) must be a string or a number. Received boolean`
473 );
474 });
475 });
476 });
477 });
478 });
479});