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 |
|
7 | describe("write", () => {
|
8 | beforeEach(helper.setCleanTestCwd);
|
9 | afterEach(helper.switchBackToCorrectCwd);
|
10 |
|
11 | describe("writes data from string", () => {
|
12 | const expectations = () => {
|
13 | path("file.txt").shouldBeFileWithContent("abc");
|
14 | };
|
15 |
|
16 | it("sync", () => {
|
17 | jetpack.write("file.txt", "abc");
|
18 | expectations();
|
19 | });
|
20 |
|
21 | it("async", done => {
|
22 | jetpack.writeAsync("file.txt", "abc").then(() => {
|
23 | expectations();
|
24 | done();
|
25 | });
|
26 | });
|
27 | });
|
28 |
|
29 | describe("writes data from Buffer", () => {
|
30 | const expectations = () => {
|
31 | path("file.txt").shouldBeFileWithContent(new Buffer([11, 22]));
|
32 | };
|
33 |
|
34 | it("sync", () => {
|
35 | jetpack.write("file.txt", new Buffer([11, 22]));
|
36 | expectations();
|
37 | });
|
38 |
|
39 | it("async", done => {
|
40 | jetpack.writeAsync("file.txt", new Buffer([11, 22])).then(() => {
|
41 | expectations();
|
42 | done();
|
43 | });
|
44 | });
|
45 | });
|
46 |
|
47 | describe("writes data as JSON", () => {
|
48 | const obj = {
|
49 | utf8: "ąćłźż"
|
50 | };
|
51 |
|
52 | const expectations = () => {
|
53 | const content = JSON.parse(fse.readFileSync("file.json", "utf8"));
|
54 | expect(content).to.eql(obj);
|
55 | };
|
56 |
|
57 | it("sync", () => {
|
58 | jetpack.write("file.json", obj);
|
59 | expectations();
|
60 | });
|
61 |
|
62 | it("async", done => {
|
63 | jetpack.writeAsync("file.json", obj).then(() => {
|
64 | expectations();
|
65 | done();
|
66 | });
|
67 | });
|
68 | });
|
69 |
|
70 | describe("written JSON data can be indented", () => {
|
71 | const obj = {
|
72 | utf8: "ąćłźż"
|
73 | };
|
74 |
|
75 | const expectations = () => {
|
76 | const sizeA = fse.statSync("a.json").size;
|
77 | const sizeB = fse.statSync("b.json").size;
|
78 | const sizeC = fse.statSync("c.json").size;
|
79 | expect(sizeB).to.be.above(sizeA);
|
80 | expect(sizeC).to.be.above(sizeB);
|
81 | };
|
82 |
|
83 | it("sync", () => {
|
84 | jetpack.write("a.json", obj, { jsonIndent: 0 });
|
85 | jetpack.write("b.json", obj);
|
86 | jetpack.write("c.json", obj, { jsonIndent: 4 });
|
87 | expectations();
|
88 | });
|
89 |
|
90 | it("async", done => {
|
91 | Promise.all([
|
92 | jetpack.writeAsync("a.json", obj, { jsonIndent: 0 }),
|
93 | jetpack.writeAsync("b.json", obj),
|
94 | jetpack.writeAsync("c.json", obj, { jsonIndent: 4 })
|
95 | ]).then(() => {
|
96 | expectations();
|
97 | done();
|
98 | });
|
99 | });
|
100 | });
|
101 |
|
102 | describe("writes and reads file as JSON with Date parsing", () => {
|
103 | const obj = {
|
104 | date: new Date()
|
105 | };
|
106 |
|
107 | const expectations = () => {
|
108 | const content = JSON.parse(fse.readFileSync("file.json", "utf8"));
|
109 | expect(content.date).to.equal(obj.date.toISOString());
|
110 | };
|
111 |
|
112 | it("sync", () => {
|
113 | jetpack.write("file.json", obj);
|
114 | expectations();
|
115 | });
|
116 |
|
117 | it("async", done => {
|
118 | jetpack.writeAsync("file.json", obj).then(() => {
|
119 | expectations();
|
120 | done();
|
121 | });
|
122 | });
|
123 | });
|
124 |
|
125 | if (process.platform !== "win32") {
|
126 | describe("sets mode of the file (unix only)", () => {
|
127 | const preparations = () => {
|
128 | fse.writeFileSync("file.txt", "abc", { mode: "700" });
|
129 | };
|
130 | const expectations = () => {
|
131 | path("file.txt").shouldBeFileWithContent("xyz");
|
132 | path("file.txt").shouldHaveMode("711");
|
133 | };
|
134 |
|
135 | it("sync, mode passed as string", () => {
|
136 | jetpack.write("file.txt", "xyz", { mode: "711" });
|
137 | expectations();
|
138 | });
|
139 |
|
140 | it("sync, mode passed as number", () => {
|
141 | jetpack.write("file.txt", "xyz", { mode: 0o711 });
|
142 | expectations();
|
143 | });
|
144 |
|
145 | it("async, mode passed as string", done => {
|
146 | jetpack
|
147 | .writeAsync("file.txt", "xyz", { mode: "711" })
|
148 | .then(() => {
|
149 | expectations();
|
150 | done();
|
151 | })
|
152 | .catch(done);
|
153 | });
|
154 |
|
155 | it("async, mode passed as number", done => {
|
156 | jetpack
|
157 | .writeAsync("file.txt", "xyz", { mode: 0o711 })
|
158 | .then(() => {
|
159 | expectations();
|
160 | done();
|
161 | })
|
162 | .catch(done);
|
163 | });
|
164 | });
|
165 | }
|
166 |
|
167 | describe("can create nonexistent parent directories", () => {
|
168 | const expectations = () => {
|
169 | path("a/b/c.txt").shouldBeFileWithContent("abc");
|
170 | };
|
171 |
|
172 | it("sync", () => {
|
173 | jetpack.write("a/b/c.txt", "abc");
|
174 | expectations();
|
175 | });
|
176 |
|
177 | it("async", done => {
|
178 | jetpack.writeAsync("a/b/c.txt", "abc").then(() => {
|
179 | expectations();
|
180 | done();
|
181 | });
|
182 | });
|
183 | });
|
184 |
|
185 | describe("respects internal CWD of jetpack instance", () => {
|
186 | const expectations = () => {
|
187 | path("a/b/c.txt").shouldBeFileWithContent("abc");
|
188 | };
|
189 |
|
190 | it("sync", () => {
|
191 | const jetContext = jetpack.cwd("a");
|
192 | jetContext.write("b/c.txt", "abc");
|
193 | expectations();
|
194 | });
|
195 |
|
196 | it("async", done => {
|
197 | const jetContext = jetpack.cwd("a");
|
198 | jetContext.writeAsync("b/c.txt", "abc").then(() => {
|
199 | expectations();
|
200 | done();
|
201 | });
|
202 | });
|
203 | });
|
204 |
|
205 | describe("input validation", () => {
|
206 | const tests = [
|
207 | { type: "sync", method: jetpack.write as any, methodName: "write" },
|
208 | {
|
209 | type: "async",
|
210 | method: jetpack.writeAsync as any,
|
211 | methodName: "writeAsync"
|
212 | }
|
213 | ];
|
214 |
|
215 | describe('"path" argument', () => {
|
216 | tests.forEach(test => {
|
217 | it(test.type, () => {
|
218 | expect(() => {
|
219 | test.method(undefined);
|
220 | }).to.throw(
|
221 | `Argument "path" passed to ${
|
222 | test.methodName
|
223 | }(path, data, [options]) must be a string. Received undefined`
|
224 | );
|
225 | });
|
226 | });
|
227 | });
|
228 |
|
229 | describe('"data" argument', () => {
|
230 | tests.forEach(test => {
|
231 | it(test.type, () => {
|
232 | expect(() => {
|
233 | test.method("abc", true);
|
234 | }).to.throw(
|
235 | `Argument "data" passed to ${
|
236 | test.methodName
|
237 | }(path, data, [options]) must be a string or a buffer or an object or an array. Received boolean`
|
238 | );
|
239 | });
|
240 | });
|
241 | });
|
242 |
|
243 | describe('"options" object', () => {
|
244 | describe('"atomic" argument', () => {
|
245 | tests.forEach(test => {
|
246 | it(test.type, () => {
|
247 | expect(() => {
|
248 | test.method("abc", "xyz", { atomic: 1 });
|
249 | }).to.throw(
|
250 | `Argument "options.atomic" passed to ${
|
251 | test.methodName
|
252 | }(path, data, [options]) must be a boolean. Received number`
|
253 | );
|
254 | });
|
255 | });
|
256 | });
|
257 | describe('"jsonIndent" argument', () => {
|
258 | tests.forEach(test => {
|
259 | it(test.type, () => {
|
260 | expect(() => {
|
261 | test.method("abc", "xyz", { jsonIndent: true });
|
262 | }).to.throw(
|
263 | `Argument "options.jsonIndent" passed to ${
|
264 | test.methodName
|
265 | }(path, data, [options]) must be a number. Received boolean`
|
266 | );
|
267 | });
|
268 | });
|
269 | });
|
270 | });
|
271 | });
|
272 | });
|