executable-stories-react 0.7.0 → 0.8.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 +418 -226
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -6
- package/dist/index.d.ts +17 -6
- package/dist/index.js +369 -177
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +492 -318
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +10 -1
- package/dist/interactive.d.ts +10 -1
- package/dist/interactive.js +416 -242
- package/dist/interactive.js.map +1 -1
- package/dist/parse.cjs +30 -0
- package/dist/parse.cjs.map +1 -1
- package/dist/parse.d.cts +10 -1
- package/dist/parse.d.ts +10 -1
- package/dist/parse.js +30 -0
- package/dist/parse.js.map +1 -1
- package/dist/report-island.global.js +23 -23
- package/dist/ssr.cjs +356 -194
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.d.cts +10 -1
- package/dist/ssr.d.ts +10 -1
- package/dist/ssr.js +316 -154
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +1 -1
package/dist/interactive.cjs
CHANGED
|
@@ -422,17 +422,29 @@ function DocHtml({ entry }) {
|
|
|
422
422
|
] });
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
-
// src/components/doc/
|
|
425
|
+
// src/components/doc/DocState.tsx
|
|
426
426
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
427
|
+
function DocState({ entry }) {
|
|
428
|
+
let json;
|
|
429
|
+
try {
|
|
430
|
+
json = JSON.stringify(entry.value, null, 2) ?? String(entry.value);
|
|
431
|
+
} catch {
|
|
432
|
+
json = String(entry.value);
|
|
433
|
+
}
|
|
434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CodeFigure, { label: entry.label ?? "State", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("code", { className: "font-mono text-xs language-json", children: json }) });
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// src/components/doc/DocCustom.tsx
|
|
438
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
427
439
|
function DocCustom({ entry }) {
|
|
428
440
|
const renderers = useCustomRenderers();
|
|
429
441
|
const renderer = renderers[entry.type];
|
|
430
442
|
if (renderer) {
|
|
431
|
-
return /* @__PURE__ */ (0,
|
|
443
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: renderer(entry) });
|
|
432
444
|
}
|
|
433
|
-
return /* @__PURE__ */ (0,
|
|
434
|
-
/* @__PURE__ */ (0,
|
|
435
|
-
/* @__PURE__ */ (0,
|
|
445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
|
|
446
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
|
|
447
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground", children: safeStringify(entry.data) })
|
|
436
448
|
] });
|
|
437
449
|
}
|
|
438
450
|
function safeStringify(value) {
|
|
@@ -444,45 +456,47 @@ function safeStringify(value) {
|
|
|
444
456
|
}
|
|
445
457
|
|
|
446
458
|
// src/components/doc/DocEntry.tsx
|
|
447
|
-
var
|
|
459
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
448
460
|
function DocEntry({ entry }) {
|
|
449
461
|
switch (entry.kind) {
|
|
450
462
|
case "note":
|
|
451
|
-
return /* @__PURE__ */ (0,
|
|
463
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocNote, { entry });
|
|
452
464
|
case "tag":
|
|
453
|
-
return /* @__PURE__ */ (0,
|
|
465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocTag, { entry });
|
|
454
466
|
case "kv":
|
|
455
|
-
return /* @__PURE__ */ (0,
|
|
467
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocKv, { entry });
|
|
456
468
|
case "code":
|
|
457
|
-
return /* @__PURE__ */ (0,
|
|
469
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocCode, { entry });
|
|
458
470
|
case "table":
|
|
459
|
-
return /* @__PURE__ */ (0,
|
|
471
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocTable, { entry });
|
|
460
472
|
case "link":
|
|
461
|
-
return /* @__PURE__ */ (0,
|
|
473
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocLink, { entry });
|
|
462
474
|
case "section":
|
|
463
|
-
return /* @__PURE__ */ (0,
|
|
475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocSection, { entry });
|
|
464
476
|
case "mermaid":
|
|
465
|
-
return /* @__PURE__ */ (0,
|
|
477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocMermaid, { entry });
|
|
466
478
|
case "screenshot":
|
|
467
|
-
return /* @__PURE__ */ (0,
|
|
479
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocScreenshot, { entry });
|
|
468
480
|
case "video":
|
|
469
|
-
return /* @__PURE__ */ (0,
|
|
481
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocVideo, { entry });
|
|
470
482
|
case "html":
|
|
471
|
-
return /* @__PURE__ */ (0,
|
|
483
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocHtml, { entry });
|
|
484
|
+
case "state":
|
|
485
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocState, { entry });
|
|
472
486
|
case "custom":
|
|
473
|
-
return /* @__PURE__ */ (0,
|
|
487
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocCustom, { entry });
|
|
474
488
|
}
|
|
475
489
|
}
|
|
476
490
|
|
|
477
491
|
// src/components/ReportDocEntries.tsx
|
|
478
|
-
var
|
|
492
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
479
493
|
function ReportDocEntries({ entries }) {
|
|
480
494
|
if (entries.length === 0) return null;
|
|
481
|
-
return /* @__PURE__ */ (0,
|
|
495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: entries.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DocEntry, { entry }, i)) });
|
|
482
496
|
}
|
|
483
497
|
|
|
484
498
|
// src/lib/step-params.tsx
|
|
485
|
-
var
|
|
499
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
486
500
|
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
487
501
|
function highlightStepParams(text) {
|
|
488
502
|
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
@@ -494,7 +508,7 @@ function highlightStepParams(text) {
|
|
|
494
508
|
const end = start + match[0].length;
|
|
495
509
|
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
496
510
|
nodes.push(
|
|
497
|
-
/* @__PURE__ */ (0,
|
|
511
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
498
512
|
);
|
|
499
513
|
lastIndex = end;
|
|
500
514
|
});
|
|
@@ -503,7 +517,7 @@ function highlightStepParams(text) {
|
|
|
503
517
|
}
|
|
504
518
|
|
|
505
519
|
// src/components/ReportSteps.tsx
|
|
506
|
-
var
|
|
520
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
507
521
|
var STEP_GLYPH = {
|
|
508
522
|
passed: "\u2713",
|
|
509
523
|
failed: "\u2717",
|
|
@@ -518,21 +532,21 @@ var STEP_GLYPH_COLOR = {
|
|
|
518
532
|
};
|
|
519
533
|
function ReportSteps({ scenario }) {
|
|
520
534
|
if (scenario.steps.length === 0) return null;
|
|
521
|
-
return /* @__PURE__ */ (0,
|
|
535
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ReportStepItem, { step }, step.id)) });
|
|
522
536
|
}
|
|
523
537
|
function ReportStepItem({ step }) {
|
|
524
538
|
const kw = step.keyword.toLowerCase();
|
|
525
539
|
const continuation = kw === "and" || kw === "but";
|
|
526
|
-
return /* @__PURE__ */ (0,
|
|
540
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
527
541
|
"li",
|
|
528
542
|
{
|
|
529
543
|
id: step.id,
|
|
530
544
|
"data-status": step.status,
|
|
531
545
|
className: cn("py-1.5 text-[0.8125rem] leading-normal", continuation && "pl-5"),
|
|
532
546
|
children: [
|
|
533
|
-
/* @__PURE__ */ (0,
|
|
534
|
-
/* @__PURE__ */ (0,
|
|
535
|
-
/* @__PURE__ */ (0,
|
|
547
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-baseline gap-2", children: [
|
|
548
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { "aria-hidden": true, className: cn("w-4 shrink-0 text-center text-xs", STEP_GLYPH_COLOR[step.status]), children: STEP_GLYPH[step.status] ?? "\u25CB" }),
|
|
549
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
536
550
|
"span",
|
|
537
551
|
{
|
|
538
552
|
className: cn(
|
|
@@ -542,10 +556,10 @@ function ReportStepItem({ step }) {
|
|
|
542
556
|
children: step.keyword
|
|
543
557
|
}
|
|
544
558
|
),
|
|
545
|
-
/* @__PURE__ */ (0,
|
|
546
|
-
step.durationMs > 0 ? /* @__PURE__ */ (0,
|
|
559
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
|
|
560
|
+
step.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(step.durationMs) }) : null
|
|
547
561
|
] }),
|
|
548
|
-
step.errorMessage ? /* @__PURE__ */ (0,
|
|
562
|
+
step.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
549
563
|
"pre",
|
|
550
564
|
{
|
|
551
565
|
role: "alert",
|
|
@@ -553,12 +567,72 @@ function ReportStepItem({ step }) {
|
|
|
553
567
|
children: step.errorMessage
|
|
554
568
|
}
|
|
555
569
|
) : null,
|
|
556
|
-
step.docEntries.length > 0 ? /* @__PURE__ */ (0,
|
|
570
|
+
step.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { "data-es-docs": true, className: "mt-2 ml-6", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ReportDocEntries, { entries: step.docEntries }) }) : null
|
|
557
571
|
]
|
|
558
572
|
}
|
|
559
573
|
);
|
|
560
574
|
}
|
|
561
575
|
|
|
576
|
+
// ../executable-stories-core/dist/state-diff.js
|
|
577
|
+
var isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
578
|
+
function deepEqual(a, b) {
|
|
579
|
+
if (Object.is(a, b)) return true;
|
|
580
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
581
|
+
return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
582
|
+
}
|
|
583
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
584
|
+
const ak = Object.keys(a);
|
|
585
|
+
const bk = Object.keys(b);
|
|
586
|
+
return ak.length === bk.length && ak.every((k) => k in b && deepEqual(a[k], b[k]));
|
|
587
|
+
}
|
|
588
|
+
return false;
|
|
589
|
+
}
|
|
590
|
+
var joinKey = (path, key) => path === "" ? key : `${path}.${key}`;
|
|
591
|
+
function walk(path, before, after, out) {
|
|
592
|
+
if (Object.is(before, after)) return;
|
|
593
|
+
if (Array.isArray(before) && Array.isArray(after)) {
|
|
594
|
+
const shared = Math.min(before.length, after.length);
|
|
595
|
+
for (let i = 0; i < shared; i++) walk(`${path}[${i}]`, before[i], after[i], out);
|
|
596
|
+
for (let i = shared; i < after.length; i++) out.push({ path: `${path}[${i}]`, kind: "added", after: after[i] });
|
|
597
|
+
for (let i = shared; i < before.length; i++) out.push({ path: `${path}[${i}]`, kind: "removed", before: before[i] });
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
if (isPlainObject(before) && isPlainObject(after)) {
|
|
601
|
+
for (const key of Object.keys(after)) {
|
|
602
|
+
const p = joinKey(path, key);
|
|
603
|
+
if (key in before) walk(p, before[key], after[key], out);
|
|
604
|
+
else out.push({ path: p, kind: "added", after: after[key] });
|
|
605
|
+
}
|
|
606
|
+
for (const key of Object.keys(before)) {
|
|
607
|
+
if (!(key in after)) out.push({ path: joinKey(path, key), kind: "removed", before: before[key] });
|
|
608
|
+
}
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
if (!deepEqual(before, after)) out.push({ path, kind: "changed", before, after });
|
|
612
|
+
}
|
|
613
|
+
function diffStateValues(before, after) {
|
|
614
|
+
const out = [];
|
|
615
|
+
walk("", before, after, out);
|
|
616
|
+
return out;
|
|
617
|
+
}
|
|
618
|
+
function formatStateValue(value, maxLen = 60) {
|
|
619
|
+
const s = value === void 0 ? "undefined" : JSON.stringify(value);
|
|
620
|
+
return s.length > maxLen ? `${s.slice(0, maxLen - 1)}\u2026` : s;
|
|
621
|
+
}
|
|
622
|
+
function summarizeStateChanges(changes) {
|
|
623
|
+
return changes.map((c) => {
|
|
624
|
+
const at = c.path === "" ? "(root)" : c.path;
|
|
625
|
+
switch (c.kind) {
|
|
626
|
+
case "added":
|
|
627
|
+
return `+ ${at}: ${formatStateValue(c.after)}`;
|
|
628
|
+
case "removed":
|
|
629
|
+
return `\u2212 ${at}`;
|
|
630
|
+
case "changed":
|
|
631
|
+
return `${at}: ${formatStateValue(c.before)} \u2192 ${formatStateValue(c.after)}`;
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
|
|
562
636
|
// ../executable-stories-core/dist/storyboard.js
|
|
563
637
|
function findScreenshot(entries) {
|
|
564
638
|
for (const entry of entries) {
|
|
@@ -570,26 +644,55 @@ function findScreenshot(entries) {
|
|
|
570
644
|
}
|
|
571
645
|
return void 0;
|
|
572
646
|
}
|
|
647
|
+
function findStates(entries, out = []) {
|
|
648
|
+
for (const entry of entries) {
|
|
649
|
+
if (entry.kind === "state") out.push(entry);
|
|
650
|
+
if (entry.children) findStates(entry.children, out);
|
|
651
|
+
}
|
|
652
|
+
return out;
|
|
653
|
+
}
|
|
654
|
+
var laneOf = (label) => label ?? "";
|
|
573
655
|
function extractStoryboardFrames(scenario) {
|
|
574
656
|
const frames = [];
|
|
657
|
+
const laneOrder = [];
|
|
658
|
+
const previous = /* @__PURE__ */ new Map();
|
|
575
659
|
for (const step of scenario.steps) {
|
|
576
660
|
const shot = findScreenshot(step.docEntries);
|
|
577
|
-
|
|
661
|
+
const stateDocs = findStates(step.docEntries);
|
|
662
|
+
if (!shot && stateDocs.length === 0) continue;
|
|
663
|
+
const byLane = /* @__PURE__ */ new Map();
|
|
664
|
+
for (const doc of stateDocs) {
|
|
665
|
+
const lane = laneOf(doc.label);
|
|
666
|
+
if (!byLane.has(lane) && !laneOrder.includes(lane)) laneOrder.push(lane);
|
|
667
|
+
byLane.set(lane, doc);
|
|
668
|
+
}
|
|
669
|
+
const states = [];
|
|
670
|
+
for (const lane of laneOrder) {
|
|
671
|
+
const doc = byLane.get(lane);
|
|
672
|
+
if (!doc) continue;
|
|
673
|
+
const card = {
|
|
674
|
+
...doc.label !== void 0 && { label: doc.label },
|
|
675
|
+
value: doc.value
|
|
676
|
+
};
|
|
677
|
+
if (previous.has(lane)) card.changes = diffStateValues(previous.get(lane), doc.value);
|
|
678
|
+
previous.set(lane, doc.value);
|
|
679
|
+
states.push(card);
|
|
680
|
+
}
|
|
578
681
|
frames.push({
|
|
579
682
|
stepId: step.id,
|
|
580
683
|
stepIndex: step.index,
|
|
581
684
|
keyword: step.keyword,
|
|
582
685
|
text: step.text,
|
|
583
686
|
status: step.status,
|
|
584
|
-
path: shot.path,
|
|
585
|
-
|
|
687
|
+
...shot && { screenshot: { path: shot.path, ...shot.alt !== void 0 && { alt: shot.alt } } },
|
|
688
|
+
states
|
|
586
689
|
});
|
|
587
690
|
}
|
|
588
691
|
return frames;
|
|
589
692
|
}
|
|
590
693
|
|
|
591
694
|
// src/components/ReportStoryboard.tsx
|
|
592
|
-
var
|
|
695
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
593
696
|
var FRAME_GLYPH = {
|
|
594
697
|
passed: "\u2713",
|
|
595
698
|
failed: "\u2717",
|
|
@@ -605,55 +708,114 @@ var FRAME_GLYPH_COLOR = {
|
|
|
605
708
|
function ReportStoryboard({ scenario }) {
|
|
606
709
|
const frames = extractStoryboardFrames(scenario);
|
|
607
710
|
if (frames.length < 2) return null;
|
|
608
|
-
return /* @__PURE__ */ (0,
|
|
609
|
-
/* @__PURE__ */ (0,
|
|
610
|
-
/* @__PURE__ */ (0,
|
|
711
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
|
|
712
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
|
|
713
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ol", { className: "flex items-start gap-3 overflow-x-auto pb-2", children: frames.map((frame) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(StoryboardFrameItem, { frame }, frame.stepId)) })
|
|
611
714
|
] });
|
|
612
715
|
}
|
|
613
716
|
function StoryboardFrameItem({ frame }) {
|
|
614
|
-
const src = isLocalFsPath(frame.path) ? void 0 : safeImageUrl(frame.path);
|
|
615
717
|
const label = `${frame.keyword} ${frame.text}`;
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
718
|
+
const hasStates = frame.states.length > 0;
|
|
719
|
+
const caption = /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
|
|
720
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
|
|
721
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "min-w-0", children: [
|
|
722
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
|
|
723
|
+
" ",
|
|
724
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-muted-foreground", children: frame.screenshot?.alt ?? frame.text })
|
|
725
|
+
] })
|
|
726
|
+
] });
|
|
727
|
+
return (
|
|
728
|
+
// State cards need room for diff rows; screenshot-only frames keep the
|
|
729
|
+
// original narrow film-cell width (and DOM) unchanged.
|
|
730
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("li", { className: cn("shrink-0", hasStates ? "w-64" : "w-40"), children: [
|
|
731
|
+
frame.screenshot ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(FrameScreenshot, { frame, label }) : null,
|
|
732
|
+
hasStates ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("flex flex-col gap-1.5", frame.screenshot && "mt-1.5"), children: frame.states.map((card, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(StateCardView, { card }, card.label ?? i)) }) : null,
|
|
733
|
+
frame.screenshot ? caption : (
|
|
734
|
+
// No screenshot means no image anchor, so the caption carries the
|
|
735
|
+
// jump-to-step link instead.
|
|
736
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("a", { href: `#${frame.stepId}`, "aria-label": `Jump to step: ${label}`, className: "block hover:underline", children: caption })
|
|
737
|
+
)
|
|
738
|
+
] })
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
function FrameScreenshot({ frame, label }) {
|
|
742
|
+
const path = frame.screenshot?.path ?? "";
|
|
743
|
+
const src = isLocalFsPath(path) ? void 0 : safeImageUrl(path);
|
|
744
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
745
|
+
"a",
|
|
746
|
+
{
|
|
747
|
+
href: `#${frame.stepId}`,
|
|
748
|
+
"aria-label": `Jump to step: ${label}`,
|
|
749
|
+
className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
|
|
750
|
+
children: src ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
751
|
+
"img",
|
|
752
|
+
{
|
|
753
|
+
src,
|
|
754
|
+
alt: frame.screenshot?.alt ?? label,
|
|
755
|
+
loading: "lazy",
|
|
756
|
+
className: "h-24 w-full bg-muted object-cover object-top"
|
|
757
|
+
}
|
|
758
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "flex h-24 w-full items-center justify-center border-b border-dashed border-border bg-muted px-2 text-center text-[0.6875rem] text-muted-foreground", children: "Screenshot unavailable" })
|
|
759
|
+
}
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
var CHANGE_TONE = {
|
|
763
|
+
added: "bg-pass-bg text-pass",
|
|
764
|
+
removed: "bg-fail-bg text-fail",
|
|
765
|
+
changed: "bg-skip-bg text-skip"
|
|
766
|
+
};
|
|
767
|
+
function prettyJson(value) {
|
|
768
|
+
try {
|
|
769
|
+
return JSON.stringify(value, null, 2) ?? String(value);
|
|
770
|
+
} catch {
|
|
771
|
+
return String(value);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
function StateCardView({ card }) {
|
|
775
|
+
const json = prettyJson(card.value);
|
|
776
|
+
const firstCapture = card.changes === void 0;
|
|
777
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { "data-slot": "state-card", className: "rounded-md border border-border bg-card p-2", children: [
|
|
778
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("p", { className: "flex flex-wrap items-baseline gap-1.5", children: [
|
|
779
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "inline-flex rounded-full border border-border px-1.5 font-mono text-[0.625rem] font-medium text-muted-foreground", children: card.label ?? "State" }),
|
|
780
|
+
firstCapture ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-[0.625rem] text-muted-foreground italic", children: "first capture" }) : null
|
|
781
|
+
] }),
|
|
782
|
+
!firstCapture && (card.changes && card.changes.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ul", { className: "mt-1.5 flex flex-col gap-0.5", children: card.changes.map((change, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
783
|
+
"li",
|
|
619
784
|
{
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
785
|
+
className: cn(
|
|
786
|
+
"rounded-sm px-1.5 py-0.5 font-mono text-[0.625rem] leading-snug break-all",
|
|
787
|
+
CHANGE_TONE[change.kind]
|
|
788
|
+
),
|
|
789
|
+
children: summarizeStateChanges([change])[0]
|
|
790
|
+
},
|
|
791
|
+
i
|
|
792
|
+
)) }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-1.5 text-[0.625rem] text-muted-foreground", children: "No changes" })),
|
|
793
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
794
|
+
"details",
|
|
795
|
+
{
|
|
796
|
+
open: firstCapture && json.length <= 240,
|
|
797
|
+
className: cn(firstCapture ? "mt-1.5" : "mt-1"),
|
|
798
|
+
children: [
|
|
799
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("summary", { className: "cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground", children: "Snapshot" }),
|
|
800
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("pre", { tabIndex: 0, className: "mt-1 max-h-48 overflow-auto rounded-sm bg-muted p-1.5 font-mono text-[0.625rem] leading-snug", children: json })
|
|
801
|
+
]
|
|
632
802
|
}
|
|
633
|
-
)
|
|
634
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
|
|
635
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
|
|
636
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "min-w-0", children: [
|
|
637
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
|
|
638
|
-
" ",
|
|
639
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-muted-foreground", children: frame.alt ?? frame.text })
|
|
640
|
-
] })
|
|
641
|
-
] })
|
|
803
|
+
)
|
|
642
804
|
] });
|
|
643
805
|
}
|
|
644
806
|
|
|
645
807
|
// src/components/ReportAttachments.tsx
|
|
646
|
-
var
|
|
808
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
647
809
|
function ReportAttachments({ attachments }) {
|
|
648
810
|
if (attachments.length === 0) return null;
|
|
649
811
|
return (
|
|
650
812
|
// role="group" (not a labelled <section>) so multiple scenarios' attachment
|
|
651
813
|
// blocks don't create duplicate "Attachments" region landmarks.
|
|
652
|
-
/* @__PURE__ */ (0,
|
|
814
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
|
|
653
815
|
const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
|
|
654
816
|
const isImage = att.mediaType.startsWith("image/");
|
|
655
|
-
return /* @__PURE__ */ (0,
|
|
656
|
-
/* @__PURE__ */ (0,
|
|
817
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
818
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
657
819
|
"img",
|
|
658
820
|
{
|
|
659
821
|
src: dataUri,
|
|
@@ -662,8 +824,8 @@ function ReportAttachments({ attachments }) {
|
|
|
662
824
|
className: "max-w-full rounded-md border border-border"
|
|
663
825
|
}
|
|
664
826
|
),
|
|
665
|
-
/* @__PURE__ */ (0,
|
|
666
|
-
] }) : /* @__PURE__ */ (0,
|
|
827
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
|
|
828
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
667
829
|
"a",
|
|
668
830
|
{
|
|
669
831
|
href: dataUri,
|
|
@@ -672,7 +834,7 @@ function ReportAttachments({ attachments }) {
|
|
|
672
834
|
children: [
|
|
673
835
|
att.name,
|
|
674
836
|
" ",
|
|
675
|
-
/* @__PURE__ */ (0,
|
|
837
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
676
838
|
"(",
|
|
677
839
|
att.mediaType,
|
|
678
840
|
")"
|
|
@@ -736,15 +898,15 @@ function toTraceRows(spans) {
|
|
|
736
898
|
roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
737
899
|
const rows = [];
|
|
738
900
|
const seen = /* @__PURE__ */ new Set();
|
|
739
|
-
const
|
|
901
|
+
const walk2 = (node, depth) => {
|
|
740
902
|
if (seen.has(node.span.spanId)) return;
|
|
741
903
|
seen.add(node.span.spanId);
|
|
742
904
|
rows.push({ ...node.span, depth });
|
|
743
|
-
for (const child of node.children)
|
|
905
|
+
for (const child of node.children) walk2(child, depth + 1);
|
|
744
906
|
};
|
|
745
|
-
for (const root of roots)
|
|
907
|
+
for (const root of roots) walk2(root, 0);
|
|
746
908
|
for (const node of byId.values()) {
|
|
747
|
-
if (!seen.has(node.span.spanId))
|
|
909
|
+
if (!seen.has(node.span.spanId)) walk2(node, 0);
|
|
748
910
|
}
|
|
749
911
|
return rows;
|
|
750
912
|
}
|
|
@@ -760,7 +922,7 @@ function traceWindow(rows) {
|
|
|
760
922
|
}
|
|
761
923
|
|
|
762
924
|
// src/components/ReportTrace.tsx
|
|
763
|
-
var
|
|
925
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
764
926
|
var BAR_COLOR = {
|
|
765
927
|
ok: "bg-pass",
|
|
766
928
|
error: "bg-fail",
|
|
@@ -771,8 +933,8 @@ function ReportTrace({ spans }) {
|
|
|
771
933
|
const rows = toTraceRows(spans);
|
|
772
934
|
if (rows.length === 0) return null;
|
|
773
935
|
const { minStartMs, totalMs } = traceWindow(rows);
|
|
774
|
-
return /* @__PURE__ */ (0,
|
|
775
|
-
/* @__PURE__ */ (0,
|
|
936
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
|
|
937
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
|
|
776
938
|
"Trace (",
|
|
777
939
|
rows.length,
|
|
778
940
|
" span",
|
|
@@ -781,11 +943,11 @@ function ReportTrace({ spans }) {
|
|
|
781
943
|
formatDuration(totalMs),
|
|
782
944
|
")"
|
|
783
945
|
] }),
|
|
784
|
-
/* @__PURE__ */ (0,
|
|
946
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
|
|
785
947
|
const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
|
|
786
948
|
const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
|
|
787
|
-
return /* @__PURE__ */ (0,
|
|
788
|
-
/* @__PURE__ */ (0,
|
|
949
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("li", { className: "flex items-center gap-2", children: [
|
|
950
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
789
951
|
"span",
|
|
790
952
|
{
|
|
791
953
|
className: "min-w-0 flex-1 truncate text-foreground",
|
|
@@ -794,14 +956,14 @@ function ReportTrace({ spans }) {
|
|
|
794
956
|
children: row.name
|
|
795
957
|
}
|
|
796
958
|
),
|
|
797
|
-
/* @__PURE__ */ (0,
|
|
959
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
798
960
|
"span",
|
|
799
961
|
{
|
|
800
962
|
className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
|
|
801
963
|
style: { left: `${leftPct}%`, width: `${widthPct}%` }
|
|
802
964
|
}
|
|
803
965
|
) }),
|
|
804
|
-
/* @__PURE__ */ (0,
|
|
966
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
|
|
805
967
|
] }, `${row.spanId}-${i}`);
|
|
806
968
|
}) })
|
|
807
969
|
] });
|
|
@@ -870,7 +1032,7 @@ function diffSinceLastRun(history2, scenarios) {
|
|
|
870
1032
|
}
|
|
871
1033
|
|
|
872
1034
|
// src/components/ScenarioRunHistory.tsx
|
|
873
|
-
var
|
|
1035
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
874
1036
|
var MAX_DOTS = 10;
|
|
875
1037
|
var DOT_COLOR = {
|
|
876
1038
|
passed: "bg-pass",
|
|
@@ -890,16 +1052,16 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
890
1052
|
const recent = entries.slice(-MAX_DOTS);
|
|
891
1053
|
const flaky = flakinessOf(recent) === "flaky";
|
|
892
1054
|
const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
|
|
893
|
-
return /* @__PURE__ */ (0,
|
|
894
|
-
flaky ? /* @__PURE__ */ (0,
|
|
895
|
-
/* @__PURE__ */ (0,
|
|
1055
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
1056
|
+
flaky ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
|
|
1057
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
896
1058
|
"span",
|
|
897
1059
|
{
|
|
898
1060
|
role: "img",
|
|
899
1061
|
"aria-label": `Run history: ${summary}`,
|
|
900
1062
|
title: summary,
|
|
901
1063
|
className: "flex shrink-0 items-center gap-[3px]",
|
|
902
|
-
children: recent.map((e, i) => /* @__PURE__ */ (0,
|
|
1064
|
+
children: recent.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
903
1065
|
"span",
|
|
904
1066
|
{
|
|
905
1067
|
"aria-hidden": true,
|
|
@@ -990,7 +1152,7 @@ function stringify(value) {
|
|
|
990
1152
|
return String(value);
|
|
991
1153
|
}
|
|
992
1154
|
}
|
|
993
|
-
function docEntryToMarkdown(entry) {
|
|
1155
|
+
function docEntryToMarkdown(entry, stateLanes) {
|
|
994
1156
|
const lines = [];
|
|
995
1157
|
switch (entry.kind) {
|
|
996
1158
|
case "note":
|
|
@@ -1042,13 +1204,24 @@ function docEntryToMarkdown(entry) {
|
|
|
1042
1204
|
case "custom":
|
|
1043
1205
|
lines.push(`**${entry.type}**`, "", "```json", stringify(entry.data), "```");
|
|
1044
1206
|
break;
|
|
1207
|
+
case "state": {
|
|
1208
|
+
const lane = entry.label ?? "";
|
|
1209
|
+
lines.push(`**${entry.label ?? "State"}**`);
|
|
1210
|
+
if (stateLanes?.has(lane)) {
|
|
1211
|
+
const summary = summarizeStateChanges(diffStateValues(stateLanes.get(lane), entry.value));
|
|
1212
|
+
if (summary.length > 0) lines.push("", ...summary.map((l) => `- ${l}`));
|
|
1213
|
+
}
|
|
1214
|
+
stateLanes?.set(lane, entry.value);
|
|
1215
|
+
lines.push("", "<details>", "<summary>snapshot</summary>", "", "```json", stringify(entry.value ?? null), "```", "", "</details>");
|
|
1216
|
+
break;
|
|
1217
|
+
}
|
|
1045
1218
|
}
|
|
1046
1219
|
for (const child of entry.children ?? []) {
|
|
1047
|
-
lines.push("", ...docEntryToMarkdown(child));
|
|
1220
|
+
lines.push("", ...docEntryToMarkdown(child, stateLanes));
|
|
1048
1221
|
}
|
|
1049
1222
|
return lines;
|
|
1050
1223
|
}
|
|
1051
|
-
function stepLines(step, ordinal, full) {
|
|
1224
|
+
function stepLines(step, ordinal, full, stateLanes) {
|
|
1052
1225
|
const status = step.status === "passed" ? "" : ` \u2014 **${step.status}**`;
|
|
1053
1226
|
const lines = [`${ordinal}. **${step.keyword}** ${step.text}${status}`];
|
|
1054
1227
|
if (!full) return lines;
|
|
@@ -1056,7 +1229,7 @@ function stepLines(step, ordinal, full) {
|
|
|
1056
1229
|
lines.push(...step.errorMessage.split("\n").map((l) => ` > ${l}`));
|
|
1057
1230
|
}
|
|
1058
1231
|
for (const entry of step.docEntries) {
|
|
1059
|
-
lines.push("", ...docEntryToMarkdown(entry).map((l) => l === "" ? l : ` ${l}`));
|
|
1232
|
+
lines.push("", ...docEntryToMarkdown(entry, stateLanes).map((l) => l === "" ? l : ` ${l}`));
|
|
1060
1233
|
}
|
|
1061
1234
|
return lines;
|
|
1062
1235
|
}
|
|
@@ -1065,9 +1238,10 @@ function scenarioToMarkdown(scenario, options = {}) {
|
|
|
1065
1238
|
const full = variant === "full";
|
|
1066
1239
|
const lines = full ? [`# ${scenario.title}`, ""] : [`## ${scenario.title} _(${scenario.status})_`, ""];
|
|
1067
1240
|
if (full && meta.length > 0) lines.push(...meta);
|
|
1241
|
+
const stateLanes = /* @__PURE__ */ new Map();
|
|
1068
1242
|
if (scenario.steps.length > 0) {
|
|
1069
1243
|
if (full) lines.push("", "## Steps", "");
|
|
1070
|
-
scenario.steps.forEach((step, i) => lines.push(...stepLines(step, i + 1, full)));
|
|
1244
|
+
scenario.steps.forEach((step, i) => lines.push(...stepLines(step, i + 1, full, stateLanes)));
|
|
1071
1245
|
}
|
|
1072
1246
|
if (scenario.errorMessage) {
|
|
1073
1247
|
if (full) lines.push("", "## Failure", "");
|
|
@@ -1076,7 +1250,7 @@ function scenarioToMarkdown(scenario, options = {}) {
|
|
|
1076
1250
|
}
|
|
1077
1251
|
if (full && scenario.docEntries.length > 0) {
|
|
1078
1252
|
lines.push("", "## Docs", "");
|
|
1079
|
-
for (const entry of scenario.docEntries) lines.push(...docEntryToMarkdown(entry), "");
|
|
1253
|
+
for (const entry of scenario.docEntries) lines.push(...docEntryToMarkdown(entry, stateLanes), "");
|
|
1080
1254
|
}
|
|
1081
1255
|
return lines.join("\n").replaceAll(/\n{3,}/g, "\n\n").trimEnd() + (full ? "\n" : "");
|
|
1082
1256
|
}
|
|
@@ -1116,9 +1290,9 @@ function scenarioPermalink(scenario) {
|
|
|
1116
1290
|
|
|
1117
1291
|
// src/components/ui/card.tsx
|
|
1118
1292
|
var React2 = require("react");
|
|
1119
|
-
var
|
|
1293
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1120
1294
|
function Card({ className, ...props }) {
|
|
1121
|
-
return /* @__PURE__ */ (0,
|
|
1295
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1122
1296
|
"div",
|
|
1123
1297
|
{
|
|
1124
1298
|
"data-slot": "card",
|
|
@@ -1131,7 +1305,7 @@ function Card({ className, ...props }) {
|
|
|
1131
1305
|
);
|
|
1132
1306
|
}
|
|
1133
1307
|
function CardHeader({ className, ...props }) {
|
|
1134
|
-
return /* @__PURE__ */ (0,
|
|
1308
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1135
1309
|
"div",
|
|
1136
1310
|
{
|
|
1137
1311
|
"data-slot": "card-header",
|
|
@@ -1144,7 +1318,7 @@ function CardHeader({ className, ...props }) {
|
|
|
1144
1318
|
);
|
|
1145
1319
|
}
|
|
1146
1320
|
function CardContent({ className, ...props }) {
|
|
1147
|
-
return /* @__PURE__ */ (0,
|
|
1321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1148
1322
|
"div",
|
|
1149
1323
|
{
|
|
1150
1324
|
"data-slot": "card-content",
|
|
@@ -1158,13 +1332,13 @@ function CardContent({ className, ...props }) {
|
|
|
1158
1332
|
var React3 = require("react");
|
|
1159
1333
|
var import_menu = require("@base-ui/react/menu");
|
|
1160
1334
|
var import_lucide_react = require("lucide-react");
|
|
1161
|
-
var
|
|
1335
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1162
1336
|
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";
|
|
1163
1337
|
function DropdownMenu(props) {
|
|
1164
|
-
return /* @__PURE__ */ (0,
|
|
1338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1165
1339
|
}
|
|
1166
1340
|
function DropdownMenuTrigger(props) {
|
|
1167
|
-
return /* @__PURE__ */ (0,
|
|
1341
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
1168
1342
|
}
|
|
1169
1343
|
function DropdownMenuContent({
|
|
1170
1344
|
className,
|
|
@@ -1172,14 +1346,14 @@ function DropdownMenuContent({
|
|
|
1172
1346
|
sideOffset = 4,
|
|
1173
1347
|
...props
|
|
1174
1348
|
}) {
|
|
1175
|
-
return /* @__PURE__ */ (0,
|
|
1349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1176
1350
|
import_menu.Menu.Positioner,
|
|
1177
1351
|
{
|
|
1178
1352
|
"data-slot": "dropdown-menu-positioner",
|
|
1179
1353
|
className: "z-50",
|
|
1180
1354
|
align,
|
|
1181
1355
|
sideOffset,
|
|
1182
|
-
children: /* @__PURE__ */ (0,
|
|
1356
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1183
1357
|
import_menu.Menu.Popup,
|
|
1184
1358
|
{
|
|
1185
1359
|
"data-slot": "dropdown-menu-content",
|
|
@@ -1197,7 +1371,7 @@ function DropdownMenuItem({
|
|
|
1197
1371
|
className,
|
|
1198
1372
|
...props
|
|
1199
1373
|
}) {
|
|
1200
|
-
return /* @__PURE__ */ (0,
|
|
1374
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1201
1375
|
import_menu.Menu.Item,
|
|
1202
1376
|
{
|
|
1203
1377
|
"data-slot": "dropdown-menu-item",
|
|
@@ -1209,7 +1383,7 @@ function DropdownMenuItem({
|
|
|
1209
1383
|
|
|
1210
1384
|
// src/components/ReportScenario.tsx
|
|
1211
1385
|
var import_lucide_react2 = require("lucide-react");
|
|
1212
|
-
var
|
|
1386
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1213
1387
|
var STATUS_META = {
|
|
1214
1388
|
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
1215
1389
|
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
@@ -1225,7 +1399,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1225
1399
|
const collapsible = collapse !== null && !hideTitle;
|
|
1226
1400
|
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
1227
1401
|
const actions = useScenarioActions();
|
|
1228
|
-
return /* @__PURE__ */ (0,
|
|
1402
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
1229
1403
|
Card,
|
|
1230
1404
|
{
|
|
1231
1405
|
id: scenario.id,
|
|
@@ -1233,10 +1407,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1233
1407
|
...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
|
|
1234
1408
|
className: "gap-0 py-0",
|
|
1235
1409
|
children: [
|
|
1236
|
-
/* @__PURE__ */ (0,
|
|
1237
|
-
/* @__PURE__ */ (0,
|
|
1238
|
-
hideTitle ? null : /* @__PURE__ */ (0,
|
|
1239
|
-
collapsible ? /* @__PURE__ */ (0,
|
|
1410
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(CardHeader, { className: "px-4 py-3", children: [
|
|
1411
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
1412
|
+
hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
1413
|
+
collapsible ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1240
1414
|
"button",
|
|
1241
1415
|
{
|
|
1242
1416
|
type: "button",
|
|
@@ -1245,49 +1419,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1245
1419
|
"aria-controls": bodyId,
|
|
1246
1420
|
"aria-label": `Toggle ${scenario.title}`,
|
|
1247
1421
|
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
1248
|
-
children: /* @__PURE__ */ (0,
|
|
1422
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
1249
1423
|
}
|
|
1250
1424
|
) : null,
|
|
1251
|
-
/* @__PURE__ */ (0,
|
|
1252
|
-
/* @__PURE__ */ (0,
|
|
1425
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
1426
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: scenario.title })
|
|
1253
1427
|
] }),
|
|
1254
|
-
/* @__PURE__ */ (0,
|
|
1255
|
-
/* @__PURE__ */ (0,
|
|
1256
|
-
scenario.durationMs > 0 ? /* @__PURE__ */ (0,
|
|
1257
|
-
meta.showPill ? /* @__PURE__ */ (0,
|
|
1258
|
-
actions ? /* @__PURE__ */ (0,
|
|
1259
|
-
/* @__PURE__ */ (0,
|
|
1428
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1429
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1430
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
|
|
1431
|
+
meta.showPill ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "sr-only", children: `Status: ${label}` }),
|
|
1432
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenu, { children: [
|
|
1433
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1260
1434
|
DropdownMenuTrigger,
|
|
1261
1435
|
{
|
|
1262
1436
|
"aria-label": `Actions for ${scenario.title}`,
|
|
1263
1437
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
1264
|
-
children: /* @__PURE__ */ (0,
|
|
1438
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
|
|
1265
1439
|
}
|
|
1266
1440
|
),
|
|
1267
|
-
/* @__PURE__ */ (0,
|
|
1268
|
-
/* @__PURE__ */ (0,
|
|
1269
|
-
/* @__PURE__ */ (0,
|
|
1441
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuContent, { align: "end", children: [
|
|
1442
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
1443
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.LinkIcon, {}),
|
|
1270
1444
|
" Copy link"
|
|
1271
1445
|
] }),
|
|
1272
|
-
/* @__PURE__ */ (0,
|
|
1273
|
-
/* @__PURE__ */ (0,
|
|
1446
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
1447
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.FileTextIcon, {}),
|
|
1274
1448
|
" Copy as Markdown"
|
|
1275
1449
|
] }),
|
|
1276
|
-
/* @__PURE__ */ (0,
|
|
1277
|
-
/* @__PURE__ */ (0,
|
|
1450
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
1451
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.SparklesIcon, {}),
|
|
1278
1452
|
" Explain with AI"
|
|
1279
1453
|
] })
|
|
1280
1454
|
] })
|
|
1281
1455
|
] }) : null
|
|
1282
1456
|
] })
|
|
1283
1457
|
] }),
|
|
1284
|
-
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0,
|
|
1285
|
-
scenario.tags.map((t) => /* @__PURE__ */ (0,
|
|
1286
|
-
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0,
|
|
1458
|
+
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
|
|
1459
|
+
scenario.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
|
|
1460
|
+
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("li", { children: ticket.url ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
|
|
1287
1461
|
] }) : null
|
|
1288
1462
|
] }),
|
|
1289
|
-
/* @__PURE__ */ (0,
|
|
1290
|
-
scenario.errorMessage ? /* @__PURE__ */ (0,
|
|
1463
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
1464
|
+
scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1291
1465
|
"pre",
|
|
1292
1466
|
{
|
|
1293
1467
|
role: "alert",
|
|
@@ -1295,11 +1469,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1295
1469
|
children: scenario.errorMessage
|
|
1296
1470
|
}
|
|
1297
1471
|
) : null,
|
|
1298
|
-
/* @__PURE__ */ (0,
|
|
1299
|
-
/* @__PURE__ */ (0,
|
|
1300
|
-
scenario.docEntries.length > 0 ? /* @__PURE__ */ (0,
|
|
1301
|
-
/* @__PURE__ */ (0,
|
|
1302
|
-
/* @__PURE__ */ (0,
|
|
1472
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportStoryboard, { scenario }),
|
|
1473
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportSteps, { scenario }),
|
|
1474
|
+
scenario.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
|
|
1475
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportAttachments, { attachments: scenario.attachments }),
|
|
1476
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportTrace, { spans: scenario.otelSpans })
|
|
1303
1477
|
] })
|
|
1304
1478
|
]
|
|
1305
1479
|
}
|
|
@@ -1307,13 +1481,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1307
1481
|
}
|
|
1308
1482
|
|
|
1309
1483
|
// src/components/ReportScenarioList.tsx
|
|
1310
|
-
var
|
|
1484
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1311
1485
|
function ReportScenarioList({ feature }) {
|
|
1312
|
-
return /* @__PURE__ */ (0,
|
|
1486
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_jsx_runtime26.Fragment, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ReportScenario, { scenario }, scenario.id)) });
|
|
1313
1487
|
}
|
|
1314
1488
|
|
|
1315
1489
|
// src/components/ReportFeature.tsx
|
|
1316
|
-
var
|
|
1490
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1317
1491
|
function ReportFeature({ feature }) {
|
|
1318
1492
|
const titleId = `${feature.id}-title`;
|
|
1319
1493
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1324,7 +1498,7 @@ function ReportFeature({ feature }) {
|
|
|
1324
1498
|
return (
|
|
1325
1499
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
1326
1500
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1327
|
-
/* @__PURE__ */ (0,
|
|
1501
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1328
1502
|
"section",
|
|
1329
1503
|
{
|
|
1330
1504
|
id: feature.id,
|
|
@@ -1332,9 +1506,9 @@ function ReportFeature({ feature }) {
|
|
|
1332
1506
|
"aria-labelledby": titleId,
|
|
1333
1507
|
className: "flex flex-col gap-3",
|
|
1334
1508
|
children: [
|
|
1335
|
-
/* @__PURE__ */ (0,
|
|
1336
|
-
/* @__PURE__ */ (0,
|
|
1337
|
-
/* @__PURE__ */ (0,
|
|
1509
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1510
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "min-w-0", children: [
|
|
1511
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1338
1512
|
"button",
|
|
1339
1513
|
{
|
|
1340
1514
|
type: "button",
|
|
@@ -1343,31 +1517,31 @@ function ReportFeature({ feature }) {
|
|
|
1343
1517
|
"aria-controls": bodyId,
|
|
1344
1518
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1345
1519
|
children: [
|
|
1346
|
-
/* @__PURE__ */ (0,
|
|
1347
|
-
/* @__PURE__ */ (0,
|
|
1520
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
|
|
1521
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate", children: feature.title })
|
|
1348
1522
|
]
|
|
1349
1523
|
}
|
|
1350
1524
|
) : feature.title }),
|
|
1351
|
-
/* @__PURE__ */ (0,
|
|
1525
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
|
|
1352
1526
|
] }),
|
|
1353
|
-
/* @__PURE__ */ (0,
|
|
1527
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1354
1528
|
"p",
|
|
1355
1529
|
{
|
|
1356
1530
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1357
1531
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1358
1532
|
children: [
|
|
1359
|
-
/* @__PURE__ */ (0,
|
|
1533
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { children: [
|
|
1360
1534
|
s.passed,
|
|
1361
1535
|
" passed"
|
|
1362
1536
|
] }),
|
|
1363
|
-
/* @__PURE__ */ (0,
|
|
1364
|
-
/* @__PURE__ */ (0,
|
|
1537
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1538
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1365
1539
|
s.failed,
|
|
1366
1540
|
" failed"
|
|
1367
1541
|
] }),
|
|
1368
|
-
skipped > 0 ? /* @__PURE__ */ (0,
|
|
1369
|
-
/* @__PURE__ */ (0,
|
|
1370
|
-
/* @__PURE__ */ (0,
|
|
1542
|
+
skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
1543
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1544
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { children: [
|
|
1371
1545
|
skipped,
|
|
1372
1546
|
" skipped"
|
|
1373
1547
|
] })
|
|
@@ -1376,7 +1550,7 @@ function ReportFeature({ feature }) {
|
|
|
1376
1550
|
}
|
|
1377
1551
|
)
|
|
1378
1552
|
] }),
|
|
1379
|
-
/* @__PURE__ */ (0,
|
|
1553
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportScenarioList, { feature }) })
|
|
1380
1554
|
]
|
|
1381
1555
|
}
|
|
1382
1556
|
)
|
|
@@ -1384,17 +1558,17 @@ function ReportFeature({ feature }) {
|
|
|
1384
1558
|
}
|
|
1385
1559
|
|
|
1386
1560
|
// src/components/ReportFeatureList.tsx
|
|
1387
|
-
var
|
|
1561
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1388
1562
|
function ReportFeatureList() {
|
|
1389
1563
|
const report = useReport();
|
|
1390
|
-
return /* @__PURE__ */ (0,
|
|
1564
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ReportFeature, { feature }, feature.id)) });
|
|
1391
1565
|
}
|
|
1392
1566
|
|
|
1393
1567
|
// src/components/ui/empty.tsx
|
|
1394
1568
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
1395
|
-
var
|
|
1569
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1396
1570
|
function Empty({ className, ...props }) {
|
|
1397
|
-
return /* @__PURE__ */ (0,
|
|
1571
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1398
1572
|
"div",
|
|
1399
1573
|
{
|
|
1400
1574
|
"data-slot": "empty",
|
|
@@ -1407,7 +1581,7 @@ function Empty({ className, ...props }) {
|
|
|
1407
1581
|
);
|
|
1408
1582
|
}
|
|
1409
1583
|
function EmptyHeader({ className, ...props }) {
|
|
1410
|
-
return /* @__PURE__ */ (0,
|
|
1584
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1411
1585
|
"div",
|
|
1412
1586
|
{
|
|
1413
1587
|
"data-slot": "empty-header",
|
|
@@ -1434,7 +1608,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
|
|
|
1434
1608
|
}
|
|
1435
1609
|
);
|
|
1436
1610
|
function EmptyTitle({ className, ...props }) {
|
|
1437
|
-
return /* @__PURE__ */ (0,
|
|
1611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1438
1612
|
"div",
|
|
1439
1613
|
{
|
|
1440
1614
|
"data-slot": "empty-title",
|
|
@@ -1445,16 +1619,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1445
1619
|
}
|
|
1446
1620
|
|
|
1447
1621
|
// src/components/ReportEmpty.tsx
|
|
1448
|
-
var
|
|
1622
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1449
1623
|
function ReportEmpty({ message }) {
|
|
1450
|
-
return /* @__PURE__ */ (0,
|
|
1624
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(EmptyHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
|
|
1451
1625
|
}
|
|
1452
1626
|
|
|
1453
1627
|
// src/components/ReportSummary.tsx
|
|
1454
|
-
var
|
|
1628
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1455
1629
|
function ReportSummary({ className }) {
|
|
1456
1630
|
const report = useReport();
|
|
1457
|
-
return /* @__PURE__ */ (0,
|
|
1631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1458
1632
|
ReportSummaryView,
|
|
1459
1633
|
{
|
|
1460
1634
|
summary: report.summary,
|
|
@@ -1480,7 +1654,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1480
1654
|
if (summary.pending > 0) {
|
|
1481
1655
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1482
1656
|
}
|
|
1483
|
-
return /* @__PURE__ */ (0,
|
|
1657
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1484
1658
|
"dl",
|
|
1485
1659
|
{
|
|
1486
1660
|
className: cn(
|
|
@@ -1493,17 +1667,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1493
1667
|
"aria-label": ariaLabel,
|
|
1494
1668
|
children: cards.map((c) => {
|
|
1495
1669
|
const tone = TONE[c.status];
|
|
1496
|
-
return /* @__PURE__ */ (0,
|
|
1670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
1497
1671
|
"div",
|
|
1498
1672
|
{
|
|
1499
1673
|
"data-status": c.status,
|
|
1500
1674
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1501
1675
|
children: [
|
|
1502
|
-
/* @__PURE__ */ (0,
|
|
1503
|
-
/* @__PURE__ */ (0,
|
|
1676
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
|
|
1677
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1504
1678
|
c.label
|
|
1505
1679
|
] }),
|
|
1506
|
-
/* @__PURE__ */ (0,
|
|
1680
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
|
|
1507
1681
|
]
|
|
1508
1682
|
},
|
|
1509
1683
|
c.status
|
|
@@ -1563,7 +1737,7 @@ function prUrl(ci) {
|
|
|
1563
1737
|
}
|
|
1564
1738
|
|
|
1565
1739
|
// src/components/ReportMeta.tsx
|
|
1566
|
-
var
|
|
1740
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1567
1741
|
function ReportMeta() {
|
|
1568
1742
|
const report = useReport();
|
|
1569
1743
|
const items = [];
|
|
@@ -1586,13 +1760,13 @@ function ReportMeta() {
|
|
|
1586
1760
|
const short = sha.slice(0, 8);
|
|
1587
1761
|
items.push({
|
|
1588
1762
|
label: "Commit",
|
|
1589
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1763
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1590
1764
|
});
|
|
1591
1765
|
}
|
|
1592
1766
|
if (report.ci) {
|
|
1593
1767
|
items.push({
|
|
1594
1768
|
label: "CI",
|
|
1595
|
-
value: report.ci.url ? /* @__PURE__ */ (0,
|
|
1769
|
+
value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1596
1770
|
ciDisplayName(report.ci.name),
|
|
1597
1771
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1598
1772
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1603,7 +1777,7 @@ function ReportMeta() {
|
|
|
1603
1777
|
const label = `#${report.ci.prNumber}`;
|
|
1604
1778
|
items.push({
|
|
1605
1779
|
label: "PR",
|
|
1606
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1780
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1607
1781
|
});
|
|
1608
1782
|
}
|
|
1609
1783
|
if (items.length === 0) return null;
|
|
@@ -1611,50 +1785,50 @@ function ReportMeta() {
|
|
|
1611
1785
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1612
1786
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1613
1787
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1614
|
-
/* @__PURE__ */ (0,
|
|
1615
|
-
/* @__PURE__ */ (0,
|
|
1616
|
-
/* @__PURE__ */ (0,
|
|
1788
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
|
|
1789
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.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: [
|
|
1790
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1617
1791
|
"Run details"
|
|
1618
1792
|
] }),
|
|
1619
|
-
/* @__PURE__ */ (0,
|
|
1620
|
-
/* @__PURE__ */ (0,
|
|
1621
|
-
/* @__PURE__ */ (0,
|
|
1793
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.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_runtime32.jsxs)("div", { className: "flex items-baseline gap-1.5", children: [
|
|
1794
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("dt", { className: "font-medium", children: item.label }),
|
|
1795
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1622
1796
|
] }, item.label)) })
|
|
1623
1797
|
] })
|
|
1624
1798
|
);
|
|
1625
1799
|
}
|
|
1626
1800
|
|
|
1627
1801
|
// src/components/ReportSchemaError.tsx
|
|
1628
|
-
var
|
|
1802
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1629
1803
|
function ReportSchemaError({ error }) {
|
|
1630
|
-
return /* @__PURE__ */ (0,
|
|
1631
|
-
/* @__PURE__ */ (0,
|
|
1632
|
-
/* @__PURE__ */ (0,
|
|
1633
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0,
|
|
1804
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1805
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("strong", { children: "Report could not be displayed." }) }),
|
|
1806
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { children: error.message }),
|
|
1807
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("p", { children: [
|
|
1634
1808
|
"The report bundle is newer than this version of ",
|
|
1635
|
-
/* @__PURE__ */ (0,
|
|
1809
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("code", { children: "executable-stories-react" }),
|
|
1636
1810
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1637
1811
|
] }) : null,
|
|
1638
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0,
|
|
1639
|
-
/* @__PURE__ */ (0,
|
|
1812
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("details", { children: [
|
|
1813
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("summary", { children: [
|
|
1640
1814
|
error.issues.length,
|
|
1641
1815
|
" validation issue",
|
|
1642
1816
|
error.issues.length === 1 ? "" : "s"
|
|
1643
1817
|
] }),
|
|
1644
|
-
/* @__PURE__ */ (0,
|
|
1818
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1645
1819
|
] }) : null
|
|
1646
1820
|
] });
|
|
1647
1821
|
}
|
|
1648
1822
|
|
|
1649
1823
|
// src/components/ReportShell.tsx
|
|
1650
|
-
var
|
|
1824
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1651
1825
|
function ReportErrorShell({
|
|
1652
1826
|
error,
|
|
1653
1827
|
className,
|
|
1654
1828
|
title,
|
|
1655
1829
|
dataTheme
|
|
1656
1830
|
}) {
|
|
1657
|
-
return /* @__PURE__ */ (0,
|
|
1831
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ReportSchemaError, { error }) });
|
|
1658
1832
|
}
|
|
1659
1833
|
|
|
1660
1834
|
// src/interactive/ReportInteractive.tsx
|
|
@@ -1663,12 +1837,12 @@ var import_lucide_react5 = require("lucide-react");
|
|
|
1663
1837
|
// src/components/ui/switch.tsx
|
|
1664
1838
|
var React4 = require("react");
|
|
1665
1839
|
var import_switch = require("@base-ui/react/switch");
|
|
1666
|
-
var
|
|
1840
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
1667
1841
|
function Switch({
|
|
1668
1842
|
className,
|
|
1669
1843
|
...props
|
|
1670
1844
|
}) {
|
|
1671
|
-
return /* @__PURE__ */ (0,
|
|
1845
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
1672
1846
|
import_switch.Switch.Root,
|
|
1673
1847
|
{
|
|
1674
1848
|
"data-slot": "switch",
|
|
@@ -1677,7 +1851,7 @@ function Switch({
|
|
|
1677
1851
|
className
|
|
1678
1852
|
),
|
|
1679
1853
|
...props,
|
|
1680
|
-
children: /* @__PURE__ */ (0,
|
|
1854
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
1681
1855
|
import_switch.Switch.Thumb,
|
|
1682
1856
|
{
|
|
1683
1857
|
"data-slot": "switch-thumb",
|
|
@@ -1693,7 +1867,7 @@ var React5 = __toESM(require("react"), 1);
|
|
|
1693
1867
|
var import_toggle_group = require("@base-ui/react/toggle-group");
|
|
1694
1868
|
var import_toggle = require("@base-ui/react/toggle");
|
|
1695
1869
|
var import_class_variance_authority3 = require("class-variance-authority");
|
|
1696
|
-
var
|
|
1870
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
1697
1871
|
var toggleItemVariants = (0, import_class_variance_authority3.cva)(
|
|
1698
1872
|
"inline-flex items-center justify-center gap-1.5 rounded-md font-medium whitespace-nowrap text-muted-foreground transition-[color,background-color,box-shadow] outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 data-[pressed]:bg-background data-[pressed]:text-foreground data-[pressed]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1699
1873
|
{
|
|
@@ -1715,13 +1889,13 @@ function ToggleGroup({
|
|
|
1715
1889
|
children,
|
|
1716
1890
|
...props
|
|
1717
1891
|
}) {
|
|
1718
|
-
return /* @__PURE__ */ (0,
|
|
1892
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
1719
1893
|
import_toggle_group.ToggleGroup,
|
|
1720
1894
|
{
|
|
1721
1895
|
"data-slot": "toggle-group",
|
|
1722
1896
|
className: cn("flex w-fit items-center gap-0.5 rounded-lg bg-muted p-0.5", className),
|
|
1723
1897
|
...props,
|
|
1724
|
-
children: /* @__PURE__ */ (0,
|
|
1898
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ToggleGroupContext.Provider, { value: { size }, children })
|
|
1725
1899
|
}
|
|
1726
1900
|
);
|
|
1727
1901
|
}
|
|
@@ -1732,7 +1906,7 @@ function ToggleGroupItem({
|
|
|
1732
1906
|
...props
|
|
1733
1907
|
}) {
|
|
1734
1908
|
const context = React5.useContext(ToggleGroupContext);
|
|
1735
|
-
return /* @__PURE__ */ (0,
|
|
1909
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
1736
1910
|
import_toggle.Toggle,
|
|
1737
1911
|
{
|
|
1738
1912
|
"data-slot": "toggle-group-item",
|
|
@@ -1749,9 +1923,9 @@ var import_lucide_react3 = require("lucide-react");
|
|
|
1749
1923
|
|
|
1750
1924
|
// src/components/ui/input.tsx
|
|
1751
1925
|
var React6 = require("react");
|
|
1752
|
-
var
|
|
1926
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
1753
1927
|
function Input({ className, type, ...props }) {
|
|
1754
|
-
return /* @__PURE__ */ (0,
|
|
1928
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
1755
1929
|
"input",
|
|
1756
1930
|
{
|
|
1757
1931
|
type,
|
|
@@ -1768,7 +1942,7 @@ function Input({ className, type, ...props }) {
|
|
|
1768
1942
|
}
|
|
1769
1943
|
|
|
1770
1944
|
// src/interactive/ReportSearch.tsx
|
|
1771
|
-
var
|
|
1945
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
1772
1946
|
var ReportSearch = (0, import_react8.forwardRef)(
|
|
1773
1947
|
function ReportSearch2(props, ref) {
|
|
1774
1948
|
const {
|
|
@@ -1790,17 +1964,17 @@ var ReportSearch = (0, import_react8.forwardRef)(
|
|
|
1790
1964
|
e.preventDefault();
|
|
1791
1965
|
}
|
|
1792
1966
|
}
|
|
1793
|
-
return /* @__PURE__ */ (0,
|
|
1794
|
-
/* @__PURE__ */ (0,
|
|
1795
|
-
/* @__PURE__ */ (0,
|
|
1796
|
-
/* @__PURE__ */ (0,
|
|
1967
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: cn("es-search flex flex-col gap-1", className), children: [
|
|
1968
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("label", { htmlFor: inputId, className: "sr-only", children: "Search" }),
|
|
1969
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "relative w-full sm:w-72", children: [
|
|
1970
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
1797
1971
|
import_lucide_react3.Search,
|
|
1798
1972
|
{
|
|
1799
1973
|
"aria-hidden": true,
|
|
1800
1974
|
className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
|
|
1801
1975
|
}
|
|
1802
1976
|
),
|
|
1803
|
-
/* @__PURE__ */ (0,
|
|
1977
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
1804
1978
|
Input,
|
|
1805
1979
|
{
|
|
1806
1980
|
ref,
|
|
@@ -1817,7 +1991,7 @@ var ReportSearch = (0, import_react8.forwardRef)(
|
|
|
1817
1991
|
}
|
|
1818
1992
|
)
|
|
1819
1993
|
] }),
|
|
1820
|
-
showCounts ? /* @__PURE__ */ (0,
|
|
1994
|
+
showCounts ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
1821
1995
|
"span",
|
|
1822
1996
|
{
|
|
1823
1997
|
className: "text-xs tabular-nums text-muted-foreground",
|
|
@@ -1858,7 +2032,7 @@ function scrollToScenarioId(scenarioId, options = {}) {
|
|
|
1858
2032
|
}
|
|
1859
2033
|
|
|
1860
2034
|
// src/interactive/ReportFailureBanner.tsx
|
|
1861
|
-
var
|
|
2035
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
1862
2036
|
function ReportFailureBanner({ failures }) {
|
|
1863
2037
|
const first = failures[0];
|
|
1864
2038
|
const jumpToFirst = (0, import_react9.useCallback)(() => {
|
|
@@ -1866,7 +2040,7 @@ function ReportFailureBanner({ failures }) {
|
|
|
1866
2040
|
scrollToScenarioId(first.scenarioId);
|
|
1867
2041
|
}, [first]);
|
|
1868
2042
|
if (failures.length === 0) return null;
|
|
1869
|
-
return /* @__PURE__ */ (0,
|
|
2043
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
1870
2044
|
"div",
|
|
1871
2045
|
{
|
|
1872
2046
|
className: "es-failure-banner",
|
|
@@ -1874,13 +2048,13 @@ function ReportFailureBanner({ failures }) {
|
|
|
1874
2048
|
"aria-live": "polite",
|
|
1875
2049
|
"aria-label": "Failure summary",
|
|
1876
2050
|
children: [
|
|
1877
|
-
/* @__PURE__ */ (0,
|
|
1878
|
-
/* @__PURE__ */ (0,
|
|
2051
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "es-failure-banner-text", children: [
|
|
2052
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("strong", { children: failures.length }),
|
|
1879
2053
|
" ",
|
|
1880
2054
|
"failure",
|
|
1881
2055
|
failures.length === 1 ? "" : "s"
|
|
1882
2056
|
] }),
|
|
1883
|
-
/* @__PURE__ */ (0,
|
|
2057
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1884
2058
|
"button",
|
|
1885
2059
|
{
|
|
1886
2060
|
type: "button",
|
|
@@ -1897,7 +2071,7 @@ function ReportFailureBanner({ failures }) {
|
|
|
1897
2071
|
|
|
1898
2072
|
// src/interactive/ReportFreshness.tsx
|
|
1899
2073
|
var import_react10 = require("react");
|
|
1900
|
-
var
|
|
2074
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
1901
2075
|
function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
1902
2076
|
const [now, setNow] = (0, import_react10.useState)(nowMs);
|
|
1903
2077
|
(0, import_react10.useEffect)(() => {
|
|
@@ -1905,7 +2079,7 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
1905
2079
|
}, [nowMs]);
|
|
1906
2080
|
if (lastRunMs === void 0 || now === void 0) return null;
|
|
1907
2081
|
const age = formatRelativeAge(lastRunMs, now);
|
|
1908
|
-
const runLink = ciUrl ? /* @__PURE__ */ (0,
|
|
2082
|
+
const runLink = ciUrl ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
1909
2083
|
"a",
|
|
1910
2084
|
{
|
|
1911
2085
|
href: ciUrl,
|
|
@@ -1916,9 +2090,9 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
1916
2090
|
}
|
|
1917
2091
|
) : null;
|
|
1918
2092
|
if (isReportStale(lastRunMs, staleAfterDays, now)) {
|
|
1919
|
-
return /* @__PURE__ */ (0,
|
|
1920
|
-
/* @__PURE__ */ (0,
|
|
1921
|
-
/* @__PURE__ */ (0,
|
|
2093
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "es-stale-banner", role: "status", "aria-label": "Report freshness", children: [
|
|
2094
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { children: [
|
|
2095
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("strong", { children: [
|
|
1922
2096
|
"Last verified ",
|
|
1923
2097
|
age,
|
|
1924
2098
|
"."
|
|
@@ -1928,10 +2102,10 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
1928
2102
|
runLink
|
|
1929
2103
|
] });
|
|
1930
2104
|
}
|
|
1931
|
-
return /* @__PURE__ */ (0,
|
|
2105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("p", { className: "es-freshness", "aria-label": "Report freshness", children: [
|
|
1932
2106
|
"Verified ",
|
|
1933
2107
|
age,
|
|
1934
|
-
runLink ? /* @__PURE__ */ (0,
|
|
2108
|
+
runLink ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
|
|
1935
2109
|
" \xB7 ",
|
|
1936
2110
|
runLink
|
|
1937
2111
|
] }) : null
|
|
@@ -1939,15 +2113,15 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
1939
2113
|
}
|
|
1940
2114
|
|
|
1941
2115
|
// src/interactive/ReportLastRunDelta.tsx
|
|
1942
|
-
var
|
|
2116
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
1943
2117
|
var MAX_LINKS = 5;
|
|
1944
2118
|
function ScenarioLinks({ scenarios, tone }) {
|
|
1945
|
-
return /* @__PURE__ */ (0,
|
|
1946
|
-
scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ (0,
|
|
2119
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
|
|
2120
|
+
scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { children: [
|
|
1947
2121
|
i > 0 ? ", " : "",
|
|
1948
|
-
/* @__PURE__ */ (0,
|
|
2122
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
|
|
1949
2123
|
] }, s.id)),
|
|
1950
|
-
scenarios.length > MAX_LINKS ? /* @__PURE__ */ (0,
|
|
2124
|
+
scenarios.length > MAX_LINKS ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { children: [
|
|
1951
2125
|
" and ",
|
|
1952
2126
|
scenarios.length - MAX_LINKS,
|
|
1953
2127
|
" more"
|
|
@@ -1964,23 +2138,23 @@ function ReportLastRunDelta({
|
|
|
1964
2138
|
if (!delta) return null;
|
|
1965
2139
|
const { newlyFailing, newlyPassing, added } = delta;
|
|
1966
2140
|
if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) {
|
|
1967
|
-
return /* @__PURE__ */ (0,
|
|
2141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: "Since last run: no behavior changes." });
|
|
1968
2142
|
}
|
|
1969
|
-
return /* @__PURE__ */ (0,
|
|
1970
|
-
/* @__PURE__ */ (0,
|
|
1971
|
-
newlyFailing.length > 0 ? /* @__PURE__ */ (0,
|
|
2143
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: [
|
|
2144
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "font-medium text-foreground", children: "Since last run:" }),
|
|
2145
|
+
newlyFailing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "ml-2 text-fail", children: [
|
|
1972
2146
|
newlyFailing.length,
|
|
1973
2147
|
" newly failing (",
|
|
1974
|
-
/* @__PURE__ */ (0,
|
|
2148
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ScenarioLinks, { scenarios: newlyFailing, tone: "text-fail" }),
|
|
1975
2149
|
")"
|
|
1976
2150
|
] }) : null,
|
|
1977
|
-
newlyPassing.length > 0 ? /* @__PURE__ */ (0,
|
|
2151
|
+
newlyPassing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "ml-2 text-pass", children: [
|
|
1978
2152
|
newlyPassing.length,
|
|
1979
2153
|
" fixed (",
|
|
1980
|
-
/* @__PURE__ */ (0,
|
|
2154
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ScenarioLinks, { scenarios: newlyPassing, tone: "text-pass" }),
|
|
1981
2155
|
")"
|
|
1982
2156
|
] }) : null,
|
|
1983
|
-
added.length > 0 ? /* @__PURE__ */ (0,
|
|
2157
|
+
added.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "ml-2", children: [
|
|
1984
2158
|
added.length,
|
|
1985
2159
|
" new"
|
|
1986
2160
|
] }) : null
|
|
@@ -2044,7 +2218,7 @@ function Button({
|
|
|
2044
2218
|
}
|
|
2045
2219
|
|
|
2046
2220
|
// src/interactive/ReportShortcutsHelp.tsx
|
|
2047
|
-
var
|
|
2221
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2048
2222
|
var SHORTCUTS = [
|
|
2049
2223
|
{ keys: "/", description: "Focus search" },
|
|
2050
2224
|
{ keys: "f", description: "Jump to next failure" },
|
|
@@ -2056,9 +2230,9 @@ var SHORTCUTS = [
|
|
|
2056
2230
|
];
|
|
2057
2231
|
function Keys({ keys }) {
|
|
2058
2232
|
const parts = keys.split(" ");
|
|
2059
|
-
return /* @__PURE__ */ (0,
|
|
2060
|
-
i > 0 ? /* @__PURE__ */ (0,
|
|
2061
|
-
/* @__PURE__ */ (0,
|
|
2233
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "inline-flex items-center gap-1", children: parts.map((k, i) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "inline-flex items-center gap-1", children: [
|
|
2234
|
+
i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "text-xs text-muted-foreground", children: "+" }) : null,
|
|
2235
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("kbd", { className: "inline-flex h-6 min-w-6 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-xs font-medium text-muted-foreground", children: k })
|
|
2062
2236
|
] }, k)) });
|
|
2063
2237
|
}
|
|
2064
2238
|
function ReportShortcutsHelp({ open, onClose }) {
|
|
@@ -2069,7 +2243,7 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2069
2243
|
if (open && !dialog.open) dialog.showModal();
|
|
2070
2244
|
else if (!open && dialog.open) dialog.close();
|
|
2071
2245
|
}, [open]);
|
|
2072
|
-
return /* @__PURE__ */ (0,
|
|
2246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
2073
2247
|
"dialog",
|
|
2074
2248
|
{
|
|
2075
2249
|
ref: dialogRef,
|
|
@@ -2077,12 +2251,12 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2077
2251
|
"aria-label": "Keyboard shortcuts",
|
|
2078
2252
|
onClose,
|
|
2079
2253
|
children: [
|
|
2080
|
-
/* @__PURE__ */ (0,
|
|
2081
|
-
/* @__PURE__ */ (0,
|
|
2082
|
-
/* @__PURE__ */ (0,
|
|
2083
|
-
/* @__PURE__ */ (0,
|
|
2254
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h2", { className: "text-base font-semibold", children: "Keyboard shortcuts" }),
|
|
2255
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("dl", { className: "mt-4 grid grid-cols-[auto_1fr] items-center gap-x-4 gap-y-2.5", children: SHORTCUTS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "col-span-2 grid grid-cols-subgrid items-center", children: [
|
|
2256
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("dt", { className: "justify-self-start", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Keys, { keys: s.keys }) }),
|
|
2257
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("dd", { className: "text-sm text-muted-foreground", children: s.description })
|
|
2084
2258
|
] }, s.keys)) }),
|
|
2085
|
-
/* @__PURE__ */ (0,
|
|
2259
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("form", { method: "dialog", className: "mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Button, { type: "submit", variant: "outline", size: "sm", children: "Close" }) })
|
|
2086
2260
|
]
|
|
2087
2261
|
}
|
|
2088
2262
|
);
|
|
@@ -2283,7 +2457,7 @@ function failuresFirst(report) {
|
|
|
2283
2457
|
|
|
2284
2458
|
// src/interactive/ReportFilters.tsx
|
|
2285
2459
|
var import_react14 = require("react");
|
|
2286
|
-
var
|
|
2460
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2287
2461
|
var TAG_LIMIT = 12;
|
|
2288
2462
|
function ReportFilters({
|
|
2289
2463
|
statuses,
|
|
@@ -2297,10 +2471,10 @@ function ReportFilters({
|
|
|
2297
2471
|
if (statuses.length === 0 && tags.length === 0) return null;
|
|
2298
2472
|
const tagsCollapsed = tags.length > TAG_LIMIT && !showAllTags;
|
|
2299
2473
|
const visibleTags = tagsCollapsed ? tags.slice(0, TAG_LIMIT) : tags;
|
|
2300
|
-
return /* @__PURE__ */ (0,
|
|
2301
|
-
statuses.length > 0 ? /* @__PURE__ */ (0,
|
|
2474
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
2475
|
+
statuses.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { role: "group", "aria-label": "Filter by status", className: "flex flex-wrap gap-1", children: statuses.map((opt) => {
|
|
2302
2476
|
const active = status === opt.key;
|
|
2303
|
-
return /* @__PURE__ */ (0,
|
|
2477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
2304
2478
|
"button",
|
|
2305
2479
|
{
|
|
2306
2480
|
type: "button",
|
|
@@ -2312,23 +2486,23 @@ function ReportFilters({
|
|
|
2312
2486
|
),
|
|
2313
2487
|
children: [
|
|
2314
2488
|
opt.label,
|
|
2315
|
-
/* @__PURE__ */ (0,
|
|
2489
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "ml-1 font-mono opacity-70", children: opt.count })
|
|
2316
2490
|
]
|
|
2317
2491
|
},
|
|
2318
2492
|
opt.key
|
|
2319
2493
|
);
|
|
2320
2494
|
}) }) : null,
|
|
2321
|
-
tags.length > 0 ? /* @__PURE__ */ (0,
|
|
2495
|
+
tags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("ul", { "aria-label": "Filter by tag", className: "flex flex-wrap items-center gap-1.5", children: [
|
|
2322
2496
|
visibleTags.map((tag) => {
|
|
2323
2497
|
const active = activeTags.includes(tag);
|
|
2324
|
-
return /* @__PURE__ */ (0,
|
|
2498
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2325
2499
|
"button",
|
|
2326
2500
|
{
|
|
2327
2501
|
type: "button",
|
|
2328
2502
|
"aria-pressed": active,
|
|
2329
2503
|
onClick: () => onToggleTag(tag),
|
|
2330
2504
|
className: "cursor-pointer",
|
|
2331
|
-
children: /* @__PURE__ */ (0,
|
|
2505
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2332
2506
|
Badge,
|
|
2333
2507
|
{
|
|
2334
2508
|
variant: "tag",
|
|
@@ -2341,7 +2515,7 @@ function ReportFilters({
|
|
|
2341
2515
|
}
|
|
2342
2516
|
) }, tag);
|
|
2343
2517
|
}),
|
|
2344
|
-
tags.length > TAG_LIMIT ? /* @__PURE__ */ (0,
|
|
2518
|
+
tags.length > TAG_LIMIT ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2345
2519
|
"button",
|
|
2346
2520
|
{
|
|
2347
2521
|
type: "button",
|
|
@@ -2357,7 +2531,7 @@ function ReportFilters({
|
|
|
2357
2531
|
|
|
2358
2532
|
// src/interactive/ReportToc.tsx
|
|
2359
2533
|
var import_react15 = require("react");
|
|
2360
|
-
var
|
|
2534
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2361
2535
|
var DOT = {
|
|
2362
2536
|
passed: "bg-pass",
|
|
2363
2537
|
failed: "bg-fail",
|
|
@@ -2386,11 +2560,11 @@ function TocContent({ onNavigate }) {
|
|
|
2386
2560
|
return () => observer.disconnect();
|
|
2387
2561
|
}, [scenarioIds]);
|
|
2388
2562
|
if (report.features.length === 0) return null;
|
|
2389
|
-
return /* @__PURE__ */ (0,
|
|
2390
|
-
/* @__PURE__ */ (0,
|
|
2391
|
-
/* @__PURE__ */ (0,
|
|
2563
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("ul", { className: "flex list-none flex-col gap-4 pl-0", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("li", { children: [
|
|
2564
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
|
|
2565
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("ul", { className: "flex list-none flex-col gap-0.5 pl-0", children: feature.scenarios.map((scenario) => {
|
|
2392
2566
|
const active = activeId === scenario.id;
|
|
2393
|
-
return /* @__PURE__ */ (0,
|
|
2567
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
2394
2568
|
"a",
|
|
2395
2569
|
{
|
|
2396
2570
|
href: `#${scenario.id}`,
|
|
@@ -2405,14 +2579,14 @@ function TocContent({ onNavigate }) {
|
|
|
2405
2579
|
active ? "border-primary font-medium text-foreground" : "border-border text-muted-foreground"
|
|
2406
2580
|
),
|
|
2407
2581
|
children: [
|
|
2408
|
-
/* @__PURE__ */ (0,
|
|
2582
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2409
2583
|
"span",
|
|
2410
2584
|
{
|
|
2411
2585
|
"aria-hidden": true,
|
|
2412
2586
|
className: cn("mt-1 size-1.5 shrink-0 rounded-full", DOT[scenario.status])
|
|
2413
2587
|
}
|
|
2414
2588
|
),
|
|
2415
|
-
/* @__PURE__ */ (0,
|
|
2589
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "break-words", children: scenario.title })
|
|
2416
2590
|
]
|
|
2417
2591
|
}
|
|
2418
2592
|
) }, scenario.id);
|
|
@@ -2422,14 +2596,14 @@ function TocContent({ onNavigate }) {
|
|
|
2422
2596
|
function ReportToc() {
|
|
2423
2597
|
const report = useReport();
|
|
2424
2598
|
if (report.features.length === 0) return null;
|
|
2425
|
-
return /* @__PURE__ */ (0,
|
|
2599
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
2426
2600
|
"nav",
|
|
2427
2601
|
{
|
|
2428
2602
|
"aria-label": "Table of contents",
|
|
2429
2603
|
className: "sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block",
|
|
2430
2604
|
children: [
|
|
2431
|
-
/* @__PURE__ */ (0,
|
|
2432
|
-
/* @__PURE__ */ (0,
|
|
2605
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
|
|
2606
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(TocContent, {})
|
|
2433
2607
|
]
|
|
2434
2608
|
}
|
|
2435
2609
|
);
|
|
@@ -2439,31 +2613,31 @@ function ReportToc() {
|
|
|
2439
2613
|
var import_react16 = require("react");
|
|
2440
2614
|
var import_dialog = require("@base-ui/react/dialog");
|
|
2441
2615
|
var import_lucide_react4 = require("lucide-react");
|
|
2442
|
-
var
|
|
2616
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2443
2617
|
function ReportTocDrawer() {
|
|
2444
2618
|
const report = useReport();
|
|
2445
2619
|
const [open, setOpen] = (0, import_react16.useState)(false);
|
|
2446
2620
|
if (report.features.length === 0) return null;
|
|
2447
|
-
return /* @__PURE__ */ (0,
|
|
2448
|
-
/* @__PURE__ */ (0,
|
|
2449
|
-
/* @__PURE__ */ (0,
|
|
2621
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_dialog.Dialog.Root, { open, onOpenChange: setOpen, children: [
|
|
2622
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_dialog.Dialog.Trigger, { className: "flex cursor-pointer items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground lg:hidden [&_svg]:size-3.5", children: [
|
|
2623
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react4.ListIcon, { "aria-hidden": true }),
|
|
2450
2624
|
" Contents"
|
|
2451
2625
|
] }),
|
|
2452
|
-
/* @__PURE__ */ (0,
|
|
2453
|
-
/* @__PURE__ */ (0,
|
|
2454
|
-
/* @__PURE__ */ (0,
|
|
2455
|
-
/* @__PURE__ */ (0,
|
|
2456
|
-
/* @__PURE__ */ (0,
|
|
2457
|
-
/* @__PURE__ */ (0,
|
|
2626
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_dialog.Dialog.Portal, { children: [
|
|
2627
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_dialog.Dialog.Backdrop, { className: "fixed inset-0 z-50 bg-black/50 transition-opacity duration-200 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0" }),
|
|
2628
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_dialog.Dialog.Popup, { className: "fixed inset-y-0 left-0 z-50 flex w-72 max-w-[80vw] flex-col gap-3 overflow-y-auto border-r border-border bg-background p-4 font-sans text-xs shadow-lg outline-none transition-transform duration-200 data-[ending-style]:-translate-x-full data-[starting-style]:-translate-x-full", children: [
|
|
2629
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2630
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_dialog.Dialog.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
|
|
2631
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2458
2632
|
import_dialog.Dialog.Close,
|
|
2459
2633
|
{
|
|
2460
2634
|
"aria-label": "Close contents",
|
|
2461
2635
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
2462
|
-
children: /* @__PURE__ */ (0,
|
|
2636
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react4.XIcon, { "aria-hidden": true })
|
|
2463
2637
|
}
|
|
2464
2638
|
)
|
|
2465
2639
|
] }),
|
|
2466
|
-
/* @__PURE__ */ (0,
|
|
2640
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TocContent, { onNavigate: () => setOpen(false) })
|
|
2467
2641
|
] })
|
|
2468
2642
|
] })
|
|
2469
2643
|
] });
|
|
@@ -2518,14 +2692,14 @@ function useTheme() {
|
|
|
2518
2692
|
}
|
|
2519
2693
|
|
|
2520
2694
|
// src/interactive/ReportInteractive.tsx
|
|
2521
|
-
var
|
|
2695
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2522
2696
|
function ReportInteractive(props) {
|
|
2523
2697
|
const { report, className, title, dataTheme } = props;
|
|
2524
2698
|
const result = unwrapReport(report);
|
|
2525
2699
|
if (!result.ok) {
|
|
2526
|
-
return /* @__PURE__ */ (0,
|
|
2700
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
2527
2701
|
}
|
|
2528
|
-
return /* @__PURE__ */ (0,
|
|
2702
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportInteractiveView, { ...props, report: result.data });
|
|
2529
2703
|
}
|
|
2530
2704
|
var THEME_OPTIONS = [
|
|
2531
2705
|
{ value: "light", label: "Light", Icon: import_lucide_react5.Sun },
|
|
@@ -2533,7 +2707,7 @@ var THEME_OPTIONS = [
|
|
|
2533
2707
|
{ value: "dark", label: "Dark", Icon: import_lucide_react5.Moon }
|
|
2534
2708
|
];
|
|
2535
2709
|
function ThemeSegment({ pref, onPref }) {
|
|
2536
|
-
return /* @__PURE__ */ (0,
|
|
2710
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2537
2711
|
ToggleGroup,
|
|
2538
2712
|
{
|
|
2539
2713
|
size: "sm",
|
|
@@ -2543,7 +2717,7 @@ function ThemeSegment({ pref, onPref }) {
|
|
|
2543
2717
|
if (next) onPref(next);
|
|
2544
2718
|
},
|
|
2545
2719
|
"aria-label": "Color theme",
|
|
2546
|
-
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ (0,
|
|
2720
|
+
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ToggleGroupItem, { value, "aria-label": label, title: label, className: "px-2", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Icon, {}) }, value))
|
|
2547
2721
|
}
|
|
2548
2722
|
);
|
|
2549
2723
|
}
|
|
@@ -2665,13 +2839,13 @@ function ReportInteractiveView({
|
|
|
2665
2839
|
const totalScenarios = report.summary.total;
|
|
2666
2840
|
const matchedScenarios = filtered.summary.total;
|
|
2667
2841
|
const showToc = !hideToc && totalScenarios > 3;
|
|
2668
|
-
return /* @__PURE__ */ (0,
|
|
2842
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(CollapseProvider, { value: collapse.api, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ScenarioActionsProvider, { value: scenarioActions, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ScenarioHistoryProvider, { value: scenarioHistory ?? null, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2669
2843
|
ReportRoot,
|
|
2670
2844
|
{
|
|
2671
2845
|
report: filtered,
|
|
2672
2846
|
customRenderers,
|
|
2673
2847
|
renderers,
|
|
2674
|
-
children: /* @__PURE__ */ (0,
|
|
2848
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
2675
2849
|
"main",
|
|
2676
2850
|
{
|
|
2677
2851
|
className: cn("es-report", "es-report-interactive", className),
|
|
@@ -2680,8 +2854,8 @@ function ReportInteractiveView({
|
|
|
2680
2854
|
"data-theme": dataTheme,
|
|
2681
2855
|
"data-detail-level": detail,
|
|
2682
2856
|
children: [
|
|
2683
|
-
/* @__PURE__ */ (0,
|
|
2684
|
-
/* @__PURE__ */ (0,
|
|
2857
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("header", { className: "es-report-header", children: [
|
|
2858
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
2685
2859
|
"div",
|
|
2686
2860
|
{
|
|
2687
2861
|
"data-es-navbar": true,
|
|
@@ -2690,9 +2864,9 @@ function ReportInteractiveView({
|
|
|
2690
2864
|
hideHeader ? "justify-end" : "justify-between"
|
|
2691
2865
|
),
|
|
2692
2866
|
children: [
|
|
2693
|
-
hideHeader ? null : /* @__PURE__ */ (0,
|
|
2694
|
-
/* @__PURE__ */ (0,
|
|
2695
|
-
/* @__PURE__ */ (0,
|
|
2867
|
+
hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h1", { className: "min-w-0", children: title ?? "Story Report" }),
|
|
2868
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2869
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2696
2870
|
ReportSearch,
|
|
2697
2871
|
{
|
|
2698
2872
|
ref: searchRef,
|
|
@@ -2702,16 +2876,16 @@ function ReportInteractiveView({
|
|
|
2702
2876
|
totalCount: totalScenarios
|
|
2703
2877
|
}
|
|
2704
2878
|
),
|
|
2705
|
-
/* @__PURE__ */ (0,
|
|
2879
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ThemeSegment, { pref: themePref, onPref: setThemePref })
|
|
2706
2880
|
] })
|
|
2707
2881
|
]
|
|
2708
2882
|
}
|
|
2709
2883
|
),
|
|
2710
|
-
hideHeader ? null : /* @__PURE__ */ (0,
|
|
2711
|
-
/* @__PURE__ */ (0,
|
|
2712
|
-
/* @__PURE__ */ (0,
|
|
2884
|
+
hideHeader ? null : /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
|
|
2885
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportSummary, {}),
|
|
2886
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportMeta, {})
|
|
2713
2887
|
] }),
|
|
2714
|
-
/* @__PURE__ */ (0,
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2715
2889
|
ReportFreshness,
|
|
2716
2890
|
{
|
|
2717
2891
|
lastRunMs: reportLastRunMs(report),
|
|
@@ -2719,8 +2893,8 @@ function ReportInteractiveView({
|
|
|
2719
2893
|
staleAfterDays
|
|
2720
2894
|
}
|
|
2721
2895
|
),
|
|
2722
|
-
/* @__PURE__ */ (0,
|
|
2723
|
-
/* @__PURE__ */ (0,
|
|
2896
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportLastRunDelta, { history: scenarioHistory, report }),
|
|
2897
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2724
2898
|
ReportFilters,
|
|
2725
2899
|
{
|
|
2726
2900
|
statuses: statusOptions,
|
|
@@ -2731,14 +2905,14 @@ function ReportInteractiveView({
|
|
|
2731
2905
|
onToggleTag: toggleTag
|
|
2732
2906
|
}
|
|
2733
2907
|
),
|
|
2734
|
-
/* @__PURE__ */ (0,
|
|
2735
|
-
showToc ? /* @__PURE__ */ (0,
|
|
2736
|
-
/* @__PURE__ */ (0,
|
|
2737
|
-
/* @__PURE__ */ (0,
|
|
2738
|
-
/* @__PURE__ */ (0,
|
|
2908
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border/60 pt-3", children: [
|
|
2909
|
+
showToc ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportTocDrawer, {}) : null,
|
|
2910
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2911
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Switch, { id: expandId, checked: expandedAll, onCheckedChange: setExpanded }),
|
|
2912
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("label", { htmlFor: expandId, className: "cursor-pointer text-sm text-muted-foreground select-none", children: "Expand all" })
|
|
2739
2913
|
] }),
|
|
2740
|
-
/* @__PURE__ */ (0,
|
|
2741
|
-
/* @__PURE__ */ (0,
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2915
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2742
2916
|
Switch,
|
|
2743
2917
|
{
|
|
2744
2918
|
id: docsId,
|
|
@@ -2746,16 +2920,16 @@ function ReportInteractiveView({
|
|
|
2746
2920
|
onCheckedChange: (checked) => setDetail(checked ? "full" : "minimal")
|
|
2747
2921
|
}
|
|
2748
2922
|
),
|
|
2749
|
-
/* @__PURE__ */ (0,
|
|
2923
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("label", { htmlFor: docsId, className: "cursor-pointer text-sm text-muted-foreground select-none", children: "Show documentation" })
|
|
2750
2924
|
] })
|
|
2751
2925
|
] })
|
|
2752
2926
|
] }),
|
|
2753
|
-
/* @__PURE__ */ (0,
|
|
2754
|
-
hasContent ? showToc ? /* @__PURE__ */ (0,
|
|
2755
|
-
/* @__PURE__ */ (0,
|
|
2756
|
-
/* @__PURE__ */ (0,
|
|
2757
|
-
] }) : /* @__PURE__ */ (0,
|
|
2758
|
-
/* @__PURE__ */ (0,
|
|
2927
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportFailureBanner, { failures }),
|
|
2928
|
+
hasContent ? showToc ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex gap-6", children: [
|
|
2929
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportToc, {}),
|
|
2930
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex min-w-0 flex-1 flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportFeatureList, {}) })
|
|
2931
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportFeatureList, {}) }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportEmpty, { message: query ? "No scenarios match the search." : void 0 }),
|
|
2932
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2759
2933
|
"button",
|
|
2760
2934
|
{
|
|
2761
2935
|
type: "button",
|
|
@@ -2766,8 +2940,8 @@ function ReportInteractiveView({
|
|
|
2766
2940
|
children: "?"
|
|
2767
2941
|
}
|
|
2768
2942
|
),
|
|
2769
|
-
/* @__PURE__ */ (0,
|
|
2770
|
-
toast ? /* @__PURE__ */ (0,
|
|
2943
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportShortcutsHelp, { open: helpOpen, onClose: () => setHelpOpen(false) }),
|
|
2944
|
+
toast ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2771
2945
|
"div",
|
|
2772
2946
|
{
|
|
2773
2947
|
role: "status",
|
|
@@ -2791,7 +2965,7 @@ var import_react20 = require("react");
|
|
|
2791
2965
|
|
|
2792
2966
|
// src/components/doc/MermaidView.tsx
|
|
2793
2967
|
var import_react19 = require("react");
|
|
2794
|
-
var
|
|
2968
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2795
2969
|
function prefersDark(el) {
|
|
2796
2970
|
const themed = el?.closest("[data-theme]");
|
|
2797
2971
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -2828,9 +3002,9 @@ function MermaidView({ entry, load }) {
|
|
|
2828
3002
|
};
|
|
2829
3003
|
}, [entry.code, load]);
|
|
2830
3004
|
if (svg) {
|
|
2831
|
-
return /* @__PURE__ */ (0,
|
|
2832
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
2833
|
-
/* @__PURE__ */ (0,
|
|
3005
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("figure", { ref, className: "my-3", children: [
|
|
3006
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
3007
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2834
3008
|
"div",
|
|
2835
3009
|
{
|
|
2836
3010
|
role: "img",
|
|
@@ -2841,11 +3015,11 @@ function MermaidView({ entry, load }) {
|
|
|
2841
3015
|
)
|
|
2842
3016
|
] });
|
|
2843
3017
|
}
|
|
2844
|
-
return /* @__PURE__ */ (0,
|
|
3018
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(MermaidSource, { entry, ref });
|
|
2845
3019
|
}
|
|
2846
3020
|
|
|
2847
3021
|
// src/interactive/island-renderers.tsx
|
|
2848
|
-
var
|
|
3022
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2849
3023
|
var HLJS_ESM = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
|
|
2850
3024
|
var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
|
|
2851
3025
|
function cachedCdnModule(url) {
|
|
@@ -2879,13 +3053,13 @@ function CdnHighlightedCode({ entry }) {
|
|
|
2879
3053
|
cancelled = true;
|
|
2880
3054
|
};
|
|
2881
3055
|
}, [entry.content, entry.lang]);
|
|
2882
|
-
return /* @__PURE__ */ (0,
|
|
3056
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2883
3057
|
"code",
|
|
2884
3058
|
{
|
|
2885
3059
|
className: cn("hljs font-mono text-xs", entry.lang && `language-${entry.lang}`),
|
|
2886
3060
|
dangerouslySetInnerHTML: { __html: html }
|
|
2887
3061
|
}
|
|
2888
|
-
) : /* @__PURE__ */ (0,
|
|
3062
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
2889
3063
|
}
|
|
2890
3064
|
function buildIslandRenderers(opts) {
|
|
2891
3065
|
const renderers = {};
|
|
@@ -2899,7 +3073,7 @@ function buildIslandRenderers(opts) {
|
|
|
2899
3073
|
}
|
|
2900
3074
|
|
|
2901
3075
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
2902
|
-
var
|
|
3076
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
2903
3077
|
function ReportInteractiveIsland({
|
|
2904
3078
|
report,
|
|
2905
3079
|
title,
|
|
@@ -2913,7 +3087,7 @@ function ReportInteractiveIsland({
|
|
|
2913
3087
|
() => buildIslandRenderers({ syntaxHighlighting, mermaid }),
|
|
2914
3088
|
[syntaxHighlighting, mermaid]
|
|
2915
3089
|
);
|
|
2916
|
-
return /* @__PURE__ */ (0,
|
|
3090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2917
3091
|
ReportInteractive,
|
|
2918
3092
|
{
|
|
2919
3093
|
report,
|