executable-stories-react 0.6.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 +472 -194
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -2
- package/dist/index.d.ts +30 -2
- package/dist/index.js +468 -191
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +544 -286
- 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 +541 -283
- 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 +31 -31
- package/dist/ssr.cjs +408 -162
- 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 +405 -159
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +1 -1
package/dist/interactive.cjs
CHANGED
|
@@ -264,7 +264,7 @@ function DocLink({ entry }) {
|
|
|
264
264
|
// src/components/doc/DocSection.tsx
|
|
265
265
|
var import_marked = require("marked");
|
|
266
266
|
|
|
267
|
-
//
|
|
267
|
+
// ../executable-stories-core/dist/utils/url.js
|
|
268
268
|
function safeUrl(value) {
|
|
269
269
|
if (!value) return void 0;
|
|
270
270
|
const trimmed = value.trim();
|
|
@@ -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,24 +567,255 @@ 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
|
+
|
|
636
|
+
// ../executable-stories-core/dist/storyboard.js
|
|
637
|
+
function findScreenshot(entries) {
|
|
638
|
+
for (const entry of entries) {
|
|
639
|
+
if (entry.kind === "screenshot") return entry;
|
|
640
|
+
if (entry.children) {
|
|
641
|
+
const nested = findScreenshot(entry.children);
|
|
642
|
+
if (nested) return nested;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
return void 0;
|
|
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 ?? "";
|
|
655
|
+
function extractStoryboardFrames(scenario) {
|
|
656
|
+
const frames = [];
|
|
657
|
+
const laneOrder = [];
|
|
658
|
+
const previous = /* @__PURE__ */ new Map();
|
|
659
|
+
for (const step of scenario.steps) {
|
|
660
|
+
const shot = findScreenshot(step.docEntries);
|
|
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
|
+
}
|
|
681
|
+
frames.push({
|
|
682
|
+
stepId: step.id,
|
|
683
|
+
stepIndex: step.index,
|
|
684
|
+
keyword: step.keyword,
|
|
685
|
+
text: step.text,
|
|
686
|
+
status: step.status,
|
|
687
|
+
...shot && { screenshot: { path: shot.path, ...shot.alt !== void 0 && { alt: shot.alt } } },
|
|
688
|
+
states
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
return frames;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// src/components/ReportStoryboard.tsx
|
|
695
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
696
|
+
var FRAME_GLYPH = {
|
|
697
|
+
passed: "\u2713",
|
|
698
|
+
failed: "\u2717",
|
|
699
|
+
skipped: "\u25CB",
|
|
700
|
+
pending: "\u25CB"
|
|
701
|
+
};
|
|
702
|
+
var FRAME_GLYPH_COLOR = {
|
|
703
|
+
passed: "text-pass",
|
|
704
|
+
failed: "text-fail",
|
|
705
|
+
skipped: "text-skip",
|
|
706
|
+
pending: "text-pend"
|
|
707
|
+
};
|
|
708
|
+
function ReportStoryboard({ scenario }) {
|
|
709
|
+
const frames = extractStoryboardFrames(scenario);
|
|
710
|
+
if (frames.length < 2) return null;
|
|
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)) })
|
|
714
|
+
] });
|
|
715
|
+
}
|
|
716
|
+
function StoryboardFrameItem({ frame }) {
|
|
717
|
+
const label = `${frame.keyword} ${frame.text}`;
|
|
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",
|
|
784
|
+
{
|
|
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
|
+
]
|
|
802
|
+
}
|
|
803
|
+
)
|
|
804
|
+
] });
|
|
805
|
+
}
|
|
806
|
+
|
|
562
807
|
// src/components/ReportAttachments.tsx
|
|
563
|
-
var
|
|
808
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
564
809
|
function ReportAttachments({ attachments }) {
|
|
565
810
|
if (attachments.length === 0) return null;
|
|
566
811
|
return (
|
|
567
812
|
// role="group" (not a labelled <section>) so multiple scenarios' attachment
|
|
568
813
|
// blocks don't create duplicate "Attachments" region landmarks.
|
|
569
|
-
/* @__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) => {
|
|
570
815
|
const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
|
|
571
816
|
const isImage = att.mediaType.startsWith("image/");
|
|
572
|
-
return /* @__PURE__ */ (0,
|
|
573
|
-
/* @__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)(
|
|
574
819
|
"img",
|
|
575
820
|
{
|
|
576
821
|
src: dataUri,
|
|
@@ -579,8 +824,8 @@ function ReportAttachments({ attachments }) {
|
|
|
579
824
|
className: "max-w-full rounded-md border border-border"
|
|
580
825
|
}
|
|
581
826
|
),
|
|
582
|
-
/* @__PURE__ */ (0,
|
|
583
|
-
] }) : /* @__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)(
|
|
584
829
|
"a",
|
|
585
830
|
{
|
|
586
831
|
href: dataUri,
|
|
@@ -589,7 +834,7 @@ function ReportAttachments({ attachments }) {
|
|
|
589
834
|
children: [
|
|
590
835
|
att.name,
|
|
591
836
|
" ",
|
|
592
|
-
/* @__PURE__ */ (0,
|
|
837
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
593
838
|
"(",
|
|
594
839
|
att.mediaType,
|
|
595
840
|
")"
|
|
@@ -653,15 +898,15 @@ function toTraceRows(spans) {
|
|
|
653
898
|
roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
654
899
|
const rows = [];
|
|
655
900
|
const seen = /* @__PURE__ */ new Set();
|
|
656
|
-
const
|
|
901
|
+
const walk2 = (node, depth) => {
|
|
657
902
|
if (seen.has(node.span.spanId)) return;
|
|
658
903
|
seen.add(node.span.spanId);
|
|
659
904
|
rows.push({ ...node.span, depth });
|
|
660
|
-
for (const child of node.children)
|
|
905
|
+
for (const child of node.children) walk2(child, depth + 1);
|
|
661
906
|
};
|
|
662
|
-
for (const root of roots)
|
|
907
|
+
for (const root of roots) walk2(root, 0);
|
|
663
908
|
for (const node of byId.values()) {
|
|
664
|
-
if (!seen.has(node.span.spanId))
|
|
909
|
+
if (!seen.has(node.span.spanId)) walk2(node, 0);
|
|
665
910
|
}
|
|
666
911
|
return rows;
|
|
667
912
|
}
|
|
@@ -677,7 +922,7 @@ function traceWindow(rows) {
|
|
|
677
922
|
}
|
|
678
923
|
|
|
679
924
|
// src/components/ReportTrace.tsx
|
|
680
|
-
var
|
|
925
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
681
926
|
var BAR_COLOR = {
|
|
682
927
|
ok: "bg-pass",
|
|
683
928
|
error: "bg-fail",
|
|
@@ -688,8 +933,8 @@ function ReportTrace({ spans }) {
|
|
|
688
933
|
const rows = toTraceRows(spans);
|
|
689
934
|
if (rows.length === 0) return null;
|
|
690
935
|
const { minStartMs, totalMs } = traceWindow(rows);
|
|
691
|
-
return /* @__PURE__ */ (0,
|
|
692
|
-
/* @__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: [
|
|
693
938
|
"Trace (",
|
|
694
939
|
rows.length,
|
|
695
940
|
" span",
|
|
@@ -698,11 +943,11 @@ function ReportTrace({ spans }) {
|
|
|
698
943
|
formatDuration(totalMs),
|
|
699
944
|
")"
|
|
700
945
|
] }),
|
|
701
|
-
/* @__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) => {
|
|
702
947
|
const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
|
|
703
948
|
const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
|
|
704
|
-
return /* @__PURE__ */ (0,
|
|
705
|
-
/* @__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)(
|
|
706
951
|
"span",
|
|
707
952
|
{
|
|
708
953
|
className: "min-w-0 flex-1 truncate text-foreground",
|
|
@@ -711,14 +956,14 @@ function ReportTrace({ spans }) {
|
|
|
711
956
|
children: row.name
|
|
712
957
|
}
|
|
713
958
|
),
|
|
714
|
-
/* @__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)(
|
|
715
960
|
"span",
|
|
716
961
|
{
|
|
717
962
|
className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
|
|
718
963
|
style: { left: `${leftPct}%`, width: `${widthPct}%` }
|
|
719
964
|
}
|
|
720
965
|
) }),
|
|
721
|
-
/* @__PURE__ */ (0,
|
|
966
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
|
|
722
967
|
] }, `${row.spanId}-${i}`);
|
|
723
968
|
}) })
|
|
724
969
|
] });
|
|
@@ -787,7 +1032,7 @@ function diffSinceLastRun(history2, scenarios) {
|
|
|
787
1032
|
}
|
|
788
1033
|
|
|
789
1034
|
// src/components/ScenarioRunHistory.tsx
|
|
790
|
-
var
|
|
1035
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
791
1036
|
var MAX_DOTS = 10;
|
|
792
1037
|
var DOT_COLOR = {
|
|
793
1038
|
passed: "bg-pass",
|
|
@@ -807,16 +1052,16 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
807
1052
|
const recent = entries.slice(-MAX_DOTS);
|
|
808
1053
|
const flaky = flakinessOf(recent) === "flaky";
|
|
809
1054
|
const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
|
|
810
|
-
return /* @__PURE__ */ (0,
|
|
811
|
-
flaky ? /* @__PURE__ */ (0,
|
|
812
|
-
/* @__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)(
|
|
813
1058
|
"span",
|
|
814
1059
|
{
|
|
815
1060
|
role: "img",
|
|
816
1061
|
"aria-label": `Run history: ${summary}`,
|
|
817
1062
|
title: summary,
|
|
818
1063
|
className: "flex shrink-0 items-center gap-[3px]",
|
|
819
|
-
children: recent.map((e, i) => /* @__PURE__ */ (0,
|
|
1064
|
+
children: recent.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
820
1065
|
"span",
|
|
821
1066
|
{
|
|
822
1067
|
"aria-hidden": true,
|
|
@@ -907,7 +1152,7 @@ function stringify(value) {
|
|
|
907
1152
|
return String(value);
|
|
908
1153
|
}
|
|
909
1154
|
}
|
|
910
|
-
function docEntryToMarkdown(entry) {
|
|
1155
|
+
function docEntryToMarkdown(entry, stateLanes) {
|
|
911
1156
|
const lines = [];
|
|
912
1157
|
switch (entry.kind) {
|
|
913
1158
|
case "note":
|
|
@@ -959,13 +1204,24 @@ function docEntryToMarkdown(entry) {
|
|
|
959
1204
|
case "custom":
|
|
960
1205
|
lines.push(`**${entry.type}**`, "", "```json", stringify(entry.data), "```");
|
|
961
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
|
+
}
|
|
962
1218
|
}
|
|
963
1219
|
for (const child of entry.children ?? []) {
|
|
964
|
-
lines.push("", ...docEntryToMarkdown(child));
|
|
1220
|
+
lines.push("", ...docEntryToMarkdown(child, stateLanes));
|
|
965
1221
|
}
|
|
966
1222
|
return lines;
|
|
967
1223
|
}
|
|
968
|
-
function stepLines(step, ordinal, full) {
|
|
1224
|
+
function stepLines(step, ordinal, full, stateLanes) {
|
|
969
1225
|
const status = step.status === "passed" ? "" : ` \u2014 **${step.status}**`;
|
|
970
1226
|
const lines = [`${ordinal}. **${step.keyword}** ${step.text}${status}`];
|
|
971
1227
|
if (!full) return lines;
|
|
@@ -973,7 +1229,7 @@ function stepLines(step, ordinal, full) {
|
|
|
973
1229
|
lines.push(...step.errorMessage.split("\n").map((l) => ` > ${l}`));
|
|
974
1230
|
}
|
|
975
1231
|
for (const entry of step.docEntries) {
|
|
976
|
-
lines.push("", ...docEntryToMarkdown(entry).map((l) => l === "" ? l : ` ${l}`));
|
|
1232
|
+
lines.push("", ...docEntryToMarkdown(entry, stateLanes).map((l) => l === "" ? l : ` ${l}`));
|
|
977
1233
|
}
|
|
978
1234
|
return lines;
|
|
979
1235
|
}
|
|
@@ -982,9 +1238,10 @@ function scenarioToMarkdown(scenario, options = {}) {
|
|
|
982
1238
|
const full = variant === "full";
|
|
983
1239
|
const lines = full ? [`# ${scenario.title}`, ""] : [`## ${scenario.title} _(${scenario.status})_`, ""];
|
|
984
1240
|
if (full && meta.length > 0) lines.push(...meta);
|
|
1241
|
+
const stateLanes = /* @__PURE__ */ new Map();
|
|
985
1242
|
if (scenario.steps.length > 0) {
|
|
986
1243
|
if (full) lines.push("", "## Steps", "");
|
|
987
|
-
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)));
|
|
988
1245
|
}
|
|
989
1246
|
if (scenario.errorMessage) {
|
|
990
1247
|
if (full) lines.push("", "## Failure", "");
|
|
@@ -993,7 +1250,7 @@ function scenarioToMarkdown(scenario, options = {}) {
|
|
|
993
1250
|
}
|
|
994
1251
|
if (full && scenario.docEntries.length > 0) {
|
|
995
1252
|
lines.push("", "## Docs", "");
|
|
996
|
-
for (const entry of scenario.docEntries) lines.push(...docEntryToMarkdown(entry), "");
|
|
1253
|
+
for (const entry of scenario.docEntries) lines.push(...docEntryToMarkdown(entry, stateLanes), "");
|
|
997
1254
|
}
|
|
998
1255
|
return lines.join("\n").replaceAll(/\n{3,}/g, "\n\n").trimEnd() + (full ? "\n" : "");
|
|
999
1256
|
}
|
|
@@ -1033,9 +1290,9 @@ function scenarioPermalink(scenario) {
|
|
|
1033
1290
|
|
|
1034
1291
|
// src/components/ui/card.tsx
|
|
1035
1292
|
var React2 = require("react");
|
|
1036
|
-
var
|
|
1293
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1037
1294
|
function Card({ className, ...props }) {
|
|
1038
|
-
return /* @__PURE__ */ (0,
|
|
1295
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1039
1296
|
"div",
|
|
1040
1297
|
{
|
|
1041
1298
|
"data-slot": "card",
|
|
@@ -1048,7 +1305,7 @@ function Card({ className, ...props }) {
|
|
|
1048
1305
|
);
|
|
1049
1306
|
}
|
|
1050
1307
|
function CardHeader({ className, ...props }) {
|
|
1051
|
-
return /* @__PURE__ */ (0,
|
|
1308
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1052
1309
|
"div",
|
|
1053
1310
|
{
|
|
1054
1311
|
"data-slot": "card-header",
|
|
@@ -1061,7 +1318,7 @@ function CardHeader({ className, ...props }) {
|
|
|
1061
1318
|
);
|
|
1062
1319
|
}
|
|
1063
1320
|
function CardContent({ className, ...props }) {
|
|
1064
|
-
return /* @__PURE__ */ (0,
|
|
1321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1065
1322
|
"div",
|
|
1066
1323
|
{
|
|
1067
1324
|
"data-slot": "card-content",
|
|
@@ -1075,13 +1332,13 @@ function CardContent({ className, ...props }) {
|
|
|
1075
1332
|
var React3 = require("react");
|
|
1076
1333
|
var import_menu = require("@base-ui/react/menu");
|
|
1077
1334
|
var import_lucide_react = require("lucide-react");
|
|
1078
|
-
var
|
|
1335
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1079
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";
|
|
1080
1337
|
function DropdownMenu(props) {
|
|
1081
|
-
return /* @__PURE__ */ (0,
|
|
1338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1082
1339
|
}
|
|
1083
1340
|
function DropdownMenuTrigger(props) {
|
|
1084
|
-
return /* @__PURE__ */ (0,
|
|
1341
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
1085
1342
|
}
|
|
1086
1343
|
function DropdownMenuContent({
|
|
1087
1344
|
className,
|
|
@@ -1089,14 +1346,14 @@ function DropdownMenuContent({
|
|
|
1089
1346
|
sideOffset = 4,
|
|
1090
1347
|
...props
|
|
1091
1348
|
}) {
|
|
1092
|
-
return /* @__PURE__ */ (0,
|
|
1349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1093
1350
|
import_menu.Menu.Positioner,
|
|
1094
1351
|
{
|
|
1095
1352
|
"data-slot": "dropdown-menu-positioner",
|
|
1096
1353
|
className: "z-50",
|
|
1097
1354
|
align,
|
|
1098
1355
|
sideOffset,
|
|
1099
|
-
children: /* @__PURE__ */ (0,
|
|
1356
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1100
1357
|
import_menu.Menu.Popup,
|
|
1101
1358
|
{
|
|
1102
1359
|
"data-slot": "dropdown-menu-content",
|
|
@@ -1114,7 +1371,7 @@ function DropdownMenuItem({
|
|
|
1114
1371
|
className,
|
|
1115
1372
|
...props
|
|
1116
1373
|
}) {
|
|
1117
|
-
return /* @__PURE__ */ (0,
|
|
1374
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1118
1375
|
import_menu.Menu.Item,
|
|
1119
1376
|
{
|
|
1120
1377
|
"data-slot": "dropdown-menu-item",
|
|
@@ -1126,7 +1383,7 @@ function DropdownMenuItem({
|
|
|
1126
1383
|
|
|
1127
1384
|
// src/components/ReportScenario.tsx
|
|
1128
1385
|
var import_lucide_react2 = require("lucide-react");
|
|
1129
|
-
var
|
|
1386
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1130
1387
|
var STATUS_META = {
|
|
1131
1388
|
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
1132
1389
|
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
@@ -1142,7 +1399,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1142
1399
|
const collapsible = collapse !== null && !hideTitle;
|
|
1143
1400
|
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
1144
1401
|
const actions = useScenarioActions();
|
|
1145
|
-
return /* @__PURE__ */ (0,
|
|
1402
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
1146
1403
|
Card,
|
|
1147
1404
|
{
|
|
1148
1405
|
id: scenario.id,
|
|
@@ -1150,10 +1407,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1150
1407
|
...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
|
|
1151
1408
|
className: "gap-0 py-0",
|
|
1152
1409
|
children: [
|
|
1153
|
-
/* @__PURE__ */ (0,
|
|
1154
|
-
/* @__PURE__ */ (0,
|
|
1155
|
-
hideTitle ? null : /* @__PURE__ */ (0,
|
|
1156
|
-
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)(
|
|
1157
1414
|
"button",
|
|
1158
1415
|
{
|
|
1159
1416
|
type: "button",
|
|
@@ -1162,49 +1419,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1162
1419
|
"aria-controls": bodyId,
|
|
1163
1420
|
"aria-label": `Toggle ${scenario.title}`,
|
|
1164
1421
|
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
1165
|
-
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" })
|
|
1166
1423
|
}
|
|
1167
1424
|
) : null,
|
|
1168
|
-
/* @__PURE__ */ (0,
|
|
1169
|
-
/* @__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 })
|
|
1170
1427
|
] }),
|
|
1171
|
-
/* @__PURE__ */ (0,
|
|
1172
|
-
/* @__PURE__ */ (0,
|
|
1173
|
-
scenario.durationMs > 0 ? /* @__PURE__ */ (0,
|
|
1174
|
-
meta.showPill ? /* @__PURE__ */ (0,
|
|
1175
|
-
actions ? /* @__PURE__ */ (0,
|
|
1176
|
-
/* @__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)(
|
|
1177
1434
|
DropdownMenuTrigger,
|
|
1178
1435
|
{
|
|
1179
1436
|
"aria-label": `Actions for ${scenario.title}`,
|
|
1180
1437
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
1181
|
-
children: /* @__PURE__ */ (0,
|
|
1438
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
|
|
1182
1439
|
}
|
|
1183
1440
|
),
|
|
1184
|
-
/* @__PURE__ */ (0,
|
|
1185
|
-
/* @__PURE__ */ (0,
|
|
1186
|
-
/* @__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, {}),
|
|
1187
1444
|
" Copy link"
|
|
1188
1445
|
] }),
|
|
1189
|
-
/* @__PURE__ */ (0,
|
|
1190
|
-
/* @__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, {}),
|
|
1191
1448
|
" Copy as Markdown"
|
|
1192
1449
|
] }),
|
|
1193
|
-
/* @__PURE__ */ (0,
|
|
1194
|
-
/* @__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, {}),
|
|
1195
1452
|
" Explain with AI"
|
|
1196
1453
|
] })
|
|
1197
1454
|
] })
|
|
1198
1455
|
] }) : null
|
|
1199
1456
|
] })
|
|
1200
1457
|
] }),
|
|
1201
|
-
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0,
|
|
1202
|
-
scenario.tags.map((t) => /* @__PURE__ */ (0,
|
|
1203
|
-
(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}`))
|
|
1204
1461
|
] }) : null
|
|
1205
1462
|
] }),
|
|
1206
|
-
/* @__PURE__ */ (0,
|
|
1207
|
-
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)(
|
|
1208
1465
|
"pre",
|
|
1209
1466
|
{
|
|
1210
1467
|
role: "alert",
|
|
@@ -1212,10 +1469,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1212
1469
|
children: scenario.errorMessage
|
|
1213
1470
|
}
|
|
1214
1471
|
) : null,
|
|
1215
|
-
/* @__PURE__ */ (0,
|
|
1216
|
-
|
|
1217
|
-
/* @__PURE__ */ (0,
|
|
1218
|
-
/* @__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 })
|
|
1219
1477
|
] })
|
|
1220
1478
|
]
|
|
1221
1479
|
}
|
|
@@ -1223,13 +1481,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1223
1481
|
}
|
|
1224
1482
|
|
|
1225
1483
|
// src/components/ReportScenarioList.tsx
|
|
1226
|
-
var
|
|
1484
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1227
1485
|
function ReportScenarioList({ feature }) {
|
|
1228
|
-
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)) });
|
|
1229
1487
|
}
|
|
1230
1488
|
|
|
1231
1489
|
// src/components/ReportFeature.tsx
|
|
1232
|
-
var
|
|
1490
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1233
1491
|
function ReportFeature({ feature }) {
|
|
1234
1492
|
const titleId = `${feature.id}-title`;
|
|
1235
1493
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1240,7 +1498,7 @@ function ReportFeature({ feature }) {
|
|
|
1240
1498
|
return (
|
|
1241
1499
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
1242
1500
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1243
|
-
/* @__PURE__ */ (0,
|
|
1501
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1244
1502
|
"section",
|
|
1245
1503
|
{
|
|
1246
1504
|
id: feature.id,
|
|
@@ -1248,9 +1506,9 @@ function ReportFeature({ feature }) {
|
|
|
1248
1506
|
"aria-labelledby": titleId,
|
|
1249
1507
|
className: "flex flex-col gap-3",
|
|
1250
1508
|
children: [
|
|
1251
|
-
/* @__PURE__ */ (0,
|
|
1252
|
-
/* @__PURE__ */ (0,
|
|
1253
|
-
/* @__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)(
|
|
1254
1512
|
"button",
|
|
1255
1513
|
{
|
|
1256
1514
|
type: "button",
|
|
@@ -1259,31 +1517,31 @@ function ReportFeature({ feature }) {
|
|
|
1259
1517
|
"aria-controls": bodyId,
|
|
1260
1518
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1261
1519
|
children: [
|
|
1262
|
-
/* @__PURE__ */ (0,
|
|
1263
|
-
/* @__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 })
|
|
1264
1522
|
]
|
|
1265
1523
|
}
|
|
1266
1524
|
) : feature.title }),
|
|
1267
|
-
/* @__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 })
|
|
1268
1526
|
] }),
|
|
1269
|
-
/* @__PURE__ */ (0,
|
|
1527
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1270
1528
|
"p",
|
|
1271
1529
|
{
|
|
1272
1530
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1273
1531
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1274
1532
|
children: [
|
|
1275
|
-
/* @__PURE__ */ (0,
|
|
1533
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { children: [
|
|
1276
1534
|
s.passed,
|
|
1277
1535
|
" passed"
|
|
1278
1536
|
] }),
|
|
1279
|
-
/* @__PURE__ */ (0,
|
|
1280
|
-
/* @__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: [
|
|
1281
1539
|
s.failed,
|
|
1282
1540
|
" failed"
|
|
1283
1541
|
] }),
|
|
1284
|
-
skipped > 0 ? /* @__PURE__ */ (0,
|
|
1285
|
-
/* @__PURE__ */ (0,
|
|
1286
|
-
/* @__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: [
|
|
1287
1545
|
skipped,
|
|
1288
1546
|
" skipped"
|
|
1289
1547
|
] })
|
|
@@ -1292,7 +1550,7 @@ function ReportFeature({ feature }) {
|
|
|
1292
1550
|
}
|
|
1293
1551
|
)
|
|
1294
1552
|
] }),
|
|
1295
|
-
/* @__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 }) })
|
|
1296
1554
|
]
|
|
1297
1555
|
}
|
|
1298
1556
|
)
|
|
@@ -1300,17 +1558,17 @@ function ReportFeature({ feature }) {
|
|
|
1300
1558
|
}
|
|
1301
1559
|
|
|
1302
1560
|
// src/components/ReportFeatureList.tsx
|
|
1303
|
-
var
|
|
1561
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1304
1562
|
function ReportFeatureList() {
|
|
1305
1563
|
const report = useReport();
|
|
1306
|
-
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)) });
|
|
1307
1565
|
}
|
|
1308
1566
|
|
|
1309
1567
|
// src/components/ui/empty.tsx
|
|
1310
1568
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
1311
|
-
var
|
|
1569
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1312
1570
|
function Empty({ className, ...props }) {
|
|
1313
|
-
return /* @__PURE__ */ (0,
|
|
1571
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1314
1572
|
"div",
|
|
1315
1573
|
{
|
|
1316
1574
|
"data-slot": "empty",
|
|
@@ -1323,7 +1581,7 @@ function Empty({ className, ...props }) {
|
|
|
1323
1581
|
);
|
|
1324
1582
|
}
|
|
1325
1583
|
function EmptyHeader({ className, ...props }) {
|
|
1326
|
-
return /* @__PURE__ */ (0,
|
|
1584
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1327
1585
|
"div",
|
|
1328
1586
|
{
|
|
1329
1587
|
"data-slot": "empty-header",
|
|
@@ -1350,7 +1608,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
|
|
|
1350
1608
|
}
|
|
1351
1609
|
);
|
|
1352
1610
|
function EmptyTitle({ className, ...props }) {
|
|
1353
|
-
return /* @__PURE__ */ (0,
|
|
1611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1354
1612
|
"div",
|
|
1355
1613
|
{
|
|
1356
1614
|
"data-slot": "empty-title",
|
|
@@ -1361,16 +1619,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1361
1619
|
}
|
|
1362
1620
|
|
|
1363
1621
|
// src/components/ReportEmpty.tsx
|
|
1364
|
-
var
|
|
1622
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1365
1623
|
function ReportEmpty({ message }) {
|
|
1366
|
-
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." }) }) });
|
|
1367
1625
|
}
|
|
1368
1626
|
|
|
1369
1627
|
// src/components/ReportSummary.tsx
|
|
1370
|
-
var
|
|
1628
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1371
1629
|
function ReportSummary({ className }) {
|
|
1372
1630
|
const report = useReport();
|
|
1373
|
-
return /* @__PURE__ */ (0,
|
|
1631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1374
1632
|
ReportSummaryView,
|
|
1375
1633
|
{
|
|
1376
1634
|
summary: report.summary,
|
|
@@ -1396,7 +1654,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1396
1654
|
if (summary.pending > 0) {
|
|
1397
1655
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1398
1656
|
}
|
|
1399
|
-
return /* @__PURE__ */ (0,
|
|
1657
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1400
1658
|
"dl",
|
|
1401
1659
|
{
|
|
1402
1660
|
className: cn(
|
|
@@ -1409,17 +1667,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1409
1667
|
"aria-label": ariaLabel,
|
|
1410
1668
|
children: cards.map((c) => {
|
|
1411
1669
|
const tone = TONE[c.status];
|
|
1412
|
-
return /* @__PURE__ */ (0,
|
|
1670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
1413
1671
|
"div",
|
|
1414
1672
|
{
|
|
1415
1673
|
"data-status": c.status,
|
|
1416
1674
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1417
1675
|
children: [
|
|
1418
|
-
/* @__PURE__ */ (0,
|
|
1419
|
-
/* @__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" }),
|
|
1420
1678
|
c.label
|
|
1421
1679
|
] }),
|
|
1422
|
-
/* @__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 })
|
|
1423
1681
|
]
|
|
1424
1682
|
},
|
|
1425
1683
|
c.status
|
|
@@ -1479,7 +1737,7 @@ function prUrl(ci) {
|
|
|
1479
1737
|
}
|
|
1480
1738
|
|
|
1481
1739
|
// src/components/ReportMeta.tsx
|
|
1482
|
-
var
|
|
1740
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1483
1741
|
function ReportMeta() {
|
|
1484
1742
|
const report = useReport();
|
|
1485
1743
|
const items = [];
|
|
@@ -1502,13 +1760,13 @@ function ReportMeta() {
|
|
|
1502
1760
|
const short = sha.slice(0, 8);
|
|
1503
1761
|
items.push({
|
|
1504
1762
|
label: "Commit",
|
|
1505
|
-
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
|
|
1506
1764
|
});
|
|
1507
1765
|
}
|
|
1508
1766
|
if (report.ci) {
|
|
1509
1767
|
items.push({
|
|
1510
1768
|
label: "CI",
|
|
1511
|
-
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: [
|
|
1512
1770
|
ciDisplayName(report.ci.name),
|
|
1513
1771
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1514
1772
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1519,7 +1777,7 @@ function ReportMeta() {
|
|
|
1519
1777
|
const label = `#${report.ci.prNumber}`;
|
|
1520
1778
|
items.push({
|
|
1521
1779
|
label: "PR",
|
|
1522
|
-
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
|
|
1523
1781
|
});
|
|
1524
1782
|
}
|
|
1525
1783
|
if (items.length === 0) return null;
|
|
@@ -1527,50 +1785,50 @@ function ReportMeta() {
|
|
|
1527
1785
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1528
1786
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1529
1787
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1530
|
-
/* @__PURE__ */ (0,
|
|
1531
|
-
/* @__PURE__ */ (0,
|
|
1532
|
-
/* @__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" }),
|
|
1533
1791
|
"Run details"
|
|
1534
1792
|
] }),
|
|
1535
|
-
/* @__PURE__ */ (0,
|
|
1536
|
-
/* @__PURE__ */ (0,
|
|
1537
|
-
/* @__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 })
|
|
1538
1796
|
] }, item.label)) })
|
|
1539
1797
|
] })
|
|
1540
1798
|
);
|
|
1541
1799
|
}
|
|
1542
1800
|
|
|
1543
1801
|
// src/components/ReportSchemaError.tsx
|
|
1544
|
-
var
|
|
1802
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1545
1803
|
function ReportSchemaError({ error }) {
|
|
1546
|
-
return /* @__PURE__ */ (0,
|
|
1547
|
-
/* @__PURE__ */ (0,
|
|
1548
|
-
/* @__PURE__ */ (0,
|
|
1549
|
-
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: [
|
|
1550
1808
|
"The report bundle is newer than this version of ",
|
|
1551
|
-
/* @__PURE__ */ (0,
|
|
1809
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("code", { children: "executable-stories-react" }),
|
|
1552
1810
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1553
1811
|
] }) : null,
|
|
1554
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0,
|
|
1555
|
-
/* @__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: [
|
|
1556
1814
|
error.issues.length,
|
|
1557
1815
|
" validation issue",
|
|
1558
1816
|
error.issues.length === 1 ? "" : "s"
|
|
1559
1817
|
] }),
|
|
1560
|
-
/* @__PURE__ */ (0,
|
|
1818
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1561
1819
|
] }) : null
|
|
1562
1820
|
] });
|
|
1563
1821
|
}
|
|
1564
1822
|
|
|
1565
1823
|
// src/components/ReportShell.tsx
|
|
1566
|
-
var
|
|
1824
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1567
1825
|
function ReportErrorShell({
|
|
1568
1826
|
error,
|
|
1569
1827
|
className,
|
|
1570
1828
|
title,
|
|
1571
1829
|
dataTheme
|
|
1572
1830
|
}) {
|
|
1573
|
-
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 }) });
|
|
1574
1832
|
}
|
|
1575
1833
|
|
|
1576
1834
|
// src/interactive/ReportInteractive.tsx
|
|
@@ -1579,12 +1837,12 @@ var import_lucide_react5 = require("lucide-react");
|
|
|
1579
1837
|
// src/components/ui/switch.tsx
|
|
1580
1838
|
var React4 = require("react");
|
|
1581
1839
|
var import_switch = require("@base-ui/react/switch");
|
|
1582
|
-
var
|
|
1840
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
1583
1841
|
function Switch({
|
|
1584
1842
|
className,
|
|
1585
1843
|
...props
|
|
1586
1844
|
}) {
|
|
1587
|
-
return /* @__PURE__ */ (0,
|
|
1845
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
1588
1846
|
import_switch.Switch.Root,
|
|
1589
1847
|
{
|
|
1590
1848
|
"data-slot": "switch",
|
|
@@ -1593,7 +1851,7 @@ function Switch({
|
|
|
1593
1851
|
className
|
|
1594
1852
|
),
|
|
1595
1853
|
...props,
|
|
1596
|
-
children: /* @__PURE__ */ (0,
|
|
1854
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
1597
1855
|
import_switch.Switch.Thumb,
|
|
1598
1856
|
{
|
|
1599
1857
|
"data-slot": "switch-thumb",
|
|
@@ -1609,7 +1867,7 @@ var React5 = __toESM(require("react"), 1);
|
|
|
1609
1867
|
var import_toggle_group = require("@base-ui/react/toggle-group");
|
|
1610
1868
|
var import_toggle = require("@base-ui/react/toggle");
|
|
1611
1869
|
var import_class_variance_authority3 = require("class-variance-authority");
|
|
1612
|
-
var
|
|
1870
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
1613
1871
|
var toggleItemVariants = (0, import_class_variance_authority3.cva)(
|
|
1614
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",
|
|
1615
1873
|
{
|
|
@@ -1631,13 +1889,13 @@ function ToggleGroup({
|
|
|
1631
1889
|
children,
|
|
1632
1890
|
...props
|
|
1633
1891
|
}) {
|
|
1634
|
-
return /* @__PURE__ */ (0,
|
|
1892
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
1635
1893
|
import_toggle_group.ToggleGroup,
|
|
1636
1894
|
{
|
|
1637
1895
|
"data-slot": "toggle-group",
|
|
1638
1896
|
className: cn("flex w-fit items-center gap-0.5 rounded-lg bg-muted p-0.5", className),
|
|
1639
1897
|
...props,
|
|
1640
|
-
children: /* @__PURE__ */ (0,
|
|
1898
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ToggleGroupContext.Provider, { value: { size }, children })
|
|
1641
1899
|
}
|
|
1642
1900
|
);
|
|
1643
1901
|
}
|
|
@@ -1648,7 +1906,7 @@ function ToggleGroupItem({
|
|
|
1648
1906
|
...props
|
|
1649
1907
|
}) {
|
|
1650
1908
|
const context = React5.useContext(ToggleGroupContext);
|
|
1651
|
-
return /* @__PURE__ */ (0,
|
|
1909
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
1652
1910
|
import_toggle.Toggle,
|
|
1653
1911
|
{
|
|
1654
1912
|
"data-slot": "toggle-group-item",
|
|
@@ -1665,9 +1923,9 @@ var import_lucide_react3 = require("lucide-react");
|
|
|
1665
1923
|
|
|
1666
1924
|
// src/components/ui/input.tsx
|
|
1667
1925
|
var React6 = require("react");
|
|
1668
|
-
var
|
|
1926
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
1669
1927
|
function Input({ className, type, ...props }) {
|
|
1670
|
-
return /* @__PURE__ */ (0,
|
|
1928
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
1671
1929
|
"input",
|
|
1672
1930
|
{
|
|
1673
1931
|
type,
|
|
@@ -1684,7 +1942,7 @@ function Input({ className, type, ...props }) {
|
|
|
1684
1942
|
}
|
|
1685
1943
|
|
|
1686
1944
|
// src/interactive/ReportSearch.tsx
|
|
1687
|
-
var
|
|
1945
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
1688
1946
|
var ReportSearch = (0, import_react8.forwardRef)(
|
|
1689
1947
|
function ReportSearch2(props, ref) {
|
|
1690
1948
|
const {
|
|
@@ -1706,17 +1964,17 @@ var ReportSearch = (0, import_react8.forwardRef)(
|
|
|
1706
1964
|
e.preventDefault();
|
|
1707
1965
|
}
|
|
1708
1966
|
}
|
|
1709
|
-
return /* @__PURE__ */ (0,
|
|
1710
|
-
/* @__PURE__ */ (0,
|
|
1711
|
-
/* @__PURE__ */ (0,
|
|
1712
|
-
/* @__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)(
|
|
1713
1971
|
import_lucide_react3.Search,
|
|
1714
1972
|
{
|
|
1715
1973
|
"aria-hidden": true,
|
|
1716
1974
|
className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
|
|
1717
1975
|
}
|
|
1718
1976
|
),
|
|
1719
|
-
/* @__PURE__ */ (0,
|
|
1977
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
1720
1978
|
Input,
|
|
1721
1979
|
{
|
|
1722
1980
|
ref,
|
|
@@ -1733,7 +1991,7 @@ var ReportSearch = (0, import_react8.forwardRef)(
|
|
|
1733
1991
|
}
|
|
1734
1992
|
)
|
|
1735
1993
|
] }),
|
|
1736
|
-
showCounts ? /* @__PURE__ */ (0,
|
|
1994
|
+
showCounts ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
1737
1995
|
"span",
|
|
1738
1996
|
{
|
|
1739
1997
|
className: "text-xs tabular-nums text-muted-foreground",
|
|
@@ -1774,7 +2032,7 @@ function scrollToScenarioId(scenarioId, options = {}) {
|
|
|
1774
2032
|
}
|
|
1775
2033
|
|
|
1776
2034
|
// src/interactive/ReportFailureBanner.tsx
|
|
1777
|
-
var
|
|
2035
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
1778
2036
|
function ReportFailureBanner({ failures }) {
|
|
1779
2037
|
const first = failures[0];
|
|
1780
2038
|
const jumpToFirst = (0, import_react9.useCallback)(() => {
|
|
@@ -1782,7 +2040,7 @@ function ReportFailureBanner({ failures }) {
|
|
|
1782
2040
|
scrollToScenarioId(first.scenarioId);
|
|
1783
2041
|
}, [first]);
|
|
1784
2042
|
if (failures.length === 0) return null;
|
|
1785
|
-
return /* @__PURE__ */ (0,
|
|
2043
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
1786
2044
|
"div",
|
|
1787
2045
|
{
|
|
1788
2046
|
className: "es-failure-banner",
|
|
@@ -1790,13 +2048,13 @@ function ReportFailureBanner({ failures }) {
|
|
|
1790
2048
|
"aria-live": "polite",
|
|
1791
2049
|
"aria-label": "Failure summary",
|
|
1792
2050
|
children: [
|
|
1793
|
-
/* @__PURE__ */ (0,
|
|
1794
|
-
/* @__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 }),
|
|
1795
2053
|
" ",
|
|
1796
2054
|
"failure",
|
|
1797
2055
|
failures.length === 1 ? "" : "s"
|
|
1798
2056
|
] }),
|
|
1799
|
-
/* @__PURE__ */ (0,
|
|
2057
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
1800
2058
|
"button",
|
|
1801
2059
|
{
|
|
1802
2060
|
type: "button",
|
|
@@ -1813,7 +2071,7 @@ function ReportFailureBanner({ failures }) {
|
|
|
1813
2071
|
|
|
1814
2072
|
// src/interactive/ReportFreshness.tsx
|
|
1815
2073
|
var import_react10 = require("react");
|
|
1816
|
-
var
|
|
2074
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
1817
2075
|
function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
1818
2076
|
const [now, setNow] = (0, import_react10.useState)(nowMs);
|
|
1819
2077
|
(0, import_react10.useEffect)(() => {
|
|
@@ -1821,7 +2079,7 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
1821
2079
|
}, [nowMs]);
|
|
1822
2080
|
if (lastRunMs === void 0 || now === void 0) return null;
|
|
1823
2081
|
const age = formatRelativeAge(lastRunMs, now);
|
|
1824
|
-
const runLink = ciUrl ? /* @__PURE__ */ (0,
|
|
2082
|
+
const runLink = ciUrl ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
1825
2083
|
"a",
|
|
1826
2084
|
{
|
|
1827
2085
|
href: ciUrl,
|
|
@@ -1832,9 +2090,9 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
1832
2090
|
}
|
|
1833
2091
|
) : null;
|
|
1834
2092
|
if (isReportStale(lastRunMs, staleAfterDays, now)) {
|
|
1835
|
-
return /* @__PURE__ */ (0,
|
|
1836
|
-
/* @__PURE__ */ (0,
|
|
1837
|
-
/* @__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: [
|
|
1838
2096
|
"Last verified ",
|
|
1839
2097
|
age,
|
|
1840
2098
|
"."
|
|
@@ -1844,10 +2102,10 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
1844
2102
|
runLink
|
|
1845
2103
|
] });
|
|
1846
2104
|
}
|
|
1847
|
-
return /* @__PURE__ */ (0,
|
|
2105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("p", { className: "es-freshness", "aria-label": "Report freshness", children: [
|
|
1848
2106
|
"Verified ",
|
|
1849
2107
|
age,
|
|
1850
|
-
runLink ? /* @__PURE__ */ (0,
|
|
2108
|
+
runLink ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
|
|
1851
2109
|
" \xB7 ",
|
|
1852
2110
|
runLink
|
|
1853
2111
|
] }) : null
|
|
@@ -1855,15 +2113,15 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
1855
2113
|
}
|
|
1856
2114
|
|
|
1857
2115
|
// src/interactive/ReportLastRunDelta.tsx
|
|
1858
|
-
var
|
|
2116
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
1859
2117
|
var MAX_LINKS = 5;
|
|
1860
2118
|
function ScenarioLinks({ scenarios, tone }) {
|
|
1861
|
-
return /* @__PURE__ */ (0,
|
|
1862
|
-
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: [
|
|
1863
2121
|
i > 0 ? ", " : "",
|
|
1864
|
-
/* @__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 })
|
|
1865
2123
|
] }, s.id)),
|
|
1866
|
-
scenarios.length > MAX_LINKS ? /* @__PURE__ */ (0,
|
|
2124
|
+
scenarios.length > MAX_LINKS ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { children: [
|
|
1867
2125
|
" and ",
|
|
1868
2126
|
scenarios.length - MAX_LINKS,
|
|
1869
2127
|
" more"
|
|
@@ -1880,23 +2138,23 @@ function ReportLastRunDelta({
|
|
|
1880
2138
|
if (!delta) return null;
|
|
1881
2139
|
const { newlyFailing, newlyPassing, added } = delta;
|
|
1882
2140
|
if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) {
|
|
1883
|
-
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." });
|
|
1884
2142
|
}
|
|
1885
|
-
return /* @__PURE__ */ (0,
|
|
1886
|
-
/* @__PURE__ */ (0,
|
|
1887
|
-
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: [
|
|
1888
2146
|
newlyFailing.length,
|
|
1889
2147
|
" newly failing (",
|
|
1890
|
-
/* @__PURE__ */ (0,
|
|
2148
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ScenarioLinks, { scenarios: newlyFailing, tone: "text-fail" }),
|
|
1891
2149
|
")"
|
|
1892
2150
|
] }) : null,
|
|
1893
|
-
newlyPassing.length > 0 ? /* @__PURE__ */ (0,
|
|
2151
|
+
newlyPassing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "ml-2 text-pass", children: [
|
|
1894
2152
|
newlyPassing.length,
|
|
1895
2153
|
" fixed (",
|
|
1896
|
-
/* @__PURE__ */ (0,
|
|
2154
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ScenarioLinks, { scenarios: newlyPassing, tone: "text-pass" }),
|
|
1897
2155
|
")"
|
|
1898
2156
|
] }) : null,
|
|
1899
|
-
added.length > 0 ? /* @__PURE__ */ (0,
|
|
2157
|
+
added.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "ml-2", children: [
|
|
1900
2158
|
added.length,
|
|
1901
2159
|
" new"
|
|
1902
2160
|
] }) : null
|
|
@@ -1960,7 +2218,7 @@ function Button({
|
|
|
1960
2218
|
}
|
|
1961
2219
|
|
|
1962
2220
|
// src/interactive/ReportShortcutsHelp.tsx
|
|
1963
|
-
var
|
|
2221
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
1964
2222
|
var SHORTCUTS = [
|
|
1965
2223
|
{ keys: "/", description: "Focus search" },
|
|
1966
2224
|
{ keys: "f", description: "Jump to next failure" },
|
|
@@ -1972,9 +2230,9 @@ var SHORTCUTS = [
|
|
|
1972
2230
|
];
|
|
1973
2231
|
function Keys({ keys }) {
|
|
1974
2232
|
const parts = keys.split(" ");
|
|
1975
|
-
return /* @__PURE__ */ (0,
|
|
1976
|
-
i > 0 ? /* @__PURE__ */ (0,
|
|
1977
|
-
/* @__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 })
|
|
1978
2236
|
] }, k)) });
|
|
1979
2237
|
}
|
|
1980
2238
|
function ReportShortcutsHelp({ open, onClose }) {
|
|
@@ -1985,7 +2243,7 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
1985
2243
|
if (open && !dialog.open) dialog.showModal();
|
|
1986
2244
|
else if (!open && dialog.open) dialog.close();
|
|
1987
2245
|
}, [open]);
|
|
1988
|
-
return /* @__PURE__ */ (0,
|
|
2246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
1989
2247
|
"dialog",
|
|
1990
2248
|
{
|
|
1991
2249
|
ref: dialogRef,
|
|
@@ -1993,12 +2251,12 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
1993
2251
|
"aria-label": "Keyboard shortcuts",
|
|
1994
2252
|
onClose,
|
|
1995
2253
|
children: [
|
|
1996
|
-
/* @__PURE__ */ (0,
|
|
1997
|
-
/* @__PURE__ */ (0,
|
|
1998
|
-
/* @__PURE__ */ (0,
|
|
1999
|
-
/* @__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 })
|
|
2000
2258
|
] }, s.keys)) }),
|
|
2001
|
-
/* @__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" }) })
|
|
2002
2260
|
]
|
|
2003
2261
|
}
|
|
2004
2262
|
);
|
|
@@ -2199,7 +2457,7 @@ function failuresFirst(report) {
|
|
|
2199
2457
|
|
|
2200
2458
|
// src/interactive/ReportFilters.tsx
|
|
2201
2459
|
var import_react14 = require("react");
|
|
2202
|
-
var
|
|
2460
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2203
2461
|
var TAG_LIMIT = 12;
|
|
2204
2462
|
function ReportFilters({
|
|
2205
2463
|
statuses,
|
|
@@ -2213,10 +2471,10 @@ function ReportFilters({
|
|
|
2213
2471
|
if (statuses.length === 0 && tags.length === 0) return null;
|
|
2214
2472
|
const tagsCollapsed = tags.length > TAG_LIMIT && !showAllTags;
|
|
2215
2473
|
const visibleTags = tagsCollapsed ? tags.slice(0, TAG_LIMIT) : tags;
|
|
2216
|
-
return /* @__PURE__ */ (0,
|
|
2217
|
-
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) => {
|
|
2218
2476
|
const active = status === opt.key;
|
|
2219
|
-
return /* @__PURE__ */ (0,
|
|
2477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
2220
2478
|
"button",
|
|
2221
2479
|
{
|
|
2222
2480
|
type: "button",
|
|
@@ -2228,23 +2486,23 @@ function ReportFilters({
|
|
|
2228
2486
|
),
|
|
2229
2487
|
children: [
|
|
2230
2488
|
opt.label,
|
|
2231
|
-
/* @__PURE__ */ (0,
|
|
2489
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "ml-1 font-mono opacity-70", children: opt.count })
|
|
2232
2490
|
]
|
|
2233
2491
|
},
|
|
2234
2492
|
opt.key
|
|
2235
2493
|
);
|
|
2236
2494
|
}) }) : null,
|
|
2237
|
-
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: [
|
|
2238
2496
|
visibleTags.map((tag) => {
|
|
2239
2497
|
const active = activeTags.includes(tag);
|
|
2240
|
-
return /* @__PURE__ */ (0,
|
|
2498
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2241
2499
|
"button",
|
|
2242
2500
|
{
|
|
2243
2501
|
type: "button",
|
|
2244
2502
|
"aria-pressed": active,
|
|
2245
2503
|
onClick: () => onToggleTag(tag),
|
|
2246
2504
|
className: "cursor-pointer",
|
|
2247
|
-
children: /* @__PURE__ */ (0,
|
|
2505
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2248
2506
|
Badge,
|
|
2249
2507
|
{
|
|
2250
2508
|
variant: "tag",
|
|
@@ -2257,7 +2515,7 @@ function ReportFilters({
|
|
|
2257
2515
|
}
|
|
2258
2516
|
) }, tag);
|
|
2259
2517
|
}),
|
|
2260
|
-
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)(
|
|
2261
2519
|
"button",
|
|
2262
2520
|
{
|
|
2263
2521
|
type: "button",
|
|
@@ -2273,7 +2531,7 @@ function ReportFilters({
|
|
|
2273
2531
|
|
|
2274
2532
|
// src/interactive/ReportToc.tsx
|
|
2275
2533
|
var import_react15 = require("react");
|
|
2276
|
-
var
|
|
2534
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2277
2535
|
var DOT = {
|
|
2278
2536
|
passed: "bg-pass",
|
|
2279
2537
|
failed: "bg-fail",
|
|
@@ -2302,11 +2560,11 @@ function TocContent({ onNavigate }) {
|
|
|
2302
2560
|
return () => observer.disconnect();
|
|
2303
2561
|
}, [scenarioIds]);
|
|
2304
2562
|
if (report.features.length === 0) return null;
|
|
2305
|
-
return /* @__PURE__ */ (0,
|
|
2306
|
-
/* @__PURE__ */ (0,
|
|
2307
|
-
/* @__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) => {
|
|
2308
2566
|
const active = activeId === scenario.id;
|
|
2309
|
-
return /* @__PURE__ */ (0,
|
|
2567
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
2310
2568
|
"a",
|
|
2311
2569
|
{
|
|
2312
2570
|
href: `#${scenario.id}`,
|
|
@@ -2321,14 +2579,14 @@ function TocContent({ onNavigate }) {
|
|
|
2321
2579
|
active ? "border-primary font-medium text-foreground" : "border-border text-muted-foreground"
|
|
2322
2580
|
),
|
|
2323
2581
|
children: [
|
|
2324
|
-
/* @__PURE__ */ (0,
|
|
2582
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2325
2583
|
"span",
|
|
2326
2584
|
{
|
|
2327
2585
|
"aria-hidden": true,
|
|
2328
2586
|
className: cn("mt-1 size-1.5 shrink-0 rounded-full", DOT[scenario.status])
|
|
2329
2587
|
}
|
|
2330
2588
|
),
|
|
2331
|
-
/* @__PURE__ */ (0,
|
|
2589
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "break-words", children: scenario.title })
|
|
2332
2590
|
]
|
|
2333
2591
|
}
|
|
2334
2592
|
) }, scenario.id);
|
|
@@ -2338,14 +2596,14 @@ function TocContent({ onNavigate }) {
|
|
|
2338
2596
|
function ReportToc() {
|
|
2339
2597
|
const report = useReport();
|
|
2340
2598
|
if (report.features.length === 0) return null;
|
|
2341
|
-
return /* @__PURE__ */ (0,
|
|
2599
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
2342
2600
|
"nav",
|
|
2343
2601
|
{
|
|
2344
2602
|
"aria-label": "Table of contents",
|
|
2345
2603
|
className: "sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block",
|
|
2346
2604
|
children: [
|
|
2347
|
-
/* @__PURE__ */ (0,
|
|
2348
|
-
/* @__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, {})
|
|
2349
2607
|
]
|
|
2350
2608
|
}
|
|
2351
2609
|
);
|
|
@@ -2355,31 +2613,31 @@ function ReportToc() {
|
|
|
2355
2613
|
var import_react16 = require("react");
|
|
2356
2614
|
var import_dialog = require("@base-ui/react/dialog");
|
|
2357
2615
|
var import_lucide_react4 = require("lucide-react");
|
|
2358
|
-
var
|
|
2616
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2359
2617
|
function ReportTocDrawer() {
|
|
2360
2618
|
const report = useReport();
|
|
2361
2619
|
const [open, setOpen] = (0, import_react16.useState)(false);
|
|
2362
2620
|
if (report.features.length === 0) return null;
|
|
2363
|
-
return /* @__PURE__ */ (0,
|
|
2364
|
-
/* @__PURE__ */ (0,
|
|
2365
|
-
/* @__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 }),
|
|
2366
2624
|
" Contents"
|
|
2367
2625
|
] }),
|
|
2368
|
-
/* @__PURE__ */ (0,
|
|
2369
|
-
/* @__PURE__ */ (0,
|
|
2370
|
-
/* @__PURE__ */ (0,
|
|
2371
|
-
/* @__PURE__ */ (0,
|
|
2372
|
-
/* @__PURE__ */ (0,
|
|
2373
|
-
/* @__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)(
|
|
2374
2632
|
import_dialog.Dialog.Close,
|
|
2375
2633
|
{
|
|
2376
2634
|
"aria-label": "Close contents",
|
|
2377
2635
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
2378
|
-
children: /* @__PURE__ */ (0,
|
|
2636
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react4.XIcon, { "aria-hidden": true })
|
|
2379
2637
|
}
|
|
2380
2638
|
)
|
|
2381
2639
|
] }),
|
|
2382
|
-
/* @__PURE__ */ (0,
|
|
2640
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TocContent, { onNavigate: () => setOpen(false) })
|
|
2383
2641
|
] })
|
|
2384
2642
|
] })
|
|
2385
2643
|
] });
|
|
@@ -2434,14 +2692,14 @@ function useTheme() {
|
|
|
2434
2692
|
}
|
|
2435
2693
|
|
|
2436
2694
|
// src/interactive/ReportInteractive.tsx
|
|
2437
|
-
var
|
|
2695
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2438
2696
|
function ReportInteractive(props) {
|
|
2439
2697
|
const { report, className, title, dataTheme } = props;
|
|
2440
2698
|
const result = unwrapReport(report);
|
|
2441
2699
|
if (!result.ok) {
|
|
2442
|
-
return /* @__PURE__ */ (0,
|
|
2700
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
2443
2701
|
}
|
|
2444
|
-
return /* @__PURE__ */ (0,
|
|
2702
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportInteractiveView, { ...props, report: result.data });
|
|
2445
2703
|
}
|
|
2446
2704
|
var THEME_OPTIONS = [
|
|
2447
2705
|
{ value: "light", label: "Light", Icon: import_lucide_react5.Sun },
|
|
@@ -2449,7 +2707,7 @@ var THEME_OPTIONS = [
|
|
|
2449
2707
|
{ value: "dark", label: "Dark", Icon: import_lucide_react5.Moon }
|
|
2450
2708
|
];
|
|
2451
2709
|
function ThemeSegment({ pref, onPref }) {
|
|
2452
|
-
return /* @__PURE__ */ (0,
|
|
2710
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2453
2711
|
ToggleGroup,
|
|
2454
2712
|
{
|
|
2455
2713
|
size: "sm",
|
|
@@ -2459,7 +2717,7 @@ function ThemeSegment({ pref, onPref }) {
|
|
|
2459
2717
|
if (next) onPref(next);
|
|
2460
2718
|
},
|
|
2461
2719
|
"aria-label": "Color theme",
|
|
2462
|
-
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))
|
|
2463
2721
|
}
|
|
2464
2722
|
);
|
|
2465
2723
|
}
|
|
@@ -2581,13 +2839,13 @@ function ReportInteractiveView({
|
|
|
2581
2839
|
const totalScenarios = report.summary.total;
|
|
2582
2840
|
const matchedScenarios = filtered.summary.total;
|
|
2583
2841
|
const showToc = !hideToc && totalScenarios > 3;
|
|
2584
|
-
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)(
|
|
2585
2843
|
ReportRoot,
|
|
2586
2844
|
{
|
|
2587
2845
|
report: filtered,
|
|
2588
2846
|
customRenderers,
|
|
2589
2847
|
renderers,
|
|
2590
|
-
children: /* @__PURE__ */ (0,
|
|
2848
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
2591
2849
|
"main",
|
|
2592
2850
|
{
|
|
2593
2851
|
className: cn("es-report", "es-report-interactive", className),
|
|
@@ -2596,8 +2854,8 @@ function ReportInteractiveView({
|
|
|
2596
2854
|
"data-theme": dataTheme,
|
|
2597
2855
|
"data-detail-level": detail,
|
|
2598
2856
|
children: [
|
|
2599
|
-
/* @__PURE__ */ (0,
|
|
2600
|
-
/* @__PURE__ */ (0,
|
|
2857
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("header", { className: "es-report-header", children: [
|
|
2858
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
2601
2859
|
"div",
|
|
2602
2860
|
{
|
|
2603
2861
|
"data-es-navbar": true,
|
|
@@ -2606,9 +2864,9 @@ function ReportInteractiveView({
|
|
|
2606
2864
|
hideHeader ? "justify-end" : "justify-between"
|
|
2607
2865
|
),
|
|
2608
2866
|
children: [
|
|
2609
|
-
hideHeader ? null : /* @__PURE__ */ (0,
|
|
2610
|
-
/* @__PURE__ */ (0,
|
|
2611
|
-
/* @__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)(
|
|
2612
2870
|
ReportSearch,
|
|
2613
2871
|
{
|
|
2614
2872
|
ref: searchRef,
|
|
@@ -2618,16 +2876,16 @@ function ReportInteractiveView({
|
|
|
2618
2876
|
totalCount: totalScenarios
|
|
2619
2877
|
}
|
|
2620
2878
|
),
|
|
2621
|
-
/* @__PURE__ */ (0,
|
|
2879
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ThemeSegment, { pref: themePref, onPref: setThemePref })
|
|
2622
2880
|
] })
|
|
2623
2881
|
]
|
|
2624
2882
|
}
|
|
2625
2883
|
),
|
|
2626
|
-
hideHeader ? null : /* @__PURE__ */ (0,
|
|
2627
|
-
/* @__PURE__ */ (0,
|
|
2628
|
-
/* @__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, {})
|
|
2629
2887
|
] }),
|
|
2630
|
-
/* @__PURE__ */ (0,
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2631
2889
|
ReportFreshness,
|
|
2632
2890
|
{
|
|
2633
2891
|
lastRunMs: reportLastRunMs(report),
|
|
@@ -2635,8 +2893,8 @@ function ReportInteractiveView({
|
|
|
2635
2893
|
staleAfterDays
|
|
2636
2894
|
}
|
|
2637
2895
|
),
|
|
2638
|
-
/* @__PURE__ */ (0,
|
|
2639
|
-
/* @__PURE__ */ (0,
|
|
2896
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportLastRunDelta, { history: scenarioHistory, report }),
|
|
2897
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2640
2898
|
ReportFilters,
|
|
2641
2899
|
{
|
|
2642
2900
|
statuses: statusOptions,
|
|
@@ -2647,14 +2905,14 @@ function ReportInteractiveView({
|
|
|
2647
2905
|
onToggleTag: toggleTag
|
|
2648
2906
|
}
|
|
2649
2907
|
),
|
|
2650
|
-
/* @__PURE__ */ (0,
|
|
2651
|
-
showToc ? /* @__PURE__ */ (0,
|
|
2652
|
-
/* @__PURE__ */ (0,
|
|
2653
|
-
/* @__PURE__ */ (0,
|
|
2654
|
-
/* @__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" })
|
|
2655
2913
|
] }),
|
|
2656
|
-
/* @__PURE__ */ (0,
|
|
2657
|
-
/* @__PURE__ */ (0,
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2915
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2658
2916
|
Switch,
|
|
2659
2917
|
{
|
|
2660
2918
|
id: docsId,
|
|
@@ -2662,16 +2920,16 @@ function ReportInteractiveView({
|
|
|
2662
2920
|
onCheckedChange: (checked) => setDetail(checked ? "full" : "minimal")
|
|
2663
2921
|
}
|
|
2664
2922
|
),
|
|
2665
|
-
/* @__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" })
|
|
2666
2924
|
] })
|
|
2667
2925
|
] })
|
|
2668
2926
|
] }),
|
|
2669
|
-
/* @__PURE__ */ (0,
|
|
2670
|
-
hasContent ? showToc ? /* @__PURE__ */ (0,
|
|
2671
|
-
/* @__PURE__ */ (0,
|
|
2672
|
-
/* @__PURE__ */ (0,
|
|
2673
|
-
] }) : /* @__PURE__ */ (0,
|
|
2674
|
-
/* @__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)(
|
|
2675
2933
|
"button",
|
|
2676
2934
|
{
|
|
2677
2935
|
type: "button",
|
|
@@ -2682,8 +2940,8 @@ function ReportInteractiveView({
|
|
|
2682
2940
|
children: "?"
|
|
2683
2941
|
}
|
|
2684
2942
|
),
|
|
2685
|
-
/* @__PURE__ */ (0,
|
|
2686
|
-
toast ? /* @__PURE__ */ (0,
|
|
2943
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ReportShortcutsHelp, { open: helpOpen, onClose: () => setHelpOpen(false) }),
|
|
2944
|
+
toast ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2687
2945
|
"div",
|
|
2688
2946
|
{
|
|
2689
2947
|
role: "status",
|
|
@@ -2707,7 +2965,7 @@ var import_react20 = require("react");
|
|
|
2707
2965
|
|
|
2708
2966
|
// src/components/doc/MermaidView.tsx
|
|
2709
2967
|
var import_react19 = require("react");
|
|
2710
|
-
var
|
|
2968
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2711
2969
|
function prefersDark(el) {
|
|
2712
2970
|
const themed = el?.closest("[data-theme]");
|
|
2713
2971
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -2744,9 +3002,9 @@ function MermaidView({ entry, load }) {
|
|
|
2744
3002
|
};
|
|
2745
3003
|
}, [entry.code, load]);
|
|
2746
3004
|
if (svg) {
|
|
2747
|
-
return /* @__PURE__ */ (0,
|
|
2748
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
2749
|
-
/* @__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)(
|
|
2750
3008
|
"div",
|
|
2751
3009
|
{
|
|
2752
3010
|
role: "img",
|
|
@@ -2757,11 +3015,11 @@ function MermaidView({ entry, load }) {
|
|
|
2757
3015
|
)
|
|
2758
3016
|
] });
|
|
2759
3017
|
}
|
|
2760
|
-
return /* @__PURE__ */ (0,
|
|
3018
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(MermaidSource, { entry, ref });
|
|
2761
3019
|
}
|
|
2762
3020
|
|
|
2763
3021
|
// src/interactive/island-renderers.tsx
|
|
2764
|
-
var
|
|
3022
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2765
3023
|
var HLJS_ESM = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
|
|
2766
3024
|
var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
|
|
2767
3025
|
function cachedCdnModule(url) {
|
|
@@ -2795,13 +3053,13 @@ function CdnHighlightedCode({ entry }) {
|
|
|
2795
3053
|
cancelled = true;
|
|
2796
3054
|
};
|
|
2797
3055
|
}, [entry.content, entry.lang]);
|
|
2798
|
-
return /* @__PURE__ */ (0,
|
|
3056
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2799
3057
|
"code",
|
|
2800
3058
|
{
|
|
2801
3059
|
className: cn("hljs font-mono text-xs", entry.lang && `language-${entry.lang}`),
|
|
2802
3060
|
dangerouslySetInnerHTML: { __html: html }
|
|
2803
3061
|
}
|
|
2804
|
-
) : /* @__PURE__ */ (0,
|
|
3062
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
2805
3063
|
}
|
|
2806
3064
|
function buildIslandRenderers(opts) {
|
|
2807
3065
|
const renderers = {};
|
|
@@ -2815,7 +3073,7 @@ function buildIslandRenderers(opts) {
|
|
|
2815
3073
|
}
|
|
2816
3074
|
|
|
2817
3075
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
2818
|
-
var
|
|
3076
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
2819
3077
|
function ReportInteractiveIsland({
|
|
2820
3078
|
report,
|
|
2821
3079
|
title,
|
|
@@ -2829,7 +3087,7 @@ function ReportInteractiveIsland({
|
|
|
2829
3087
|
() => buildIslandRenderers({ syntaxHighlighting, mermaid }),
|
|
2830
3088
|
[syntaxHighlighting, mermaid]
|
|
2831
3089
|
);
|
|
2832
|
-
return /* @__PURE__ */ (0,
|
|
3090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2833
3091
|
ReportInteractive,
|
|
2834
3092
|
{
|
|
2835
3093
|
report,
|