@ls-stack/utils 3.23.0 → 3.24.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/docs/testUtils.md +27 -3
- package/docs/yamlStringify.md +53 -15
- package/lib/chunk-JAPKLFIK.js +353 -0
- package/lib/testUtils.cjs +538 -0
- package/lib/testUtils.d.cts +16 -1
- package/lib/testUtils.d.ts +16 -1
- package/lib/testUtils.js +172 -1
- package/lib/yamlStringify.cjs +83 -30
- package/lib/yamlStringify.d.cts +5 -3
- package/lib/yamlStringify.d.ts +5 -3
- package/lib/yamlStringify.js +4 -291
- package/package.json +1 -1
package/lib/testUtils.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/testUtils.ts
|
|
21
21
|
var testUtils_exports = {};
|
|
22
22
|
__export(testUtils_exports, {
|
|
23
|
+
compactSnapshot: () => compactSnapshot,
|
|
23
24
|
createLoggerStore: () => createLoggerStore,
|
|
24
25
|
getResultFn: () => getResultFn,
|
|
25
26
|
waitController: () => waitController
|
|
@@ -30,6 +31,17 @@ module.exports = __toCommonJS(testUtils_exports);
|
|
|
30
31
|
function isObject(value) {
|
|
31
32
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32
33
|
}
|
|
34
|
+
function isPlainObject(value) {
|
|
35
|
+
if (!value || typeof value !== "object") return false;
|
|
36
|
+
const proto = Object.getPrototypeOf(value);
|
|
37
|
+
if (proto === null) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
const Ctor = Object.hasOwnProperty.call(proto, "constructor") && proto.constructor;
|
|
41
|
+
if (Ctor === Object) return true;
|
|
42
|
+
const objectCtorString = Object.prototype.constructor.toString();
|
|
43
|
+
return typeof Ctor == "function" && Function.toString.call(Ctor) === objectCtorString;
|
|
44
|
+
}
|
|
33
45
|
|
|
34
46
|
// src/assertions.ts
|
|
35
47
|
var isObject2 = isObject;
|
|
@@ -153,6 +165,368 @@ function defer() {
|
|
|
153
165
|
return { resolve, reject, promise };
|
|
154
166
|
}
|
|
155
167
|
|
|
168
|
+
// src/conversions.ts
|
|
169
|
+
function bytesToHumanReadable(bytes) {
|
|
170
|
+
if (bytes < 1024) {
|
|
171
|
+
return `${bytes} B`;
|
|
172
|
+
}
|
|
173
|
+
const kb = bytes / 1024;
|
|
174
|
+
if (kb < 1024) {
|
|
175
|
+
return `${kb.toFixed(2)} KB`;
|
|
176
|
+
}
|
|
177
|
+
const mb = kb / 1024;
|
|
178
|
+
if (mb < 1024) {
|
|
179
|
+
return `${mb.toFixed(2)} MB`;
|
|
180
|
+
}
|
|
181
|
+
const gb = mb / 1024;
|
|
182
|
+
return `${gb.toFixed(2)} GB`;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// src/stringUtils.ts
|
|
186
|
+
function truncateString(str, length, ellipsis = "\u2026") {
|
|
187
|
+
if (str.length <= length) return str;
|
|
188
|
+
return str.slice(0, length - 1) + ellipsis;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// src/yamlStringify.ts
|
|
192
|
+
function yamlStringify(obj, {
|
|
193
|
+
maxLineLength = 100,
|
|
194
|
+
showUndefined,
|
|
195
|
+
maxDepth = 50,
|
|
196
|
+
collapseObjects = false,
|
|
197
|
+
addRootObjSpaces = "beforeAndAfter"
|
|
198
|
+
} = {}) {
|
|
199
|
+
if (isObject(obj) || Array.isArray(obj) || typeof obj === "function") {
|
|
200
|
+
return `${stringifyValue(obj, "", maxLineLength, !!showUndefined, maxDepth, 0, collapseObjects, addRootObjSpaces)}
|
|
201
|
+
`;
|
|
202
|
+
}
|
|
203
|
+
return JSON.stringify(obj) || "undefined";
|
|
204
|
+
}
|
|
205
|
+
function stringifyValue(value, indent, maxLineLength, showUndefined, maxDepth, depth, collapseObjects, addObjSpaces) {
|
|
206
|
+
let result = "";
|
|
207
|
+
const childIndent = `${indent} `;
|
|
208
|
+
if (isPlainObject(value)) {
|
|
209
|
+
if (Object.keys(value).length === 0) {
|
|
210
|
+
return "{}";
|
|
211
|
+
}
|
|
212
|
+
if (collapseObjects && depth > 0) {
|
|
213
|
+
const entries = Object.entries(value).filter(
|
|
214
|
+
([, val]) => val !== void 0 || showUndefined
|
|
215
|
+
);
|
|
216
|
+
const isSimpleObject = entries.every(
|
|
217
|
+
([, val]) => {
|
|
218
|
+
if (typeof val === "string") {
|
|
219
|
+
return !val.includes("'") && !val.includes('"') && !val.includes("\\");
|
|
220
|
+
}
|
|
221
|
+
return typeof val === "number" || typeof val === "boolean" || val === null || val === void 0;
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
if (isSimpleObject && entries.length > 0) {
|
|
225
|
+
let line = "{ ";
|
|
226
|
+
line += entries.map(([key, val]) => {
|
|
227
|
+
let valueStr;
|
|
228
|
+
if (typeof val === "string") {
|
|
229
|
+
if (val.includes("'") && !val.includes('"')) {
|
|
230
|
+
valueStr = `"${val}"`;
|
|
231
|
+
} else if (val.includes('"') && !val.includes("'")) {
|
|
232
|
+
valueStr = `'${val}'`;
|
|
233
|
+
} else if (val.includes("'") && val.includes('"')) {
|
|
234
|
+
valueStr = `"${val.replace(/"/g, '\\"')}"`;
|
|
235
|
+
} else {
|
|
236
|
+
valueStr = `'${val}'`;
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
valueStr = String(val);
|
|
240
|
+
}
|
|
241
|
+
return `${key}: ${valueStr}`;
|
|
242
|
+
}).join(", ");
|
|
243
|
+
line += " }";
|
|
244
|
+
if (line.length <= maxLineLength) {
|
|
245
|
+
return line;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
let prevValue;
|
|
250
|
+
let afterSpaceWasAdded = false;
|
|
251
|
+
for (let [key, objVal] of Object.entries(value)) {
|
|
252
|
+
if (objVal === void 0 && !showUndefined) {
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
if (depth > maxDepth) {
|
|
256
|
+
objVal = `{max depth reached}`;
|
|
257
|
+
}
|
|
258
|
+
const normalizedValue2 = normalizeValue(objVal);
|
|
259
|
+
if (normalizedValue2 !== null) {
|
|
260
|
+
objVal = normalizedValue2[1];
|
|
261
|
+
key = `${key}{${normalizedValue2[0]}}`;
|
|
262
|
+
}
|
|
263
|
+
const valueString = stringifyValue(
|
|
264
|
+
objVal,
|
|
265
|
+
childIndent,
|
|
266
|
+
maxLineLength,
|
|
267
|
+
showUndefined,
|
|
268
|
+
maxDepth,
|
|
269
|
+
depth + 1,
|
|
270
|
+
collapseObjects,
|
|
271
|
+
addObjSpaces
|
|
272
|
+
);
|
|
273
|
+
const willBeCollapsed = isObject(objVal) && (Object.keys(objVal).length === 0 || collapseObjects && depth + 1 > 0 && Object.entries(objVal).filter(([, val]) => val !== void 0 || showUndefined).every(([, val]) => {
|
|
274
|
+
if (typeof val === "string") {
|
|
275
|
+
return !val.includes("'") && !val.includes('"') && !val.includes("\\");
|
|
276
|
+
}
|
|
277
|
+
return typeof val === "number" || typeof val === "boolean" || val === null || val === void 0;
|
|
278
|
+
}));
|
|
279
|
+
const prevWasCollapsed = prevValue && isObject(prevValue) && (Object.keys(prevValue).length === 0 || collapseObjects && depth + 1 > 0 && Object.entries(prevValue).filter(([, val]) => val !== void 0 || showUndefined).every(([, val]) => {
|
|
280
|
+
if (typeof val === "string") {
|
|
281
|
+
return !val.includes("'") && !val.includes('"') && !val.includes("\\");
|
|
282
|
+
}
|
|
283
|
+
return typeof val === "number" || typeof val === "boolean" || val === null || val === void 0;
|
|
284
|
+
}));
|
|
285
|
+
if (!afterSpaceWasAdded && indent === "" && isObject(objVal) && !willBeCollapsed && prevValue && !prevWasCollapsed && (addObjSpaces === "before" || addObjSpaces === "beforeAndAfter")) {
|
|
286
|
+
result += "\n";
|
|
287
|
+
}
|
|
288
|
+
if (Array.isArray(objVal)) {
|
|
289
|
+
const arrayIsSingleLine = valueString.split("\n").length === 1;
|
|
290
|
+
if (arrayIsSingleLine && !valueString.trim().startsWith("-")) {
|
|
291
|
+
result += `${indent}${key}: `;
|
|
292
|
+
} else {
|
|
293
|
+
result += `${indent}${key}:
|
|
294
|
+
`;
|
|
295
|
+
}
|
|
296
|
+
} else if (isObject(objVal)) {
|
|
297
|
+
const isCollapsedObject = valueString.startsWith("{") && !valueString.includes("\n");
|
|
298
|
+
if (Object.keys(objVal).length === 0 || isCollapsedObject) {
|
|
299
|
+
result += `${indent}${key}: `;
|
|
300
|
+
} else {
|
|
301
|
+
result += `${indent}${key}:
|
|
302
|
+
`;
|
|
303
|
+
}
|
|
304
|
+
} else {
|
|
305
|
+
result += `${indent}${key}: `;
|
|
306
|
+
}
|
|
307
|
+
result += valueString;
|
|
308
|
+
result += "\n";
|
|
309
|
+
if (indent === "") {
|
|
310
|
+
const isCollapsedObject = valueString.startsWith("{") && !valueString.includes("\n") && valueString.length > 2;
|
|
311
|
+
if (isObject(objVal) && !isCollapsedObject) {
|
|
312
|
+
if (addObjSpaces === "after" || addObjSpaces === "beforeAndAfter") {
|
|
313
|
+
result += "\n";
|
|
314
|
+
afterSpaceWasAdded = true;
|
|
315
|
+
} else {
|
|
316
|
+
afterSpaceWasAdded = false;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
prevValue = objVal;
|
|
321
|
+
}
|
|
322
|
+
return result.trimEnd();
|
|
323
|
+
}
|
|
324
|
+
if (Array.isArray(value)) {
|
|
325
|
+
let arrayWasAdded = false;
|
|
326
|
+
if (value.length === 0 || value.every(
|
|
327
|
+
(item) => typeof item === "string" || typeof item === "number" || typeof item === "boolean" || item === null || item === void 0
|
|
328
|
+
)) {
|
|
329
|
+
let line = "";
|
|
330
|
+
line += `[`;
|
|
331
|
+
line += value.map((item) => {
|
|
332
|
+
let valueToUse = item;
|
|
333
|
+
if (depth > maxDepth) {
|
|
334
|
+
valueToUse = `{max depth reached}`;
|
|
335
|
+
}
|
|
336
|
+
if (typeof valueToUse === "string" && valueToUse.includes("\n")) {
|
|
337
|
+
valueToUse = valueToUse.replace(/\n/g, "\\n");
|
|
338
|
+
}
|
|
339
|
+
return stringifyValue(
|
|
340
|
+
valueToUse,
|
|
341
|
+
"",
|
|
342
|
+
maxLineLength,
|
|
343
|
+
showUndefined,
|
|
344
|
+
maxDepth,
|
|
345
|
+
depth + 1,
|
|
346
|
+
collapseObjects,
|
|
347
|
+
addObjSpaces
|
|
348
|
+
);
|
|
349
|
+
}).join(", ");
|
|
350
|
+
line += "]";
|
|
351
|
+
if (line.length <= maxLineLength) {
|
|
352
|
+
result += line;
|
|
353
|
+
arrayWasAdded = true;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (!arrayWasAdded) {
|
|
357
|
+
for (let item of value) {
|
|
358
|
+
if (depth > maxDepth) {
|
|
359
|
+
item = `{max depth reached}`;
|
|
360
|
+
}
|
|
361
|
+
result += `${indent}- `;
|
|
362
|
+
if (Array.isArray(item) || isObject(item)) {
|
|
363
|
+
let arrayString = stringifyValue(
|
|
364
|
+
item,
|
|
365
|
+
childIndent,
|
|
366
|
+
maxLineLength,
|
|
367
|
+
showUndefined,
|
|
368
|
+
maxDepth,
|
|
369
|
+
depth + 1,
|
|
370
|
+
collapseObjects,
|
|
371
|
+
addObjSpaces
|
|
372
|
+
);
|
|
373
|
+
arrayString = arrayString.trimStart();
|
|
374
|
+
result += arrayString;
|
|
375
|
+
} else {
|
|
376
|
+
result += stringifyValue(
|
|
377
|
+
item,
|
|
378
|
+
childIndent,
|
|
379
|
+
maxLineLength,
|
|
380
|
+
showUndefined,
|
|
381
|
+
maxDepth,
|
|
382
|
+
depth + 1,
|
|
383
|
+
collapseObjects,
|
|
384
|
+
addObjSpaces
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
result += "\n";
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return result.trimEnd();
|
|
391
|
+
}
|
|
392
|
+
if (typeof value === "string") {
|
|
393
|
+
if (value.includes("\n")) {
|
|
394
|
+
const lines = value.split("\n");
|
|
395
|
+
for (const [i, line] of lines.entries()) {
|
|
396
|
+
if (i === 0) {
|
|
397
|
+
if (value.endsWith("\n")) {
|
|
398
|
+
result += `|`;
|
|
399
|
+
} else {
|
|
400
|
+
result += `|-`;
|
|
401
|
+
}
|
|
402
|
+
result += `
|
|
403
|
+
${indent}${line}
|
|
404
|
+
`;
|
|
405
|
+
} else {
|
|
406
|
+
result += `${indent}${line}
|
|
407
|
+
`;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
} else {
|
|
411
|
+
if (value.includes("'") && !value.includes('"')) {
|
|
412
|
+
result += `"${value}"`;
|
|
413
|
+
} else if (value.includes('"') && !value.includes("'")) {
|
|
414
|
+
result += `'${value}'`;
|
|
415
|
+
} else if (value.includes("'") && value.includes('"')) {
|
|
416
|
+
result += `"${value.replace(/"/g, '\\"')}"`;
|
|
417
|
+
} else {
|
|
418
|
+
result += `'${value}'`;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return result.trimEnd();
|
|
422
|
+
}
|
|
423
|
+
if (typeof value === "number" || typeof value === "boolean" || value === null || value === void 0) {
|
|
424
|
+
return String(value).trimEnd();
|
|
425
|
+
}
|
|
426
|
+
const normalizedValue = normalizeValue(value);
|
|
427
|
+
if (normalizedValue !== null) {
|
|
428
|
+
return stringifyValue(
|
|
429
|
+
{
|
|
430
|
+
[`${normalizedValue[0]}#`]: normalizedValue[1]
|
|
431
|
+
},
|
|
432
|
+
indent,
|
|
433
|
+
maxLineLength,
|
|
434
|
+
showUndefined,
|
|
435
|
+
maxDepth,
|
|
436
|
+
depth + 1,
|
|
437
|
+
collapseObjects,
|
|
438
|
+
addObjSpaces
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
return JSON.stringify(value);
|
|
442
|
+
}
|
|
443
|
+
function normalizeValue(value) {
|
|
444
|
+
if (value === null || isPlainObject(value) || Array.isArray(value)) {
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
if (value instanceof Map) {
|
|
448
|
+
const mapEntries = Array.from(value.entries());
|
|
449
|
+
let mapValue;
|
|
450
|
+
if (mapEntries.every(([key]) => typeof key === "string")) {
|
|
451
|
+
const mapObjValue = {};
|
|
452
|
+
for (const [key, val] of mapEntries) {
|
|
453
|
+
mapObjValue[key] = val;
|
|
454
|
+
}
|
|
455
|
+
mapValue = mapObjValue;
|
|
456
|
+
} else {
|
|
457
|
+
mapValue = mapEntries.map(([key, val]) => ({
|
|
458
|
+
key,
|
|
459
|
+
value: val
|
|
460
|
+
}));
|
|
461
|
+
}
|
|
462
|
+
return ["Map", mapValue];
|
|
463
|
+
}
|
|
464
|
+
if (value instanceof Set) {
|
|
465
|
+
const setValue = Array.from(value);
|
|
466
|
+
return ["Set", setValue];
|
|
467
|
+
}
|
|
468
|
+
if (value instanceof Date) {
|
|
469
|
+
return ["Date", value.toISOString()];
|
|
470
|
+
}
|
|
471
|
+
if (value instanceof RegExp) {
|
|
472
|
+
return ["RegExp", value.toString()];
|
|
473
|
+
}
|
|
474
|
+
if (value instanceof Error) {
|
|
475
|
+
return [
|
|
476
|
+
"Error",
|
|
477
|
+
{
|
|
478
|
+
message: value.message,
|
|
479
|
+
name: value.name,
|
|
480
|
+
stack: value.stack
|
|
481
|
+
}
|
|
482
|
+
];
|
|
483
|
+
}
|
|
484
|
+
if (value instanceof File) {
|
|
485
|
+
return [
|
|
486
|
+
"File",
|
|
487
|
+
{
|
|
488
|
+
name: value.name,
|
|
489
|
+
type: value.type,
|
|
490
|
+
lastModified: new Date(value.lastModified).toISOString(),
|
|
491
|
+
size: bytesToHumanReadable(value.size)
|
|
492
|
+
}
|
|
493
|
+
];
|
|
494
|
+
}
|
|
495
|
+
if (typeof value === "object") {
|
|
496
|
+
if ("toJSON" in value && typeof value.toJSON === "function") {
|
|
497
|
+
return [value.constructor.name, value.toJSON()];
|
|
498
|
+
}
|
|
499
|
+
if ("toString" in value && typeof value.toString === "function") {
|
|
500
|
+
const stringValue = value.toString();
|
|
501
|
+
if (stringValue.toString() !== "[object Object]") {
|
|
502
|
+
return [value.constructor.name, stringValue];
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
const objectValue = { ...value };
|
|
506
|
+
const displayValue = {};
|
|
507
|
+
let addedKeys = 0;
|
|
508
|
+
for (const [key, item] of Object.entries(objectValue)) {
|
|
509
|
+
if (addedKeys > 4) {
|
|
510
|
+
displayValue["...and more properties"] = Object.keys(objectValue).length - 4;
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
513
|
+
if (typeof item === "string" || typeof item === "number" || typeof item === "boolean" || item === null || item === void 0) {
|
|
514
|
+
displayValue[key] = item;
|
|
515
|
+
addedKeys++;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return [String(value.constructor.name), displayValue];
|
|
519
|
+
}
|
|
520
|
+
if (typeof value === "function") {
|
|
521
|
+
const functionString = value.toString();
|
|
522
|
+
return [
|
|
523
|
+
`Function`,
|
|
524
|
+
functionString.includes("\n") ? truncateString(functionString.split("\n").join(""), 40) : functionString
|
|
525
|
+
];
|
|
526
|
+
}
|
|
527
|
+
return null;
|
|
528
|
+
}
|
|
529
|
+
|
|
156
530
|
// src/testUtils.ts
|
|
157
531
|
function createLoggerStore({
|
|
158
532
|
filterKeys: defaultFilterKeys,
|
|
@@ -379,8 +753,172 @@ function waitController() {
|
|
|
379
753
|
}
|
|
380
754
|
};
|
|
381
755
|
}
|
|
756
|
+
function matchesKeyPattern(path, pattern) {
|
|
757
|
+
if (path === pattern) {
|
|
758
|
+
return true;
|
|
759
|
+
}
|
|
760
|
+
if (pattern.includes("*")) {
|
|
761
|
+
const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, "[^.]*");
|
|
762
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
763
|
+
return regex.test(path);
|
|
764
|
+
}
|
|
765
|
+
return false;
|
|
766
|
+
}
|
|
767
|
+
function isParentOfPattern(path, pattern) {
|
|
768
|
+
if (pattern.includes("*")) {
|
|
769
|
+
const patternParts = pattern.split(".");
|
|
770
|
+
const pathParts = path.split(".");
|
|
771
|
+
if (pathParts.length >= patternParts.length) {
|
|
772
|
+
return false;
|
|
773
|
+
}
|
|
774
|
+
for (let i = 0; i < pathParts.length; i++) {
|
|
775
|
+
const pathPart = pathParts[i];
|
|
776
|
+
const patternPart = patternParts[i];
|
|
777
|
+
if (patternPart === "*") {
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
if (pathPart !== patternPart) {
|
|
781
|
+
return false;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
return true;
|
|
785
|
+
} else {
|
|
786
|
+
return pattern.startsWith(`${path}.`);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
function applyKeyFiltering(value, { rejectKeys, filterKeys }, currentPath = "", visited = /* @__PURE__ */ new Set()) {
|
|
790
|
+
if (!isPlainObject(value) && !Array.isArray(value)) {
|
|
791
|
+
return value;
|
|
792
|
+
}
|
|
793
|
+
if (Array.isArray(value)) {
|
|
794
|
+
if (visited.has(value)) {
|
|
795
|
+
throw new Error("Circular reference detected in array during key filtering");
|
|
796
|
+
}
|
|
797
|
+
visited.add(value);
|
|
798
|
+
try {
|
|
799
|
+
return value.map(
|
|
800
|
+
(item, index) => applyKeyFiltering(item, { rejectKeys, filterKeys }, currentPath ? `${currentPath}[${index}]` : `[${index}]`, visited)
|
|
801
|
+
);
|
|
802
|
+
} finally {
|
|
803
|
+
visited.delete(value);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
if (isPlainObject(value)) {
|
|
807
|
+
if (visited.has(value)) {
|
|
808
|
+
throw new Error("Circular reference detected in object during key filtering");
|
|
809
|
+
}
|
|
810
|
+
visited.add(value);
|
|
811
|
+
try {
|
|
812
|
+
const result = {};
|
|
813
|
+
for (const [key, itemValue] of Object.entries(value)) {
|
|
814
|
+
const fullPath = currentPath ? `${currentPath}.${key}` : key;
|
|
815
|
+
if (rejectKeys?.some(
|
|
816
|
+
(rejectPath) => matchesKeyPattern(fullPath, rejectPath) || matchesKeyPattern(key, rejectPath)
|
|
817
|
+
)) {
|
|
818
|
+
continue;
|
|
819
|
+
}
|
|
820
|
+
if (filterKeys) {
|
|
821
|
+
const shouldInclude = filterKeys.some(
|
|
822
|
+
(filterPath) => (
|
|
823
|
+
// Exact match
|
|
824
|
+
matchesKeyPattern(fullPath, filterPath) || matchesKeyPattern(key, filterPath) || // This path is a parent of a filter pattern (so we include it to allow children)
|
|
825
|
+
isParentOfPattern(fullPath, filterPath)
|
|
826
|
+
)
|
|
827
|
+
);
|
|
828
|
+
if (!shouldInclude) {
|
|
829
|
+
continue;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
result[key] = applyKeyFiltering(itemValue, { rejectKeys, filterKeys }, fullPath, visited);
|
|
833
|
+
}
|
|
834
|
+
return result;
|
|
835
|
+
} finally {
|
|
836
|
+
visited.delete(value);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
return value;
|
|
840
|
+
}
|
|
841
|
+
function compactSnapshot(value, {
|
|
842
|
+
collapseObjects = true,
|
|
843
|
+
maxLineLength = 100,
|
|
844
|
+
showUndefined = false,
|
|
845
|
+
showBooleansAs = true,
|
|
846
|
+
rejectKeys,
|
|
847
|
+
filterKeys,
|
|
848
|
+
...options
|
|
849
|
+
} = {}) {
|
|
850
|
+
let processedValue = value;
|
|
851
|
+
if (rejectKeys || filterKeys) {
|
|
852
|
+
processedValue = applyKeyFiltering(processedValue, { rejectKeys, filterKeys });
|
|
853
|
+
}
|
|
854
|
+
processedValue = showBooleansAs ? replaceBooleansWithEmoji(processedValue, showBooleansAs) : processedValue;
|
|
855
|
+
return `
|
|
856
|
+
${yamlStringify(processedValue, {
|
|
857
|
+
collapseObjects,
|
|
858
|
+
maxLineLength,
|
|
859
|
+
showUndefined,
|
|
860
|
+
...options
|
|
861
|
+
})}`;
|
|
862
|
+
}
|
|
863
|
+
function replaceBooleansWithEmoji(value, showBooleansAs, visited = /* @__PURE__ */ new Set()) {
|
|
864
|
+
if (showBooleansAs === false) {
|
|
865
|
+
return value;
|
|
866
|
+
}
|
|
867
|
+
const defaultTrueText = "\u2705";
|
|
868
|
+
const defaultFalseText = "\u274C";
|
|
869
|
+
const config = typeof showBooleansAs === "boolean" ? { trueText: defaultTrueText, falseText: defaultFalseText } : {
|
|
870
|
+
trueText: showBooleansAs.trueText ?? defaultTrueText,
|
|
871
|
+
falseText: showBooleansAs.falseText ?? defaultFalseText,
|
|
872
|
+
props: showBooleansAs.props ?? {},
|
|
873
|
+
ignoreProps: showBooleansAs.ignoreProps ?? []
|
|
874
|
+
};
|
|
875
|
+
function processValue(val, propName) {
|
|
876
|
+
if (typeof val === "boolean") {
|
|
877
|
+
if (propName && config.ignoreProps?.includes(propName)) {
|
|
878
|
+
return val;
|
|
879
|
+
}
|
|
880
|
+
if (propName && config.props?.[propName]) {
|
|
881
|
+
const propConfig = config.props[propName];
|
|
882
|
+
if (propConfig === true) {
|
|
883
|
+
return val ? config.trueText : config.falseText;
|
|
884
|
+
}
|
|
885
|
+
return val ? propConfig.trueText ?? config.trueText : propConfig.falseText ?? config.falseText;
|
|
886
|
+
}
|
|
887
|
+
return val ? config.trueText : config.falseText;
|
|
888
|
+
}
|
|
889
|
+
if (Array.isArray(val)) {
|
|
890
|
+
if (visited.has(val)) {
|
|
891
|
+
throw new Error("Circular reference detected in array");
|
|
892
|
+
}
|
|
893
|
+
visited.add(val);
|
|
894
|
+
try {
|
|
895
|
+
return val.map((item) => processValue(item));
|
|
896
|
+
} finally {
|
|
897
|
+
visited.delete(val);
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
if (isPlainObject(val)) {
|
|
901
|
+
if (visited.has(val)) {
|
|
902
|
+
throw new Error("Circular reference detected in object");
|
|
903
|
+
}
|
|
904
|
+
visited.add(val);
|
|
905
|
+
try {
|
|
906
|
+
const result = {};
|
|
907
|
+
for (const [key, itemValue] of Object.entries(val)) {
|
|
908
|
+
result[key] = processValue(itemValue, key);
|
|
909
|
+
}
|
|
910
|
+
return result;
|
|
911
|
+
} finally {
|
|
912
|
+
visited.delete(val);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
return val;
|
|
916
|
+
}
|
|
917
|
+
return processValue(value);
|
|
918
|
+
}
|
|
382
919
|
// Annotate the CommonJS export names for ESM import in node:
|
|
383
920
|
0 && (module.exports = {
|
|
921
|
+
compactSnapshot,
|
|
384
922
|
createLoggerStore,
|
|
385
923
|
getResultFn,
|
|
386
924
|
waitController
|
package/lib/testUtils.d.cts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { YamlStringifyOptions } from './yamlStringify.cjs';
|
|
2
|
+
|
|
1
3
|
declare function createLoggerStore({ filterKeys: defaultFilterKeys, rejectKeys: defaultRejectKeys, splitLongLines: defaultSplitLongLines, maxLineLengthBeforeSplit: defaultMaxLineLengthBeforeSplit, fromLastSnapshot: defaultFromLastSnapshot, arrays: defaultArrays, changesOnly: defaultChangesOnly, useEmojiForBooleans: defaultUseEmojiForBooleans, }?: {
|
|
2
4
|
filterKeys?: string[];
|
|
3
5
|
rejectKeys?: string[];
|
|
@@ -39,5 +41,18 @@ declare function waitController(): {
|
|
|
39
41
|
stopWaiting: () => void;
|
|
40
42
|
stopWaitingAfter: (ms: number) => void;
|
|
41
43
|
};
|
|
44
|
+
declare function compactSnapshot(value: unknown, { collapseObjects, maxLineLength, showUndefined, showBooleansAs, rejectKeys, filterKeys, ...options }?: YamlStringifyOptions & {
|
|
45
|
+
showBooleansAs?: boolean | {
|
|
46
|
+
props?: Record<string, {
|
|
47
|
+
trueText?: string;
|
|
48
|
+
falseText?: string;
|
|
49
|
+
} | true>;
|
|
50
|
+
ignoreProps?: string[];
|
|
51
|
+
trueText?: string;
|
|
52
|
+
falseText?: string;
|
|
53
|
+
};
|
|
54
|
+
rejectKeys?: string[];
|
|
55
|
+
filterKeys?: string[];
|
|
56
|
+
}): string;
|
|
42
57
|
|
|
43
|
-
export { createLoggerStore, getResultFn, waitController };
|
|
58
|
+
export { compactSnapshot, createLoggerStore, getResultFn, waitController };
|
package/lib/testUtils.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { YamlStringifyOptions } from './yamlStringify.js';
|
|
2
|
+
|
|
1
3
|
declare function createLoggerStore({ filterKeys: defaultFilterKeys, rejectKeys: defaultRejectKeys, splitLongLines: defaultSplitLongLines, maxLineLengthBeforeSplit: defaultMaxLineLengthBeforeSplit, fromLastSnapshot: defaultFromLastSnapshot, arrays: defaultArrays, changesOnly: defaultChangesOnly, useEmojiForBooleans: defaultUseEmojiForBooleans, }?: {
|
|
2
4
|
filterKeys?: string[];
|
|
3
5
|
rejectKeys?: string[];
|
|
@@ -39,5 +41,18 @@ declare function waitController(): {
|
|
|
39
41
|
stopWaiting: () => void;
|
|
40
42
|
stopWaitingAfter: (ms: number) => void;
|
|
41
43
|
};
|
|
44
|
+
declare function compactSnapshot(value: unknown, { collapseObjects, maxLineLength, showUndefined, showBooleansAs, rejectKeys, filterKeys, ...options }?: YamlStringifyOptions & {
|
|
45
|
+
showBooleansAs?: boolean | {
|
|
46
|
+
props?: Record<string, {
|
|
47
|
+
trueText?: string;
|
|
48
|
+
falseText?: string;
|
|
49
|
+
} | true>;
|
|
50
|
+
ignoreProps?: string[];
|
|
51
|
+
trueText?: string;
|
|
52
|
+
falseText?: string;
|
|
53
|
+
};
|
|
54
|
+
rejectKeys?: string[];
|
|
55
|
+
filterKeys?: string[];
|
|
56
|
+
}): string;
|
|
42
57
|
|
|
43
|
-
export { createLoggerStore, getResultFn, waitController };
|
|
58
|
+
export { compactSnapshot, createLoggerStore, getResultFn, waitController };
|