@cronn/lib-file-snapshots 0.7.0 → 0.9.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/dist/index.d.ts CHANGED
@@ -34,17 +34,18 @@ interface JsonSerializerOptions {
34
34
  /**
35
35
  * Custom normalizers to apply before serialization
36
36
  */
37
- normalizers?: JsonNormalizer[];
37
+ normalizers?: Array<JsonNormalizer>;
38
38
  }
39
39
  type JsonNormalizer = (value: unknown, context: JsonNormalizerContext) => unknown;
40
40
  interface JsonNormalizerContext {
41
41
  key?: string;
42
+ index?: number;
42
43
  }
43
44
  declare class JsonSerializer implements SnapshotSerializer {
44
45
  private readonly includeUndefinedObjectProperties;
45
46
  private readonly normalizers;
46
47
  constructor(options?: JsonSerializerOptions);
47
- canSerialize(value: unknown): boolean;
48
+ canSerialize(_value: unknown): boolean;
48
49
  serialize(value: unknown): SnapshotSerializerResult;
49
50
  private normalizeValueRecursive;
50
51
  private normalizeNumber;
@@ -62,7 +63,7 @@ interface TextSerializerOptions {
62
63
  /**
63
64
  * Custom normalizers to apply before serialization
64
65
  */
65
- normalizers?: TextNormalizer[];
66
+ normalizers?: Array<TextNormalizer>;
66
67
  }
67
68
  type TextNormalizer = (value: string) => string;
68
69
  declare class TextSerializer implements SnapshotSerializer {
@@ -99,18 +100,25 @@ interface MatchValidationFileOptions {
99
100
  *
100
101
  * @example ["test A", "when x, then y"]
101
102
  */
102
- titlePath: string[];
103
+ titlePath: Array<string>;
103
104
  /**
104
105
  * Unique name of the file snapshot
105
106
  *
106
107
  * Used to distinguish multiple file snapshots within the same `test`.
107
108
  */
108
109
  name?: string;
110
+ /**
111
+ * The naming strategy to use for storing the file snapshot
112
+ *
113
+ * @default "file"
114
+ */
115
+ namingStrategy?: SnapshotNamingStrategy;
109
116
  /**
110
117
  * The serializer to use for the snapshot
111
118
  */
112
119
  serializer: SnapshotSerializer;
113
120
  }
121
+ type SnapshotNamingStrategy = "file" | "fileSuffix";
114
122
  interface ValidationFileMatcherResult {
115
123
  actual: string;
116
124
  expected: string;
@@ -125,12 +133,13 @@ declare class ValidationFileMatcher {
125
133
  constructor(config?: ValidationFileMatcherConfig);
126
134
  matchFileSnapshot(actual: unknown, options: MatchValidationFileOptions): ValidationFileMatcherResult;
127
135
  private buildValidationFilePath;
136
+ private applyNamingStrategy;
128
137
  private writeFileSnapshots;
129
138
  }
130
139
 
131
140
  declare function isString(value: unknown): value is string;
132
- declare function isArray(value: unknown): value is unknown[];
141
+ declare function isArray(value: unknown): value is Array<unknown>;
133
142
  type PlainObject = Record<PropertyKey, unknown>;
134
143
  declare function isPlainObject(value: unknown): value is PlainObject;
135
144
 
136
- export { type JsonNormalizer, type JsonNormalizerContext, JsonSerializer, type PlainObject, type SnapshotSerializer, type TextNormalizer, TextSerializer, ValidationFileMatcher, isArray, isPlainObject, isString };
145
+ export { type JsonNormalizer, type JsonNormalizerContext, JsonSerializer, type PlainObject, type SnapshotNamingStrategy, type SnapshotSerializer, type TextNormalizer, TextSerializer, ValidationFileMatcher, isArray, isPlainObject, isString };
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ var JsonSerializer = class {
24
24
  this.includeUndefinedObjectProperties = options.includeUndefinedObjectProperties ?? false;
25
25
  this.normalizers = options.normalizers ?? [];
26
26
  }
27
- canSerialize(value) {
27
+ canSerialize(_value) {
28
28
  return true;
29
29
  }
30
30
  serialize(value) {
@@ -100,7 +100,7 @@ var JsonSerializer = class {
100
100
  }
101
101
  normalizeArray(value) {
102
102
  return value.map(
103
- (item, index) => this.normalizeValueRecursive(item, { key: index.toString() })
103
+ (item, index) => this.normalizeValueRecursive(item, { index })
104
104
  );
105
105
  }
106
106
  normalizeObject(value) {
@@ -214,7 +214,7 @@ import * as path from "path";
214
214
  import fs from "fs";
215
215
  var NEW_LINE_SEPARATOR = "\n";
216
216
  function normalizeFileName(testName) {
217
- return testName.replaceAll(/\+0/g, "0").replaceAll(/'([\w ]+)'/g, "$1").replaceAll(/[ .:']/g, "_").replaceAll(/[,$]/g, "");
217
+ return testName.replaceAll(/[+*%~<>?!$#'"`|\\/()[\]{}]/g, "").replaceAll(/[\s.:,;]+/g, "_").replaceAll(/_{2,}/g, "_");
218
218
  }
219
219
  function mkdirRecursive(path2) {
220
220
  fs.mkdirSync(path2, { recursive: true });
@@ -245,7 +245,7 @@ var ValidationFileMatcher = class {
245
245
  this.outputDir = config.outputDir ?? "data/test/output";
246
246
  }
247
247
  matchFileSnapshot(actual, options) {
248
- const { testPath, titlePath, name, serializer } = options;
248
+ const { testPath, titlePath, name, namingStrategy, serializer } = options;
249
249
  if (!serializer.canSerialize(actual)) {
250
250
  throw new Error(`Cannot serialize value of type ${typeof actual}`);
251
251
  }
@@ -254,6 +254,7 @@ var ValidationFileMatcher = class {
254
254
  titlePath,
255
255
  testPath,
256
256
  name,
257
+ namingStrategy,
257
258
  fileExtension: serializerResult.fileExtension
258
259
  });
259
260
  return this.writeFileSnapshots(
@@ -262,13 +263,25 @@ var ValidationFileMatcher = class {
262
263
  );
263
264
  }
264
265
  buildValidationFilePath(options) {
265
- const { testPath, titlePath, name, fileExtension } = options;
266
+ const { testPath, titlePath, name, namingStrategy, fileExtension } = options;
266
267
  const normalizedTitlePath = titlePath.map(normalizeFileName);
267
- const normalizedFileName = name !== void 0 ? `_${normalizeFileName(name)}` : "";
268
- const normalizedTestName = normalizedTitlePath.pop();
269
- const validationFilePath = path.join(testPath, ...normalizedTitlePath);
270
- const validationFileName = `${normalizedTestName}${normalizedFileName}.${fileExtension}`;
271
- return path.join(validationFilePath, validationFileName);
268
+ const filePath = path.join(testPath, ...normalizedTitlePath);
269
+ const fullFilePath = this.applyNamingStrategy(
270
+ filePath,
271
+ name,
272
+ namingStrategy
273
+ );
274
+ return `${fullFilePath}.${fileExtension}`;
275
+ }
276
+ applyNamingStrategy(filePath, snapshotName, namingStrategy) {
277
+ if (snapshotName === void 0) {
278
+ return filePath;
279
+ }
280
+ const normalizedSnapshotName = normalizeFileName(snapshotName);
281
+ if (namingStrategy === "fileSuffix") {
282
+ return `${filePath}_${normalizedSnapshotName}`;
283
+ }
284
+ return path.join(filePath, normalizedSnapshotName);
272
285
  }
273
286
  writeFileSnapshots(actual, validationFilePath) {
274
287
  const validationFileDir = path.dirname(validationFilePath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cronn/lib-file-snapshots",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "The library agnostic core for testing file snapshots",
5
5
  "keywords": [
6
6
  "file snapshots"
@@ -32,21 +32,29 @@
32
32
  "dist"
33
33
  ],
34
34
  "devDependencies": {
35
- "@biomejs/biome": "1.9.4",
35
+ "@trivago/prettier-plugin-sort-imports": "5.2.2",
36
36
  "@types/node": "22.15.30",
37
37
  "@vitest/coverage-istanbul": "3.2.4",
38
+ "eslint": "9.30.1",
39
+ "eslint-config-prettier": "10.1.5",
40
+ "eslint-plugin-unused-imports": "4.1.4",
41
+ "jiti": "2.4.2",
42
+ "prettier": "3.6.2",
38
43
  "tsup": "8.5.0",
39
44
  "typescript": "5.8.3",
45
+ "typescript-eslint": "8.36.0",
40
46
  "vitest": "3.2.4",
41
47
  "@cronn/shared-configs": "0.0.0"
42
48
  },
43
49
  "scripts": {
44
- "check": "biome check .",
45
- "check:fix": "biome check --write .",
50
+ "lint:check": "eslint src/ --max-warnings=0",
51
+ "lint:fix": "eslint src/ --max-warnings=0 --fix",
52
+ "check": "pnpm run compile && pnpm run lint:check",
53
+ "fix": "pnpm run lint:fix",
46
54
  "test": "vitest run",
47
55
  "test:coverage": "vitest run --coverage",
48
56
  "compile": "tsc",
49
57
  "build": "tsup",
50
- "ci": "biome ci . && pnpm run compile && pnpm run test:coverage && pnpm run build"
58
+ "ci": "pnpm run check && pnpm run test:coverage && pnpm run build"
51
59
  }
52
60
  }