@cronn/lib-file-snapshots 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/dist/index.d.mts +52 -11
- package/dist/index.mjs +54 -10
- package/package.json +14 -11
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
|
+
//#region src/models/table.d.ts
|
|
2
|
+
interface TableData<TRow extends TableRow = TableRow> {
|
|
3
|
+
columns: Array<string>;
|
|
4
|
+
rows: Array<TRow>;
|
|
5
|
+
}
|
|
6
|
+
type TableRow = Array<TableCell>;
|
|
7
|
+
type TableCell = string | number | boolean | null | undefined;
|
|
8
|
+
type TableRowRecord = Record<string, TableCell>;
|
|
9
|
+
declare class Table<TRow extends TableRow = TableRow> implements TableData<TRow> {
|
|
10
|
+
readonly columns: Array<string>;
|
|
11
|
+
readonly rows: Array<TRow>;
|
|
12
|
+
private constructor();
|
|
13
|
+
/**
|
|
14
|
+
* Defines a table
|
|
15
|
+
*/
|
|
16
|
+
static define<TRow extends TableRow>(data: TableData<TRow>): Table<TRow>;
|
|
17
|
+
/**
|
|
18
|
+
* Defines a table from record-based rows
|
|
19
|
+
*
|
|
20
|
+
* Columns are derived from keys, rows from values.
|
|
21
|
+
*/
|
|
22
|
+
static fromRecords<TRow extends TableRowRecord>(rows: Array<TRow>): Table;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
1
25
|
//#region src/types/serializer.d.ts
|
|
2
|
-
interface SnapshotSerializer {
|
|
26
|
+
interface SnapshotSerializer<TValue> {
|
|
3
27
|
/**
|
|
4
28
|
* The file extension associated with the serialized value
|
|
5
29
|
*/
|
|
@@ -11,7 +35,7 @@ interface SnapshotSerializer {
|
|
|
11
35
|
* @return {string} The serialized value
|
|
12
36
|
* @throws {Error} Will throw an error if value cannot be serialized.
|
|
13
37
|
*/
|
|
14
|
-
serialize(value:
|
|
38
|
+
serialize(value: TValue): string;
|
|
15
39
|
}
|
|
16
40
|
//#endregion
|
|
17
41
|
//#region src/serializers/json-serializer.d.ts
|
|
@@ -38,7 +62,7 @@ interface JsonNormalizerContext {
|
|
|
38
62
|
key?: string;
|
|
39
63
|
index?: number;
|
|
40
64
|
}
|
|
41
|
-
declare class JsonSerializer implements SnapshotSerializer {
|
|
65
|
+
declare class JsonSerializer implements SnapshotSerializer<unknown> {
|
|
42
66
|
readonly fileExtension = "json";
|
|
43
67
|
private readonly includeUndefinedObjectProperties;
|
|
44
68
|
private readonly normalizers;
|
|
@@ -57,6 +81,23 @@ declare class JsonSerializer implements SnapshotSerializer {
|
|
|
57
81
|
private applyCustomNormalizers;
|
|
58
82
|
}
|
|
59
83
|
//#endregion
|
|
84
|
+
//#region src/serializers/markdown-table-serializer.d.ts
|
|
85
|
+
interface MarkdownTableSerializerOptions {
|
|
86
|
+
/**
|
|
87
|
+
* Custom normalizers to apply before serialization
|
|
88
|
+
*/
|
|
89
|
+
normalizers?: Array<MarkdownTableNormalizer>;
|
|
90
|
+
}
|
|
91
|
+
type MarkdownTableNormalizer = (value: TableCell) => TableCell;
|
|
92
|
+
declare class MarkdownTableSerializer implements SnapshotSerializer<TableData> {
|
|
93
|
+
readonly fileExtension = "md";
|
|
94
|
+
private readonly normalizers;
|
|
95
|
+
constructor(options?: MarkdownTableSerializerOptions);
|
|
96
|
+
serialize(value: TableData): string;
|
|
97
|
+
private serializeCellValue;
|
|
98
|
+
private mapCellValueToString;
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
60
101
|
//#region src/serializers/text-serializer.d.ts
|
|
61
102
|
interface TextSerializerOptions {
|
|
62
103
|
/**
|
|
@@ -71,16 +112,16 @@ interface TextSerializerOptions {
|
|
|
71
112
|
fileExtension?: string;
|
|
72
113
|
}
|
|
73
114
|
type TextNormalizer = (value: string) => string;
|
|
74
|
-
declare class TextSerializer implements SnapshotSerializer {
|
|
115
|
+
declare class TextSerializer implements SnapshotSerializer<string> {
|
|
75
116
|
readonly fileExtension: string;
|
|
76
117
|
private readonly normalizers;
|
|
77
118
|
constructor(options?: TextSerializerOptions);
|
|
78
|
-
serialize(value:
|
|
119
|
+
serialize(value: string): string;
|
|
79
120
|
private normalizeValue;
|
|
80
121
|
}
|
|
81
122
|
//#endregion
|
|
82
123
|
//#region src/types/matcher.d.ts
|
|
83
|
-
interface ValidationFileMatcherConfig {
|
|
124
|
+
interface ValidationFileMatcherConfig<TValue> {
|
|
84
125
|
/**
|
|
85
126
|
* Directory in which golden masters are stored
|
|
86
127
|
*/
|
|
@@ -98,7 +139,7 @@ interface ValidationFileMatcherConfig {
|
|
|
98
139
|
/**
|
|
99
140
|
* The serializer to use for the snapshot
|
|
100
141
|
*/
|
|
101
|
-
serializer: SnapshotSerializer
|
|
142
|
+
serializer: SnapshotSerializer<TValue>;
|
|
102
143
|
/**
|
|
103
144
|
* Whether to update golden masters with the actual result.
|
|
104
145
|
*
|
|
@@ -123,15 +164,15 @@ interface FilePathResolverParams {
|
|
|
123
164
|
}
|
|
124
165
|
//#endregion
|
|
125
166
|
//#region src/matcher/validation-file-matcher.d.ts
|
|
126
|
-
declare class ValidationFileMatcher {
|
|
167
|
+
declare class ValidationFileMatcher<TValue> {
|
|
127
168
|
private readonly updateSnapshots;
|
|
128
169
|
private readonly serializer;
|
|
129
170
|
private readonly filePaths;
|
|
130
171
|
private validationFile;
|
|
131
|
-
constructor(config: ValidationFileMatcherConfig);
|
|
172
|
+
constructor(config: ValidationFileMatcherConfig<TValue>);
|
|
132
173
|
get isValidationFileMissing(): boolean;
|
|
133
174
|
get isUpdate(): boolean;
|
|
134
|
-
matchFileSnapshot(actual:
|
|
175
|
+
matchFileSnapshot(actual: TValue): ValidationFileMatcherResult;
|
|
135
176
|
private buildFilePaths;
|
|
136
177
|
private readValidationFile;
|
|
137
178
|
private createMatcherResult;
|
|
@@ -152,4 +193,4 @@ declare function isArray(value: unknown): value is Array<unknown>;
|
|
|
152
193
|
type PlainObject = Record<PropertyKey, unknown>;
|
|
153
194
|
declare function isPlainObject(value: unknown): value is PlainObject;
|
|
154
195
|
//#endregion
|
|
155
|
-
export { type FilePathResolver, type FilePathResolverParams, type JsonNormalizer, type JsonNormalizerContext, JsonSerializer, type PlainObject, type SnapshotSerializer, type TextNormalizer, TextSerializer, type UpdateSnapshotsType, ValidationFileMatcher, type ValidationFileMatcherResult, isArray, isPlainObject, isString, normalizeFileName, resolveNameAsFile, resolveNameAsFileSuffix };
|
|
196
|
+
export { type FilePathResolver, type FilePathResolverParams, type JsonNormalizer, type JsonNormalizerContext, JsonSerializer, type MarkdownTableNormalizer, MarkdownTableSerializer, type PlainObject, type SnapshotSerializer, Table, type TableCell, type TableData, type TableRow, type TextNormalizer, TextSerializer, type UpdateSnapshotsType, ValidationFileMatcher, type ValidationFileMatcherResult, isArray, isPlainObject, isString, normalizeFileName, resolveNameAsFile, resolveNameAsFileSuffix };
|
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,35 @@ import fs from "node:fs";
|
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
|
|
6
|
+
import { markdownTable } from "markdown-table";
|
|
7
|
+
//#region src/models/table.ts
|
|
8
|
+
var Table = class Table {
|
|
9
|
+
columns;
|
|
10
|
+
rows;
|
|
11
|
+
constructor(data) {
|
|
12
|
+
this.columns = data.columns;
|
|
13
|
+
this.rows = data.rows;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Defines a table
|
|
17
|
+
*/
|
|
18
|
+
static define(data) {
|
|
19
|
+
return new Table(data);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Defines a table from record-based rows
|
|
23
|
+
*
|
|
24
|
+
* Columns are derived from keys, rows from values.
|
|
25
|
+
*/
|
|
26
|
+
static fromRecords(rows) {
|
|
27
|
+
const [firstRow] = rows;
|
|
28
|
+
return new Table({
|
|
29
|
+
columns: firstRow !== void 0 ? Object.keys(firstRow) : [],
|
|
30
|
+
rows: rows.map((row) => Object.values(row))
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
//#endregion
|
|
7
35
|
//#region src/utils/file.ts
|
|
8
36
|
const NEW_LINE_SEPARATOR = "\n";
|
|
9
37
|
const EMOJI_REGEXP = /(?!(\*|#|\d))[\p{Extended_Pictographic}\p{Emoji_Component}]|[\u0030-\u0039]\ufe0f?[\u20e3]|[\u002A\u0023]?\ufe0f?[\u20e3]/gu;
|
|
@@ -28,7 +56,6 @@ function addTrailingNewLine(data) {
|
|
|
28
56
|
function addMissingFileMarker(data) {
|
|
29
57
|
return `===== missing file =====${NEW_LINE_SEPARATOR}${data}`;
|
|
30
58
|
}
|
|
31
|
-
|
|
32
59
|
//#endregion
|
|
33
60
|
//#region src/utils/guards.ts
|
|
34
61
|
function isString(value) {
|
|
@@ -45,13 +72,11 @@ function isPlainObject(value) {
|
|
|
45
72
|
const proto = Object.getPrototypeOf(value);
|
|
46
73
|
return proto === null || proto === Object.prototype;
|
|
47
74
|
}
|
|
48
|
-
|
|
49
75
|
//#endregion
|
|
50
76
|
//#region src/utils/validators.ts
|
|
51
77
|
function isPositiveInteger(value) {
|
|
52
78
|
return Number.isInteger(value) && value > 0;
|
|
53
79
|
}
|
|
54
|
-
|
|
55
80
|
//#endregion
|
|
56
81
|
//#region src/serializers/json-serializer.ts
|
|
57
82
|
var JsonSerializer = class {
|
|
@@ -142,7 +167,30 @@ var JsonSerializer = class {
|
|
|
142
167
|
return normalizedValue;
|
|
143
168
|
}
|
|
144
169
|
};
|
|
145
|
-
|
|
170
|
+
//#endregion
|
|
171
|
+
//#region src/serializers/markdown-table-serializer.ts
|
|
172
|
+
var MarkdownTableSerializer = class {
|
|
173
|
+
fileExtension = "md";
|
|
174
|
+
normalizers;
|
|
175
|
+
constructor(options = {}) {
|
|
176
|
+
this.normalizers = options.normalizers ?? [];
|
|
177
|
+
}
|
|
178
|
+
serialize(value) {
|
|
179
|
+
const { columns, rows } = value;
|
|
180
|
+
if (columns.length === 0) throw new Error("Markdown table must have at least one column.");
|
|
181
|
+
return addTrailingNewLine(markdownTable([columns, ...rows.map((row) => row.map((cellValue) => this.serializeCellValue(cellValue)))]));
|
|
182
|
+
}
|
|
183
|
+
serializeCellValue(value) {
|
|
184
|
+
let normalizedValue = value;
|
|
185
|
+
for (const normalizer of this.normalizers) normalizedValue = normalizer(normalizedValue);
|
|
186
|
+
return this.mapCellValueToString(normalizedValue);
|
|
187
|
+
}
|
|
188
|
+
mapCellValueToString(value) {
|
|
189
|
+
if (value === void 0) return "undefined";
|
|
190
|
+
if (value === null) return "null";
|
|
191
|
+
return value.toString().trim();
|
|
192
|
+
}
|
|
193
|
+
};
|
|
146
194
|
//#endregion
|
|
147
195
|
//#region src/serializers/text-serializer.ts
|
|
148
196
|
var TextSerializer = class {
|
|
@@ -153,7 +201,6 @@ var TextSerializer = class {
|
|
|
153
201
|
this.fileExtension = options.fileExtension ?? "txt";
|
|
154
202
|
}
|
|
155
203
|
serialize(value) {
|
|
156
|
-
if (!isString(value)) throw new Error(`Value of type ${typeof value} cannot be serialized as text. Only strings are supported.`);
|
|
157
204
|
return addTrailingNewLine(this.normalizeValue(value));
|
|
158
205
|
}
|
|
159
206
|
normalizeValue(value) {
|
|
@@ -162,7 +209,6 @@ var TextSerializer = class {
|
|
|
162
209
|
return normalizedValue.trim();
|
|
163
210
|
}
|
|
164
211
|
};
|
|
165
|
-
|
|
166
212
|
//#endregion
|
|
167
213
|
//#region src/matcher/validation-file-matcher.ts
|
|
168
214
|
var ValidationFileMatcher = class {
|
|
@@ -231,7 +277,6 @@ var ValidationFileMatcher = class {
|
|
|
231
277
|
return this.validationFile;
|
|
232
278
|
}
|
|
233
279
|
};
|
|
234
|
-
|
|
235
280
|
//#endregion
|
|
236
281
|
//#region src/matcher/file-path-resolver.ts
|
|
237
282
|
function resolveNameAsFile(params) {
|
|
@@ -254,6 +299,5 @@ function resolveFilePath(params, resolveNamedFilePath) {
|
|
|
254
299
|
normalizedName: normalizeFileName(name)
|
|
255
300
|
});
|
|
256
301
|
}
|
|
257
|
-
|
|
258
302
|
//#endregion
|
|
259
|
-
export { JsonSerializer, TextSerializer, ValidationFileMatcher, isArray, isPlainObject, isString, normalizeFileName, resolveNameAsFile, resolveNameAsFileSuffix };
|
|
303
|
+
export { JsonSerializer, MarkdownTableSerializer, Table, TextSerializer, ValidationFileMatcher, isArray, isPlainObject, isString, normalizeFileName, resolveNameAsFile, resolveNameAsFileSuffix };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cronn/lib-file-snapshots",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "The library agnostic core for testing file snapshots",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"file snapshots"
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
"devEngines": {
|
|
23
23
|
"runtime": {
|
|
24
24
|
"name": "node",
|
|
25
|
-
"version": ">=24.
|
|
25
|
+
"version": ">=24.14.1 <25",
|
|
26
26
|
"onFail": "error"
|
|
27
27
|
},
|
|
28
28
|
"packageManager": {
|
|
29
29
|
"name": "pnpm",
|
|
30
|
-
"version": ">=10.
|
|
30
|
+
"version": ">=10.33.0 <11",
|
|
31
31
|
"onFail": "error"
|
|
32
32
|
}
|
|
33
33
|
},
|
|
@@ -45,18 +45,20 @@
|
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@arethetypeswrong/core": "0.18.2",
|
|
47
47
|
"@trivago/prettier-plugin-sort-imports": "6.0.2",
|
|
48
|
-
"@types/node": "24.
|
|
49
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
50
|
-
"@vitest/coverage-v8": "4.
|
|
51
|
-
"eslint": "10.0
|
|
48
|
+
"@types/node": "24.12.2",
|
|
49
|
+
"@typescript/native-preview": "7.0.0-dev.20260406.1",
|
|
50
|
+
"@vitest/coverage-v8": "4.1.4",
|
|
51
|
+
"eslint": "10.2.0",
|
|
52
52
|
"eslint-config-prettier": "10.1.8",
|
|
53
53
|
"eslint-plugin-check-file": "3.3.1",
|
|
54
54
|
"eslint-plugin-unused-imports": "4.4.1",
|
|
55
|
+
"markdown-table": "3.0.4",
|
|
55
56
|
"prettier": "3.8.1",
|
|
56
57
|
"publint": "0.3.18",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
58
|
+
"rimraf": "6.1.3",
|
|
59
|
+
"tsdown": "0.21.7",
|
|
60
|
+
"typescript-eslint": "8.58.0",
|
|
61
|
+
"vitest": "4.1.4",
|
|
60
62
|
"@cronn/shared-configs": "0.0.0"
|
|
61
63
|
},
|
|
62
64
|
"scripts": {
|
|
@@ -65,6 +67,7 @@
|
|
|
65
67
|
"test": "vitest run",
|
|
66
68
|
"test:coverage": "vitest run --coverage",
|
|
67
69
|
"compile": "tsgo",
|
|
68
|
-
"build": "tsdown"
|
|
70
|
+
"build": "tsdown",
|
|
71
|
+
"clean": "rimraf .turbo dist coverage"
|
|
69
72
|
}
|
|
70
73
|
}
|