executable-stories-formatters 0.7.9 → 0.7.11
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/cli.js +126 -96
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +95 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +94 -64
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/cli.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { parseArgs } from "util";
|
|
5
|
-
import * as
|
|
6
|
-
import * as
|
|
5
|
+
import * as fs8 from "fs";
|
|
6
|
+
import * as path8 from "path";
|
|
7
7
|
|
|
8
8
|
// src/validation/schema-validator.ts
|
|
9
9
|
import Ajv from "ajv/dist/2020.js";
|
|
@@ -492,17 +492,17 @@ function validateRawRun(data) {
|
|
|
492
492
|
return { valid: true, errors: [] };
|
|
493
493
|
}
|
|
494
494
|
const errors = (validate.errors ?? []).map((err) => {
|
|
495
|
-
const
|
|
495
|
+
const path9 = err.instancePath || "/";
|
|
496
496
|
const message = err.message ?? "unknown error";
|
|
497
497
|
if (err.keyword === "additionalProperties") {
|
|
498
498
|
const extra = err.params.additionalProperty;
|
|
499
|
-
return `${
|
|
499
|
+
return `${path9}: ${message} \u2014 '${extra}'`;
|
|
500
500
|
}
|
|
501
501
|
if (err.keyword === "enum") {
|
|
502
502
|
const allowed = err.params.allowedValues;
|
|
503
|
-
return `${
|
|
503
|
+
return `${path9}: ${message} \u2014 allowed: ${JSON.stringify(allowed)}`;
|
|
504
504
|
}
|
|
505
|
-
return `${
|
|
505
|
+
return `${path9}: ${message}`;
|
|
506
506
|
});
|
|
507
507
|
return { valid: false, errors };
|
|
508
508
|
}
|
|
@@ -966,7 +966,7 @@ ${result.errors.join("\n")}`);
|
|
|
966
966
|
|
|
967
967
|
// src/index.ts
|
|
968
968
|
import "fs";
|
|
969
|
-
import * as
|
|
969
|
+
import * as path6 from "path";
|
|
970
970
|
import * as fsPromises from "fs/promises";
|
|
971
971
|
|
|
972
972
|
// src/converters/acl/lines.ts
|
|
@@ -1330,6 +1330,10 @@ ${doc.markdown}`,
|
|
|
1330
1330
|
}
|
|
1331
1331
|
};
|
|
1332
1332
|
|
|
1333
|
+
// src/formatters/html/renderers/index.ts
|
|
1334
|
+
import * as fs2 from "fs";
|
|
1335
|
+
import * as path2 from "path";
|
|
1336
|
+
|
|
1333
1337
|
// src/formatters/html/template.ts
|
|
1334
1338
|
var JS_THEME = `
|
|
1335
1339
|
// Theme management
|
|
@@ -13637,7 +13641,9 @@ function renderDocMermaid(entry, deps) {
|
|
|
13637
13641
|
}
|
|
13638
13642
|
function renderDocScreenshot(entry, deps) {
|
|
13639
13643
|
const alt = entry.alt ?? "Screenshot";
|
|
13640
|
-
const
|
|
13644
|
+
const embedEnabled = deps.embedScreenshots ?? true;
|
|
13645
|
+
const isRemote = /^(?:https?:|data:)/i.test(entry.path);
|
|
13646
|
+
const src = embedEnabled && !isRemote && deps.readScreenshot ? deps.readScreenshot(entry.path) ?? entry.path : entry.path;
|
|
13641
13647
|
return `<div class="doc-screenshot">
|
|
13642
13648
|
<img src="${deps.escapeHtml(src)}" alt="${deps.escapeHtml(alt)}" class="doc-screenshot-img" />
|
|
13643
13649
|
${entry.alt ? `<div class="doc-screenshot-caption">${deps.escapeHtml(entry.alt)}</div>` : ""}
|
|
@@ -14219,6 +14225,28 @@ function renderToc(args, deps) {
|
|
|
14219
14225
|
}
|
|
14220
14226
|
|
|
14221
14227
|
// src/formatters/html/renderers/index.ts
|
|
14228
|
+
var SCREENSHOT_MIME_BY_EXT = {
|
|
14229
|
+
png: "image/png",
|
|
14230
|
+
jpg: "image/jpeg",
|
|
14231
|
+
jpeg: "image/jpeg",
|
|
14232
|
+
gif: "image/gif",
|
|
14233
|
+
webp: "image/webp",
|
|
14234
|
+
svg: "image/svg+xml",
|
|
14235
|
+
avif: "image/avif",
|
|
14236
|
+
bmp: "image/bmp"
|
|
14237
|
+
};
|
|
14238
|
+
function readScreenshotAsDataUri(filePath) {
|
|
14239
|
+
try {
|
|
14240
|
+
const ext = path2.extname(filePath).slice(1).toLowerCase();
|
|
14241
|
+
const mime = SCREENSHOT_MIME_BY_EXT[ext];
|
|
14242
|
+
if (!mime) return void 0;
|
|
14243
|
+
if (!fs2.existsSync(filePath)) return void 0;
|
|
14244
|
+
const buf = fs2.readFileSync(filePath);
|
|
14245
|
+
return `data:${mime};base64,${buf.toString("base64")}`;
|
|
14246
|
+
} catch {
|
|
14247
|
+
return void 0;
|
|
14248
|
+
}
|
|
14249
|
+
}
|
|
14222
14250
|
function normalizeOptions(options = {}) {
|
|
14223
14251
|
return {
|
|
14224
14252
|
title: options.title ?? "Test Results",
|
|
@@ -14242,7 +14270,9 @@ function createHtmlFormatter(options = {}) {
|
|
|
14242
14270
|
escapeHtml,
|
|
14243
14271
|
syntaxHighlighting: opts.syntaxHighlighting,
|
|
14244
14272
|
markdownEnabled: opts.markdownEnabled,
|
|
14245
|
-
mermaidEnabled: opts.mermaidEnabled
|
|
14273
|
+
mermaidEnabled: opts.mermaidEnabled,
|
|
14274
|
+
embedScreenshots: opts.embedScreenshots,
|
|
14275
|
+
readScreenshot: (filePath) => readScreenshotAsDataUri(filePath)
|
|
14246
14276
|
};
|
|
14247
14277
|
const renderDocs = (docs, containerClass) => {
|
|
14248
14278
|
if (!docs || docs.length === 0) return "";
|
|
@@ -15671,8 +15701,8 @@ function extractDocAttachments(step) {
|
|
|
15671
15701
|
}
|
|
15672
15702
|
return attachments;
|
|
15673
15703
|
}
|
|
15674
|
-
function guessMediaType(
|
|
15675
|
-
const lower =
|
|
15704
|
+
function guessMediaType(path9) {
|
|
15705
|
+
const lower = path9.toLowerCase();
|
|
15676
15706
|
if (lower.endsWith(".png")) return "image/png";
|
|
15677
15707
|
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
|
|
15678
15708
|
if (lower.endsWith(".gif")) return "image/gif";
|
|
@@ -16746,8 +16776,8 @@ function selectTestCases(args, deps) {
|
|
|
16746
16776
|
}
|
|
16747
16777
|
|
|
16748
16778
|
// src/bundler/bundle-assets.ts
|
|
16749
|
-
import * as
|
|
16750
|
-
import * as
|
|
16779
|
+
import * as fs4 from "fs";
|
|
16780
|
+
import * as path4 from "path";
|
|
16751
16781
|
|
|
16752
16782
|
// src/bundler/scan-html-assets.ts
|
|
16753
16783
|
function scanHtmlAssets(html) {
|
|
@@ -16777,21 +16807,21 @@ function isLocalAssetRef(ref) {
|
|
|
16777
16807
|
}
|
|
16778
16808
|
|
|
16779
16809
|
// src/bundler/copy-asset.ts
|
|
16780
|
-
import * as
|
|
16781
|
-
import * as
|
|
16810
|
+
import * as fs3 from "fs";
|
|
16811
|
+
import * as path3 from "path";
|
|
16782
16812
|
import * as crypto from "crypto";
|
|
16783
16813
|
function copyAsset(sourcePath, assetsDir) {
|
|
16784
|
-
if (!
|
|
16785
|
-
|
|
16814
|
+
if (!fs3.existsSync(assetsDir)) {
|
|
16815
|
+
fs3.mkdirSync(assetsDir, { recursive: true });
|
|
16786
16816
|
}
|
|
16787
|
-
const content =
|
|
16817
|
+
const content = fs3.readFileSync(sourcePath);
|
|
16788
16818
|
const hash = crypto.createHash("sha256").update(content).digest("hex").slice(0, 8);
|
|
16789
|
-
const ext =
|
|
16790
|
-
const baseName = sanitize(
|
|
16819
|
+
const ext = path3.extname(sourcePath);
|
|
16820
|
+
const baseName = sanitize(path3.basename(sourcePath, ext));
|
|
16791
16821
|
const destName = `${baseName}-${hash}${ext}`;
|
|
16792
|
-
const destPath =
|
|
16793
|
-
if (!
|
|
16794
|
-
|
|
16822
|
+
const destPath = path3.join(assetsDir, destName);
|
|
16823
|
+
if (!fs3.existsSync(destPath)) {
|
|
16824
|
+
fs3.copyFileSync(sourcePath, destPath);
|
|
16795
16825
|
}
|
|
16796
16826
|
return `assets/${destName}`;
|
|
16797
16827
|
}
|
|
@@ -16801,15 +16831,15 @@ function sanitize(name) {
|
|
|
16801
16831
|
|
|
16802
16832
|
// src/bundler/bundle-assets.ts
|
|
16803
16833
|
function bundleAssets(htmlPath, options = {}) {
|
|
16804
|
-
const htmlDir =
|
|
16805
|
-
const assetsDir =
|
|
16806
|
-
let html =
|
|
16834
|
+
const htmlDir = path4.dirname(htmlPath);
|
|
16835
|
+
const assetsDir = path4.join(htmlDir, "assets");
|
|
16836
|
+
let html = fs4.readFileSync(htmlPath, "utf8");
|
|
16807
16837
|
const refs = scanHtmlAssets(html);
|
|
16808
16838
|
let copiedCount = 0;
|
|
16809
16839
|
const missing = [];
|
|
16810
16840
|
for (const ref of refs) {
|
|
16811
|
-
const absolutePath =
|
|
16812
|
-
if (!
|
|
16841
|
+
const absolutePath = path4.resolve(htmlDir, ref);
|
|
16842
|
+
if (!fs4.existsSync(absolutePath)) {
|
|
16813
16843
|
missing.push(ref);
|
|
16814
16844
|
continue;
|
|
16815
16845
|
}
|
|
@@ -16822,7 +16852,7 @@ function bundleAssets(htmlPath, options = {}) {
|
|
|
16822
16852
|
`Missing asset${missing.length > 1 ? "s" : ""}: ${missing.join(", ")}`
|
|
16823
16853
|
);
|
|
16824
16854
|
}
|
|
16825
|
-
|
|
16855
|
+
fs4.writeFileSync(htmlPath, html, "utf8");
|
|
16826
16856
|
return {
|
|
16827
16857
|
copiedCount,
|
|
16828
16858
|
missingCount: missing.length,
|
|
@@ -17305,15 +17335,15 @@ function groupBy7(items, keyFn) {
|
|
|
17305
17335
|
}
|
|
17306
17336
|
|
|
17307
17337
|
// src/formatters/astro-assets.ts
|
|
17308
|
-
import * as
|
|
17309
|
-
import * as
|
|
17338
|
+
import * as fs5 from "fs";
|
|
17339
|
+
import * as path5 from "path";
|
|
17310
17340
|
var SKIP_PREFIXES = ["http://", "https://", "data:", "#"];
|
|
17311
17341
|
function isLocalPath(src) {
|
|
17312
17342
|
const trimmed = src.trim();
|
|
17313
17343
|
if (SKIP_PREFIXES.some((prefix) => trimmed.startsWith(prefix))) {
|
|
17314
17344
|
return false;
|
|
17315
17345
|
}
|
|
17316
|
-
return !
|
|
17346
|
+
return !path5.posix.isAbsolute(trimmed) && !path5.win32.isAbsolute(trimmed);
|
|
17317
17347
|
}
|
|
17318
17348
|
function stripCodeContent(markdown) {
|
|
17319
17349
|
let result = markdown.replace(/^[ \t]*(`{3,}|~{3,})[^\n]*\n[\s\S]*?^[ \t]*\1\s*$/gm, "");
|
|
@@ -17407,8 +17437,8 @@ function copyMarkdownAssets(options) {
|
|
|
17407
17437
|
const pathMap = /* @__PURE__ */ new Map();
|
|
17408
17438
|
const missing = [];
|
|
17409
17439
|
for (const ref of refs) {
|
|
17410
|
-
const absPath =
|
|
17411
|
-
if (!
|
|
17440
|
+
const absPath = path5.resolve(markdownDir, ref);
|
|
17441
|
+
if (!fs5.existsSync(absPath)) {
|
|
17412
17442
|
if (!allowMissing) {
|
|
17413
17443
|
throw new Error(`Asset not found: ${absPath}`);
|
|
17414
17444
|
}
|
|
@@ -18716,11 +18746,11 @@ function computeOutputPath(sourceFile, format, mode, colocatedStyle, baseOutputD
|
|
|
18716
18746
|
const ext = FORMAT_EXTENSIONS[format];
|
|
18717
18747
|
const effectiveName = outputName + (outputNameSuffix ?? "");
|
|
18718
18748
|
if (mode === "aggregated") {
|
|
18719
|
-
return toPosix(
|
|
18749
|
+
return toPosix(path6.join(baseOutputDir, `${effectiveName}${ext}`));
|
|
18720
18750
|
}
|
|
18721
18751
|
const normalizedSource = toPosix(sourceFile);
|
|
18722
|
-
const dirOfSource =
|
|
18723
|
-
let baseName =
|
|
18752
|
+
const dirOfSource = path6.posix.dirname(normalizedSource);
|
|
18753
|
+
let baseName = path6.posix.basename(normalizedSource);
|
|
18724
18754
|
for (const testExt of TEST_EXTENSIONS) {
|
|
18725
18755
|
if (baseName.endsWith(testExt)) {
|
|
18726
18756
|
baseName = baseName.slice(0, -testExt.length);
|
|
@@ -18729,9 +18759,9 @@ function computeOutputPath(sourceFile, format, mode, colocatedStyle, baseOutputD
|
|
|
18729
18759
|
}
|
|
18730
18760
|
const fileName = `${baseName}.${effectiveName}${ext}`;
|
|
18731
18761
|
if (colocatedStyle === "adjacent") {
|
|
18732
|
-
return toPosix(
|
|
18762
|
+
return toPosix(path6.posix.join(dirOfSource, fileName));
|
|
18733
18763
|
}
|
|
18734
|
-
return toPosix(
|
|
18764
|
+
return toPosix(path6.posix.join(baseOutputDir, dirOfSource, fileName));
|
|
18735
18765
|
}
|
|
18736
18766
|
function groupTestCasesByOutput(testCases, format, options, logger, outputNameSuffix) {
|
|
18737
18767
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -18929,8 +18959,8 @@ var ReportGenerator = class {
|
|
|
18929
18959
|
if (astroPaths) {
|
|
18930
18960
|
for (const mdPath of astroPaths) {
|
|
18931
18961
|
const content = await fsPromises.readFile(mdPath, "utf8");
|
|
18932
|
-
const mdDir =
|
|
18933
|
-
const assetsDir =
|
|
18962
|
+
const mdDir = path6.dirname(mdPath);
|
|
18963
|
+
const assetsDir = path6.resolve(this.options.astro.assetsDir);
|
|
18934
18964
|
const result = copyMarkdownAssets({
|
|
18935
18965
|
markdown: content,
|
|
18936
18966
|
markdownDir: mdDir,
|
|
@@ -18961,9 +18991,9 @@ var ReportGenerator = class {
|
|
|
18961
18991
|
if (groups.size === 0 && this.options.output.mode === "aggregated") {
|
|
18962
18992
|
const ext = FORMAT_EXTENSIONS[format];
|
|
18963
18993
|
const effectiveName = this.options.outputName + (outputNameSuffix ?? "");
|
|
18964
|
-
const outputPath = toPosix(
|
|
18994
|
+
const outputPath = toPosix(path6.join(this.options.outputDir, `${effectiveName}${ext}`));
|
|
18965
18995
|
const content = await this.formatContent(run, format);
|
|
18966
|
-
const dir =
|
|
18996
|
+
const dir = path6.dirname(outputPath);
|
|
18967
18997
|
await fsPromises.mkdir(dir, { recursive: true });
|
|
18968
18998
|
await this.deps.writeFile(outputPath, content);
|
|
18969
18999
|
return [outputPath];
|
|
@@ -18975,7 +19005,7 @@ var ReportGenerator = class {
|
|
|
18975
19005
|
testCases
|
|
18976
19006
|
};
|
|
18977
19007
|
const content = await this.formatContent(groupRun, format);
|
|
18978
|
-
const dir =
|
|
19008
|
+
const dir = path6.dirname(outputPath);
|
|
18979
19009
|
await fsPromises.mkdir(dir, { recursive: true });
|
|
18980
19010
|
await this.deps.writeFile(outputPath, content);
|
|
18981
19011
|
writtenPaths.push(outputPath);
|
|
@@ -19095,7 +19125,7 @@ async function generateRunComparison(args) {
|
|
|
19095
19125
|
await fsPromises.mkdir(outputDir, { recursive: true });
|
|
19096
19126
|
for (const format of args.formats) {
|
|
19097
19127
|
const ext = format === "html" ? ".html" : ".md";
|
|
19098
|
-
const outputPath = toPosix(
|
|
19128
|
+
const outputPath = toPosix(path6.join(outputDir, `${outputName}${ext}`));
|
|
19099
19129
|
const content = format === "html" ? new RunDiffHtmlFormatter({ title: args.title }).format(diff) : new RunDiffMarkdownFormatter({ title: args.title }).format(diff);
|
|
19100
19130
|
await fsPromises.writeFile(outputPath, content, "utf8");
|
|
19101
19131
|
files.push(outputPath);
|
|
@@ -19104,23 +19134,23 @@ async function generateRunComparison(args) {
|
|
|
19104
19134
|
}
|
|
19105
19135
|
|
|
19106
19136
|
// src/init-astro.ts
|
|
19107
|
-
import * as
|
|
19108
|
-
import * as
|
|
19137
|
+
import * as fs7 from "fs";
|
|
19138
|
+
import * as path7 from "path";
|
|
19109
19139
|
import { fileURLToPath } from "url";
|
|
19110
|
-
var __dirname =
|
|
19140
|
+
var __dirname = path7.dirname(fileURLToPath(import.meta.url));
|
|
19111
19141
|
function initAstro(options = {}) {
|
|
19112
19142
|
const targetDir = options.targetDir ?? "./story-docs";
|
|
19113
19143
|
const force = options.force ?? false;
|
|
19114
|
-
if (
|
|
19115
|
-
const entries =
|
|
19144
|
+
if (fs7.existsSync(targetDir)) {
|
|
19145
|
+
const entries = fs7.readdirSync(targetDir);
|
|
19116
19146
|
if (entries.length > 0 && !force) {
|
|
19117
19147
|
throw new Error(
|
|
19118
19148
|
`Directory "${targetDir}" already exists and is not empty. Use --force to overwrite.`
|
|
19119
19149
|
);
|
|
19120
19150
|
}
|
|
19121
19151
|
}
|
|
19122
|
-
const templateDir =
|
|
19123
|
-
if (!
|
|
19152
|
+
const templateDir = path7.resolve(__dirname, "..", "templates", "astro-starlight");
|
|
19153
|
+
if (!fs7.existsSync(templateDir)) {
|
|
19124
19154
|
throw new Error(
|
|
19125
19155
|
`Template directory not found at ${templateDir}. Ensure the package is installed correctly.`
|
|
19126
19156
|
);
|
|
@@ -19129,25 +19159,25 @@ function initAstro(options = {}) {
|
|
|
19129
19159
|
return { targetDir };
|
|
19130
19160
|
}
|
|
19131
19161
|
function copyDirRecursive(src, dest) {
|
|
19132
|
-
|
|
19133
|
-
const entries =
|
|
19162
|
+
fs7.mkdirSync(dest, { recursive: true });
|
|
19163
|
+
const entries = fs7.readdirSync(src, { withFileTypes: true });
|
|
19134
19164
|
for (const entry of entries) {
|
|
19135
|
-
const srcPath =
|
|
19136
|
-
const destPath =
|
|
19165
|
+
const srcPath = path7.join(src, entry.name);
|
|
19166
|
+
const destPath = path7.join(dest, entry.name);
|
|
19137
19167
|
if (entry.isDirectory()) {
|
|
19138
19168
|
copyDirRecursive(srcPath, destPath);
|
|
19139
19169
|
} else {
|
|
19140
|
-
|
|
19170
|
+
fs7.copyFileSync(srcPath, destPath);
|
|
19141
19171
|
}
|
|
19142
19172
|
}
|
|
19143
19173
|
}
|
|
19144
19174
|
|
|
19145
19175
|
// src/config.ts
|
|
19146
|
-
import { existsSync as
|
|
19176
|
+
import { existsSync as existsSync7 } from "fs";
|
|
19147
19177
|
import { resolve as resolve6 } from "path";
|
|
19148
19178
|
async function loadConfig(configPath) {
|
|
19149
19179
|
const resolved = configPath ? resolve6(configPath) : resolve6(process.cwd(), "executable-stories.config.js");
|
|
19150
|
-
if (!
|
|
19180
|
+
if (!existsSync7(resolved)) return {};
|
|
19151
19181
|
const mod = await import(resolved);
|
|
19152
19182
|
const config = mod.default;
|
|
19153
19183
|
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
@@ -19566,20 +19596,20 @@ async function readInput(args) {
|
|
|
19566
19596
|
if (args.stdin) {
|
|
19567
19597
|
return readStdin();
|
|
19568
19598
|
}
|
|
19569
|
-
const filePath =
|
|
19570
|
-
if (!
|
|
19599
|
+
const filePath = path8.resolve(args.inputFile);
|
|
19600
|
+
if (!fs8.existsSync(filePath)) {
|
|
19571
19601
|
console.error(`Error: File not found: ${filePath}`);
|
|
19572
19602
|
process.exit(EXIT_USAGE);
|
|
19573
19603
|
}
|
|
19574
|
-
return
|
|
19604
|
+
return fs8.readFileSync(filePath, "utf8");
|
|
19575
19605
|
}
|
|
19576
19606
|
function readFileInput(filePath) {
|
|
19577
|
-
const resolved =
|
|
19578
|
-
if (!
|
|
19607
|
+
const resolved = path8.resolve(filePath);
|
|
19608
|
+
if (!fs8.existsSync(resolved)) {
|
|
19579
19609
|
console.error(`Error: File not found: ${resolved}`);
|
|
19580
19610
|
process.exit(EXIT_USAGE);
|
|
19581
19611
|
}
|
|
19582
|
-
return
|
|
19612
|
+
return fs8.readFileSync(resolved, "utf8");
|
|
19583
19613
|
}
|
|
19584
19614
|
function readStdin() {
|
|
19585
19615
|
return new Promise((resolve8, reject) => {
|
|
@@ -19712,14 +19742,14 @@ function tryNormalizeRunFromText(text2, args) {
|
|
|
19712
19742
|
}
|
|
19713
19743
|
}
|
|
19714
19744
|
function listBaselineCandidates(currentFile, args) {
|
|
19715
|
-
const baselineDir =
|
|
19716
|
-
const currentResolved =
|
|
19717
|
-
if (!
|
|
19745
|
+
const baselineDir = path8.resolve(args.baselineDir ?? path8.dirname(currentFile));
|
|
19746
|
+
const currentResolved = path8.resolve(currentFile);
|
|
19747
|
+
if (!fs8.existsSync(baselineDir)) {
|
|
19718
19748
|
console.error(`Error: baseline directory not found: ${baselineDir}`);
|
|
19719
19749
|
process.exit(EXIT_USAGE);
|
|
19720
19750
|
}
|
|
19721
|
-
const entries =
|
|
19722
|
-
return entries.filter((entry) => entry.isFile()).map((entry) =>
|
|
19751
|
+
const entries = fs8.readdirSync(baselineDir, { withFileTypes: true });
|
|
19752
|
+
return entries.filter((entry) => entry.isFile()).map((entry) => path8.join(baselineDir, entry.name)).filter((candidate) => path8.resolve(candidate) !== currentResolved).filter(
|
|
19723
19753
|
(candidate) => args.inputType === "ndjson" ? candidate.endsWith(".ndjson") : candidate.endsWith(".json")
|
|
19724
19754
|
);
|
|
19725
19755
|
}
|
|
@@ -19727,14 +19757,14 @@ function resolveBaselineAuto(currentFile, currentRun, args) {
|
|
|
19727
19757
|
const candidates = listBaselineCandidates(currentFile, args);
|
|
19728
19758
|
const comparable = [];
|
|
19729
19759
|
for (const candidate of candidates) {
|
|
19730
|
-
const run = tryNormalizeRunFromText(
|
|
19760
|
+
const run = tryNormalizeRunFromText(fs8.readFileSync(candidate, "utf8"), args);
|
|
19731
19761
|
if (run) {
|
|
19732
19762
|
comparable.push({ file: candidate, run });
|
|
19733
19763
|
}
|
|
19734
19764
|
}
|
|
19735
19765
|
if (comparable.length === 0) {
|
|
19736
19766
|
console.error(
|
|
19737
|
-
`Error: no compatible baseline files found in ${
|
|
19767
|
+
`Error: no compatible baseline files found in ${path8.resolve(args.baselineDir ?? path8.dirname(currentFile))}.`
|
|
19738
19768
|
);
|
|
19739
19769
|
process.exit(EXIT_USAGE);
|
|
19740
19770
|
}
|
|
@@ -19823,9 +19853,9 @@ async function main() {
|
|
|
19823
19853
|
process.exit(EXIT_SCHEMA_VALIDATION);
|
|
19824
19854
|
}
|
|
19825
19855
|
if (args.emitCanonical) {
|
|
19826
|
-
const outPath =
|
|
19827
|
-
|
|
19828
|
-
|
|
19856
|
+
const outPath = path8.resolve(args.emitCanonical);
|
|
19857
|
+
fs8.mkdirSync(path8.dirname(outPath), { recursive: true });
|
|
19858
|
+
fs8.writeFileSync(outPath, JSON.stringify(run, null, 2), "utf8");
|
|
19829
19859
|
}
|
|
19830
19860
|
try {
|
|
19831
19861
|
const result = await generateReports(run, args);
|
|
@@ -19882,9 +19912,9 @@ ${msg}`);
|
|
|
19882
19912
|
}
|
|
19883
19913
|
const run = data;
|
|
19884
19914
|
if (args.emitCanonical) {
|
|
19885
|
-
const outPath =
|
|
19886
|
-
|
|
19887
|
-
|
|
19915
|
+
const outPath = path8.resolve(args.emitCanonical);
|
|
19916
|
+
fs8.mkdirSync(path8.dirname(outPath), { recursive: true });
|
|
19917
|
+
fs8.writeFileSync(outPath, JSON.stringify(run, null, 2), "utf8");
|
|
19888
19918
|
}
|
|
19889
19919
|
try {
|
|
19890
19920
|
const result = await generateReports(run, args);
|
|
@@ -19940,9 +19970,9 @@ ${msg}`);
|
|
|
19940
19970
|
process.exit(EXIT_CANONICAL_VALIDATION);
|
|
19941
19971
|
}
|
|
19942
19972
|
if (args.emitCanonical) {
|
|
19943
|
-
const outPath =
|
|
19944
|
-
|
|
19945
|
-
|
|
19973
|
+
const outPath = path8.resolve(args.emitCanonical);
|
|
19974
|
+
fs8.mkdirSync(path8.dirname(outPath), { recursive: true });
|
|
19975
|
+
fs8.writeFileSync(outPath, JSON.stringify(canonical, null, 2), "utf8");
|
|
19946
19976
|
}
|
|
19947
19977
|
try {
|
|
19948
19978
|
const result = await generateReports(canonical, args, droppedMissingStory);
|
|
@@ -19967,9 +19997,9 @@ function runCustomFormatters(run, customRequested, formatters, args) {
|
|
|
19967
19997
|
const ext = formatter.fileExtension ?? formatName;
|
|
19968
19998
|
const baseName = args.outputName ?? "report";
|
|
19969
19999
|
const filename = args.outputNameTimestamp ? `${baseName}-${Math.floor(run.startedAtMs / 1e3)}.${ext}` : `${baseName}.${ext}`;
|
|
19970
|
-
const filepath =
|
|
19971
|
-
|
|
19972
|
-
|
|
20000
|
+
const filepath = path8.join(outputDir, filename);
|
|
20001
|
+
fs8.mkdirSync(outputDir, { recursive: true });
|
|
20002
|
+
fs8.writeFileSync(filepath, content, "utf8");
|
|
19973
20003
|
console.log(`Generated: ${filepath}`);
|
|
19974
20004
|
} catch (err) {
|
|
19975
20005
|
console.error(`Error running custom formatter "${formatName}": ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -20019,13 +20049,13 @@ async function dispatchNotifications(run, args) {
|
|
|
20019
20049
|
}
|
|
20020
20050
|
function runHistoryPipeline(run, args) {
|
|
20021
20051
|
if (!args.historyFile) return;
|
|
20022
|
-
const historyPath =
|
|
20052
|
+
const historyPath = path8.resolve(args.historyFile);
|
|
20023
20053
|
const store = loadHistory(
|
|
20024
20054
|
{ filePath: historyPath },
|
|
20025
20055
|
{
|
|
20026
20056
|
readFile: (p) => {
|
|
20027
20057
|
try {
|
|
20028
|
-
return
|
|
20058
|
+
return fs8.readFileSync(p, "utf8");
|
|
20029
20059
|
} catch {
|
|
20030
20060
|
return void 0;
|
|
20031
20061
|
}
|
|
@@ -20038,11 +20068,11 @@ function runHistoryPipeline(run, args) {
|
|
|
20038
20068
|
run,
|
|
20039
20069
|
maxRuns: args.maxHistoryRuns
|
|
20040
20070
|
});
|
|
20041
|
-
const dir =
|
|
20042
|
-
|
|
20071
|
+
const dir = path8.dirname(historyPath);
|
|
20072
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
20043
20073
|
saveHistory(
|
|
20044
20074
|
{ filePath: historyPath, store: updated },
|
|
20045
|
-
{ writeFile: (p, content) =>
|
|
20075
|
+
{ writeFile: (p, content) => fs8.writeFileSync(p, content, "utf8") }
|
|
20046
20076
|
);
|
|
20047
20077
|
let metricsCount = 0;
|
|
20048
20078
|
for (const testId of Object.keys(updated.tests)) {
|
|
@@ -20140,9 +20170,9 @@ function printResult(result, args, startMs, droppedMissingStory = 0) {
|
|
|
20140
20170
|
function printCompareResult(result, args, startMs) {
|
|
20141
20171
|
const durationMs = Date.now() - startMs;
|
|
20142
20172
|
if (result.prSummary && args.prSummaryFile) {
|
|
20143
|
-
const outputPath =
|
|
20144
|
-
|
|
20145
|
-
|
|
20173
|
+
const outputPath = path8.resolve(args.prSummaryFile);
|
|
20174
|
+
fs8.mkdirSync(path8.dirname(outputPath), { recursive: true });
|
|
20175
|
+
fs8.writeFileSync(outputPath, result.prSummary, "utf8");
|
|
20146
20176
|
}
|
|
20147
20177
|
if (args.jsonSummary) {
|
|
20148
20178
|
console.log(
|
|
@@ -20213,7 +20243,7 @@ Generate an API token at https://id.atlassian.com/manage-profile/security/api-to
|
|
|
20213
20243
|
console.error("Error: missing ADF file argument. Run with --help for usage.");
|
|
20214
20244
|
process.exit(EXIT_USAGE);
|
|
20215
20245
|
}
|
|
20216
|
-
if (!
|
|
20246
|
+
if (!fs8.existsSync(inputFile)) {
|
|
20217
20247
|
console.error(`Error: file not found: ${inputFile}`);
|
|
20218
20248
|
process.exit(EXIT_USAGE);
|
|
20219
20249
|
}
|
|
@@ -20241,7 +20271,7 @@ Generate an API token at https://id.atlassian.com/manage-profile/security/api-to
|
|
|
20241
20271
|
console.error("Error: --title is required when creating a new page");
|
|
20242
20272
|
process.exit(EXIT_USAGE);
|
|
20243
20273
|
}
|
|
20244
|
-
const adf =
|
|
20274
|
+
const adf = fs8.readFileSync(path8.resolve(inputFile), "utf8");
|
|
20245
20275
|
if (dryRun) {
|
|
20246
20276
|
console.log(
|
|
20247
20277
|
JSON.stringify(
|
|
@@ -20320,7 +20350,7 @@ Generate an API token at https://id.atlassian.com/manage-profile/security/api-to
|
|
|
20320
20350
|
console.error("Error: missing ADF file argument. Run with --help for usage.");
|
|
20321
20351
|
process.exit(EXIT_USAGE);
|
|
20322
20352
|
}
|
|
20323
|
-
if (!
|
|
20353
|
+
if (!fs8.existsSync(inputFile)) {
|
|
20324
20354
|
console.error(`Error: file not found: ${inputFile}`);
|
|
20325
20355
|
process.exit(EXIT_USAGE);
|
|
20326
20356
|
}
|
|
@@ -20347,7 +20377,7 @@ Generate an API token at https://id.atlassian.com/manage-profile/security/api-to
|
|
|
20347
20377
|
process.exit(EXIT_USAGE);
|
|
20348
20378
|
}
|
|
20349
20379
|
const mode = modeRaw;
|
|
20350
|
-
const adf =
|
|
20380
|
+
const adf = fs8.readFileSync(path8.resolve(inputFile), "utf8");
|
|
20351
20381
|
if (dryRun) {
|
|
20352
20382
|
console.log(
|
|
20353
20383
|
JSON.stringify(
|