executable-stories-formatters 0.7.12 → 0.7.14
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/adapters.cjs +9 -2
- package/dist/adapters.cjs.map +1 -1
- package/dist/adapters.d.cts +1 -1
- package/dist/adapters.d.ts +1 -1
- package/dist/adapters.js +9 -2
- package/dist/adapters.js.map +1 -1
- package/dist/cli.js +134 -11
- package/dist/cli.js.map +1 -1
- package/dist/{index-C0OOaaiK.d.cts → index-fqrm5-Xr.d.cts} +34 -24
- package/dist/{index-C0OOaaiK.d.ts → index-fqrm5-Xr.d.ts} +34 -24
- package/dist/index.cjs +143 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -9
- package/dist/index.d.ts +7 -9
- package/dist/index.js +143 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed CI provider and canonical CI info.
|
|
3
|
+
*
|
|
4
|
+
* RawCIInfo.name = legacy transport string (kept for backward compat + schema).
|
|
5
|
+
* CIInfo.displayName = canonical display name for downstream consumers.
|
|
6
|
+
*
|
|
7
|
+
* All downstream code (HTML meta, notifications, history) uses CIInfo via mappers.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
type CIProvider = "github" | "gitlab" | "circleci" | "jenkins" | "azure" | "buildkite" | "travis" | "unknown";
|
|
11
|
+
interface CIInfo {
|
|
12
|
+
provider: CIProvider;
|
|
13
|
+
displayName: string;
|
|
14
|
+
url?: string;
|
|
15
|
+
buildNumber?: string;
|
|
16
|
+
branch?: string;
|
|
17
|
+
commitSha?: string;
|
|
18
|
+
prNumber?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Convert RawCIInfo (legacy transport) to canonical CIInfo. */
|
|
21
|
+
declare function toCIInfo(raw?: RawCIInfo): CIInfo | undefined;
|
|
22
|
+
/** Convert canonical CIInfo back to RawCIInfo (for serialization). */
|
|
23
|
+
declare function toRawCIInfo(ci?: CIInfo): RawCIInfo | undefined;
|
|
24
|
+
|
|
1
25
|
/**
|
|
2
26
|
* OTel span types for trace waterfall rendering.
|
|
3
27
|
*
|
|
@@ -175,6 +199,7 @@ interface RawAttachment {
|
|
|
175
199
|
/** Raw step event from framework (if available) */
|
|
176
200
|
interface RawStepEvent {
|
|
177
201
|
index?: number;
|
|
202
|
+
stepId?: string;
|
|
178
203
|
title?: string;
|
|
179
204
|
status?: RawStatus;
|
|
180
205
|
durationMs?: number;
|
|
@@ -248,30 +273,6 @@ interface RawRun {
|
|
|
248
273
|
ci?: RawCIInfo;
|
|
249
274
|
}
|
|
250
275
|
|
|
251
|
-
/**
|
|
252
|
-
* Typed CI provider and canonical CI info.
|
|
253
|
-
*
|
|
254
|
-
* RawCIInfo.name = legacy transport string (kept for backward compat + schema).
|
|
255
|
-
* CIInfo.displayName = canonical display name for downstream consumers.
|
|
256
|
-
*
|
|
257
|
-
* All downstream code (HTML meta, notifications, history) uses CIInfo via mappers.
|
|
258
|
-
*/
|
|
259
|
-
|
|
260
|
-
type CIProvider = "github" | "gitlab" | "circleci" | "jenkins" | "azure" | "buildkite" | "travis" | "unknown";
|
|
261
|
-
interface CIInfo {
|
|
262
|
-
provider: CIProvider;
|
|
263
|
-
displayName: string;
|
|
264
|
-
url?: string;
|
|
265
|
-
buildNumber?: string;
|
|
266
|
-
branch?: string;
|
|
267
|
-
commitSha?: string;
|
|
268
|
-
prNumber?: string;
|
|
269
|
-
}
|
|
270
|
-
/** Convert RawCIInfo (legacy transport) to canonical CIInfo. */
|
|
271
|
-
declare function toCIInfo(raw?: RawCIInfo): CIInfo | undefined;
|
|
272
|
-
/** Convert canonical CIInfo back to RawCIInfo (for serialization). */
|
|
273
|
-
declare function toRawCIInfo(ci?: CIInfo): RawCIInfo | undefined;
|
|
274
|
-
|
|
275
276
|
/**
|
|
276
277
|
* Jest Adapter - Layer 1.
|
|
277
278
|
*
|
|
@@ -400,6 +401,15 @@ interface PlaywrightTestResult {
|
|
|
400
401
|
errors: PlaywrightError[];
|
|
401
402
|
attachments: PlaywrightAttachment[];
|
|
402
403
|
retry: number;
|
|
404
|
+
/** Optional step events if caller captures Playwright step timing. */
|
|
405
|
+
stepEvents?: Array<{
|
|
406
|
+
index?: number;
|
|
407
|
+
stepId?: string;
|
|
408
|
+
title?: string;
|
|
409
|
+
status?: RawStatus;
|
|
410
|
+
durationMs?: number;
|
|
411
|
+
errorMessage?: string;
|
|
412
|
+
}>;
|
|
403
413
|
}
|
|
404
414
|
/** Playwright test case annotation */
|
|
405
415
|
interface PlaywrightAnnotation {
|
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed CI provider and canonical CI info.
|
|
3
|
+
*
|
|
4
|
+
* RawCIInfo.name = legacy transport string (kept for backward compat + schema).
|
|
5
|
+
* CIInfo.displayName = canonical display name for downstream consumers.
|
|
6
|
+
*
|
|
7
|
+
* All downstream code (HTML meta, notifications, history) uses CIInfo via mappers.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
type CIProvider = "github" | "gitlab" | "circleci" | "jenkins" | "azure" | "buildkite" | "travis" | "unknown";
|
|
11
|
+
interface CIInfo {
|
|
12
|
+
provider: CIProvider;
|
|
13
|
+
displayName: string;
|
|
14
|
+
url?: string;
|
|
15
|
+
buildNumber?: string;
|
|
16
|
+
branch?: string;
|
|
17
|
+
commitSha?: string;
|
|
18
|
+
prNumber?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Convert RawCIInfo (legacy transport) to canonical CIInfo. */
|
|
21
|
+
declare function toCIInfo(raw?: RawCIInfo): CIInfo | undefined;
|
|
22
|
+
/** Convert canonical CIInfo back to RawCIInfo (for serialization). */
|
|
23
|
+
declare function toRawCIInfo(ci?: CIInfo): RawCIInfo | undefined;
|
|
24
|
+
|
|
1
25
|
/**
|
|
2
26
|
* OTel span types for trace waterfall rendering.
|
|
3
27
|
*
|
|
@@ -175,6 +199,7 @@ interface RawAttachment {
|
|
|
175
199
|
/** Raw step event from framework (if available) */
|
|
176
200
|
interface RawStepEvent {
|
|
177
201
|
index?: number;
|
|
202
|
+
stepId?: string;
|
|
178
203
|
title?: string;
|
|
179
204
|
status?: RawStatus;
|
|
180
205
|
durationMs?: number;
|
|
@@ -248,30 +273,6 @@ interface RawRun {
|
|
|
248
273
|
ci?: RawCIInfo;
|
|
249
274
|
}
|
|
250
275
|
|
|
251
|
-
/**
|
|
252
|
-
* Typed CI provider and canonical CI info.
|
|
253
|
-
*
|
|
254
|
-
* RawCIInfo.name = legacy transport string (kept for backward compat + schema).
|
|
255
|
-
* CIInfo.displayName = canonical display name for downstream consumers.
|
|
256
|
-
*
|
|
257
|
-
* All downstream code (HTML meta, notifications, history) uses CIInfo via mappers.
|
|
258
|
-
*/
|
|
259
|
-
|
|
260
|
-
type CIProvider = "github" | "gitlab" | "circleci" | "jenkins" | "azure" | "buildkite" | "travis" | "unknown";
|
|
261
|
-
interface CIInfo {
|
|
262
|
-
provider: CIProvider;
|
|
263
|
-
displayName: string;
|
|
264
|
-
url?: string;
|
|
265
|
-
buildNumber?: string;
|
|
266
|
-
branch?: string;
|
|
267
|
-
commitSha?: string;
|
|
268
|
-
prNumber?: string;
|
|
269
|
-
}
|
|
270
|
-
/** Convert RawCIInfo (legacy transport) to canonical CIInfo. */
|
|
271
|
-
declare function toCIInfo(raw?: RawCIInfo): CIInfo | undefined;
|
|
272
|
-
/** Convert canonical CIInfo back to RawCIInfo (for serialization). */
|
|
273
|
-
declare function toRawCIInfo(ci?: CIInfo): RawCIInfo | undefined;
|
|
274
|
-
|
|
275
276
|
/**
|
|
276
277
|
* Jest Adapter - Layer 1.
|
|
277
278
|
*
|
|
@@ -400,6 +401,15 @@ interface PlaywrightTestResult {
|
|
|
400
401
|
errors: PlaywrightError[];
|
|
401
402
|
attachments: PlaywrightAttachment[];
|
|
402
403
|
retry: number;
|
|
404
|
+
/** Optional step events if caller captures Playwright step timing. */
|
|
405
|
+
stepEvents?: Array<{
|
|
406
|
+
index?: number;
|
|
407
|
+
stepId?: string;
|
|
408
|
+
title?: string;
|
|
409
|
+
status?: RawStatus;
|
|
410
|
+
durationMs?: number;
|
|
411
|
+
errorMessage?: string;
|
|
412
|
+
}>;
|
|
403
413
|
}
|
|
404
414
|
/** Playwright test case annotation */
|
|
405
415
|
interface PlaywrightAnnotation {
|
package/dist/index.cjs
CHANGED
|
@@ -158,6 +158,7 @@ function deriveStepResults(steps, scenarioStatus, error) {
|
|
|
158
158
|
if (scenarioStatus === "passed") {
|
|
159
159
|
return steps.map((_, index) => ({
|
|
160
160
|
index,
|
|
161
|
+
stepId: steps[index].id,
|
|
161
162
|
status: "passed",
|
|
162
163
|
durationMs: 0
|
|
163
164
|
}));
|
|
@@ -165,6 +166,7 @@ function deriveStepResults(steps, scenarioStatus, error) {
|
|
|
165
166
|
if (scenarioStatus === "skipped" || scenarioStatus === "pending") {
|
|
166
167
|
return steps.map((_, index) => ({
|
|
167
168
|
index,
|
|
169
|
+
stepId: steps[index].id,
|
|
168
170
|
status: scenarioStatus,
|
|
169
171
|
durationMs: 0
|
|
170
172
|
}));
|
|
@@ -172,16 +174,17 @@ function deriveStepResults(steps, scenarioStatus, error) {
|
|
|
172
174
|
const failingIndex = findFailingStepIndex(steps, error);
|
|
173
175
|
return steps.map((_, index) => {
|
|
174
176
|
if (index < failingIndex) {
|
|
175
|
-
return { index, status: "passed", durationMs: 0 };
|
|
177
|
+
return { index, stepId: steps[index].id, status: "passed", durationMs: 0 };
|
|
176
178
|
} else if (index === failingIndex) {
|
|
177
179
|
return {
|
|
178
180
|
index,
|
|
181
|
+
stepId: steps[index].id,
|
|
179
182
|
status: "failed",
|
|
180
183
|
durationMs: 0,
|
|
181
184
|
errorMessage: error?.message
|
|
182
185
|
};
|
|
183
186
|
} else {
|
|
184
|
-
return { index, status: "skipped", durationMs: 0 };
|
|
187
|
+
return { index, stepId: steps[index].id, status: "skipped", durationMs: 0 };
|
|
185
188
|
}
|
|
186
189
|
});
|
|
187
190
|
}
|
|
@@ -203,18 +206,23 @@ function mergeStepResults(derived, events) {
|
|
|
203
206
|
return derived;
|
|
204
207
|
}
|
|
205
208
|
const actualByIndex = /* @__PURE__ */ new Map();
|
|
209
|
+
const actualByStepId = /* @__PURE__ */ new Map();
|
|
206
210
|
for (const event of events) {
|
|
207
211
|
if (event.index !== void 0) {
|
|
208
212
|
actualByIndex.set(event.index, event);
|
|
209
213
|
}
|
|
214
|
+
if (event.stepId) {
|
|
215
|
+
actualByStepId.set(event.stepId, event);
|
|
216
|
+
}
|
|
210
217
|
}
|
|
211
218
|
return derived.map((step) => {
|
|
212
|
-
const actual = actualByIndex.get(step.index);
|
|
219
|
+
const actual = (step.stepId ? actualByStepId.get(step.stepId) : void 0) ?? actualByIndex.get(step.index);
|
|
213
220
|
if (!actual) {
|
|
214
221
|
return step;
|
|
215
222
|
}
|
|
216
223
|
return {
|
|
217
224
|
index: step.index,
|
|
225
|
+
stepId: step.stepId ?? actual.stepId,
|
|
218
226
|
status: normalizeStepStatus(actual.status) ?? step.status,
|
|
219
227
|
durationMs: actual.durationMs ?? step.durationMs,
|
|
220
228
|
errorMessage: actual.errorMessage ?? step.errorMessage
|
|
@@ -348,6 +356,7 @@ function canonicalizeTestCase(raw, options, projectRoot) {
|
|
|
348
356
|
derivedSteps,
|
|
349
357
|
raw.stepEvents?.map((e) => ({
|
|
350
358
|
index: e.index,
|
|
359
|
+
stepId: e.stepId,
|
|
351
360
|
status: e.status,
|
|
352
361
|
durationMs: e.durationMs,
|
|
353
362
|
errorMessage: e.errorMessage
|
|
@@ -369,6 +378,7 @@ function canonicalizeTestCase(raw, options, projectRoot) {
|
|
|
369
378
|
sourceFile,
|
|
370
379
|
sourceLine: raw.sourceLine ?? 1,
|
|
371
380
|
status,
|
|
381
|
+
rawStatus: raw.status,
|
|
372
382
|
durationMs: raw.durationMs ?? 0,
|
|
373
383
|
errorMessage: raw.error?.message,
|
|
374
384
|
errorStack: raw.error?.stack,
|
|
@@ -736,19 +746,34 @@ ${doc.markdown}`,
|
|
|
736
746
|
}
|
|
737
747
|
};
|
|
738
748
|
}
|
|
739
|
-
case "
|
|
749
|
+
case "custom":
|
|
750
|
+
if (doc.type === "visual" && doc.data && typeof doc.data === "object") {
|
|
751
|
+
const data = doc.data;
|
|
752
|
+
const status = typeof data.status === "string" ? data.status : "unknown";
|
|
753
|
+
const lines = [`Visual Check (${status})`];
|
|
754
|
+
if (typeof data.baseline === "string") lines.push(`Baseline: ${data.baseline}`);
|
|
755
|
+
if (typeof data.actual === "string") lines.push(`Actual: ${data.actual}`);
|
|
756
|
+
if (typeof data.diff === "string") lines.push(`Diff: ${data.diff}`);
|
|
757
|
+
return {
|
|
758
|
+
doc_string: {
|
|
759
|
+
content: lines.join("\n"),
|
|
760
|
+
content_type: "text/plain",
|
|
761
|
+
line: 0
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
}
|
|
740
765
|
return {
|
|
741
766
|
doc_string: {
|
|
742
|
-
content: doc.
|
|
743
|
-
content_type: "
|
|
767
|
+
content: JSON.stringify(doc.data, null, 2),
|
|
768
|
+
content_type: "application/json",
|
|
744
769
|
line: 0
|
|
745
770
|
}
|
|
746
771
|
};
|
|
747
|
-
case "
|
|
772
|
+
case "tag":
|
|
748
773
|
return {
|
|
749
774
|
doc_string: {
|
|
750
|
-
content:
|
|
751
|
-
content_type: "
|
|
775
|
+
content: doc.names.map((n) => `@${n}`).join(" "),
|
|
776
|
+
content_type: "text/plain",
|
|
752
777
|
line: 0
|
|
753
778
|
}
|
|
754
779
|
};
|
|
@@ -2266,6 +2291,14 @@ body {
|
|
|
2266
2291
|
font-family: var(--font-mono);
|
|
2267
2292
|
}
|
|
2268
2293
|
|
|
2294
|
+
.outcome-tag {
|
|
2295
|
+
background: var(--status-fail-bg, color-mix(in srgb, var(--destructive, #ef4444) 12%, transparent));
|
|
2296
|
+
color: var(--destructive, #b91c1c);
|
|
2297
|
+
border-color: color-mix(in srgb, var(--destructive, #ef4444) 35%, transparent);
|
|
2298
|
+
text-transform: uppercase;
|
|
2299
|
+
letter-spacing: 0.04em;
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2269
2302
|
.scenario-duration {
|
|
2270
2303
|
font-size: 0.75rem;
|
|
2271
2304
|
color: var(--muted-foreground);
|
|
@@ -3029,6 +3062,63 @@ body {
|
|
|
3029
3062
|
opacity: 0.8;
|
|
3030
3063
|
}
|
|
3031
3064
|
|
|
3065
|
+
/* ============================================================================
|
|
3066
|
+
Documentation Entries - Visual Check
|
|
3067
|
+
============================================================================ */
|
|
3068
|
+
.doc-visual {
|
|
3069
|
+
margin-bottom: 0.5rem;
|
|
3070
|
+
padding: 0.75rem;
|
|
3071
|
+
border: 1px solid var(--border);
|
|
3072
|
+
border-radius: calc(var(--radius) - 2px);
|
|
3073
|
+
background: var(--muted, transparent);
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
.doc-visual:last-child {
|
|
3077
|
+
margin-bottom: 0;
|
|
3078
|
+
}
|
|
3079
|
+
|
|
3080
|
+
.doc-visual-header {
|
|
3081
|
+
font-size: 0.8125rem;
|
|
3082
|
+
font-weight: 600;
|
|
3083
|
+
margin-bottom: 0.5rem;
|
|
3084
|
+
display: flex;
|
|
3085
|
+
align-items: center;
|
|
3086
|
+
gap: 0.5rem;
|
|
3087
|
+
}
|
|
3088
|
+
|
|
3089
|
+
.doc-visual-status {
|
|
3090
|
+
font-size: 0.6875rem;
|
|
3091
|
+
font-family: var(--font-mono);
|
|
3092
|
+
font-weight: 500;
|
|
3093
|
+
padding: 0.125rem 0.5rem;
|
|
3094
|
+
border-radius: 9999px;
|
|
3095
|
+
background: var(--tag-bg);
|
|
3096
|
+
color: var(--tag-color);
|
|
3097
|
+
border: 1px solid var(--tag-border);
|
|
3098
|
+
text-transform: uppercase;
|
|
3099
|
+
letter-spacing: 0.04em;
|
|
3100
|
+
}
|
|
3101
|
+
|
|
3102
|
+
.doc-visual-grid {
|
|
3103
|
+
display: grid;
|
|
3104
|
+
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
3105
|
+
gap: 0.5rem;
|
|
3106
|
+
}
|
|
3107
|
+
|
|
3108
|
+
.doc-visual-item {
|
|
3109
|
+
display: flex;
|
|
3110
|
+
flex-direction: column;
|
|
3111
|
+
gap: 0.25rem;
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3114
|
+
.doc-visual-label {
|
|
3115
|
+
font-size: 0.6875rem;
|
|
3116
|
+
font-weight: 600;
|
|
3117
|
+
color: var(--muted-foreground);
|
|
3118
|
+
text-transform: uppercase;
|
|
3119
|
+
letter-spacing: 0.04em;
|
|
3120
|
+
}
|
|
3121
|
+
|
|
3032
3122
|
/* ============================================================================
|
|
3033
3123
|
Documentation Entries - Custom
|
|
3034
3124
|
============================================================================ */
|
|
@@ -13151,6 +13241,22 @@ function renderDocScreenshot(entry, deps) {
|
|
|
13151
13241
|
</div>`;
|
|
13152
13242
|
}
|
|
13153
13243
|
function renderDocCustom(entry, deps) {
|
|
13244
|
+
if (entry.type === "visual" && entry.data && typeof entry.data === "object") {
|
|
13245
|
+
const data = entry.data;
|
|
13246
|
+
const status = typeof data.status === "string" ? data.status : "unknown";
|
|
13247
|
+
const baseline = typeof data.baseline === "string" ? data.baseline : void 0;
|
|
13248
|
+
const actual = typeof data.actual === "string" ? data.actual : void 0;
|
|
13249
|
+
const diff = typeof data.diff === "string" ? data.diff : void 0;
|
|
13250
|
+
const maybeImg = (src, label) => src ? `<div class="doc-visual-item"><div class="doc-visual-label">${deps.escapeHtml(label ?? "")}</div><img src="${deps.escapeHtml(src)}" alt="${deps.escapeHtml(label ?? "visual image")}" class="doc-screenshot-img" /></div>` : "";
|
|
13251
|
+
return `<div class="doc-visual">
|
|
13252
|
+
<div class="doc-visual-header">Visual Check <span class="doc-visual-status">${deps.escapeHtml(status)}</span></div>
|
|
13253
|
+
<div class="doc-visual-grid">
|
|
13254
|
+
${maybeImg(baseline, "Baseline")}
|
|
13255
|
+
${maybeImg(actual, "Actual")}
|
|
13256
|
+
${maybeImg(diff, "Diff")}
|
|
13257
|
+
</div>
|
|
13258
|
+
</div>`;
|
|
13259
|
+
}
|
|
13154
13260
|
const dataStr = JSON.stringify(entry.data, null, 2);
|
|
13155
13261
|
return `<div class="doc-custom">
|
|
13156
13262
|
<div class="doc-custom-type">${deps.escapeHtml(entry.type)}</div>
|
|
@@ -13219,8 +13325,11 @@ function renderStep(step, stepResult, index, deps) {
|
|
|
13219
13325
|
</div>${stepDocs}`;
|
|
13220
13326
|
}
|
|
13221
13327
|
function renderSteps(args, deps) {
|
|
13328
|
+
const byStepId = new Map(
|
|
13329
|
+
args.stepResults.filter((sr) => typeof sr.stepId === "string" && sr.stepId.length > 0).map((sr) => [sr.stepId, sr])
|
|
13330
|
+
);
|
|
13222
13331
|
const stepsHtml = args.steps.map((step, index) => {
|
|
13223
|
-
const stepResult = args.stepResults.find((sr) => sr.index === index);
|
|
13332
|
+
const stepResult = (step.id ? byStepId.get(step.id) : void 0) ?? args.stepResults.find((sr) => sr.index === index);
|
|
13224
13333
|
return renderStep(step, stepResult, index, deps);
|
|
13225
13334
|
}).join("");
|
|
13226
13335
|
return `<div class="steps">${stepsHtml}</div>`;
|
|
@@ -13273,6 +13382,7 @@ function renderScenario(args, deps) {
|
|
|
13273
13382
|
const duration = tc.durationMs > 0 ? `${(tc.durationMs / 1e3).toFixed(2)}s` : "";
|
|
13274
13383
|
const tags = tc.tags.map((t) => `<span class="tag">${deps.escapeHtml(t)}</span>`).join("");
|
|
13275
13384
|
const tickets = (tc.story.tickets ?? []).map((t) => renderTicket(t, deps.ticketUrlTemplate, deps.escapeHtml)).join("");
|
|
13385
|
+
const outcomeBadge = tc.rawStatus === "timeout" || tc.rawStatus === "interrupted" ? `<span class="tag outcome-tag">${deps.escapeHtml(tc.rawStatus)}</span>` : "";
|
|
13276
13386
|
const otelMeta = tc.story.meta?.otel;
|
|
13277
13387
|
let traceBadge = "";
|
|
13278
13388
|
if (otelMeta?.traceId) {
|
|
@@ -13340,7 +13450,7 @@ function renderScenario(args, deps) {
|
|
|
13340
13450
|
<span class="status-icon ${statusClass}">${statusIcon2}</span>
|
|
13341
13451
|
<span class="scenario-name">${deps.escapeHtml(tc.story.scenario)}</span>
|
|
13342
13452
|
</div>
|
|
13343
|
-
<div class="scenario-meta">${tags}${tickets}${sourceLink}${traceBadge}${metricBadges}</div>
|
|
13453
|
+
<div class="scenario-meta">${tags}${tickets}${outcomeBadge}${sourceLink}${traceBadge}${metricBadges}</div>
|
|
13344
13454
|
</div>
|
|
13345
13455
|
<div class="scenario-actions">
|
|
13346
13456
|
<button class="copy-scenario-btn" onclick="copyScenarioAsMarkdown('scenario-${tc.id}')" aria-label="Copy scenario as markdown" title="Copy as Markdown"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button>
|
|
@@ -14344,6 +14454,9 @@ var MarkdownFormatter = class {
|
|
|
14344
14454
|
});
|
|
14345
14455
|
meta.push(`Tickets: ${ticketLinks.join(", ")}`);
|
|
14346
14456
|
}
|
|
14457
|
+
if (tc.rawStatus === "timeout" || tc.rawStatus === "interrupted") {
|
|
14458
|
+
meta.push(`Outcome: \`${tc.rawStatus}\``);
|
|
14459
|
+
}
|
|
14347
14460
|
const otelMeta = tc.story.meta?.otel;
|
|
14348
14461
|
if (otelMeta?.traceId) {
|
|
14349
14462
|
const traceTemplate = this.options.traceUrlTemplate;
|
|
@@ -14506,6 +14619,16 @@ var MarkdownFormatter = class {
|
|
|
14506
14619
|
lines.push(`${indent}`);
|
|
14507
14620
|
break;
|
|
14508
14621
|
case "custom":
|
|
14622
|
+
if (entry.type === "visual" && entry.data && typeof entry.data === "object") {
|
|
14623
|
+
const data = entry.data;
|
|
14624
|
+
const status = typeof data.status === "string" ? data.status : "unknown";
|
|
14625
|
+
lines.push(`${indent}**Visual Check** (${status})`);
|
|
14626
|
+
if (typeof data.baseline === "string") lines.push(`${indent}- Baseline: ${data.baseline}`);
|
|
14627
|
+
if (typeof data.actual === "string") lines.push(`${indent}- Actual: ${data.actual}`);
|
|
14628
|
+
if (typeof data.diff === "string") lines.push(`${indent}- Diff: ${data.diff}`);
|
|
14629
|
+
lines.push(`${indent}`);
|
|
14630
|
+
break;
|
|
14631
|
+
}
|
|
14509
14632
|
lines.push(`${indent}**[${entry.type}]**`);
|
|
14510
14633
|
lines.push(`${indent}`);
|
|
14511
14634
|
lines.push(`${indent}\`\`\`json`);
|
|
@@ -17157,6 +17280,14 @@ function adaptPlaywrightRun(testResults, options = {}) {
|
|
|
17157
17280
|
message: result.errors[0].message,
|
|
17158
17281
|
stack: result.errors[0].stack
|
|
17159
17282
|
} : void 0;
|
|
17283
|
+
const stepEvents = result.stepEvents?.length ? result.stepEvents : story.steps.map(
|
|
17284
|
+
(step, index) => step.durationMs !== void 0 ? {
|
|
17285
|
+
index,
|
|
17286
|
+
stepId: step.id,
|
|
17287
|
+
title: step.text,
|
|
17288
|
+
durationMs: step.durationMs
|
|
17289
|
+
} : void 0
|
|
17290
|
+
).filter((e) => e !== void 0);
|
|
17160
17291
|
testCases.push({
|
|
17161
17292
|
externalId: test.titlePath().join(" > "),
|
|
17162
17293
|
title: story.scenario,
|
|
@@ -17167,8 +17298,7 @@ function adaptPlaywrightRun(testResults, options = {}) {
|
|
|
17167
17298
|
status: mapPlaywrightStatus(result.status),
|
|
17168
17299
|
durationMs: result.duration,
|
|
17169
17300
|
error,
|
|
17170
|
-
stepEvents: void 0,
|
|
17171
|
-
// Playwright could provide step info, but we don't capture it yet
|
|
17301
|
+
stepEvents: stepEvents.length > 0 ? stepEvents : void 0,
|
|
17172
17302
|
attachments,
|
|
17173
17303
|
meta: {
|
|
17174
17304
|
playwrightStatus: result.status,
|