@jsenv/snapshot 1.0.1 → 1.1.0
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 +3 -3
- package/src/main.js +79 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/snapshot",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Snapshot testing",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"test": "node --conditions=development ./scripts/test.mjs"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@jsenv/filesystem": "4.5.
|
|
38
|
+
"@jsenv/filesystem": "4.5.1",
|
|
39
39
|
"@jsenv/urls": "2.2.1",
|
|
40
|
-
"@jsenv/utils": "2.0
|
|
40
|
+
"@jsenv/utils": "2.1.0",
|
|
41
41
|
"@jsenv/assert": "2.13.0"
|
|
42
42
|
}
|
|
43
43
|
}
|
package/src/main.js
CHANGED
|
@@ -3,6 +3,11 @@ import {
|
|
|
3
3
|
assertAndNormalizeDirectoryUrl,
|
|
4
4
|
assertAndNormalizeFileUrl,
|
|
5
5
|
comparePathnames,
|
|
6
|
+
ensureEmptyDirectorySync,
|
|
7
|
+
removeFileSync,
|
|
8
|
+
writeFileSync,
|
|
9
|
+
removeDirectorySync,
|
|
10
|
+
writeFileStructureSync,
|
|
6
11
|
} from "@jsenv/filesystem";
|
|
7
12
|
import { urlToFilename, urlToRelativeUrl } from "@jsenv/urls";
|
|
8
13
|
import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js";
|
|
@@ -18,13 +23,54 @@ export const takeDirectorySnapshot = (directoryUrl) => {
|
|
|
18
23
|
directoryUrl = assertAndNormalizeDirectoryUrl(directoryUrl);
|
|
19
24
|
directoryUrl = new URL(directoryUrl);
|
|
20
25
|
|
|
26
|
+
const expectedDirectorySnapshot = createDirectorySnapshot(directoryUrl);
|
|
27
|
+
ensureEmptyDirectorySync(directoryUrl);
|
|
28
|
+
return {
|
|
29
|
+
addFile: (relativeUrl, content) => {
|
|
30
|
+
writeFileSync(new URL(relativeUrl, directoryUrl), content);
|
|
31
|
+
},
|
|
32
|
+
compare: () => {
|
|
33
|
+
const actualDirectorySnapshot = createDirectorySnapshot(directoryUrl);
|
|
34
|
+
compareSnapshots(actualDirectorySnapshot, expectedDirectorySnapshot);
|
|
35
|
+
},
|
|
36
|
+
restore: () => {
|
|
37
|
+
if (expectedDirectorySnapshot.notFound) {
|
|
38
|
+
removeDirectorySync(directoryUrl, {
|
|
39
|
+
recursive: true,
|
|
40
|
+
allowUseless: true,
|
|
41
|
+
});
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (expectedDirectorySnapshot.empty) {
|
|
45
|
+
ensureEmptyDirectorySync(directoryUrl);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const fileStructure = {};
|
|
50
|
+
Object.keys(expectedDirectorySnapshot.fileSnapshots).forEach(
|
|
51
|
+
(relativeUrl) => {
|
|
52
|
+
const fileSnapshot =
|
|
53
|
+
expectedDirectorySnapshot.fileSnapshots[relativeUrl];
|
|
54
|
+
if (!fileSnapshot.empty) {
|
|
55
|
+
fileStructure[relativeUrl] = fileSnapshot.content;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
writeFileStructureSync(
|
|
60
|
+
directoryUrl,
|
|
61
|
+
expectedDirectorySnapshot.fileStructure,
|
|
62
|
+
);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
const createDirectorySnapshot = (directoryUrl) => {
|
|
21
67
|
const directorySnapshot = {
|
|
22
68
|
[snapshotSymbol]: true,
|
|
23
69
|
empty: false,
|
|
24
70
|
type: "directory",
|
|
25
71
|
url: directoryUrl.href,
|
|
26
72
|
notFound: false,
|
|
27
|
-
|
|
73
|
+
fileSnapshots: {},
|
|
28
74
|
};
|
|
29
75
|
|
|
30
76
|
let stat;
|
|
@@ -46,7 +92,7 @@ export const takeDirectorySnapshot = (directoryUrl) => {
|
|
|
46
92
|
}
|
|
47
93
|
}
|
|
48
94
|
|
|
49
|
-
const
|
|
95
|
+
const fileSnapshotsNaturalOrder = {};
|
|
50
96
|
const visitDirectory = (url) => {
|
|
51
97
|
try {
|
|
52
98
|
const directoryContent = readdirSync(url);
|
|
@@ -58,7 +104,7 @@ export const takeDirectorySnapshot = (directoryUrl) => {
|
|
|
58
104
|
return;
|
|
59
105
|
}
|
|
60
106
|
const relativeUrl = urlToRelativeUrl(contentUrl, directoryUrl);
|
|
61
|
-
|
|
107
|
+
fileSnapshotsNaturalOrder[relativeUrl] = createFileSnapshot(contentUrl);
|
|
62
108
|
});
|
|
63
109
|
} catch (e) {
|
|
64
110
|
if (e && e.code === "ENOENT") {
|
|
@@ -69,18 +115,37 @@ export const takeDirectorySnapshot = (directoryUrl) => {
|
|
|
69
115
|
};
|
|
70
116
|
visitDirectory(directoryUrl);
|
|
71
117
|
|
|
72
|
-
const relativeUrls = Object.keys(
|
|
118
|
+
const relativeUrls = Object.keys(fileSnapshotsNaturalOrder);
|
|
73
119
|
relativeUrls.sort(comparePathnames);
|
|
74
120
|
relativeUrls.forEach((relativeUrl) => {
|
|
75
|
-
directorySnapshot.
|
|
76
|
-
|
|
121
|
+
directorySnapshot.fileSnapshots[relativeUrl] =
|
|
122
|
+
fileSnapshotsNaturalOrder[relativeUrl];
|
|
77
123
|
});
|
|
78
124
|
return directorySnapshot;
|
|
79
125
|
};
|
|
80
126
|
|
|
81
127
|
export const takeFileSnapshot = (fileUrl) => {
|
|
82
128
|
fileUrl = assertAndNormalizeFileUrl(fileUrl);
|
|
83
|
-
|
|
129
|
+
const expectedFileSnapshot = createFileSnapshot(fileUrl);
|
|
130
|
+
removeFileSync(fileUrl);
|
|
131
|
+
return {
|
|
132
|
+
writeContent: (content) => {
|
|
133
|
+
writeFileSync(fileUrl, content);
|
|
134
|
+
},
|
|
135
|
+
compare: () => {
|
|
136
|
+
const actualFileSnapshot = createFileSnapshot(fileUrl);
|
|
137
|
+
compareSnapshots(actualFileSnapshot, expectedFileSnapshot);
|
|
138
|
+
},
|
|
139
|
+
restore: () => {
|
|
140
|
+
if (expectedFileSnapshot.empty) {
|
|
141
|
+
removeFileSync(fileUrl, { allowUseless: true });
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
writeFileSync(fileUrl, expectedFileSnapshot.content);
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
const createFileSnapshot = (fileUrl) => {
|
|
84
149
|
const fileSnapshot = {
|
|
85
150
|
[snapshotSymbol]: true,
|
|
86
151
|
empty: false,
|
|
@@ -124,7 +189,7 @@ export const takeFileSnapshot = (fileUrl) => {
|
|
|
124
189
|
return fileSnapshot;
|
|
125
190
|
};
|
|
126
191
|
|
|
127
|
-
|
|
192
|
+
const compareSnapshots = (currentSnapshot, previousSnapshot) => {
|
|
128
193
|
if (!currentSnapshot || !currentSnapshot[snapshotSymbol]) {
|
|
129
194
|
throw new TypeError(
|
|
130
195
|
`1st argument must be a snapshot, received ${currentSnapshot}`,
|
|
@@ -163,10 +228,10 @@ export const compareSnapshots = (currentSnapshot, previousSnapshot) => {
|
|
|
163
228
|
const snapshotComparers = {
|
|
164
229
|
directory: (currentDirectorySnapshot, previousDirectorySnapshot) => {
|
|
165
230
|
const failureMessage = `comparison with previous directory snapshot failed`;
|
|
166
|
-
const
|
|
167
|
-
const
|
|
168
|
-
const currentRelativeUrls = Object.keys(
|
|
169
|
-
const previousRelativeUrls = Object.keys(
|
|
231
|
+
const currentFileSnapshots = currentDirectorySnapshot.fileSnapshots;
|
|
232
|
+
const previousFileSnapshots = previousDirectorySnapshot.fileSnapshots;
|
|
233
|
+
const currentRelativeUrls = Object.keys(currentFileSnapshots);
|
|
234
|
+
const previousRelativeUrls = Object.keys(previousFileSnapshots);
|
|
170
235
|
|
|
171
236
|
// missing_files
|
|
172
237
|
{
|
|
@@ -225,8 +290,8 @@ ${extraUrls.join("\n")}`);
|
|
|
225
290
|
// file contents
|
|
226
291
|
{
|
|
227
292
|
for (const relativeUrl of currentRelativeUrls) {
|
|
228
|
-
const currentFileSnapshot =
|
|
229
|
-
const previousFileSnapshot =
|
|
293
|
+
const currentFileSnapshot = currentFileSnapshots[relativeUrl];
|
|
294
|
+
const previousFileSnapshot = previousFileSnapshots[relativeUrl];
|
|
230
295
|
compareSnapshots(currentFileSnapshot, previousFileSnapshot);
|
|
231
296
|
}
|
|
232
297
|
}
|