@jsenv/snapshot 2.8.8 → 2.8.10
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 +4 -4
- package/src/replace_fluctuating_values.js +12 -5
- package/src/side_effects/log/log_side_effects.js +65 -3
- package/src/side_effects/render_logs_gif.js +2 -1
- package/src/side_effects/render_side_effects.js +40 -24
- package/src/side_effects/snapshot_side_effects.js +4 -2
- package/src/side_effects/snapshot_tests.js +106 -87
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/snapshot",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.10",
|
|
4
4
|
"description": "Snapshot testing",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
"test": "node --conditions=development ./scripts/test.mjs"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@jsenv/assert": "4.
|
|
37
|
-
"@jsenv/ast": "6.2.
|
|
38
|
-
"@jsenv/exception": "1.0
|
|
36
|
+
"@jsenv/assert": "4.2.0",
|
|
37
|
+
"@jsenv/ast": "6.2.16",
|
|
38
|
+
"@jsenv/exception": "1.1.0",
|
|
39
39
|
"@jsenv/filesystem": "4.10.0",
|
|
40
40
|
"@jsenv/terminal-recorder": "1.4.4",
|
|
41
41
|
"@jsenv/urls": "2.5.2",
|
|
@@ -38,8 +38,8 @@ export const replaceFluctuatingValues = (
|
|
|
38
38
|
const extension = urlToExtension(fileUrl);
|
|
39
39
|
if (extension === ".html") {
|
|
40
40
|
stringType = "html";
|
|
41
|
-
} else if (extension === ".svg") {
|
|
42
|
-
stringType = "
|
|
41
|
+
} else if (extension === ".svg" || extension === ".xml") {
|
|
42
|
+
stringType = "xml";
|
|
43
43
|
} else if (extension === ".json" || CONTENT_TYPE.isJson(contentType)) {
|
|
44
44
|
stringType = "json";
|
|
45
45
|
}
|
|
@@ -92,10 +92,10 @@ export const replaceFluctuatingValues = (
|
|
|
92
92
|
const replaced = replaceInObject(jsValue, { replace: replaceThings });
|
|
93
93
|
return JSON.stringify(replaced, null, " ");
|
|
94
94
|
}
|
|
95
|
-
if (stringType === "html" || stringType === "
|
|
95
|
+
if (stringType === "html" || stringType === "xml") {
|
|
96
96
|
// do parse html
|
|
97
97
|
const htmlAst =
|
|
98
|
-
stringType === "
|
|
98
|
+
stringType === "xml"
|
|
99
99
|
? parseSvgString(value)
|
|
100
100
|
: parseHtml({
|
|
101
101
|
html: value,
|
|
@@ -112,7 +112,14 @@ export const replaceFluctuatingValues = (
|
|
|
112
112
|
const attributes = getHtmlNodeAttributes(node);
|
|
113
113
|
if (attributes) {
|
|
114
114
|
for (const name of Object.keys(attributes)) {
|
|
115
|
-
|
|
115
|
+
const attributeValue = attributes[name];
|
|
116
|
+
if (name === "timestamp") {
|
|
117
|
+
attributes[name] = "[timestamp]";
|
|
118
|
+
} else if (name === "time") {
|
|
119
|
+
attributes[name] = "[time]";
|
|
120
|
+
} else {
|
|
121
|
+
attributes[name] = replaceThings(attributeValue);
|
|
122
|
+
}
|
|
116
123
|
}
|
|
117
124
|
setHtmlNodeAttributes(node, attributes);
|
|
118
125
|
}
|
|
@@ -5,7 +5,31 @@ import { groupLogSideEffects } from "./group_log_side_effects.js";
|
|
|
5
5
|
const logSideEffectsOptionsDefault = {
|
|
6
6
|
prevent: true,
|
|
7
7
|
group: true,
|
|
8
|
-
|
|
8
|
+
level: "info", // "debug", "trace", "info", "warn", "error", "off"
|
|
9
|
+
onlyIfLevel: "debug",
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const isLogSideEffect = (sideEffect) => {
|
|
13
|
+
const { type } = sideEffect;
|
|
14
|
+
return typeof typeToLevelMap[type] === "number";
|
|
15
|
+
};
|
|
16
|
+
const typeToLevelMap = {
|
|
17
|
+
"console.debug": 0,
|
|
18
|
+
"console.trace": 1,
|
|
19
|
+
"console.info": 2,
|
|
20
|
+
"console.log": 2,
|
|
21
|
+
"process.stdout": 2,
|
|
22
|
+
"console.warn": 3,
|
|
23
|
+
"console.error": 4,
|
|
24
|
+
"process.stderr": 4,
|
|
25
|
+
};
|
|
26
|
+
const levelNumberMap = {
|
|
27
|
+
debug: 0,
|
|
28
|
+
trace: 1,
|
|
29
|
+
info: 2,
|
|
30
|
+
warn: 3,
|
|
31
|
+
error: 4,
|
|
32
|
+
off: 5,
|
|
9
33
|
};
|
|
10
34
|
|
|
11
35
|
export const logSideEffects = (logSideEffectsOptions) => {
|
|
@@ -16,7 +40,30 @@ export const logSideEffects = (logSideEffectsOptions) => {
|
|
|
16
40
|
return {
|
|
17
41
|
name: "console",
|
|
18
42
|
install: (addSideEffect, { addFinallyCallback }) => {
|
|
19
|
-
const { prevent, group,
|
|
43
|
+
const { level, prevent, group, onlyIfLevel } = logSideEffectsOptions;
|
|
44
|
+
const levelNumber = levelNumberMap[level];
|
|
45
|
+
if (onlyIfLevel && onlyIfLevel !== "debug") {
|
|
46
|
+
const onlyIfLevelNumber = levelNumberMap[onlyIfLevel];
|
|
47
|
+
addFinallyCallback((sideEffects) => {
|
|
48
|
+
const logSideEffects = [];
|
|
49
|
+
let hasOneOfLevelOrAbove;
|
|
50
|
+
for (const sideEffect of sideEffects) {
|
|
51
|
+
if (!isLogSideEffect(sideEffect)) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
logSideEffects.push(sideEffect);
|
|
55
|
+
if (!hasOneOfLevelOrAbove) {
|
|
56
|
+
const sideEffectLevel = typeToLevelMap[sideEffect.type];
|
|
57
|
+
hasOneOfLevelOrAbove = sideEffectLevel >= onlyIfLevelNumber;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (!hasOneOfLevelOrAbove) {
|
|
61
|
+
for (const logSideEffect of logSideEffects) {
|
|
62
|
+
sideEffects.removeSideEffect(logSideEffect);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
20
67
|
if (group) {
|
|
21
68
|
addFinallyCallback((sideEffects) => {
|
|
22
69
|
groupLogSideEffects(sideEffects, {
|
|
@@ -60,8 +107,23 @@ export const logSideEffects = (logSideEffectsOptions) => {
|
|
|
60
107
|
});
|
|
61
108
|
});
|
|
62
109
|
}
|
|
110
|
+
|
|
63
111
|
const addLogSideEffect = (type, message) => {
|
|
64
|
-
|
|
112
|
+
const sideEffectLevel = typeToLevelMap[type];
|
|
113
|
+
if (sideEffectLevel < levelNumber) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
message = String(message);
|
|
117
|
+
// some messages are flaky by definition we don't want to
|
|
118
|
+
// fail on thoose
|
|
119
|
+
if (
|
|
120
|
+
message.includes(
|
|
121
|
+
"GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels",
|
|
122
|
+
)
|
|
123
|
+
) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (message.includes("task queue exceeded allotted deadline by")) {
|
|
65
127
|
return;
|
|
66
128
|
}
|
|
67
129
|
addSideEffect({
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { writeFileSync } from "@jsenv/filesystem";
|
|
2
2
|
import { startTerminalRecording } from "@jsenv/terminal-recorder";
|
|
3
|
+
import { isLogSideEffect } from "./log/log_side_effects.js";
|
|
3
4
|
|
|
4
5
|
export const renderLogsGif = async (sideEffects, gitFileUrl) => {
|
|
5
6
|
const terminalRecorder = await startTerminalRecording({
|
|
6
7
|
gif: true,
|
|
7
8
|
});
|
|
8
9
|
for (const sideEffect of sideEffects) {
|
|
9
|
-
if (sideEffect
|
|
10
|
+
if (isLogSideEffect(sideEffect)) {
|
|
10
11
|
await terminalRecorder.write(sideEffect.value, {
|
|
11
12
|
delay: sideEffect.delay,
|
|
12
13
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createException } from "@jsenv/exception";
|
|
1
|
+
import { createException, stringifyException } from "@jsenv/exception";
|
|
2
2
|
import { writeFileSync } from "@jsenv/filesystem";
|
|
3
3
|
import { renderTerminalSvg } from "@jsenv/terminal-recorder";
|
|
4
4
|
import { urlToExtension, urlToRelativeUrl } from "@jsenv/urls";
|
|
@@ -37,9 +37,11 @@ export const createBigSizeEffect =
|
|
|
37
37
|
export const renderSideEffects = (
|
|
38
38
|
sideEffects,
|
|
39
39
|
{
|
|
40
|
+
sourceFileUrl,
|
|
40
41
|
sideEffectMdFileUrl,
|
|
41
42
|
generateOutFileUrl,
|
|
42
43
|
generatedBy = true,
|
|
44
|
+
title,
|
|
43
45
|
titleLevel = 1,
|
|
44
46
|
getBigSizeEffect = createBigSizeEffect({
|
|
45
47
|
details: { line: 15, length: 2000 },
|
|
@@ -48,8 +50,7 @@ export const renderSideEffects = (
|
|
|
48
50
|
// and in that case we might want to move it to an other file
|
|
49
51
|
dedicatedFile: { line: 50, length: 5000 },
|
|
50
52
|
}),
|
|
51
|
-
|
|
52
|
-
errorMessageTransform,
|
|
53
|
+
errorTransform,
|
|
53
54
|
} = {},
|
|
54
55
|
) => {
|
|
55
56
|
const { rootDirectoryUrl, replaceFilesystemWellKnownValues } =
|
|
@@ -64,6 +65,8 @@ export const renderSideEffects = (
|
|
|
64
65
|
};
|
|
65
66
|
|
|
66
67
|
let markdown = "";
|
|
68
|
+
markdown += `# [${title}](${urlToRelativeUrl(sourceFileUrl, sideEffectMdFileUrl, { preferRelativeNotation: true })})`;
|
|
69
|
+
markdown += "\n\n";
|
|
67
70
|
let sideEffectNumber = 0;
|
|
68
71
|
for (const sideEffect of sideEffects) {
|
|
69
72
|
if (sideEffect.skippable) {
|
|
@@ -77,41 +80,59 @@ export const renderSideEffects = (
|
|
|
77
80
|
}
|
|
78
81
|
const lastSideEffectNumber = sideEffectNumber;
|
|
79
82
|
|
|
83
|
+
let sideEffectMd = "";
|
|
80
84
|
for (const sideEffect of sideEffects) {
|
|
81
85
|
if (sideEffect.skippable) {
|
|
82
86
|
continue;
|
|
83
87
|
}
|
|
84
|
-
if (
|
|
85
|
-
|
|
88
|
+
if (sideEffectMd) {
|
|
89
|
+
sideEffectMd += "\n\n";
|
|
86
90
|
}
|
|
87
|
-
|
|
91
|
+
sideEffectMd += renderOneSideEffect(sideEffect, {
|
|
88
92
|
sideEffectMdFileUrl,
|
|
89
93
|
generateOutFileUrl,
|
|
90
94
|
rootDirectoryUrl,
|
|
91
95
|
titleLevel,
|
|
92
96
|
getBigSizeEffect,
|
|
93
97
|
replace,
|
|
94
|
-
|
|
95
|
-
errorMessageTransform,
|
|
98
|
+
errorTransform,
|
|
96
99
|
lastSideEffectNumber,
|
|
97
100
|
});
|
|
98
101
|
}
|
|
102
|
+
markdown += sideEffectMd;
|
|
99
103
|
if (generatedBy) {
|
|
100
|
-
|
|
104
|
+
markdown += "\n";
|
|
105
|
+
markdown += "---";
|
|
106
|
+
markdown += "\n\n";
|
|
107
|
+
markdown += renderSmallLink(
|
|
101
108
|
{
|
|
102
109
|
text: "@jsenv/snapshot",
|
|
103
110
|
href: "https://github.com/jsenv/core/tree/main/packages/independent/snapshot",
|
|
104
111
|
},
|
|
105
|
-
{
|
|
106
|
-
prefix: "Generated by ",
|
|
107
|
-
},
|
|
112
|
+
{ prefix: "Generated by " },
|
|
108
113
|
);
|
|
109
|
-
markdown += "\n\n";
|
|
110
|
-
markdown += generatedByLink;
|
|
111
114
|
}
|
|
112
115
|
return markdown;
|
|
113
116
|
};
|
|
114
117
|
|
|
118
|
+
export const renderInfosTableMd = (infos) => {
|
|
119
|
+
const infoKeys = Object.keys(infos);
|
|
120
|
+
if (infoKeys.length === 0) {
|
|
121
|
+
return "";
|
|
122
|
+
}
|
|
123
|
+
let infoTableMd = "";
|
|
124
|
+
infoTableMd += "\n";
|
|
125
|
+
infoTableMd += `Infos | `;
|
|
126
|
+
infoTableMd += "\n";
|
|
127
|
+
infoTableMd += `----- | ------`;
|
|
128
|
+
for (const key of infoKeys) {
|
|
129
|
+
infoTableMd += "\n";
|
|
130
|
+
infoTableMd += `${key} | ${infos[key]}`;
|
|
131
|
+
}
|
|
132
|
+
infoTableMd += "\n";
|
|
133
|
+
return infoTableMd;
|
|
134
|
+
};
|
|
135
|
+
|
|
115
136
|
export const renderSmallLink = (
|
|
116
137
|
link,
|
|
117
138
|
{ prefix = "", suffix = "", indent } = {},
|
|
@@ -139,8 +160,7 @@ const renderOneSideEffect = (
|
|
|
139
160
|
titleLevel,
|
|
140
161
|
getBigSizeEffect,
|
|
141
162
|
replace,
|
|
142
|
-
|
|
143
|
-
errorMessageTransform,
|
|
163
|
+
errorTransform,
|
|
144
164
|
lastSideEffectNumber,
|
|
145
165
|
},
|
|
146
166
|
) => {
|
|
@@ -175,8 +195,7 @@ const renderOneSideEffect = (
|
|
|
175
195
|
generateOutFileUrl,
|
|
176
196
|
replace,
|
|
177
197
|
rootDirectoryUrl,
|
|
178
|
-
|
|
179
|
-
errorMessageTransform,
|
|
198
|
+
errorTransform,
|
|
180
199
|
});
|
|
181
200
|
}
|
|
182
201
|
if (sideEffect.code === "source_code") {
|
|
@@ -212,8 +231,7 @@ const renderText = (
|
|
|
212
231
|
generateOutFileUrl,
|
|
213
232
|
replace,
|
|
214
233
|
rootDirectoryUrl,
|
|
215
|
-
|
|
216
|
-
errorMessageTransform,
|
|
234
|
+
errorTransform,
|
|
217
235
|
},
|
|
218
236
|
) => {
|
|
219
237
|
if (text && typeof text === "object") {
|
|
@@ -253,11 +271,9 @@ const renderText = (
|
|
|
253
271
|
// return renderMarkdownBlock(text.value.stack);
|
|
254
272
|
const exception = createException(jsValue, {
|
|
255
273
|
rootDirectoryUrl,
|
|
256
|
-
|
|
274
|
+
errorTransform,
|
|
257
275
|
});
|
|
258
|
-
const exceptionText =
|
|
259
|
-
? `${exception.name}: ${exception.message}`
|
|
260
|
-
: exception.stack || exception.message || exception;
|
|
276
|
+
const exceptionText = stringifyException(exception);
|
|
261
277
|
return renderPotentialAnsi(exceptionText, {
|
|
262
278
|
stringType: "error",
|
|
263
279
|
sideEffect,
|
|
@@ -32,7 +32,7 @@ export const snapshotSideEffects = (
|
|
|
32
32
|
{
|
|
33
33
|
sideEffectMdFileUrl,
|
|
34
34
|
outFilePattern = "_[source_filename]/[filename]",
|
|
35
|
-
|
|
35
|
+
errorTransform,
|
|
36
36
|
throwWhenDiff,
|
|
37
37
|
...captureOptions
|
|
38
38
|
} = {},
|
|
@@ -60,9 +60,11 @@ export const snapshotSideEffects = (
|
|
|
60
60
|
const outDirectorySnapshot = takeDirectorySnapshot(outDirectoryUrl);
|
|
61
61
|
const onSideEffects = (sideEffects) => {
|
|
62
62
|
const sideEffectFileContent = renderSideEffects(sideEffects, {
|
|
63
|
+
sourceFileUrl,
|
|
64
|
+
title: urlToFilename(sourceFileUrl),
|
|
63
65
|
sideEffectMdFileUrl,
|
|
64
66
|
generateOutFileUrl,
|
|
65
|
-
|
|
67
|
+
errorTransform,
|
|
66
68
|
});
|
|
67
69
|
writeFileSync(sideEffectMdFileUrl, sideEffectFileContent);
|
|
68
70
|
outDirectorySnapshot.compare(throwWhenDiff);
|
|
@@ -37,10 +37,7 @@ export const snapshotTests = async (
|
|
|
37
37
|
},
|
|
38
38
|
rootDirectoryUrl,
|
|
39
39
|
generatedBy = true,
|
|
40
|
-
|
|
41
|
-
linkToEachSource,
|
|
42
|
-
errorStackHidden,
|
|
43
|
-
errorMessageTransform,
|
|
40
|
+
errorTransform,
|
|
44
41
|
logEffects,
|
|
45
42
|
filesystemEffects,
|
|
46
43
|
throwWhenDiff = process.env.CI,
|
|
@@ -48,7 +45,7 @@ export const snapshotTests = async (
|
|
|
48
45
|
) => {
|
|
49
46
|
filesystemActions = {
|
|
50
47
|
...filesystemActions,
|
|
51
|
-
"**/*.svg": "
|
|
48
|
+
"**/*.svg": "compare_presence_only",
|
|
52
49
|
};
|
|
53
50
|
|
|
54
51
|
const sourceName = urlToBasename(sourceFileUrl, true);
|
|
@@ -68,42 +65,32 @@ export const snapshotTests = async (
|
|
|
68
65
|
|
|
69
66
|
const dirUrlMap = new Map();
|
|
70
67
|
const sideEffectsMap = new Map();
|
|
71
|
-
const
|
|
72
|
-
|
|
68
|
+
const testArray = [];
|
|
69
|
+
let index = 0;
|
|
70
|
+
let hasOnly = false;
|
|
73
71
|
const test = (scenario, fn, options) => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
testArray.push({
|
|
73
|
+
index,
|
|
74
|
+
scenario,
|
|
75
|
+
fn,
|
|
76
|
+
options,
|
|
77
|
+
callSite: getCallerLocation(2),
|
|
78
|
+
});
|
|
79
|
+
index++;
|
|
78
80
|
};
|
|
79
81
|
test.ONLY = (scenario, fn, options) => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
hasOnly = true;
|
|
83
|
+
testArray.push({
|
|
84
|
+
index,
|
|
85
|
+
scenario,
|
|
86
|
+
fn,
|
|
87
|
+
options,
|
|
88
|
+
callSite: getCallerLocation(2),
|
|
89
|
+
only: true,
|
|
90
|
+
});
|
|
91
|
+
index++;
|
|
84
92
|
};
|
|
85
93
|
const fnReturnValue = await fnRegisteringTest({ test });
|
|
86
|
-
|
|
87
|
-
let activeTestMap;
|
|
88
|
-
const toIgnoreActions = {};
|
|
89
|
-
if (onlyTestMap.size) {
|
|
90
|
-
activeTestMap = onlyTestMap;
|
|
91
|
-
for (const [scenario] of testMap) {
|
|
92
|
-
const testScenario = asValidFilename(scenario);
|
|
93
|
-
const generateScenarioOutFileUrl = (outfilename) => {
|
|
94
|
-
return generateOutFileUrl(`${testScenario}/${outfilename}`);
|
|
95
|
-
};
|
|
96
|
-
const scenarioOutDirectoryUrl = generateScenarioOutFileUrl("");
|
|
97
|
-
toIgnoreActions[scenarioOutDirectoryUrl] = "ignore";
|
|
98
|
-
}
|
|
99
|
-
} else {
|
|
100
|
-
activeTestMap = testMap;
|
|
101
|
-
}
|
|
102
|
-
// ignore tout ceux aui sont désactivé
|
|
103
|
-
const outDirectorySnapshot = takeDirectorySnapshot(outDirectoryUrl, {
|
|
104
|
-
...filesystemActions,
|
|
105
|
-
...toIgnoreActions,
|
|
106
|
-
});
|
|
107
94
|
const captureSideEffects = createCaptureSideEffects({
|
|
108
95
|
sourceFileUrl,
|
|
109
96
|
rootDirectoryUrl,
|
|
@@ -111,51 +98,79 @@ export const snapshotTests = async (
|
|
|
111
98
|
filesystemEffects,
|
|
112
99
|
filesystemActions,
|
|
113
100
|
});
|
|
101
|
+
const sourceRelativeUrl = urlToRelativeUrl(
|
|
102
|
+
sourceFileUrl,
|
|
103
|
+
sideEffectMdFileUrl,
|
|
104
|
+
{
|
|
105
|
+
preferRelativeNotation: true,
|
|
106
|
+
},
|
|
107
|
+
);
|
|
114
108
|
let markdown = "";
|
|
115
|
-
markdown += `# ${
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
suffix:
|
|
125
|
-
linkToSource && sourceFileUrl
|
|
126
|
-
? generateExecutingLink(sourceFileUrl, sideEffectMdFileUrl)
|
|
127
|
-
: "",
|
|
128
|
-
},
|
|
109
|
+
markdown += `# [${urlToFilename(sourceFileUrl)}](${sourceRelativeUrl})`;
|
|
110
|
+
markdown += `\n\n`;
|
|
111
|
+
let testMd = "";
|
|
112
|
+
testMd += `\n\n`;
|
|
113
|
+
let outDirectorySnapshot;
|
|
114
|
+
if (testArray.length === 0) {
|
|
115
|
+
outDirectorySnapshot = takeDirectorySnapshot(
|
|
116
|
+
outDirectoryUrl,
|
|
117
|
+
filesystemActions,
|
|
129
118
|
);
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
119
|
+
testMd += "No test";
|
|
120
|
+
testMd += "\n";
|
|
121
|
+
} else {
|
|
122
|
+
let allTestMd = "";
|
|
123
|
+
const scenarioDirs = [];
|
|
124
|
+
const scenarioIgnoreActions = {};
|
|
125
|
+
const testToExecuteArray = [];
|
|
126
|
+
for (const testRegistered of testArray) {
|
|
127
|
+
const { scenario, only } = testRegistered;
|
|
128
|
+
const scenarioFilename = asValidFilename(scenario);
|
|
129
|
+
scenarioDirs.push(scenarioFilename);
|
|
130
|
+
const generateScenarioOutFileUrl = (outFilename) => {
|
|
131
|
+
return generateOutFileUrl(`${scenarioFilename}/${outFilename}`);
|
|
132
|
+
};
|
|
133
|
+
const scenarioOutDirectoryUrl = generateScenarioOutFileUrl("");
|
|
134
|
+
dirUrlMap.set(scenario, scenarioOutDirectoryUrl);
|
|
135
|
+
const scenarioMdFileUrl = generateScenarioOutFileUrl(
|
|
136
|
+
`${scenarioFilename}.md`,
|
|
137
|
+
);
|
|
138
|
+
allTestMd += `- [${scenario}](${urlToRelativeUrl(scenarioMdFileUrl, sideEffectMdFileUrl)})`;
|
|
139
|
+
allTestMd += "\n";
|
|
140
|
+
if (hasOnly && !only) {
|
|
141
|
+
scenarioIgnoreActions[scenarioOutDirectoryUrl] = "ignore";
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
testRegistered.generateScenarioOutFileUrl = generateScenarioOutFileUrl;
|
|
145
|
+
testRegistered.scenarioMdFileUrl = scenarioMdFileUrl;
|
|
146
|
+
testToExecuteArray.push(testRegistered);
|
|
147
|
+
}
|
|
148
|
+
outDirectorySnapshot = takeDirectorySnapshot(outDirectoryUrl, {
|
|
149
|
+
...filesystemActions,
|
|
150
|
+
...scenarioIgnoreActions,
|
|
157
151
|
});
|
|
158
|
-
|
|
152
|
+
for (const testToExecute of testToExecuteArray) {
|
|
153
|
+
const {
|
|
154
|
+
scenario,
|
|
155
|
+
fn,
|
|
156
|
+
callSite,
|
|
157
|
+
scenarioMdFileUrl,
|
|
158
|
+
generateScenarioOutFileUrl,
|
|
159
|
+
} = testToExecute;
|
|
160
|
+
const sideEffects = await captureSideEffects(fn, {
|
|
161
|
+
baseDirectory: String(new URL("./", callSite.url)),
|
|
162
|
+
});
|
|
163
|
+
sideEffectsMap.set(scenario, sideEffects);
|
|
164
|
+
const sideEffectsMarkdown = renderSideEffects(sideEffects, {
|
|
165
|
+
sourceFileUrl: `${callSite.url}#L${callSite.line}`,
|
|
166
|
+
sideEffectMdFileUrl: scenarioMdFileUrl,
|
|
167
|
+
generateOutFileUrl: generateScenarioOutFileUrl,
|
|
168
|
+
title: scenario,
|
|
169
|
+
errorTransform,
|
|
170
|
+
});
|
|
171
|
+
writeFileSync(scenarioMdFileUrl, sideEffectsMarkdown);
|
|
172
|
+
}
|
|
173
|
+
testMd += allTestMd;
|
|
159
174
|
}
|
|
160
175
|
if (typeof fnReturnValue === "function") {
|
|
161
176
|
await fnReturnValue();
|
|
@@ -176,21 +191,25 @@ export const snapshotTests = async (
|
|
|
176
191
|
// });
|
|
177
192
|
// }
|
|
178
193
|
// }
|
|
194
|
+
markdown += testMd;
|
|
195
|
+
if (generatedBy) {
|
|
196
|
+
markdown += "\n";
|
|
197
|
+
markdown += "---";
|
|
198
|
+
markdown += "\n\n";
|
|
199
|
+
markdown += renderSmallLink(
|
|
200
|
+
{
|
|
201
|
+
text: "@jsenv/snapshot",
|
|
202
|
+
href: "https://github.com/jsenv/core/tree/main/packages/independent/snapshot",
|
|
203
|
+
},
|
|
204
|
+
{ prefix: "Generated by " },
|
|
205
|
+
);
|
|
206
|
+
}
|
|
179
207
|
writeFileSync(sideEffectMdFileUrl, markdown);
|
|
180
208
|
outDirectorySnapshot.compare(throwWhenDiff);
|
|
181
209
|
|
|
182
210
|
return { dirUrlMap, sideEffectsMap };
|
|
183
211
|
};
|
|
184
212
|
|
|
185
|
-
const generateExecutingLink = (sourceFileUrl, sideEffectFileUrl) => {
|
|
186
|
-
const relativeUrl = urlToRelativeUrl(sourceFileUrl, sideEffectFileUrl, {
|
|
187
|
-
preferRelativeNotation: true,
|
|
188
|
-
});
|
|
189
|
-
const href = `${relativeUrl}`;
|
|
190
|
-
const text = `${relativeUrl}`;
|
|
191
|
-
return ` executing <a href="${href}">${text}</a>`;
|
|
192
|
-
};
|
|
193
|
-
|
|
194
213
|
// see https://github.com/parshap/node-sanitize-filename/blob/master/index.js
|
|
195
214
|
const asValidFilename = (string) => {
|
|
196
215
|
return string
|