@jsenv/snapshot 2.10.3 → 2.11.1
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.
|
|
3
|
+
"version": "2.11.1",
|
|
4
4
|
"description": "Snapshot testing",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -29,16 +29,13 @@
|
|
|
29
29
|
"files": [
|
|
30
30
|
"/src/"
|
|
31
31
|
],
|
|
32
|
-
"scripts": {
|
|
33
|
-
"test": "node --conditions=development ./scripts/test.mjs"
|
|
34
|
-
},
|
|
35
32
|
"dependencies": {
|
|
36
33
|
"@jsenv/assert": "4.4.1",
|
|
37
34
|
"@jsenv/ast": "6.2.17",
|
|
38
|
-
"@jsenv/exception": "1.1.
|
|
35
|
+
"@jsenv/exception": "1.1.3",
|
|
39
36
|
"@jsenv/humanize": "1.2.8",
|
|
40
|
-
"@jsenv/filesystem": "4.10.
|
|
41
|
-
"@jsenv/terminal-recorder": "1.4.
|
|
37
|
+
"@jsenv/filesystem": "4.10.3",
|
|
38
|
+
"@jsenv/terminal-recorder": "1.4.8",
|
|
42
39
|
"@jsenv/urls": "2.5.2",
|
|
43
40
|
"@jsenv/utils": "2.1.2",
|
|
44
41
|
"ansi-regex": "6.0.1",
|
|
@@ -4,12 +4,17 @@ import { createReplaceFilesystemWellKnownValues } from "../filesystem_well_known
|
|
|
4
4
|
import { filesystemSideEffects } from "./filesystem/filesystem_side_effects.js";
|
|
5
5
|
import { logSideEffects } from "./log/log_side_effects.js";
|
|
6
6
|
|
|
7
|
+
const executionEffectsDefault = {
|
|
8
|
+
catch: true,
|
|
9
|
+
return: true,
|
|
10
|
+
};
|
|
11
|
+
|
|
7
12
|
export const createCaptureSideEffects = ({
|
|
8
13
|
sourceFileUrl,
|
|
9
14
|
logEffects = true,
|
|
10
15
|
filesystemEffects = true,
|
|
11
16
|
filesystemActions,
|
|
12
|
-
executionEffects =
|
|
17
|
+
executionEffects = executionEffectsDefault,
|
|
13
18
|
rootDirectoryUrl,
|
|
14
19
|
replaceFilesystemWellKnownValues = createReplaceFilesystemWellKnownValues({
|
|
15
20
|
rootDirectoryUrl,
|
|
@@ -21,6 +26,7 @@ export const createCaptureSideEffects = ({
|
|
|
21
26
|
return: false,
|
|
22
27
|
};
|
|
23
28
|
}
|
|
29
|
+
executionEffects = { ...executionEffectsDefault, ...executionEffects };
|
|
24
30
|
|
|
25
31
|
const detectors = [];
|
|
26
32
|
if (logEffects) {
|
|
@@ -49,6 +49,25 @@ export const spyFilesystemCalls = (
|
|
|
49
49
|
const fileDescriptorPathMap = new Map();
|
|
50
50
|
const fileRestoreMap = new Map();
|
|
51
51
|
const dirRestoreMap = new Map();
|
|
52
|
+
|
|
53
|
+
const onWriteFileDone = (stateBefore, stateAfter) =>
|
|
54
|
+
onFileMutationDone(stateBefore, stateAfter);
|
|
55
|
+
const onCopyFileDone = (stateBefore, stateAfter) =>
|
|
56
|
+
onFileMutationDone(stateBefore, stateAfter);
|
|
57
|
+
const onMoveFileDone = (fromStateBefore, toStateBefore, toStateAfter) => {
|
|
58
|
+
if (!toStateAfter.found) {
|
|
59
|
+
// seems to be possible somehow
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
// effect on source file
|
|
63
|
+
registerUndoAndNotify(fromStateBefore, () => {
|
|
64
|
+
onRemoveFile(fromStateBefore.url, fromStateBefore.buffer, "move");
|
|
65
|
+
});
|
|
66
|
+
// effect on target file
|
|
67
|
+
registerUndoAndNotify(toStateBefore, () => {
|
|
68
|
+
onWriteFile(toStateBefore.url, fromStateBefore.buffer, "created");
|
|
69
|
+
});
|
|
70
|
+
};
|
|
52
71
|
const onFileMutationDone = (stateBefore, stateAfter) => {
|
|
53
72
|
if (!stateAfter.found) {
|
|
54
73
|
// seems to be possible somehow
|
|
@@ -58,45 +77,61 @@ export const spyFilesystemCalls = (
|
|
|
58
77
|
// - writing file for the 1st time
|
|
59
78
|
// - updating file content
|
|
60
79
|
// the important part is the file content in the end of the function execution
|
|
61
|
-
|
|
62
|
-
if (!
|
|
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 {
|
|
71
|
-
// file is exactly the same
|
|
72
|
-
// function did not have any effect on the file
|
|
80
|
+
const reason = getMutationReason(stateBefore, stateAfter);
|
|
81
|
+
if (!reason) {
|
|
73
82
|
return;
|
|
74
83
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
84
|
+
registerUndoAndNotify(stateBefore, () => {
|
|
85
|
+
onWriteFile(stateAfter.url, stateAfter.buffer, reason);
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
const getMutationReason = (stateBefore, stateAfter) => {
|
|
89
|
+
if (!stateBefore.found && stateAfter.found) {
|
|
90
|
+
return "created";
|
|
91
|
+
}
|
|
92
|
+
if (Buffer.compare(stateBefore.buffer, stateAfter.buffer)) {
|
|
93
|
+
return "content_modified";
|
|
94
|
+
}
|
|
95
|
+
if (stateBefore.mtimeMs !== stateAfter.mtimeMs) {
|
|
96
|
+
return "mtime_modified";
|
|
97
|
+
}
|
|
98
|
+
// file is exactly the same
|
|
99
|
+
// function did not have any effect on the file
|
|
100
|
+
return null;
|
|
101
|
+
};
|
|
102
|
+
const registerUndoAndNotify = (stateBefore, notify) => {
|
|
103
|
+
const url = stateBefore.url;
|
|
104
|
+
const action = getAction(url);
|
|
78
105
|
const shouldCompare =
|
|
79
106
|
action === "compare" ||
|
|
80
107
|
action === "compare_presence_only" ||
|
|
81
108
|
action === true;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
109
|
+
// "ignore", false, anything else
|
|
110
|
+
undo: {
|
|
111
|
+
if (!undoFilesystemSideEffects) {
|
|
112
|
+
break undo;
|
|
113
|
+
}
|
|
114
|
+
if (action !== "undo" && !shouldCompare) {
|
|
115
|
+
break undo;
|
|
116
|
+
}
|
|
117
|
+
if (fileRestoreMap.has(url)) {
|
|
118
|
+
break undo;
|
|
119
|
+
}
|
|
120
|
+
if (stateBefore.found) {
|
|
121
|
+
fileRestoreMap.set(url, () => {
|
|
122
|
+
writeFileSync(url, stateBefore.buffer);
|
|
123
|
+
});
|
|
124
|
+
} else {
|
|
125
|
+
fileRestoreMap.set(url, () => {
|
|
126
|
+
removeFileSync(url, { allowUseless: true });
|
|
127
|
+
});
|
|
93
128
|
}
|
|
94
129
|
}
|
|
95
130
|
if (shouldCompare) {
|
|
96
|
-
|
|
131
|
+
notify();
|
|
97
132
|
}
|
|
98
|
-
// "ignore", false, anything else
|
|
99
133
|
};
|
|
134
|
+
|
|
100
135
|
const onWriteDirectoryDone = (directoryUrl) => {
|
|
101
136
|
const action = getAction(directoryUrl);
|
|
102
137
|
const shouldCompare =
|
|
@@ -217,7 +252,7 @@ export const spyFilesystemCalls = (
|
|
|
217
252
|
fileDescriptorPathMap.delete(fileDescriptor);
|
|
218
253
|
filesystemStateInfoMap.delete(filePath);
|
|
219
254
|
const stateAfter = getFileStateWithinHook(filePath);
|
|
220
|
-
|
|
255
|
+
onWriteFileDone(stateBefore, stateAfter);
|
|
221
256
|
},
|
|
222
257
|
};
|
|
223
258
|
},
|
|
@@ -231,7 +266,7 @@ export const spyFilesystemCalls = (
|
|
|
231
266
|
return {
|
|
232
267
|
return: () => {
|
|
233
268
|
const stateAfter = getFileStateWithinHook(filePath);
|
|
234
|
-
|
|
269
|
+
onWriteFileDone(stateBefore, stateAfter);
|
|
235
270
|
},
|
|
236
271
|
};
|
|
237
272
|
},
|
|
@@ -247,11 +282,11 @@ export const spyFilesystemCalls = (
|
|
|
247
282
|
_internalFs,
|
|
248
283
|
"copyFile",
|
|
249
284
|
(fromPath, toPath) => {
|
|
250
|
-
const
|
|
285
|
+
const toStateBefore = getFileStateWithinHook(toPath);
|
|
251
286
|
return {
|
|
252
287
|
return: () => {
|
|
253
|
-
const
|
|
254
|
-
|
|
288
|
+
const toStateAfter = getFileStateWithinHook(toPath);
|
|
289
|
+
onCopyFileDone(toStateBefore, toStateAfter);
|
|
255
290
|
},
|
|
256
291
|
};
|
|
257
292
|
},
|
|
@@ -261,11 +296,12 @@ export const spyFilesystemCalls = (
|
|
|
261
296
|
_internalFs,
|
|
262
297
|
"rename",
|
|
263
298
|
(fromPath, toPath) => {
|
|
264
|
-
const
|
|
299
|
+
const fromStateBefore = getFileStateWithinHook(fromPath);
|
|
300
|
+
const toStateBefore = getFileStateWithinHook(toPath);
|
|
265
301
|
return {
|
|
266
302
|
return: () => {
|
|
267
|
-
const
|
|
268
|
-
|
|
303
|
+
const toStateAfter = getFileStateWithinHook(toPath);
|
|
304
|
+
onMoveFileDone(fromStateBefore, toStateBefore, toStateAfter);
|
|
269
305
|
},
|
|
270
306
|
};
|
|
271
307
|
},
|
|
@@ -12,6 +12,11 @@ import { renderSideEffects, renderSmallLink } from "./render_side_effects.js";
|
|
|
12
12
|
* @param {Object} snapshotTestsOptions
|
|
13
13
|
* @param {string|url} snapshotTestsOptions.outFilePattern
|
|
14
14
|
* @param {string|url} snapshotTestsOptions.rootDirectoryUrl
|
|
15
|
+
* @param {Object} [snapshotTestsOptions.executionEffects]
|
|
16
|
+
* @param {boolean} [snapshotTestsOptions.executionEffects.catch=true]
|
|
17
|
+
* Any error thrown by test function is detected and added to side effects
|
|
18
|
+
* @param {boolean} [snapshotTestsOptions.executionEffects.return=true]
|
|
19
|
+
* Test function return value is added to side effects
|
|
15
20
|
* @param {Object} [snapshotTestsOptions.filesystemActions]
|
|
16
21
|
* Control what to do when there is a file side effect
|
|
17
22
|
* "compare", "compare_presence_only", "undo", "ignore"
|