executable-stories-react 0.10.1 → 0.11.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 +183 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +183 -102
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +229 -187
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.js +229 -187
- package/dist/interactive.js.map +1 -1
- package/dist/parse.cjs +40 -1
- package/dist/parse.cjs.map +1 -1
- package/dist/parse.js +40 -1
- package/dist/parse.js.map +1 -1
- package/dist/report-island.global.js +23 -21
- package/dist/ssr.cjs +109 -67
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.js +109 -67
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -470,21 +470,29 @@ function DocLink({ entry }) {
|
|
|
470
470
|
);
|
|
471
471
|
}
|
|
472
472
|
|
|
473
|
-
// src/
|
|
473
|
+
// src/lib/markdown.ts
|
|
474
474
|
var import_marked = require("marked");
|
|
475
475
|
|
|
476
476
|
// src/lib/url.ts
|
|
477
477
|
var import_url = require("executable-stories-core/utils/url");
|
|
478
478
|
|
|
479
|
-
// src/
|
|
480
|
-
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
481
|
-
function neutralizeUrl(value) {
|
|
482
|
-
return (0, import_url.safeUrl)(value) ?? "#";
|
|
483
|
-
}
|
|
479
|
+
// src/lib/markdown.ts
|
|
484
480
|
function safeMarkdownHtml(markdown) {
|
|
485
481
|
const raw = import_marked.marked.parse(markdown, { async: false });
|
|
486
482
|
return raw.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<\/?(?:iframe|object|embed|form|base)\b[^>]*>/gi, "").replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, "").replace(/\son[a-z]+\s*=\s*'[^']*'/gi, "").replace(/\son[a-z]+\s*=\s*[^\s>]+/gi, "").replace(/(href|src)\s*=\s*"([^"]*)"/gi, (_m, attr, val) => `${attr}="${neutralizeUrl(val)}"`).replace(/(href|src)\s*=\s*'([^']*)'/gi, (_m, attr, val) => `${attr}='${neutralizeUrl(val)}'`);
|
|
487
483
|
}
|
|
484
|
+
function dedent(text) {
|
|
485
|
+
const lines = text.replace(/\t/g, " ").split("\n");
|
|
486
|
+
const indents = lines.filter((line) => line.trim().length > 0).map((line) => line.length - line.trimStart().length);
|
|
487
|
+
const shortest = indents.length > 0 ? Math.min(...indents) : 0;
|
|
488
|
+
return lines.map((line) => line.slice(shortest)).join("\n").trim();
|
|
489
|
+
}
|
|
490
|
+
function neutralizeUrl(value) {
|
|
491
|
+
return (0, import_url.safeUrl)(value) ?? "#";
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// src/components/doc/DocSection.tsx
|
|
495
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
488
496
|
function DocSection({ entry }) {
|
|
489
497
|
const renderers = useBuiltinRenderers();
|
|
490
498
|
if (renderers.section) {
|
|
@@ -1361,8 +1369,35 @@ function ReportScenarioList({ feature }) {
|
|
|
1361
1369
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_jsx_runtime27.Fragment, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportScenario, { scenario }, scenario.id)) });
|
|
1362
1370
|
}
|
|
1363
1371
|
|
|
1364
|
-
// src/components/
|
|
1372
|
+
// src/components/ReportFeatureIntro.tsx
|
|
1365
1373
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1374
|
+
function ReportFeatureIntro({ feature }) {
|
|
1375
|
+
const hasNarrative = Boolean(feature.narrative?.trim());
|
|
1376
|
+
const hasGlossary = Boolean(feature.glossary?.length);
|
|
1377
|
+
if (!hasNarrative && !hasGlossary) return null;
|
|
1378
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col gap-3 border-l-2 border-border pl-4 text-sm", children: [
|
|
1379
|
+
hasNarrative ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
1380
|
+
"div",
|
|
1381
|
+
{
|
|
1382
|
+
className: "es-doc-prose prose prose-sm max-w-none text-muted-foreground",
|
|
1383
|
+
dangerouslySetInnerHTML: { __html: safeMarkdownHtml(dedent(feature.narrative)) }
|
|
1384
|
+
}
|
|
1385
|
+
) : null,
|
|
1386
|
+
hasGlossary ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("dl", { className: "grid gap-1.5", "aria-label": "Glossary", children: feature.glossary.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-wrap gap-x-2 text-xs", children: [
|
|
1387
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("dt", { className: "font-medium text-foreground", children: entry.term }),
|
|
1388
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("dd", { className: "flex-1 text-muted-foreground", children: entry.definition })
|
|
1389
|
+
] }, entry.term)) }) : null
|
|
1390
|
+
] });
|
|
1391
|
+
}
|
|
1392
|
+
function featureKindLabel(kind) {
|
|
1393
|
+
if (kind === "ability") return "Ability";
|
|
1394
|
+
if (kind === "business-need") return "Business need";
|
|
1395
|
+
if (kind === "feature") return "Feature";
|
|
1396
|
+
return null;
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
// src/components/ReportFeature.tsx
|
|
1400
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1366
1401
|
function ReportFeature({ feature }) {
|
|
1367
1402
|
const titleId = `${feature.id}-title`;
|
|
1368
1403
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1370,10 +1405,11 @@ function ReportFeature({ feature }) {
|
|
|
1370
1405
|
const skipped = s.skipped + s.pending;
|
|
1371
1406
|
const collapse = useCollapse();
|
|
1372
1407
|
const collapsed = collapse?.isCollapsed(feature.id) ?? false;
|
|
1408
|
+
const kindLabel = featureKindLabel(feature.kind);
|
|
1373
1409
|
return (
|
|
1374
1410
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
1375
1411
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1376
|
-
/* @__PURE__ */ (0,
|
|
1412
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
1377
1413
|
"section",
|
|
1378
1414
|
{
|
|
1379
1415
|
id: feature.id,
|
|
@@ -1381,9 +1417,9 @@ function ReportFeature({ feature }) {
|
|
|
1381
1417
|
"aria-labelledby": titleId,
|
|
1382
1418
|
className: "flex flex-col gap-3",
|
|
1383
1419
|
children: [
|
|
1384
|
-
/* @__PURE__ */ (0,
|
|
1385
|
-
/* @__PURE__ */ (0,
|
|
1386
|
-
/* @__PURE__ */ (0,
|
|
1420
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1421
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "min-w-0", children: [
|
|
1422
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
1387
1423
|
"button",
|
|
1388
1424
|
{
|
|
1389
1425
|
type: "button",
|
|
@@ -1392,31 +1428,34 @@ function ReportFeature({ feature }) {
|
|
|
1392
1428
|
"aria-controls": bodyId,
|
|
1393
1429
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1394
1430
|
children: [
|
|
1395
|
-
/* @__PURE__ */ (0,
|
|
1396
|
-
/* @__PURE__ */ (0,
|
|
1431
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
|
|
1432
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "truncate", children: feature.title })
|
|
1397
1433
|
]
|
|
1398
1434
|
}
|
|
1399
1435
|
) : feature.title }),
|
|
1400
|
-
/* @__PURE__ */ (0,
|
|
1436
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("p", { className: cn("mt-0.5 flex items-center gap-2 text-xs text-muted-foreground", collapse && "pl-5"), children: [
|
|
1437
|
+
kindLabel ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "shrink-0 rounded-sm bg-muted px-1.5 py-0.5 font-medium text-foreground", children: kindLabel }) : null,
|
|
1438
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "truncate font-mono", children: feature.sourceFile })
|
|
1439
|
+
] })
|
|
1401
1440
|
] }),
|
|
1402
|
-
/* @__PURE__ */ (0,
|
|
1441
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
1403
1442
|
"p",
|
|
1404
1443
|
{
|
|
1405
1444
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1406
1445
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1407
1446
|
children: [
|
|
1408
|
-
/* @__PURE__ */ (0,
|
|
1447
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { children: [
|
|
1409
1448
|
s.passed,
|
|
1410
1449
|
" passed"
|
|
1411
1450
|
] }),
|
|
1412
|
-
/* @__PURE__ */ (0,
|
|
1413
|
-
/* @__PURE__ */ (0,
|
|
1451
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1452
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1414
1453
|
s.failed,
|
|
1415
1454
|
" failed"
|
|
1416
1455
|
] }),
|
|
1417
|
-
skipped > 0 ? /* @__PURE__ */ (0,
|
|
1418
|
-
/* @__PURE__ */ (0,
|
|
1419
|
-
/* @__PURE__ */ (0,
|
|
1456
|
+
skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
|
|
1457
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1458
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { children: [
|
|
1420
1459
|
skipped,
|
|
1421
1460
|
" skipped"
|
|
1422
1461
|
] })
|
|
@@ -1425,7 +1464,10 @@ function ReportFeature({ feature }) {
|
|
|
1425
1464
|
}
|
|
1426
1465
|
)
|
|
1427
1466
|
] }),
|
|
1428
|
-
/* @__PURE__ */ (0,
|
|
1467
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: [
|
|
1468
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ReportFeatureIntro, { feature }),
|
|
1469
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ReportScenarioList, { feature })
|
|
1470
|
+
] })
|
|
1429
1471
|
]
|
|
1430
1472
|
}
|
|
1431
1473
|
)
|
|
@@ -1433,17 +1475,17 @@ function ReportFeature({ feature }) {
|
|
|
1433
1475
|
}
|
|
1434
1476
|
|
|
1435
1477
|
// src/components/ReportFeatureList.tsx
|
|
1436
|
-
var
|
|
1478
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1437
1479
|
function ReportFeatureList() {
|
|
1438
1480
|
const report = useReport();
|
|
1439
|
-
return /* @__PURE__ */ (0,
|
|
1481
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ReportFeature, { feature }, feature.id)) });
|
|
1440
1482
|
}
|
|
1441
1483
|
|
|
1442
1484
|
// src/components/ui/empty.tsx
|
|
1443
1485
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
1444
|
-
var
|
|
1486
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1445
1487
|
function Empty({ className, ...props }) {
|
|
1446
|
-
return /* @__PURE__ */ (0,
|
|
1488
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1447
1489
|
"div",
|
|
1448
1490
|
{
|
|
1449
1491
|
"data-slot": "empty",
|
|
@@ -1456,7 +1498,7 @@ function Empty({ className, ...props }) {
|
|
|
1456
1498
|
);
|
|
1457
1499
|
}
|
|
1458
1500
|
function EmptyHeader({ className, ...props }) {
|
|
1459
|
-
return /* @__PURE__ */ (0,
|
|
1501
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1460
1502
|
"div",
|
|
1461
1503
|
{
|
|
1462
1504
|
"data-slot": "empty-header",
|
|
@@ -1483,7 +1525,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
|
|
|
1483
1525
|
}
|
|
1484
1526
|
);
|
|
1485
1527
|
function EmptyTitle({ className, ...props }) {
|
|
1486
|
-
return /* @__PURE__ */ (0,
|
|
1528
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1487
1529
|
"div",
|
|
1488
1530
|
{
|
|
1489
1531
|
"data-slot": "empty-title",
|
|
@@ -1494,16 +1536,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1494
1536
|
}
|
|
1495
1537
|
|
|
1496
1538
|
// src/components/ReportEmpty.tsx
|
|
1497
|
-
var
|
|
1539
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1498
1540
|
function ReportEmpty({ message }) {
|
|
1499
|
-
return /* @__PURE__ */ (0,
|
|
1541
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(EmptyHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
|
|
1500
1542
|
}
|
|
1501
1543
|
|
|
1502
1544
|
// src/components/ReportSummary.tsx
|
|
1503
|
-
var
|
|
1545
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1504
1546
|
function ReportSummary({ className }) {
|
|
1505
1547
|
const report = useReport();
|
|
1506
|
-
return /* @__PURE__ */ (0,
|
|
1548
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
1507
1549
|
ReportSummaryView,
|
|
1508
1550
|
{
|
|
1509
1551
|
summary: report.summary,
|
|
@@ -1529,7 +1571,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1529
1571
|
if (summary.pending > 0) {
|
|
1530
1572
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1531
1573
|
}
|
|
1532
|
-
return /* @__PURE__ */ (0,
|
|
1574
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
1533
1575
|
"dl",
|
|
1534
1576
|
{
|
|
1535
1577
|
className: cn(
|
|
@@ -1542,17 +1584,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1542
1584
|
"aria-label": ariaLabel,
|
|
1543
1585
|
children: cards.map((c) => {
|
|
1544
1586
|
const tone = TONE[c.status];
|
|
1545
|
-
return /* @__PURE__ */ (0,
|
|
1587
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
1546
1588
|
"div",
|
|
1547
1589
|
{
|
|
1548
1590
|
"data-status": c.status,
|
|
1549
1591
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1550
1592
|
children: [
|
|
1551
|
-
/* @__PURE__ */ (0,
|
|
1552
|
-
/* @__PURE__ */ (0,
|
|
1593
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
|
|
1594
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1553
1595
|
c.label
|
|
1554
1596
|
] }),
|
|
1555
|
-
/* @__PURE__ */ (0,
|
|
1597
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
|
|
1556
1598
|
]
|
|
1557
1599
|
},
|
|
1558
1600
|
c.status
|
|
@@ -1615,7 +1657,7 @@ function prUrl(ci) {
|
|
|
1615
1657
|
}
|
|
1616
1658
|
|
|
1617
1659
|
// src/components/ReportMeta.tsx
|
|
1618
|
-
var
|
|
1660
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1619
1661
|
function ReportMeta() {
|
|
1620
1662
|
const report = useReport();
|
|
1621
1663
|
const items = [];
|
|
@@ -1638,13 +1680,13 @@ function ReportMeta() {
|
|
|
1638
1680
|
const short = sha.slice(0, 8);
|
|
1639
1681
|
items.push({
|
|
1640
1682
|
label: "Commit",
|
|
1641
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1683
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1642
1684
|
});
|
|
1643
1685
|
}
|
|
1644
1686
|
if (report.ci) {
|
|
1645
1687
|
items.push({
|
|
1646
1688
|
label: "CI",
|
|
1647
|
-
value: report.ci.url ? /* @__PURE__ */ (0,
|
|
1689
|
+
value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1648
1690
|
ciDisplayName(report.ci.name),
|
|
1649
1691
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1650
1692
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1655,7 +1697,7 @@ function ReportMeta() {
|
|
|
1655
1697
|
const label = `#${report.ci.prNumber}`;
|
|
1656
1698
|
items.push({
|
|
1657
1699
|
label: "PR",
|
|
1658
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1700
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1659
1701
|
});
|
|
1660
1702
|
}
|
|
1661
1703
|
if (items.length === 0) return null;
|
|
@@ -1663,48 +1705,48 @@ function ReportMeta() {
|
|
|
1663
1705
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1664
1706
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1665
1707
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1666
|
-
/* @__PURE__ */ (0,
|
|
1667
|
-
/* @__PURE__ */ (0,
|
|
1668
|
-
/* @__PURE__ */ (0,
|
|
1708
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
|
|
1709
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("summary", { className: "flex cursor-pointer list-none select-none items-center gap-1.5 px-4 py-2 font-medium text-muted-foreground [&::-webkit-details-marker]:hidden", children: [
|
|
1710
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1669
1711
|
"Run details"
|
|
1670
1712
|
] }),
|
|
1671
|
-
/* @__PURE__ */ (0,
|
|
1672
|
-
/* @__PURE__ */ (0,
|
|
1673
|
-
/* @__PURE__ */ (0,
|
|
1713
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("dl", { className: "flex flex-wrap gap-x-5 gap-y-2 border-t border-border px-4 py-3 text-muted-foreground", "aria-label": "Run metadata", children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-baseline gap-1.5", children: [
|
|
1714
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("dt", { className: "font-medium", children: item.label }),
|
|
1715
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1674
1716
|
] }, item.label)) })
|
|
1675
1717
|
] })
|
|
1676
1718
|
);
|
|
1677
1719
|
}
|
|
1678
1720
|
|
|
1679
1721
|
// src/components/ReportSchemaError.tsx
|
|
1680
|
-
var
|
|
1722
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
1681
1723
|
function ReportSchemaError({ error }) {
|
|
1682
|
-
return /* @__PURE__ */ (0,
|
|
1683
|
-
/* @__PURE__ */ (0,
|
|
1684
|
-
/* @__PURE__ */ (0,
|
|
1685
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0,
|
|
1724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1725
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("strong", { children: "Report could not be displayed." }) }),
|
|
1726
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { children: error.message }),
|
|
1727
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("p", { children: [
|
|
1686
1728
|
"The report bundle is newer than this version of ",
|
|
1687
|
-
/* @__PURE__ */ (0,
|
|
1729
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("code", { children: "executable-stories-react" }),
|
|
1688
1730
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1689
1731
|
] }) : null,
|
|
1690
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0,
|
|
1691
|
-
/* @__PURE__ */ (0,
|
|
1732
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("details", { children: [
|
|
1733
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("summary", { children: [
|
|
1692
1734
|
error.issues.length,
|
|
1693
1735
|
" validation issue",
|
|
1694
1736
|
error.issues.length === 1 ? "" : "s"
|
|
1695
1737
|
] }),
|
|
1696
|
-
/* @__PURE__ */ (0,
|
|
1738
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1697
1739
|
] }) : null
|
|
1698
1740
|
] });
|
|
1699
1741
|
}
|
|
1700
1742
|
|
|
1701
1743
|
// src/components/ReportShell.tsx
|
|
1702
|
-
var
|
|
1744
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
1703
1745
|
function ReportTitleBlock({ title }) {
|
|
1704
|
-
return /* @__PURE__ */ (0,
|
|
1705
|
-
/* @__PURE__ */ (0,
|
|
1706
|
-
/* @__PURE__ */ (0,
|
|
1707
|
-
/* @__PURE__ */ (0,
|
|
1746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
1747
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("h1", { children: title ?? "Story Report" }),
|
|
1748
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportSummary, {}),
|
|
1749
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportMeta, {})
|
|
1708
1750
|
] });
|
|
1709
1751
|
}
|
|
1710
1752
|
function ReportErrorShell({
|
|
@@ -1713,28 +1755,28 @@ function ReportErrorShell({
|
|
|
1713
1755
|
title,
|
|
1714
1756
|
dataTheme
|
|
1715
1757
|
}) {
|
|
1716
|
-
return /* @__PURE__ */ (0,
|
|
1758
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ReportSchemaError, { error }) });
|
|
1717
1759
|
}
|
|
1718
1760
|
|
|
1719
1761
|
// src/components/Report.tsx
|
|
1720
|
-
var
|
|
1762
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
1721
1763
|
function Report(props) {
|
|
1722
1764
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1723
1765
|
const result = unwrapReport(report);
|
|
1724
1766
|
if (!result.ok) {
|
|
1725
|
-
return /* @__PURE__ */ (0,
|
|
1767
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1726
1768
|
}
|
|
1727
1769
|
const data = result.data;
|
|
1728
1770
|
const hasContent = data.features.length > 0;
|
|
1729
|
-
return /* @__PURE__ */ (0,
|
|
1730
|
-
/* @__PURE__ */ (0,
|
|
1731
|
-
hasContent ? /* @__PURE__ */ (0,
|
|
1771
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1772
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportTitleBlock, { title }) }),
|
|
1773
|
+
hasContent ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportEmpty, {})
|
|
1732
1774
|
] }) });
|
|
1733
1775
|
}
|
|
1734
1776
|
|
|
1735
1777
|
// src/components/doc/MermaidView.tsx
|
|
1736
1778
|
var import_react8 = require("react");
|
|
1737
|
-
var
|
|
1779
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
1738
1780
|
function prefersDark(el) {
|
|
1739
1781
|
const themed = el?.closest("[data-theme]");
|
|
1740
1782
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -1788,9 +1830,9 @@ function MermaidView({ entry, load }) {
|
|
|
1788
1830
|
};
|
|
1789
1831
|
}, [entry.code, load]);
|
|
1790
1832
|
if (svg) {
|
|
1791
|
-
return /* @__PURE__ */ (0,
|
|
1792
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
1793
|
-
/* @__PURE__ */ (0,
|
|
1833
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("figure", { ref, className: "my-3", children: [
|
|
1834
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
1835
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
1794
1836
|
"div",
|
|
1795
1837
|
{
|
|
1796
1838
|
role: "img",
|
|
@@ -1801,8 +1843,8 @@ function MermaidView({ entry, load }) {
|
|
|
1801
1843
|
)
|
|
1802
1844
|
] });
|
|
1803
1845
|
}
|
|
1804
|
-
return /* @__PURE__ */ (0,
|
|
1805
|
-
error ? /* @__PURE__ */ (0,
|
|
1846
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_jsx_runtime38.Fragment, { children: [
|
|
1847
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
1806
1848
|
"p",
|
|
1807
1849
|
{
|
|
1808
1850
|
role: "alert",
|
|
@@ -1814,19 +1856,19 @@ function MermaidView({ entry, load }) {
|
|
|
1814
1856
|
]
|
|
1815
1857
|
}
|
|
1816
1858
|
) : null,
|
|
1817
|
-
/* @__PURE__ */ (0,
|
|
1859
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(MermaidSource, { entry, ref })
|
|
1818
1860
|
] });
|
|
1819
1861
|
}
|
|
1820
1862
|
|
|
1821
1863
|
// src/components/doc/MermaidDiagram.tsx
|
|
1822
|
-
var
|
|
1864
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
1823
1865
|
var mermaidLoader;
|
|
1824
1866
|
function loadMermaid() {
|
|
1825
1867
|
mermaidLoader ??= import("mermaid").then((m) => m.default);
|
|
1826
1868
|
return mermaidLoader;
|
|
1827
1869
|
}
|
|
1828
1870
|
function MermaidDiagram({ entry, load = loadMermaid }) {
|
|
1829
|
-
return /* @__PURE__ */ (0,
|
|
1871
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(MermaidView, { entry, load });
|
|
1830
1872
|
}
|
|
1831
1873
|
|
|
1832
1874
|
// src/components/ScenarioExplorer.tsx
|
|
@@ -1836,12 +1878,12 @@ var import_react9 = require("react");
|
|
|
1836
1878
|
var React4 = require("react");
|
|
1837
1879
|
var import_cmdk = require("cmdk");
|
|
1838
1880
|
var import_lucide_react3 = require("lucide-react");
|
|
1839
|
-
var
|
|
1881
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
1840
1882
|
function Command({
|
|
1841
1883
|
className,
|
|
1842
1884
|
...props
|
|
1843
1885
|
}) {
|
|
1844
|
-
return /* @__PURE__ */ (0,
|
|
1886
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
1845
1887
|
import_cmdk.Command,
|
|
1846
1888
|
{
|
|
1847
1889
|
"data-slot": "command",
|
|
@@ -1857,14 +1899,14 @@ function CommandInput({
|
|
|
1857
1899
|
className,
|
|
1858
1900
|
...props
|
|
1859
1901
|
}) {
|
|
1860
|
-
return /* @__PURE__ */ (0,
|
|
1902
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
1861
1903
|
"div",
|
|
1862
1904
|
{
|
|
1863
1905
|
"data-slot": "command-input-wrapper",
|
|
1864
1906
|
className: "flex h-9 items-center gap-2 border-b px-3",
|
|
1865
1907
|
children: [
|
|
1866
|
-
/* @__PURE__ */ (0,
|
|
1867
|
-
/* @__PURE__ */ (0,
|
|
1908
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react3.SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
|
|
1909
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
1868
1910
|
import_cmdk.Command.Input,
|
|
1869
1911
|
{
|
|
1870
1912
|
"data-slot": "command-input",
|
|
@@ -1883,7 +1925,7 @@ function CommandList({
|
|
|
1883
1925
|
className,
|
|
1884
1926
|
...props
|
|
1885
1927
|
}) {
|
|
1886
|
-
return /* @__PURE__ */ (0,
|
|
1928
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
1887
1929
|
import_cmdk.Command.List,
|
|
1888
1930
|
{
|
|
1889
1931
|
"data-slot": "command-list",
|
|
@@ -1898,7 +1940,7 @@ function CommandList({
|
|
|
1898
1940
|
function CommandEmpty({
|
|
1899
1941
|
...props
|
|
1900
1942
|
}) {
|
|
1901
|
-
return /* @__PURE__ */ (0,
|
|
1943
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
1902
1944
|
import_cmdk.Command.Empty,
|
|
1903
1945
|
{
|
|
1904
1946
|
"data-slot": "command-empty",
|
|
@@ -1911,7 +1953,7 @@ function CommandGroup({
|
|
|
1911
1953
|
className,
|
|
1912
1954
|
...props
|
|
1913
1955
|
}) {
|
|
1914
|
-
return /* @__PURE__ */ (0,
|
|
1956
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
1915
1957
|
import_cmdk.Command.Group,
|
|
1916
1958
|
{
|
|
1917
1959
|
"data-slot": "command-group",
|
|
@@ -1927,7 +1969,7 @@ function CommandItem({
|
|
|
1927
1969
|
className,
|
|
1928
1970
|
...props
|
|
1929
1971
|
}) {
|
|
1930
|
-
return /* @__PURE__ */ (0,
|
|
1972
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
1931
1973
|
import_cmdk.Command.Item,
|
|
1932
1974
|
{
|
|
1933
1975
|
"data-slot": "command-item",
|
|
@@ -1941,7 +1983,7 @@ function CommandItem({
|
|
|
1941
1983
|
}
|
|
1942
1984
|
|
|
1943
1985
|
// src/components/ScenarioExplorer.tsx
|
|
1944
|
-
var
|
|
1986
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
1945
1987
|
var STATUS_FILTERS = [
|
|
1946
1988
|
{ value: "all", label: "All" },
|
|
1947
1989
|
{ value: "passed", label: "Passed" },
|
|
@@ -1952,22 +1994,22 @@ var STATUS_FILTERS = [
|
|
|
1952
1994
|
function ScenarioExplorer({ scenarios, summary }) {
|
|
1953
1995
|
const [status, setStatus] = (0, import_react9.useState)("all");
|
|
1954
1996
|
const visible = status === "all" ? scenarios : scenarios.filter((s) => s.status === status);
|
|
1955
|
-
return /* @__PURE__ */ (0,
|
|
1956
|
-
summary ? /* @__PURE__ */ (0,
|
|
1997
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "font-sans text-foreground", children: [
|
|
1998
|
+
summary ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("p", { className: "mb-3 text-sm text-muted-foreground", children: [
|
|
1957
1999
|
summary.total,
|
|
1958
2000
|
" scenarios \xB7 ",
|
|
1959
|
-
/* @__PURE__ */ (0,
|
|
2001
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "text-pass", children: [
|
|
1960
2002
|
summary.passed,
|
|
1961
2003
|
" passed"
|
|
1962
2004
|
] }),
|
|
1963
2005
|
" \xB7",
|
|
1964
2006
|
" ",
|
|
1965
|
-
/* @__PURE__ */ (0,
|
|
2007
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "text-fail", children: [
|
|
1966
2008
|
summary.failed,
|
|
1967
2009
|
" failed"
|
|
1968
2010
|
] })
|
|
1969
2011
|
] }) : null,
|
|
1970
|
-
/* @__PURE__ */ (0,
|
|
2012
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "mb-2 flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by status", children: STATUS_FILTERS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
1971
2013
|
"button",
|
|
1972
2014
|
{
|
|
1973
2015
|
type: "button",
|
|
@@ -1982,26 +2024,26 @@ function ScenarioExplorer({ scenarios, summary }) {
|
|
|
1982
2024
|
},
|
|
1983
2025
|
f.value
|
|
1984
2026
|
)) }),
|
|
1985
|
-
/* @__PURE__ */ (0,
|
|
2027
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
|
|
1986
2028
|
Command,
|
|
1987
2029
|
{
|
|
1988
2030
|
className: "rounded-lg border border-border bg-card",
|
|
1989
2031
|
filter: (value, search) => value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0,
|
|
1990
2032
|
children: [
|
|
1991
|
-
/* @__PURE__ */ (0,
|
|
1992
|
-
/* @__PURE__ */ (0,
|
|
1993
|
-
/* @__PURE__ */ (0,
|
|
1994
|
-
/* @__PURE__ */ (0,
|
|
2033
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(CommandInput, { placeholder: "Search scenarios\u2026" }),
|
|
2034
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(CommandList, { className: "max-h-none", children: [
|
|
2035
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(CommandEmpty, { children: "No scenarios match your filters." }),
|
|
2036
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
1995
2037
|
CommandItem,
|
|
1996
2038
|
{
|
|
1997
2039
|
value: `${s.title} ${s.feature} ${s.tags.join(" ")}`,
|
|
1998
2040
|
asChild: true,
|
|
1999
2041
|
className: "cursor-pointer",
|
|
2000
|
-
children: /* @__PURE__ */ (0,
|
|
2001
|
-
/* @__PURE__ */ (0,
|
|
2002
|
-
/* @__PURE__ */ (0,
|
|
2003
|
-
s.tags.slice(0, 3).map((t) => /* @__PURE__ */ (0,
|
|
2004
|
-
/* @__PURE__ */ (0,
|
|
2042
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("a", { href: s.href, className: "flex items-center gap-3", children: [
|
|
2043
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Badge, { variant: s.status, children: s.status }),
|
|
2044
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
|
|
2045
|
+
s.tags.slice(0, 3).map((t) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
|
|
2046
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
|
|
2005
2047
|
] })
|
|
2006
2048
|
},
|
|
2007
2049
|
s.id
|
|
@@ -2148,7 +2190,7 @@ var story_report_v1_default = {
|
|
|
2148
2190
|
title: {
|
|
2149
2191
|
type: "string",
|
|
2150
2192
|
minLength: 1,
|
|
2151
|
-
description: "Display title.
|
|
2193
|
+
description: "Display title. Comes from story.feature(...) when declared, otherwise the describe block or file basename."
|
|
2152
2194
|
},
|
|
2153
2195
|
sourceFile: {
|
|
2154
2196
|
type: "string",
|
|
@@ -2164,6 +2206,26 @@ var story_report_v1_default = {
|
|
|
2164
2206
|
$ref: "#/$defs/Scenario"
|
|
2165
2207
|
},
|
|
2166
2208
|
description: "Scenarios in this feature, in declaration order."
|
|
2209
|
+
},
|
|
2210
|
+
kind: {
|
|
2211
|
+
type: "string",
|
|
2212
|
+
enum: [
|
|
2213
|
+
"feature",
|
|
2214
|
+
"ability",
|
|
2215
|
+
"business-need"
|
|
2216
|
+
],
|
|
2217
|
+
description: "How the feature was declared. Absent when the title was derived rather than declared."
|
|
2218
|
+
},
|
|
2219
|
+
narrative: {
|
|
2220
|
+
type: "string",
|
|
2221
|
+
description: "Markdown explaining why the feature exists and who it serves."
|
|
2222
|
+
},
|
|
2223
|
+
glossary: {
|
|
2224
|
+
type: "array",
|
|
2225
|
+
items: {
|
|
2226
|
+
$ref: "#/$defs/GlossaryTerm"
|
|
2227
|
+
},
|
|
2228
|
+
description: "Terms this feature defines, linked wherever they appear in scenario text."
|
|
2167
2229
|
}
|
|
2168
2230
|
},
|
|
2169
2231
|
required: [
|
|
@@ -2975,6 +3037,25 @@ var story_report_v1_default = {
|
|
|
2975
3037
|
}
|
|
2976
3038
|
},
|
|
2977
3039
|
additionalProperties: false
|
|
3040
|
+
},
|
|
3041
|
+
GlossaryTerm: {
|
|
3042
|
+
type: "object",
|
|
3043
|
+
description: "One glossary entry: a term the scenarios use and what it means.",
|
|
3044
|
+
properties: {
|
|
3045
|
+
term: {
|
|
3046
|
+
type: "string",
|
|
3047
|
+
minLength: 1
|
|
3048
|
+
},
|
|
3049
|
+
definition: {
|
|
3050
|
+
type: "string",
|
|
3051
|
+
minLength: 1
|
|
3052
|
+
}
|
|
3053
|
+
},
|
|
3054
|
+
required: [
|
|
3055
|
+
"term",
|
|
3056
|
+
"definition"
|
|
3057
|
+
],
|
|
3058
|
+
additionalProperties: false
|
|
2978
3059
|
}
|
|
2979
3060
|
}
|
|
2980
3061
|
};
|