@jsenv/snapshot 1.5.7 → 2.0.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/snapshot",
3
- "version": "1.5.7",
3
+ "version": "2.0.0",
4
4
  "description": "Snapshot testing",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -39,9 +39,7 @@
39
39
  "@jsenv/urls": "2.2.11",
40
40
  "@jsenv/utils": "2.1.1",
41
41
  "pixelmatch": "6.0.0",
42
- "prettier": "3.3.3"
43
- },
44
- "devDependencies": {
42
+ "prettier": "3.3.3",
45
43
  "strip-ansi": "7.1.0"
46
44
  }
47
45
  }
@@ -1,4 +1,5 @@
1
1
  import { readdirSync, statSync, readFileSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
2
3
  import { URL_META } from "@jsenv/url-meta";
3
4
  import {
4
5
  assertAndNormalizeDirectoryUrl,
@@ -19,18 +20,32 @@ import {
19
20
  ExtraFileAssertionError,
20
21
  FileContentAssertionError,
21
22
  } from "./errors.js";
23
+ import { replaceFluctuatingValues } from "./replace_fluctuating_values.js";
22
24
  import { comparePngFiles } from "./compare_png_files.js";
23
25
 
24
26
  export const takeFileSnapshot = (fileUrl) => {
25
27
  fileUrl = assertAndNormalizeFileUrl(fileUrl);
26
28
  const fileSnapshot = createFileSnapshot(fileUrl);
27
29
  removeFileSync(fileUrl, { allowUseless: true });
30
+ const compare = (throwWhenDiff = process.env.CI) => {
31
+ fileSnapshot.compare(createFileSnapshot(fileUrl), { throwWhenDiff });
32
+ };
28
33
  return {
29
- compare: (throwWhenDiff = process.env.CI) => {
30
- fileSnapshot.compare(createFileSnapshot(fileUrl), { throwWhenDiff });
31
- },
32
- writeContent: (content) => {
34
+ compare,
35
+ update: (
36
+ content,
37
+ { mockFluctuatingValues = true, rootDirectoryUrl, throwWhenDiff } = {},
38
+ ) => {
39
+ if (mockFluctuatingValues) {
40
+ content = replaceFluctuatingValues(content, {
41
+ cwdPath: rootDirectoryUrl
42
+ ? fileURLToPath(rootDirectoryUrl)
43
+ : undefined,
44
+ cwdUrl: rootDirectoryUrl ? String(rootDirectoryUrl) : undefined,
45
+ });
46
+ }
33
47
  writeFileSync(fileUrl, content);
48
+ compare(throwWhenDiff);
34
49
  },
35
50
  restore: () => {
36
51
  if (fileSnapshot.empty) {
package/src/main.js CHANGED
@@ -1 +1,5 @@
1
- export { takeDirectorySnapshot, takeFileSnapshot } from "./file_snapshots.js";
1
+ export {
2
+ takeDirectorySnapshot,
3
+ takeFileSnapshot,
4
+ } from "./filesystem_snapshot.js";
5
+ export { replaceFluctuatingValues } from "./replace_fluctuating_values.js";
@@ -0,0 +1,59 @@
1
+ // - Find all things looking like urls and replace with stable values
2
+ // - Find all things looking likes dates and replace with stable values
3
+
4
+ import stripAnsi from "strip-ansi";
5
+ import { pathToFileURL, fileURLToPath } from "node:url";
6
+ import { escapeRegexpSpecialChars } from "@jsenv/utils/src/string/escape_regexp_special_chars.js";
7
+
8
+ export const replaceFluctuatingValues = (
9
+ string,
10
+ {
11
+ removeAnsi = true,
12
+ rootDirectoryUrl = pathToFileURL(process.cwd()),
13
+ // for unit tests
14
+ rootDirectoryPath = fileURLToPath(rootDirectoryUrl),
15
+ isWindows = process.platform === "win32",
16
+ } = {},
17
+ ) => {
18
+ if (removeAnsi) {
19
+ string = stripAnsi(string);
20
+ }
21
+ rootDirectoryUrl = String(rootDirectoryUrl);
22
+ if (rootDirectoryUrl[rootDirectoryUrl.length - 1] === "/") {
23
+ rootDirectoryUrl = rootDirectoryUrl.slice(0, -1);
24
+ }
25
+ string = string.replaceAll(rootDirectoryUrl, "file:///cwd()");
26
+ if (isWindows) {
27
+ const windowPathRegex = new RegExp(
28
+ `${escapeRegexpSpecialChars(rootDirectoryPath)}(((?:\\\\(?:[\\w !#()-]+|[.]{1,2})+)*)(?:\\\\)?)`,
29
+ "gm",
30
+ );
31
+ string = string.replaceAll(windowPathRegex, (match, afterCwd) => {
32
+ return `cwd()${afterCwd.replaceAll("\\", "/")}`;
33
+ });
34
+ } else {
35
+ string = string.replaceAll(rootDirectoryPath, "cwd()");
36
+ }
37
+ string = replaceHttpUrls(string);
38
+ return string;
39
+ };
40
+
41
+ const replaceHttpUrls = (source) => {
42
+ return source.replace(/(?:https?|ftp):\/\/\S+/g, (match) => {
43
+ const lastChar = match[match.length - 1];
44
+ // hotfix because our url regex sucks a bit
45
+ const endsWithSeparationChar = lastChar === ")" || lastChar === ":";
46
+ if (endsWithSeparationChar) {
47
+ match = match.slice(0, -1);
48
+ }
49
+ try {
50
+ const urlObject = new URL(match);
51
+ if (urlObject.port) {
52
+ urlObject.port = 9999;
53
+ }
54
+ return urlObject.href;
55
+ } catch (e) {
56
+ return match;
57
+ }
58
+ });
59
+ };