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.js
CHANGED
|
@@ -379,21 +379,29 @@ function DocLink({ entry }) {
|
|
|
379
379
|
);
|
|
380
380
|
}
|
|
381
381
|
|
|
382
|
-
// src/
|
|
382
|
+
// src/lib/markdown.ts
|
|
383
383
|
import { marked } from "marked";
|
|
384
384
|
|
|
385
385
|
// src/lib/url.ts
|
|
386
386
|
import { safeUrl, safeImageUrl, isLocalFsPath } from "executable-stories-core/utils/url";
|
|
387
387
|
|
|
388
|
-
// src/
|
|
389
|
-
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
390
|
-
function neutralizeUrl(value) {
|
|
391
|
-
return safeUrl(value) ?? "#";
|
|
392
|
-
}
|
|
388
|
+
// src/lib/markdown.ts
|
|
393
389
|
function safeMarkdownHtml(markdown) {
|
|
394
390
|
const raw = marked.parse(markdown, { async: false });
|
|
395
391
|
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)}'`);
|
|
396
392
|
}
|
|
393
|
+
function dedent(text) {
|
|
394
|
+
const lines = text.replace(/\t/g, " ").split("\n");
|
|
395
|
+
const indents = lines.filter((line) => line.trim().length > 0).map((line) => line.length - line.trimStart().length);
|
|
396
|
+
const shortest = indents.length > 0 ? Math.min(...indents) : 0;
|
|
397
|
+
return lines.map((line) => line.slice(shortest)).join("\n").trim();
|
|
398
|
+
}
|
|
399
|
+
function neutralizeUrl(value) {
|
|
400
|
+
return safeUrl(value) ?? "#";
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// src/components/doc/DocSection.tsx
|
|
404
|
+
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
397
405
|
function DocSection({ entry }) {
|
|
398
406
|
const renderers = useBuiltinRenderers();
|
|
399
407
|
if (renderers.section) {
|
|
@@ -1270,8 +1278,35 @@ function ReportScenarioList({ feature }) {
|
|
|
1270
1278
|
return /* @__PURE__ */ jsx27(Fragment8, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ jsx27(ReportScenario, { scenario }, scenario.id)) });
|
|
1271
1279
|
}
|
|
1272
1280
|
|
|
1281
|
+
// src/components/ReportFeatureIntro.tsx
|
|
1282
|
+
import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1283
|
+
function ReportFeatureIntro({ feature }) {
|
|
1284
|
+
const hasNarrative = Boolean(feature.narrative?.trim());
|
|
1285
|
+
const hasGlossary = Boolean(feature.glossary?.length);
|
|
1286
|
+
if (!hasNarrative && !hasGlossary) return null;
|
|
1287
|
+
return /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-3 border-l-2 border-border pl-4 text-sm", children: [
|
|
1288
|
+
hasNarrative ? /* @__PURE__ */ jsx28(
|
|
1289
|
+
"div",
|
|
1290
|
+
{
|
|
1291
|
+
className: "es-doc-prose prose prose-sm max-w-none text-muted-foreground",
|
|
1292
|
+
dangerouslySetInnerHTML: { __html: safeMarkdownHtml(dedent(feature.narrative)) }
|
|
1293
|
+
}
|
|
1294
|
+
) : null,
|
|
1295
|
+
hasGlossary ? /* @__PURE__ */ jsx28("dl", { className: "grid gap-1.5", "aria-label": "Glossary", children: feature.glossary.map((entry) => /* @__PURE__ */ jsxs18("div", { className: "flex flex-wrap gap-x-2 text-xs", children: [
|
|
1296
|
+
/* @__PURE__ */ jsx28("dt", { className: "font-medium text-foreground", children: entry.term }),
|
|
1297
|
+
/* @__PURE__ */ jsx28("dd", { className: "flex-1 text-muted-foreground", children: entry.definition })
|
|
1298
|
+
] }, entry.term)) }) : null
|
|
1299
|
+
] });
|
|
1300
|
+
}
|
|
1301
|
+
function featureKindLabel(kind) {
|
|
1302
|
+
if (kind === "ability") return "Ability";
|
|
1303
|
+
if (kind === "business-need") return "Business need";
|
|
1304
|
+
if (kind === "feature") return "Feature";
|
|
1305
|
+
return null;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1273
1308
|
// src/components/ReportFeature.tsx
|
|
1274
|
-
import { Fragment as Fragment9, jsx as
|
|
1309
|
+
import { Fragment as Fragment9, jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1275
1310
|
function ReportFeature({ feature }) {
|
|
1276
1311
|
const titleId = `${feature.id}-title`;
|
|
1277
1312
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1279,10 +1314,11 @@ function ReportFeature({ feature }) {
|
|
|
1279
1314
|
const skipped = s.skipped + s.pending;
|
|
1280
1315
|
const collapse = useCollapse();
|
|
1281
1316
|
const collapsed = collapse?.isCollapsed(feature.id) ?? false;
|
|
1317
|
+
const kindLabel = featureKindLabel(feature.kind);
|
|
1282
1318
|
return (
|
|
1283
1319
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
1284
1320
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1285
|
-
/* @__PURE__ */
|
|
1321
|
+
/* @__PURE__ */ jsxs19(
|
|
1286
1322
|
"section",
|
|
1287
1323
|
{
|
|
1288
1324
|
id: feature.id,
|
|
@@ -1290,9 +1326,9 @@ function ReportFeature({ feature }) {
|
|
|
1290
1326
|
"aria-labelledby": titleId,
|
|
1291
1327
|
className: "flex flex-col gap-3",
|
|
1292
1328
|
children: [
|
|
1293
|
-
/* @__PURE__ */
|
|
1294
|
-
/* @__PURE__ */
|
|
1295
|
-
/* @__PURE__ */
|
|
1329
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1330
|
+
/* @__PURE__ */ jsxs19("div", { className: "min-w-0", children: [
|
|
1331
|
+
/* @__PURE__ */ jsx29("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ jsxs19(
|
|
1296
1332
|
"button",
|
|
1297
1333
|
{
|
|
1298
1334
|
type: "button",
|
|
@@ -1301,31 +1337,34 @@ function ReportFeature({ feature }) {
|
|
|
1301
1337
|
"aria-controls": bodyId,
|
|
1302
1338
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1303
1339
|
children: [
|
|
1304
|
-
/* @__PURE__ */
|
|
1305
|
-
/* @__PURE__ */
|
|
1340
|
+
/* @__PURE__ */ jsx29("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
|
|
1341
|
+
/* @__PURE__ */ jsx29("span", { className: "truncate", children: feature.title })
|
|
1306
1342
|
]
|
|
1307
1343
|
}
|
|
1308
1344
|
) : feature.title }),
|
|
1309
|
-
/* @__PURE__ */
|
|
1345
|
+
/* @__PURE__ */ jsxs19("p", { className: cn("mt-0.5 flex items-center gap-2 text-xs text-muted-foreground", collapse && "pl-5"), children: [
|
|
1346
|
+
kindLabel ? /* @__PURE__ */ jsx29("span", { className: "shrink-0 rounded-sm bg-muted px-1.5 py-0.5 font-medium text-foreground", children: kindLabel }) : null,
|
|
1347
|
+
/* @__PURE__ */ jsx29("span", { className: "truncate font-mono", children: feature.sourceFile })
|
|
1348
|
+
] })
|
|
1310
1349
|
] }),
|
|
1311
|
-
/* @__PURE__ */
|
|
1350
|
+
/* @__PURE__ */ jsxs19(
|
|
1312
1351
|
"p",
|
|
1313
1352
|
{
|
|
1314
1353
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1315
1354
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1316
1355
|
children: [
|
|
1317
|
-
/* @__PURE__ */
|
|
1356
|
+
/* @__PURE__ */ jsxs19("span", { children: [
|
|
1318
1357
|
s.passed,
|
|
1319
1358
|
" passed"
|
|
1320
1359
|
] }),
|
|
1321
|
-
/* @__PURE__ */
|
|
1322
|
-
/* @__PURE__ */
|
|
1360
|
+
/* @__PURE__ */ jsx29("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1361
|
+
/* @__PURE__ */ jsxs19("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1323
1362
|
s.failed,
|
|
1324
1363
|
" failed"
|
|
1325
1364
|
] }),
|
|
1326
|
-
skipped > 0 ? /* @__PURE__ */
|
|
1327
|
-
/* @__PURE__ */
|
|
1328
|
-
/* @__PURE__ */
|
|
1365
|
+
skipped > 0 ? /* @__PURE__ */ jsxs19(Fragment9, { children: [
|
|
1366
|
+
/* @__PURE__ */ jsx29("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1367
|
+
/* @__PURE__ */ jsxs19("span", { children: [
|
|
1329
1368
|
skipped,
|
|
1330
1369
|
" skipped"
|
|
1331
1370
|
] })
|
|
@@ -1334,7 +1373,10 @@ function ReportFeature({ feature }) {
|
|
|
1334
1373
|
}
|
|
1335
1374
|
)
|
|
1336
1375
|
] }),
|
|
1337
|
-
/* @__PURE__ */
|
|
1376
|
+
/* @__PURE__ */ jsxs19("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: [
|
|
1377
|
+
/* @__PURE__ */ jsx29(ReportFeatureIntro, { feature }),
|
|
1378
|
+
/* @__PURE__ */ jsx29(ReportScenarioList, { feature })
|
|
1379
|
+
] })
|
|
1338
1380
|
]
|
|
1339
1381
|
}
|
|
1340
1382
|
)
|
|
@@ -1342,17 +1384,17 @@ function ReportFeature({ feature }) {
|
|
|
1342
1384
|
}
|
|
1343
1385
|
|
|
1344
1386
|
// src/components/ReportFeatureList.tsx
|
|
1345
|
-
import { jsx as
|
|
1387
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
1346
1388
|
function ReportFeatureList() {
|
|
1347
1389
|
const report = useReport();
|
|
1348
|
-
return /* @__PURE__ */
|
|
1390
|
+
return /* @__PURE__ */ jsx30("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ jsx30(ReportFeature, { feature }, feature.id)) });
|
|
1349
1391
|
}
|
|
1350
1392
|
|
|
1351
1393
|
// src/components/ui/empty.tsx
|
|
1352
1394
|
import { cva as cva2 } from "class-variance-authority";
|
|
1353
|
-
import { jsx as
|
|
1395
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
1354
1396
|
function Empty({ className, ...props }) {
|
|
1355
|
-
return /* @__PURE__ */
|
|
1397
|
+
return /* @__PURE__ */ jsx31(
|
|
1356
1398
|
"div",
|
|
1357
1399
|
{
|
|
1358
1400
|
"data-slot": "empty",
|
|
@@ -1365,7 +1407,7 @@ function Empty({ className, ...props }) {
|
|
|
1365
1407
|
);
|
|
1366
1408
|
}
|
|
1367
1409
|
function EmptyHeader({ className, ...props }) {
|
|
1368
|
-
return /* @__PURE__ */
|
|
1410
|
+
return /* @__PURE__ */ jsx31(
|
|
1369
1411
|
"div",
|
|
1370
1412
|
{
|
|
1371
1413
|
"data-slot": "empty-header",
|
|
@@ -1392,7 +1434,7 @@ var emptyMediaVariants = cva2(
|
|
|
1392
1434
|
}
|
|
1393
1435
|
);
|
|
1394
1436
|
function EmptyTitle({ className, ...props }) {
|
|
1395
|
-
return /* @__PURE__ */
|
|
1437
|
+
return /* @__PURE__ */ jsx31(
|
|
1396
1438
|
"div",
|
|
1397
1439
|
{
|
|
1398
1440
|
"data-slot": "empty-title",
|
|
@@ -1403,16 +1445,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1403
1445
|
}
|
|
1404
1446
|
|
|
1405
1447
|
// src/components/ReportEmpty.tsx
|
|
1406
|
-
import { jsx as
|
|
1448
|
+
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
1407
1449
|
function ReportEmpty({ message }) {
|
|
1408
|
-
return /* @__PURE__ */
|
|
1450
|
+
return /* @__PURE__ */ jsx32(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ jsx32(EmptyHeader, { children: /* @__PURE__ */ jsx32(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
|
|
1409
1451
|
}
|
|
1410
1452
|
|
|
1411
1453
|
// src/components/ReportSummary.tsx
|
|
1412
|
-
import { jsx as
|
|
1454
|
+
import { jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1413
1455
|
function ReportSummary({ className }) {
|
|
1414
1456
|
const report = useReport();
|
|
1415
|
-
return /* @__PURE__ */
|
|
1457
|
+
return /* @__PURE__ */ jsx33(
|
|
1416
1458
|
ReportSummaryView,
|
|
1417
1459
|
{
|
|
1418
1460
|
summary: report.summary,
|
|
@@ -1438,7 +1480,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1438
1480
|
if (summary.pending > 0) {
|
|
1439
1481
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1440
1482
|
}
|
|
1441
|
-
return /* @__PURE__ */
|
|
1483
|
+
return /* @__PURE__ */ jsx33(
|
|
1442
1484
|
"dl",
|
|
1443
1485
|
{
|
|
1444
1486
|
className: cn(
|
|
@@ -1451,17 +1493,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1451
1493
|
"aria-label": ariaLabel,
|
|
1452
1494
|
children: cards.map((c) => {
|
|
1453
1495
|
const tone = TONE[c.status];
|
|
1454
|
-
return /* @__PURE__ */
|
|
1496
|
+
return /* @__PURE__ */ jsxs20(
|
|
1455
1497
|
"div",
|
|
1456
1498
|
{
|
|
1457
1499
|
"data-status": c.status,
|
|
1458
1500
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1459
1501
|
children: [
|
|
1460
|
-
/* @__PURE__ */
|
|
1461
|
-
/* @__PURE__ */
|
|
1502
|
+
/* @__PURE__ */ jsxs20("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
|
|
1503
|
+
/* @__PURE__ */ jsx33("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1462
1504
|
c.label
|
|
1463
1505
|
] }),
|
|
1464
|
-
/* @__PURE__ */
|
|
1506
|
+
/* @__PURE__ */ jsx33("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
|
|
1465
1507
|
]
|
|
1466
1508
|
},
|
|
1467
1509
|
c.status
|
|
@@ -1524,7 +1566,7 @@ function prUrl(ci) {
|
|
|
1524
1566
|
}
|
|
1525
1567
|
|
|
1526
1568
|
// src/components/ReportMeta.tsx
|
|
1527
|
-
import { jsx as
|
|
1569
|
+
import { jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1528
1570
|
function ReportMeta() {
|
|
1529
1571
|
const report = useReport();
|
|
1530
1572
|
const items = [];
|
|
@@ -1547,13 +1589,13 @@ function ReportMeta() {
|
|
|
1547
1589
|
const short = sha.slice(0, 8);
|
|
1548
1590
|
items.push({
|
|
1549
1591
|
label: "Commit",
|
|
1550
|
-
value: url ? /* @__PURE__ */
|
|
1592
|
+
value: url ? /* @__PURE__ */ jsx34("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1551
1593
|
});
|
|
1552
1594
|
}
|
|
1553
1595
|
if (report.ci) {
|
|
1554
1596
|
items.push({
|
|
1555
1597
|
label: "CI",
|
|
1556
|
-
value: report.ci.url ? /* @__PURE__ */
|
|
1598
|
+
value: report.ci.url ? /* @__PURE__ */ jsxs21("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1557
1599
|
ciDisplayName(report.ci.name),
|
|
1558
1600
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1559
1601
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1564,7 +1606,7 @@ function ReportMeta() {
|
|
|
1564
1606
|
const label = `#${report.ci.prNumber}`;
|
|
1565
1607
|
items.push({
|
|
1566
1608
|
label: "PR",
|
|
1567
|
-
value: url ? /* @__PURE__ */
|
|
1609
|
+
value: url ? /* @__PURE__ */ jsx34("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1568
1610
|
});
|
|
1569
1611
|
}
|
|
1570
1612
|
if (items.length === 0) return null;
|
|
@@ -1572,48 +1614,48 @@ function ReportMeta() {
|
|
|
1572
1614
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1573
1615
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1574
1616
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1575
|
-
/* @__PURE__ */
|
|
1576
|
-
/* @__PURE__ */
|
|
1577
|
-
/* @__PURE__ */
|
|
1617
|
+
/* @__PURE__ */ jsxs21("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
|
|
1618
|
+
/* @__PURE__ */ jsxs21("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: [
|
|
1619
|
+
/* @__PURE__ */ jsx34("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1578
1620
|
"Run details"
|
|
1579
1621
|
] }),
|
|
1580
|
-
/* @__PURE__ */
|
|
1581
|
-
/* @__PURE__ */
|
|
1582
|
-
/* @__PURE__ */
|
|
1622
|
+
/* @__PURE__ */ jsx34("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__ */ jsxs21("div", { className: "flex items-baseline gap-1.5", children: [
|
|
1623
|
+
/* @__PURE__ */ jsx34("dt", { className: "font-medium", children: item.label }),
|
|
1624
|
+
/* @__PURE__ */ jsx34("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1583
1625
|
] }, item.label)) })
|
|
1584
1626
|
] })
|
|
1585
1627
|
);
|
|
1586
1628
|
}
|
|
1587
1629
|
|
|
1588
1630
|
// src/components/ReportSchemaError.tsx
|
|
1589
|
-
import { jsx as
|
|
1631
|
+
import { jsx as jsx35, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1590
1632
|
function ReportSchemaError({ error }) {
|
|
1591
|
-
return /* @__PURE__ */
|
|
1592
|
-
/* @__PURE__ */
|
|
1593
|
-
/* @__PURE__ */
|
|
1594
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */
|
|
1633
|
+
return /* @__PURE__ */ jsxs22("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1634
|
+
/* @__PURE__ */ jsx35("p", { children: /* @__PURE__ */ jsx35("strong", { children: "Report could not be displayed." }) }),
|
|
1635
|
+
/* @__PURE__ */ jsx35("p", { children: error.message }),
|
|
1636
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ jsxs22("p", { children: [
|
|
1595
1637
|
"The report bundle is newer than this version of ",
|
|
1596
|
-
/* @__PURE__ */
|
|
1638
|
+
/* @__PURE__ */ jsx35("code", { children: "executable-stories-react" }),
|
|
1597
1639
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1598
1640
|
] }) : null,
|
|
1599
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */
|
|
1600
|
-
/* @__PURE__ */
|
|
1641
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ jsxs22("details", { children: [
|
|
1642
|
+
/* @__PURE__ */ jsxs22("summary", { children: [
|
|
1601
1643
|
error.issues.length,
|
|
1602
1644
|
" validation issue",
|
|
1603
1645
|
error.issues.length === 1 ? "" : "s"
|
|
1604
1646
|
] }),
|
|
1605
|
-
/* @__PURE__ */
|
|
1647
|
+
/* @__PURE__ */ jsx35("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1606
1648
|
] }) : null
|
|
1607
1649
|
] });
|
|
1608
1650
|
}
|
|
1609
1651
|
|
|
1610
1652
|
// src/components/ReportShell.tsx
|
|
1611
|
-
import { Fragment as Fragment10, jsx as
|
|
1653
|
+
import { Fragment as Fragment10, jsx as jsx36, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1612
1654
|
function ReportTitleBlock({ title }) {
|
|
1613
|
-
return /* @__PURE__ */
|
|
1614
|
-
/* @__PURE__ */
|
|
1615
|
-
/* @__PURE__ */
|
|
1616
|
-
/* @__PURE__ */
|
|
1655
|
+
return /* @__PURE__ */ jsxs23(Fragment10, { children: [
|
|
1656
|
+
/* @__PURE__ */ jsx36("h1", { children: title ?? "Story Report" }),
|
|
1657
|
+
/* @__PURE__ */ jsx36(ReportSummary, {}),
|
|
1658
|
+
/* @__PURE__ */ jsx36(ReportMeta, {})
|
|
1617
1659
|
] });
|
|
1618
1660
|
}
|
|
1619
1661
|
function ReportErrorShell({
|
|
@@ -1622,28 +1664,28 @@ function ReportErrorShell({
|
|
|
1622
1664
|
title,
|
|
1623
1665
|
dataTheme
|
|
1624
1666
|
}) {
|
|
1625
|
-
return /* @__PURE__ */
|
|
1667
|
+
return /* @__PURE__ */ jsx36("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx36(ReportSchemaError, { error }) });
|
|
1626
1668
|
}
|
|
1627
1669
|
|
|
1628
1670
|
// src/components/Report.tsx
|
|
1629
|
-
import { jsx as
|
|
1671
|
+
import { jsx as jsx37, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1630
1672
|
function Report(props) {
|
|
1631
1673
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1632
1674
|
const result = unwrapReport(report);
|
|
1633
1675
|
if (!result.ok) {
|
|
1634
|
-
return /* @__PURE__ */
|
|
1676
|
+
return /* @__PURE__ */ jsx37(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1635
1677
|
}
|
|
1636
1678
|
const data = result.data;
|
|
1637
1679
|
const hasContent = data.features.length > 0;
|
|
1638
|
-
return /* @__PURE__ */
|
|
1639
|
-
/* @__PURE__ */
|
|
1640
|
-
hasContent ? /* @__PURE__ */
|
|
1680
|
+
return /* @__PURE__ */ jsx37(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ jsxs24("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1681
|
+
/* @__PURE__ */ jsx37("header", { className: "es-report-header", children: /* @__PURE__ */ jsx37(ReportTitleBlock, { title }) }),
|
|
1682
|
+
hasContent ? /* @__PURE__ */ jsx37(ReportFeatureList, {}) : /* @__PURE__ */ jsx37(ReportEmpty, {})
|
|
1641
1683
|
] }) });
|
|
1642
1684
|
}
|
|
1643
1685
|
|
|
1644
1686
|
// src/components/doc/MermaidView.tsx
|
|
1645
1687
|
import { useEffect, useRef, useState as useState2 } from "react";
|
|
1646
|
-
import { Fragment as Fragment11, jsx as
|
|
1688
|
+
import { Fragment as Fragment11, jsx as jsx38, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1647
1689
|
function prefersDark(el) {
|
|
1648
1690
|
const themed = el?.closest("[data-theme]");
|
|
1649
1691
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -1697,9 +1739,9 @@ function MermaidView({ entry, load }) {
|
|
|
1697
1739
|
};
|
|
1698
1740
|
}, [entry.code, load]);
|
|
1699
1741
|
if (svg) {
|
|
1700
|
-
return /* @__PURE__ */
|
|
1701
|
-
entry.title ? /* @__PURE__ */
|
|
1702
|
-
/* @__PURE__ */
|
|
1742
|
+
return /* @__PURE__ */ jsxs25("figure", { ref, className: "my-3", children: [
|
|
1743
|
+
entry.title ? /* @__PURE__ */ jsx38("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
1744
|
+
/* @__PURE__ */ jsx38(
|
|
1703
1745
|
"div",
|
|
1704
1746
|
{
|
|
1705
1747
|
role: "img",
|
|
@@ -1710,8 +1752,8 @@ function MermaidView({ entry, load }) {
|
|
|
1710
1752
|
)
|
|
1711
1753
|
] });
|
|
1712
1754
|
}
|
|
1713
|
-
return /* @__PURE__ */
|
|
1714
|
-
error ? /* @__PURE__ */
|
|
1755
|
+
return /* @__PURE__ */ jsxs25(Fragment11, { children: [
|
|
1756
|
+
error ? /* @__PURE__ */ jsxs25(
|
|
1715
1757
|
"p",
|
|
1716
1758
|
{
|
|
1717
1759
|
role: "alert",
|
|
@@ -1723,19 +1765,19 @@ function MermaidView({ entry, load }) {
|
|
|
1723
1765
|
]
|
|
1724
1766
|
}
|
|
1725
1767
|
) : null,
|
|
1726
|
-
/* @__PURE__ */
|
|
1768
|
+
/* @__PURE__ */ jsx38(MermaidSource, { entry, ref })
|
|
1727
1769
|
] });
|
|
1728
1770
|
}
|
|
1729
1771
|
|
|
1730
1772
|
// src/components/doc/MermaidDiagram.tsx
|
|
1731
|
-
import { jsx as
|
|
1773
|
+
import { jsx as jsx39 } from "react/jsx-runtime";
|
|
1732
1774
|
var mermaidLoader;
|
|
1733
1775
|
function loadMermaid() {
|
|
1734
1776
|
mermaidLoader ??= import("mermaid").then((m) => m.default);
|
|
1735
1777
|
return mermaidLoader;
|
|
1736
1778
|
}
|
|
1737
1779
|
function MermaidDiagram({ entry, load = loadMermaid }) {
|
|
1738
|
-
return /* @__PURE__ */
|
|
1780
|
+
return /* @__PURE__ */ jsx39(MermaidView, { entry, load });
|
|
1739
1781
|
}
|
|
1740
1782
|
|
|
1741
1783
|
// src/components/ScenarioExplorer.tsx
|
|
@@ -1745,12 +1787,12 @@ import { useState as useState3 } from "react";
|
|
|
1745
1787
|
import "react";
|
|
1746
1788
|
import { Command as CommandPrimitive } from "cmdk";
|
|
1747
1789
|
import { SearchIcon } from "lucide-react";
|
|
1748
|
-
import { jsx as
|
|
1790
|
+
import { jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1749
1791
|
function Command({
|
|
1750
1792
|
className,
|
|
1751
1793
|
...props
|
|
1752
1794
|
}) {
|
|
1753
|
-
return /* @__PURE__ */
|
|
1795
|
+
return /* @__PURE__ */ jsx40(
|
|
1754
1796
|
CommandPrimitive,
|
|
1755
1797
|
{
|
|
1756
1798
|
"data-slot": "command",
|
|
@@ -1766,14 +1808,14 @@ function CommandInput({
|
|
|
1766
1808
|
className,
|
|
1767
1809
|
...props
|
|
1768
1810
|
}) {
|
|
1769
|
-
return /* @__PURE__ */
|
|
1811
|
+
return /* @__PURE__ */ jsxs26(
|
|
1770
1812
|
"div",
|
|
1771
1813
|
{
|
|
1772
1814
|
"data-slot": "command-input-wrapper",
|
|
1773
1815
|
className: "flex h-9 items-center gap-2 border-b px-3",
|
|
1774
1816
|
children: [
|
|
1775
|
-
/* @__PURE__ */
|
|
1776
|
-
/* @__PURE__ */
|
|
1817
|
+
/* @__PURE__ */ jsx40(SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
|
|
1818
|
+
/* @__PURE__ */ jsx40(
|
|
1777
1819
|
CommandPrimitive.Input,
|
|
1778
1820
|
{
|
|
1779
1821
|
"data-slot": "command-input",
|
|
@@ -1792,7 +1834,7 @@ function CommandList({
|
|
|
1792
1834
|
className,
|
|
1793
1835
|
...props
|
|
1794
1836
|
}) {
|
|
1795
|
-
return /* @__PURE__ */
|
|
1837
|
+
return /* @__PURE__ */ jsx40(
|
|
1796
1838
|
CommandPrimitive.List,
|
|
1797
1839
|
{
|
|
1798
1840
|
"data-slot": "command-list",
|
|
@@ -1807,7 +1849,7 @@ function CommandList({
|
|
|
1807
1849
|
function CommandEmpty({
|
|
1808
1850
|
...props
|
|
1809
1851
|
}) {
|
|
1810
|
-
return /* @__PURE__ */
|
|
1852
|
+
return /* @__PURE__ */ jsx40(
|
|
1811
1853
|
CommandPrimitive.Empty,
|
|
1812
1854
|
{
|
|
1813
1855
|
"data-slot": "command-empty",
|
|
@@ -1820,7 +1862,7 @@ function CommandGroup({
|
|
|
1820
1862
|
className,
|
|
1821
1863
|
...props
|
|
1822
1864
|
}) {
|
|
1823
|
-
return /* @__PURE__ */
|
|
1865
|
+
return /* @__PURE__ */ jsx40(
|
|
1824
1866
|
CommandPrimitive.Group,
|
|
1825
1867
|
{
|
|
1826
1868
|
"data-slot": "command-group",
|
|
@@ -1836,7 +1878,7 @@ function CommandItem({
|
|
|
1836
1878
|
className,
|
|
1837
1879
|
...props
|
|
1838
1880
|
}) {
|
|
1839
|
-
return /* @__PURE__ */
|
|
1881
|
+
return /* @__PURE__ */ jsx40(
|
|
1840
1882
|
CommandPrimitive.Item,
|
|
1841
1883
|
{
|
|
1842
1884
|
"data-slot": "command-item",
|
|
@@ -1850,7 +1892,7 @@ function CommandItem({
|
|
|
1850
1892
|
}
|
|
1851
1893
|
|
|
1852
1894
|
// src/components/ScenarioExplorer.tsx
|
|
1853
|
-
import { jsx as
|
|
1895
|
+
import { jsx as jsx41, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1854
1896
|
var STATUS_FILTERS = [
|
|
1855
1897
|
{ value: "all", label: "All" },
|
|
1856
1898
|
{ value: "passed", label: "Passed" },
|
|
@@ -1861,22 +1903,22 @@ var STATUS_FILTERS = [
|
|
|
1861
1903
|
function ScenarioExplorer({ scenarios, summary }) {
|
|
1862
1904
|
const [status, setStatus] = useState3("all");
|
|
1863
1905
|
const visible = status === "all" ? scenarios : scenarios.filter((s) => s.status === status);
|
|
1864
|
-
return /* @__PURE__ */
|
|
1865
|
-
summary ? /* @__PURE__ */
|
|
1906
|
+
return /* @__PURE__ */ jsxs27("div", { className: "font-sans text-foreground", children: [
|
|
1907
|
+
summary ? /* @__PURE__ */ jsxs27("p", { className: "mb-3 text-sm text-muted-foreground", children: [
|
|
1866
1908
|
summary.total,
|
|
1867
1909
|
" scenarios \xB7 ",
|
|
1868
|
-
/* @__PURE__ */
|
|
1910
|
+
/* @__PURE__ */ jsxs27("span", { className: "text-pass", children: [
|
|
1869
1911
|
summary.passed,
|
|
1870
1912
|
" passed"
|
|
1871
1913
|
] }),
|
|
1872
1914
|
" \xB7",
|
|
1873
1915
|
" ",
|
|
1874
|
-
/* @__PURE__ */
|
|
1916
|
+
/* @__PURE__ */ jsxs27("span", { className: "text-fail", children: [
|
|
1875
1917
|
summary.failed,
|
|
1876
1918
|
" failed"
|
|
1877
1919
|
] })
|
|
1878
1920
|
] }) : null,
|
|
1879
|
-
/* @__PURE__ */
|
|
1921
|
+
/* @__PURE__ */ jsx41("div", { className: "mb-2 flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by status", children: STATUS_FILTERS.map((f) => /* @__PURE__ */ jsx41(
|
|
1880
1922
|
"button",
|
|
1881
1923
|
{
|
|
1882
1924
|
type: "button",
|
|
@@ -1891,26 +1933,26 @@ function ScenarioExplorer({ scenarios, summary }) {
|
|
|
1891
1933
|
},
|
|
1892
1934
|
f.value
|
|
1893
1935
|
)) }),
|
|
1894
|
-
/* @__PURE__ */
|
|
1936
|
+
/* @__PURE__ */ jsxs27(
|
|
1895
1937
|
Command,
|
|
1896
1938
|
{
|
|
1897
1939
|
className: "rounded-lg border border-border bg-card",
|
|
1898
1940
|
filter: (value, search) => value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0,
|
|
1899
1941
|
children: [
|
|
1900
|
-
/* @__PURE__ */
|
|
1901
|
-
/* @__PURE__ */
|
|
1902
|
-
/* @__PURE__ */
|
|
1903
|
-
/* @__PURE__ */
|
|
1942
|
+
/* @__PURE__ */ jsx41(CommandInput, { placeholder: "Search scenarios\u2026" }),
|
|
1943
|
+
/* @__PURE__ */ jsxs27(CommandList, { className: "max-h-none", children: [
|
|
1944
|
+
/* @__PURE__ */ jsx41(CommandEmpty, { children: "No scenarios match your filters." }),
|
|
1945
|
+
/* @__PURE__ */ jsx41(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ jsx41(
|
|
1904
1946
|
CommandItem,
|
|
1905
1947
|
{
|
|
1906
1948
|
value: `${s.title} ${s.feature} ${s.tags.join(" ")}`,
|
|
1907
1949
|
asChild: true,
|
|
1908
1950
|
className: "cursor-pointer",
|
|
1909
|
-
children: /* @__PURE__ */
|
|
1910
|
-
/* @__PURE__ */
|
|
1911
|
-
/* @__PURE__ */
|
|
1912
|
-
s.tags.slice(0, 3).map((t) => /* @__PURE__ */
|
|
1913
|
-
/* @__PURE__ */
|
|
1951
|
+
children: /* @__PURE__ */ jsxs27("a", { href: s.href, className: "flex items-center gap-3", children: [
|
|
1952
|
+
/* @__PURE__ */ jsx41(Badge, { variant: s.status, children: s.status }),
|
|
1953
|
+
/* @__PURE__ */ jsx41("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
|
|
1954
|
+
s.tags.slice(0, 3).map((t) => /* @__PURE__ */ jsx41(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
|
|
1955
|
+
/* @__PURE__ */ jsx41("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
|
|
1914
1956
|
] })
|
|
1915
1957
|
},
|
|
1916
1958
|
s.id
|
|
@@ -2057,7 +2099,7 @@ var story_report_v1_default = {
|
|
|
2057
2099
|
title: {
|
|
2058
2100
|
type: "string",
|
|
2059
2101
|
minLength: 1,
|
|
2060
|
-
description: "Display title.
|
|
2102
|
+
description: "Display title. Comes from story.feature(...) when declared, otherwise the describe block or file basename."
|
|
2061
2103
|
},
|
|
2062
2104
|
sourceFile: {
|
|
2063
2105
|
type: "string",
|
|
@@ -2073,6 +2115,26 @@ var story_report_v1_default = {
|
|
|
2073
2115
|
$ref: "#/$defs/Scenario"
|
|
2074
2116
|
},
|
|
2075
2117
|
description: "Scenarios in this feature, in declaration order."
|
|
2118
|
+
},
|
|
2119
|
+
kind: {
|
|
2120
|
+
type: "string",
|
|
2121
|
+
enum: [
|
|
2122
|
+
"feature",
|
|
2123
|
+
"ability",
|
|
2124
|
+
"business-need"
|
|
2125
|
+
],
|
|
2126
|
+
description: "How the feature was declared. Absent when the title was derived rather than declared."
|
|
2127
|
+
},
|
|
2128
|
+
narrative: {
|
|
2129
|
+
type: "string",
|
|
2130
|
+
description: "Markdown explaining why the feature exists and who it serves."
|
|
2131
|
+
},
|
|
2132
|
+
glossary: {
|
|
2133
|
+
type: "array",
|
|
2134
|
+
items: {
|
|
2135
|
+
$ref: "#/$defs/GlossaryTerm"
|
|
2136
|
+
},
|
|
2137
|
+
description: "Terms this feature defines, linked wherever they appear in scenario text."
|
|
2076
2138
|
}
|
|
2077
2139
|
},
|
|
2078
2140
|
required: [
|
|
@@ -2884,6 +2946,25 @@ var story_report_v1_default = {
|
|
|
2884
2946
|
}
|
|
2885
2947
|
},
|
|
2886
2948
|
additionalProperties: false
|
|
2949
|
+
},
|
|
2950
|
+
GlossaryTerm: {
|
|
2951
|
+
type: "object",
|
|
2952
|
+
description: "One glossary entry: a term the scenarios use and what it means.",
|
|
2953
|
+
properties: {
|
|
2954
|
+
term: {
|
|
2955
|
+
type: "string",
|
|
2956
|
+
minLength: 1
|
|
2957
|
+
},
|
|
2958
|
+
definition: {
|
|
2959
|
+
type: "string",
|
|
2960
|
+
minLength: 1
|
|
2961
|
+
}
|
|
2962
|
+
},
|
|
2963
|
+
required: [
|
|
2964
|
+
"term",
|
|
2965
|
+
"definition"
|
|
2966
|
+
],
|
|
2967
|
+
additionalProperties: false
|
|
2887
2968
|
}
|
|
2888
2969
|
}
|
|
2889
2970
|
};
|