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/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import "fs";
|
|
3
|
-
import * as
|
|
3
|
+
import * as path8 from "path";
|
|
4
4
|
import * as fsPromises from "fs/promises";
|
|
5
5
|
|
|
6
6
|
// src/converters/acl/status.ts
|
|
@@ -653,6 +653,10 @@ ${doc.markdown}`,
|
|
|
653
653
|
}
|
|
654
654
|
};
|
|
655
655
|
|
|
656
|
+
// src/formatters/html/renderers/index.ts
|
|
657
|
+
import * as fs2 from "fs";
|
|
658
|
+
import * as path2 from "path";
|
|
659
|
+
|
|
656
660
|
// src/formatters/html/template.ts
|
|
657
661
|
var JS_THEME = `
|
|
658
662
|
// Theme management
|
|
@@ -12963,7 +12967,9 @@ function renderDocMermaid(entry, deps) {
|
|
|
12963
12967
|
}
|
|
12964
12968
|
function renderDocScreenshot(entry, deps) {
|
|
12965
12969
|
const alt = entry.alt ?? "Screenshot";
|
|
12966
|
-
const
|
|
12970
|
+
const embedEnabled = deps.embedScreenshots ?? true;
|
|
12971
|
+
const isRemote = /^(?:https?:|data:)/i.test(entry.path);
|
|
12972
|
+
const src = embedEnabled && !isRemote && deps.readScreenshot ? deps.readScreenshot(entry.path) ?? entry.path : entry.path;
|
|
12967
12973
|
return `<div class="doc-screenshot">
|
|
12968
12974
|
<img src="${deps.escapeHtml(src)}" alt="${deps.escapeHtml(alt)}" class="doc-screenshot-img" />
|
|
12969
12975
|
${entry.alt ? `<div class="doc-screenshot-caption">${deps.escapeHtml(entry.alt)}</div>` : ""}
|
|
@@ -13550,6 +13556,28 @@ function renderToc(args, deps) {
|
|
|
13550
13556
|
}
|
|
13551
13557
|
|
|
13552
13558
|
// src/formatters/html/renderers/index.ts
|
|
13559
|
+
var SCREENSHOT_MIME_BY_EXT = {
|
|
13560
|
+
png: "image/png",
|
|
13561
|
+
jpg: "image/jpeg",
|
|
13562
|
+
jpeg: "image/jpeg",
|
|
13563
|
+
gif: "image/gif",
|
|
13564
|
+
webp: "image/webp",
|
|
13565
|
+
svg: "image/svg+xml",
|
|
13566
|
+
avif: "image/avif",
|
|
13567
|
+
bmp: "image/bmp"
|
|
13568
|
+
};
|
|
13569
|
+
function readScreenshotAsDataUri(filePath) {
|
|
13570
|
+
try {
|
|
13571
|
+
const ext = path2.extname(filePath).slice(1).toLowerCase();
|
|
13572
|
+
const mime = SCREENSHOT_MIME_BY_EXT[ext];
|
|
13573
|
+
if (!mime) return void 0;
|
|
13574
|
+
if (!fs2.existsSync(filePath)) return void 0;
|
|
13575
|
+
const buf = fs2.readFileSync(filePath);
|
|
13576
|
+
return `data:${mime};base64,${buf.toString("base64")}`;
|
|
13577
|
+
} catch {
|
|
13578
|
+
return void 0;
|
|
13579
|
+
}
|
|
13580
|
+
}
|
|
13553
13581
|
function normalizeOptions(options = {}) {
|
|
13554
13582
|
return {
|
|
13555
13583
|
title: options.title ?? "Test Results",
|
|
@@ -13573,7 +13601,9 @@ function createHtmlFormatter(options = {}) {
|
|
|
13573
13601
|
escapeHtml,
|
|
13574
13602
|
syntaxHighlighting: opts.syntaxHighlighting,
|
|
13575
13603
|
markdownEnabled: opts.markdownEnabled,
|
|
13576
|
-
mermaidEnabled: opts.mermaidEnabled
|
|
13604
|
+
mermaidEnabled: opts.mermaidEnabled,
|
|
13605
|
+
embedScreenshots: opts.embedScreenshots,
|
|
13606
|
+
readScreenshot: (filePath) => readScreenshotAsDataUri(filePath)
|
|
13577
13607
|
};
|
|
13578
13608
|
const renderDocs = (docs, containerClass) => {
|
|
13579
13609
|
if (!docs || docs.length === 0) return "";
|
|
@@ -15002,8 +15032,8 @@ function extractDocAttachments(step) {
|
|
|
15002
15032
|
}
|
|
15003
15033
|
return attachments;
|
|
15004
15034
|
}
|
|
15005
|
-
function guessMediaType(
|
|
15006
|
-
const lower =
|
|
15035
|
+
function guessMediaType(path9) {
|
|
15036
|
+
const lower = path9.toLowerCase();
|
|
15007
15037
|
if (lower.endsWith(".png")) return "image/png";
|
|
15008
15038
|
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
|
|
15009
15039
|
if (lower.endsWith(".gif")) return "image/gif";
|
|
@@ -16047,8 +16077,8 @@ function selectTestCases(args, deps) {
|
|
|
16047
16077
|
}
|
|
16048
16078
|
|
|
16049
16079
|
// src/bundler/bundle-assets.ts
|
|
16050
|
-
import * as
|
|
16051
|
-
import * as
|
|
16080
|
+
import * as fs4 from "fs";
|
|
16081
|
+
import * as path4 from "path";
|
|
16052
16082
|
|
|
16053
16083
|
// src/bundler/scan-html-assets.ts
|
|
16054
16084
|
function scanHtmlAssets(html) {
|
|
@@ -16078,21 +16108,21 @@ function isLocalAssetRef(ref) {
|
|
|
16078
16108
|
}
|
|
16079
16109
|
|
|
16080
16110
|
// src/bundler/copy-asset.ts
|
|
16081
|
-
import * as
|
|
16082
|
-
import * as
|
|
16111
|
+
import * as fs3 from "fs";
|
|
16112
|
+
import * as path3 from "path";
|
|
16083
16113
|
import * as crypto from "crypto";
|
|
16084
16114
|
function copyAsset(sourcePath, assetsDir) {
|
|
16085
|
-
if (!
|
|
16086
|
-
|
|
16115
|
+
if (!fs3.existsSync(assetsDir)) {
|
|
16116
|
+
fs3.mkdirSync(assetsDir, { recursive: true });
|
|
16087
16117
|
}
|
|
16088
|
-
const content =
|
|
16118
|
+
const content = fs3.readFileSync(sourcePath);
|
|
16089
16119
|
const hash = crypto.createHash("sha256").update(content).digest("hex").slice(0, 8);
|
|
16090
|
-
const ext =
|
|
16091
|
-
const baseName = sanitize(
|
|
16120
|
+
const ext = path3.extname(sourcePath);
|
|
16121
|
+
const baseName = sanitize(path3.basename(sourcePath, ext));
|
|
16092
16122
|
const destName = `${baseName}-${hash}${ext}`;
|
|
16093
|
-
const destPath =
|
|
16094
|
-
if (!
|
|
16095
|
-
|
|
16123
|
+
const destPath = path3.join(assetsDir, destName);
|
|
16124
|
+
if (!fs3.existsSync(destPath)) {
|
|
16125
|
+
fs3.copyFileSync(sourcePath, destPath);
|
|
16096
16126
|
}
|
|
16097
16127
|
return `assets/${destName}`;
|
|
16098
16128
|
}
|
|
@@ -16102,15 +16132,15 @@ function sanitize(name) {
|
|
|
16102
16132
|
|
|
16103
16133
|
// src/bundler/bundle-assets.ts
|
|
16104
16134
|
function bundleAssets(htmlPath, options = {}) {
|
|
16105
|
-
const htmlDir =
|
|
16106
|
-
const assetsDir =
|
|
16107
|
-
let html =
|
|
16135
|
+
const htmlDir = path4.dirname(htmlPath);
|
|
16136
|
+
const assetsDir = path4.join(htmlDir, "assets");
|
|
16137
|
+
let html = fs4.readFileSync(htmlPath, "utf8");
|
|
16108
16138
|
const refs = scanHtmlAssets(html);
|
|
16109
16139
|
let copiedCount = 0;
|
|
16110
16140
|
const missing = [];
|
|
16111
16141
|
for (const ref of refs) {
|
|
16112
|
-
const absolutePath =
|
|
16113
|
-
if (!
|
|
16142
|
+
const absolutePath = path4.resolve(htmlDir, ref);
|
|
16143
|
+
if (!fs4.existsSync(absolutePath)) {
|
|
16114
16144
|
missing.push(ref);
|
|
16115
16145
|
continue;
|
|
16116
16146
|
}
|
|
@@ -16123,7 +16153,7 @@ function bundleAssets(htmlPath, options = {}) {
|
|
|
16123
16153
|
`Missing asset${missing.length > 1 ? "s" : ""}: ${missing.join(", ")}`
|
|
16124
16154
|
);
|
|
16125
16155
|
}
|
|
16126
|
-
|
|
16156
|
+
fs4.writeFileSync(htmlPath, html, "utf8");
|
|
16127
16157
|
return {
|
|
16128
16158
|
copiedCount,
|
|
16129
16159
|
missingCount: missing.length,
|
|
@@ -16606,15 +16636,15 @@ function groupBy7(items, keyFn) {
|
|
|
16606
16636
|
}
|
|
16607
16637
|
|
|
16608
16638
|
// src/formatters/astro-assets.ts
|
|
16609
|
-
import * as
|
|
16610
|
-
import * as
|
|
16639
|
+
import * as fs5 from "fs";
|
|
16640
|
+
import * as path5 from "path";
|
|
16611
16641
|
var SKIP_PREFIXES = ["http://", "https://", "data:", "#"];
|
|
16612
16642
|
function isLocalPath(src) {
|
|
16613
16643
|
const trimmed = src.trim();
|
|
16614
16644
|
if (SKIP_PREFIXES.some((prefix) => trimmed.startsWith(prefix))) {
|
|
16615
16645
|
return false;
|
|
16616
16646
|
}
|
|
16617
|
-
return !
|
|
16647
|
+
return !path5.posix.isAbsolute(trimmed) && !path5.win32.isAbsolute(trimmed);
|
|
16618
16648
|
}
|
|
16619
16649
|
function stripCodeContent(markdown) {
|
|
16620
16650
|
let result = markdown.replace(/^[ \t]*(`{3,}|~{3,})[^\n]*\n[\s\S]*?^[ \t]*\1\s*$/gm, "");
|
|
@@ -16708,8 +16738,8 @@ function copyMarkdownAssets(options) {
|
|
|
16708
16738
|
const pathMap = /* @__PURE__ */ new Map();
|
|
16709
16739
|
const missing = [];
|
|
16710
16740
|
for (const ref of refs) {
|
|
16711
|
-
const absPath =
|
|
16712
|
-
if (!
|
|
16741
|
+
const absPath = path5.resolve(markdownDir, ref);
|
|
16742
|
+
if (!fs5.existsSync(absPath)) {
|
|
16713
16743
|
if (!allowMissing) {
|
|
16714
16744
|
throw new Error(`Asset not found: ${absPath}`);
|
|
16715
16745
|
}
|
|
@@ -17725,27 +17755,27 @@ function pickleStepArgumentToDocs(ps) {
|
|
|
17725
17755
|
}
|
|
17726
17756
|
|
|
17727
17757
|
// src/utils/git-info.ts
|
|
17728
|
-
import * as
|
|
17729
|
-
import * as
|
|
17758
|
+
import * as fs6 from "fs";
|
|
17759
|
+
import * as path6 from "path";
|
|
17730
17760
|
function readGitSha(cwd = process.cwd()) {
|
|
17731
17761
|
const envSha = process.env.GITHUB_SHA || process.env.GIT_COMMIT || process.env.CI_COMMIT_SHA;
|
|
17732
17762
|
if (envSha) return envSha;
|
|
17733
17763
|
const gitDir = findGitDir(cwd);
|
|
17734
17764
|
if (!gitDir) return void 0;
|
|
17735
17765
|
try {
|
|
17736
|
-
const headPath =
|
|
17737
|
-
const head =
|
|
17766
|
+
const headPath = path6.join(gitDir, "HEAD");
|
|
17767
|
+
const head = fs6.readFileSync(headPath, "utf8").trim();
|
|
17738
17768
|
if (!head.startsWith("ref:")) {
|
|
17739
17769
|
return head;
|
|
17740
17770
|
}
|
|
17741
17771
|
const refPath = head.replace("ref:", "").trim();
|
|
17742
|
-
const refFile =
|
|
17743
|
-
if (
|
|
17744
|
-
return
|
|
17772
|
+
const refFile = path6.join(gitDir, refPath);
|
|
17773
|
+
if (fs6.existsSync(refFile)) {
|
|
17774
|
+
return fs6.readFileSync(refFile, "utf8").trim();
|
|
17745
17775
|
}
|
|
17746
|
-
const packedRefs =
|
|
17747
|
-
if (
|
|
17748
|
-
const content =
|
|
17776
|
+
const packedRefs = path6.join(gitDir, "packed-refs");
|
|
17777
|
+
if (fs6.existsSync(packedRefs)) {
|
|
17778
|
+
const content = fs6.readFileSync(packedRefs, "utf8");
|
|
17749
17779
|
for (const line of content.split("\n")) {
|
|
17750
17780
|
if (!line || line.startsWith("#") || line.startsWith("^")) continue;
|
|
17751
17781
|
const [sha, ref] = line.split(" ");
|
|
@@ -17760,19 +17790,19 @@ function readGitSha(cwd = process.cwd()) {
|
|
|
17760
17790
|
function findGitDir(start) {
|
|
17761
17791
|
let current = start;
|
|
17762
17792
|
while (true) {
|
|
17763
|
-
const candidate =
|
|
17764
|
-
if (
|
|
17765
|
-
const stat =
|
|
17793
|
+
const candidate = path6.join(current, ".git");
|
|
17794
|
+
if (fs6.existsSync(candidate)) {
|
|
17795
|
+
const stat = fs6.statSync(candidate);
|
|
17766
17796
|
if (stat.isFile()) {
|
|
17767
|
-
const content =
|
|
17797
|
+
const content = fs6.readFileSync(candidate, "utf8").trim();
|
|
17768
17798
|
const match = content.match(/^gitdir: (.+)$/);
|
|
17769
17799
|
if (match) {
|
|
17770
|
-
return
|
|
17800
|
+
return path6.resolve(current, match[1]);
|
|
17771
17801
|
}
|
|
17772
17802
|
}
|
|
17773
17803
|
return candidate;
|
|
17774
17804
|
}
|
|
17775
|
-
const parent =
|
|
17805
|
+
const parent = path6.dirname(current);
|
|
17776
17806
|
if (parent === current) return void 0;
|
|
17777
17807
|
current = parent;
|
|
17778
17808
|
}
|
|
@@ -17783,8 +17813,8 @@ function readBranchName(cwd = process.cwd()) {
|
|
|
17783
17813
|
const gitDir = findGitDir(cwd);
|
|
17784
17814
|
if (!gitDir) return void 0;
|
|
17785
17815
|
try {
|
|
17786
|
-
const headPath =
|
|
17787
|
-
const head =
|
|
17816
|
+
const headPath = path6.join(gitDir, "HEAD");
|
|
17817
|
+
const head = fs6.readFileSync(headPath, "utf8").trim();
|
|
17788
17818
|
if (head.startsWith("ref:")) {
|
|
17789
17819
|
const refPath = head.replace("ref:", "").trim();
|
|
17790
17820
|
const match = refPath.match(/^refs\/heads\/(.+)$/);
|
|
@@ -17821,8 +17851,8 @@ function nanosecondsToMs(ns) {
|
|
|
17821
17851
|
}
|
|
17822
17852
|
|
|
17823
17853
|
// src/utils/metadata.ts
|
|
17824
|
-
import * as
|
|
17825
|
-
import * as
|
|
17854
|
+
import * as fs7 from "fs";
|
|
17855
|
+
import * as path7 from "path";
|
|
17826
17856
|
var versionCache = /* @__PURE__ */ new Map();
|
|
17827
17857
|
function readPackageVersion(root) {
|
|
17828
17858
|
if (versionCache.has(root)) {
|
|
@@ -17833,18 +17863,18 @@ function readPackageVersion(root) {
|
|
|
17833
17863
|
return version;
|
|
17834
17864
|
}
|
|
17835
17865
|
function findPackageVersion(startDir) {
|
|
17836
|
-
let current =
|
|
17866
|
+
let current = path7.resolve(startDir);
|
|
17837
17867
|
while (true) {
|
|
17838
|
-
const pkgPath =
|
|
17868
|
+
const pkgPath = path7.join(current, "package.json");
|
|
17839
17869
|
try {
|
|
17840
|
-
if (
|
|
17841
|
-
const raw =
|
|
17870
|
+
if (fs7.existsSync(pkgPath)) {
|
|
17871
|
+
const raw = fs7.readFileSync(pkgPath, "utf8");
|
|
17842
17872
|
const parsed = JSON.parse(raw);
|
|
17843
17873
|
return parsed.version;
|
|
17844
17874
|
}
|
|
17845
17875
|
} catch {
|
|
17846
17876
|
}
|
|
17847
|
-
const parent =
|
|
17877
|
+
const parent = path7.dirname(current);
|
|
17848
17878
|
if (parent === current) {
|
|
17849
17879
|
return void 0;
|
|
17850
17880
|
}
|
|
@@ -18834,11 +18864,11 @@ function computeOutputPath(sourceFile, format, mode, colocatedStyle, baseOutputD
|
|
|
18834
18864
|
const ext = FORMAT_EXTENSIONS[format];
|
|
18835
18865
|
const effectiveName = outputName + (outputNameSuffix ?? "");
|
|
18836
18866
|
if (mode === "aggregated") {
|
|
18837
|
-
return toPosix(
|
|
18867
|
+
return toPosix(path8.join(baseOutputDir, `${effectiveName}${ext}`));
|
|
18838
18868
|
}
|
|
18839
18869
|
const normalizedSource = toPosix(sourceFile);
|
|
18840
|
-
const dirOfSource =
|
|
18841
|
-
let baseName =
|
|
18870
|
+
const dirOfSource = path8.posix.dirname(normalizedSource);
|
|
18871
|
+
let baseName = path8.posix.basename(normalizedSource);
|
|
18842
18872
|
for (const testExt of TEST_EXTENSIONS) {
|
|
18843
18873
|
if (baseName.endsWith(testExt)) {
|
|
18844
18874
|
baseName = baseName.slice(0, -testExt.length);
|
|
@@ -18847,9 +18877,9 @@ function computeOutputPath(sourceFile, format, mode, colocatedStyle, baseOutputD
|
|
|
18847
18877
|
}
|
|
18848
18878
|
const fileName = `${baseName}.${effectiveName}${ext}`;
|
|
18849
18879
|
if (colocatedStyle === "adjacent") {
|
|
18850
|
-
return toPosix(
|
|
18880
|
+
return toPosix(path8.posix.join(dirOfSource, fileName));
|
|
18851
18881
|
}
|
|
18852
|
-
return toPosix(
|
|
18882
|
+
return toPosix(path8.posix.join(baseOutputDir, dirOfSource, fileName));
|
|
18853
18883
|
}
|
|
18854
18884
|
function groupTestCasesByOutput(testCases, format, options, logger, outputNameSuffix) {
|
|
18855
18885
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -19047,8 +19077,8 @@ var ReportGenerator = class {
|
|
|
19047
19077
|
if (astroPaths) {
|
|
19048
19078
|
for (const mdPath of astroPaths) {
|
|
19049
19079
|
const content = await fsPromises.readFile(mdPath, "utf8");
|
|
19050
|
-
const mdDir =
|
|
19051
|
-
const assetsDir =
|
|
19080
|
+
const mdDir = path8.dirname(mdPath);
|
|
19081
|
+
const assetsDir = path8.resolve(this.options.astro.assetsDir);
|
|
19052
19082
|
const result = copyMarkdownAssets({
|
|
19053
19083
|
markdown: content,
|
|
19054
19084
|
markdownDir: mdDir,
|
|
@@ -19079,9 +19109,9 @@ var ReportGenerator = class {
|
|
|
19079
19109
|
if (groups.size === 0 && this.options.output.mode === "aggregated") {
|
|
19080
19110
|
const ext = FORMAT_EXTENSIONS[format];
|
|
19081
19111
|
const effectiveName = this.options.outputName + (outputNameSuffix ?? "");
|
|
19082
|
-
const outputPath = toPosix(
|
|
19112
|
+
const outputPath = toPosix(path8.join(this.options.outputDir, `${effectiveName}${ext}`));
|
|
19083
19113
|
const content = await this.formatContent(run, format);
|
|
19084
|
-
const dir =
|
|
19114
|
+
const dir = path8.dirname(outputPath);
|
|
19085
19115
|
await fsPromises.mkdir(dir, { recursive: true });
|
|
19086
19116
|
await this.deps.writeFile(outputPath, content);
|
|
19087
19117
|
return [outputPath];
|
|
@@ -19093,7 +19123,7 @@ var ReportGenerator = class {
|
|
|
19093
19123
|
testCases
|
|
19094
19124
|
};
|
|
19095
19125
|
const content = await this.formatContent(groupRun, format);
|
|
19096
|
-
const dir =
|
|
19126
|
+
const dir = path8.dirname(outputPath);
|
|
19097
19127
|
await fsPromises.mkdir(dir, { recursive: true });
|
|
19098
19128
|
await this.deps.writeFile(outputPath, content);
|
|
19099
19129
|
writtenPaths.push(outputPath);
|
|
@@ -19216,7 +19246,7 @@ async function generateRunComparison(args) {
|
|
|
19216
19246
|
await fsPromises.mkdir(outputDir, { recursive: true });
|
|
19217
19247
|
for (const format of args.formats) {
|
|
19218
19248
|
const ext = format === "html" ? ".html" : ".md";
|
|
19219
|
-
const outputPath = toPosix(
|
|
19249
|
+
const outputPath = toPosix(path8.join(outputDir, `${outputName}${ext}`));
|
|
19220
19250
|
const content = format === "html" ? new RunDiffHtmlFormatter({ title: args.title }).format(diff) : new RunDiffMarkdownFormatter({ title: args.title }).format(diff);
|
|
19221
19251
|
await fsPromises.writeFile(outputPath, content, "utf8");
|
|
19222
19252
|
files.push(outputPath);
|