@jsenv/snapshot 2.10.2 → 2.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/snapshot",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.3",
|
|
4
4
|
"description": "Snapshot testing",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@jsenv/assert": "4.4.1",
|
|
37
|
-
"@jsenv/ast": "6.2.
|
|
37
|
+
"@jsenv/ast": "6.2.17",
|
|
38
38
|
"@jsenv/exception": "1.1.2",
|
|
39
39
|
"@jsenv/humanize": "1.2.8",
|
|
40
40
|
"@jsenv/filesystem": "4.10.2",
|
|
@@ -15,6 +15,13 @@ export const createCaptureSideEffects = ({
|
|
|
15
15
|
rootDirectoryUrl,
|
|
16
16
|
}),
|
|
17
17
|
}) => {
|
|
18
|
+
if (executionEffects === false) {
|
|
19
|
+
executionEffects = {
|
|
20
|
+
catch: false,
|
|
21
|
+
return: false,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
const detectors = [];
|
|
19
26
|
if (logEffects) {
|
|
20
27
|
detectors.push(logSideEffects(logEffects === true ? {} : logEffects));
|
|
@@ -283,6 +290,33 @@ export const createCaptureSideEffects = ({
|
|
|
283
290
|
finallyCallbackSet.clear();
|
|
284
291
|
};
|
|
285
292
|
|
|
293
|
+
const onThrowOrReject = (value, isThrow) => {
|
|
294
|
+
if (executionEffects.catch === false) {
|
|
295
|
+
throw value;
|
|
296
|
+
}
|
|
297
|
+
if (typeof executionEffects.catch === "function") {
|
|
298
|
+
executionEffects.catch(value);
|
|
299
|
+
}
|
|
300
|
+
if (isThrow) {
|
|
301
|
+
onCatch(value);
|
|
302
|
+
} else {
|
|
303
|
+
onReject(value);
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
const onReturnOrResolve = (value, isReturn) => {
|
|
307
|
+
if (executionEffects.return === false) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
if (typeof executionEffects.return === "function") {
|
|
311
|
+
executionEffects.return(value);
|
|
312
|
+
}
|
|
313
|
+
if (isReturn) {
|
|
314
|
+
onReturn(value);
|
|
315
|
+
} else {
|
|
316
|
+
onResolve(value);
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
286
320
|
process.env.CAPTURING_SIDE_EFFECTS = "1";
|
|
287
321
|
functionExecutingCount++;
|
|
288
322
|
let returnedPromise = false;
|
|
@@ -292,34 +326,22 @@ export const createCaptureSideEffects = ({
|
|
|
292
326
|
onReturn(RETURN_PROMISE);
|
|
293
327
|
returnedPromise = valueReturned.then(
|
|
294
328
|
(value) => {
|
|
295
|
-
|
|
329
|
+
onReturnOrResolve(value);
|
|
296
330
|
onFinally();
|
|
297
331
|
return sideEffects;
|
|
298
332
|
},
|
|
299
333
|
(e) => {
|
|
300
|
-
|
|
301
|
-
throw e;
|
|
302
|
-
}
|
|
303
|
-
if (typeof executionEffects.catch === "function") {
|
|
304
|
-
executionEffects.catch(e);
|
|
305
|
-
}
|
|
306
|
-
onReject(e);
|
|
334
|
+
onThrowOrReject(e);
|
|
307
335
|
onFinally();
|
|
308
336
|
return sideEffects;
|
|
309
337
|
},
|
|
310
338
|
);
|
|
311
339
|
return returnedPromise;
|
|
312
340
|
}
|
|
313
|
-
|
|
341
|
+
onReturnOrResolve(valueReturned, true);
|
|
314
342
|
return sideEffects;
|
|
315
343
|
} catch (e) {
|
|
316
|
-
|
|
317
|
-
throw e;
|
|
318
|
-
}
|
|
319
|
-
if (typeof executionEffects.catch === "function") {
|
|
320
|
-
executionEffects.catch(e);
|
|
321
|
-
}
|
|
322
|
-
onCatch(e);
|
|
344
|
+
onThrowOrReject(e, true);
|
|
323
345
|
return sideEffects;
|
|
324
346
|
} finally {
|
|
325
347
|
if (!returnedPromise) {
|
|
@@ -49,7 +49,7 @@ export const spyFilesystemCalls = (
|
|
|
49
49
|
const fileDescriptorPathMap = new Map();
|
|
50
50
|
const fileRestoreMap = new Map();
|
|
51
51
|
const dirRestoreMap = new Map();
|
|
52
|
-
const
|
|
52
|
+
const onFileMutationDone = (stateBefore, stateAfter) => {
|
|
53
53
|
if (!stateAfter.found) {
|
|
54
54
|
// seems to be possible somehow
|
|
55
55
|
return;
|
|
@@ -58,39 +58,42 @@ export const spyFilesystemCalls = (
|
|
|
58
58
|
// - writing file for the 1st time
|
|
59
59
|
// - updating file content
|
|
60
60
|
// the important part is the file content in the end of the function execution
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
61
|
+
let reason;
|
|
62
|
+
if (!stateBefore.found && stateAfter.found) {
|
|
63
|
+
reason = "created";
|
|
64
|
+
} else if (Buffer.compare(stateBefore.buffer, stateAfter.buffer)) {
|
|
65
|
+
reason = "content_modified";
|
|
66
|
+
} else if (stateBefore.mtimeMs !== stateAfter.mtimeMs) {
|
|
67
|
+
reason = "mtime_modified";
|
|
68
|
+
} else if (stateBefore.url !== stateAfter.url) {
|
|
69
|
+
reason = "moved";
|
|
70
|
+
} else {
|
|
70
71
|
// file is exactly the same
|
|
71
72
|
// function did not have any effect on the file
|
|
72
73
|
return;
|
|
73
74
|
}
|
|
74
|
-
const
|
|
75
|
+
const beforeUrl = stateBefore.url;
|
|
76
|
+
const afterUrl = stateAfter.url;
|
|
77
|
+
const action = getAction(beforeUrl);
|
|
75
78
|
const shouldCompare =
|
|
76
79
|
action === "compare" ||
|
|
77
80
|
action === "compare_presence_only" ||
|
|
78
81
|
action === true;
|
|
79
82
|
if (action === "undo" || shouldCompare) {
|
|
80
|
-
if (undoFilesystemSideEffects && !fileRestoreMap.has(
|
|
83
|
+
if (undoFilesystemSideEffects && !fileRestoreMap.has(beforeUrl)) {
|
|
81
84
|
if (stateBefore.found) {
|
|
82
|
-
fileRestoreMap.set(
|
|
83
|
-
writeFileSync(
|
|
85
|
+
fileRestoreMap.set(beforeUrl, () => {
|
|
86
|
+
writeFileSync(beforeUrl, stateBefore.buffer);
|
|
84
87
|
});
|
|
85
88
|
} else {
|
|
86
|
-
fileRestoreMap.set(
|
|
87
|
-
removeFileSync(
|
|
89
|
+
fileRestoreMap.set(beforeUrl, () => {
|
|
90
|
+
removeFileSync(beforeUrl, { allowUseless: true });
|
|
88
91
|
});
|
|
89
92
|
}
|
|
90
93
|
}
|
|
91
94
|
}
|
|
92
95
|
if (shouldCompare) {
|
|
93
|
-
onWriteFile(
|
|
96
|
+
onWriteFile(afterUrl, stateAfter.buffer, reason);
|
|
94
97
|
}
|
|
95
98
|
// "ignore", false, anything else
|
|
96
99
|
};
|
|
@@ -121,9 +124,9 @@ export const spyFilesystemCalls = (
|
|
|
121
124
|
};
|
|
122
125
|
const restoreCallbackSet = new Set();
|
|
123
126
|
|
|
124
|
-
const getFileStateWithinHook = (
|
|
127
|
+
const getFileStateWithinHook = (filePath) => {
|
|
125
128
|
return disableHooksWhileCalling(
|
|
126
|
-
() => getFileState(
|
|
129
|
+
() => getFileState(filePath),
|
|
127
130
|
[openHook, closeHook],
|
|
128
131
|
);
|
|
129
132
|
};
|
|
@@ -208,14 +211,13 @@ export const spyFilesystemCalls = (
|
|
|
208
211
|
fileDescriptorPathMap.delete(fileDescriptor);
|
|
209
212
|
return;
|
|
210
213
|
}
|
|
211
|
-
const fileUrl = pathToFileURL(filePath);
|
|
212
214
|
if (buffer) {
|
|
213
|
-
onReadFile(
|
|
215
|
+
onReadFile(filePath);
|
|
214
216
|
}
|
|
215
217
|
fileDescriptorPathMap.delete(fileDescriptor);
|
|
216
218
|
filesystemStateInfoMap.delete(filePath);
|
|
217
|
-
const stateAfter = getFileStateWithinHook(
|
|
218
|
-
|
|
219
|
+
const stateAfter = getFileStateWithinHook(filePath);
|
|
220
|
+
onFileMutationDone(stateBefore, stateAfter);
|
|
219
221
|
},
|
|
220
222
|
};
|
|
221
223
|
},
|
|
@@ -225,12 +227,11 @@ export const spyFilesystemCalls = (
|
|
|
225
227
|
_internalFs,
|
|
226
228
|
"writeFileUtf8",
|
|
227
229
|
(filePath) => {
|
|
228
|
-
const
|
|
229
|
-
const stateBefore = getFileStateWithinHook(fileUrl);
|
|
230
|
+
const stateBefore = getFileStateWithinHook(filePath);
|
|
230
231
|
return {
|
|
231
232
|
return: () => {
|
|
232
|
-
const stateAfter = getFileStateWithinHook(
|
|
233
|
-
|
|
233
|
+
const stateAfter = getFileStateWithinHook(filePath);
|
|
234
|
+
onFileMutationDone(stateBefore, stateAfter);
|
|
234
235
|
},
|
|
235
236
|
};
|
|
236
237
|
},
|
|
@@ -242,12 +243,44 @@ export const spyFilesystemCalls = (
|
|
|
242
243
|
},
|
|
243
244
|
};
|
|
244
245
|
});
|
|
246
|
+
const copyFileHook = hookIntoMethod(
|
|
247
|
+
_internalFs,
|
|
248
|
+
"copyFile",
|
|
249
|
+
(fromPath, toPath) => {
|
|
250
|
+
const stateBefore = getFileStateWithinHook(fromPath);
|
|
251
|
+
return {
|
|
252
|
+
return: () => {
|
|
253
|
+
const stateAfter = getFileStateWithinHook(toPath);
|
|
254
|
+
onFileMutationDone(stateBefore, stateAfter);
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
},
|
|
258
|
+
{ execute: METHOD_EXECUTION_NODE_CALLBACK },
|
|
259
|
+
);
|
|
260
|
+
const renameHook = hookIntoMethod(
|
|
261
|
+
_internalFs,
|
|
262
|
+
"rename",
|
|
263
|
+
(fromPath, toPath) => {
|
|
264
|
+
const stateBefore = getFileStateWithinHook(fromPath);
|
|
265
|
+
return {
|
|
266
|
+
return: () => {
|
|
267
|
+
const stateAfter = getFileStateWithinHook(toPath);
|
|
268
|
+
onFileMutationDone(stateBefore, stateAfter);
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
execute: METHOD_EXECUTION_NODE_CALLBACK,
|
|
274
|
+
},
|
|
275
|
+
);
|
|
245
276
|
restoreCallbackSet.add(() => {
|
|
246
277
|
mkdirHook.remove();
|
|
247
278
|
openHook.remove();
|
|
248
279
|
closeHook.remove();
|
|
249
280
|
writeFileUtf8Hook.remove();
|
|
250
281
|
unlinkHook.remove();
|
|
282
|
+
copyFileHook.remove();
|
|
283
|
+
renameHook.remove();
|
|
251
284
|
});
|
|
252
285
|
return {
|
|
253
286
|
restore: () => {
|
|
@@ -275,11 +308,13 @@ export const spyFilesystemCalls = (
|
|
|
275
308
|
};
|
|
276
309
|
};
|
|
277
310
|
|
|
278
|
-
const getFileState = (
|
|
311
|
+
const getFileState = (filePath) => {
|
|
312
|
+
const fileUrl = pathToFileURL(filePath);
|
|
279
313
|
try {
|
|
280
|
-
const fileBuffer = readFileSync(
|
|
281
|
-
const { mtimeMs } = statSync(
|
|
314
|
+
const fileBuffer = readFileSync(fileUrl);
|
|
315
|
+
const { mtimeMs } = statSync(fileUrl);
|
|
282
316
|
return {
|
|
317
|
+
url: String(fileUrl),
|
|
283
318
|
found: true,
|
|
284
319
|
mtimeMs,
|
|
285
320
|
buffer: fileBuffer,
|
|
@@ -287,6 +322,7 @@ const getFileState = (file) => {
|
|
|
287
322
|
} catch (e) {
|
|
288
323
|
if (e.code === "ENOENT") {
|
|
289
324
|
return {
|
|
325
|
+
url: String(fileUrl),
|
|
290
326
|
found: false,
|
|
291
327
|
};
|
|
292
328
|
}
|