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/index.js
CHANGED
|
@@ -216,7 +216,7 @@ function DocLink({ entry }) {
|
|
|
216
216
|
// src/components/doc/DocSection.tsx
|
|
217
217
|
import { marked } from "marked";
|
|
218
218
|
|
|
219
|
-
//
|
|
219
|
+
// ../executable-stories-core/dist/utils/url.js
|
|
220
220
|
function safeUrl(value) {
|
|
221
221
|
if (!value) return void 0;
|
|
222
222
|
const trimmed = value.trim();
|
|
@@ -374,17 +374,29 @@ function DocHtml({ entry }) {
|
|
|
374
374
|
] });
|
|
375
375
|
}
|
|
376
376
|
|
|
377
|
+
// src/components/doc/DocState.tsx
|
|
378
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
379
|
+
function DocState({ entry }) {
|
|
380
|
+
let json;
|
|
381
|
+
try {
|
|
382
|
+
json = JSON.stringify(entry.value, null, 2) ?? String(entry.value);
|
|
383
|
+
} catch {
|
|
384
|
+
json = String(entry.value);
|
|
385
|
+
}
|
|
386
|
+
return /* @__PURE__ */ jsx13(CodeFigure, { label: entry.label ?? "State", children: /* @__PURE__ */ jsx13("code", { className: "font-mono text-xs language-json", children: json }) });
|
|
387
|
+
}
|
|
388
|
+
|
|
377
389
|
// src/components/doc/DocCustom.tsx
|
|
378
|
-
import { Fragment as Fragment4, jsx as
|
|
390
|
+
import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
379
391
|
function DocCustom({ entry }) {
|
|
380
392
|
const renderers = useCustomRenderers();
|
|
381
393
|
const renderer = renderers[entry.type];
|
|
382
394
|
if (renderer) {
|
|
383
|
-
return /* @__PURE__ */
|
|
395
|
+
return /* @__PURE__ */ jsx14(Fragment4, { children: renderer(entry) });
|
|
384
396
|
}
|
|
385
397
|
return /* @__PURE__ */ jsxs9("div", { className: "my-2", "data-type": entry.type, children: [
|
|
386
|
-
/* @__PURE__ */
|
|
387
|
-
/* @__PURE__ */
|
|
398
|
+
/* @__PURE__ */ jsx14("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
|
|
399
|
+
/* @__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) })
|
|
388
400
|
] });
|
|
389
401
|
}
|
|
390
402
|
function safeStringify(value) {
|
|
@@ -396,45 +408,47 @@ function safeStringify(value) {
|
|
|
396
408
|
}
|
|
397
409
|
|
|
398
410
|
// src/components/doc/DocEntry.tsx
|
|
399
|
-
import { jsx as
|
|
411
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
400
412
|
function DocEntry({ entry }) {
|
|
401
413
|
switch (entry.kind) {
|
|
402
414
|
case "note":
|
|
403
|
-
return /* @__PURE__ */
|
|
415
|
+
return /* @__PURE__ */ jsx15(DocNote, { entry });
|
|
404
416
|
case "tag":
|
|
405
|
-
return /* @__PURE__ */
|
|
417
|
+
return /* @__PURE__ */ jsx15(DocTag, { entry });
|
|
406
418
|
case "kv":
|
|
407
|
-
return /* @__PURE__ */
|
|
419
|
+
return /* @__PURE__ */ jsx15(DocKv, { entry });
|
|
408
420
|
case "code":
|
|
409
|
-
return /* @__PURE__ */
|
|
421
|
+
return /* @__PURE__ */ jsx15(DocCode, { entry });
|
|
410
422
|
case "table":
|
|
411
|
-
return /* @__PURE__ */
|
|
423
|
+
return /* @__PURE__ */ jsx15(DocTable, { entry });
|
|
412
424
|
case "link":
|
|
413
|
-
return /* @__PURE__ */
|
|
425
|
+
return /* @__PURE__ */ jsx15(DocLink, { entry });
|
|
414
426
|
case "section":
|
|
415
|
-
return /* @__PURE__ */
|
|
427
|
+
return /* @__PURE__ */ jsx15(DocSection, { entry });
|
|
416
428
|
case "mermaid":
|
|
417
|
-
return /* @__PURE__ */
|
|
429
|
+
return /* @__PURE__ */ jsx15(DocMermaid, { entry });
|
|
418
430
|
case "screenshot":
|
|
419
|
-
return /* @__PURE__ */
|
|
431
|
+
return /* @__PURE__ */ jsx15(DocScreenshot, { entry });
|
|
420
432
|
case "video":
|
|
421
|
-
return /* @__PURE__ */
|
|
433
|
+
return /* @__PURE__ */ jsx15(DocVideo, { entry });
|
|
422
434
|
case "html":
|
|
423
|
-
return /* @__PURE__ */
|
|
435
|
+
return /* @__PURE__ */ jsx15(DocHtml, { entry });
|
|
436
|
+
case "state":
|
|
437
|
+
return /* @__PURE__ */ jsx15(DocState, { entry });
|
|
424
438
|
case "custom":
|
|
425
|
-
return /* @__PURE__ */
|
|
439
|
+
return /* @__PURE__ */ jsx15(DocCustom, { entry });
|
|
426
440
|
}
|
|
427
441
|
}
|
|
428
442
|
|
|
429
443
|
// src/components/ReportDocEntries.tsx
|
|
430
|
-
import { Fragment as Fragment5, jsx as
|
|
444
|
+
import { Fragment as Fragment5, jsx as jsx16 } from "react/jsx-runtime";
|
|
431
445
|
function ReportDocEntries({ entries }) {
|
|
432
446
|
if (entries.length === 0) return null;
|
|
433
|
-
return /* @__PURE__ */
|
|
447
|
+
return /* @__PURE__ */ jsx16(Fragment5, { children: entries.map((entry, i) => /* @__PURE__ */ jsx16(DocEntry, { entry }, i)) });
|
|
434
448
|
}
|
|
435
449
|
|
|
436
450
|
// src/lib/step-params.tsx
|
|
437
|
-
import { jsx as
|
|
451
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
438
452
|
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
439
453
|
function highlightStepParams(text) {
|
|
440
454
|
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
@@ -446,7 +460,7 @@ function highlightStepParams(text) {
|
|
|
446
460
|
const end = start + match[0].length;
|
|
447
461
|
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
448
462
|
nodes.push(
|
|
449
|
-
/* @__PURE__ */
|
|
463
|
+
/* @__PURE__ */ jsx17("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
450
464
|
);
|
|
451
465
|
lastIndex = end;
|
|
452
466
|
});
|
|
@@ -455,7 +469,7 @@ function highlightStepParams(text) {
|
|
|
455
469
|
}
|
|
456
470
|
|
|
457
471
|
// src/components/ReportSteps.tsx
|
|
458
|
-
import { jsx as
|
|
472
|
+
import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
459
473
|
var STEP_GLYPH = {
|
|
460
474
|
passed: "\u2713",
|
|
461
475
|
failed: "\u2717",
|
|
@@ -470,7 +484,7 @@ var STEP_GLYPH_COLOR = {
|
|
|
470
484
|
};
|
|
471
485
|
function ReportSteps({ scenario }) {
|
|
472
486
|
if (scenario.steps.length === 0) return null;
|
|
473
|
-
return /* @__PURE__ */
|
|
487
|
+
return /* @__PURE__ */ jsx18("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ jsx18(ReportStepItem, { step }, step.id)) });
|
|
474
488
|
}
|
|
475
489
|
function ReportStepItem({ step }) {
|
|
476
490
|
const kw = step.keyword.toLowerCase();
|
|
@@ -483,8 +497,8 @@ function ReportStepItem({ step }) {
|
|
|
483
497
|
className: cn("py-1.5 text-[0.8125rem] leading-normal", continuation && "pl-5"),
|
|
484
498
|
children: [
|
|
485
499
|
/* @__PURE__ */ jsxs10("div", { className: "flex items-baseline gap-2", children: [
|
|
486
|
-
/* @__PURE__ */
|
|
487
|
-
/* @__PURE__ */
|
|
500
|
+
/* @__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" }),
|
|
501
|
+
/* @__PURE__ */ jsx18(
|
|
488
502
|
"span",
|
|
489
503
|
{
|
|
490
504
|
className: cn(
|
|
@@ -494,10 +508,10 @@ function ReportStepItem({ step }) {
|
|
|
494
508
|
children: step.keyword
|
|
495
509
|
}
|
|
496
510
|
),
|
|
497
|
-
/* @__PURE__ */
|
|
498
|
-
step.durationMs > 0 ? /* @__PURE__ */
|
|
511
|
+
/* @__PURE__ */ jsx18("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
|
|
512
|
+
step.durationMs > 0 ? /* @__PURE__ */ jsx18("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(step.durationMs) }) : null
|
|
499
513
|
] }),
|
|
500
|
-
step.errorMessage ? /* @__PURE__ */
|
|
514
|
+
step.errorMessage ? /* @__PURE__ */ jsx18(
|
|
501
515
|
"pre",
|
|
502
516
|
{
|
|
503
517
|
role: "alert",
|
|
@@ -505,24 +519,255 @@ function ReportStepItem({ step }) {
|
|
|
505
519
|
children: step.errorMessage
|
|
506
520
|
}
|
|
507
521
|
) : null,
|
|
508
|
-
step.docEntries.length > 0 ? /* @__PURE__ */
|
|
522
|
+
step.docEntries.length > 0 ? /* @__PURE__ */ jsx18("div", { "data-es-docs": true, className: "mt-2 ml-6", children: /* @__PURE__ */ jsx18(ReportDocEntries, { entries: step.docEntries }) }) : null
|
|
509
523
|
]
|
|
510
524
|
}
|
|
511
525
|
);
|
|
512
526
|
}
|
|
513
527
|
|
|
528
|
+
// ../executable-stories-core/dist/state-diff.js
|
|
529
|
+
var isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
530
|
+
function deepEqual(a, b) {
|
|
531
|
+
if (Object.is(a, b)) return true;
|
|
532
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
533
|
+
return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
534
|
+
}
|
|
535
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
536
|
+
const ak = Object.keys(a);
|
|
537
|
+
const bk = Object.keys(b);
|
|
538
|
+
return ak.length === bk.length && ak.every((k) => k in b && deepEqual(a[k], b[k]));
|
|
539
|
+
}
|
|
540
|
+
return false;
|
|
541
|
+
}
|
|
542
|
+
var joinKey = (path, key) => path === "" ? key : `${path}.${key}`;
|
|
543
|
+
function walk(path, before, after, out) {
|
|
544
|
+
if (Object.is(before, after)) return;
|
|
545
|
+
if (Array.isArray(before) && Array.isArray(after)) {
|
|
546
|
+
const shared = Math.min(before.length, after.length);
|
|
547
|
+
for (let i = 0; i < shared; i++) walk(`${path}[${i}]`, before[i], after[i], out);
|
|
548
|
+
for (let i = shared; i < after.length; i++) out.push({ path: `${path}[${i}]`, kind: "added", after: after[i] });
|
|
549
|
+
for (let i = shared; i < before.length; i++) out.push({ path: `${path}[${i}]`, kind: "removed", before: before[i] });
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
if (isPlainObject(before) && isPlainObject(after)) {
|
|
553
|
+
for (const key of Object.keys(after)) {
|
|
554
|
+
const p = joinKey(path, key);
|
|
555
|
+
if (key in before) walk(p, before[key], after[key], out);
|
|
556
|
+
else out.push({ path: p, kind: "added", after: after[key] });
|
|
557
|
+
}
|
|
558
|
+
for (const key of Object.keys(before)) {
|
|
559
|
+
if (!(key in after)) out.push({ path: joinKey(path, key), kind: "removed", before: before[key] });
|
|
560
|
+
}
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
if (!deepEqual(before, after)) out.push({ path, kind: "changed", before, after });
|
|
564
|
+
}
|
|
565
|
+
function diffStateValues(before, after) {
|
|
566
|
+
const out = [];
|
|
567
|
+
walk("", before, after, out);
|
|
568
|
+
return out;
|
|
569
|
+
}
|
|
570
|
+
function formatStateValue(value, maxLen = 60) {
|
|
571
|
+
const s = value === void 0 ? "undefined" : JSON.stringify(value);
|
|
572
|
+
return s.length > maxLen ? `${s.slice(0, maxLen - 1)}\u2026` : s;
|
|
573
|
+
}
|
|
574
|
+
function summarizeStateChanges(changes) {
|
|
575
|
+
return changes.map((c) => {
|
|
576
|
+
const at = c.path === "" ? "(root)" : c.path;
|
|
577
|
+
switch (c.kind) {
|
|
578
|
+
case "added":
|
|
579
|
+
return `+ ${at}: ${formatStateValue(c.after)}`;
|
|
580
|
+
case "removed":
|
|
581
|
+
return `\u2212 ${at}`;
|
|
582
|
+
case "changed":
|
|
583
|
+
return `${at}: ${formatStateValue(c.before)} \u2192 ${formatStateValue(c.after)}`;
|
|
584
|
+
}
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// ../executable-stories-core/dist/storyboard.js
|
|
589
|
+
function findScreenshot(entries) {
|
|
590
|
+
for (const entry of entries) {
|
|
591
|
+
if (entry.kind === "screenshot") return entry;
|
|
592
|
+
if (entry.children) {
|
|
593
|
+
const nested = findScreenshot(entry.children);
|
|
594
|
+
if (nested) return nested;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
return void 0;
|
|
598
|
+
}
|
|
599
|
+
function findStates(entries, out = []) {
|
|
600
|
+
for (const entry of entries) {
|
|
601
|
+
if (entry.kind === "state") out.push(entry);
|
|
602
|
+
if (entry.children) findStates(entry.children, out);
|
|
603
|
+
}
|
|
604
|
+
return out;
|
|
605
|
+
}
|
|
606
|
+
var laneOf = (label) => label ?? "";
|
|
607
|
+
function extractStoryboardFrames(scenario) {
|
|
608
|
+
const frames = [];
|
|
609
|
+
const laneOrder = [];
|
|
610
|
+
const previous = /* @__PURE__ */ new Map();
|
|
611
|
+
for (const step of scenario.steps) {
|
|
612
|
+
const shot = findScreenshot(step.docEntries);
|
|
613
|
+
const stateDocs = findStates(step.docEntries);
|
|
614
|
+
if (!shot && stateDocs.length === 0) continue;
|
|
615
|
+
const byLane = /* @__PURE__ */ new Map();
|
|
616
|
+
for (const doc of stateDocs) {
|
|
617
|
+
const lane = laneOf(doc.label);
|
|
618
|
+
if (!byLane.has(lane) && !laneOrder.includes(lane)) laneOrder.push(lane);
|
|
619
|
+
byLane.set(lane, doc);
|
|
620
|
+
}
|
|
621
|
+
const states = [];
|
|
622
|
+
for (const lane of laneOrder) {
|
|
623
|
+
const doc = byLane.get(lane);
|
|
624
|
+
if (!doc) continue;
|
|
625
|
+
const card = {
|
|
626
|
+
...doc.label !== void 0 && { label: doc.label },
|
|
627
|
+
value: doc.value
|
|
628
|
+
};
|
|
629
|
+
if (previous.has(lane)) card.changes = diffStateValues(previous.get(lane), doc.value);
|
|
630
|
+
previous.set(lane, doc.value);
|
|
631
|
+
states.push(card);
|
|
632
|
+
}
|
|
633
|
+
frames.push({
|
|
634
|
+
stepId: step.id,
|
|
635
|
+
stepIndex: step.index,
|
|
636
|
+
keyword: step.keyword,
|
|
637
|
+
text: step.text,
|
|
638
|
+
status: step.status,
|
|
639
|
+
...shot && { screenshot: { path: shot.path, ...shot.alt !== void 0 && { alt: shot.alt } } },
|
|
640
|
+
states
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
return frames;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// src/components/ReportStoryboard.tsx
|
|
647
|
+
import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
648
|
+
var FRAME_GLYPH = {
|
|
649
|
+
passed: "\u2713",
|
|
650
|
+
failed: "\u2717",
|
|
651
|
+
skipped: "\u25CB",
|
|
652
|
+
pending: "\u25CB"
|
|
653
|
+
};
|
|
654
|
+
var FRAME_GLYPH_COLOR = {
|
|
655
|
+
passed: "text-pass",
|
|
656
|
+
failed: "text-fail",
|
|
657
|
+
skipped: "text-skip",
|
|
658
|
+
pending: "text-pend"
|
|
659
|
+
};
|
|
660
|
+
function ReportStoryboard({ scenario }) {
|
|
661
|
+
const frames = extractStoryboardFrames(scenario);
|
|
662
|
+
if (frames.length < 2) return null;
|
|
663
|
+
return /* @__PURE__ */ jsxs11("section", { "data-slot": "storyboard", "aria-label": "Storyboard", className: "mb-3", children: [
|
|
664
|
+
/* @__PURE__ */ jsx19("h4", { className: "mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Storyboard" }),
|
|
665
|
+
/* @__PURE__ */ jsx19("ol", { className: "flex items-start gap-3 overflow-x-auto pb-2", children: frames.map((frame) => /* @__PURE__ */ jsx19(StoryboardFrameItem, { frame }, frame.stepId)) })
|
|
666
|
+
] });
|
|
667
|
+
}
|
|
668
|
+
function StoryboardFrameItem({ frame }) {
|
|
669
|
+
const label = `${frame.keyword} ${frame.text}`;
|
|
670
|
+
const hasStates = frame.states.length > 0;
|
|
671
|
+
const caption = /* @__PURE__ */ jsxs11("p", { className: "mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug", children: [
|
|
672
|
+
/* @__PURE__ */ jsx19("span", { "aria-hidden": true, className: cn("shrink-0", FRAME_GLYPH_COLOR[frame.status]), children: FRAME_GLYPH[frame.status] ?? "\u25CB" }),
|
|
673
|
+
/* @__PURE__ */ jsxs11("span", { className: "min-w-0", children: [
|
|
674
|
+
/* @__PURE__ */ jsx19("span", { className: "font-mono font-semibold text-keyword", children: frame.keyword }),
|
|
675
|
+
" ",
|
|
676
|
+
/* @__PURE__ */ jsx19("span", { className: "text-muted-foreground", children: frame.screenshot?.alt ?? frame.text })
|
|
677
|
+
] })
|
|
678
|
+
] });
|
|
679
|
+
return (
|
|
680
|
+
// State cards need room for diff rows; screenshot-only frames keep the
|
|
681
|
+
// original narrow film-cell width (and DOM) unchanged.
|
|
682
|
+
/* @__PURE__ */ jsxs11("li", { className: cn("shrink-0", hasStates ? "w-64" : "w-40"), children: [
|
|
683
|
+
frame.screenshot ? /* @__PURE__ */ jsx19(FrameScreenshot, { frame, label }) : null,
|
|
684
|
+
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,
|
|
685
|
+
frame.screenshot ? caption : (
|
|
686
|
+
// No screenshot means no image anchor, so the caption carries the
|
|
687
|
+
// jump-to-step link instead.
|
|
688
|
+
/* @__PURE__ */ jsx19("a", { href: `#${frame.stepId}`, "aria-label": `Jump to step: ${label}`, className: "block hover:underline", children: caption })
|
|
689
|
+
)
|
|
690
|
+
] })
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
function FrameScreenshot({ frame, label }) {
|
|
694
|
+
const path = frame.screenshot?.path ?? "";
|
|
695
|
+
const src = isLocalFsPath(path) ? void 0 : safeImageUrl(path);
|
|
696
|
+
return /* @__PURE__ */ jsx19(
|
|
697
|
+
"a",
|
|
698
|
+
{
|
|
699
|
+
href: `#${frame.stepId}`,
|
|
700
|
+
"aria-label": `Jump to step: ${label}`,
|
|
701
|
+
className: "block overflow-hidden rounded-md border border-border transition-colors hover:border-ring",
|
|
702
|
+
children: src ? /* @__PURE__ */ jsx19(
|
|
703
|
+
"img",
|
|
704
|
+
{
|
|
705
|
+
src,
|
|
706
|
+
alt: frame.screenshot?.alt ?? label,
|
|
707
|
+
loading: "lazy",
|
|
708
|
+
className: "h-24 w-full bg-muted object-cover object-top"
|
|
709
|
+
}
|
|
710
|
+
) : /* @__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" })
|
|
711
|
+
}
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
var CHANGE_TONE = {
|
|
715
|
+
added: "bg-pass-bg text-pass",
|
|
716
|
+
removed: "bg-fail-bg text-fail",
|
|
717
|
+
changed: "bg-skip-bg text-skip"
|
|
718
|
+
};
|
|
719
|
+
function prettyJson(value) {
|
|
720
|
+
try {
|
|
721
|
+
return JSON.stringify(value, null, 2) ?? String(value);
|
|
722
|
+
} catch {
|
|
723
|
+
return String(value);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
function StateCardView({ card }) {
|
|
727
|
+
const json = prettyJson(card.value);
|
|
728
|
+
const firstCapture = card.changes === void 0;
|
|
729
|
+
return /* @__PURE__ */ jsxs11("div", { "data-slot": "state-card", className: "rounded-md border border-border bg-card p-2", children: [
|
|
730
|
+
/* @__PURE__ */ jsxs11("p", { className: "flex flex-wrap items-baseline gap-1.5", children: [
|
|
731
|
+
/* @__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" }),
|
|
732
|
+
firstCapture ? /* @__PURE__ */ jsx19("span", { className: "text-[0.625rem] text-muted-foreground italic", children: "first capture" }) : null
|
|
733
|
+
] }),
|
|
734
|
+
!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(
|
|
735
|
+
"li",
|
|
736
|
+
{
|
|
737
|
+
className: cn(
|
|
738
|
+
"rounded-sm px-1.5 py-0.5 font-mono text-[0.625rem] leading-snug break-all",
|
|
739
|
+
CHANGE_TONE[change.kind]
|
|
740
|
+
),
|
|
741
|
+
children: summarizeStateChanges([change])[0]
|
|
742
|
+
},
|
|
743
|
+
i
|
|
744
|
+
)) }) : /* @__PURE__ */ jsx19("p", { className: "mt-1.5 text-[0.625rem] text-muted-foreground", children: "No changes" })),
|
|
745
|
+
/* @__PURE__ */ jsxs11(
|
|
746
|
+
"details",
|
|
747
|
+
{
|
|
748
|
+
open: firstCapture && json.length <= 240,
|
|
749
|
+
className: cn(firstCapture ? "mt-1.5" : "mt-1"),
|
|
750
|
+
children: [
|
|
751
|
+
/* @__PURE__ */ jsx19("summary", { className: "cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground", children: "Snapshot" }),
|
|
752
|
+
/* @__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 })
|
|
753
|
+
]
|
|
754
|
+
}
|
|
755
|
+
)
|
|
756
|
+
] });
|
|
757
|
+
}
|
|
758
|
+
|
|
514
759
|
// src/components/ReportAttachments.tsx
|
|
515
|
-
import { Fragment as Fragment6, jsx as
|
|
760
|
+
import { Fragment as Fragment6, jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
516
761
|
function ReportAttachments({ attachments }) {
|
|
517
762
|
if (attachments.length === 0) return null;
|
|
518
763
|
return (
|
|
519
764
|
// role="group" (not a labelled <section>) so multiple scenarios' attachment
|
|
520
765
|
// blocks don't create duplicate "Attachments" region landmarks.
|
|
521
|
-
/* @__PURE__ */
|
|
766
|
+
/* @__PURE__ */ jsx20("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
|
|
522
767
|
const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
|
|
523
768
|
const isImage = att.mediaType.startsWith("image/");
|
|
524
|
-
return /* @__PURE__ */
|
|
525
|
-
/* @__PURE__ */
|
|
769
|
+
return /* @__PURE__ */ jsx20("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ jsxs12(Fragment6, { children: [
|
|
770
|
+
/* @__PURE__ */ jsx20(
|
|
526
771
|
"img",
|
|
527
772
|
{
|
|
528
773
|
src: dataUri,
|
|
@@ -531,8 +776,8 @@ function ReportAttachments({ attachments }) {
|
|
|
531
776
|
className: "max-w-full rounded-md border border-border"
|
|
532
777
|
}
|
|
533
778
|
),
|
|
534
|
-
/* @__PURE__ */
|
|
535
|
-
] }) : /* @__PURE__ */
|
|
779
|
+
/* @__PURE__ */ jsx20("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
|
|
780
|
+
] }) : /* @__PURE__ */ jsxs12(
|
|
536
781
|
"a",
|
|
537
782
|
{
|
|
538
783
|
href: dataUri,
|
|
@@ -541,7 +786,7 @@ function ReportAttachments({ attachments }) {
|
|
|
541
786
|
children: [
|
|
542
787
|
att.name,
|
|
543
788
|
" ",
|
|
544
|
-
/* @__PURE__ */
|
|
789
|
+
/* @__PURE__ */ jsxs12("span", { className: "text-muted-foreground", children: [
|
|
545
790
|
"(",
|
|
546
791
|
att.mediaType,
|
|
547
792
|
")"
|
|
@@ -605,15 +850,15 @@ function toTraceRows(spans) {
|
|
|
605
850
|
roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
606
851
|
const rows = [];
|
|
607
852
|
const seen = /* @__PURE__ */ new Set();
|
|
608
|
-
const
|
|
853
|
+
const walk2 = (node, depth) => {
|
|
609
854
|
if (seen.has(node.span.spanId)) return;
|
|
610
855
|
seen.add(node.span.spanId);
|
|
611
856
|
rows.push({ ...node.span, depth });
|
|
612
|
-
for (const child of node.children)
|
|
857
|
+
for (const child of node.children) walk2(child, depth + 1);
|
|
613
858
|
};
|
|
614
|
-
for (const root of roots)
|
|
859
|
+
for (const root of roots) walk2(root, 0);
|
|
615
860
|
for (const node of byId.values()) {
|
|
616
|
-
if (!seen.has(node.span.spanId))
|
|
861
|
+
if (!seen.has(node.span.spanId)) walk2(node, 0);
|
|
617
862
|
}
|
|
618
863
|
return rows;
|
|
619
864
|
}
|
|
@@ -629,7 +874,7 @@ function traceWindow(rows) {
|
|
|
629
874
|
}
|
|
630
875
|
|
|
631
876
|
// src/components/ReportTrace.tsx
|
|
632
|
-
import { jsx as
|
|
877
|
+
import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
633
878
|
var BAR_COLOR = {
|
|
634
879
|
ok: "bg-pass",
|
|
635
880
|
error: "bg-fail",
|
|
@@ -640,8 +885,8 @@ function ReportTrace({ spans }) {
|
|
|
640
885
|
const rows = toTraceRows(spans);
|
|
641
886
|
if (rows.length === 0) return null;
|
|
642
887
|
const { minStartMs, totalMs } = traceWindow(rows);
|
|
643
|
-
return /* @__PURE__ */
|
|
644
|
-
/* @__PURE__ */
|
|
888
|
+
return /* @__PURE__ */ jsxs13("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
|
|
889
|
+
/* @__PURE__ */ jsxs13("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
|
|
645
890
|
"Trace (",
|
|
646
891
|
rows.length,
|
|
647
892
|
" span",
|
|
@@ -650,11 +895,11 @@ function ReportTrace({ spans }) {
|
|
|
650
895
|
formatDuration(totalMs),
|
|
651
896
|
")"
|
|
652
897
|
] }),
|
|
653
|
-
/* @__PURE__ */
|
|
898
|
+
/* @__PURE__ */ jsx21("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
|
|
654
899
|
const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
|
|
655
900
|
const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
|
|
656
|
-
return /* @__PURE__ */
|
|
657
|
-
/* @__PURE__ */
|
|
901
|
+
return /* @__PURE__ */ jsxs13("li", { className: "flex items-center gap-2", children: [
|
|
902
|
+
/* @__PURE__ */ jsx21(
|
|
658
903
|
"span",
|
|
659
904
|
{
|
|
660
905
|
className: "min-w-0 flex-1 truncate text-foreground",
|
|
@@ -663,14 +908,14 @@ function ReportTrace({ spans }) {
|
|
|
663
908
|
children: row.name
|
|
664
909
|
}
|
|
665
910
|
),
|
|
666
|
-
/* @__PURE__ */
|
|
911
|
+
/* @__PURE__ */ jsx21("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ jsx21(
|
|
667
912
|
"span",
|
|
668
913
|
{
|
|
669
914
|
className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
|
|
670
915
|
style: { left: `${leftPct}%`, width: `${widthPct}%` }
|
|
671
916
|
}
|
|
672
917
|
) }),
|
|
673
|
-
/* @__PURE__ */
|
|
918
|
+
/* @__PURE__ */ jsx21("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration(row.durationMs) })
|
|
674
919
|
] }, `${row.spanId}-${i}`);
|
|
675
920
|
}) })
|
|
676
921
|
] });
|
|
@@ -721,7 +966,7 @@ function flakinessOf(entries) {
|
|
|
721
966
|
}
|
|
722
967
|
|
|
723
968
|
// src/components/ScenarioRunHistory.tsx
|
|
724
|
-
import { Fragment as Fragment7, jsx as
|
|
969
|
+
import { Fragment as Fragment7, jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
725
970
|
var MAX_DOTS = 10;
|
|
726
971
|
var DOT_COLOR = {
|
|
727
972
|
passed: "bg-pass",
|
|
@@ -741,16 +986,16 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
741
986
|
const recent = entries.slice(-MAX_DOTS);
|
|
742
987
|
const flaky = flakinessOf(recent) === "flaky";
|
|
743
988
|
const summary = flaky ? `${describeRunHistory(recent)} \xB7 Flaky` : describeRunHistory(recent);
|
|
744
|
-
return /* @__PURE__ */
|
|
745
|
-
flaky ? /* @__PURE__ */
|
|
746
|
-
/* @__PURE__ */
|
|
989
|
+
return /* @__PURE__ */ jsxs14(Fragment7, { children: [
|
|
990
|
+
flaky ? /* @__PURE__ */ jsx22(Badge, { variant: "pending", "aria-label": "Flaky: status flips between recent runs", title: summary, children: "Flaky" }) : null,
|
|
991
|
+
/* @__PURE__ */ jsx22(
|
|
747
992
|
"span",
|
|
748
993
|
{
|
|
749
994
|
role: "img",
|
|
750
995
|
"aria-label": `Run history: ${summary}`,
|
|
751
996
|
title: summary,
|
|
752
997
|
className: "flex shrink-0 items-center gap-[3px]",
|
|
753
|
-
children: recent.map((e, i) => /* @__PURE__ */
|
|
998
|
+
children: recent.map((e, i) => /* @__PURE__ */ jsx22(
|
|
754
999
|
"span",
|
|
755
1000
|
{
|
|
756
1001
|
"aria-hidden": true,
|
|
@@ -789,9 +1034,9 @@ function useScenarioActions() {
|
|
|
789
1034
|
|
|
790
1035
|
// src/components/ui/card.tsx
|
|
791
1036
|
import "react";
|
|
792
|
-
import { jsx as
|
|
1037
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
793
1038
|
function Card({ className, ...props }) {
|
|
794
|
-
return /* @__PURE__ */
|
|
1039
|
+
return /* @__PURE__ */ jsx23(
|
|
795
1040
|
"div",
|
|
796
1041
|
{
|
|
797
1042
|
"data-slot": "card",
|
|
@@ -804,7 +1049,7 @@ function Card({ className, ...props }) {
|
|
|
804
1049
|
);
|
|
805
1050
|
}
|
|
806
1051
|
function CardHeader({ className, ...props }) {
|
|
807
|
-
return /* @__PURE__ */
|
|
1052
|
+
return /* @__PURE__ */ jsx23(
|
|
808
1053
|
"div",
|
|
809
1054
|
{
|
|
810
1055
|
"data-slot": "card-header",
|
|
@@ -817,7 +1062,7 @@ function CardHeader({ className, ...props }) {
|
|
|
817
1062
|
);
|
|
818
1063
|
}
|
|
819
1064
|
function CardContent({ className, ...props }) {
|
|
820
|
-
return /* @__PURE__ */
|
|
1065
|
+
return /* @__PURE__ */ jsx23(
|
|
821
1066
|
"div",
|
|
822
1067
|
{
|
|
823
1068
|
"data-slot": "card-content",
|
|
@@ -831,13 +1076,13 @@ function CardContent({ className, ...props }) {
|
|
|
831
1076
|
import "react";
|
|
832
1077
|
import { Menu as MenuPrimitive } from "@base-ui/react/menu";
|
|
833
1078
|
import { CheckIcon } from "lucide-react";
|
|
834
|
-
import { jsx as
|
|
1079
|
+
import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
835
1080
|
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";
|
|
836
1081
|
function DropdownMenu(props) {
|
|
837
|
-
return /* @__PURE__ */
|
|
1082
|
+
return /* @__PURE__ */ jsx24(MenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
838
1083
|
}
|
|
839
1084
|
function DropdownMenuTrigger(props) {
|
|
840
|
-
return /* @__PURE__ */
|
|
1085
|
+
return /* @__PURE__ */ jsx24(MenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
841
1086
|
}
|
|
842
1087
|
function DropdownMenuContent({
|
|
843
1088
|
className,
|
|
@@ -845,14 +1090,14 @@ function DropdownMenuContent({
|
|
|
845
1090
|
sideOffset = 4,
|
|
846
1091
|
...props
|
|
847
1092
|
}) {
|
|
848
|
-
return /* @__PURE__ */
|
|
1093
|
+
return /* @__PURE__ */ jsx24(MenuPrimitive.Portal, { children: /* @__PURE__ */ jsx24(
|
|
849
1094
|
MenuPrimitive.Positioner,
|
|
850
1095
|
{
|
|
851
1096
|
"data-slot": "dropdown-menu-positioner",
|
|
852
1097
|
className: "z-50",
|
|
853
1098
|
align,
|
|
854
1099
|
sideOffset,
|
|
855
|
-
children: /* @__PURE__ */
|
|
1100
|
+
children: /* @__PURE__ */ jsx24(
|
|
856
1101
|
MenuPrimitive.Popup,
|
|
857
1102
|
{
|
|
858
1103
|
"data-slot": "dropdown-menu-content",
|
|
@@ -870,7 +1115,7 @@ function DropdownMenuItem({
|
|
|
870
1115
|
className,
|
|
871
1116
|
...props
|
|
872
1117
|
}) {
|
|
873
|
-
return /* @__PURE__ */
|
|
1118
|
+
return /* @__PURE__ */ jsx24(
|
|
874
1119
|
MenuPrimitive.Item,
|
|
875
1120
|
{
|
|
876
1121
|
"data-slot": "dropdown-menu-item",
|
|
@@ -882,7 +1127,7 @@ function DropdownMenuItem({
|
|
|
882
1127
|
|
|
883
1128
|
// src/components/ReportScenario.tsx
|
|
884
1129
|
import { LinkIcon, FileTextIcon, SparklesIcon, MoreHorizontalIcon } from "lucide-react";
|
|
885
|
-
import { jsx as
|
|
1130
|
+
import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
886
1131
|
var STATUS_META = {
|
|
887
1132
|
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
888
1133
|
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
@@ -898,7 +1143,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
898
1143
|
const collapsible = collapse !== null && !hideTitle;
|
|
899
1144
|
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
900
1145
|
const actions = useScenarioActions();
|
|
901
|
-
return /* @__PURE__ */
|
|
1146
|
+
return /* @__PURE__ */ jsxs16(
|
|
902
1147
|
Card,
|
|
903
1148
|
{
|
|
904
1149
|
id: scenario.id,
|
|
@@ -906,10 +1151,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
906
1151
|
...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
|
|
907
1152
|
className: "gap-0 py-0",
|
|
908
1153
|
children: [
|
|
909
|
-
/* @__PURE__ */
|
|
910
|
-
/* @__PURE__ */
|
|
911
|
-
hideTitle ? null : /* @__PURE__ */
|
|
912
|
-
collapsible ? /* @__PURE__ */
|
|
1154
|
+
/* @__PURE__ */ jsxs16(CardHeader, { className: "px-4 py-3", children: [
|
|
1155
|
+
/* @__PURE__ */ jsxs16("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
1156
|
+
hideTitle ? null : /* @__PURE__ */ jsxs16("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
1157
|
+
collapsible ? /* @__PURE__ */ jsx25(
|
|
913
1158
|
"button",
|
|
914
1159
|
{
|
|
915
1160
|
type: "button",
|
|
@@ -918,49 +1163,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
918
1163
|
"aria-controls": bodyId,
|
|
919
1164
|
"aria-label": `Toggle ${scenario.title}`,
|
|
920
1165
|
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
921
|
-
children: /* @__PURE__ */
|
|
1166
|
+
children: /* @__PURE__ */ jsx25("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
922
1167
|
}
|
|
923
1168
|
) : null,
|
|
924
|
-
/* @__PURE__ */
|
|
925
|
-
/* @__PURE__ */
|
|
1169
|
+
/* @__PURE__ */ jsx25("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
1170
|
+
/* @__PURE__ */ jsx25("span", { children: scenario.title })
|
|
926
1171
|
] }),
|
|
927
|
-
/* @__PURE__ */
|
|
928
|
-
/* @__PURE__ */
|
|
929
|
-
scenario.durationMs > 0 ? /* @__PURE__ */
|
|
930
|
-
meta.showPill ? /* @__PURE__ */
|
|
931
|
-
actions ? /* @__PURE__ */
|
|
932
|
-
/* @__PURE__ */
|
|
1172
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1173
|
+
/* @__PURE__ */ jsx25(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1174
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ jsx25("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
|
|
1175
|
+
meta.showPill ? /* @__PURE__ */ jsx25(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ jsx25("span", { className: "sr-only", children: `Status: ${label}` }),
|
|
1176
|
+
actions ? /* @__PURE__ */ jsxs16(DropdownMenu, { children: [
|
|
1177
|
+
/* @__PURE__ */ jsx25(
|
|
933
1178
|
DropdownMenuTrigger,
|
|
934
1179
|
{
|
|
935
1180
|
"aria-label": `Actions for ${scenario.title}`,
|
|
936
1181
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
937
|
-
children: /* @__PURE__ */
|
|
1182
|
+
children: /* @__PURE__ */ jsx25(MoreHorizontalIcon, { "aria-hidden": true })
|
|
938
1183
|
}
|
|
939
1184
|
),
|
|
940
|
-
/* @__PURE__ */
|
|
941
|
-
/* @__PURE__ */
|
|
942
|
-
/* @__PURE__ */
|
|
1185
|
+
/* @__PURE__ */ jsxs16(DropdownMenuContent, { align: "end", children: [
|
|
1186
|
+
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
1187
|
+
/* @__PURE__ */ jsx25(LinkIcon, {}),
|
|
943
1188
|
" Copy link"
|
|
944
1189
|
] }),
|
|
945
|
-
/* @__PURE__ */
|
|
946
|
-
/* @__PURE__ */
|
|
1190
|
+
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
1191
|
+
/* @__PURE__ */ jsx25(FileTextIcon, {}),
|
|
947
1192
|
" Copy as Markdown"
|
|
948
1193
|
] }),
|
|
949
|
-
/* @__PURE__ */
|
|
950
|
-
/* @__PURE__ */
|
|
1194
|
+
/* @__PURE__ */ jsxs16(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
1195
|
+
/* @__PURE__ */ jsx25(SparklesIcon, {}),
|
|
951
1196
|
" Explain with AI"
|
|
952
1197
|
] })
|
|
953
1198
|
] })
|
|
954
1199
|
] }) : null
|
|
955
1200
|
] })
|
|
956
1201
|
] }),
|
|
957
|
-
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */
|
|
958
|
-
scenario.tags.map((t) => /* @__PURE__ */
|
|
959
|
-
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */
|
|
1202
|
+
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: [
|
|
1203
|
+
scenario.tags.map((t) => /* @__PURE__ */ jsx25("li", { children: /* @__PURE__ */ jsx25(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
|
|
1204
|
+
(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}`))
|
|
960
1205
|
] }) : null
|
|
961
1206
|
] }),
|
|
962
|
-
/* @__PURE__ */
|
|
963
|
-
scenario.errorMessage ? /* @__PURE__ */
|
|
1207
|
+
/* @__PURE__ */ jsxs16(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
1208
|
+
scenario.errorMessage ? /* @__PURE__ */ jsx25(
|
|
964
1209
|
"pre",
|
|
965
1210
|
{
|
|
966
1211
|
role: "alert",
|
|
@@ -968,10 +1213,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
968
1213
|
children: scenario.errorMessage
|
|
969
1214
|
}
|
|
970
1215
|
) : null,
|
|
971
|
-
/* @__PURE__ */
|
|
972
|
-
|
|
973
|
-
/* @__PURE__ */
|
|
974
|
-
/* @__PURE__ */
|
|
1216
|
+
/* @__PURE__ */ jsx25(ReportStoryboard, { scenario }),
|
|
1217
|
+
/* @__PURE__ */ jsx25(ReportSteps, { scenario }),
|
|
1218
|
+
scenario.docEntries.length > 0 ? /* @__PURE__ */ jsx25("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ jsx25(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
|
|
1219
|
+
/* @__PURE__ */ jsx25(ReportAttachments, { attachments: scenario.attachments }),
|
|
1220
|
+
/* @__PURE__ */ jsx25(ReportTrace, { spans: scenario.otelSpans })
|
|
975
1221
|
] })
|
|
976
1222
|
]
|
|
977
1223
|
}
|
|
@@ -979,13 +1225,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
979
1225
|
}
|
|
980
1226
|
|
|
981
1227
|
// src/components/ReportScenarioList.tsx
|
|
982
|
-
import { Fragment as Fragment8, jsx as
|
|
1228
|
+
import { Fragment as Fragment8, jsx as jsx26 } from "react/jsx-runtime";
|
|
983
1229
|
function ReportScenarioList({ feature }) {
|
|
984
|
-
return /* @__PURE__ */
|
|
1230
|
+
return /* @__PURE__ */ jsx26(Fragment8, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ jsx26(ReportScenario, { scenario }, scenario.id)) });
|
|
985
1231
|
}
|
|
986
1232
|
|
|
987
1233
|
// src/components/ReportFeature.tsx
|
|
988
|
-
import { Fragment as Fragment9, jsx as
|
|
1234
|
+
import { Fragment as Fragment9, jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
989
1235
|
function ReportFeature({ feature }) {
|
|
990
1236
|
const titleId = `${feature.id}-title`;
|
|
991
1237
|
const bodyId = `${feature.id}-body`;
|
|
@@ -996,7 +1242,7 @@ function ReportFeature({ feature }) {
|
|
|
996
1242
|
return (
|
|
997
1243
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
998
1244
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
999
|
-
/* @__PURE__ */
|
|
1245
|
+
/* @__PURE__ */ jsxs17(
|
|
1000
1246
|
"section",
|
|
1001
1247
|
{
|
|
1002
1248
|
id: feature.id,
|
|
@@ -1004,9 +1250,9 @@ function ReportFeature({ feature }) {
|
|
|
1004
1250
|
"aria-labelledby": titleId,
|
|
1005
1251
|
className: "flex flex-col gap-3",
|
|
1006
1252
|
children: [
|
|
1007
|
-
/* @__PURE__ */
|
|
1008
|
-
/* @__PURE__ */
|
|
1009
|
-
/* @__PURE__ */
|
|
1253
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1254
|
+
/* @__PURE__ */ jsxs17("div", { className: "min-w-0", children: [
|
|
1255
|
+
/* @__PURE__ */ jsx27("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ jsxs17(
|
|
1010
1256
|
"button",
|
|
1011
1257
|
{
|
|
1012
1258
|
type: "button",
|
|
@@ -1015,31 +1261,31 @@ function ReportFeature({ feature }) {
|
|
|
1015
1261
|
"aria-controls": bodyId,
|
|
1016
1262
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1017
1263
|
children: [
|
|
1018
|
-
/* @__PURE__ */
|
|
1019
|
-
/* @__PURE__ */
|
|
1264
|
+
/* @__PURE__ */ jsx27("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
|
|
1265
|
+
/* @__PURE__ */ jsx27("span", { className: "truncate", children: feature.title })
|
|
1020
1266
|
]
|
|
1021
1267
|
}
|
|
1022
1268
|
) : feature.title }),
|
|
1023
|
-
/* @__PURE__ */
|
|
1269
|
+
/* @__PURE__ */ jsx27("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
|
|
1024
1270
|
] }),
|
|
1025
|
-
/* @__PURE__ */
|
|
1271
|
+
/* @__PURE__ */ jsxs17(
|
|
1026
1272
|
"p",
|
|
1027
1273
|
{
|
|
1028
1274
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1029
1275
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1030
1276
|
children: [
|
|
1031
|
-
/* @__PURE__ */
|
|
1277
|
+
/* @__PURE__ */ jsxs17("span", { children: [
|
|
1032
1278
|
s.passed,
|
|
1033
1279
|
" passed"
|
|
1034
1280
|
] }),
|
|
1035
|
-
/* @__PURE__ */
|
|
1036
|
-
/* @__PURE__ */
|
|
1281
|
+
/* @__PURE__ */ jsx27("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1282
|
+
/* @__PURE__ */ jsxs17("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1037
1283
|
s.failed,
|
|
1038
1284
|
" failed"
|
|
1039
1285
|
] }),
|
|
1040
|
-
skipped > 0 ? /* @__PURE__ */
|
|
1041
|
-
/* @__PURE__ */
|
|
1042
|
-
/* @__PURE__ */
|
|
1286
|
+
skipped > 0 ? /* @__PURE__ */ jsxs17(Fragment9, { children: [
|
|
1287
|
+
/* @__PURE__ */ jsx27("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1288
|
+
/* @__PURE__ */ jsxs17("span", { children: [
|
|
1043
1289
|
skipped,
|
|
1044
1290
|
" skipped"
|
|
1045
1291
|
] })
|
|
@@ -1048,7 +1294,7 @@ function ReportFeature({ feature }) {
|
|
|
1048
1294
|
}
|
|
1049
1295
|
)
|
|
1050
1296
|
] }),
|
|
1051
|
-
/* @__PURE__ */
|
|
1297
|
+
/* @__PURE__ */ jsx27("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx27(ReportScenarioList, { feature }) })
|
|
1052
1298
|
]
|
|
1053
1299
|
}
|
|
1054
1300
|
)
|
|
@@ -1056,17 +1302,17 @@ function ReportFeature({ feature }) {
|
|
|
1056
1302
|
}
|
|
1057
1303
|
|
|
1058
1304
|
// src/components/ReportFeatureList.tsx
|
|
1059
|
-
import { jsx as
|
|
1305
|
+
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
1060
1306
|
function ReportFeatureList() {
|
|
1061
1307
|
const report = useReport();
|
|
1062
|
-
return /* @__PURE__ */
|
|
1308
|
+
return /* @__PURE__ */ jsx28("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ jsx28(ReportFeature, { feature }, feature.id)) });
|
|
1063
1309
|
}
|
|
1064
1310
|
|
|
1065
1311
|
// src/components/ui/empty.tsx
|
|
1066
1312
|
import { cva as cva2 } from "class-variance-authority";
|
|
1067
|
-
import { jsx as
|
|
1313
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
1068
1314
|
function Empty({ className, ...props }) {
|
|
1069
|
-
return /* @__PURE__ */
|
|
1315
|
+
return /* @__PURE__ */ jsx29(
|
|
1070
1316
|
"div",
|
|
1071
1317
|
{
|
|
1072
1318
|
"data-slot": "empty",
|
|
@@ -1079,7 +1325,7 @@ function Empty({ className, ...props }) {
|
|
|
1079
1325
|
);
|
|
1080
1326
|
}
|
|
1081
1327
|
function EmptyHeader({ className, ...props }) {
|
|
1082
|
-
return /* @__PURE__ */
|
|
1328
|
+
return /* @__PURE__ */ jsx29(
|
|
1083
1329
|
"div",
|
|
1084
1330
|
{
|
|
1085
1331
|
"data-slot": "empty-header",
|
|
@@ -1106,7 +1352,7 @@ var emptyMediaVariants = cva2(
|
|
|
1106
1352
|
}
|
|
1107
1353
|
);
|
|
1108
1354
|
function EmptyTitle({ className, ...props }) {
|
|
1109
|
-
return /* @__PURE__ */
|
|
1355
|
+
return /* @__PURE__ */ jsx29(
|
|
1110
1356
|
"div",
|
|
1111
1357
|
{
|
|
1112
1358
|
"data-slot": "empty-title",
|
|
@@ -1117,16 +1363,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1117
1363
|
}
|
|
1118
1364
|
|
|
1119
1365
|
// src/components/ReportEmpty.tsx
|
|
1120
|
-
import { jsx as
|
|
1366
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
1121
1367
|
function ReportEmpty({ message }) {
|
|
1122
|
-
return /* @__PURE__ */
|
|
1368
|
+
return /* @__PURE__ */ jsx30(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ jsx30(EmptyHeader, { children: /* @__PURE__ */ jsx30(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
|
|
1123
1369
|
}
|
|
1124
1370
|
|
|
1125
1371
|
// src/components/ReportSummary.tsx
|
|
1126
|
-
import { jsx as
|
|
1372
|
+
import { jsx as jsx31, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1127
1373
|
function ReportSummary({ className }) {
|
|
1128
1374
|
const report = useReport();
|
|
1129
|
-
return /* @__PURE__ */
|
|
1375
|
+
return /* @__PURE__ */ jsx31(
|
|
1130
1376
|
ReportSummaryView,
|
|
1131
1377
|
{
|
|
1132
1378
|
summary: report.summary,
|
|
@@ -1152,7 +1398,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1152
1398
|
if (summary.pending > 0) {
|
|
1153
1399
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1154
1400
|
}
|
|
1155
|
-
return /* @__PURE__ */
|
|
1401
|
+
return /* @__PURE__ */ jsx31(
|
|
1156
1402
|
"dl",
|
|
1157
1403
|
{
|
|
1158
1404
|
className: cn(
|
|
@@ -1165,17 +1411,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1165
1411
|
"aria-label": ariaLabel,
|
|
1166
1412
|
children: cards.map((c) => {
|
|
1167
1413
|
const tone = TONE[c.status];
|
|
1168
|
-
return /* @__PURE__ */
|
|
1414
|
+
return /* @__PURE__ */ jsxs18(
|
|
1169
1415
|
"div",
|
|
1170
1416
|
{
|
|
1171
1417
|
"data-status": c.status,
|
|
1172
1418
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1173
1419
|
children: [
|
|
1174
|
-
/* @__PURE__ */
|
|
1175
|
-
/* @__PURE__ */
|
|
1420
|
+
/* @__PURE__ */ jsxs18("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
|
|
1421
|
+
/* @__PURE__ */ jsx31("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1176
1422
|
c.label
|
|
1177
1423
|
] }),
|
|
1178
|
-
/* @__PURE__ */
|
|
1424
|
+
/* @__PURE__ */ jsx31("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
|
|
1179
1425
|
]
|
|
1180
1426
|
},
|
|
1181
1427
|
c.status
|
|
@@ -1235,7 +1481,7 @@ function prUrl(ci) {
|
|
|
1235
1481
|
}
|
|
1236
1482
|
|
|
1237
1483
|
// src/components/ReportMeta.tsx
|
|
1238
|
-
import { jsx as
|
|
1484
|
+
import { jsx as jsx32, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1239
1485
|
function ReportMeta() {
|
|
1240
1486
|
const report = useReport();
|
|
1241
1487
|
const items = [];
|
|
@@ -1258,13 +1504,13 @@ function ReportMeta() {
|
|
|
1258
1504
|
const short = sha.slice(0, 8);
|
|
1259
1505
|
items.push({
|
|
1260
1506
|
label: "Commit",
|
|
1261
|
-
value: url ? /* @__PURE__ */
|
|
1507
|
+
value: url ? /* @__PURE__ */ jsx32("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1262
1508
|
});
|
|
1263
1509
|
}
|
|
1264
1510
|
if (report.ci) {
|
|
1265
1511
|
items.push({
|
|
1266
1512
|
label: "CI",
|
|
1267
|
-
value: report.ci.url ? /* @__PURE__ */
|
|
1513
|
+
value: report.ci.url ? /* @__PURE__ */ jsxs19("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1268
1514
|
ciDisplayName(report.ci.name),
|
|
1269
1515
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1270
1516
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1275,7 +1521,7 @@ function ReportMeta() {
|
|
|
1275
1521
|
const label = `#${report.ci.prNumber}`;
|
|
1276
1522
|
items.push({
|
|
1277
1523
|
label: "PR",
|
|
1278
|
-
value: url ? /* @__PURE__ */
|
|
1524
|
+
value: url ? /* @__PURE__ */ jsx32("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1279
1525
|
});
|
|
1280
1526
|
}
|
|
1281
1527
|
if (items.length === 0) return null;
|
|
@@ -1283,48 +1529,48 @@ function ReportMeta() {
|
|
|
1283
1529
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1284
1530
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1285
1531
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1286
|
-
/* @__PURE__ */
|
|
1287
|
-
/* @__PURE__ */
|
|
1288
|
-
/* @__PURE__ */
|
|
1532
|
+
/* @__PURE__ */ jsxs19("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
|
|
1533
|
+
/* @__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: [
|
|
1534
|
+
/* @__PURE__ */ jsx32("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1289
1535
|
"Run details"
|
|
1290
1536
|
] }),
|
|
1291
|
-
/* @__PURE__ */
|
|
1292
|
-
/* @__PURE__ */
|
|
1293
|
-
/* @__PURE__ */
|
|
1537
|
+
/* @__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: [
|
|
1538
|
+
/* @__PURE__ */ jsx32("dt", { className: "font-medium", children: item.label }),
|
|
1539
|
+
/* @__PURE__ */ jsx32("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1294
1540
|
] }, item.label)) })
|
|
1295
1541
|
] })
|
|
1296
1542
|
);
|
|
1297
1543
|
}
|
|
1298
1544
|
|
|
1299
1545
|
// src/components/ReportSchemaError.tsx
|
|
1300
|
-
import { jsx as
|
|
1546
|
+
import { jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1301
1547
|
function ReportSchemaError({ error }) {
|
|
1302
|
-
return /* @__PURE__ */
|
|
1303
|
-
/* @__PURE__ */
|
|
1304
|
-
/* @__PURE__ */
|
|
1305
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */
|
|
1548
|
+
return /* @__PURE__ */ jsxs20("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1549
|
+
/* @__PURE__ */ jsx33("p", { children: /* @__PURE__ */ jsx33("strong", { children: "Report could not be displayed." }) }),
|
|
1550
|
+
/* @__PURE__ */ jsx33("p", { children: error.message }),
|
|
1551
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ jsxs20("p", { children: [
|
|
1306
1552
|
"The report bundle is newer than this version of ",
|
|
1307
|
-
/* @__PURE__ */
|
|
1553
|
+
/* @__PURE__ */ jsx33("code", { children: "executable-stories-react" }),
|
|
1308
1554
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1309
1555
|
] }) : null,
|
|
1310
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */
|
|
1311
|
-
/* @__PURE__ */
|
|
1556
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ jsxs20("details", { children: [
|
|
1557
|
+
/* @__PURE__ */ jsxs20("summary", { children: [
|
|
1312
1558
|
error.issues.length,
|
|
1313
1559
|
" validation issue",
|
|
1314
1560
|
error.issues.length === 1 ? "" : "s"
|
|
1315
1561
|
] }),
|
|
1316
|
-
/* @__PURE__ */
|
|
1562
|
+
/* @__PURE__ */ jsx33("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1317
1563
|
] }) : null
|
|
1318
1564
|
] });
|
|
1319
1565
|
}
|
|
1320
1566
|
|
|
1321
1567
|
// src/components/ReportShell.tsx
|
|
1322
|
-
import { Fragment as Fragment10, jsx as
|
|
1568
|
+
import { Fragment as Fragment10, jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1323
1569
|
function ReportTitleBlock({ title }) {
|
|
1324
|
-
return /* @__PURE__ */
|
|
1325
|
-
/* @__PURE__ */
|
|
1326
|
-
/* @__PURE__ */
|
|
1327
|
-
/* @__PURE__ */
|
|
1570
|
+
return /* @__PURE__ */ jsxs21(Fragment10, { children: [
|
|
1571
|
+
/* @__PURE__ */ jsx34("h1", { children: title ?? "Story Report" }),
|
|
1572
|
+
/* @__PURE__ */ jsx34(ReportSummary, {}),
|
|
1573
|
+
/* @__PURE__ */ jsx34(ReportMeta, {})
|
|
1328
1574
|
] });
|
|
1329
1575
|
}
|
|
1330
1576
|
function ReportErrorShell({
|
|
@@ -1333,28 +1579,28 @@ function ReportErrorShell({
|
|
|
1333
1579
|
title,
|
|
1334
1580
|
dataTheme
|
|
1335
1581
|
}) {
|
|
1336
|
-
return /* @__PURE__ */
|
|
1582
|
+
return /* @__PURE__ */ jsx34("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx34(ReportSchemaError, { error }) });
|
|
1337
1583
|
}
|
|
1338
1584
|
|
|
1339
1585
|
// src/components/Report.tsx
|
|
1340
|
-
import { jsx as
|
|
1586
|
+
import { jsx as jsx35, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1341
1587
|
function Report(props) {
|
|
1342
1588
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1343
1589
|
const result = unwrapReport(report);
|
|
1344
1590
|
if (!result.ok) {
|
|
1345
|
-
return /* @__PURE__ */
|
|
1591
|
+
return /* @__PURE__ */ jsx35(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1346
1592
|
}
|
|
1347
1593
|
const data = result.data;
|
|
1348
1594
|
const hasContent = data.features.length > 0;
|
|
1349
|
-
return /* @__PURE__ */
|
|
1350
|
-
/* @__PURE__ */
|
|
1351
|
-
hasContent ? /* @__PURE__ */
|
|
1595
|
+
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: [
|
|
1596
|
+
/* @__PURE__ */ jsx35("header", { className: "es-report-header", children: /* @__PURE__ */ jsx35(ReportTitleBlock, { title }) }),
|
|
1597
|
+
hasContent ? /* @__PURE__ */ jsx35(ReportFeatureList, {}) : /* @__PURE__ */ jsx35(ReportEmpty, {})
|
|
1352
1598
|
] }) });
|
|
1353
1599
|
}
|
|
1354
1600
|
|
|
1355
1601
|
// src/components/doc/MermaidView.tsx
|
|
1356
1602
|
import { useEffect, useRef, useState as useState2 } from "react";
|
|
1357
|
-
import { jsx as
|
|
1603
|
+
import { jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1358
1604
|
function prefersDark(el) {
|
|
1359
1605
|
const themed = el?.closest("[data-theme]");
|
|
1360
1606
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -1391,9 +1637,9 @@ function MermaidView({ entry, load }) {
|
|
|
1391
1637
|
};
|
|
1392
1638
|
}, [entry.code, load]);
|
|
1393
1639
|
if (svg) {
|
|
1394
|
-
return /* @__PURE__ */
|
|
1395
|
-
entry.title ? /* @__PURE__ */
|
|
1396
|
-
/* @__PURE__ */
|
|
1640
|
+
return /* @__PURE__ */ jsxs23("figure", { ref, className: "my-3", children: [
|
|
1641
|
+
entry.title ? /* @__PURE__ */ jsx36("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
1642
|
+
/* @__PURE__ */ jsx36(
|
|
1397
1643
|
"div",
|
|
1398
1644
|
{
|
|
1399
1645
|
role: "img",
|
|
@@ -1404,18 +1650,18 @@ function MermaidView({ entry, load }) {
|
|
|
1404
1650
|
)
|
|
1405
1651
|
] });
|
|
1406
1652
|
}
|
|
1407
|
-
return /* @__PURE__ */
|
|
1653
|
+
return /* @__PURE__ */ jsx36(MermaidSource, { entry, ref });
|
|
1408
1654
|
}
|
|
1409
1655
|
|
|
1410
1656
|
// src/components/doc/MermaidDiagram.tsx
|
|
1411
|
-
import { jsx as
|
|
1657
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
1412
1658
|
var mermaidLoader;
|
|
1413
1659
|
function loadMermaid() {
|
|
1414
1660
|
mermaidLoader ??= import("mermaid").then((m) => m.default);
|
|
1415
1661
|
return mermaidLoader;
|
|
1416
1662
|
}
|
|
1417
1663
|
function MermaidDiagram({ entry, load = loadMermaid }) {
|
|
1418
|
-
return /* @__PURE__ */
|
|
1664
|
+
return /* @__PURE__ */ jsx37(MermaidView, { entry, load });
|
|
1419
1665
|
}
|
|
1420
1666
|
|
|
1421
1667
|
// src/components/ScenarioExplorer.tsx
|
|
@@ -1425,12 +1671,12 @@ import { useState as useState3 } from "react";
|
|
|
1425
1671
|
import "react";
|
|
1426
1672
|
import { Command as CommandPrimitive } from "cmdk";
|
|
1427
1673
|
import { SearchIcon } from "lucide-react";
|
|
1428
|
-
import { jsx as
|
|
1674
|
+
import { jsx as jsx38, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1429
1675
|
function Command({
|
|
1430
1676
|
className,
|
|
1431
1677
|
...props
|
|
1432
1678
|
}) {
|
|
1433
|
-
return /* @__PURE__ */
|
|
1679
|
+
return /* @__PURE__ */ jsx38(
|
|
1434
1680
|
CommandPrimitive,
|
|
1435
1681
|
{
|
|
1436
1682
|
"data-slot": "command",
|
|
@@ -1446,14 +1692,14 @@ function CommandInput({
|
|
|
1446
1692
|
className,
|
|
1447
1693
|
...props
|
|
1448
1694
|
}) {
|
|
1449
|
-
return /* @__PURE__ */
|
|
1695
|
+
return /* @__PURE__ */ jsxs24(
|
|
1450
1696
|
"div",
|
|
1451
1697
|
{
|
|
1452
1698
|
"data-slot": "command-input-wrapper",
|
|
1453
1699
|
className: "flex h-9 items-center gap-2 border-b px-3",
|
|
1454
1700
|
children: [
|
|
1455
|
-
/* @__PURE__ */
|
|
1456
|
-
/* @__PURE__ */
|
|
1701
|
+
/* @__PURE__ */ jsx38(SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
|
|
1702
|
+
/* @__PURE__ */ jsx38(
|
|
1457
1703
|
CommandPrimitive.Input,
|
|
1458
1704
|
{
|
|
1459
1705
|
"data-slot": "command-input",
|
|
@@ -1472,7 +1718,7 @@ function CommandList({
|
|
|
1472
1718
|
className,
|
|
1473
1719
|
...props
|
|
1474
1720
|
}) {
|
|
1475
|
-
return /* @__PURE__ */
|
|
1721
|
+
return /* @__PURE__ */ jsx38(
|
|
1476
1722
|
CommandPrimitive.List,
|
|
1477
1723
|
{
|
|
1478
1724
|
"data-slot": "command-list",
|
|
@@ -1487,7 +1733,7 @@ function CommandList({
|
|
|
1487
1733
|
function CommandEmpty({
|
|
1488
1734
|
...props
|
|
1489
1735
|
}) {
|
|
1490
|
-
return /* @__PURE__ */
|
|
1736
|
+
return /* @__PURE__ */ jsx38(
|
|
1491
1737
|
CommandPrimitive.Empty,
|
|
1492
1738
|
{
|
|
1493
1739
|
"data-slot": "command-empty",
|
|
@@ -1500,7 +1746,7 @@ function CommandGroup({
|
|
|
1500
1746
|
className,
|
|
1501
1747
|
...props
|
|
1502
1748
|
}) {
|
|
1503
|
-
return /* @__PURE__ */
|
|
1749
|
+
return /* @__PURE__ */ jsx38(
|
|
1504
1750
|
CommandPrimitive.Group,
|
|
1505
1751
|
{
|
|
1506
1752
|
"data-slot": "command-group",
|
|
@@ -1516,7 +1762,7 @@ function CommandItem({
|
|
|
1516
1762
|
className,
|
|
1517
1763
|
...props
|
|
1518
1764
|
}) {
|
|
1519
|
-
return /* @__PURE__ */
|
|
1765
|
+
return /* @__PURE__ */ jsx38(
|
|
1520
1766
|
CommandPrimitive.Item,
|
|
1521
1767
|
{
|
|
1522
1768
|
"data-slot": "command-item",
|
|
@@ -1530,7 +1776,7 @@ function CommandItem({
|
|
|
1530
1776
|
}
|
|
1531
1777
|
|
|
1532
1778
|
// src/components/ScenarioExplorer.tsx
|
|
1533
|
-
import { jsx as
|
|
1779
|
+
import { jsx as jsx39, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1534
1780
|
var STATUS_FILTERS = [
|
|
1535
1781
|
{ value: "all", label: "All" },
|
|
1536
1782
|
{ value: "passed", label: "Passed" },
|
|
@@ -1541,22 +1787,22 @@ var STATUS_FILTERS = [
|
|
|
1541
1787
|
function ScenarioExplorer({ scenarios, summary }) {
|
|
1542
1788
|
const [status, setStatus] = useState3("all");
|
|
1543
1789
|
const visible = status === "all" ? scenarios : scenarios.filter((s) => s.status === status);
|
|
1544
|
-
return /* @__PURE__ */
|
|
1545
|
-
summary ? /* @__PURE__ */
|
|
1790
|
+
return /* @__PURE__ */ jsxs25("div", { className: "font-sans text-foreground", children: [
|
|
1791
|
+
summary ? /* @__PURE__ */ jsxs25("p", { className: "mb-3 text-sm text-muted-foreground", children: [
|
|
1546
1792
|
summary.total,
|
|
1547
1793
|
" scenarios \xB7 ",
|
|
1548
|
-
/* @__PURE__ */
|
|
1794
|
+
/* @__PURE__ */ jsxs25("span", { className: "text-pass", children: [
|
|
1549
1795
|
summary.passed,
|
|
1550
1796
|
" passed"
|
|
1551
1797
|
] }),
|
|
1552
1798
|
" \xB7",
|
|
1553
1799
|
" ",
|
|
1554
|
-
/* @__PURE__ */
|
|
1800
|
+
/* @__PURE__ */ jsxs25("span", { className: "text-fail", children: [
|
|
1555
1801
|
summary.failed,
|
|
1556
1802
|
" failed"
|
|
1557
1803
|
] })
|
|
1558
1804
|
] }) : null,
|
|
1559
|
-
/* @__PURE__ */
|
|
1805
|
+
/* @__PURE__ */ jsx39("div", { className: "mb-2 flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by status", children: STATUS_FILTERS.map((f) => /* @__PURE__ */ jsx39(
|
|
1560
1806
|
"button",
|
|
1561
1807
|
{
|
|
1562
1808
|
type: "button",
|
|
@@ -1571,26 +1817,26 @@ function ScenarioExplorer({ scenarios, summary }) {
|
|
|
1571
1817
|
},
|
|
1572
1818
|
f.value
|
|
1573
1819
|
)) }),
|
|
1574
|
-
/* @__PURE__ */
|
|
1820
|
+
/* @__PURE__ */ jsxs25(
|
|
1575
1821
|
Command,
|
|
1576
1822
|
{
|
|
1577
1823
|
className: "rounded-lg border border-border bg-card",
|
|
1578
1824
|
filter: (value, search) => value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0,
|
|
1579
1825
|
children: [
|
|
1580
|
-
/* @__PURE__ */
|
|
1581
|
-
/* @__PURE__ */
|
|
1582
|
-
/* @__PURE__ */
|
|
1583
|
-
/* @__PURE__ */
|
|
1826
|
+
/* @__PURE__ */ jsx39(CommandInput, { placeholder: "Search scenarios\u2026" }),
|
|
1827
|
+
/* @__PURE__ */ jsxs25(CommandList, { className: "max-h-none", children: [
|
|
1828
|
+
/* @__PURE__ */ jsx39(CommandEmpty, { children: "No scenarios match your filters." }),
|
|
1829
|
+
/* @__PURE__ */ jsx39(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ jsx39(
|
|
1584
1830
|
CommandItem,
|
|
1585
1831
|
{
|
|
1586
1832
|
value: `${s.title} ${s.feature} ${s.tags.join(" ")}`,
|
|
1587
1833
|
asChild: true,
|
|
1588
1834
|
className: "cursor-pointer",
|
|
1589
|
-
children: /* @__PURE__ */
|
|
1590
|
-
/* @__PURE__ */
|
|
1591
|
-
/* @__PURE__ */
|
|
1592
|
-
s.tags.slice(0, 3).map((t) => /* @__PURE__ */
|
|
1593
|
-
/* @__PURE__ */
|
|
1835
|
+
children: /* @__PURE__ */ jsxs25("a", { href: s.href, className: "flex items-center gap-3", children: [
|
|
1836
|
+
/* @__PURE__ */ jsx39(Badge, { variant: s.status, children: s.status }),
|
|
1837
|
+
/* @__PURE__ */ jsx39("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
|
|
1838
|
+
s.tags.slice(0, 3).map((t) => /* @__PURE__ */ jsx39(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
|
|
1839
|
+
/* @__PURE__ */ jsx39("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
|
|
1594
1840
|
] })
|
|
1595
1841
|
},
|
|
1596
1842
|
s.id
|
|
@@ -2086,6 +2332,9 @@ var story_report_v1_default = {
|
|
|
2086
2332
|
{
|
|
2087
2333
|
$ref: "#/$defs/DocHtml"
|
|
2088
2334
|
},
|
|
2335
|
+
{
|
|
2336
|
+
$ref: "#/$defs/DocState"
|
|
2337
|
+
},
|
|
2089
2338
|
{
|
|
2090
2339
|
$ref: "#/$defs/DocCustom"
|
|
2091
2340
|
}
|
|
@@ -2461,6 +2710,33 @@ var story_report_v1_default = {
|
|
|
2461
2710
|
}
|
|
2462
2711
|
]
|
|
2463
2712
|
},
|
|
2713
|
+
DocState: {
|
|
2714
|
+
type: "object",
|
|
2715
|
+
properties: {
|
|
2716
|
+
kind: {
|
|
2717
|
+
const: "state"
|
|
2718
|
+
},
|
|
2719
|
+
label: {
|
|
2720
|
+
type: "string"
|
|
2721
|
+
},
|
|
2722
|
+
value: {},
|
|
2723
|
+
phase: {
|
|
2724
|
+
$ref: "#/$defs/DocPhase"
|
|
2725
|
+
},
|
|
2726
|
+
children: {
|
|
2727
|
+
type: "array",
|
|
2728
|
+
items: {
|
|
2729
|
+
$ref: "#/$defs/DocEntry"
|
|
2730
|
+
}
|
|
2731
|
+
}
|
|
2732
|
+
},
|
|
2733
|
+
required: [
|
|
2734
|
+
"kind",
|
|
2735
|
+
"value",
|
|
2736
|
+
"phase"
|
|
2737
|
+
],
|
|
2738
|
+
additionalProperties: false
|
|
2739
|
+
},
|
|
2464
2740
|
DocCustom: {
|
|
2465
2741
|
type: "object",
|
|
2466
2742
|
properties: {
|
|
@@ -2610,6 +2886,7 @@ export {
|
|
|
2610
2886
|
ReportSchemaError,
|
|
2611
2887
|
ReportStepItem,
|
|
2612
2888
|
ReportSteps,
|
|
2889
|
+
ReportStoryboard,
|
|
2613
2890
|
ReportSummary,
|
|
2614
2891
|
ReportSummaryView,
|
|
2615
2892
|
ReportTrace,
|