UNPKG

8.96 kBPlain TextView Raw
1import * as fse from "fs-extra";
2import { expect } from "chai";
3import * as pathUtil from "path";
4import path from "./assert_path";
5import helper from "./helper";
6import * as jetpack from "..";
7import { FSJetpack } from "../types";
8
9describe("dir", () => {
10 beforeEach(helper.setCleanTestCwd);
11 afterEach(helper.switchBackToCorrectCwd);
12
13 describe("creates directory if it doesn't exist", () => {
14 const expectations = () => {
15 path("x").shouldBeDirectory();
16 };
17
18 it("sync", () => {
19 jetpack.dir("x");
20 expectations();
21 });
22
23 it("async", done => {
24 jetpack.dirAsync("x").then(() => {
25 expectations();
26 done();
27 });
28 });
29 });
30
31 describe("does nothing if directory already exists", () => {
32 const preparations = () => {
33 fse.mkdirsSync("x");
34 };
35
36 const expectations = () => {
37 path("x").shouldBeDirectory();
38 };
39
40 it("sync", () => {
41 preparations();
42 jetpack.dir("x");
43 expectations();
44 });
45
46 it("async", done => {
47 preparations();
48 jetpack.dirAsync("x").then(() => {
49 expectations();
50 done();
51 });
52 });
53 });
54
55 describe("creates nested directories if necessary", () => {
56 const expectations = () => {
57 path("a/b/c").shouldBeDirectory();
58 };
59
60 it("sync", () => {
61 jetpack.dir("a/b/c");
62 expectations();
63 });
64
65 it("async", done => {
66 jetpack.dirAsync("a/b/c").then(() => {
67 expectations();
68 done();
69 });
70 });
71 });
72
73 describe("handles well two calls racing to create the same directory", () => {
74 const expectations = () => {
75 path("a/b/c").shouldBeDirectory();
76 };
77
78 it("async", done => {
79 let doneCount = 0;
80 const check = () => {
81 doneCount += 1;
82 if (doneCount === 2) {
83 expectations();
84 done();
85 }
86 };
87 jetpack.dirAsync("a/b/c").then(check);
88 jetpack.dirAsync("a/b/c").then(check);
89 });
90 });
91
92 describe("doesn't touch directory content by default", () => {
93 const preparations = () => {
94 fse.mkdirsSync("a/b");
95 fse.outputFileSync("a/c.txt", "abc");
96 };
97
98 const expectations = () => {
99 path("a/b").shouldBeDirectory();
100 path("a/c.txt").shouldBeFileWithContent("abc");
101 };
102
103 it("sync", () => {
104 preparations();
105 jetpack.dir("a");
106 expectations();
107 });
108
109 it("async", done => {
110 preparations();
111 jetpack.dirAsync("a").then(() => {
112 expectations();
113 done();
114 });
115 });
116 });
117
118 describe("makes directory empty if that option specified", () => {
119 const preparations = () => {
120 fse.outputFileSync("a/b/file.txt", "abc");
121 };
122
123 const expectations = () => {
124 path("a/b/file.txt").shouldNotExist();
125 path("a").shouldBeDirectory();
126 };
127
128 it("sync", () => {
129 preparations();
130 jetpack.dir("a", { empty: true });
131 expectations();
132 });
133
134 it("async", done => {
135 preparations();
136 jetpack.dirAsync("a", { empty: true }).then(() => {
137 expectations();
138 done();
139 });
140 });
141 });
142
143 describe("throws if given path is something other than directory", () => {
144 const preparations = () => {
145 fse.outputFileSync("a", "abc");
146 };
147
148 const expectations = (err: any) => {
149 expect(err.message).to.have.string("exists but is not a directory");
150 };
151
152 it("sync", () => {
153 preparations();
154 try {
155 jetpack.dir("a");
156 throw new Error("Expected error to be thrown");
157 } catch (err) {
158 expectations(err);
159 }
160 });
161
162 it("async", done => {
163 preparations();
164 jetpack.dirAsync("a").catch(err => {
165 expectations(err);
166 done();
167 });
168 });
169 });
170
171 describe("respects internal CWD of jetpack instance", () => {
172 const expectations = () => {
173 path("a/b").shouldBeDirectory();
174 };
175
176 it("sync", () => {
177 const jetContext = jetpack.cwd("a");
178 jetContext.dir("b");
179 expectations();
180 });
181
182 it("async", done => {
183 const jetContext = jetpack.cwd("a");
184 jetContext.dirAsync("b").then(() => {
185 expectations();
186 done();
187 });
188 });
189 });
190
191 describe("returns jetack instance pointing on this directory", () => {
192 const expectations = (jetpackContext: FSJetpack) => {
193 expect(jetpackContext.cwd()).to.equal(pathUtil.resolve("a"));
194 };
195
196 it("sync", () => {
197 expectations(jetpack.dir("a"));
198 });
199
200 it("async", done => {
201 jetpack.dirAsync("a").then(jetpackContext => {
202 expectations(jetpackContext);
203 done();
204 });
205 });
206 });
207
208 if (process.platform !== "win32") {
209 describe("sets mode to newly created directory (unix only)", () => {
210 const expectations = () => {
211 path("a").shouldHaveMode("511");
212 };
213
214 it("sync, mode passed as string", () => {
215 jetpack.dir("a", { mode: "511" });
216 expectations();
217 });
218
219 it("sync, mode passed as number", () => {
220 jetpack.dir("a", { mode: 0o511 });
221 expectations();
222 });
223
224 it("async, mode passed as string", done => {
225 jetpack.dirAsync("a", { mode: "511" }).then(() => {
226 expectations();
227 done();
228 });
229 });
230
231 it("async, mode passed as number", done => {
232 jetpack.dirAsync("a", { mode: 0o511 }).then(() => {
233 expectations();
234 done();
235 });
236 });
237 });
238
239 describe("sets desired mode to every created directory (unix only)", () => {
240 const expectations = () => {
241 path("a").shouldHaveMode("711");
242 path("a/b").shouldHaveMode("711");
243 };
244
245 it("sync", () => {
246 jetpack.dir("a/b", { mode: "711" });
247 expectations();
248 });
249
250 it("async", done => {
251 jetpack.dirAsync("a/b", { mode: "711" }).then(() => {
252 expectations();
253 done();
254 });
255 });
256 });
257
258 describe("changes mode of existing directory to desired (unix only)", () => {
259 const preparations = () => {
260 fse.mkdirSync("a", "777");
261 };
262 const expectations = () => {
263 path("a").shouldHaveMode("511");
264 };
265
266 it("sync", () => {
267 preparations();
268 jetpack.dir("a", { mode: "511" });
269 expectations();
270 });
271
272 it("async", done => {
273 preparations();
274 jetpack.dirAsync("a", { mode: "511" }).then(() => {
275 expectations();
276 done();
277 });
278 });
279 });
280
281 describe("leaves mode of directory intact by default (unix only)", () => {
282 const preparations = () => {
283 fse.mkdirSync("a", "700");
284 };
285
286 const expectations = () => {
287 path("a").shouldHaveMode("700");
288 };
289
290 it("sync", () => {
291 preparations();
292 jetpack.dir("a");
293 expectations();
294 });
295
296 it("async", done => {
297 preparations();
298 jetpack.dirAsync("a").then(() => {
299 expectations();
300 done();
301 });
302 });
303 });
304 } else {
305 describe("specyfying mode have no effect and throws no error (windows only)", () => {
306 const expectations = () => {
307 path("x").shouldBeDirectory();
308 };
309
310 it("sync", () => {
311 jetpack.dir("x", { mode: "511" });
312 expectations();
313 });
314
315 it("async", done => {
316 jetpack.dirAsync("x", { mode: "511" }).then(() => {
317 expectations();
318 done();
319 });
320 });
321 });
322 }
323
324 describe("input validation", () => {
325 const tests = [
326 { type: "sync", method: jetpack.dir as any, methodName: "dir" },
327 { type: "async", method: jetpack.dirAsync as any, methodName: "dirAsync" }
328 ];
329
330 describe('"path" argument', () => {
331 tests.forEach(test => {
332 it(test.type, () => {
333 expect(() => {
334 test.method(undefined);
335 }).to.throw(
336 `Argument "path" passed to ${
337 test.methodName
338 }(path, [criteria]) must be a string. Received undefined`
339 );
340 });
341 });
342 });
343
344 describe('"criteria" object', () => {
345 describe('"empty" argument', () => {
346 tests.forEach(test => {
347 it(test.type, () => {
348 expect(() => {
349 test.method("abc", { empty: 1 });
350 }).to.throw(
351 `Argument "criteria.empty" passed to ${
352 test.methodName
353 }(path, [criteria]) must be a boolean. Received number`
354 );
355 });
356 });
357 });
358 describe('"mode" argument', () => {
359 tests.forEach(test => {
360 it(test.type, () => {
361 expect(() => {
362 test.method("abc", { mode: true });
363 }).to.throw(
364 `Argument "criteria.mode" passed to ${
365 test.methodName
366 }(path, [criteria]) must be a string or a number. Received boolean`
367 );
368 });
369 });
370 });
371 });
372 });
373});