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/ssr.cjs
CHANGED
|
@@ -241,7 +241,7 @@ function DocLink({ entry }) {
|
|
|
241
241
|
// src/components/doc/DocSection.tsx
|
|
242
242
|
var import_marked = require("marked");
|
|
243
243
|
|
|
244
|
-
//
|
|
244
|
+
// ../executable-stories-core/dist/utils/url.js
|
|
245
245
|
function safeUrl(value) {
|
|
246
246
|
if (!value) return void 0;
|
|
247
247
|
const trimmed = value.trim();
|
|
@@ -399,17 +399,29 @@ function DocHtml({ entry }) {
|
|
|
399
399
|
] });
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
-
// src/components/doc/
|
|
402
|
+
// src/components/doc/DocState.tsx
|
|
403
403
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
404
|
+
function DocState({ entry }) {
|
|
405
|
+
let json;
|
|
406
|
+
try {
|
|
407
|
+
json = JSON.stringify(entry.value, null, 2) ?? String(entry.value);
|
|
408
|
+
} catch {
|
|
409
|
+
json = String(entry.value);
|
|
410
|
+
}
|
|
411
|
+
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 }) });
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// src/components/doc/DocCustom.tsx
|
|
415
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
404
416
|
function DocCustom({ entry }) {
|
|
405
417
|
const renderers = useCustomRenderers();
|
|
406
418
|
const renderer = renderers[entry.type];
|
|
407
419
|
if (renderer) {
|
|
408
|
-
return /* @__PURE__ */ (0,
|
|
420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: renderer(entry) });
|
|
409
421
|
}
|
|
410
|
-
return /* @__PURE__ */ (0,
|
|
411
|
-
/* @__PURE__ */ (0,
|
|
412
|
-
/* @__PURE__ */ (0,
|
|
422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
|
|
423
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
|
|
424
|
+
/* @__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) })
|
|
413
425
|
] });
|
|
414
426
|
}
|
|
415
427
|
function safeStringify(value) {
|
|
@@ -421,45 +433,47 @@ function safeStringify(value) {
|
|
|
421
433
|
}
|
|
422
434
|
|
|
423
435
|
// src/components/doc/DocEntry.tsx
|
|
424
|
-
var
|
|
436
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
425
437
|
function DocEntry({ entry }) {
|
|
426
438
|
switch (entry.kind) {
|
|
427
439
|
case "note":
|
|
428
|
-
return /* @__PURE__ */ (0,
|
|
440
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocNote, { entry });
|
|
429
441
|
case "tag":
|
|
430
|
-
return /* @__PURE__ */ (0,
|
|
442
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocTag, { entry });
|
|
431
443
|
case "kv":
|
|
432
|
-
return /* @__PURE__ */ (0,
|
|
444
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocKv, { entry });
|
|
433
445
|
case "code":
|
|
434
|
-
return /* @__PURE__ */ (0,
|
|
446
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocCode, { entry });
|
|
435
447
|
case "table":
|
|
436
|
-
return /* @__PURE__ */ (0,
|
|
448
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocTable, { entry });
|
|
437
449
|
case "link":
|
|
438
|
-
return /* @__PURE__ */ (0,
|
|
450
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocLink, { entry });
|
|
439
451
|
case "section":
|
|
440
|
-
return /* @__PURE__ */ (0,
|
|
452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocSection, { entry });
|
|
441
453
|
case "mermaid":
|
|
442
|
-
return /* @__PURE__ */ (0,
|
|
454
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocMermaid, { entry });
|
|
443
455
|
case "screenshot":
|
|
444
|
-
return /* @__PURE__ */ (0,
|
|
456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocScreenshot, { entry });
|
|
445
457
|
case "video":
|
|
446
|
-
return /* @__PURE__ */ (0,
|
|
458
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocVideo, { entry });
|
|
447
459
|
case "html":
|
|
448
|
-
return /* @__PURE__ */ (0,
|
|
460
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocHtml, { entry });
|
|
461
|
+
case "state":
|
|
462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocState, { entry });
|
|
449
463
|
case "custom":
|
|
450
|
-
return /* @__PURE__ */ (0,
|
|
464
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DocCustom, { entry });
|
|
451
465
|
}
|
|
452
466
|
}
|
|
453
467
|
|
|
454
468
|
// src/components/ReportDocEntries.tsx
|
|
455
|
-
var
|
|
469
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
456
470
|
function ReportDocEntries({ entries }) {
|
|
457
471
|
if (entries.length === 0) return null;
|
|
458
|
-
return /* @__PURE__ */ (0,
|
|
472
|
+
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)) });
|
|
459
473
|
}
|
|
460
474
|
|
|
461
475
|
// src/lib/step-params.tsx
|
|
462
|
-
var
|
|
476
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
463
477
|
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
464
478
|
function highlightStepParams(text) {
|
|
465
479
|
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
@@ -471,7 +485,7 @@ function highlightStepParams(text) {
|
|
|
471
485
|
const end = start + match[0].length;
|
|
472
486
|
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
473
487
|
nodes.push(
|
|
474
|
-
/* @__PURE__ */ (0,
|
|
488
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
475
489
|
);
|
|
476
490
|
lastIndex = end;
|
|
477
491
|
});
|
|
@@ -480,7 +494,7 @@ function highlightStepParams(text) {
|
|
|
480
494
|
}
|
|
481
495
|
|
|
482
496
|
// src/components/ReportSteps.tsx
|
|
483
|
-
var
|
|
497
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
484
498
|
var STEP_GLYPH = {
|
|
485
499
|
passed: "\u2713",
|
|
486
500
|
failed: "\u2717",
|
|
@@ -495,21 +509,21 @@ var STEP_GLYPH_COLOR = {
|
|
|
495
509
|
};
|
|
496
510
|
function ReportSteps({ scenario }) {
|
|
497
511
|
if (scenario.steps.length === 0) return null;
|
|
498
|
-
return /* @__PURE__ */ (0,
|
|
512
|
+
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)) });
|
|
499
513
|
}
|
|
500
514
|
function ReportStepItem({ step }) {
|
|
501
515
|
const kw = step.keyword.toLowerCase();
|
|
502
516
|
const continuation = kw === "and" || kw === "but";
|
|
503
|
-
return /* @__PURE__ */ (0,
|
|
517
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
504
518
|
"li",
|
|
505
519
|
{
|
|
506
520
|
id: step.id,
|
|
507
521
|
"data-status": step.status,
|
|
508
522
|
className: cn("py-1.5 text-[0.8125rem] leading-normal", continuation && "pl-5"),
|
|
509
523
|
children: [
|
|
510
|
-
/* @__PURE__ */ (0,
|
|
511
|
-
/* @__PURE__ */ (0,
|
|
512
|
-
/* @__PURE__ */ (0,
|
|
524
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-baseline gap-2", children: [
|
|
525
|
+
/* @__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" }),
|
|
526
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
513
527
|
"span",
|
|
514
528
|
{
|
|
515
529
|
className: cn(
|
|
@@ -519,10 +533,10 @@ function ReportStepItem({ step }) {
|
|
|
519
533
|
children: step.keyword
|
|
520
534
|
}
|
|
521
535
|
),
|
|
522
|
-
/* @__PURE__ */ (0,
|
|
523
|
-
step.durationMs > 0 ? /* @__PURE__ */ (0,
|
|
536
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
|
|
537
|
+
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
|
|
524
538
|
] }),
|
|
525
|
-
step.errorMessage ? /* @__PURE__ */ (0,
|
|
539
|
+
step.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
526
540
|
"pre",
|
|
527
541
|
{
|
|
528
542
|
role: "alert",
|
|
@@ -530,24 +544,255 @@ function ReportStepItem({ step }) {
|
|
|
530
544
|
children: step.errorMessage
|
|
531
545
|
}
|
|
532
546
|
) : null,
|
|
533
|
-
step.docEntries.length > 0 ? /* @__PURE__ */ (0,
|
|
547
|
+
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
|
|
534
548
|
]
|
|
535
549
|
}
|
|
536
550
|
);
|
|
537
551
|
}
|
|
538
552
|
|
|
553
|
+
// ../executable-stories-core/dist/state-diff.js
|
|
554
|
+
var isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
555
|
+
function deepEqual(a, b) {
|
|
556
|
+
if (Object.is(a, b)) return true;
|
|
557
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
558
|
+
return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
559
|
+
}
|
|
560
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
561
|
+
const ak = Object.keys(a);
|
|
562
|
+
const bk = Object.keys(b);
|
|
563
|
+
return ak.length === bk.length && ak.every((k) => k in b && deepEqual(a[k], b[k]));
|
|
564
|
+
}
|
|
565
|
+
return false;
|
|
566
|
+
}
|
|
567
|
+
var joinKey = (path, key) => path === "" ? key : `${path}.${key}`;
|
|
568
|
+
function walk(path, before, after, out) {
|
|
569
|
+
if (Object.is(before, after)) return;
|
|
570
|
+
if (Array.isArray(before) && Array.isArray(after)) {
|
|
571
|
+
const shared = Math.min(before.length, after.length);
|
|
572
|
+
for (let i = 0; i < shared; i++) walk(`${path}[${i}]`, before[i], after[i], out);
|
|
573
|
+
for (let i = shared; i < after.length; i++) out.push({ path: `${path}[${i}]`, kind: "added", after: after[i] });
|
|
574
|
+
for (let i = shared; i < before.length; i++) out.push({ path: `${path}[${i}]`, kind: "removed", before: before[i] });
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
if (isPlainObject(before) && isPlainObject(after)) {
|
|
578
|
+
for (const key of Object.keys(after)) {
|
|
579
|
+
const p = joinKey(path, key);
|
|
580
|
+
if (key in before) walk(p, before[key], after[key], out);
|
|
581
|
+
else out.push({ path: p, kind: "added", after: after[key] });
|
|
582
|
+
}
|
|
583
|
+
for (const key of Object.keys(before)) {
|
|
584
|
+
if (!(key in after)) out.push({ path: joinKey(path, key), kind: "removed", before: before[key] });
|
|
585
|
+
}
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
if (!deepEqual(before, after)) out.push({ path, kind: "changed", before, after });
|
|
589
|
+
}
|
|
590
|
+
function diffStateValues(before, after) {
|
|
591
|
+
const out = [];
|
|
592
|
+
walk("", before, after, out);
|
|
593
|
+
return out;
|
|
594
|
+
}
|
|
595
|
+
function formatStateValue(value, maxLen = 60) {
|
|
596
|
+
const s = value === void 0 ? "undefined" : JSON.stringify(value);
|
|
597
|
+
return s.length > maxLen ? `${s.slice(0, maxLen - 1)}\u2026` : s;
|
|
598
|
+
}
|
|
599
|
+
function summarizeStateChanges(changes) {
|
|
600
|
+
return changes.map((c) => {
|
|
601
|
+
const at = c.path === "" ? "(root)" : c.path;
|
|
602
|
+
switch (c.kind) {
|
|
603
|
+
case "added":
|
|
604
|
+
return `+ ${at}: ${formatStateValue(c.after)}`;
|
|
605
|
+
case "removed":
|
|
606
|
+
return `\u2212 ${at}`;
|
|
607
|
+
case "changed":
|
|
608
|
+
return `${at}: ${formatStateValue(c.before)} \u2192 ${formatStateValue(c.after)}`;
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// ../executable-stories-core/dist/storyboard.js
|
|
614
|
+
function findScreenshot(entries) {
|
|
615
|
+
for (const entry of entries) {
|
|
616
|
+
if (entry.kind === "screenshot") return entry;
|
|
617
|
+
if (entry.children) {
|
|
618
|
+
const nested = findScreenshot(entry.children);
|
|
619
|
+
if (nested) return nested;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
return void 0;
|
|
623
|
+
}
|
|
624
|
+
function findStates(entries, out = []) {
|
|
625
|
+
for (const entry of entries) {
|
|
626
|
+
if (entry.kind === "state") out.push(entry);
|
|
627
|
+
if (entry.children) findStates(entry.children, out);
|
|
628
|
+
}
|
|
629
|
+
return out;
|
|
630
|
+
}
|
|
631
|
+
var laneOf = (label) => label ?? "";
|
|
632
|
+
function extractStoryboardFrames(scenario) {
|
|
633
|
+
const frames = [];
|
|
634
|
+
const laneOrder = [];
|
|
635
|
+
const previous = /* @__PURE__ */ new Map();
|
|
636
|
+
for (const step of scenario.steps) {
|
|
637
|
+
const shot = findScreenshot(step.docEntries);
|
|
638
|
+
const stateDocs = findStates(step.docEntries);
|
|
639
|
+
if (!shot && stateDocs.length === 0) continue;
|
|
640
|
+
const byLane = /* @__PURE__ */ new Map();
|
|
641
|
+
for (const doc of stateDocs) {
|
|
642
|
+
const lane = laneOf(doc.label);
|
|
643
|
+
if (!byLane.has(lane) && !laneOrder.includes(lane)) laneOrder.push(lane);
|
|
644
|
+
byLane.set(lane, doc);
|
|
645
|
+
}
|
|
646
|
+
const states = [];
|
|
647
|
+
for (const lane of laneOrder) {
|
|
648
|
+
const doc = byLane.get(lane);
|
|
649
|
+
if (!doc) continue;
|
|
650
|
+
const card = {
|
|
651
|
+
...doc.label !== void 0 && { label: doc.label },
|
|
652
|
+
value: doc.value
|
|
653
|
+
};
|
|
654
|
+
if (previous.has(lane)) card.changes = diffStateValues(previous.get(lane), doc.value);
|
|
655
|
+
previous.set(lane, doc.value);
|
|
656
|
+
states.push(card);
|
|
657
|
+
}
|
|
658
|
+
frames.push({
|
|
659
|
+
stepId: step.id,
|
|
660
|
+
stepIndex: step.index,
|
|
661
|
+
keyword: step.keyword,
|
|
662
|
+
text: step.text,
|
|
663
|
+
status: step.status,
|
|
664
|
+
...shot && { screenshot: { path: shot.path, ...shot.alt !== void 0 && { alt: shot.alt } } },
|
|
665
|
+
states
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
return frames;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// src/components/ReportStoryboard.tsx
|
|
672
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
673
|
+
var FRAME_GLYPH = {
|
|
674
|
+
passed: "\u2713",
|
|
675
|
+
failed: "\u2717",
|
|
676
|
+
skipped: "\u25CB",
|
|
677
|
+
pending: "\u25CB"
|
|
678
|
+
};
|
|
679
|
+
var FRAME_GLYPH_COLOR = {
|
|
680
|
+
passed: "text-pass",
|
|
681
|
+
failed: "text-fail",
|
|
682
|
+
skipped: "text-skip",
|
|
683
|
+
pending: "text-pend"
|
|
684
|
+
};
|
|
685
|
+
function ReportStoryboard({ scenario }) {
|
|
686
|
+
const frames = extractStoryboardFrames(scenario);
|
|
687
|
+
if (frames.length < 2) return null;
|
|
688
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
|
|
689
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
|
|
690
|
+
/* @__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)) })
|
|
691
|
+
] });
|
|
692
|
+
}
|
|
693
|
+
function StoryboardFrameItem({ frame }) {
|
|
694
|
+
const label = `${frame.keyword} ${frame.text}`;
|
|
695
|
+
const hasStates = frame.states.length > 0;
|
|
696
|
+
const caption = /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
|
|
697
|
+
/* @__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" }),
|
|
698
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "min-w-0", children: [
|
|
699
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
|
|
700
|
+
" ",
|
|
701
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-muted-foreground", children: frame.screenshot?.alt ?? frame.text })
|
|
702
|
+
] })
|
|
703
|
+
] });
|
|
704
|
+
return (
|
|
705
|
+
// State cards need room for diff rows; screenshot-only frames keep the
|
|
706
|
+
// original narrow film-cell width (and DOM) unchanged.
|
|
707
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("li", { className: cn("shrink-0", hasStates ? "w-64" : "w-40"), children: [
|
|
708
|
+
frame.screenshot ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(FrameScreenshot, { frame, label }) : null,
|
|
709
|
+
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,
|
|
710
|
+
frame.screenshot ? caption : (
|
|
711
|
+
// No screenshot means no image anchor, so the caption carries the
|
|
712
|
+
// jump-to-step link instead.
|
|
713
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("a", { href: `#${frame.stepId}`, "aria-label": `Jump to step: ${label}`, className: "block hover:underline", children: caption })
|
|
714
|
+
)
|
|
715
|
+
] })
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
function FrameScreenshot({ frame, label }) {
|
|
719
|
+
const path = frame.screenshot?.path ?? "";
|
|
720
|
+
const src = isLocalFsPath(path) ? void 0 : safeImageUrl(path);
|
|
721
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
722
|
+
"a",
|
|
723
|
+
{
|
|
724
|
+
href: `#${frame.stepId}`,
|
|
725
|
+
"aria-label": `Jump to step: ${label}`,
|
|
726
|
+
className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
|
|
727
|
+
children: src ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
728
|
+
"img",
|
|
729
|
+
{
|
|
730
|
+
src,
|
|
731
|
+
alt: frame.screenshot?.alt ?? label,
|
|
732
|
+
loading: "lazy",
|
|
733
|
+
className: "h-24 w-full bg-muted object-cover object-top"
|
|
734
|
+
}
|
|
735
|
+
) : /* @__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" })
|
|
736
|
+
}
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
var CHANGE_TONE = {
|
|
740
|
+
added: "bg-pass-bg text-pass",
|
|
741
|
+
removed: "bg-fail-bg text-fail",
|
|
742
|
+
changed: "bg-skip-bg text-skip"
|
|
743
|
+
};
|
|
744
|
+
function prettyJson(value) {
|
|
745
|
+
try {
|
|
746
|
+
return JSON.stringify(value, null, 2) ?? String(value);
|
|
747
|
+
} catch {
|
|
748
|
+
return String(value);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
function StateCardView({ card }) {
|
|
752
|
+
const json = prettyJson(card.value);
|
|
753
|
+
const firstCapture = card.changes === void 0;
|
|
754
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { "data-slot": "state-card", className: "rounded-md border border-border bg-card p-2", children: [
|
|
755
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("p", { className: "flex flex-wrap items-baseline gap-1.5", children: [
|
|
756
|
+
/* @__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" }),
|
|
757
|
+
firstCapture ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-[0.625rem] text-muted-foreground italic", children: "first capture" }) : null
|
|
758
|
+
] }),
|
|
759
|
+
!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)(
|
|
760
|
+
"li",
|
|
761
|
+
{
|
|
762
|
+
className: cn(
|
|
763
|
+
"rounded-sm px-1.5 py-0.5 font-mono text-[0.625rem] leading-snug break-all",
|
|
764
|
+
CHANGE_TONE[change.kind]
|
|
765
|
+
),
|
|
766
|
+
children: summarizeStateChanges([change])[0]
|
|
767
|
+
},
|
|
768
|
+
i
|
|
769
|
+
)) }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-1.5 text-[0.625rem] text-muted-foreground", children: "No changes" })),
|
|
770
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
771
|
+
"details",
|
|
772
|
+
{
|
|
773
|
+
open: firstCapture && json.length <= 240,
|
|
774
|
+
className: cn(firstCapture ? "mt-1.5" : "mt-1"),
|
|
775
|
+
children: [
|
|
776
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("summary", { className: "cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground", children: "Snapshot" }),
|
|
777
|
+
/* @__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 })
|
|
778
|
+
]
|
|
779
|
+
}
|
|
780
|
+
)
|
|
781
|
+
] });
|
|
782
|
+
}
|
|
783
|
+
|
|
539
784
|
// src/components/ReportAttachments.tsx
|
|
540
|
-
var
|
|
785
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
541
786
|
function ReportAttachments({ attachments }) {
|
|
542
787
|
if (attachments.length === 0) return null;
|
|
543
788
|
return (
|
|
544
789
|
// role="group" (not a labelled <section>) so multiple scenarios' attachment
|
|
545
790
|
// blocks don't create duplicate "Attachments" region landmarks.
|
|
546
|
-
/* @__PURE__ */ (0,
|
|
791
|
+
/* @__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) => {
|
|
547
792
|
const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
|
|
548
793
|
const isImage = att.mediaType.startsWith("image/");
|
|
549
|
-
return /* @__PURE__ */ (0,
|
|
550
|
-
/* @__PURE__ */ (0,
|
|
794
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
795
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
551
796
|
"img",
|
|
552
797
|
{
|
|
553
798
|
src: dataUri,
|
|
@@ -556,8 +801,8 @@ function ReportAttachments({ attachments }) {
|
|
|
556
801
|
className: "max-w-full rounded-md border border-border"
|
|
557
802
|
}
|
|
558
803
|
),
|
|
559
|
-
/* @__PURE__ */ (0,
|
|
560
|
-
] }) : /* @__PURE__ */ (0,
|
|
804
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
|
|
805
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
561
806
|
"a",
|
|
562
807
|
{
|
|
563
808
|
href: dataUri,
|
|
@@ -566,7 +811,7 @@ function ReportAttachments({ attachments }) {
|
|
|
566
811
|
children: [
|
|
567
812
|
att.name,
|
|
568
813
|
" ",
|
|
569
|
-
/* @__PURE__ */ (0,
|
|
814
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
570
815
|
"(",
|
|
571
816
|
att.mediaType,
|
|
572
817
|
")"
|
|
@@ -630,15 +875,15 @@ function toTraceRows(spans) {
|
|
|
630
875
|
roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
631
876
|
const rows = [];
|
|
632
877
|
const seen = /* @__PURE__ */ new Set();
|
|
633
|
-
const
|
|
878
|
+
const walk2 = (node, depth) => {
|
|
634
879
|
if (seen.has(node.span.spanId)) return;
|
|
635
880
|
seen.add(node.span.spanId);
|
|
636
881
|
rows.push({ ...node.span, depth });
|
|
637
|
-
for (const child of node.children)
|
|
882
|
+
for (const child of node.children) walk2(child, depth + 1);
|
|
638
883
|
};
|
|
639
|
-
for (const root of roots)
|
|
884
|
+
for (const root of roots) walk2(root, 0);
|
|
640
885
|
for (const node of byId.values()) {
|
|
641
|
-
if (!seen.has(node.span.spanId))
|
|
886
|
+
if (!seen.has(node.span.spanId)) walk2(node, 0);
|
|
642
887
|
}
|
|
643
888
|
return rows;
|
|
644
889
|
}
|
|
@@ -654,7 +899,7 @@ function traceWindow(rows) {
|
|
|
654
899
|
}
|
|
655
900
|
|
|
656
901
|
// src/components/ReportTrace.tsx
|
|
657
|
-
var
|
|
902
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
658
903
|
var BAR_COLOR = {
|
|
659
904
|
ok: "bg-pass",
|
|
660
905
|
error: "bg-fail",
|
|
@@ -665,8 +910,8 @@ function ReportTrace({ spans }) {
|
|
|
665
910
|
const rows = toTraceRows(spans);
|
|
666
911
|
if (rows.length === 0) return null;
|
|
667
912
|
const { minStartMs, totalMs } = traceWindow(rows);
|
|
668
|
-
return /* @__PURE__ */ (0,
|
|
669
|
-
/* @__PURE__ */ (0,
|
|
913
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
|
|
914
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
|
|
670
915
|
"Trace (",
|
|
671
916
|
rows.length,
|
|
672
917
|
" span",
|
|
@@ -675,11 +920,11 @@ function ReportTrace({ spans }) {
|
|
|
675
920
|
formatDuration(totalMs),
|
|
676
921
|
")"
|
|
677
922
|
] }),
|
|
678
|
-
/* @__PURE__ */ (0,
|
|
923
|
+
/* @__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) => {
|
|
679
924
|
const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
|
|
680
925
|
const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
|
|
681
|
-
return /* @__PURE__ */ (0,
|
|
682
|
-
/* @__PURE__ */ (0,
|
|
926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("li", { className: "flex items-center gap-2", children: [
|
|
927
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
683
928
|
"span",
|
|
684
929
|
{
|
|
685
930
|
className: "min-w-0 flex-1 truncate text-foreground",
|
|
@@ -688,14 +933,14 @@ function ReportTrace({ spans }) {
|
|
|
688
933
|
children: row.name
|
|
689
934
|
}
|
|
690
935
|
),
|
|
691
|
-
/* @__PURE__ */ (0,
|
|
936
|
+
/* @__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)(
|
|
692
937
|
"span",
|
|
693
938
|
{
|
|
694
939
|
className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
|
|
695
940
|
style: { left: `${leftPct}%`, width: `${widthPct}%` }
|
|
696
941
|
}
|
|
697
942
|
) }),
|
|
698
|
-
/* @__PURE__ */ (0,
|
|
943
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
|
|
699
944
|
] }, `${row.spanId}-${i}`);
|
|
700
945
|
}) })
|
|
701
946
|
] });
|
|
@@ -746,7 +991,7 @@ function flakinessOf(entries) {
|
|
|
746
991
|
}
|
|
747
992
|
|
|
748
993
|
// src/components/ScenarioRunHistory.tsx
|
|
749
|
-
var
|
|
994
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
750
995
|
var MAX_DOTS = 10;
|
|
751
996
|
var DOT_COLOR = {
|
|
752
997
|
passed: "bg-pass",
|
|
@@ -766,16 +1011,16 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
766
1011
|
const recent = entries.slice(-MAX_DOTS);
|
|
767
1012
|
const flaky = flakinessOf(recent) === "flaky";
|
|
768
1013
|
const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
|
|
769
|
-
return /* @__PURE__ */ (0,
|
|
770
|
-
flaky ? /* @__PURE__ */ (0,
|
|
771
|
-
/* @__PURE__ */ (0,
|
|
1014
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
1015
|
+
flaky ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
|
|
1016
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
772
1017
|
"span",
|
|
773
1018
|
{
|
|
774
1019
|
role: "img",
|
|
775
1020
|
"aria-label": `Run history: ${summary}`,
|
|
776
1021
|
title: summary,
|
|
777
1022
|
className: "flex shrink-0 items-center gap-[3px]",
|
|
778
|
-
children: recent.map((e, i) => /* @__PURE__ */ (0,
|
|
1023
|
+
children: recent.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
779
1024
|
"span",
|
|
780
1025
|
{
|
|
781
1026
|
"aria-hidden": true,
|
|
@@ -814,9 +1059,9 @@ function useScenarioActions() {
|
|
|
814
1059
|
|
|
815
1060
|
// src/components/ui/card.tsx
|
|
816
1061
|
var React2 = require("react");
|
|
817
|
-
var
|
|
1062
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
818
1063
|
function Card({ className, ...props }) {
|
|
819
|
-
return /* @__PURE__ */ (0,
|
|
1064
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
820
1065
|
"div",
|
|
821
1066
|
{
|
|
822
1067
|
"data-slot": "card",
|
|
@@ -829,7 +1074,7 @@ function Card({ className, ...props }) {
|
|
|
829
1074
|
);
|
|
830
1075
|
}
|
|
831
1076
|
function CardHeader({ className, ...props }) {
|
|
832
|
-
return /* @__PURE__ */ (0,
|
|
1077
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
833
1078
|
"div",
|
|
834
1079
|
{
|
|
835
1080
|
"data-slot": "card-header",
|
|
@@ -842,7 +1087,7 @@ function CardHeader({ className, ...props }) {
|
|
|
842
1087
|
);
|
|
843
1088
|
}
|
|
844
1089
|
function CardContent({ className, ...props }) {
|
|
845
|
-
return /* @__PURE__ */ (0,
|
|
1090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
846
1091
|
"div",
|
|
847
1092
|
{
|
|
848
1093
|
"data-slot": "card-content",
|
|
@@ -856,13 +1101,13 @@ function CardContent({ className, ...props }) {
|
|
|
856
1101
|
var React3 = require("react");
|
|
857
1102
|
var import_menu = require("@base-ui/react/menu");
|
|
858
1103
|
var import_lucide_react = require("lucide-react");
|
|
859
|
-
var
|
|
1104
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
860
1105
|
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";
|
|
861
1106
|
function DropdownMenu(props) {
|
|
862
|
-
return /* @__PURE__ */ (0,
|
|
1107
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
863
1108
|
}
|
|
864
1109
|
function DropdownMenuTrigger(props) {
|
|
865
|
-
return /* @__PURE__ */ (0,
|
|
1110
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
866
1111
|
}
|
|
867
1112
|
function DropdownMenuContent({
|
|
868
1113
|
className,
|
|
@@ -870,14 +1115,14 @@ function DropdownMenuContent({
|
|
|
870
1115
|
sideOffset = 4,
|
|
871
1116
|
...props
|
|
872
1117
|
}) {
|
|
873
|
-
return /* @__PURE__ */ (0,
|
|
1118
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
874
1119
|
import_menu.Menu.Positioner,
|
|
875
1120
|
{
|
|
876
1121
|
"data-slot": "dropdown-menu-positioner",
|
|
877
1122
|
className: "z-50",
|
|
878
1123
|
align,
|
|
879
1124
|
sideOffset,
|
|
880
|
-
children: /* @__PURE__ */ (0,
|
|
1125
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
881
1126
|
import_menu.Menu.Popup,
|
|
882
1127
|
{
|
|
883
1128
|
"data-slot": "dropdown-menu-content",
|
|
@@ -895,7 +1140,7 @@ function DropdownMenuItem({
|
|
|
895
1140
|
className,
|
|
896
1141
|
...props
|
|
897
1142
|
}) {
|
|
898
|
-
return /* @__PURE__ */ (0,
|
|
1143
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
899
1144
|
import_menu.Menu.Item,
|
|
900
1145
|
{
|
|
901
1146
|
"data-slot": "dropdown-menu-item",
|
|
@@ -907,7 +1152,7 @@ function DropdownMenuItem({
|
|
|
907
1152
|
|
|
908
1153
|
// src/components/ReportScenario.tsx
|
|
909
1154
|
var import_lucide_react2 = require("lucide-react");
|
|
910
|
-
var
|
|
1155
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
911
1156
|
var STATUS_META = {
|
|
912
1157
|
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
913
1158
|
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
@@ -923,7 +1168,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
923
1168
|
const collapsible = collapse !== null && !hideTitle;
|
|
924
1169
|
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
925
1170
|
const actions = useScenarioActions();
|
|
926
|
-
return /* @__PURE__ */ (0,
|
|
1171
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
927
1172
|
Card,
|
|
928
1173
|
{
|
|
929
1174
|
id: scenario.id,
|
|
@@ -931,10 +1176,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
931
1176
|
...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
|
|
932
1177
|
className: "gap-0 py-0",
|
|
933
1178
|
children: [
|
|
934
|
-
/* @__PURE__ */ (0,
|
|
935
|
-
/* @__PURE__ */ (0,
|
|
936
|
-
hideTitle ? null : /* @__PURE__ */ (0,
|
|
937
|
-
collapsible ? /* @__PURE__ */ (0,
|
|
1179
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(CardHeader, { className: "px-4 py-3", children: [
|
|
1180
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
1181
|
+
hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
1182
|
+
collapsible ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
938
1183
|
"button",
|
|
939
1184
|
{
|
|
940
1185
|
type: "button",
|
|
@@ -943,49 +1188,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
943
1188
|
"aria-controls": bodyId,
|
|
944
1189
|
"aria-label": `Toggle ${scenario.title}`,
|
|
945
1190
|
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
946
|
-
children: /* @__PURE__ */ (0,
|
|
1191
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
947
1192
|
}
|
|
948
1193
|
) : null,
|
|
949
|
-
/* @__PURE__ */ (0,
|
|
950
|
-
/* @__PURE__ */ (0,
|
|
1194
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
1195
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: scenario.title })
|
|
951
1196
|
] }),
|
|
952
|
-
/* @__PURE__ */ (0,
|
|
953
|
-
/* @__PURE__ */ (0,
|
|
954
|
-
scenario.durationMs > 0 ? /* @__PURE__ */ (0,
|
|
955
|
-
meta.showPill ? /* @__PURE__ */ (0,
|
|
956
|
-
actions ? /* @__PURE__ */ (0,
|
|
957
|
-
/* @__PURE__ */ (0,
|
|
1197
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1198
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1199
|
+
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,
|
|
1200
|
+
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}` }),
|
|
1201
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenu, { children: [
|
|
1202
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
958
1203
|
DropdownMenuTrigger,
|
|
959
1204
|
{
|
|
960
1205
|
"aria-label": `Actions for ${scenario.title}`,
|
|
961
1206
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
962
|
-
children: /* @__PURE__ */ (0,
|
|
1207
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
|
|
963
1208
|
}
|
|
964
1209
|
),
|
|
965
|
-
/* @__PURE__ */ (0,
|
|
966
|
-
/* @__PURE__ */ (0,
|
|
967
|
-
/* @__PURE__ */ (0,
|
|
1210
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuContent, { align: "end", children: [
|
|
1211
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
1212
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.LinkIcon, {}),
|
|
968
1213
|
" Copy link"
|
|
969
1214
|
] }),
|
|
970
|
-
/* @__PURE__ */ (0,
|
|
971
|
-
/* @__PURE__ */ (0,
|
|
1215
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
1216
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.FileTextIcon, {}),
|
|
972
1217
|
" Copy as Markdown"
|
|
973
1218
|
] }),
|
|
974
|
-
/* @__PURE__ */ (0,
|
|
975
|
-
/* @__PURE__ */ (0,
|
|
1219
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
1220
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react2.SparklesIcon, {}),
|
|
976
1221
|
" Explain with AI"
|
|
977
1222
|
] })
|
|
978
1223
|
] })
|
|
979
1224
|
] }) : null
|
|
980
1225
|
] })
|
|
981
1226
|
] }),
|
|
982
|
-
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0,
|
|
983
|
-
scenario.tags.map((t) => /* @__PURE__ */ (0,
|
|
984
|
-
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0,
|
|
1227
|
+
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: [
|
|
1228
|
+
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}`)),
|
|
1229
|
+
(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}`))
|
|
985
1230
|
] }) : null
|
|
986
1231
|
] }),
|
|
987
|
-
/* @__PURE__ */ (0,
|
|
988
|
-
scenario.errorMessage ? /* @__PURE__ */ (0,
|
|
1232
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
1233
|
+
scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
989
1234
|
"pre",
|
|
990
1235
|
{
|
|
991
1236
|
role: "alert",
|
|
@@ -993,10 +1238,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
993
1238
|
children: scenario.errorMessage
|
|
994
1239
|
}
|
|
995
1240
|
) : null,
|
|
996
|
-
/* @__PURE__ */ (0,
|
|
997
|
-
|
|
998
|
-
/* @__PURE__ */ (0,
|
|
999
|
-
/* @__PURE__ */ (0,
|
|
1241
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportStoryboard, { scenario }),
|
|
1242
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportSteps, { scenario }),
|
|
1243
|
+
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,
|
|
1244
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportAttachments, { attachments: scenario.attachments }),
|
|
1245
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ReportTrace, { spans: scenario.otelSpans })
|
|
1000
1246
|
] })
|
|
1001
1247
|
]
|
|
1002
1248
|
}
|
|
@@ -1004,13 +1250,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1004
1250
|
}
|
|
1005
1251
|
|
|
1006
1252
|
// src/components/ReportScenarioList.tsx
|
|
1007
|
-
var
|
|
1253
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1008
1254
|
function ReportScenarioList({ feature }) {
|
|
1009
|
-
return /* @__PURE__ */ (0,
|
|
1255
|
+
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)) });
|
|
1010
1256
|
}
|
|
1011
1257
|
|
|
1012
1258
|
// src/components/ReportFeature.tsx
|
|
1013
|
-
var
|
|
1259
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1014
1260
|
function ReportFeature({ feature }) {
|
|
1015
1261
|
const titleId = `${feature.id}-title`;
|
|
1016
1262
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1021,7 +1267,7 @@ function ReportFeature({ feature }) {
|
|
|
1021
1267
|
return (
|
|
1022
1268
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
1023
1269
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1024
|
-
/* @__PURE__ */ (0,
|
|
1270
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1025
1271
|
"section",
|
|
1026
1272
|
{
|
|
1027
1273
|
id: feature.id,
|
|
@@ -1029,9 +1275,9 @@ function ReportFeature({ feature }) {
|
|
|
1029
1275
|
"aria-labelledby": titleId,
|
|
1030
1276
|
className: "flex flex-col gap-3",
|
|
1031
1277
|
children: [
|
|
1032
|
-
/* @__PURE__ */ (0,
|
|
1033
|
-
/* @__PURE__ */ (0,
|
|
1034
|
-
/* @__PURE__ */ (0,
|
|
1278
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1279
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "min-w-0", children: [
|
|
1280
|
+
/* @__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)(
|
|
1035
1281
|
"button",
|
|
1036
1282
|
{
|
|
1037
1283
|
type: "button",
|
|
@@ -1040,31 +1286,31 @@ function ReportFeature({ feature }) {
|
|
|
1040
1286
|
"aria-controls": bodyId,
|
|
1041
1287
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1042
1288
|
children: [
|
|
1043
|
-
/* @__PURE__ */ (0,
|
|
1044
|
-
/* @__PURE__ */ (0,
|
|
1289
|
+
/* @__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" }),
|
|
1290
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate", children: feature.title })
|
|
1045
1291
|
]
|
|
1046
1292
|
}
|
|
1047
1293
|
) : feature.title }),
|
|
1048
|
-
/* @__PURE__ */ (0,
|
|
1294
|
+
/* @__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 })
|
|
1049
1295
|
] }),
|
|
1050
|
-
/* @__PURE__ */ (0,
|
|
1296
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1051
1297
|
"p",
|
|
1052
1298
|
{
|
|
1053
1299
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1054
1300
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1055
1301
|
children: [
|
|
1056
|
-
/* @__PURE__ */ (0,
|
|
1302
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { children: [
|
|
1057
1303
|
s.passed,
|
|
1058
1304
|
" passed"
|
|
1059
1305
|
] }),
|
|
1060
|
-
/* @__PURE__ */ (0,
|
|
1061
|
-
/* @__PURE__ */ (0,
|
|
1306
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1307
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1062
1308
|
s.failed,
|
|
1063
1309
|
" failed"
|
|
1064
1310
|
] }),
|
|
1065
|
-
skipped > 0 ? /* @__PURE__ */ (0,
|
|
1066
|
-
/* @__PURE__ */ (0,
|
|
1067
|
-
/* @__PURE__ */ (0,
|
|
1311
|
+
skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
1312
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1313
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { children: [
|
|
1068
1314
|
skipped,
|
|
1069
1315
|
" skipped"
|
|
1070
1316
|
] })
|
|
@@ -1073,7 +1319,7 @@ function ReportFeature({ feature }) {
|
|
|
1073
1319
|
}
|
|
1074
1320
|
)
|
|
1075
1321
|
] }),
|
|
1076
|
-
/* @__PURE__ */ (0,
|
|
1322
|
+
/* @__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 }) })
|
|
1077
1323
|
]
|
|
1078
1324
|
}
|
|
1079
1325
|
)
|
|
@@ -1081,17 +1327,17 @@ function ReportFeature({ feature }) {
|
|
|
1081
1327
|
}
|
|
1082
1328
|
|
|
1083
1329
|
// src/components/ReportFeatureList.tsx
|
|
1084
|
-
var
|
|
1330
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1085
1331
|
function ReportFeatureList() {
|
|
1086
1332
|
const report = useReport();
|
|
1087
|
-
return /* @__PURE__ */ (0,
|
|
1333
|
+
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)) });
|
|
1088
1334
|
}
|
|
1089
1335
|
|
|
1090
1336
|
// src/components/ui/empty.tsx
|
|
1091
1337
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
1092
|
-
var
|
|
1338
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1093
1339
|
function Empty({ className, ...props }) {
|
|
1094
|
-
return /* @__PURE__ */ (0,
|
|
1340
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1095
1341
|
"div",
|
|
1096
1342
|
{
|
|
1097
1343
|
"data-slot": "empty",
|
|
@@ -1104,7 +1350,7 @@ function Empty({ className, ...props }) {
|
|
|
1104
1350
|
);
|
|
1105
1351
|
}
|
|
1106
1352
|
function EmptyHeader({ className, ...props }) {
|
|
1107
|
-
return /* @__PURE__ */ (0,
|
|
1353
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1108
1354
|
"div",
|
|
1109
1355
|
{
|
|
1110
1356
|
"data-slot": "empty-header",
|
|
@@ -1131,7 +1377,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
|
|
|
1131
1377
|
}
|
|
1132
1378
|
);
|
|
1133
1379
|
function EmptyTitle({ className, ...props }) {
|
|
1134
|
-
return /* @__PURE__ */ (0,
|
|
1380
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1135
1381
|
"div",
|
|
1136
1382
|
{
|
|
1137
1383
|
"data-slot": "empty-title",
|
|
@@ -1142,16 +1388,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1142
1388
|
}
|
|
1143
1389
|
|
|
1144
1390
|
// src/components/ReportEmpty.tsx
|
|
1145
|
-
var
|
|
1391
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1146
1392
|
function ReportEmpty({ message }) {
|
|
1147
|
-
return /* @__PURE__ */ (0,
|
|
1393
|
+
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." }) }) });
|
|
1148
1394
|
}
|
|
1149
1395
|
|
|
1150
1396
|
// src/components/ReportSummary.tsx
|
|
1151
|
-
var
|
|
1397
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1152
1398
|
function ReportSummary({ className }) {
|
|
1153
1399
|
const report = useReport();
|
|
1154
|
-
return /* @__PURE__ */ (0,
|
|
1400
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1155
1401
|
ReportSummaryView,
|
|
1156
1402
|
{
|
|
1157
1403
|
summary: report.summary,
|
|
@@ -1177,7 +1423,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1177
1423
|
if (summary.pending > 0) {
|
|
1178
1424
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1179
1425
|
}
|
|
1180
|
-
return /* @__PURE__ */ (0,
|
|
1426
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1181
1427
|
"dl",
|
|
1182
1428
|
{
|
|
1183
1429
|
className: cn(
|
|
@@ -1190,17 +1436,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1190
1436
|
"aria-label": ariaLabel,
|
|
1191
1437
|
children: cards.map((c) => {
|
|
1192
1438
|
const tone = TONE[c.status];
|
|
1193
|
-
return /* @__PURE__ */ (0,
|
|
1439
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
1194
1440
|
"div",
|
|
1195
1441
|
{
|
|
1196
1442
|
"data-status": c.status,
|
|
1197
1443
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1198
1444
|
children: [
|
|
1199
|
-
/* @__PURE__ */ (0,
|
|
1200
|
-
/* @__PURE__ */ (0,
|
|
1445
|
+
/* @__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: [
|
|
1446
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1201
1447
|
c.label
|
|
1202
1448
|
] }),
|
|
1203
|
-
/* @__PURE__ */ (0,
|
|
1449
|
+
/* @__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 })
|
|
1204
1450
|
]
|
|
1205
1451
|
},
|
|
1206
1452
|
c.status
|
|
@@ -1241,7 +1487,7 @@ function prUrl(ci) {
|
|
|
1241
1487
|
}
|
|
1242
1488
|
|
|
1243
1489
|
// src/components/ReportMeta.tsx
|
|
1244
|
-
var
|
|
1490
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1245
1491
|
function ReportMeta() {
|
|
1246
1492
|
const report = useReport();
|
|
1247
1493
|
const items = [];
|
|
@@ -1264,13 +1510,13 @@ function ReportMeta() {
|
|
|
1264
1510
|
const short = sha.slice(0, 8);
|
|
1265
1511
|
items.push({
|
|
1266
1512
|
label: "Commit",
|
|
1267
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1513
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1268
1514
|
});
|
|
1269
1515
|
}
|
|
1270
1516
|
if (report.ci) {
|
|
1271
1517
|
items.push({
|
|
1272
1518
|
label: "CI",
|
|
1273
|
-
value: report.ci.url ? /* @__PURE__ */ (0,
|
|
1519
|
+
value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1274
1520
|
ciDisplayName(report.ci.name),
|
|
1275
1521
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1276
1522
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1281,7 +1527,7 @@ function ReportMeta() {
|
|
|
1281
1527
|
const label = `#${report.ci.prNumber}`;
|
|
1282
1528
|
items.push({
|
|
1283
1529
|
label: "PR",
|
|
1284
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1530
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1285
1531
|
});
|
|
1286
1532
|
}
|
|
1287
1533
|
if (items.length === 0) return null;
|
|
@@ -1289,48 +1535,48 @@ function ReportMeta() {
|
|
|
1289
1535
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1290
1536
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1291
1537
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1292
|
-
/* @__PURE__ */ (0,
|
|
1293
|
-
/* @__PURE__ */ (0,
|
|
1294
|
-
/* @__PURE__ */ (0,
|
|
1538
|
+
/* @__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: [
|
|
1539
|
+
/* @__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: [
|
|
1540
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1295
1541
|
"Run details"
|
|
1296
1542
|
] }),
|
|
1297
|
-
/* @__PURE__ */ (0,
|
|
1298
|
-
/* @__PURE__ */ (0,
|
|
1299
|
-
/* @__PURE__ */ (0,
|
|
1543
|
+
/* @__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: [
|
|
1544
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("dt", { className: "font-medium", children: item.label }),
|
|
1545
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1300
1546
|
] }, item.label)) })
|
|
1301
1547
|
] })
|
|
1302
1548
|
);
|
|
1303
1549
|
}
|
|
1304
1550
|
|
|
1305
1551
|
// src/components/ReportSchemaError.tsx
|
|
1306
|
-
var
|
|
1552
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1307
1553
|
function ReportSchemaError({ error }) {
|
|
1308
|
-
return /* @__PURE__ */ (0,
|
|
1309
|
-
/* @__PURE__ */ (0,
|
|
1310
|
-
/* @__PURE__ */ (0,
|
|
1311
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0,
|
|
1554
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1555
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("strong", { children: "Report could not be displayed." }) }),
|
|
1556
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { children: error.message }),
|
|
1557
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("p", { children: [
|
|
1312
1558
|
"The report bundle is newer than this version of ",
|
|
1313
|
-
/* @__PURE__ */ (0,
|
|
1559
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("code", { children: "executable-stories-react" }),
|
|
1314
1560
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1315
1561
|
] }) : null,
|
|
1316
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0,
|
|
1317
|
-
/* @__PURE__ */ (0,
|
|
1562
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("details", { children: [
|
|
1563
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("summary", { children: [
|
|
1318
1564
|
error.issues.length,
|
|
1319
1565
|
" validation issue",
|
|
1320
1566
|
error.issues.length === 1 ? "" : "s"
|
|
1321
1567
|
] }),
|
|
1322
|
-
/* @__PURE__ */ (0,
|
|
1568
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1323
1569
|
] }) : null
|
|
1324
1570
|
] });
|
|
1325
1571
|
}
|
|
1326
1572
|
|
|
1327
1573
|
// src/components/ReportShell.tsx
|
|
1328
|
-
var
|
|
1574
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1329
1575
|
function ReportTitleBlock({ title }) {
|
|
1330
|
-
return /* @__PURE__ */ (0,
|
|
1331
|
-
/* @__PURE__ */ (0,
|
|
1332
|
-
/* @__PURE__ */ (0,
|
|
1333
|
-
/* @__PURE__ */ (0,
|
|
1576
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
1577
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("h1", { children: title ?? "Story Report" }),
|
|
1578
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ReportSummary, {}),
|
|
1579
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ReportMeta, {})
|
|
1334
1580
|
] });
|
|
1335
1581
|
}
|
|
1336
1582
|
function ReportErrorShell({
|
|
@@ -1339,22 +1585,22 @@ function ReportErrorShell({
|
|
|
1339
1585
|
title,
|
|
1340
1586
|
dataTheme
|
|
1341
1587
|
}) {
|
|
1342
|
-
return /* @__PURE__ */ (0,
|
|
1588
|
+
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 }) });
|
|
1343
1589
|
}
|
|
1344
1590
|
|
|
1345
1591
|
// src/components/Report.tsx
|
|
1346
|
-
var
|
|
1592
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
1347
1593
|
function Report(props) {
|
|
1348
1594
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1349
1595
|
const result = unwrapReport(report);
|
|
1350
1596
|
if (!result.ok) {
|
|
1351
|
-
return /* @__PURE__ */ (0,
|
|
1597
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1352
1598
|
}
|
|
1353
1599
|
const data = result.data;
|
|
1354
1600
|
const hasContent = data.features.length > 0;
|
|
1355
|
-
return /* @__PURE__ */ (0,
|
|
1356
|
-
/* @__PURE__ */ (0,
|
|
1357
|
-
hasContent ? /* @__PURE__ */ (0,
|
|
1601
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1602
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportTitleBlock, { title }) }),
|
|
1603
|
+
hasContent ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ReportEmpty, {})
|
|
1358
1604
|
] }) });
|
|
1359
1605
|
}
|
|
1360
1606
|
|