executable-stories-react 0.11.0 → 0.13.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/dist/index.cjs +414 -464
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +313 -361
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +1779 -1340
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +32 -32
- package/dist/interactive.d.ts +32 -32
- package/dist/interactive.js +1694 -1246
- package/dist/interactive.js.map +1 -1
- package/dist/parse.cjs +34 -147
- package/dist/parse.cjs.map +1 -1
- package/dist/parse.js +34 -147
- package/dist/parse.js.map +1 -1
- package/dist/report-island.global.js +64 -54
- package/dist/ssr.cjs +331 -260
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.js +250 -176
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +2 -2
- package/package.json +24 -23
package/dist/index.cjs
CHANGED
|
@@ -84,6 +84,7 @@ __export(src_exports, {
|
|
|
84
84
|
parseStoryReport: () => parseStoryReport,
|
|
85
85
|
prUrl: () => prUrl,
|
|
86
86
|
reportLastRunMs: () => reportLastRunMs,
|
|
87
|
+
scenarioLastRunMs: () => scenarioLastRunMs,
|
|
87
88
|
storyReportSchema: () => storyReportSchema,
|
|
88
89
|
useBuiltinRenderers: () => useBuiltinRenderers,
|
|
89
90
|
useCustomRenderers: () => useCustomRenderers,
|
|
@@ -380,23 +381,45 @@ function useReport() {
|
|
|
380
381
|
// src/components/ReportScenario.tsx
|
|
381
382
|
var import_duration3 = require("executable-stories-core/utils/duration");
|
|
382
383
|
|
|
384
|
+
// src/lib/step-params.tsx
|
|
385
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
386
|
+
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
387
|
+
function highlightStepParams(text) {
|
|
388
|
+
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
389
|
+
if (matches.length === 0) return text;
|
|
390
|
+
const nodes = [];
|
|
391
|
+
let lastIndex = 0;
|
|
392
|
+
matches.forEach((match, i) => {
|
|
393
|
+
const start = match.index;
|
|
394
|
+
const end = start + match[0].length;
|
|
395
|
+
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
396
|
+
nodes.push(
|
|
397
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
398
|
+
);
|
|
399
|
+
lastIndex = end;
|
|
400
|
+
});
|
|
401
|
+
if (lastIndex < text.length) nodes.push(text.slice(lastIndex));
|
|
402
|
+
return nodes;
|
|
403
|
+
}
|
|
404
|
+
|
|
383
405
|
// src/components/ReportSteps.tsx
|
|
406
|
+
var import_assertive_steps = require("executable-stories-core/utils/assertive-steps");
|
|
384
407
|
var import_duration = require("executable-stories-core/utils/duration");
|
|
385
408
|
|
|
386
409
|
// src/components/doc/DocNote.tsx
|
|
387
|
-
var
|
|
410
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
388
411
|
function DocNote({ entry }) {
|
|
389
|
-
return /* @__PURE__ */ (0,
|
|
412
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
|
|
390
413
|
}
|
|
391
414
|
|
|
392
415
|
// src/components/doc/DocTag.tsx
|
|
393
|
-
var
|
|
416
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
394
417
|
function DocTag({ entry }) {
|
|
395
|
-
return /* @__PURE__ */ (0,
|
|
418
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "my-2 flex flex-wrap gap-1.5", "aria-label": "Tags", children: entry.names.map((n) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Badge, { variant: "tag", children: n }) }, n)) });
|
|
396
419
|
}
|
|
397
420
|
|
|
398
421
|
// src/components/doc/DocKv.tsx
|
|
399
|
-
var
|
|
422
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
400
423
|
function formatValue(value) {
|
|
401
424
|
if (value === null) return "null";
|
|
402
425
|
if (typeof value === "string") return value;
|
|
@@ -408,9 +431,9 @@ function formatValue(value) {
|
|
|
408
431
|
}
|
|
409
432
|
}
|
|
410
433
|
function DocKv({ entry }) {
|
|
411
|
-
return /* @__PURE__ */ (0,
|
|
412
|
-
/* @__PURE__ */ (0,
|
|
413
|
-
/* @__PURE__ */ (0,
|
|
434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
|
|
435
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dt", { className: "font-semibold text-muted-foreground", children: entry.label }),
|
|
436
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dd", { className: "font-mono text-foreground", children: formatValue(entry.value) })
|
|
414
437
|
] });
|
|
415
438
|
}
|
|
416
439
|
|
|
@@ -428,37 +451,37 @@ function useBuiltinRenderers() {
|
|
|
428
451
|
}
|
|
429
452
|
|
|
430
453
|
// src/components/doc/DocCode.tsx
|
|
431
|
-
var
|
|
454
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
432
455
|
function CodeFigure({ label, children }) {
|
|
433
|
-
return /* @__PURE__ */ (0,
|
|
434
|
-
label ? /* @__PURE__ */ (0,
|
|
435
|
-
/* @__PURE__ */ (0,
|
|
456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("figure", { className: "my-3", children: [
|
|
457
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: label }) : null,
|
|
458
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3", children })
|
|
436
459
|
] });
|
|
437
460
|
}
|
|
438
461
|
function DocCode({ entry }) {
|
|
439
462
|
const renderers = useBuiltinRenderers();
|
|
440
463
|
if (renderers.code) {
|
|
441
|
-
return /* @__PURE__ */ (0,
|
|
464
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: renderers.code(entry) });
|
|
442
465
|
}
|
|
443
|
-
return /* @__PURE__ */ (0,
|
|
466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CodeFigure, { label: entry.label, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
444
467
|
}
|
|
445
468
|
|
|
446
469
|
// src/components/doc/DocTable.tsx
|
|
447
|
-
var
|
|
470
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
448
471
|
function DocTable({ entry }) {
|
|
449
|
-
return /* @__PURE__ */ (0,
|
|
450
|
-
entry.label ? /* @__PURE__ */ (0,
|
|
451
|
-
/* @__PURE__ */ (0,
|
|
452
|
-
/* @__PURE__ */ (0,
|
|
453
|
-
/* @__PURE__ */ (0,
|
|
472
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("figure", { className: "my-3", children: [
|
|
473
|
+
entry.label ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.label }) : null,
|
|
474
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("table", { className: "w-full border-collapse text-sm", children: [
|
|
475
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tr", { className: "bg-muted/50", children: entry.columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: c }, c)) }) }),
|
|
476
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tbody", { children: entry.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tr", { children: row.map((cell, j) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: cell }, j)) }, i)) })
|
|
454
477
|
] }) })
|
|
455
478
|
] });
|
|
456
479
|
}
|
|
457
480
|
|
|
458
481
|
// src/components/doc/DocLink.tsx
|
|
459
|
-
var
|
|
482
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
460
483
|
function DocLink({ entry }) {
|
|
461
|
-
return /* @__PURE__ */ (0,
|
|
484
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
462
485
|
"a",
|
|
463
486
|
{
|
|
464
487
|
className: "text-sm font-medium text-primary underline underline-offset-2 hover:no-underline",
|
|
@@ -492,16 +515,16 @@ function neutralizeUrl(value) {
|
|
|
492
515
|
}
|
|
493
516
|
|
|
494
517
|
// src/components/doc/DocSection.tsx
|
|
495
|
-
var
|
|
518
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
496
519
|
function DocSection({ entry }) {
|
|
497
520
|
const renderers = useBuiltinRenderers();
|
|
498
521
|
if (renderers.section) {
|
|
499
|
-
return /* @__PURE__ */ (0,
|
|
522
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: renderers.section(entry) });
|
|
500
523
|
}
|
|
501
524
|
const html = safeMarkdownHtml(entry.markdown);
|
|
502
|
-
return /* @__PURE__ */ (0,
|
|
503
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
504
|
-
/* @__PURE__ */ (0,
|
|
525
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("section", { className: "my-3 text-sm", "aria-label": entry.title, children: [
|
|
526
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h4", { className: "mb-1 font-semibold text-foreground", children: entry.title }) : null,
|
|
527
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
505
528
|
"div",
|
|
506
529
|
{
|
|
507
530
|
className: "es-doc-prose prose prose-sm max-w-none",
|
|
@@ -512,11 +535,11 @@ function DocSection({ entry }) {
|
|
|
512
535
|
}
|
|
513
536
|
|
|
514
537
|
// src/components/doc/DocMermaid.tsx
|
|
515
|
-
var
|
|
538
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
516
539
|
function MermaidSource({ entry, ref }) {
|
|
517
|
-
return /* @__PURE__ */ (0,
|
|
518
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
519
|
-
/* @__PURE__ */ (0,
|
|
540
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("figure", { ref, className: "my-3", "aria-label": entry.title ?? "Diagram", children: [
|
|
541
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
542
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
520
543
|
"pre",
|
|
521
544
|
{
|
|
522
545
|
"data-mermaid": true,
|
|
@@ -530,24 +553,24 @@ function MermaidSource({ entry, ref }) {
|
|
|
530
553
|
function DocMermaid({ entry }) {
|
|
531
554
|
const renderers = useBuiltinRenderers();
|
|
532
555
|
if (renderers.mermaid) {
|
|
533
|
-
return /* @__PURE__ */ (0,
|
|
556
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children: renderers.mermaid(entry) });
|
|
534
557
|
}
|
|
535
|
-
return /* @__PURE__ */ (0,
|
|
558
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MermaidSource, { entry });
|
|
536
559
|
}
|
|
537
560
|
|
|
538
561
|
// src/components/doc/DocScreenshot.tsx
|
|
539
|
-
var
|
|
562
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
540
563
|
function DocScreenshot({ entry }) {
|
|
541
564
|
const src = (0, import_url.isLocalFsPath)(entry.path) ? void 0 : (0, import_url.safeImageUrl)(entry.path);
|
|
542
565
|
if (!src) {
|
|
543
|
-
return /* @__PURE__ */ (0,
|
|
544
|
-
/* @__PURE__ */ (0,
|
|
545
|
-
/* @__PURE__ */ (0,
|
|
546
|
-
entry.alt ? /* @__PURE__ */ (0,
|
|
566
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
|
|
567
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "font-medium", children: "Screenshot unavailable" }),
|
|
568
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
569
|
+
entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.alt }) : null
|
|
547
570
|
] });
|
|
548
571
|
}
|
|
549
|
-
return /* @__PURE__ */ (0,
|
|
550
|
-
/* @__PURE__ */ (0,
|
|
572
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "my-3", children: [
|
|
573
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
551
574
|
"img",
|
|
552
575
|
{
|
|
553
576
|
src,
|
|
@@ -556,24 +579,24 @@ function DocScreenshot({ entry }) {
|
|
|
556
579
|
className: "max-w-full rounded-md border border-border"
|
|
557
580
|
}
|
|
558
581
|
),
|
|
559
|
-
entry.alt ? /* @__PURE__ */ (0,
|
|
582
|
+
entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { className: "mt-1.5 text-xs text-muted-foreground", children: entry.alt }) : null
|
|
560
583
|
] });
|
|
561
584
|
}
|
|
562
585
|
|
|
563
586
|
// src/components/doc/DocVideo.tsx
|
|
564
|
-
var
|
|
587
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
565
588
|
function DocVideo({ entry }) {
|
|
566
589
|
if ((0, import_url.isLocalFsPath)(entry.path)) {
|
|
567
|
-
return /* @__PURE__ */ (0,
|
|
568
|
-
/* @__PURE__ */ (0,
|
|
569
|
-
/* @__PURE__ */ (0,
|
|
570
|
-
entry.caption ? /* @__PURE__ */ (0,
|
|
590
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
|
|
591
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "font-medium", children: "Video unavailable" }),
|
|
592
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
593
|
+
entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.caption }) : null
|
|
571
594
|
] });
|
|
572
595
|
}
|
|
573
596
|
const src = (0, import_url.safeUrl)(entry.path);
|
|
574
597
|
const poster = (0, import_url.safeUrl)(entry.poster);
|
|
575
|
-
return /* @__PURE__ */ (0,
|
|
576
|
-
/* @__PURE__ */ (0,
|
|
598
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("figure", { className: "my-3", children: [
|
|
599
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
577
600
|
"video",
|
|
578
601
|
{
|
|
579
602
|
controls: true,
|
|
@@ -583,21 +606,21 @@ function DocVideo({ entry }) {
|
|
|
583
606
|
className: "max-w-full rounded-md border border-border"
|
|
584
607
|
}
|
|
585
608
|
),
|
|
586
|
-
entry.caption ? /* @__PURE__ */ (0,
|
|
609
|
+
entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: entry.caption }) : null
|
|
587
610
|
] });
|
|
588
611
|
}
|
|
589
612
|
|
|
590
613
|
// src/components/doc/DocHtml.tsx
|
|
591
|
-
var
|
|
614
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
592
615
|
function DocHtml({ entry }) {
|
|
593
616
|
const height = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
594
617
|
const title = entry.title ?? "Embedded HTML";
|
|
595
618
|
const safeHref = (0, import_url.safeUrl)(entry.url ?? entry.path);
|
|
596
619
|
const frameProps = entry.content !== void 0 ? { srcDoc: entry.content } : { src: safeHref ?? "" };
|
|
597
|
-
return /* @__PURE__ */ (0,
|
|
598
|
-
/* @__PURE__ */ (0,
|
|
599
|
-
/* @__PURE__ */ (0,
|
|
600
|
-
safeHref ? /* @__PURE__ */ (0,
|
|
620
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
|
|
621
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("figcaption", { className: "flex items-center justify-between border-b border-border bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground", children: [
|
|
622
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: entry.title ?? "HTML" }),
|
|
623
|
+
safeHref ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
601
624
|
"a",
|
|
602
625
|
{
|
|
603
626
|
href: safeHref,
|
|
@@ -610,7 +633,7 @@ function DocHtml({ entry }) {
|
|
|
610
633
|
}
|
|
611
634
|
) : null
|
|
612
635
|
] }),
|
|
613
|
-
/* @__PURE__ */ (0,
|
|
636
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
614
637
|
"iframe",
|
|
615
638
|
{
|
|
616
639
|
...frameProps,
|
|
@@ -625,7 +648,7 @@ function DocHtml({ entry }) {
|
|
|
625
648
|
}
|
|
626
649
|
|
|
627
650
|
// src/components/doc/DocState.tsx
|
|
628
|
-
var
|
|
651
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
629
652
|
function DocState({ entry }) {
|
|
630
653
|
let json;
|
|
631
654
|
try {
|
|
@@ -633,20 +656,20 @@ function DocState({ entry }) {
|
|
|
633
656
|
} catch {
|
|
634
657
|
json = String(entry.value);
|
|
635
658
|
}
|
|
636
|
-
return /* @__PURE__ */ (0,
|
|
659
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CodeFigure, { label: entry.label ?? "State", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("code", { className: "font-mono text-xs language-json", children: json }) });
|
|
637
660
|
}
|
|
638
661
|
|
|
639
662
|
// src/components/doc/DocCustom.tsx
|
|
640
|
-
var
|
|
663
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
641
664
|
function DocCustom({ entry }) {
|
|
642
665
|
const renderers = useCustomRenderers();
|
|
643
666
|
const renderer = renderers[entry.type];
|
|
644
667
|
if (renderer) {
|
|
645
|
-
return /* @__PURE__ */ (0,
|
|
668
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: renderer(entry) });
|
|
646
669
|
}
|
|
647
|
-
return /* @__PURE__ */ (0,
|
|
648
|
-
/* @__PURE__ */ (0,
|
|
649
|
-
/* @__PURE__ */ (0,
|
|
670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
|
|
671
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
|
|
672
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground", children: safeStringify2(entry.data) })
|
|
650
673
|
] });
|
|
651
674
|
}
|
|
652
675
|
function safeStringify2(value) {
|
|
@@ -658,64 +681,43 @@ function safeStringify2(value) {
|
|
|
658
681
|
}
|
|
659
682
|
|
|
660
683
|
// src/components/doc/DocEntry.tsx
|
|
661
|
-
var
|
|
684
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
662
685
|
function DocEntry({ entry }) {
|
|
663
686
|
switch (entry.kind) {
|
|
664
687
|
case "note":
|
|
665
|
-
return /* @__PURE__ */ (0,
|
|
688
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocNote, { entry });
|
|
666
689
|
case "tag":
|
|
667
|
-
return /* @__PURE__ */ (0,
|
|
690
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocTag, { entry });
|
|
668
691
|
case "kv":
|
|
669
|
-
return /* @__PURE__ */ (0,
|
|
692
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocKv, { entry });
|
|
670
693
|
case "code":
|
|
671
|
-
return /* @__PURE__ */ (0,
|
|
694
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocCode, { entry });
|
|
672
695
|
case "table":
|
|
673
|
-
return /* @__PURE__ */ (0,
|
|
696
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocTable, { entry });
|
|
674
697
|
case "link":
|
|
675
|
-
return /* @__PURE__ */ (0,
|
|
698
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocLink, { entry });
|
|
676
699
|
case "section":
|
|
677
|
-
return /* @__PURE__ */ (0,
|
|
700
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocSection, { entry });
|
|
678
701
|
case "mermaid":
|
|
679
|
-
return /* @__PURE__ */ (0,
|
|
702
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocMermaid, { entry });
|
|
680
703
|
case "screenshot":
|
|
681
|
-
return /* @__PURE__ */ (0,
|
|
704
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocScreenshot, { entry });
|
|
682
705
|
case "video":
|
|
683
|
-
return /* @__PURE__ */ (0,
|
|
706
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocVideo, { entry });
|
|
684
707
|
case "html":
|
|
685
|
-
return /* @__PURE__ */ (0,
|
|
708
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocHtml, { entry });
|
|
686
709
|
case "state":
|
|
687
|
-
return /* @__PURE__ */ (0,
|
|
710
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocState, { entry });
|
|
688
711
|
case "custom":
|
|
689
|
-
return /* @__PURE__ */ (0,
|
|
712
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocCustom, { entry });
|
|
690
713
|
}
|
|
691
714
|
}
|
|
692
715
|
|
|
693
716
|
// src/components/ReportDocEntries.tsx
|
|
694
|
-
var
|
|
717
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
695
718
|
function ReportDocEntries({ entries }) {
|
|
696
719
|
if (entries.length === 0) return null;
|
|
697
|
-
return /* @__PURE__ */ (0,
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
// src/lib/step-params.tsx
|
|
701
|
-
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
702
|
-
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
703
|
-
function highlightStepParams(text) {
|
|
704
|
-
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
705
|
-
if (matches.length === 0) return text;
|
|
706
|
-
const nodes = [];
|
|
707
|
-
let lastIndex = 0;
|
|
708
|
-
matches.forEach((match, i) => {
|
|
709
|
-
const start = match.index;
|
|
710
|
-
const end = start + match[0].length;
|
|
711
|
-
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
712
|
-
nodes.push(
|
|
713
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
714
|
-
);
|
|
715
|
-
lastIndex = end;
|
|
716
|
-
});
|
|
717
|
-
if (lastIndex < text.length) nodes.push(text.slice(lastIndex));
|
|
718
|
-
return nodes;
|
|
720
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children: entries.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DocEntry, { entry }, i)) });
|
|
719
721
|
}
|
|
720
722
|
|
|
721
723
|
// src/components/ReportSteps.tsx
|
|
@@ -734,9 +736,22 @@ var STEP_GLYPH_COLOR = {
|
|
|
734
736
|
};
|
|
735
737
|
function ReportSteps({ scenario }) {
|
|
736
738
|
if (scenario.steps.length === 0) return null;
|
|
737
|
-
|
|
739
|
+
const unasserted = new Set(
|
|
740
|
+
(0, import_assertive_steps.assertionState)(scenario.steps) === "unasserted" ? (0, import_assertive_steps.assertiveSteps)(scenario.steps).map((step) => step.id) : []
|
|
741
|
+
);
|
|
742
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
743
|
+
ReportStepItem,
|
|
744
|
+
{
|
|
745
|
+
step,
|
|
746
|
+
unasserted: unasserted.has(step.id)
|
|
747
|
+
},
|
|
748
|
+
step.id
|
|
749
|
+
)) });
|
|
738
750
|
}
|
|
739
|
-
function ReportStepItem({
|
|
751
|
+
function ReportStepItem({
|
|
752
|
+
step,
|
|
753
|
+
unasserted = false
|
|
754
|
+
}) {
|
|
740
755
|
const kw = step.keyword.toLowerCase();
|
|
741
756
|
const continuation = kw === "and" || kw === "but";
|
|
742
757
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
@@ -744,10 +759,23 @@ function ReportStepItem({ step }) {
|
|
|
744
759
|
{
|
|
745
760
|
id: step.id,
|
|
746
761
|
"data-status": step.status,
|
|
747
|
-
className: cn(
|
|
762
|
+
className: cn(
|
|
763
|
+
"py-1.5 text-[0.8125rem] leading-normal",
|
|
764
|
+
continuation && "pl-5"
|
|
765
|
+
),
|
|
748
766
|
children: [
|
|
749
767
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-baseline gap-2", children: [
|
|
750
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
768
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
769
|
+
"span",
|
|
770
|
+
{
|
|
771
|
+
"aria-hidden": true,
|
|
772
|
+
className: cn(
|
|
773
|
+
"w-4 shrink-0 text-center text-xs",
|
|
774
|
+
STEP_GLYPH_COLOR[step.status]
|
|
775
|
+
),
|
|
776
|
+
children: STEP_GLYPH[step.status] ?? "\u25CB"
|
|
777
|
+
}
|
|
778
|
+
),
|
|
751
779
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
752
780
|
"span",
|
|
753
781
|
{
|
|
@@ -759,6 +787,7 @@ function ReportStepItem({ step }) {
|
|
|
759
787
|
}
|
|
760
788
|
),
|
|
761
789
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
|
|
790
|
+
unasserted ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "shrink-0 rounded-full border border-pend-border bg-pend-bg px-2 py-0.5 text-[0.6875rem] font-medium text-pend", children: "No assertion" }) : null,
|
|
762
791
|
step.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: (0, import_duration.formatDuration)(step.durationMs) }) : null
|
|
763
792
|
] }),
|
|
764
793
|
step.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
@@ -1154,28 +1183,111 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
1154
1183
|
] });
|
|
1155
1184
|
}
|
|
1156
1185
|
|
|
1157
|
-
// src/
|
|
1186
|
+
// src/components/ScenarioStaleness.tsx
|
|
1187
|
+
var import_react7 = require("react");
|
|
1188
|
+
|
|
1189
|
+
// src/lib/provenance.ts
|
|
1190
|
+
function reportLastRunMs(report) {
|
|
1191
|
+
if (report.finishedAtMs && report.finishedAtMs > 0) return report.finishedAtMs;
|
|
1192
|
+
if (report.startedAtMs && report.startedAtMs > 0) return report.startedAtMs;
|
|
1193
|
+
return void 0;
|
|
1194
|
+
}
|
|
1195
|
+
function scenarioLastRunMs(scenario, report) {
|
|
1196
|
+
if (scenario.lastRunAtMs && scenario.lastRunAtMs > 0) return scenario.lastRunAtMs;
|
|
1197
|
+
return reportLastRunMs(report);
|
|
1198
|
+
}
|
|
1199
|
+
function formatRelativeAge(thenMs, nowMs) {
|
|
1200
|
+
const deltaMs = Math.max(0, nowMs - thenMs);
|
|
1201
|
+
const minutes = Math.floor(deltaMs / 6e4);
|
|
1202
|
+
if (minutes < 1) return "just now";
|
|
1203
|
+
if (minutes < 60) return `${minutes} minute${minutes === 1 ? "" : "s"} ago`;
|
|
1204
|
+
const hours = Math.floor(minutes / 60);
|
|
1205
|
+
if (hours < 24) return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
|
1206
|
+
const days = Math.floor(hours / 24);
|
|
1207
|
+
return `${days} day${days === 1 ? "" : "s"} ago`;
|
|
1208
|
+
}
|
|
1209
|
+
function isReportStale(lastRunMs, staleAfterDays, nowMs) {
|
|
1210
|
+
if (lastRunMs === void 0 || staleAfterDays <= 0) return false;
|
|
1211
|
+
return nowMs - lastRunMs >= staleAfterDays * 864e5;
|
|
1212
|
+
}
|
|
1213
|
+
var CI_DISPLAY_NAMES = {
|
|
1214
|
+
github: "GitHub Actions",
|
|
1215
|
+
gitlab: "GitLab CI",
|
|
1216
|
+
circleci: "CircleCI",
|
|
1217
|
+
jenkins: "Jenkins",
|
|
1218
|
+
azure: "Azure DevOps",
|
|
1219
|
+
buildkite: "Buildkite",
|
|
1220
|
+
travis: "Travis CI",
|
|
1221
|
+
ci: "CI"
|
|
1222
|
+
};
|
|
1223
|
+
function ciDisplayName(name) {
|
|
1224
|
+
return CI_DISPLAY_NAMES[name] ?? name;
|
|
1225
|
+
}
|
|
1226
|
+
function commitUrl(ci, sha) {
|
|
1227
|
+
const commitSha = ci?.commitSha ?? sha;
|
|
1228
|
+
if (!ci?.url || !commitSha) return void 0;
|
|
1229
|
+
const github = ci.url.match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)\/actions\/runs\//);
|
|
1230
|
+
if (github) return `${github[1]}/commit/${commitSha}`;
|
|
1231
|
+
const gitlab = ci.url.match(/^(https?:\/\/.+)\/-\/pipelines\//);
|
|
1232
|
+
if (gitlab) return `${gitlab[1]}/-/commit/${commitSha}`;
|
|
1233
|
+
return void 0;
|
|
1234
|
+
}
|
|
1235
|
+
function prUrl(ci) {
|
|
1236
|
+
if (!ci?.url || !ci.prNumber) return void 0;
|
|
1237
|
+
const github = ci.url.match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)\/actions\/runs\//);
|
|
1238
|
+
if (github) return `${github[1]}/pull/${ci.prNumber}`;
|
|
1239
|
+
return void 0;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
// src/interactive/scenario-freshness-context.tsx
|
|
1158
1243
|
var import_react6 = require("react");
|
|
1159
|
-
var
|
|
1244
|
+
var ScenarioFreshnessContext = (0, import_react6.createContext)(null);
|
|
1245
|
+
var ScenarioFreshnessProvider = ScenarioFreshnessContext.Provider;
|
|
1246
|
+
function useScenarioFreshness() {
|
|
1247
|
+
return (0, import_react6.useContext)(ScenarioFreshnessContext);
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
// src/components/ScenarioStaleness.tsx
|
|
1251
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1252
|
+
function ScenarioStaleness({ scenario }) {
|
|
1253
|
+
const freshness = useScenarioFreshness();
|
|
1254
|
+
const fixedNow = freshness?.nowMs;
|
|
1255
|
+
const [now, setNow] = (0, import_react7.useState)(fixedNow);
|
|
1256
|
+
(0, import_react7.useEffect)(() => {
|
|
1257
|
+
if (fixedNow === void 0) setNow(Date.now());
|
|
1258
|
+
}, [fixedNow]);
|
|
1259
|
+
if (!freshness || now === void 0) return null;
|
|
1260
|
+
const lastRunAtMs = scenario.lastRunAtMs;
|
|
1261
|
+
if (!lastRunAtMs || lastRunAtMs <= 0) return null;
|
|
1262
|
+
if (!isReportStale(lastRunAtMs, freshness.staleAfterDays, now)) return null;
|
|
1263
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Badge, { variant: "outline", "aria-label": "Scenario freshness", children: [
|
|
1264
|
+
"Last ran ",
|
|
1265
|
+
formatRelativeAge(lastRunAtMs, now)
|
|
1266
|
+
] });
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
// src/interactive/collapse-context.ts
|
|
1270
|
+
var import_react8 = require("react");
|
|
1271
|
+
var CollapseContext = (0, import_react8.createContext)(null);
|
|
1160
1272
|
var CollapseProvider = CollapseContext.Provider;
|
|
1161
1273
|
function useCollapse() {
|
|
1162
|
-
return (0,
|
|
1274
|
+
return (0, import_react8.useContext)(CollapseContext);
|
|
1163
1275
|
}
|
|
1164
1276
|
|
|
1165
1277
|
// src/interactive/scenario-actions.tsx
|
|
1166
|
-
var
|
|
1278
|
+
var import_react9 = require("react");
|
|
1167
1279
|
var import_scenario_markdown = require("executable-stories-core/utils/scenario-markdown");
|
|
1168
|
-
var ScenarioActionsContext = (0,
|
|
1280
|
+
var ScenarioActionsContext = (0, import_react9.createContext)(null);
|
|
1169
1281
|
var ScenarioActionsProvider = ScenarioActionsContext.Provider;
|
|
1170
1282
|
function useScenarioActions() {
|
|
1171
|
-
return (0,
|
|
1283
|
+
return (0, import_react9.useContext)(ScenarioActionsContext);
|
|
1172
1284
|
}
|
|
1173
1285
|
|
|
1174
1286
|
// src/components/ui/card.tsx
|
|
1175
1287
|
var React2 = require("react");
|
|
1176
|
-
var
|
|
1288
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1177
1289
|
function Card({ className, ...props }) {
|
|
1178
|
-
return /* @__PURE__ */ (0,
|
|
1290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1179
1291
|
"div",
|
|
1180
1292
|
{
|
|
1181
1293
|
"data-slot": "card",
|
|
@@ -1188,7 +1300,7 @@ function Card({ className, ...props }) {
|
|
|
1188
1300
|
);
|
|
1189
1301
|
}
|
|
1190
1302
|
function CardHeader({ className, ...props }) {
|
|
1191
|
-
return /* @__PURE__ */ (0,
|
|
1303
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1192
1304
|
"div",
|
|
1193
1305
|
{
|
|
1194
1306
|
"data-slot": "card-header",
|
|
@@ -1201,7 +1313,7 @@ function CardHeader({ className, ...props }) {
|
|
|
1201
1313
|
);
|
|
1202
1314
|
}
|
|
1203
1315
|
function CardContent({ className, ...props }) {
|
|
1204
|
-
return /* @__PURE__ */ (0,
|
|
1316
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1205
1317
|
"div",
|
|
1206
1318
|
{
|
|
1207
1319
|
"data-slot": "card-content",
|
|
@@ -1215,13 +1327,13 @@ function CardContent({ className, ...props }) {
|
|
|
1215
1327
|
var React3 = require("react");
|
|
1216
1328
|
var import_menu = require("@base-ui/react/menu");
|
|
1217
1329
|
var import_lucide_react = require("lucide-react");
|
|
1218
|
-
var
|
|
1330
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1219
1331
|
var itemClasses = "relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 [&_svg:not([class*='text-'])]:text-muted-foreground";
|
|
1220
1332
|
function DropdownMenu(props) {
|
|
1221
|
-
return /* @__PURE__ */ (0,
|
|
1333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1222
1334
|
}
|
|
1223
1335
|
function DropdownMenuTrigger(props) {
|
|
1224
|
-
return /* @__PURE__ */ (0,
|
|
1336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
1225
1337
|
}
|
|
1226
1338
|
function DropdownMenuContent({
|
|
1227
1339
|
className,
|
|
@@ -1229,14 +1341,14 @@ function DropdownMenuContent({
|
|
|
1229
1341
|
sideOffset = 4,
|
|
1230
1342
|
...props
|
|
1231
1343
|
}) {
|
|
1232
|
-
return /* @__PURE__ */ (0,
|
|
1344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1233
1345
|
import_menu.Menu.Positioner,
|
|
1234
1346
|
{
|
|
1235
1347
|
"data-slot": "dropdown-menu-positioner",
|
|
1236
1348
|
className: "z-50",
|
|
1237
1349
|
align,
|
|
1238
1350
|
sideOffset,
|
|
1239
|
-
children: /* @__PURE__ */ (0,
|
|
1351
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1240
1352
|
import_menu.Menu.Popup,
|
|
1241
1353
|
{
|
|
1242
1354
|
"data-slot": "dropdown-menu-content",
|
|
@@ -1254,7 +1366,7 @@ function DropdownMenuItem({
|
|
|
1254
1366
|
className,
|
|
1255
1367
|
...props
|
|
1256
1368
|
}) {
|
|
1257
|
-
return /* @__PURE__ */ (0,
|
|
1369
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1258
1370
|
import_menu.Menu.Item,
|
|
1259
1371
|
{
|
|
1260
1372
|
"data-slot": "dropdown-menu-item",
|
|
@@ -1266,7 +1378,7 @@ function DropdownMenuItem({
|
|
|
1266
1378
|
|
|
1267
1379
|
// src/components/ReportScenario.tsx
|
|
1268
1380
|
var import_lucide_react2 = require("lucide-react");
|
|
1269
|
-
var
|
|
1381
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1270
1382
|
var STATUS_META = {
|
|
1271
1383
|
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
1272
1384
|
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
@@ -1282,7 +1394,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1282
1394
|
const collapsible = collapse !== null && !hideTitle;
|
|
1283
1395
|
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
1284
1396
|
const actions = useScenarioActions();
|
|
1285
|
-
return /* @__PURE__ */ (0,
|
|
1397
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1286
1398
|
Card,
|
|
1287
1399
|
{
|
|
1288
1400
|
id: scenario.id,
|
|
@@ -1290,10 +1402,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1290
1402
|
...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
|
|
1291
1403
|
className: "gap-0 py-0",
|
|
1292
1404
|
children: [
|
|
1293
|
-
/* @__PURE__ */ (0,
|
|
1294
|
-
/* @__PURE__ */ (0,
|
|
1295
|
-
hideTitle ? null : /* @__PURE__ */ (0,
|
|
1296
|
-
collapsible ? /* @__PURE__ */ (0,
|
|
1405
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(CardHeader, { className: "px-4 py-3", children: [
|
|
1406
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
1407
|
+
hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
1408
|
+
collapsible ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
1297
1409
|
"button",
|
|
1298
1410
|
{
|
|
1299
1411
|
type: "button",
|
|
@@ -1302,49 +1414,50 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1302
1414
|
"aria-controls": bodyId,
|
|
1303
1415
|
"aria-label": `Toggle ${scenario.title}`,
|
|
1304
1416
|
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
1305
|
-
children: /* @__PURE__ */ (0,
|
|
1417
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
1306
1418
|
}
|
|
1307
1419
|
) : null,
|
|
1308
|
-
/* @__PURE__ */ (0,
|
|
1309
|
-
/* @__PURE__ */ (0,
|
|
1420
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
1421
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: scenario.title })
|
|
1310
1422
|
] }),
|
|
1311
|
-
/* @__PURE__ */ (0,
|
|
1312
|
-
/* @__PURE__ */ (0,
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1423
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1424
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1425
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ScenarioStaleness, { scenario }),
|
|
1426
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: (0, import_duration3.formatDuration)(scenario.durationMs) }) : null,
|
|
1427
|
+
meta.showPill ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "sr-only", children: `Status: ${label}` }),
|
|
1428
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(DropdownMenu, { children: [
|
|
1429
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
1317
1430
|
DropdownMenuTrigger,
|
|
1318
1431
|
{
|
|
1319
1432
|
"aria-label": `Actions for ${scenario.title}`,
|
|
1320
1433
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
1321
|
-
children: /* @__PURE__ */ (0,
|
|
1434
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
|
|
1322
1435
|
}
|
|
1323
1436
|
),
|
|
1324
|
-
/* @__PURE__ */ (0,
|
|
1325
|
-
/* @__PURE__ */ (0,
|
|
1326
|
-
/* @__PURE__ */ (0,
|
|
1437
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(DropdownMenuContent, { align: "end", children: [
|
|
1438
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
1439
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react2.LinkIcon, {}),
|
|
1327
1440
|
" Copy link"
|
|
1328
1441
|
] }),
|
|
1329
|
-
/* @__PURE__ */ (0,
|
|
1330
|
-
/* @__PURE__ */ (0,
|
|
1442
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
1443
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react2.FileTextIcon, {}),
|
|
1331
1444
|
" Copy as Markdown"
|
|
1332
1445
|
] }),
|
|
1333
|
-
/* @__PURE__ */ (0,
|
|
1334
|
-
/* @__PURE__ */ (0,
|
|
1446
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
1447
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react2.SparklesIcon, {}),
|
|
1335
1448
|
" Explain with AI"
|
|
1336
1449
|
] })
|
|
1337
1450
|
] })
|
|
1338
1451
|
] }) : null
|
|
1339
1452
|
] })
|
|
1340
1453
|
] }),
|
|
1341
|
-
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0,
|
|
1342
|
-
scenario.tags.map((t) => /* @__PURE__ */ (0,
|
|
1343
|
-
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0,
|
|
1454
|
+
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
|
|
1455
|
+
scenario.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
|
|
1456
|
+
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("li", { children: ticket.url ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
|
|
1344
1457
|
] }) : null
|
|
1345
1458
|
] }),
|
|
1346
|
-
/* @__PURE__ */ (0,
|
|
1347
|
-
scenario.errorMessage ? /* @__PURE__ */ (0,
|
|
1459
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
1460
|
+
scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
1348
1461
|
"pre",
|
|
1349
1462
|
{
|
|
1350
1463
|
role: "alert",
|
|
@@ -1352,11 +1465,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1352
1465
|
children: scenario.errorMessage
|
|
1353
1466
|
}
|
|
1354
1467
|
) : null,
|
|
1355
|
-
/* @__PURE__ */ (0,
|
|
1356
|
-
/* @__PURE__ */ (0,
|
|
1357
|
-
scenario.docEntries.length > 0 ? /* @__PURE__ */ (0,
|
|
1358
|
-
/* @__PURE__ */ (0,
|
|
1359
|
-
/* @__PURE__ */ (0,
|
|
1468
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportStoryboard, { scenario }),
|
|
1469
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportSteps, { scenario }),
|
|
1470
|
+
scenario.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
|
|
1471
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportAttachments, { attachments: scenario.attachments }),
|
|
1472
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportTrace, { spans: scenario.otelSpans })
|
|
1360
1473
|
] })
|
|
1361
1474
|
]
|
|
1362
1475
|
}
|
|
@@ -1364,28 +1477,28 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1364
1477
|
}
|
|
1365
1478
|
|
|
1366
1479
|
// src/components/ReportScenarioList.tsx
|
|
1367
|
-
var
|
|
1480
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1368
1481
|
function ReportScenarioList({ feature }) {
|
|
1369
|
-
return /* @__PURE__ */ (0,
|
|
1482
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_jsx_runtime28.Fragment, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ReportScenario, { scenario }, scenario.id)) });
|
|
1370
1483
|
}
|
|
1371
1484
|
|
|
1372
1485
|
// src/components/ReportFeatureIntro.tsx
|
|
1373
|
-
var
|
|
1486
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1374
1487
|
function ReportFeatureIntro({ feature }) {
|
|
1375
1488
|
const hasNarrative = Boolean(feature.narrative?.trim());
|
|
1376
1489
|
const hasGlossary = Boolean(feature.glossary?.length);
|
|
1377
1490
|
if (!hasNarrative && !hasGlossary) return null;
|
|
1378
|
-
return /* @__PURE__ */ (0,
|
|
1379
|
-
hasNarrative ? /* @__PURE__ */ (0,
|
|
1491
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3 border-l-2 border-border pl-4 text-sm", children: [
|
|
1492
|
+
hasNarrative ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1380
1493
|
"div",
|
|
1381
1494
|
{
|
|
1382
1495
|
className: "es-doc-prose prose prose-sm max-w-none text-muted-foreground",
|
|
1383
1496
|
dangerouslySetInnerHTML: { __html: safeMarkdownHtml(dedent(feature.narrative)) }
|
|
1384
1497
|
}
|
|
1385
1498
|
) : null,
|
|
1386
|
-
hasGlossary ? /* @__PURE__ */ (0,
|
|
1387
|
-
/* @__PURE__ */ (0,
|
|
1388
|
-
/* @__PURE__ */ (0,
|
|
1499
|
+
hasGlossary ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dl", { className: "grid gap-1.5", "aria-label": "Glossary", children: feature.glossary.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-wrap gap-x-2 text-xs", children: [
|
|
1500
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dt", { className: "font-medium text-foreground", children: entry.term }),
|
|
1501
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dd", { className: "flex-1 text-muted-foreground", children: entry.definition })
|
|
1389
1502
|
] }, entry.term)) }) : null
|
|
1390
1503
|
] });
|
|
1391
1504
|
}
|
|
@@ -1397,7 +1510,7 @@ function featureKindLabel(kind) {
|
|
|
1397
1510
|
}
|
|
1398
1511
|
|
|
1399
1512
|
// src/components/ReportFeature.tsx
|
|
1400
|
-
var
|
|
1513
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1401
1514
|
function ReportFeature({ feature }) {
|
|
1402
1515
|
const titleId = `${feature.id}-title`;
|
|
1403
1516
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1409,7 +1522,7 @@ function ReportFeature({ feature }) {
|
|
|
1409
1522
|
return (
|
|
1410
1523
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
1411
1524
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1412
|
-
/* @__PURE__ */ (0,
|
|
1525
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
1413
1526
|
"section",
|
|
1414
1527
|
{
|
|
1415
1528
|
id: feature.id,
|
|
@@ -1417,9 +1530,9 @@ function ReportFeature({ feature }) {
|
|
|
1417
1530
|
"aria-labelledby": titleId,
|
|
1418
1531
|
className: "flex flex-col gap-3",
|
|
1419
1532
|
children: [
|
|
1420
|
-
/* @__PURE__ */ (0,
|
|
1421
|
-
/* @__PURE__ */ (0,
|
|
1422
|
-
/* @__PURE__ */ (0,
|
|
1533
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1534
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "min-w-0", children: [
|
|
1535
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
1423
1536
|
"button",
|
|
1424
1537
|
{
|
|
1425
1538
|
type: "button",
|
|
@@ -1428,34 +1541,34 @@ function ReportFeature({ feature }) {
|
|
|
1428
1541
|
"aria-controls": bodyId,
|
|
1429
1542
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1430
1543
|
children: [
|
|
1431
|
-
/* @__PURE__ */ (0,
|
|
1432
|
-
/* @__PURE__ */ (0,
|
|
1544
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
|
|
1545
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "truncate", children: feature.title })
|
|
1433
1546
|
]
|
|
1434
1547
|
}
|
|
1435
1548
|
) : feature.title }),
|
|
1436
|
-
/* @__PURE__ */ (0,
|
|
1437
|
-
kindLabel ? /* @__PURE__ */ (0,
|
|
1438
|
-
/* @__PURE__ */ (0,
|
|
1549
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("p", { className: cn("mt-0.5 flex items-center gap-2 text-xs text-muted-foreground", collapse && "pl-5"), children: [
|
|
1550
|
+
kindLabel ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "shrink-0 rounded-sm bg-muted px-1.5 py-0.5 font-medium text-foreground", children: kindLabel }) : null,
|
|
1551
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "truncate font-mono", children: feature.sourceFile })
|
|
1439
1552
|
] })
|
|
1440
1553
|
] }),
|
|
1441
|
-
/* @__PURE__ */ (0,
|
|
1554
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
1442
1555
|
"p",
|
|
1443
1556
|
{
|
|
1444
1557
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1445
1558
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1446
1559
|
children: [
|
|
1447
|
-
/* @__PURE__ */ (0,
|
|
1560
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { children: [
|
|
1448
1561
|
s.passed,
|
|
1449
1562
|
" passed"
|
|
1450
1563
|
] }),
|
|
1451
|
-
/* @__PURE__ */ (0,
|
|
1452
|
-
/* @__PURE__ */ (0,
|
|
1564
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1565
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1453
1566
|
s.failed,
|
|
1454
1567
|
" failed"
|
|
1455
1568
|
] }),
|
|
1456
|
-
skipped > 0 ? /* @__PURE__ */ (0,
|
|
1457
|
-
/* @__PURE__ */ (0,
|
|
1458
|
-
/* @__PURE__ */ (0,
|
|
1569
|
+
skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
1570
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1571
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { children: [
|
|
1459
1572
|
skipped,
|
|
1460
1573
|
" skipped"
|
|
1461
1574
|
] })
|
|
@@ -1464,9 +1577,9 @@ function ReportFeature({ feature }) {
|
|
|
1464
1577
|
}
|
|
1465
1578
|
)
|
|
1466
1579
|
] }),
|
|
1467
|
-
/* @__PURE__ */ (0,
|
|
1468
|
-
/* @__PURE__ */ (0,
|
|
1469
|
-
/* @__PURE__ */ (0,
|
|
1580
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: [
|
|
1581
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ReportFeatureIntro, { feature }),
|
|
1582
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ReportScenarioList, { feature })
|
|
1470
1583
|
] })
|
|
1471
1584
|
]
|
|
1472
1585
|
}
|
|
@@ -1475,17 +1588,17 @@ function ReportFeature({ feature }) {
|
|
|
1475
1588
|
}
|
|
1476
1589
|
|
|
1477
1590
|
// src/components/ReportFeatureList.tsx
|
|
1478
|
-
var
|
|
1591
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1479
1592
|
function ReportFeatureList() {
|
|
1480
1593
|
const report = useReport();
|
|
1481
|
-
return /* @__PURE__ */ (0,
|
|
1594
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ReportFeature, { feature }, feature.id)) });
|
|
1482
1595
|
}
|
|
1483
1596
|
|
|
1484
1597
|
// src/components/ui/empty.tsx
|
|
1485
1598
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
1486
|
-
var
|
|
1599
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1487
1600
|
function Empty({ className, ...props }) {
|
|
1488
|
-
return /* @__PURE__ */ (0,
|
|
1601
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1489
1602
|
"div",
|
|
1490
1603
|
{
|
|
1491
1604
|
"data-slot": "empty",
|
|
@@ -1498,7 +1611,7 @@ function Empty({ className, ...props }) {
|
|
|
1498
1611
|
);
|
|
1499
1612
|
}
|
|
1500
1613
|
function EmptyHeader({ className, ...props }) {
|
|
1501
|
-
return /* @__PURE__ */ (0,
|
|
1614
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1502
1615
|
"div",
|
|
1503
1616
|
{
|
|
1504
1617
|
"data-slot": "empty-header",
|
|
@@ -1525,7 +1638,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
|
|
|
1525
1638
|
}
|
|
1526
1639
|
);
|
|
1527
1640
|
function EmptyTitle({ className, ...props }) {
|
|
1528
|
-
return /* @__PURE__ */ (0,
|
|
1641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1529
1642
|
"div",
|
|
1530
1643
|
{
|
|
1531
1644
|
"data-slot": "empty-title",
|
|
@@ -1536,16 +1649,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1536
1649
|
}
|
|
1537
1650
|
|
|
1538
1651
|
// src/components/ReportEmpty.tsx
|
|
1539
|
-
var
|
|
1652
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1540
1653
|
function ReportEmpty({ message }) {
|
|
1541
|
-
return /* @__PURE__ */ (0,
|
|
1654
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(EmptyHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
|
|
1542
1655
|
}
|
|
1543
1656
|
|
|
1544
1657
|
// src/components/ReportSummary.tsx
|
|
1545
|
-
var
|
|
1658
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1546
1659
|
function ReportSummary({ className }) {
|
|
1547
1660
|
const report = useReport();
|
|
1548
|
-
return /* @__PURE__ */ (0,
|
|
1661
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
1549
1662
|
ReportSummaryView,
|
|
1550
1663
|
{
|
|
1551
1664
|
summary: report.summary,
|
|
@@ -1571,7 +1684,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1571
1684
|
if (summary.pending > 0) {
|
|
1572
1685
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1573
1686
|
}
|
|
1574
|
-
return /* @__PURE__ */ (0,
|
|
1687
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
1575
1688
|
"dl",
|
|
1576
1689
|
{
|
|
1577
1690
|
className: cn(
|
|
@@ -1584,17 +1697,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1584
1697
|
"aria-label": ariaLabel,
|
|
1585
1698
|
children: cards.map((c) => {
|
|
1586
1699
|
const tone = TONE[c.status];
|
|
1587
|
-
return /* @__PURE__ */ (0,
|
|
1700
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
1588
1701
|
"div",
|
|
1589
1702
|
{
|
|
1590
1703
|
"data-status": c.status,
|
|
1591
1704
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1592
1705
|
children: [
|
|
1593
|
-
/* @__PURE__ */ (0,
|
|
1594
|
-
/* @__PURE__ */ (0,
|
|
1706
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
|
|
1707
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1595
1708
|
c.label
|
|
1596
1709
|
] }),
|
|
1597
|
-
/* @__PURE__ */ (0,
|
|
1710
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
|
|
1598
1711
|
]
|
|
1599
1712
|
},
|
|
1600
1713
|
c.status
|
|
@@ -1606,58 +1719,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1606
1719
|
|
|
1607
1720
|
// src/components/ReportMeta.tsx
|
|
1608
1721
|
var import_duration4 = require("executable-stories-core/utils/duration");
|
|
1609
|
-
|
|
1610
|
-
// src/lib/provenance.ts
|
|
1611
|
-
function reportLastRunMs(report) {
|
|
1612
|
-
if (report.finishedAtMs && report.finishedAtMs > 0) return report.finishedAtMs;
|
|
1613
|
-
if (report.startedAtMs && report.startedAtMs > 0) return report.startedAtMs;
|
|
1614
|
-
return void 0;
|
|
1615
|
-
}
|
|
1616
|
-
function formatRelativeAge(thenMs, nowMs) {
|
|
1617
|
-
const deltaMs = Math.max(0, nowMs - thenMs);
|
|
1618
|
-
const minutes = Math.floor(deltaMs / 6e4);
|
|
1619
|
-
if (minutes < 1) return "just now";
|
|
1620
|
-
if (minutes < 60) return `${minutes} minute${minutes === 1 ? "" : "s"} ago`;
|
|
1621
|
-
const hours = Math.floor(minutes / 60);
|
|
1622
|
-
if (hours < 24) return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
|
1623
|
-
const days = Math.floor(hours / 24);
|
|
1624
|
-
return `${days} day${days === 1 ? "" : "s"} ago`;
|
|
1625
|
-
}
|
|
1626
|
-
function isReportStale(lastRunMs, staleAfterDays, nowMs) {
|
|
1627
|
-
if (lastRunMs === void 0 || staleAfterDays <= 0) return false;
|
|
1628
|
-
return nowMs - lastRunMs >= staleAfterDays * 864e5;
|
|
1629
|
-
}
|
|
1630
|
-
var CI_DISPLAY_NAMES = {
|
|
1631
|
-
github: "GitHub Actions",
|
|
1632
|
-
gitlab: "GitLab CI",
|
|
1633
|
-
circleci: "CircleCI",
|
|
1634
|
-
jenkins: "Jenkins",
|
|
1635
|
-
azure: "Azure DevOps",
|
|
1636
|
-
buildkite: "Buildkite",
|
|
1637
|
-
travis: "Travis CI",
|
|
1638
|
-
ci: "CI"
|
|
1639
|
-
};
|
|
1640
|
-
function ciDisplayName(name) {
|
|
1641
|
-
return CI_DISPLAY_NAMES[name] ?? name;
|
|
1642
|
-
}
|
|
1643
|
-
function commitUrl(ci, sha) {
|
|
1644
|
-
const commitSha = ci?.commitSha ?? sha;
|
|
1645
|
-
if (!ci?.url || !commitSha) return void 0;
|
|
1646
|
-
const github = ci.url.match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)\/actions\/runs\//);
|
|
1647
|
-
if (github) return `${github[1]}/commit/${commitSha}`;
|
|
1648
|
-
const gitlab = ci.url.match(/^(https?:\/\/.+)\/-\/pipelines\//);
|
|
1649
|
-
if (gitlab) return `${gitlab[1]}/-/commit/${commitSha}`;
|
|
1650
|
-
return void 0;
|
|
1651
|
-
}
|
|
1652
|
-
function prUrl(ci) {
|
|
1653
|
-
if (!ci?.url || !ci.prNumber) return void 0;
|
|
1654
|
-
const github = ci.url.match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)\/actions\/runs\//);
|
|
1655
|
-
if (github) return `${github[1]}/pull/${ci.prNumber}`;
|
|
1656
|
-
return void 0;
|
|
1657
|
-
}
|
|
1658
|
-
|
|
1659
|
-
// src/components/ReportMeta.tsx
|
|
1660
|
-
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1722
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
1661
1723
|
function ReportMeta() {
|
|
1662
1724
|
const report = useReport();
|
|
1663
1725
|
const items = [];
|
|
@@ -1680,13 +1742,13 @@ function ReportMeta() {
|
|
|
1680
1742
|
const short = sha.slice(0, 8);
|
|
1681
1743
|
items.push({
|
|
1682
1744
|
label: "Commit",
|
|
1683
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1745
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1684
1746
|
});
|
|
1685
1747
|
}
|
|
1686
1748
|
if (report.ci) {
|
|
1687
1749
|
items.push({
|
|
1688
1750
|
label: "CI",
|
|
1689
|
-
value: report.ci.url ? /* @__PURE__ */ (0,
|
|
1751
|
+
value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1690
1752
|
ciDisplayName(report.ci.name),
|
|
1691
1753
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1692
1754
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1697,7 +1759,7 @@ function ReportMeta() {
|
|
|
1697
1759
|
const label = `#${report.ci.prNumber}`;
|
|
1698
1760
|
items.push({
|
|
1699
1761
|
label: "PR",
|
|
1700
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1762
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1701
1763
|
});
|
|
1702
1764
|
}
|
|
1703
1765
|
if (items.length === 0) return null;
|
|
@@ -1705,48 +1767,48 @@ function ReportMeta() {
|
|
|
1705
1767
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1706
1768
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1707
1769
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1708
|
-
/* @__PURE__ */ (0,
|
|
1709
|
-
/* @__PURE__ */ (0,
|
|
1710
|
-
/* @__PURE__ */ (0,
|
|
1770
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
|
|
1771
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("summary", { className: "flex cursor-pointer list-none select-none items-center gap-1.5 px-4 py-2 font-medium text-muted-foreground [&::-webkit-details-marker]:hidden", children: [
|
|
1772
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1711
1773
|
"Run details"
|
|
1712
1774
|
] }),
|
|
1713
|
-
/* @__PURE__ */ (0,
|
|
1714
|
-
/* @__PURE__ */ (0,
|
|
1715
|
-
/* @__PURE__ */ (0,
|
|
1775
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("dl", { className: "flex flex-wrap gap-x-5 gap-y-2 border-t border-border px-4 py-3 text-muted-foreground", "aria-label": "Run metadata", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex items-baseline gap-1.5", children: [
|
|
1776
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("dt", { className: "font-medium", children: item.label }),
|
|
1777
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1716
1778
|
] }, item.label)) })
|
|
1717
1779
|
] })
|
|
1718
1780
|
);
|
|
1719
1781
|
}
|
|
1720
1782
|
|
|
1721
1783
|
// src/components/ReportSchemaError.tsx
|
|
1722
|
-
var
|
|
1784
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
1723
1785
|
function ReportSchemaError({ error }) {
|
|
1724
|
-
return /* @__PURE__ */ (0,
|
|
1725
|
-
/* @__PURE__ */ (0,
|
|
1726
|
-
/* @__PURE__ */ (0,
|
|
1727
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0,
|
|
1786
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1787
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("strong", { children: "Report could not be displayed." }) }),
|
|
1788
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { children: error.message }),
|
|
1789
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("p", { children: [
|
|
1728
1790
|
"The report bundle is newer than this version of ",
|
|
1729
|
-
/* @__PURE__ */ (0,
|
|
1791
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("code", { children: "executable-stories-react" }),
|
|
1730
1792
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1731
1793
|
] }) : null,
|
|
1732
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0,
|
|
1733
|
-
/* @__PURE__ */ (0,
|
|
1794
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("details", { children: [
|
|
1795
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("summary", { children: [
|
|
1734
1796
|
error.issues.length,
|
|
1735
1797
|
" validation issue",
|
|
1736
1798
|
error.issues.length === 1 ? "" : "s"
|
|
1737
1799
|
] }),
|
|
1738
|
-
/* @__PURE__ */ (0,
|
|
1800
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1739
1801
|
] }) : null
|
|
1740
1802
|
] });
|
|
1741
1803
|
}
|
|
1742
1804
|
|
|
1743
1805
|
// src/components/ReportShell.tsx
|
|
1744
|
-
var
|
|
1806
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
1745
1807
|
function ReportTitleBlock({ title }) {
|
|
1746
|
-
return /* @__PURE__ */ (0,
|
|
1747
|
-
/* @__PURE__ */ (0,
|
|
1748
|
-
/* @__PURE__ */ (0,
|
|
1749
|
-
/* @__PURE__ */ (0,
|
|
1808
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
|
|
1809
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("h1", { children: title ?? "Story Report" }),
|
|
1810
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportSummary, {}),
|
|
1811
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportMeta, {})
|
|
1750
1812
|
] });
|
|
1751
1813
|
}
|
|
1752
1814
|
function ReportErrorShell({
|
|
@@ -1755,28 +1817,28 @@ function ReportErrorShell({
|
|
|
1755
1817
|
title,
|
|
1756
1818
|
dataTheme
|
|
1757
1819
|
}) {
|
|
1758
|
-
return /* @__PURE__ */ (0,
|
|
1820
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportSchemaError, { error }) });
|
|
1759
1821
|
}
|
|
1760
1822
|
|
|
1761
1823
|
// src/components/Report.tsx
|
|
1762
|
-
var
|
|
1824
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
1763
1825
|
function Report(props) {
|
|
1764
1826
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1765
1827
|
const result = unwrapReport(report);
|
|
1766
1828
|
if (!result.ok) {
|
|
1767
|
-
return /* @__PURE__ */ (0,
|
|
1829
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1768
1830
|
}
|
|
1769
1831
|
const data = result.data;
|
|
1770
1832
|
const hasContent = data.features.length > 0;
|
|
1771
|
-
return /* @__PURE__ */ (0,
|
|
1772
|
-
/* @__PURE__ */ (0,
|
|
1773
|
-
hasContent ? /* @__PURE__ */ (0,
|
|
1833
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1834
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportTitleBlock, { title }) }),
|
|
1835
|
+
hasContent ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportEmpty, {})
|
|
1774
1836
|
] }) });
|
|
1775
1837
|
}
|
|
1776
1838
|
|
|
1777
1839
|
// src/components/doc/MermaidView.tsx
|
|
1778
|
-
var
|
|
1779
|
-
var
|
|
1840
|
+
var import_react10 = require("react");
|
|
1841
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
1780
1842
|
function prefersDark(el) {
|
|
1781
1843
|
const themed = el?.closest("[data-theme]");
|
|
1782
1844
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -1784,10 +1846,10 @@ function prefersDark(el) {
|
|
|
1784
1846
|
return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
|
|
1785
1847
|
}
|
|
1786
1848
|
function MermaidView({ entry, load }) {
|
|
1787
|
-
const ref = (0,
|
|
1788
|
-
const [svg, setSvg] = (0,
|
|
1789
|
-
const [error, setError] = (0,
|
|
1790
|
-
(0,
|
|
1849
|
+
const ref = (0, import_react10.useRef)(null);
|
|
1850
|
+
const [svg, setSvg] = (0, import_react10.useState)(null);
|
|
1851
|
+
const [error, setError] = (0, import_react10.useState)(null);
|
|
1852
|
+
(0, import_react10.useEffect)(() => {
|
|
1791
1853
|
let cancelled = false;
|
|
1792
1854
|
const draw = async () => {
|
|
1793
1855
|
let mermaid;
|
|
@@ -1830,9 +1892,9 @@ function MermaidView({ entry, load }) {
|
|
|
1830
1892
|
};
|
|
1831
1893
|
}, [entry.code, load]);
|
|
1832
1894
|
if (svg) {
|
|
1833
|
-
return /* @__PURE__ */ (0,
|
|
1834
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
1835
|
-
/* @__PURE__ */ (0,
|
|
1895
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("figure", { ref, className: "my-3", children: [
|
|
1896
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
1897
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1836
1898
|
"div",
|
|
1837
1899
|
{
|
|
1838
1900
|
role: "img",
|
|
@@ -1843,8 +1905,8 @@ function MermaidView({ entry, load }) {
|
|
|
1843
1905
|
)
|
|
1844
1906
|
] });
|
|
1845
1907
|
}
|
|
1846
|
-
return /* @__PURE__ */ (0,
|
|
1847
|
-
error ? /* @__PURE__ */ (0,
|
|
1908
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
|
|
1909
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
1848
1910
|
"p",
|
|
1849
1911
|
{
|
|
1850
1912
|
role: "alert",
|
|
@@ -1856,34 +1918,34 @@ function MermaidView({ entry, load }) {
|
|
|
1856
1918
|
]
|
|
1857
1919
|
}
|
|
1858
1920
|
) : null,
|
|
1859
|
-
/* @__PURE__ */ (0,
|
|
1921
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(MermaidSource, { entry, ref })
|
|
1860
1922
|
] });
|
|
1861
1923
|
}
|
|
1862
1924
|
|
|
1863
1925
|
// src/components/doc/MermaidDiagram.tsx
|
|
1864
|
-
var
|
|
1926
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
1865
1927
|
var mermaidLoader;
|
|
1866
1928
|
function loadMermaid() {
|
|
1867
1929
|
mermaidLoader ??= import("mermaid").then((m) => m.default);
|
|
1868
1930
|
return mermaidLoader;
|
|
1869
1931
|
}
|
|
1870
1932
|
function MermaidDiagram({ entry, load = loadMermaid }) {
|
|
1871
|
-
return /* @__PURE__ */ (0,
|
|
1933
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(MermaidView, { entry, load });
|
|
1872
1934
|
}
|
|
1873
1935
|
|
|
1874
1936
|
// src/components/ScenarioExplorer.tsx
|
|
1875
|
-
var
|
|
1937
|
+
var import_react11 = require("react");
|
|
1876
1938
|
|
|
1877
1939
|
// src/components/ui/command.tsx
|
|
1878
1940
|
var React4 = require("react");
|
|
1879
1941
|
var import_cmdk = require("cmdk");
|
|
1880
1942
|
var import_lucide_react3 = require("lucide-react");
|
|
1881
|
-
var
|
|
1943
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
1882
1944
|
function Command({
|
|
1883
1945
|
className,
|
|
1884
1946
|
...props
|
|
1885
1947
|
}) {
|
|
1886
|
-
return /* @__PURE__ */ (0,
|
|
1948
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
1887
1949
|
import_cmdk.Command,
|
|
1888
1950
|
{
|
|
1889
1951
|
"data-slot": "command",
|
|
@@ -1899,14 +1961,14 @@ function CommandInput({
|
|
|
1899
1961
|
className,
|
|
1900
1962
|
...props
|
|
1901
1963
|
}) {
|
|
1902
|
-
return /* @__PURE__ */ (0,
|
|
1964
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
|
|
1903
1965
|
"div",
|
|
1904
1966
|
{
|
|
1905
1967
|
"data-slot": "command-input-wrapper",
|
|
1906
1968
|
className: "flex h-9 items-center gap-2 border-b px-3",
|
|
1907
1969
|
children: [
|
|
1908
|
-
/* @__PURE__ */ (0,
|
|
1909
|
-
/* @__PURE__ */ (0,
|
|
1970
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react3.SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
|
|
1971
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
1910
1972
|
import_cmdk.Command.Input,
|
|
1911
1973
|
{
|
|
1912
1974
|
"data-slot": "command-input",
|
|
@@ -1925,7 +1987,7 @@ function CommandList({
|
|
|
1925
1987
|
className,
|
|
1926
1988
|
...props
|
|
1927
1989
|
}) {
|
|
1928
|
-
return /* @__PURE__ */ (0,
|
|
1990
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
1929
1991
|
import_cmdk.Command.List,
|
|
1930
1992
|
{
|
|
1931
1993
|
"data-slot": "command-list",
|
|
@@ -1940,7 +2002,7 @@ function CommandList({
|
|
|
1940
2002
|
function CommandEmpty({
|
|
1941
2003
|
...props
|
|
1942
2004
|
}) {
|
|
1943
|
-
return /* @__PURE__ */ (0,
|
|
2005
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
1944
2006
|
import_cmdk.Command.Empty,
|
|
1945
2007
|
{
|
|
1946
2008
|
"data-slot": "command-empty",
|
|
@@ -1953,7 +2015,7 @@ function CommandGroup({
|
|
|
1953
2015
|
className,
|
|
1954
2016
|
...props
|
|
1955
2017
|
}) {
|
|
1956
|
-
return /* @__PURE__ */ (0,
|
|
2018
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
1957
2019
|
import_cmdk.Command.Group,
|
|
1958
2020
|
{
|
|
1959
2021
|
"data-slot": "command-group",
|
|
@@ -1969,7 +2031,7 @@ function CommandItem({
|
|
|
1969
2031
|
className,
|
|
1970
2032
|
...props
|
|
1971
2033
|
}) {
|
|
1972
|
-
return /* @__PURE__ */ (0,
|
|
2034
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
1973
2035
|
import_cmdk.Command.Item,
|
|
1974
2036
|
{
|
|
1975
2037
|
"data-slot": "command-item",
|
|
@@ -1983,7 +2045,7 @@ function CommandItem({
|
|
|
1983
2045
|
}
|
|
1984
2046
|
|
|
1985
2047
|
// src/components/ScenarioExplorer.tsx
|
|
1986
|
-
var
|
|
2048
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
1987
2049
|
var STATUS_FILTERS = [
|
|
1988
2050
|
{ value: "all", label: "All" },
|
|
1989
2051
|
{ value: "passed", label: "Passed" },
|
|
@@ -1992,24 +2054,24 @@ var STATUS_FILTERS = [
|
|
|
1992
2054
|
{ value: "pending", label: "Pending" }
|
|
1993
2055
|
];
|
|
1994
2056
|
function ScenarioExplorer({ scenarios, summary }) {
|
|
1995
|
-
const [status, setStatus] = (0,
|
|
2057
|
+
const [status, setStatus] = (0, import_react11.useState)("all");
|
|
1996
2058
|
const visible = status === "all" ? scenarios : scenarios.filter((s) => s.status === status);
|
|
1997
|
-
return /* @__PURE__ */ (0,
|
|
1998
|
-
summary ? /* @__PURE__ */ (0,
|
|
2059
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "font-sans text-foreground", children: [
|
|
2060
|
+
summary ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("p", { className: "mb-3 text-sm text-muted-foreground", children: [
|
|
1999
2061
|
summary.total,
|
|
2000
2062
|
" scenarios \xB7 ",
|
|
2001
|
-
/* @__PURE__ */ (0,
|
|
2063
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "text-pass", children: [
|
|
2002
2064
|
summary.passed,
|
|
2003
2065
|
" passed"
|
|
2004
2066
|
] }),
|
|
2005
2067
|
" \xB7",
|
|
2006
2068
|
" ",
|
|
2007
|
-
/* @__PURE__ */ (0,
|
|
2069
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "text-fail", children: [
|
|
2008
2070
|
summary.failed,
|
|
2009
2071
|
" failed"
|
|
2010
2072
|
] })
|
|
2011
2073
|
] }) : null,
|
|
2012
|
-
/* @__PURE__ */ (0,
|
|
2074
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "mb-2 flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by status", children: STATUS_FILTERS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2013
2075
|
"button",
|
|
2014
2076
|
{
|
|
2015
2077
|
type: "button",
|
|
@@ -2024,26 +2086,26 @@ function ScenarioExplorer({ scenarios, summary }) {
|
|
|
2024
2086
|
},
|
|
2025
2087
|
f.value
|
|
2026
2088
|
)) }),
|
|
2027
|
-
/* @__PURE__ */ (0,
|
|
2089
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
2028
2090
|
Command,
|
|
2029
2091
|
{
|
|
2030
2092
|
className: "rounded-lg border border-border bg-card",
|
|
2031
2093
|
filter: (value, search) => value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0,
|
|
2032
2094
|
children: [
|
|
2033
|
-
/* @__PURE__ */ (0,
|
|
2034
|
-
/* @__PURE__ */ (0,
|
|
2035
|
-
/* @__PURE__ */ (0,
|
|
2036
|
-
/* @__PURE__ */ (0,
|
|
2095
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(CommandInput, { placeholder: "Search scenarios\u2026" }),
|
|
2096
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(CommandList, { className: "max-h-none", children: [
|
|
2097
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(CommandEmpty, { children: "No scenarios match your filters." }),
|
|
2098
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2037
2099
|
CommandItem,
|
|
2038
2100
|
{
|
|
2039
2101
|
value: `${s.title} ${s.feature} ${s.tags.join(" ")}`,
|
|
2040
2102
|
asChild: true,
|
|
2041
2103
|
className: "cursor-pointer",
|
|
2042
|
-
children: /* @__PURE__ */ (0,
|
|
2043
|
-
/* @__PURE__ */ (0,
|
|
2044
|
-
/* @__PURE__ */ (0,
|
|
2045
|
-
s.tags.slice(0, 3).map((t) => /* @__PURE__ */ (0,
|
|
2046
|
-
/* @__PURE__ */ (0,
|
|
2104
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("a", { href: s.href, className: "flex items-center gap-3", children: [
|
|
2105
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Badge, { variant: s.status, children: s.status }),
|
|
2106
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
|
|
2107
|
+
s.tags.slice(0, 3).map((t) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
|
|
2108
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
|
|
2047
2109
|
] })
|
|
2048
2110
|
},
|
|
2049
2111
|
s.id
|
|
@@ -2209,11 +2271,7 @@ var story_report_v1_default = {
|
|
|
2209
2271
|
},
|
|
2210
2272
|
kind: {
|
|
2211
2273
|
type: "string",
|
|
2212
|
-
enum: [
|
|
2213
|
-
"feature",
|
|
2214
|
-
"ability",
|
|
2215
|
-
"business-need"
|
|
2216
|
-
],
|
|
2274
|
+
enum: ["feature", "ability", "business-need"],
|
|
2217
2275
|
description: "How the feature was declared. Absent when the title was derived rather than declared."
|
|
2218
2276
|
},
|
|
2219
2277
|
narrative: {
|
|
@@ -2228,13 +2286,7 @@ var story_report_v1_default = {
|
|
|
2228
2286
|
description: "Terms this feature defines, linked wherever they appear in scenario text."
|
|
2229
2287
|
}
|
|
2230
2288
|
},
|
|
2231
|
-
required: [
|
|
2232
|
-
"id",
|
|
2233
|
-
"title",
|
|
2234
|
-
"sourceFile",
|
|
2235
|
-
"summary",
|
|
2236
|
-
"scenarios"
|
|
2237
|
-
],
|
|
2289
|
+
required: ["id", "title", "sourceFile", "summary", "scenarios"],
|
|
2238
2290
|
additionalProperties: false
|
|
2239
2291
|
},
|
|
2240
2292
|
Scenario: {
|
|
@@ -2364,6 +2416,11 @@ var story_report_v1_default = {
|
|
|
2364
2416
|
type: "number",
|
|
2365
2417
|
minimum: 0
|
|
2366
2418
|
},
|
|
2419
|
+
assertions: {
|
|
2420
|
+
type: "integer",
|
|
2421
|
+
minimum: 0,
|
|
2422
|
+
description: "Assertions observed or declared for this step. Omit when the adapter cannot observe assertions; zero means observed none."
|
|
2423
|
+
},
|
|
2367
2424
|
errorMessage: {
|
|
2368
2425
|
type: "string"
|
|
2369
2426
|
},
|
|
@@ -2391,33 +2448,15 @@ var story_report_v1_default = {
|
|
|
2391
2448
|
},
|
|
2392
2449
|
StepKeyword: {
|
|
2393
2450
|
type: "string",
|
|
2394
|
-
enum: [
|
|
2395
|
-
"Given",
|
|
2396
|
-
"When",
|
|
2397
|
-
"Then",
|
|
2398
|
-
"And",
|
|
2399
|
-
"But"
|
|
2400
|
-
]
|
|
2451
|
+
enum: ["Given", "When", "Then", "And", "But"]
|
|
2401
2452
|
},
|
|
2402
2453
|
StepMode: {
|
|
2403
2454
|
type: "string",
|
|
2404
|
-
enum: [
|
|
2405
|
-
"normal",
|
|
2406
|
-
"skip",
|
|
2407
|
-
"only",
|
|
2408
|
-
"todo",
|
|
2409
|
-
"fails",
|
|
2410
|
-
"concurrent"
|
|
2411
|
-
]
|
|
2455
|
+
enum: ["normal", "skip", "only", "todo", "fails", "concurrent"]
|
|
2412
2456
|
},
|
|
2413
2457
|
TestStatus: {
|
|
2414
2458
|
type: "string",
|
|
2415
|
-
enum: [
|
|
2416
|
-
"passed",
|
|
2417
|
-
"failed",
|
|
2418
|
-
"skipped",
|
|
2419
|
-
"pending"
|
|
2420
|
-
]
|
|
2459
|
+
enum: ["passed", "failed", "skipped", "pending"]
|
|
2421
2460
|
},
|
|
2422
2461
|
Ticket: {
|
|
2423
2462
|
type: "object",
|
|
@@ -2430,9 +2469,7 @@ var story_report_v1_default = {
|
|
|
2430
2469
|
type: "string"
|
|
2431
2470
|
}
|
|
2432
2471
|
},
|
|
2433
|
-
required: [
|
|
2434
|
-
"id"
|
|
2435
|
-
],
|
|
2472
|
+
required: ["id"],
|
|
2436
2473
|
additionalProperties: false
|
|
2437
2474
|
},
|
|
2438
2475
|
Attachment: {
|
|
@@ -2450,18 +2487,10 @@ var story_report_v1_default = {
|
|
|
2450
2487
|
},
|
|
2451
2488
|
contentEncoding: {
|
|
2452
2489
|
type: "string",
|
|
2453
|
-
enum: [
|
|
2454
|
-
"BASE64",
|
|
2455
|
-
"IDENTITY"
|
|
2456
|
-
]
|
|
2490
|
+
enum: ["BASE64", "IDENTITY"]
|
|
2457
2491
|
}
|
|
2458
2492
|
},
|
|
2459
|
-
required: [
|
|
2460
|
-
"name",
|
|
2461
|
-
"mediaType",
|
|
2462
|
-
"body",
|
|
2463
|
-
"contentEncoding"
|
|
2464
|
-
],
|
|
2493
|
+
required: ["name", "mediaType", "body", "contentEncoding"],
|
|
2465
2494
|
additionalProperties: false
|
|
2466
2495
|
},
|
|
2467
2496
|
CIInfo: {
|
|
@@ -2486,9 +2515,7 @@ var story_report_v1_default = {
|
|
|
2486
2515
|
type: "string"
|
|
2487
2516
|
}
|
|
2488
2517
|
},
|
|
2489
|
-
required: [
|
|
2490
|
-
"name"
|
|
2491
|
-
],
|
|
2518
|
+
required: ["name"],
|
|
2492
2519
|
additionalProperties: false
|
|
2493
2520
|
},
|
|
2494
2521
|
CoverageSummary: {
|
|
@@ -2519,10 +2546,7 @@ var story_report_v1_default = {
|
|
|
2519
2546
|
},
|
|
2520
2547
|
DocPhase: {
|
|
2521
2548
|
type: "string",
|
|
2522
|
-
enum: [
|
|
2523
|
-
"static",
|
|
2524
|
-
"runtime"
|
|
2525
|
-
]
|
|
2549
|
+
enum: ["static", "runtime"]
|
|
2526
2550
|
},
|
|
2527
2551
|
DocEntry: {
|
|
2528
2552
|
oneOf: [
|
|
@@ -2586,11 +2610,7 @@ var story_report_v1_default = {
|
|
|
2586
2610
|
}
|
|
2587
2611
|
}
|
|
2588
2612
|
},
|
|
2589
|
-
required: [
|
|
2590
|
-
"kind",
|
|
2591
|
-
"text",
|
|
2592
|
-
"phase"
|
|
2593
|
-
],
|
|
2613
|
+
required: ["kind", "text", "phase"],
|
|
2594
2614
|
additionalProperties: false
|
|
2595
2615
|
},
|
|
2596
2616
|
DocTag: {
|
|
@@ -2615,11 +2635,7 @@ var story_report_v1_default = {
|
|
|
2615
2635
|
}
|
|
2616
2636
|
}
|
|
2617
2637
|
},
|
|
2618
|
-
required: [
|
|
2619
|
-
"kind",
|
|
2620
|
-
"names",
|
|
2621
|
-
"phase"
|
|
2622
|
-
],
|
|
2638
|
+
required: ["kind", "names", "phase"],
|
|
2623
2639
|
additionalProperties: false
|
|
2624
2640
|
},
|
|
2625
2641
|
DocKv: {
|
|
@@ -2642,12 +2658,7 @@ var story_report_v1_default = {
|
|
|
2642
2658
|
}
|
|
2643
2659
|
}
|
|
2644
2660
|
},
|
|
2645
|
-
required: [
|
|
2646
|
-
"kind",
|
|
2647
|
-
"label",
|
|
2648
|
-
"value",
|
|
2649
|
-
"phase"
|
|
2650
|
-
],
|
|
2661
|
+
required: ["kind", "label", "value", "phase"],
|
|
2651
2662
|
additionalProperties: false
|
|
2652
2663
|
},
|
|
2653
2664
|
DocCode: {
|
|
@@ -2675,12 +2686,7 @@ var story_report_v1_default = {
|
|
|
2675
2686
|
}
|
|
2676
2687
|
}
|
|
2677
2688
|
},
|
|
2678
|
-
required: [
|
|
2679
|
-
"kind",
|
|
2680
|
-
"label",
|
|
2681
|
-
"content",
|
|
2682
|
-
"phase"
|
|
2683
|
-
],
|
|
2689
|
+
required: ["kind", "label", "content", "phase"],
|
|
2684
2690
|
additionalProperties: false
|
|
2685
2691
|
},
|
|
2686
2692
|
DocTable: {
|
|
@@ -2717,13 +2723,7 @@ var story_report_v1_default = {
|
|
|
2717
2723
|
}
|
|
2718
2724
|
}
|
|
2719
2725
|
},
|
|
2720
|
-
required: [
|
|
2721
|
-
"kind",
|
|
2722
|
-
"label",
|
|
2723
|
-
"columns",
|
|
2724
|
-
"rows",
|
|
2725
|
-
"phase"
|
|
2726
|
-
],
|
|
2726
|
+
required: ["kind", "label", "columns", "rows", "phase"],
|
|
2727
2727
|
additionalProperties: false
|
|
2728
2728
|
},
|
|
2729
2729
|
DocLink: {
|
|
@@ -2748,12 +2748,7 @@ var story_report_v1_default = {
|
|
|
2748
2748
|
}
|
|
2749
2749
|
}
|
|
2750
2750
|
},
|
|
2751
|
-
required: [
|
|
2752
|
-
"kind",
|
|
2753
|
-
"label",
|
|
2754
|
-
"url",
|
|
2755
|
-
"phase"
|
|
2756
|
-
],
|
|
2751
|
+
required: ["kind", "label", "url", "phase"],
|
|
2757
2752
|
additionalProperties: false
|
|
2758
2753
|
},
|
|
2759
2754
|
DocSection: {
|
|
@@ -2778,12 +2773,7 @@ var story_report_v1_default = {
|
|
|
2778
2773
|
}
|
|
2779
2774
|
}
|
|
2780
2775
|
},
|
|
2781
|
-
required: [
|
|
2782
|
-
"kind",
|
|
2783
|
-
"title",
|
|
2784
|
-
"markdown",
|
|
2785
|
-
"phase"
|
|
2786
|
-
],
|
|
2776
|
+
required: ["kind", "title", "markdown", "phase"],
|
|
2787
2777
|
additionalProperties: false
|
|
2788
2778
|
},
|
|
2789
2779
|
DocMermaid: {
|
|
@@ -2808,11 +2798,7 @@ var story_report_v1_default = {
|
|
|
2808
2798
|
}
|
|
2809
2799
|
}
|
|
2810
2800
|
},
|
|
2811
|
-
required: [
|
|
2812
|
-
"kind",
|
|
2813
|
-
"code",
|
|
2814
|
-
"phase"
|
|
2815
|
-
],
|
|
2801
|
+
required: ["kind", "code", "phase"],
|
|
2816
2802
|
additionalProperties: false
|
|
2817
2803
|
},
|
|
2818
2804
|
DocScreenshot: {
|
|
@@ -2837,11 +2823,7 @@ var story_report_v1_default = {
|
|
|
2837
2823
|
}
|
|
2838
2824
|
}
|
|
2839
2825
|
},
|
|
2840
|
-
required: [
|
|
2841
|
-
"kind",
|
|
2842
|
-
"path",
|
|
2843
|
-
"phase"
|
|
2844
|
-
],
|
|
2826
|
+
required: ["kind", "path", "phase"],
|
|
2845
2827
|
additionalProperties: false
|
|
2846
2828
|
},
|
|
2847
2829
|
DocVideo: {
|
|
@@ -2869,11 +2851,7 @@ var story_report_v1_default = {
|
|
|
2869
2851
|
}
|
|
2870
2852
|
}
|
|
2871
2853
|
},
|
|
2872
|
-
required: [
|
|
2873
|
-
"kind",
|
|
2874
|
-
"path",
|
|
2875
|
-
"phase"
|
|
2876
|
-
],
|
|
2854
|
+
required: ["kind", "path", "phase"],
|
|
2877
2855
|
additionalProperties: false
|
|
2878
2856
|
},
|
|
2879
2857
|
DocHtml: {
|
|
@@ -2914,26 +2892,17 @@ var story_report_v1_default = {
|
|
|
2914
2892
|
}
|
|
2915
2893
|
}
|
|
2916
2894
|
},
|
|
2917
|
-
required: [
|
|
2918
|
-
"kind",
|
|
2919
|
-
"phase"
|
|
2920
|
-
],
|
|
2895
|
+
required: ["kind", "phase"],
|
|
2921
2896
|
additionalProperties: false,
|
|
2922
2897
|
oneOf: [
|
|
2923
2898
|
{
|
|
2924
|
-
required: [
|
|
2925
|
-
"path"
|
|
2926
|
-
]
|
|
2899
|
+
required: ["path"]
|
|
2927
2900
|
},
|
|
2928
2901
|
{
|
|
2929
|
-
required: [
|
|
2930
|
-
"url"
|
|
2931
|
-
]
|
|
2902
|
+
required: ["url"]
|
|
2932
2903
|
},
|
|
2933
2904
|
{
|
|
2934
|
-
required: [
|
|
2935
|
-
"content"
|
|
2936
|
-
]
|
|
2905
|
+
required: ["content"]
|
|
2937
2906
|
}
|
|
2938
2907
|
]
|
|
2939
2908
|
},
|
|
@@ -2957,11 +2926,7 @@ var story_report_v1_default = {
|
|
|
2957
2926
|
}
|
|
2958
2927
|
}
|
|
2959
2928
|
},
|
|
2960
|
-
required: [
|
|
2961
|
-
"kind",
|
|
2962
|
-
"value",
|
|
2963
|
-
"phase"
|
|
2964
|
-
],
|
|
2929
|
+
required: ["kind", "value", "phase"],
|
|
2965
2930
|
additionalProperties: false
|
|
2966
2931
|
},
|
|
2967
2932
|
DocCustom: {
|
|
@@ -2985,21 +2950,12 @@ var story_report_v1_default = {
|
|
|
2985
2950
|
}
|
|
2986
2951
|
}
|
|
2987
2952
|
},
|
|
2988
|
-
required: [
|
|
2989
|
-
"kind",
|
|
2990
|
-
"type",
|
|
2991
|
-
"data",
|
|
2992
|
-
"phase"
|
|
2993
|
-
],
|
|
2953
|
+
required: ["kind", "type", "data", "phase"],
|
|
2994
2954
|
additionalProperties: false
|
|
2995
2955
|
},
|
|
2996
2956
|
OtelSpan: {
|
|
2997
2957
|
type: "object",
|
|
2998
|
-
required: [
|
|
2999
|
-
"spanId",
|
|
3000
|
-
"name",
|
|
3001
|
-
"status"
|
|
3002
|
-
],
|
|
2958
|
+
required: ["spanId", "name", "status"],
|
|
3003
2959
|
properties: {
|
|
3004
2960
|
spanId: {
|
|
3005
2961
|
type: "string"
|
|
@@ -3023,11 +2979,7 @@ var story_report_v1_default = {
|
|
|
3023
2979
|
type: "number"
|
|
3024
2980
|
},
|
|
3025
2981
|
status: {
|
|
3026
|
-
enum: [
|
|
3027
|
-
"ok",
|
|
3028
|
-
"error",
|
|
3029
|
-
"unset"
|
|
3030
|
-
]
|
|
2982
|
+
enum: ["ok", "error", "unset"]
|
|
3031
2983
|
},
|
|
3032
2984
|
statusMessage: {
|
|
3033
2985
|
type: "string"
|
|
@@ -3051,10 +3003,7 @@ var story_report_v1_default = {
|
|
|
3051
3003
|
minLength: 1
|
|
3052
3004
|
}
|
|
3053
3005
|
},
|
|
3054
|
-
required: [
|
|
3055
|
-
"term",
|
|
3056
|
-
"definition"
|
|
3057
|
-
],
|
|
3006
|
+
required: ["term", "definition"],
|
|
3058
3007
|
additionalProperties: false
|
|
3059
3008
|
}
|
|
3060
3009
|
}
|
|
@@ -3158,6 +3107,7 @@ function parseStoryReport(input) {
|
|
|
3158
3107
|
parseStoryReport,
|
|
3159
3108
|
prUrl,
|
|
3160
3109
|
reportLastRunMs,
|
|
3110
|
+
scenarioLastRunMs,
|
|
3161
3111
|
storyReportSchema,
|
|
3162
3112
|
useBuiltinRenderers,
|
|
3163
3113
|
useCustomRenderers,
|