executable-stories-react 0.7.0 → 0.9.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 +453 -230
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -6
- package/dist/index.d.ts +17 -6
- package/dist/index.js +404 -181
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +669 -377
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +35 -4
- package/dist/interactive.d.ts +35 -4
- package/dist/interactive.js +583 -291
- 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 +26 -26
- package/dist/ssr.cjs +356 -194
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.d.cts +10 -1
- package/dist/ssr.d.ts +10 -1
- package/dist/ssr.js +316 -154
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +1 -1
package/dist/ssr.js
CHANGED
|
@@ -375,17 +375,29 @@ function DocHtml({ entry }) {
|
|
|
375
375
|
] });
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
+
// src/components/doc/DocState.tsx
|
|
379
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
380
|
+
function DocState({ entry }) {
|
|
381
|
+
let json;
|
|
382
|
+
try {
|
|
383
|
+
json = JSON.stringify(entry.value, null, 2) ?? String(entry.value);
|
|
384
|
+
} catch {
|
|
385
|
+
json = String(entry.value);
|
|
386
|
+
}
|
|
387
|
+
return /* @__PURE__ */ jsx13(CodeFigure, { label: entry.label ?? "State", children: /* @__PURE__ */ jsx13("code", { className: "font-mono text-xs language-json", children: json }) });
|
|
388
|
+
}
|
|
389
|
+
|
|
378
390
|
// src/components/doc/DocCustom.tsx
|
|
379
|
-
import { Fragment as Fragment4, jsx as
|
|
391
|
+
import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
380
392
|
function DocCustom({ entry }) {
|
|
381
393
|
const renderers = useCustomRenderers();
|
|
382
394
|
const renderer = renderers[entry.type];
|
|
383
395
|
if (renderer) {
|
|
384
|
-
return /* @__PURE__ */
|
|
396
|
+
return /* @__PURE__ */ jsx14(Fragment4, { children: renderer(entry) });
|
|
385
397
|
}
|
|
386
398
|
return /* @__PURE__ */ jsxs9("div", { className: "my-2", "data-type": entry.type, children: [
|
|
387
|
-
/* @__PURE__ */
|
|
388
|
-
/* @__PURE__ */
|
|
399
|
+
/* @__PURE__ */ jsx14("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
|
|
400
|
+
/* @__PURE__ */ jsx14("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground", children: safeStringify(entry.data) })
|
|
389
401
|
] });
|
|
390
402
|
}
|
|
391
403
|
function safeStringify(value) {
|
|
@@ -397,45 +409,47 @@ function safeStringify(value) {
|
|
|
397
409
|
}
|
|
398
410
|
|
|
399
411
|
// src/components/doc/DocEntry.tsx
|
|
400
|
-
import { jsx as
|
|
412
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
401
413
|
function DocEntry({ entry }) {
|
|
402
414
|
switch (entry.kind) {
|
|
403
415
|
case "note":
|
|
404
|
-
return /* @__PURE__ */
|
|
416
|
+
return /* @__PURE__ */ jsx15(DocNote, { entry });
|
|
405
417
|
case "tag":
|
|
406
|
-
return /* @__PURE__ */
|
|
418
|
+
return /* @__PURE__ */ jsx15(DocTag, { entry });
|
|
407
419
|
case "kv":
|
|
408
|
-
return /* @__PURE__ */
|
|
420
|
+
return /* @__PURE__ */ jsx15(DocKv, { entry });
|
|
409
421
|
case "code":
|
|
410
|
-
return /* @__PURE__ */
|
|
422
|
+
return /* @__PURE__ */ jsx15(DocCode, { entry });
|
|
411
423
|
case "table":
|
|
412
|
-
return /* @__PURE__ */
|
|
424
|
+
return /* @__PURE__ */ jsx15(DocTable, { entry });
|
|
413
425
|
case "link":
|
|
414
|
-
return /* @__PURE__ */
|
|
426
|
+
return /* @__PURE__ */ jsx15(DocLink, { entry });
|
|
415
427
|
case "section":
|
|
416
|
-
return /* @__PURE__ */
|
|
428
|
+
return /* @__PURE__ */ jsx15(DocSection, { entry });
|
|
417
429
|
case "mermaid":
|
|
418
|
-
return /* @__PURE__ */
|
|
430
|
+
return /* @__PURE__ */ jsx15(DocMermaid, { entry });
|
|
419
431
|
case "screenshot":
|
|
420
|
-
return /* @__PURE__ */
|
|
432
|
+
return /* @__PURE__ */ jsx15(DocScreenshot, { entry });
|
|
421
433
|
case "video":
|
|
422
|
-
return /* @__PURE__ */
|
|
434
|
+
return /* @__PURE__ */ jsx15(DocVideo, { entry });
|
|
423
435
|
case "html":
|
|
424
|
-
return /* @__PURE__ */
|
|
436
|
+
return /* @__PURE__ */ jsx15(DocHtml, { entry });
|
|
437
|
+
case "state":
|
|
438
|
+
return /* @__PURE__ */ jsx15(DocState, { entry });
|
|
425
439
|
case "custom":
|
|
426
|
-
return /* @__PURE__ */
|
|
440
|
+
return /* @__PURE__ */ jsx15(DocCustom, { entry });
|
|
427
441
|
}
|
|
428
442
|
}
|
|
429
443
|
|
|
430
444
|
// src/components/ReportDocEntries.tsx
|
|
431
|
-
import { Fragment as Fragment5, jsx as
|
|
445
|
+
import { Fragment as Fragment5, jsx as jsx16 } from "react/jsx-runtime";
|
|
432
446
|
function ReportDocEntries({ entries }) {
|
|
433
447
|
if (entries.length === 0) return null;
|
|
434
|
-
return /* @__PURE__ */
|
|
448
|
+
return /* @__PURE__ */ jsx16(Fragment5, { children: entries.map((entry, i) => /* @__PURE__ */ jsx16(DocEntry, { entry }, i)) });
|
|
435
449
|
}
|
|
436
450
|
|
|
437
451
|
// src/lib/step-params.tsx
|
|
438
|
-
import { jsx as
|
|
452
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
439
453
|
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
440
454
|
function highlightStepParams(text) {
|
|
441
455
|
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
@@ -447,7 +461,7 @@ function highlightStepParams(text) {
|
|
|
447
461
|
const end = start + match[0].length;
|
|
448
462
|
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
449
463
|
nodes.push(
|
|
450
|
-
/* @__PURE__ */
|
|
464
|
+
/* @__PURE__ */ jsx17("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
451
465
|
);
|
|
452
466
|
lastIndex = end;
|
|
453
467
|
});
|
|
@@ -456,7 +470,7 @@ function highlightStepParams(text) {
|
|
|
456
470
|
}
|
|
457
471
|
|
|
458
472
|
// src/components/ReportSteps.tsx
|
|
459
|
-
import { jsx as
|
|
473
|
+
import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
460
474
|
var STEP_GLYPH = {
|
|
461
475
|
passed: "\u2713",
|
|
462
476
|
failed: "\u2717",
|
|
@@ -471,7 +485,7 @@ var STEP_GLYPH_COLOR = {
|
|
|
471
485
|
};
|
|
472
486
|
function ReportSteps({ scenario }) {
|
|
473
487
|
if (scenario.steps.length === 0) return null;
|
|
474
|
-
return /* @__PURE__ */
|
|
488
|
+
return /* @__PURE__ */ jsx18("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ jsx18(ReportStepItem, { step }, step.id)) });
|
|
475
489
|
}
|
|
476
490
|
function ReportStepItem({ step }) {
|
|
477
491
|
const kw = step.keyword.toLowerCase();
|
|
@@ -484,8 +498,8 @@ function ReportStepItem({ step }) {
|
|
|
484
498
|
className: cn("py-1.5 text-[0.8125rem] leading-normal", continuation && "pl-5"),
|
|
485
499
|
children: [
|
|
486
500
|
/* @__PURE__ */ jsxs10("div", { className: "flex items-baseline gap-2", children: [
|
|
487
|
-
/* @__PURE__ */
|
|
488
|
-
/* @__PURE__ */
|
|
501
|
+
/* @__PURE__ */ jsx18("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" }),
|
|
502
|
+
/* @__PURE__ */ jsx18(
|
|
489
503
|
"span",
|
|
490
504
|
{
|
|
491
505
|
className: cn(
|
|
@@ -495,10 +509,10 @@ function ReportStepItem({ step }) {
|
|
|
495
509
|
children: step.keyword
|
|
496
510
|
}
|
|
497
511
|
),
|
|
498
|
-
/* @__PURE__ */
|
|
499
|
-
step.durationMs > 0 ? /* @__PURE__ */
|
|
512
|
+
/* @__PURE__ */ jsx18("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
|
|
513
|
+
step.durationMs > 0 ? /* @__PURE__ */ jsx18("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(step.durationMs) }) : null
|
|
500
514
|
] }),
|
|
501
|
-
step.errorMessage ? /* @__PURE__ */
|
|
515
|
+
step.errorMessage ? /* @__PURE__ */ jsx18(
|
|
502
516
|
"pre",
|
|
503
517
|
{
|
|
504
518
|
role: "alert",
|
|
@@ -506,12 +520,72 @@ function ReportStepItem({ step }) {
|
|
|
506
520
|
children: step.errorMessage
|
|
507
521
|
}
|
|
508
522
|
) : null,
|
|
509
|
-
step.docEntries.length > 0 ? /* @__PURE__ */
|
|
523
|
+
step.docEntries.length > 0 ? /* @__PURE__ */ jsx18("div", { "data-es-docs": true, className: "mt-2 ml-6", children: /* @__PURE__ */ jsx18(ReportDocEntries, { entries: step.docEntries }) }) : null
|
|
510
524
|
]
|
|
511
525
|
}
|
|
512
526
|
);
|
|
513
527
|
}
|
|
514
528
|
|
|
529
|
+
// ../executable-stories-core/dist/state-diff.js
|
|
530
|
+
var isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
531
|
+
function deepEqual(a, b) {
|
|
532
|
+
if (Object.is(a, b)) return true;
|
|
533
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
534
|
+
return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
535
|
+
}
|
|
536
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
537
|
+
const ak = Object.keys(a);
|
|
538
|
+
const bk = Object.keys(b);
|
|
539
|
+
return ak.length === bk.length && ak.every((k) => k in b && deepEqual(a[k], b[k]));
|
|
540
|
+
}
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
var joinKey = (path, key) => path === "" ? key : `${path}.${key}`;
|
|
544
|
+
function walk(path, before, after, out) {
|
|
545
|
+
if (Object.is(before, after)) return;
|
|
546
|
+
if (Array.isArray(before) && Array.isArray(after)) {
|
|
547
|
+
const shared = Math.min(before.length, after.length);
|
|
548
|
+
for (let i = 0; i < shared; i++) walk(`${path}[${i}]`, before[i], after[i], out);
|
|
549
|
+
for (let i = shared; i < after.length; i++) out.push({ path: `${path}[${i}]`, kind: "added", after: after[i] });
|
|
550
|
+
for (let i = shared; i < before.length; i++) out.push({ path: `${path}[${i}]`, kind: "removed", before: before[i] });
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
if (isPlainObject(before) && isPlainObject(after)) {
|
|
554
|
+
for (const key of Object.keys(after)) {
|
|
555
|
+
const p = joinKey(path, key);
|
|
556
|
+
if (key in before) walk(p, before[key], after[key], out);
|
|
557
|
+
else out.push({ path: p, kind: "added", after: after[key] });
|
|
558
|
+
}
|
|
559
|
+
for (const key of Object.keys(before)) {
|
|
560
|
+
if (!(key in after)) out.push({ path: joinKey(path, key), kind: "removed", before: before[key] });
|
|
561
|
+
}
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
if (!deepEqual(before, after)) out.push({ path, kind: "changed", before, after });
|
|
565
|
+
}
|
|
566
|
+
function diffStateValues(before, after) {
|
|
567
|
+
const out = [];
|
|
568
|
+
walk("", before, after, out);
|
|
569
|
+
return out;
|
|
570
|
+
}
|
|
571
|
+
function formatStateValue(value, maxLen = 60) {
|
|
572
|
+
const s = value === void 0 ? "undefined" : JSON.stringify(value);
|
|
573
|
+
return s.length > maxLen ? `${s.slice(0, maxLen - 1)}\u2026` : s;
|
|
574
|
+
}
|
|
575
|
+
function summarizeStateChanges(changes) {
|
|
576
|
+
return changes.map((c) => {
|
|
577
|
+
const at = c.path === "" ? "(root)" : c.path;
|
|
578
|
+
switch (c.kind) {
|
|
579
|
+
case "added":
|
|
580
|
+
return `+ ${at}: ${formatStateValue(c.after)}`;
|
|
581
|
+
case "removed":
|
|
582
|
+
return `\u2212 ${at}`;
|
|
583
|
+
case "changed":
|
|
584
|
+
return `${at}: ${formatStateValue(c.before)} \u2192 ${formatStateValue(c.after)}`;
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
|
|
515
589
|
// ../executable-stories-core/dist/storyboard.js
|
|
516
590
|
function findScreenshot(entries) {
|
|
517
591
|
for (const entry of entries) {
|
|
@@ -523,26 +597,55 @@ function findScreenshot(entries) {
|
|
|
523
597
|
}
|
|
524
598
|
return void 0;
|
|
525
599
|
}
|
|
600
|
+
function findStates(entries, out = []) {
|
|
601
|
+
for (const entry of entries) {
|
|
602
|
+
if (entry.kind === "state") out.push(entry);
|
|
603
|
+
if (entry.children) findStates(entry.children, out);
|
|
604
|
+
}
|
|
605
|
+
return out;
|
|
606
|
+
}
|
|
607
|
+
var laneOf = (label) => label ?? "";
|
|
526
608
|
function extractStoryboardFrames(scenario) {
|
|
527
609
|
const frames = [];
|
|
610
|
+
const laneOrder = [];
|
|
611
|
+
const previous = /* @__PURE__ */ new Map();
|
|
528
612
|
for (const step of scenario.steps) {
|
|
529
613
|
const shot = findScreenshot(step.docEntries);
|
|
530
|
-
|
|
614
|
+
const stateDocs = findStates(step.docEntries);
|
|
615
|
+
if (!shot && stateDocs.length === 0) continue;
|
|
616
|
+
const byLane = /* @__PURE__ */ new Map();
|
|
617
|
+
for (const doc of stateDocs) {
|
|
618
|
+
const lane = laneOf(doc.label);
|
|
619
|
+
if (!byLane.has(lane) && !laneOrder.includes(lane)) laneOrder.push(lane);
|
|
620
|
+
byLane.set(lane, doc);
|
|
621
|
+
}
|
|
622
|
+
const states = [];
|
|
623
|
+
for (const lane of laneOrder) {
|
|
624
|
+
const doc = byLane.get(lane);
|
|
625
|
+
if (!doc) continue;
|
|
626
|
+
const card = {
|
|
627
|
+
...doc.label !== void 0 && { label: doc.label },
|
|
628
|
+
value: doc.value
|
|
629
|
+
};
|
|
630
|
+
if (previous.has(lane)) card.changes = diffStateValues(previous.get(lane), doc.value);
|
|
631
|
+
previous.set(lane, doc.value);
|
|
632
|
+
states.push(card);
|
|
633
|
+
}
|
|
531
634
|
frames.push({
|
|
532
635
|
stepId: step.id,
|
|
533
636
|
stepIndex: step.index,
|
|
534
637
|
keyword: step.keyword,
|
|
535
638
|
text: step.text,
|
|
536
639
|
status: step.status,
|
|
537
|
-
path: shot.path,
|
|
538
|
-
|
|
640
|
+
...shot && { screenshot: { path: shot.path, ...shot.alt !== void 0 && { alt: shot.alt } } },
|
|
641
|
+
states
|
|
539
642
|
});
|
|
540
643
|
}
|
|
541
644
|
return frames;
|
|
542
645
|
}
|
|
543
646
|
|
|
544
647
|
// src/components/ReportStoryboard.tsx
|
|
545
|
-
import { jsx as
|
|
648
|
+
import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
546
649
|
var FRAME_GLYPH = {
|
|
547
650
|
passed: "\u2713",
|
|
548
651
|
failed: "\u2717",
|
|
@@ -559,54 +662,113 @@ function ReportStoryboard({ scenario }) {
|
|
|
559
662
|
const frames = extractStoryboardFrames(scenario);
|
|
560
663
|
if (frames.length < 2) return null;
|
|
561
664
|
return /* @__PURE__ */ jsxs11("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
|
|
562
|
-
/* @__PURE__ */
|
|
563
|
-
/* @__PURE__ */
|
|
665
|
+
/* @__PURE__ */ jsx19("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
|
|
666
|
+
/* @__PURE__ */ jsx19("ol", { className: "flex items-start gap-3 overflow-x-auto pb-2", children: frames.map((frame) => /* @__PURE__ */ jsx19(StoryboardFrameItem, { frame }, frame.stepId)) })
|
|
564
667
|
] });
|
|
565
668
|
}
|
|
566
669
|
function StoryboardFrameItem({ frame }) {
|
|
567
|
-
const src = isLocalFsPath(frame.path) ? void 0 : safeImageUrl(frame.path);
|
|
568
670
|
const label = `${frame.keyword} ${frame.text}`;
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
671
|
+
const hasStates = frame.states.length > 0;
|
|
672
|
+
const caption = /* @__PURE__ */ jsxs11("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
|
|
673
|
+
/* @__PURE__ */ jsx19("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
|
|
674
|
+
/* @__PURE__ */ jsxs11("span", { className: "min-w-0", children: [
|
|
675
|
+
/* @__PURE__ */ jsx19("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
|
|
676
|
+
" ",
|
|
677
|
+
/* @__PURE__ */ jsx19("span", { className: "text-muted-foreground", children: frame.screenshot?.alt ?? frame.text })
|
|
678
|
+
] })
|
|
679
|
+
] });
|
|
680
|
+
return (
|
|
681
|
+
// State cards need room for diff rows; screenshot-only frames keep the
|
|
682
|
+
// original narrow film-cell width (and DOM) unchanged.
|
|
683
|
+
/* @__PURE__ */ jsxs11("li", { className: cn("shrink-0", hasStates ? "w-64" : "w-40"), children: [
|
|
684
|
+
frame.screenshot ? /* @__PURE__ */ jsx19(FrameScreenshot, { frame, label }) : null,
|
|
685
|
+
hasStates ? /* @__PURE__ */ jsx19("div", { className: cn("flex flex-col gap-1.5", frame.screenshot && "mt-1.5"), children: frame.states.map((card, i) => /* @__PURE__ */ jsx19(StateCardView, { card }, card.label ?? i)) }) : null,
|
|
686
|
+
frame.screenshot ? caption : (
|
|
687
|
+
// No screenshot means no image anchor, so the caption carries the
|
|
688
|
+
// jump-to-step link instead.
|
|
689
|
+
/* @__PURE__ */ jsx19("a", { href: `#${frame.stepId}`, "aria-label": `Jump to step: ${label}`, className: "block hover:underline", children: caption })
|
|
690
|
+
)
|
|
691
|
+
] })
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
function FrameScreenshot({ frame, label }) {
|
|
695
|
+
const path = frame.screenshot?.path ?? "";
|
|
696
|
+
const src = isLocalFsPath(path) ? void 0 : safeImageUrl(path);
|
|
697
|
+
return /* @__PURE__ */ jsx19(
|
|
698
|
+
"a",
|
|
699
|
+
{
|
|
700
|
+
href: `#${frame.stepId}`,
|
|
701
|
+
"aria-label": `Jump to step: ${label}`,
|
|
702
|
+
className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
|
|
703
|
+
children: src ? /* @__PURE__ */ jsx19(
|
|
704
|
+
"img",
|
|
705
|
+
{
|
|
706
|
+
src,
|
|
707
|
+
alt: frame.screenshot?.alt ?? label,
|
|
708
|
+
loading: "lazy",
|
|
709
|
+
className: "h-24 w-full bg-muted object-cover object-top"
|
|
710
|
+
}
|
|
711
|
+
) : /* @__PURE__ */ jsx19("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" })
|
|
712
|
+
}
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
var CHANGE_TONE = {
|
|
716
|
+
added: "bg-pass-bg text-pass",
|
|
717
|
+
removed: "bg-fail-bg text-fail",
|
|
718
|
+
changed: "bg-skip-bg text-skip"
|
|
719
|
+
};
|
|
720
|
+
function prettyJson(value) {
|
|
721
|
+
try {
|
|
722
|
+
return JSON.stringify(value, null, 2) ?? String(value);
|
|
723
|
+
} catch {
|
|
724
|
+
return String(value);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
function StateCardView({ card }) {
|
|
728
|
+
const json = prettyJson(card.value);
|
|
729
|
+
const firstCapture = card.changes === void 0;
|
|
730
|
+
return /* @__PURE__ */ jsxs11("div", { "data-slot": "state-card", className: "rounded-md border border-border bg-card p-2", children: [
|
|
731
|
+
/* @__PURE__ */ jsxs11("p", { className: "flex flex-wrap items-baseline gap-1.5", children: [
|
|
732
|
+
/* @__PURE__ */ jsx19("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" }),
|
|
733
|
+
firstCapture ? /* @__PURE__ */ jsx19("span", { className: "text-[0.625rem] text-muted-foreground italic", children: "first capture" }) : null
|
|
734
|
+
] }),
|
|
735
|
+
!firstCapture && (card.changes && card.changes.length > 0 ? /* @__PURE__ */ jsx19("ul", { className: "mt-1.5 flex flex-col gap-0.5", children: card.changes.map((change, i) => /* @__PURE__ */ jsx19(
|
|
736
|
+
"li",
|
|
572
737
|
{
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
738
|
+
className: cn(
|
|
739
|
+
"rounded-sm px-1.5 py-0.5 font-mono text-[0.625rem] leading-snug break-all",
|
|
740
|
+
CHANGE_TONE[change.kind]
|
|
741
|
+
),
|
|
742
|
+
children: summarizeStateChanges([change])[0]
|
|
743
|
+
},
|
|
744
|
+
i
|
|
745
|
+
)) }) : /* @__PURE__ */ jsx19("p", { className: "mt-1.5 text-[0.625rem] text-muted-foreground", children: "No changes" })),
|
|
746
|
+
/* @__PURE__ */ jsxs11(
|
|
747
|
+
"details",
|
|
748
|
+
{
|
|
749
|
+
open: firstCapture && json.length <= 240,
|
|
750
|
+
className: cn(firstCapture ? "mt-1.5" : "mt-1"),
|
|
751
|
+
children: [
|
|
752
|
+
/* @__PURE__ */ jsx19("summary", { className: "cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground", children: "Snapshot" }),
|
|
753
|
+
/* @__PURE__ */ jsx19("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 })
|
|
754
|
+
]
|
|
585
755
|
}
|
|
586
|
-
)
|
|
587
|
-
/* @__PURE__ */ jsxs11("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
|
|
588
|
-
/* @__PURE__ */ jsx18("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
|
|
589
|
-
/* @__PURE__ */ jsxs11("span", { className: "min-w-0", children: [
|
|
590
|
-
/* @__PURE__ */ jsx18("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
|
|
591
|
-
" ",
|
|
592
|
-
/* @__PURE__ */ jsx18("span", { className: "text-muted-foreground", children: frame.alt ?? frame.text })
|
|
593
|
-
] })
|
|
594
|
-
] })
|
|
756
|
+
)
|
|
595
757
|
] });
|
|
596
758
|
}
|
|
597
759
|
|
|
598
760
|
// src/components/ReportAttachments.tsx
|
|
599
|
-
import { Fragment as Fragment6, jsx as
|
|
761
|
+
import { Fragment as Fragment6, jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
600
762
|
function ReportAttachments({ attachments }) {
|
|
601
763
|
if (attachments.length === 0) return null;
|
|
602
764
|
return (
|
|
603
765
|
// role="group" (not a labelled <section>) so multiple scenarios' attachment
|
|
604
766
|
// blocks don't create duplicate "Attachments" region landmarks.
|
|
605
|
-
/* @__PURE__ */
|
|
767
|
+
/* @__PURE__ */ jsx20("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
|
|
606
768
|
const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
|
|
607
769
|
const isImage = att.mediaType.startsWith("image/");
|
|
608
|
-
return /* @__PURE__ */
|
|
609
|
-
/* @__PURE__ */
|
|
770
|
+
return /* @__PURE__ */ jsx20("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ jsxs12(Fragment6, { children: [
|
|
771
|
+
/* @__PURE__ */ jsx20(
|
|
610
772
|
"img",
|
|
611
773
|
{
|
|
612
774
|
src: dataUri,
|
|
@@ -615,7 +777,7 @@ function ReportAttachments({ attachments }) {
|
|
|
615
777
|
className: "max-w-full rounded-md border border-border"
|
|
616
778
|
}
|
|
617
779
|
),
|
|
618
|
-
/* @__PURE__ */
|
|
780
|
+
/* @__PURE__ */ jsx20("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
|
|
619
781
|
] }) : /* @__PURE__ */ jsxs12(
|
|
620
782
|
"a",
|
|
621
783
|
{
|
|
@@ -689,15 +851,15 @@ function toTraceRows(spans) {
|
|
|
689
851
|
roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
690
852
|
const rows = [];
|
|
691
853
|
const seen = /* @__PURE__ */ new Set();
|
|
692
|
-
const
|
|
854
|
+
const walk2 = (node, depth) => {
|
|
693
855
|
if (seen.has(node.span.spanId)) return;
|
|
694
856
|
seen.add(node.span.spanId);
|
|
695
857
|
rows.push({ ...node.span, depth });
|
|
696
|
-
for (const child of node.children)
|
|
858
|
+
for (const child of node.children) walk2(child, depth + 1);
|
|
697
859
|
};
|
|
698
|
-
for (const root of roots)
|
|
860
|
+
for (const root of roots) walk2(root, 0);
|
|
699
861
|
for (const node of byId.values()) {
|
|
700
|
-
if (!seen.has(node.span.spanId))
|
|
862
|
+
if (!seen.has(node.span.spanId)) walk2(node, 0);
|
|
701
863
|
}
|
|
702
864
|
return rows;
|
|
703
865
|
}
|
|
@@ -713,7 +875,7 @@ function traceWindow(rows) {
|
|
|
713
875
|
}
|
|
714
876
|
|
|
715
877
|
// src/components/ReportTrace.tsx
|
|
716
|
-
import { jsx as
|
|
878
|
+
import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
717
879
|
var BAR_COLOR = {
|
|
718
880
|
ok: "bg-pass",
|
|
719
881
|
error: "bg-fail",
|
|
@@ -734,11 +896,11 @@ function ReportTrace({ spans }) {
|
|
|
734
896
|
formatDuration(totalMs),
|
|
735
897
|
")"
|
|
736
898
|
] }),
|
|
737
|
-
/* @__PURE__ */
|
|
899
|
+
/* @__PURE__ */ jsx21("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
|
|
738
900
|
const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
|
|
739
901
|
const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
|
|
740
902
|
return /* @__PURE__ */ jsxs13("li", { className: "flex items-center gap-2", children: [
|
|
741
|
-
/* @__PURE__ */
|
|
903
|
+
/* @__PURE__ */ jsx21(
|
|
742
904
|
"span",
|
|
743
905
|
{
|
|
744
906
|
className: "min-w-0 flex-1 truncate text-foreground",
|
|
@@ -747,14 +909,14 @@ function ReportTrace({ spans }) {
|
|
|
747
909
|
children: row.name
|
|
748
910
|
}
|
|
749
911
|
),
|
|
750
|
-
/* @__PURE__ */
|
|
912
|
+
/* @__PURE__ */ jsx21("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ jsx21(
|
|
751
913
|
"span",
|
|
752
914
|
{
|
|
753
915
|
className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
|
|
754
916
|
style: { left: `${leftPct}%`, width: `${widthPct}%` }
|
|
755
917
|
}
|
|
756
918
|
) }),
|
|
757
|
-
/* @__PURE__ */
|
|
919
|
+
/* @__PURE__ */ jsx21("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
|
|
758
920
|
] }, `${row.spanId}-${i}`);
|
|
759
921
|
}) })
|
|
760
922
|
] });
|
|
@@ -805,7 +967,7 @@ function flakinessOf(entries) {
|
|
|
805
967
|
}
|
|
806
968
|
|
|
807
969
|
// src/components/ScenarioRunHistory.tsx
|
|
808
|
-
import { Fragment as Fragment7, jsx as
|
|
970
|
+
import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
809
971
|
var MAX_DOTS = 10;
|
|
810
972
|
var DOT_COLOR = {
|
|
811
973
|
passed: "bg-pass",
|
|
@@ -826,15 +988,15 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
826
988
|
const flaky = flakinessOf(recent) === "flaky";
|
|
827
989
|
const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
|
|
828
990
|
return /* @__PURE__ */ jsxs14(Fragment7, { children: [
|
|
829
|
-
flaky ? /* @__PURE__ */
|
|
830
|
-
/* @__PURE__ */
|
|
991
|
+
flaky ? /* @__PURE__ */ jsx22(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
|
|
992
|
+
/* @__PURE__ */ jsx22(
|
|
831
993
|
"span",
|
|
832
994
|
{
|
|
833
995
|
role: "img",
|
|
834
996
|
"aria-label": `Run history: ${summary}`,
|
|
835
997
|
title: summary,
|
|
836
998
|
className: "flex shrink-0 items-center gap-[3px]",
|
|
837
|
-
children: recent.map((e, i) => /* @__PURE__ */
|
|
999
|
+
children: recent.map((e, i) => /* @__PURE__ */ jsx22(
|
|
838
1000
|
"span",
|
|
839
1001
|
{
|
|
840
1002
|
"aria-hidden": true,
|
|
@@ -873,9 +1035,9 @@ function useScenarioActions() {
|
|
|
873
1035
|
|
|
874
1036
|
// src/components/ui/card.tsx
|
|
875
1037
|
import "react";
|
|
876
|
-
import { jsx as
|
|
1038
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
877
1039
|
function Card({ className, ...props }) {
|
|
878
|
-
return /* @__PURE__ */
|
|
1040
|
+
return /* @__PURE__ */ jsx23(
|
|
879
1041
|
"div",
|
|
880
1042
|
{
|
|
881
1043
|
"data-slot": "card",
|
|
@@ -888,7 +1050,7 @@ function Card({ className, ...props }) {
|
|
|
888
1050
|
);
|
|
889
1051
|
}
|
|
890
1052
|
function CardHeader({ className, ...props }) {
|
|
891
|
-
return /* @__PURE__ */
|
|
1053
|
+
return /* @__PURE__ */ jsx23(
|
|
892
1054
|
"div",
|
|
893
1055
|
{
|
|
894
1056
|
"data-slot": "card-header",
|
|
@@ -901,7 +1063,7 @@ function CardHeader({ className, ...props }) {
|
|
|
901
1063
|
);
|
|
902
1064
|
}
|
|
903
1065
|
function CardContent({ className, ...props }) {
|
|
904
|
-
return /* @__PURE__ */
|
|
1066
|
+
return /* @__PURE__ */ jsx23(
|
|
905
1067
|
"div",
|
|
906
1068
|
{
|
|
907
1069
|
"data-slot": "card-content",
|
|
@@ -915,13 +1077,13 @@ function CardContent({ className, ...props }) {
|
|
|
915
1077
|
import "react";
|
|
916
1078
|
import { Menu as MenuPrimitive } from "@base-ui/react/menu";
|
|
917
1079
|
import { CheckIcon } from "lucide-react";
|
|
918
|
-
import { jsx as
|
|
1080
|
+
import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
919
1081
|
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";
|
|
920
1082
|
function DropdownMenu(props) {
|
|
921
|
-
return /* @__PURE__ */
|
|
1083
|
+
return /* @__PURE__ */ jsx24(MenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
922
1084
|
}
|
|
923
1085
|
function DropdownMenuTrigger(props) {
|
|
924
|
-
return /* @__PURE__ */
|
|
1086
|
+
return /* @__PURE__ */ jsx24(MenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
925
1087
|
}
|
|
926
1088
|
function DropdownMenuContent({
|
|
927
1089
|
className,
|
|
@@ -929,14 +1091,14 @@ function DropdownMenuContent({
|
|
|
929
1091
|
sideOffset = 4,
|
|
930
1092
|
...props
|
|
931
1093
|
}) {
|
|
932
|
-
return /* @__PURE__ */
|
|
1094
|
+
return /* @__PURE__ */ jsx24(MenuPrimitive.Portal, { children: /* @__PURE__ */ jsx24(
|
|
933
1095
|
MenuPrimitive.Positioner,
|
|
934
1096
|
{
|
|
935
1097
|
"data-slot": "dropdown-menu-positioner",
|
|
936
1098
|
className: "z-50",
|
|
937
1099
|
align,
|
|
938
1100
|
sideOffset,
|
|
939
|
-
children: /* @__PURE__ */
|
|
1101
|
+
children: /* @__PURE__ */ jsx24(
|
|
940
1102
|
MenuPrimitive.Popup,
|
|
941
1103
|
{
|
|
942
1104
|
"data-slot": "dropdown-menu-content",
|
|
@@ -954,7 +1116,7 @@ function DropdownMenuItem({
|
|
|
954
1116
|
className,
|
|
955
1117
|
...props
|
|
956
1118
|
}) {
|
|
957
|
-
return /* @__PURE__ */
|
|
1119
|
+
return /* @__PURE__ */ jsx24(
|
|
958
1120
|
MenuPrimitive.Item,
|
|
959
1121
|
{
|
|
960
1122
|
"data-slot": "dropdown-menu-item",
|
|
@@ -966,7 +1128,7 @@ function DropdownMenuItem({
|
|
|
966
1128
|
|
|
967
1129
|
// src/components/ReportScenario.tsx
|
|
968
1130
|
import { LinkIcon, FileTextIcon, SparklesIcon, MoreHorizontalIcon } from "lucide-react";
|
|
969
|
-
import { jsx as
|
|
1131
|
+
import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
970
1132
|
var STATUS_META = {
|
|
971
1133
|
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
972
1134
|
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
@@ -993,7 +1155,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
993
1155
|
/* @__PURE__ */ jsxs16(CardHeader, { className: "px-4 py-3", children: [
|
|
994
1156
|
/* @__PURE__ */ jsxs16("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
995
1157
|
hideTitle ? null : /* @__PURE__ */ jsxs16("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
996
|
-
collapsible ? /* @__PURE__ */
|
|
1158
|
+
collapsible ? /* @__PURE__ */ jsx25(
|
|
997
1159
|
"button",
|
|
998
1160
|
{
|
|
999
1161
|
type: "button",
|
|
@@ -1002,36 +1164,36 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1002
1164
|
"aria-controls": bodyId,
|
|
1003
1165
|
"aria-label": `Toggle ${scenario.title}`,
|
|
1004
1166
|
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
1005
|
-
children: /* @__PURE__ */
|
|
1167
|
+
children: /* @__PURE__ */ jsx25("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
1006
1168
|
}
|
|
1007
1169
|
) : null,
|
|
1008
|
-
/* @__PURE__ */
|
|
1009
|
-
/* @__PURE__ */
|
|
1170
|
+
/* @__PURE__ */ jsx25("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
1171
|
+
/* @__PURE__ */ jsx25("span", { children: scenario.title })
|
|
1010
1172
|
] }),
|
|
1011
1173
|
/* @__PURE__ */ jsxs16("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1012
|
-
/* @__PURE__ */
|
|
1013
|
-
scenario.durationMs > 0 ? /* @__PURE__ */
|
|
1014
|
-
meta.showPill ? /* @__PURE__ */
|
|
1174
|
+
/* @__PURE__ */ jsx25(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1175
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ jsx25("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
|
|
1176
|
+
meta.showPill ? /* @__PURE__ */ jsx25(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ jsx25("span", { className: "sr-only", children: `Status: ${label}` }),
|
|
1015
1177
|
actions ? /* @__PURE__ */ jsxs16(DropdownMenu, { children: [
|
|
1016
|
-
/* @__PURE__ */
|
|
1178
|
+
/* @__PURE__ */ jsx25(
|
|
1017
1179
|
DropdownMenuTrigger,
|
|
1018
1180
|
{
|
|
1019
1181
|
"aria-label": `Actions for ${scenario.title}`,
|
|
1020
1182
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
1021
|
-
children: /* @__PURE__ */
|
|
1183
|
+
children: /* @__PURE__ */ jsx25(MoreHorizontalIcon, { "aria-hidden": true })
|
|
1022
1184
|
}
|
|
1023
1185
|
),
|
|
1024
1186
|
/* @__PURE__ */ jsxs16(DropdownMenuContent, { align: "end", children: [
|
|
1025
1187
|
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
1026
|
-
/* @__PURE__ */
|
|
1188
|
+
/* @__PURE__ */ jsx25(LinkIcon, {}),
|
|
1027
1189
|
" Copy link"
|
|
1028
1190
|
] }),
|
|
1029
1191
|
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
1030
|
-
/* @__PURE__ */
|
|
1192
|
+
/* @__PURE__ */ jsx25(FileTextIcon, {}),
|
|
1031
1193
|
" Copy as Markdown"
|
|
1032
1194
|
] }),
|
|
1033
1195
|
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
1034
|
-
/* @__PURE__ */
|
|
1196
|
+
/* @__PURE__ */ jsx25(SparklesIcon, {}),
|
|
1035
1197
|
" Explain with AI"
|
|
1036
1198
|
] })
|
|
1037
1199
|
] })
|
|
@@ -1039,12 +1201,12 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1039
1201
|
] })
|
|
1040
1202
|
] }),
|
|
1041
1203
|
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs16("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
|
|
1042
|
-
scenario.tags.map((t) => /* @__PURE__ */
|
|
1043
|
-
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */
|
|
1204
|
+
scenario.tags.map((t) => /* @__PURE__ */ jsx25("li", { children: /* @__PURE__ */ jsx25(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
|
|
1205
|
+
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ jsx25("li", { children: ticket.url ? /* @__PURE__ */ jsx25("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ jsx25(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ jsx25(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
|
|
1044
1206
|
] }) : null
|
|
1045
1207
|
] }),
|
|
1046
1208
|
/* @__PURE__ */ jsxs16(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
1047
|
-
scenario.errorMessage ? /* @__PURE__ */
|
|
1209
|
+
scenario.errorMessage ? /* @__PURE__ */ jsx25(
|
|
1048
1210
|
"pre",
|
|
1049
1211
|
{
|
|
1050
1212
|
role: "alert",
|
|
@@ -1052,11 +1214,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1052
1214
|
children: scenario.errorMessage
|
|
1053
1215
|
}
|
|
1054
1216
|
) : null,
|
|
1055
|
-
/* @__PURE__ */
|
|
1056
|
-
/* @__PURE__ */
|
|
1057
|
-
scenario.docEntries.length > 0 ? /* @__PURE__ */
|
|
1058
|
-
/* @__PURE__ */
|
|
1059
|
-
/* @__PURE__ */
|
|
1217
|
+
/* @__PURE__ */ jsx25(ReportStoryboard, { scenario }),
|
|
1218
|
+
/* @__PURE__ */ jsx25(ReportSteps, { scenario }),
|
|
1219
|
+
scenario.docEntries.length > 0 ? /* @__PURE__ */ jsx25("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ jsx25(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
|
|
1220
|
+
/* @__PURE__ */ jsx25(ReportAttachments, { attachments: scenario.attachments }),
|
|
1221
|
+
/* @__PURE__ */ jsx25(ReportTrace, { spans: scenario.otelSpans })
|
|
1060
1222
|
] })
|
|
1061
1223
|
]
|
|
1062
1224
|
}
|
|
@@ -1064,13 +1226,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1064
1226
|
}
|
|
1065
1227
|
|
|
1066
1228
|
// src/components/ReportScenarioList.tsx
|
|
1067
|
-
import { Fragment as Fragment8, jsx as
|
|
1229
|
+
import { Fragment as Fragment8, jsx as jsx26 } from "react/jsx-runtime";
|
|
1068
1230
|
function ReportScenarioList({ feature }) {
|
|
1069
|
-
return /* @__PURE__ */
|
|
1231
|
+
return /* @__PURE__ */ jsx26(Fragment8, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ jsx26(ReportScenario, { scenario }, scenario.id)) });
|
|
1070
1232
|
}
|
|
1071
1233
|
|
|
1072
1234
|
// src/components/ReportFeature.tsx
|
|
1073
|
-
import { Fragment as Fragment9, jsx as
|
|
1235
|
+
import { Fragment as Fragment9, jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1074
1236
|
function ReportFeature({ feature }) {
|
|
1075
1237
|
const titleId = `${feature.id}-title`;
|
|
1076
1238
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1091,7 +1253,7 @@ function ReportFeature({ feature }) {
|
|
|
1091
1253
|
children: [
|
|
1092
1254
|
/* @__PURE__ */ jsxs17("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1093
1255
|
/* @__PURE__ */ jsxs17("div", { className: "min-w-0", children: [
|
|
1094
|
-
/* @__PURE__ */
|
|
1256
|
+
/* @__PURE__ */ jsx27("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ jsxs17(
|
|
1095
1257
|
"button",
|
|
1096
1258
|
{
|
|
1097
1259
|
type: "button",
|
|
@@ -1100,12 +1262,12 @@ function ReportFeature({ feature }) {
|
|
|
1100
1262
|
"aria-controls": bodyId,
|
|
1101
1263
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1102
1264
|
children: [
|
|
1103
|
-
/* @__PURE__ */
|
|
1104
|
-
/* @__PURE__ */
|
|
1265
|
+
/* @__PURE__ */ jsx27("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
|
|
1266
|
+
/* @__PURE__ */ jsx27("span", { className: "truncate", children: feature.title })
|
|
1105
1267
|
]
|
|
1106
1268
|
}
|
|
1107
1269
|
) : feature.title }),
|
|
1108
|
-
/* @__PURE__ */
|
|
1270
|
+
/* @__PURE__ */ jsx27("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
|
|
1109
1271
|
] }),
|
|
1110
1272
|
/* @__PURE__ */ jsxs17(
|
|
1111
1273
|
"p",
|
|
@@ -1117,13 +1279,13 @@ function ReportFeature({ feature }) {
|
|
|
1117
1279
|
s.passed,
|
|
1118
1280
|
" passed"
|
|
1119
1281
|
] }),
|
|
1120
|
-
/* @__PURE__ */
|
|
1282
|
+
/* @__PURE__ */ jsx27("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1121
1283
|
/* @__PURE__ */ jsxs17("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1122
1284
|
s.failed,
|
|
1123
1285
|
" failed"
|
|
1124
1286
|
] }),
|
|
1125
1287
|
skipped > 0 ? /* @__PURE__ */ jsxs17(Fragment9, { children: [
|
|
1126
|
-
/* @__PURE__ */
|
|
1288
|
+
/* @__PURE__ */ jsx27("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1127
1289
|
/* @__PURE__ */ jsxs17("span", { children: [
|
|
1128
1290
|
skipped,
|
|
1129
1291
|
" skipped"
|
|
@@ -1133,7 +1295,7 @@ function ReportFeature({ feature }) {
|
|
|
1133
1295
|
}
|
|
1134
1296
|
)
|
|
1135
1297
|
] }),
|
|
1136
|
-
/* @__PURE__ */
|
|
1298
|
+
/* @__PURE__ */ jsx27("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx27(ReportScenarioList, { feature }) })
|
|
1137
1299
|
]
|
|
1138
1300
|
}
|
|
1139
1301
|
)
|
|
@@ -1141,17 +1303,17 @@ function ReportFeature({ feature }) {
|
|
|
1141
1303
|
}
|
|
1142
1304
|
|
|
1143
1305
|
// src/components/ReportFeatureList.tsx
|
|
1144
|
-
import { jsx as
|
|
1306
|
+
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
1145
1307
|
function ReportFeatureList() {
|
|
1146
1308
|
const report = useReport();
|
|
1147
|
-
return /* @__PURE__ */
|
|
1309
|
+
return /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ jsx28(ReportFeature, { feature }, feature.id)) });
|
|
1148
1310
|
}
|
|
1149
1311
|
|
|
1150
1312
|
// src/components/ui/empty.tsx
|
|
1151
1313
|
import { cva as cva2 } from "class-variance-authority";
|
|
1152
|
-
import { jsx as
|
|
1314
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
1153
1315
|
function Empty({ className, ...props }) {
|
|
1154
|
-
return /* @__PURE__ */
|
|
1316
|
+
return /* @__PURE__ */ jsx29(
|
|
1155
1317
|
"div",
|
|
1156
1318
|
{
|
|
1157
1319
|
"data-slot": "empty",
|
|
@@ -1164,7 +1326,7 @@ function Empty({ className, ...props }) {
|
|
|
1164
1326
|
);
|
|
1165
1327
|
}
|
|
1166
1328
|
function EmptyHeader({ className, ...props }) {
|
|
1167
|
-
return /* @__PURE__ */
|
|
1329
|
+
return /* @__PURE__ */ jsx29(
|
|
1168
1330
|
"div",
|
|
1169
1331
|
{
|
|
1170
1332
|
"data-slot": "empty-header",
|
|
@@ -1191,7 +1353,7 @@ var emptyMediaVariants = cva2(
|
|
|
1191
1353
|
}
|
|
1192
1354
|
);
|
|
1193
1355
|
function EmptyTitle({ className, ...props }) {
|
|
1194
|
-
return /* @__PURE__ */
|
|
1356
|
+
return /* @__PURE__ */ jsx29(
|
|
1195
1357
|
"div",
|
|
1196
1358
|
{
|
|
1197
1359
|
"data-slot": "empty-title",
|
|
@@ -1202,16 +1364,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1202
1364
|
}
|
|
1203
1365
|
|
|
1204
1366
|
// src/components/ReportEmpty.tsx
|
|
1205
|
-
import { jsx as
|
|
1367
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
1206
1368
|
function ReportEmpty({ message }) {
|
|
1207
|
-
return /* @__PURE__ */
|
|
1369
|
+
return /* @__PURE__ */ jsx30(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ jsx30(EmptyHeader, { children: /* @__PURE__ */ jsx30(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
|
|
1208
1370
|
}
|
|
1209
1371
|
|
|
1210
1372
|
// src/components/ReportSummary.tsx
|
|
1211
|
-
import { jsx as
|
|
1373
|
+
import { jsx as jsx31, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1212
1374
|
function ReportSummary({ className }) {
|
|
1213
1375
|
const report = useReport();
|
|
1214
|
-
return /* @__PURE__ */
|
|
1376
|
+
return /* @__PURE__ */ jsx31(
|
|
1215
1377
|
ReportSummaryView,
|
|
1216
1378
|
{
|
|
1217
1379
|
summary: report.summary,
|
|
@@ -1237,7 +1399,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1237
1399
|
if (summary.pending > 0) {
|
|
1238
1400
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1239
1401
|
}
|
|
1240
|
-
return /* @__PURE__ */
|
|
1402
|
+
return /* @__PURE__ */ jsx31(
|
|
1241
1403
|
"dl",
|
|
1242
1404
|
{
|
|
1243
1405
|
className: cn(
|
|
@@ -1257,10 +1419,10 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1257
1419
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1258
1420
|
children: [
|
|
1259
1421
|
/* @__PURE__ */ jsxs18("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
|
|
1260
|
-
/* @__PURE__ */
|
|
1422
|
+
/* @__PURE__ */ jsx31("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1261
1423
|
c.label
|
|
1262
1424
|
] }),
|
|
1263
|
-
/* @__PURE__ */
|
|
1425
|
+
/* @__PURE__ */ jsx31("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
|
|
1264
1426
|
]
|
|
1265
1427
|
},
|
|
1266
1428
|
c.status
|
|
@@ -1301,7 +1463,7 @@ function prUrl(ci) {
|
|
|
1301
1463
|
}
|
|
1302
1464
|
|
|
1303
1465
|
// src/components/ReportMeta.tsx
|
|
1304
|
-
import { jsx as
|
|
1466
|
+
import { jsx as jsx32, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1305
1467
|
function ReportMeta() {
|
|
1306
1468
|
const report = useReport();
|
|
1307
1469
|
const items = [];
|
|
@@ -1324,7 +1486,7 @@ function ReportMeta() {
|
|
|
1324
1486
|
const short = sha.slice(0, 8);
|
|
1325
1487
|
items.push({
|
|
1326
1488
|
label: "Commit",
|
|
1327
|
-
value: url ? /* @__PURE__ */
|
|
1489
|
+
value: url ? /* @__PURE__ */ jsx32("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1328
1490
|
});
|
|
1329
1491
|
}
|
|
1330
1492
|
if (report.ci) {
|
|
@@ -1341,7 +1503,7 @@ function ReportMeta() {
|
|
|
1341
1503
|
const label = `#${report.ci.prNumber}`;
|
|
1342
1504
|
items.push({
|
|
1343
1505
|
label: "PR",
|
|
1344
|
-
value: url ? /* @__PURE__ */
|
|
1506
|
+
value: url ? /* @__PURE__ */ jsx32("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1345
1507
|
});
|
|
1346
1508
|
}
|
|
1347
1509
|
if (items.length === 0) return null;
|
|
@@ -1351,26 +1513,26 @@ function ReportMeta() {
|
|
|
1351
1513
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1352
1514
|
/* @__PURE__ */ jsxs19("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
|
|
1353
1515
|
/* @__PURE__ */ jsxs19("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: [
|
|
1354
|
-
/* @__PURE__ */
|
|
1516
|
+
/* @__PURE__ */ jsx32("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1355
1517
|
"Run details"
|
|
1356
1518
|
] }),
|
|
1357
|
-
/* @__PURE__ */
|
|
1358
|
-
/* @__PURE__ */
|
|
1359
|
-
/* @__PURE__ */
|
|
1519
|
+
/* @__PURE__ */ jsx32("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__ */ jsxs19("div", { className: "flex items-baseline gap-1.5", children: [
|
|
1520
|
+
/* @__PURE__ */ jsx32("dt", { className: "font-medium", children: item.label }),
|
|
1521
|
+
/* @__PURE__ */ jsx32("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1360
1522
|
] }, item.label)) })
|
|
1361
1523
|
] })
|
|
1362
1524
|
);
|
|
1363
1525
|
}
|
|
1364
1526
|
|
|
1365
1527
|
// src/components/ReportSchemaError.tsx
|
|
1366
|
-
import { jsx as
|
|
1528
|
+
import { jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1367
1529
|
function ReportSchemaError({ error }) {
|
|
1368
1530
|
return /* @__PURE__ */ jsxs20("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1369
|
-
/* @__PURE__ */
|
|
1370
|
-
/* @__PURE__ */
|
|
1531
|
+
/* @__PURE__ */ jsx33("p", { children: /* @__PURE__ */ jsx33("strong", { children: "Report could not be displayed." }) }),
|
|
1532
|
+
/* @__PURE__ */ jsx33("p", { children: error.message }),
|
|
1371
1533
|
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ jsxs20("p", { children: [
|
|
1372
1534
|
"The report bundle is newer than this version of ",
|
|
1373
|
-
/* @__PURE__ */
|
|
1535
|
+
/* @__PURE__ */ jsx33("code", { children: "executable-stories-react" }),
|
|
1374
1536
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1375
1537
|
] }) : null,
|
|
1376
1538
|
error.issues && error.issues.length > 0 ? /* @__PURE__ */ jsxs20("details", { children: [
|
|
@@ -1379,18 +1541,18 @@ function ReportSchemaError({ error }) {
|
|
|
1379
1541
|
" validation issue",
|
|
1380
1542
|
error.issues.length === 1 ? "" : "s"
|
|
1381
1543
|
] }),
|
|
1382
|
-
/* @__PURE__ */
|
|
1544
|
+
/* @__PURE__ */ jsx33("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1383
1545
|
] }) : null
|
|
1384
1546
|
] });
|
|
1385
1547
|
}
|
|
1386
1548
|
|
|
1387
1549
|
// src/components/ReportShell.tsx
|
|
1388
|
-
import { Fragment as Fragment10, jsx as
|
|
1550
|
+
import { Fragment as Fragment10, jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1389
1551
|
function ReportTitleBlock({ title }) {
|
|
1390
1552
|
return /* @__PURE__ */ jsxs21(Fragment10, { children: [
|
|
1391
|
-
/* @__PURE__ */
|
|
1392
|
-
/* @__PURE__ */
|
|
1393
|
-
/* @__PURE__ */
|
|
1553
|
+
/* @__PURE__ */ jsx34("h1", { children: title ?? "Story Report" }),
|
|
1554
|
+
/* @__PURE__ */ jsx34(ReportSummary, {}),
|
|
1555
|
+
/* @__PURE__ */ jsx34(ReportMeta, {})
|
|
1394
1556
|
] });
|
|
1395
1557
|
}
|
|
1396
1558
|
function ReportErrorShell({
|
|
@@ -1399,22 +1561,22 @@ function ReportErrorShell({
|
|
|
1399
1561
|
title,
|
|
1400
1562
|
dataTheme
|
|
1401
1563
|
}) {
|
|
1402
|
-
return /* @__PURE__ */
|
|
1564
|
+
return /* @__PURE__ */ jsx34("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx34(ReportSchemaError, { error }) });
|
|
1403
1565
|
}
|
|
1404
1566
|
|
|
1405
1567
|
// src/components/Report.tsx
|
|
1406
|
-
import { jsx as
|
|
1568
|
+
import { jsx as jsx35, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1407
1569
|
function Report(props) {
|
|
1408
1570
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1409
1571
|
const result = unwrapReport(report);
|
|
1410
1572
|
if (!result.ok) {
|
|
1411
|
-
return /* @__PURE__ */
|
|
1573
|
+
return /* @__PURE__ */ jsx35(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1412
1574
|
}
|
|
1413
1575
|
const data = result.data;
|
|
1414
1576
|
const hasContent = data.features.length > 0;
|
|
1415
|
-
return /* @__PURE__ */
|
|
1416
|
-
/* @__PURE__ */
|
|
1417
|
-
hasContent ? /* @__PURE__ */
|
|
1577
|
+
return /* @__PURE__ */ jsx35(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ jsxs22("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1578
|
+
/* @__PURE__ */ jsx35("header", { className: "es-report-header", children: /* @__PURE__ */ jsx35(ReportTitleBlock, { title }) }),
|
|
1579
|
+
hasContent ? /* @__PURE__ */ jsx35(ReportFeatureList, {}) : /* @__PURE__ */ jsx35(ReportEmpty, {})
|
|
1418
1580
|
] }) });
|
|
1419
1581
|
}
|
|
1420
1582
|
|