executable-stories-formatters 0.2.0 → 0.3.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/README.md +1 -1
- package/dist/cli.js +79 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +109 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -1
- package/dist/index.d.ts +27 -1
- package/dist/index.js +106 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schemas/README.md +7 -12
package/dist/index.d.cts
CHANGED
|
@@ -280,6 +280,8 @@ interface MarkdownFormatterOptions {
|
|
|
280
280
|
permalinkBaseUrl?: string;
|
|
281
281
|
/** URL template for ticket links. Use {ticket} as placeholder. E.g., "https://jira.example.com/browse/{ticket}" */
|
|
282
282
|
ticketUrlTemplate?: string;
|
|
283
|
+
/** URL template for trace links. Use {traceId} as placeholder. E.g., "https://grafana.example.com/explore?traceId={traceId}" */
|
|
284
|
+
traceUrlTemplate?: string;
|
|
283
285
|
/** Include source links when permalinkBaseUrl is set. Default: true */
|
|
284
286
|
includeSourceLinks?: boolean;
|
|
285
287
|
/** Custom renderers for doc entries */
|
|
@@ -350,6 +352,7 @@ interface ResolvedFormatterOptions {
|
|
|
350
352
|
includeSummaryTable: boolean;
|
|
351
353
|
permalinkBaseUrl?: string;
|
|
352
354
|
ticketUrlTemplate?: string;
|
|
355
|
+
traceUrlTemplate?: string;
|
|
353
356
|
includeSourceLinks: boolean;
|
|
354
357
|
customRenderers?: MarkdownRenderers;
|
|
355
358
|
};
|
|
@@ -871,6 +874,8 @@ interface MarkdownOptions {
|
|
|
871
874
|
permalinkBaseUrl?: string;
|
|
872
875
|
/** URL template for ticket links. Use {ticket} as placeholder */
|
|
873
876
|
ticketUrlTemplate?: string;
|
|
877
|
+
/** URL template for trace links. Use {traceId} as placeholder. E.g. "https://grafana.example.com/explore?traceId={traceId}" */
|
|
878
|
+
traceUrlTemplate?: string;
|
|
874
879
|
/** Include source links when permalinkBaseUrl is set. Default: true */
|
|
875
880
|
includeSourceLinks?: boolean;
|
|
876
881
|
/** Custom renderers for doc entries */
|
|
@@ -1376,6 +1381,27 @@ declare function clearVersionCache(): void;
|
|
|
1376
1381
|
*/
|
|
1377
1382
|
declare function detectCI(env?: Record<string, string | undefined>): RawCIInfo | undefined;
|
|
1378
1383
|
|
|
1384
|
+
/**
|
|
1385
|
+
* OTel trace context detection.
|
|
1386
|
+
*
|
|
1387
|
+
* Detects an active OpenTelemetry span via `@opentelemetry/api` (optional peer).
|
|
1388
|
+
* Uses `createRequire` so the import is lazy and never breaks if OTel isn't installed.
|
|
1389
|
+
*/
|
|
1390
|
+
interface OtelTraceContext {
|
|
1391
|
+
traceId: string;
|
|
1392
|
+
spanId: string;
|
|
1393
|
+
}
|
|
1394
|
+
/**
|
|
1395
|
+
* Try to read trace context from the currently-active OTel span.
|
|
1396
|
+
* Returns `undefined` when `@opentelemetry/api` is not installed or no span is active.
|
|
1397
|
+
*/
|
|
1398
|
+
declare function tryGetActiveOtelContext(): OtelTraceContext | undefined;
|
|
1399
|
+
/**
|
|
1400
|
+
* Replace `{traceId}` in a URL template.
|
|
1401
|
+
* Returns `undefined` when no template is provided.
|
|
1402
|
+
*/
|
|
1403
|
+
declare function resolveTraceUrl(template: string | undefined, traceId: string): string | undefined;
|
|
1404
|
+
|
|
1379
1405
|
/**
|
|
1380
1406
|
* @executable-stories/formatters
|
|
1381
1407
|
*
|
|
@@ -1465,4 +1491,4 @@ declare function normalizeVitestResults(testModules: Parameters<typeof adaptVite
|
|
|
1465
1491
|
*/
|
|
1466
1492
|
declare function normalizePlaywrightResults(testResults: Parameters<typeof adaptPlaywrightRun>[0], adapterOptions?: Parameters<typeof adaptPlaywrightRun>[1], canonicalizeOptions?: CanonicalizeOptions): TestRunResult;
|
|
1467
1493
|
|
|
1468
|
-
export { type Attachment, type CIInfo, type CanonicalizeOptions, type ColocatedStyle, type CoverageSummary, CucumberHtmlFormatter, type CucumberHtmlOptions, CucumberJsonFormatter, type CucumberJsonOptions, CucumberMessagesFormatter, type CucumberMessagesOptions, DocEntry, type FormatterOptions, type GenerateArgs, type GenerateDeps, type GenerateResult, HtmlFormatter, type HtmlOptions, type IJsonDataTable, type IJsonDocString, type IJsonEmbedding, type IJsonFeature, type IJsonScenario, type IJsonStep, type IJsonStepArgument, type IJsonStepResult, type IJsonTableRow, type IJsonTag, JUnitFormatter, type JUnitOptions, type Logger, MarkdownFormatter, type MarkdownFormatterOptions, type MarkdownOptions, type MarkdownRenderers, type OutputConfig, type OutputFormat, type OutputMode, type OutputRule, RawAttachment, RawCIInfo, RawRun, RawStatus, ReportGenerator, type ResolvedFormatterOptions, type StepResult, StoryMeta, StoryStep, type TestCaseAttempt, type TestCaseResult, type TestRunResult, type TestStatus, type ValidationResult, type WriteFile, adaptJestRun, adaptPlaywrightRun, adaptVitestRun, assertValidRun, canonicalizeRun, clearVersionCache, createReportGenerator, deriveStepResults, detectCI, findGitDir, formatDuration, generateRunId, generateTestCaseId, mergeStepResults, msToNanoseconds, nanosecondsToMs, normalizeJestResults, normalizePlaywrightResults, normalizeStatus, normalizeVitestResults, parseEnvelopes, parseNdjson, readBranchName, readGitSha, readPackageVersion, resolveAttachment, resolveAttachments, slugify, validateCanonicalRun };
|
|
1494
|
+
export { type Attachment, type CIInfo, type CanonicalizeOptions, type ColocatedStyle, type CoverageSummary, CucumberHtmlFormatter, type CucumberHtmlOptions, CucumberJsonFormatter, type CucumberJsonOptions, CucumberMessagesFormatter, type CucumberMessagesOptions, DocEntry, type FormatterOptions, type GenerateArgs, type GenerateDeps, type GenerateResult, HtmlFormatter, type HtmlOptions, type IJsonDataTable, type IJsonDocString, type IJsonEmbedding, type IJsonFeature, type IJsonScenario, type IJsonStep, type IJsonStepArgument, type IJsonStepResult, type IJsonTableRow, type IJsonTag, JUnitFormatter, type JUnitOptions, type Logger, MarkdownFormatter, type MarkdownFormatterOptions, type MarkdownOptions, type MarkdownRenderers, type OtelTraceContext, type OutputConfig, type OutputFormat, type OutputMode, type OutputRule, RawAttachment, RawCIInfo, RawRun, RawStatus, ReportGenerator, type ResolvedFormatterOptions, type StepResult, StoryMeta, StoryStep, type TestCaseAttempt, type TestCaseResult, type TestRunResult, type TestStatus, type ValidationResult, type WriteFile, adaptJestRun, adaptPlaywrightRun, adaptVitestRun, assertValidRun, canonicalizeRun, clearVersionCache, createReportGenerator, deriveStepResults, detectCI, findGitDir, formatDuration, generateRunId, generateTestCaseId, mergeStepResults, msToNanoseconds, nanosecondsToMs, normalizeJestResults, normalizePlaywrightResults, normalizeStatus, normalizeVitestResults, parseEnvelopes, parseNdjson, readBranchName, readGitSha, readPackageVersion, resolveAttachment, resolveAttachments, resolveTraceUrl, slugify, tryGetActiveOtelContext, validateCanonicalRun };
|
package/dist/index.d.ts
CHANGED
|
@@ -280,6 +280,8 @@ interface MarkdownFormatterOptions {
|
|
|
280
280
|
permalinkBaseUrl?: string;
|
|
281
281
|
/** URL template for ticket links. Use {ticket} as placeholder. E.g., "https://jira.example.com/browse/{ticket}" */
|
|
282
282
|
ticketUrlTemplate?: string;
|
|
283
|
+
/** URL template for trace links. Use {traceId} as placeholder. E.g., "https://grafana.example.com/explore?traceId={traceId}" */
|
|
284
|
+
traceUrlTemplate?: string;
|
|
283
285
|
/** Include source links when permalinkBaseUrl is set. Default: true */
|
|
284
286
|
includeSourceLinks?: boolean;
|
|
285
287
|
/** Custom renderers for doc entries */
|
|
@@ -350,6 +352,7 @@ interface ResolvedFormatterOptions {
|
|
|
350
352
|
includeSummaryTable: boolean;
|
|
351
353
|
permalinkBaseUrl?: string;
|
|
352
354
|
ticketUrlTemplate?: string;
|
|
355
|
+
traceUrlTemplate?: string;
|
|
353
356
|
includeSourceLinks: boolean;
|
|
354
357
|
customRenderers?: MarkdownRenderers;
|
|
355
358
|
};
|
|
@@ -871,6 +874,8 @@ interface MarkdownOptions {
|
|
|
871
874
|
permalinkBaseUrl?: string;
|
|
872
875
|
/** URL template for ticket links. Use {ticket} as placeholder */
|
|
873
876
|
ticketUrlTemplate?: string;
|
|
877
|
+
/** URL template for trace links. Use {traceId} as placeholder. E.g. "https://grafana.example.com/explore?traceId={traceId}" */
|
|
878
|
+
traceUrlTemplate?: string;
|
|
874
879
|
/** Include source links when permalinkBaseUrl is set. Default: true */
|
|
875
880
|
includeSourceLinks?: boolean;
|
|
876
881
|
/** Custom renderers for doc entries */
|
|
@@ -1376,6 +1381,27 @@ declare function clearVersionCache(): void;
|
|
|
1376
1381
|
*/
|
|
1377
1382
|
declare function detectCI(env?: Record<string, string | undefined>): RawCIInfo | undefined;
|
|
1378
1383
|
|
|
1384
|
+
/**
|
|
1385
|
+
* OTel trace context detection.
|
|
1386
|
+
*
|
|
1387
|
+
* Detects an active OpenTelemetry span via `@opentelemetry/api` (optional peer).
|
|
1388
|
+
* Uses `createRequire` so the import is lazy and never breaks if OTel isn't installed.
|
|
1389
|
+
*/
|
|
1390
|
+
interface OtelTraceContext {
|
|
1391
|
+
traceId: string;
|
|
1392
|
+
spanId: string;
|
|
1393
|
+
}
|
|
1394
|
+
/**
|
|
1395
|
+
* Try to read trace context from the currently-active OTel span.
|
|
1396
|
+
* Returns `undefined` when `@opentelemetry/api` is not installed or no span is active.
|
|
1397
|
+
*/
|
|
1398
|
+
declare function tryGetActiveOtelContext(): OtelTraceContext | undefined;
|
|
1399
|
+
/**
|
|
1400
|
+
* Replace `{traceId}` in a URL template.
|
|
1401
|
+
* Returns `undefined` when no template is provided.
|
|
1402
|
+
*/
|
|
1403
|
+
declare function resolveTraceUrl(template: string | undefined, traceId: string): string | undefined;
|
|
1404
|
+
|
|
1379
1405
|
/**
|
|
1380
1406
|
* @executable-stories/formatters
|
|
1381
1407
|
*
|
|
@@ -1465,4 +1491,4 @@ declare function normalizeVitestResults(testModules: Parameters<typeof adaptVite
|
|
|
1465
1491
|
*/
|
|
1466
1492
|
declare function normalizePlaywrightResults(testResults: Parameters<typeof adaptPlaywrightRun>[0], adapterOptions?: Parameters<typeof adaptPlaywrightRun>[1], canonicalizeOptions?: CanonicalizeOptions): TestRunResult;
|
|
1467
1493
|
|
|
1468
|
-
export { type Attachment, type CIInfo, type CanonicalizeOptions, type ColocatedStyle, type CoverageSummary, CucumberHtmlFormatter, type CucumberHtmlOptions, CucumberJsonFormatter, type CucumberJsonOptions, CucumberMessagesFormatter, type CucumberMessagesOptions, DocEntry, type FormatterOptions, type GenerateArgs, type GenerateDeps, type GenerateResult, HtmlFormatter, type HtmlOptions, type IJsonDataTable, type IJsonDocString, type IJsonEmbedding, type IJsonFeature, type IJsonScenario, type IJsonStep, type IJsonStepArgument, type IJsonStepResult, type IJsonTableRow, type IJsonTag, JUnitFormatter, type JUnitOptions, type Logger, MarkdownFormatter, type MarkdownFormatterOptions, type MarkdownOptions, type MarkdownRenderers, type OutputConfig, type OutputFormat, type OutputMode, type OutputRule, RawAttachment, RawCIInfo, RawRun, RawStatus, ReportGenerator, type ResolvedFormatterOptions, type StepResult, StoryMeta, StoryStep, type TestCaseAttempt, type TestCaseResult, type TestRunResult, type TestStatus, type ValidationResult, type WriteFile, adaptJestRun, adaptPlaywrightRun, adaptVitestRun, assertValidRun, canonicalizeRun, clearVersionCache, createReportGenerator, deriveStepResults, detectCI, findGitDir, formatDuration, generateRunId, generateTestCaseId, mergeStepResults, msToNanoseconds, nanosecondsToMs, normalizeJestResults, normalizePlaywrightResults, normalizeStatus, normalizeVitestResults, parseEnvelopes, parseNdjson, readBranchName, readGitSha, readPackageVersion, resolveAttachment, resolveAttachments, slugify, validateCanonicalRun };
|
|
1494
|
+
export { type Attachment, type CIInfo, type CanonicalizeOptions, type ColocatedStyle, type CoverageSummary, CucumberHtmlFormatter, type CucumberHtmlOptions, CucumberJsonFormatter, type CucumberJsonOptions, CucumberMessagesFormatter, type CucumberMessagesOptions, DocEntry, type FormatterOptions, type GenerateArgs, type GenerateDeps, type GenerateResult, HtmlFormatter, type HtmlOptions, type IJsonDataTable, type IJsonDocString, type IJsonEmbedding, type IJsonFeature, type IJsonScenario, type IJsonStep, type IJsonStepArgument, type IJsonStepResult, type IJsonTableRow, type IJsonTag, JUnitFormatter, type JUnitOptions, type Logger, MarkdownFormatter, type MarkdownFormatterOptions, type MarkdownOptions, type MarkdownRenderers, type OtelTraceContext, type OutputConfig, type OutputFormat, type OutputMode, type OutputRule, RawAttachment, RawCIInfo, RawRun, RawStatus, ReportGenerator, type ResolvedFormatterOptions, type StepResult, StoryMeta, StoryStep, type TestCaseAttempt, type TestCaseResult, type TestRunResult, type TestStatus, type ValidationResult, type WriteFile, adaptJestRun, adaptPlaywrightRun, adaptVitestRun, assertValidRun, canonicalizeRun, clearVersionCache, createReportGenerator, deriveStepResults, detectCI, findGitDir, formatDuration, generateRunId, generateTestCaseId, mergeStepResults, msToNanoseconds, nanosecondsToMs, normalizeJestResults, normalizePlaywrightResults, normalizeStatus, normalizeVitestResults, parseEnvelopes, parseNdjson, readBranchName, readGitSha, readPackageVersion, resolveAttachment, resolveAttachments, resolveTraceUrl, slugify, tryGetActiveOtelContext, validateCanonicalRun };
|
package/dist/index.js
CHANGED
|
@@ -883,6 +883,18 @@ function initCollapse() {
|
|
|
883
883
|
}
|
|
884
884
|
});
|
|
885
885
|
});
|
|
886
|
+
|
|
887
|
+
document.querySelectorAll('.trace-view-header').forEach(header => {
|
|
888
|
+
header.addEventListener('click', () => {
|
|
889
|
+
toggleCollapse(header, header.closest('.trace-view'));
|
|
890
|
+
});
|
|
891
|
+
header.addEventListener('keydown', (e) => {
|
|
892
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
893
|
+
e.preventDefault();
|
|
894
|
+
toggleCollapse(header, header.closest('.trace-view'));
|
|
895
|
+
}
|
|
896
|
+
});
|
|
897
|
+
});
|
|
886
898
|
}
|
|
887
899
|
|
|
888
900
|
function expandAll() {
|
|
@@ -1086,6 +1098,7 @@ var CSS_STYLES = `
|
|
|
1086
1098
|
--tag-bg: hsl(145 55% 95%);
|
|
1087
1099
|
--tag-color: hsl(145 63% 30%);
|
|
1088
1100
|
--tag-border: hsl(145 55% 85%);
|
|
1101
|
+
--step-param-color: hsl(220 70% 50%);
|
|
1089
1102
|
|
|
1090
1103
|
/* Accordion/Collapsible styling */
|
|
1091
1104
|
--accordion-header-hover: hsl(0 0% 98%);
|
|
@@ -1144,6 +1157,7 @@ var CSS_STYLES = `
|
|
|
1144
1157
|
--tag-bg: hsl(145 35% 14%);
|
|
1145
1158
|
--tag-color: hsl(145 63% 60%);
|
|
1146
1159
|
--tag-border: hsl(145 35% 22%);
|
|
1160
|
+
--step-param-color: hsl(220 70% 70%);
|
|
1147
1161
|
|
|
1148
1162
|
/* Accordion/Collapsible styling */
|
|
1149
1163
|
--accordion-header-hover: hsl(0 0% 11%);
|
|
@@ -1192,6 +1206,7 @@ var CSS_STYLES = `
|
|
|
1192
1206
|
--tag-bg: hsl(145 35% 14%);
|
|
1193
1207
|
--tag-color: hsl(145 63% 60%);
|
|
1194
1208
|
--tag-border: hsl(145 35% 22%);
|
|
1209
|
+
--step-param-color: hsl(220 70% 70%);
|
|
1195
1210
|
--accordion-header-hover: hsl(0 0% 11%);
|
|
1196
1211
|
--accordion-content-bg: hsl(0 0% 7%);
|
|
1197
1212
|
}
|
|
@@ -1737,6 +1752,12 @@ body {
|
|
|
1737
1752
|
color: var(--foreground);
|
|
1738
1753
|
}
|
|
1739
1754
|
|
|
1755
|
+
.step-param {
|
|
1756
|
+
font-style: italic;
|
|
1757
|
+
font-weight: 500;
|
|
1758
|
+
color: var(--step-param-color);
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1740
1761
|
.step-duration {
|
|
1741
1762
|
color: var(--muted-foreground);
|
|
1742
1763
|
font-size: 0.6875rem;
|
|
@@ -2413,6 +2434,7 @@ body {
|
|
|
2413
2434
|
font-family: inherit;
|
|
2414
2435
|
background: none;
|
|
2415
2436
|
}
|
|
2437
|
+
|
|
2416
2438
|
`;
|
|
2417
2439
|
|
|
2418
2440
|
// src/formatters/html/renderers/status.ts
|
|
@@ -2657,10 +2679,11 @@ function renderStep(step, stepResult, index, deps) {
|
|
|
2657
2679
|
const isContinuation = CONTINUATION_KEYWORDS.includes(keywordTrimmed);
|
|
2658
2680
|
const stepClass = isContinuation ? "step continuation" : "step";
|
|
2659
2681
|
const stepDocs = deps.renderDocs(step.docs, "step-docs");
|
|
2682
|
+
const textHtml = deps.highlightStepParams ? deps.highlightStepParams(step.text) : deps.escapeHtml(step.text);
|
|
2660
2683
|
return `<div class="${stepClass}">
|
|
2661
2684
|
<span class="step-status ${statusClass}">${statusIcon}</span>
|
|
2662
2685
|
<span class="step-keyword">${deps.escapeHtml(step.keyword)}</span>
|
|
2663
|
-
<span class="step-text">${
|
|
2686
|
+
<span class="step-text">${textHtml}</span>
|
|
2664
2687
|
<span class="step-duration">${duration}</span>
|
|
2665
2688
|
</div>${stepDocs}`;
|
|
2666
2689
|
}
|
|
@@ -2672,6 +2695,30 @@ function renderSteps(args, deps) {
|
|
|
2672
2695
|
return `<div class="steps">${stepsHtml}</div>`;
|
|
2673
2696
|
}
|
|
2674
2697
|
|
|
2698
|
+
// src/formatters/html/renderers/step-params.ts
|
|
2699
|
+
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.\-])\d+(?:\.\d+)?(?![\w.\-])/g;
|
|
2700
|
+
function highlightStepParams(text, deps) {
|
|
2701
|
+
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
2702
|
+
if (matches.length === 0) {
|
|
2703
|
+
return deps.escapeHtml(text);
|
|
2704
|
+
}
|
|
2705
|
+
let result = "";
|
|
2706
|
+
let lastIndex = 0;
|
|
2707
|
+
for (const match of matches) {
|
|
2708
|
+
const matchStart = match.index;
|
|
2709
|
+
const matchEnd = matchStart + match[0].length;
|
|
2710
|
+
if (matchStart > lastIndex) {
|
|
2711
|
+
result += deps.escapeHtml(text.slice(lastIndex, matchStart));
|
|
2712
|
+
}
|
|
2713
|
+
result += `<span class="step-param">${deps.escapeHtml(match[0])}</span>`;
|
|
2714
|
+
lastIndex = matchEnd;
|
|
2715
|
+
}
|
|
2716
|
+
if (lastIndex < text.length) {
|
|
2717
|
+
result += deps.escapeHtml(text.slice(lastIndex));
|
|
2718
|
+
}
|
|
2719
|
+
return result;
|
|
2720
|
+
}
|
|
2721
|
+
|
|
2675
2722
|
// src/formatters/html/renderers/scenario.ts
|
|
2676
2723
|
function renderScenario(args, deps) {
|
|
2677
2724
|
const { tc } = args;
|
|
@@ -2679,6 +2726,19 @@ function renderScenario(args, deps) {
|
|
|
2679
2726
|
const statusClass = `status-${tc.status}`;
|
|
2680
2727
|
const duration = tc.durationMs > 0 ? `${(tc.durationMs / 1e3).toFixed(2)}s` : "";
|
|
2681
2728
|
const tags = tc.tags.map((t) => `<span class="tag">${deps.escapeHtml(t)}</span>`).join("");
|
|
2729
|
+
const otelMeta = tc.story.meta?.otel;
|
|
2730
|
+
let traceBadge = "";
|
|
2731
|
+
if (otelMeta?.traceId) {
|
|
2732
|
+
const shortId = otelMeta.traceId.slice(0, 16);
|
|
2733
|
+
const traceLink = tc.story.docs?.find(
|
|
2734
|
+
(d) => d.kind === "link" && d.label === "View Trace"
|
|
2735
|
+
);
|
|
2736
|
+
if (traceLink) {
|
|
2737
|
+
traceBadge = `<a class="tag trace-tag" href="${deps.escapeHtml(traceLink.url)}" title="${deps.escapeHtml(otelMeta.traceId)}" target="_blank" rel="noopener">${deps.escapeHtml(shortId)}\u2026</a>`;
|
|
2738
|
+
} else {
|
|
2739
|
+
traceBadge = `<span class="tag trace-tag" title="${deps.escapeHtml(otelMeta.traceId)}">${deps.escapeHtml(shortId)}\u2026</span>`;
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2682
2742
|
const storyDocs = deps.renderDocs(tc.story.docs, "story-docs");
|
|
2683
2743
|
const steps = deps.renderSteps(
|
|
2684
2744
|
{ steps: tc.story.steps, stepResults: tc.stepResults },
|
|
@@ -2709,7 +2769,7 @@ function renderScenario(args, deps) {
|
|
|
2709
2769
|
<span class="status-icon ${statusClass}">${statusIcon}</span>
|
|
2710
2770
|
<span class="scenario-name">${deps.escapeHtml(tc.story.scenario)}</span>
|
|
2711
2771
|
</div>
|
|
2712
|
-
<div class="scenario-meta">${tags}</div>
|
|
2772
|
+
<div class="scenario-meta">${tags}${traceBadge}</div>
|
|
2713
2773
|
</div>
|
|
2714
2774
|
<span class="scenario-duration">${duration}</span>
|
|
2715
2775
|
</div>
|
|
@@ -2843,7 +2903,8 @@ function createHtmlFormatter(options = {}) {
|
|
|
2843
2903
|
const stepsDeps = {
|
|
2844
2904
|
escapeHtml,
|
|
2845
2905
|
getStatusIcon,
|
|
2846
|
-
renderDocs
|
|
2906
|
+
renderDocs,
|
|
2907
|
+
highlightStepParams: (text) => highlightStepParams(text, { escapeHtml })
|
|
2847
2908
|
};
|
|
2848
2909
|
const scenarioDeps = {
|
|
2849
2910
|
escapeHtml,
|
|
@@ -3145,6 +3206,7 @@ var MarkdownFormatter = class {
|
|
|
3145
3206
|
includeSummaryTable: options.includeSummaryTable ?? false,
|
|
3146
3207
|
permalinkBaseUrl: options.permalinkBaseUrl,
|
|
3147
3208
|
ticketUrlTemplate: options.ticketUrlTemplate,
|
|
3209
|
+
traceUrlTemplate: options.traceUrlTemplate,
|
|
3148
3210
|
includeSourceLinks: options.includeSourceLinks ?? true,
|
|
3149
3211
|
customRenderers: options.customRenderers
|
|
3150
3212
|
};
|
|
@@ -3367,6 +3429,18 @@ var MarkdownFormatter = class {
|
|
|
3367
3429
|
meta.push(`Tickets: ${tc.story.tickets.map((t) => `\`${t}\``).join(", ")}`);
|
|
3368
3430
|
}
|
|
3369
3431
|
}
|
|
3432
|
+
const otelMeta = tc.story.meta?.otel;
|
|
3433
|
+
if (otelMeta?.traceId) {
|
|
3434
|
+
const traceTemplate = this.options.traceUrlTemplate;
|
|
3435
|
+
if (traceTemplate) {
|
|
3436
|
+
const url = traceTemplate.replace(/\{traceId\}/g, otelMeta.traceId);
|
|
3437
|
+
meta.push(
|
|
3438
|
+
`Trace: [${otelMeta.traceId.slice(0, 16)}\u2026](${url})`
|
|
3439
|
+
);
|
|
3440
|
+
} else {
|
|
3441
|
+
meta.push(`Trace: \`${otelMeta.traceId}\``);
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3370
3444
|
if (meta.length > 0) {
|
|
3371
3445
|
lines.push(meta.join(" | "));
|
|
3372
3446
|
}
|
|
@@ -5309,6 +5383,31 @@ function detectCI4(env = process.env) {
|
|
|
5309
5383
|
return void 0;
|
|
5310
5384
|
}
|
|
5311
5385
|
|
|
5386
|
+
// src/utils/otel-detect.ts
|
|
5387
|
+
import { createRequire } from "module";
|
|
5388
|
+
function getRequire() {
|
|
5389
|
+
const url = import.meta.url ?? (typeof __filename !== "undefined" ? `file://${__filename}` : void 0);
|
|
5390
|
+
if (!url) throw new Error("Cannot determine module URL");
|
|
5391
|
+
return createRequire(url);
|
|
5392
|
+
}
|
|
5393
|
+
function tryGetActiveOtelContext() {
|
|
5394
|
+
try {
|
|
5395
|
+
const api = getRequire()("@opentelemetry/api");
|
|
5396
|
+
const span = api.trace?.getActiveSpan?.();
|
|
5397
|
+
if (!span) return void 0;
|
|
5398
|
+
const ctx = span.spanContext?.();
|
|
5399
|
+
if (!ctx?.traceId || ctx.traceId === "00000000000000000000000000000000")
|
|
5400
|
+
return void 0;
|
|
5401
|
+
return { traceId: ctx.traceId, spanId: ctx.spanId };
|
|
5402
|
+
} catch {
|
|
5403
|
+
return void 0;
|
|
5404
|
+
}
|
|
5405
|
+
}
|
|
5406
|
+
function resolveTraceUrl(template, traceId) {
|
|
5407
|
+
if (!template) return void 0;
|
|
5408
|
+
return template.replace(/\{traceId\}/g, traceId);
|
|
5409
|
+
}
|
|
5410
|
+
|
|
5312
5411
|
// src/index.ts
|
|
5313
5412
|
var FORMAT_EXTENSIONS = {
|
|
5314
5413
|
markdown: ".md",
|
|
@@ -5499,6 +5598,7 @@ var ReportGenerator = class {
|
|
|
5499
5598
|
includeSummaryTable: options.markdown?.includeSummaryTable ?? false,
|
|
5500
5599
|
permalinkBaseUrl: options.markdown?.permalinkBaseUrl,
|
|
5501
5600
|
ticketUrlTemplate: options.markdown?.ticketUrlTemplate,
|
|
5601
|
+
traceUrlTemplate: options.markdown?.traceUrlTemplate,
|
|
5502
5602
|
includeSourceLinks: options.markdown?.includeSourceLinks ?? true,
|
|
5503
5603
|
customRenderers: options.markdown?.customRenderers
|
|
5504
5604
|
}
|
|
@@ -5624,6 +5724,7 @@ var ReportGenerator = class {
|
|
|
5624
5724
|
includeSummaryTable: this.options.markdown.includeSummaryTable,
|
|
5625
5725
|
permalinkBaseUrl: this.options.markdown.permalinkBaseUrl,
|
|
5626
5726
|
ticketUrlTemplate: this.options.markdown.ticketUrlTemplate,
|
|
5727
|
+
traceUrlTemplate: this.options.markdown.traceUrlTemplate,
|
|
5627
5728
|
includeSourceLinks: this.options.markdown.includeSourceLinks,
|
|
5628
5729
|
customRenderers: this.options.markdown.customRenderers
|
|
5629
5730
|
});
|
|
@@ -5685,7 +5786,9 @@ export {
|
|
|
5685
5786
|
readPackageVersion,
|
|
5686
5787
|
resolveAttachment,
|
|
5687
5788
|
resolveAttachments,
|
|
5789
|
+
resolveTraceUrl,
|
|
5688
5790
|
slugify,
|
|
5791
|
+
tryGetActiveOtelContext,
|
|
5689
5792
|
validateCanonicalRun
|
|
5690
5793
|
};
|
|
5691
5794
|
//# sourceMappingURL=index.js.map
|