executable-stories-react 0.11.0 → 0.13.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 +414 -464
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +313 -361
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +1779 -1340
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +32 -32
- package/dist/interactive.d.ts +32 -32
- package/dist/interactive.js +1694 -1246
- package/dist/interactive.js.map +1 -1
- package/dist/parse.cjs +34 -147
- package/dist/parse.cjs.map +1 -1
- package/dist/parse.js +34 -147
- package/dist/parse.js.map +1 -1
- package/dist/report-island.global.js +64 -54
- package/dist/ssr.cjs +331 -260
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.js +250 -176
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +2 -2
- package/package.json +24 -23
package/dist/ssr.cjs
CHANGED
|
@@ -23,7 +23,7 @@ __export(ssr_entry_exports, {
|
|
|
23
23
|
renderReportToHtml: () => renderReportToHtml
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(ssr_entry_exports);
|
|
26
|
-
var
|
|
26
|
+
var import_react10 = require("react");
|
|
27
27
|
var import_server = require("react-dom/server");
|
|
28
28
|
|
|
29
29
|
// src/result.ts
|
|
@@ -314,23 +314,45 @@ function useReport() {
|
|
|
314
314
|
// src/components/ReportScenario.tsx
|
|
315
315
|
var import_duration3 = require("executable-stories-core/utils/duration");
|
|
316
316
|
|
|
317
|
+
// src/lib/step-params.tsx
|
|
318
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
319
|
+
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
320
|
+
function highlightStepParams(text) {
|
|
321
|
+
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
322
|
+
if (matches.length === 0) return text;
|
|
323
|
+
const nodes = [];
|
|
324
|
+
let lastIndex = 0;
|
|
325
|
+
matches.forEach((match, i) => {
|
|
326
|
+
const start = match.index;
|
|
327
|
+
const end = start + match[0].length;
|
|
328
|
+
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
329
|
+
nodes.push(
|
|
330
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
331
|
+
);
|
|
332
|
+
lastIndex = end;
|
|
333
|
+
});
|
|
334
|
+
if (lastIndex < text.length) nodes.push(text.slice(lastIndex));
|
|
335
|
+
return nodes;
|
|
336
|
+
}
|
|
337
|
+
|
|
317
338
|
// src/components/ReportSteps.tsx
|
|
339
|
+
var import_assertive_steps = require("executable-stories-core/utils/assertive-steps");
|
|
318
340
|
var import_duration = require("executable-stories-core/utils/duration");
|
|
319
341
|
|
|
320
342
|
// src/components/doc/DocNote.tsx
|
|
321
|
-
var
|
|
343
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
322
344
|
function DocNote({ entry }) {
|
|
323
|
-
return /* @__PURE__ */ (0,
|
|
345
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
|
|
324
346
|
}
|
|
325
347
|
|
|
326
348
|
// src/components/doc/DocTag.tsx
|
|
327
|
-
var
|
|
349
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
328
350
|
function DocTag({ entry }) {
|
|
329
|
-
return /* @__PURE__ */ (0,
|
|
351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "my-2 flex flex-wrap gap-1.5", "aria-label": "Tags", children: entry.names.map((n) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Badge, { variant: "tag", children: n }) }, n)) });
|
|
330
352
|
}
|
|
331
353
|
|
|
332
354
|
// src/components/doc/DocKv.tsx
|
|
333
|
-
var
|
|
355
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
334
356
|
function formatValue(value) {
|
|
335
357
|
if (value === null) return "null";
|
|
336
358
|
if (typeof value === "string") return value;
|
|
@@ -342,9 +364,9 @@ function formatValue(value) {
|
|
|
342
364
|
}
|
|
343
365
|
}
|
|
344
366
|
function DocKv({ entry }) {
|
|
345
|
-
return /* @__PURE__ */ (0,
|
|
346
|
-
/* @__PURE__ */ (0,
|
|
347
|
-
/* @__PURE__ */ (0,
|
|
367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
|
|
368
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dt", { className: "font-semibold text-muted-foreground", children: entry.label }),
|
|
369
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("dd", { className: "font-mono text-foreground", children: formatValue(entry.value) })
|
|
348
370
|
] });
|
|
349
371
|
}
|
|
350
372
|
|
|
@@ -362,37 +384,37 @@ function useBuiltinRenderers() {
|
|
|
362
384
|
}
|
|
363
385
|
|
|
364
386
|
// src/components/doc/DocCode.tsx
|
|
365
|
-
var
|
|
387
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
366
388
|
function CodeFigure({ label, children }) {
|
|
367
|
-
return /* @__PURE__ */ (0,
|
|
368
|
-
label ? /* @__PURE__ */ (0,
|
|
369
|
-
/* @__PURE__ */ (0,
|
|
389
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("figure", { className: "my-3", children: [
|
|
390
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: label }) : null,
|
|
391
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3", children })
|
|
370
392
|
] });
|
|
371
393
|
}
|
|
372
394
|
function DocCode({ entry }) {
|
|
373
395
|
const renderers = useBuiltinRenderers();
|
|
374
396
|
if (renderers.code) {
|
|
375
|
-
return /* @__PURE__ */ (0,
|
|
397
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: renderers.code(entry) });
|
|
376
398
|
}
|
|
377
|
-
return /* @__PURE__ */ (0,
|
|
399
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CodeFigure, { label: entry.label, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
378
400
|
}
|
|
379
401
|
|
|
380
402
|
// src/components/doc/DocTable.tsx
|
|
381
|
-
var
|
|
403
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
382
404
|
function DocTable({ entry }) {
|
|
383
|
-
return /* @__PURE__ */ (0,
|
|
384
|
-
entry.label ? /* @__PURE__ */ (0,
|
|
385
|
-
/* @__PURE__ */ (0,
|
|
386
|
-
/* @__PURE__ */ (0,
|
|
387
|
-
/* @__PURE__ */ (0,
|
|
405
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("figure", { className: "my-3", children: [
|
|
406
|
+
entry.label ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.label }) : null,
|
|
407
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("table", { className: "w-full border-collapse text-sm", children: [
|
|
408
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tr", { className: "bg-muted/50", children: entry.columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: c }, c)) }) }),
|
|
409
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tbody", { children: entry.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("tr", { children: row.map((cell, j) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: cell }, j)) }, i)) })
|
|
388
410
|
] }) })
|
|
389
411
|
] });
|
|
390
412
|
}
|
|
391
413
|
|
|
392
414
|
// src/components/doc/DocLink.tsx
|
|
393
|
-
var
|
|
415
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
394
416
|
function DocLink({ entry }) {
|
|
395
|
-
return /* @__PURE__ */ (0,
|
|
417
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
396
418
|
"a",
|
|
397
419
|
{
|
|
398
420
|
className: "text-sm font-medium text-primary underline underline-offset-2 hover:no-underline",
|
|
@@ -426,16 +448,16 @@ function neutralizeUrl(value) {
|
|
|
426
448
|
}
|
|
427
449
|
|
|
428
450
|
// src/components/doc/DocSection.tsx
|
|
429
|
-
var
|
|
451
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
430
452
|
function DocSection({ entry }) {
|
|
431
453
|
const renderers = useBuiltinRenderers();
|
|
432
454
|
if (renderers.section) {
|
|
433
|
-
return /* @__PURE__ */ (0,
|
|
455
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: renderers.section(entry) });
|
|
434
456
|
}
|
|
435
457
|
const html = safeMarkdownHtml(entry.markdown);
|
|
436
|
-
return /* @__PURE__ */ (0,
|
|
437
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
438
|
-
/* @__PURE__ */ (0,
|
|
458
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("section", { className: "my-3 text-sm", "aria-label": entry.title, children: [
|
|
459
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h4", { className: "mb-1 font-semibold text-foreground", children: entry.title }) : null,
|
|
460
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
439
461
|
"div",
|
|
440
462
|
{
|
|
441
463
|
className: "es-doc-prose prose prose-sm max-w-none",
|
|
@@ -446,11 +468,11 @@ function DocSection({ entry }) {
|
|
|
446
468
|
}
|
|
447
469
|
|
|
448
470
|
// src/components/doc/DocMermaid.tsx
|
|
449
|
-
var
|
|
471
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
450
472
|
function MermaidSource({ entry, ref }) {
|
|
451
|
-
return /* @__PURE__ */ (0,
|
|
452
|
-
entry.title ? /* @__PURE__ */ (0,
|
|
453
|
-
/* @__PURE__ */ (0,
|
|
473
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("figure", { ref, className: "my-3", "aria-label": entry.title ?? "Diagram", children: [
|
|
474
|
+
entry.title ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
475
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
454
476
|
"pre",
|
|
455
477
|
{
|
|
456
478
|
"data-mermaid": true,
|
|
@@ -464,24 +486,24 @@ function MermaidSource({ entry, ref }) {
|
|
|
464
486
|
function DocMermaid({ entry }) {
|
|
465
487
|
const renderers = useBuiltinRenderers();
|
|
466
488
|
if (renderers.mermaid) {
|
|
467
|
-
return /* @__PURE__ */ (0,
|
|
489
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children: renderers.mermaid(entry) });
|
|
468
490
|
}
|
|
469
|
-
return /* @__PURE__ */ (0,
|
|
491
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MermaidSource, { entry });
|
|
470
492
|
}
|
|
471
493
|
|
|
472
494
|
// src/components/doc/DocScreenshot.tsx
|
|
473
|
-
var
|
|
495
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
474
496
|
function DocScreenshot({ entry }) {
|
|
475
497
|
const src = (0, import_url.isLocalFsPath)(entry.path) ? void 0 : (0, import_url.safeImageUrl)(entry.path);
|
|
476
498
|
if (!src) {
|
|
477
|
-
return /* @__PURE__ */ (0,
|
|
478
|
-
/* @__PURE__ */ (0,
|
|
479
|
-
/* @__PURE__ */ (0,
|
|
480
|
-
entry.alt ? /* @__PURE__ */ (0,
|
|
499
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
|
|
500
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "font-medium", children: "Screenshot unavailable" }),
|
|
501
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
502
|
+
entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.alt }) : null
|
|
481
503
|
] });
|
|
482
504
|
}
|
|
483
|
-
return /* @__PURE__ */ (0,
|
|
484
|
-
/* @__PURE__ */ (0,
|
|
505
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "my-3", children: [
|
|
506
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
485
507
|
"img",
|
|
486
508
|
{
|
|
487
509
|
src,
|
|
@@ -490,24 +512,24 @@ function DocScreenshot({ entry }) {
|
|
|
490
512
|
className: "max-w-full rounded-md border border-border"
|
|
491
513
|
}
|
|
492
514
|
),
|
|
493
|
-
entry.alt ? /* @__PURE__ */ (0,
|
|
515
|
+
entry.alt ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { className: "mt-1.5 text-xs text-muted-foreground", children: entry.alt }) : null
|
|
494
516
|
] });
|
|
495
517
|
}
|
|
496
518
|
|
|
497
519
|
// src/components/doc/DocVideo.tsx
|
|
498
|
-
var
|
|
520
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
499
521
|
function DocVideo({ entry }) {
|
|
500
522
|
if ((0, import_url.isLocalFsPath)(entry.path)) {
|
|
501
|
-
return /* @__PURE__ */ (0,
|
|
502
|
-
/* @__PURE__ */ (0,
|
|
503
|
-
/* @__PURE__ */ (0,
|
|
504
|
-
entry.caption ? /* @__PURE__ */ (0,
|
|
523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
|
|
524
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "font-medium", children: "Video unavailable" }),
|
|
525
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
526
|
+
entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("figcaption", { className: "mt-1.5 text-xs", children: entry.caption }) : null
|
|
505
527
|
] });
|
|
506
528
|
}
|
|
507
529
|
const src = (0, import_url.safeUrl)(entry.path);
|
|
508
530
|
const poster = (0, import_url.safeUrl)(entry.poster);
|
|
509
|
-
return /* @__PURE__ */ (0,
|
|
510
|
-
/* @__PURE__ */ (0,
|
|
531
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("figure", { className: "my-3", children: [
|
|
532
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
511
533
|
"video",
|
|
512
534
|
{
|
|
513
535
|
controls: true,
|
|
@@ -517,21 +539,21 @@ function DocVideo({ entry }) {
|
|
|
517
539
|
className: "max-w-full rounded-md border border-border"
|
|
518
540
|
}
|
|
519
541
|
),
|
|
520
|
-
entry.caption ? /* @__PURE__ */ (0,
|
|
542
|
+
entry.caption ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: entry.caption }) : null
|
|
521
543
|
] });
|
|
522
544
|
}
|
|
523
545
|
|
|
524
546
|
// src/components/doc/DocHtml.tsx
|
|
525
|
-
var
|
|
547
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
526
548
|
function DocHtml({ entry }) {
|
|
527
549
|
const height = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
528
550
|
const title = entry.title ?? "Embedded HTML";
|
|
529
551
|
const safeHref = (0, import_url.safeUrl)(entry.url ?? entry.path);
|
|
530
552
|
const frameProps = entry.content !== void 0 ? { srcDoc: entry.content } : { src: safeHref ?? "" };
|
|
531
|
-
return /* @__PURE__ */ (0,
|
|
532
|
-
/* @__PURE__ */ (0,
|
|
533
|
-
/* @__PURE__ */ (0,
|
|
534
|
-
safeHref ? /* @__PURE__ */ (0,
|
|
553
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
|
|
554
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("figcaption", { className: "flex items-center justify-between border-b border-border bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground", children: [
|
|
555
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: entry.title ?? "HTML" }),
|
|
556
|
+
safeHref ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
535
557
|
"a",
|
|
536
558
|
{
|
|
537
559
|
href: safeHref,
|
|
@@ -544,7 +566,7 @@ function DocHtml({ entry }) {
|
|
|
544
566
|
}
|
|
545
567
|
) : null
|
|
546
568
|
] }),
|
|
547
|
-
/* @__PURE__ */ (0,
|
|
569
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
548
570
|
"iframe",
|
|
549
571
|
{
|
|
550
572
|
...frameProps,
|
|
@@ -559,7 +581,7 @@ function DocHtml({ entry }) {
|
|
|
559
581
|
}
|
|
560
582
|
|
|
561
583
|
// src/components/doc/DocState.tsx
|
|
562
|
-
var
|
|
584
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
563
585
|
function DocState({ entry }) {
|
|
564
586
|
let json;
|
|
565
587
|
try {
|
|
@@ -567,20 +589,20 @@ function DocState({ entry }) {
|
|
|
567
589
|
} catch {
|
|
568
590
|
json = String(entry.value);
|
|
569
591
|
}
|
|
570
|
-
return /* @__PURE__ */ (0,
|
|
592
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CodeFigure, { label: entry.label ?? "State", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("code", { className: "font-mono text-xs language-json", children: json }) });
|
|
571
593
|
}
|
|
572
594
|
|
|
573
595
|
// src/components/doc/DocCustom.tsx
|
|
574
|
-
var
|
|
596
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
575
597
|
function DocCustom({ entry }) {
|
|
576
598
|
const renderers = useCustomRenderers();
|
|
577
599
|
const renderer = renderers[entry.type];
|
|
578
600
|
if (renderer) {
|
|
579
|
-
return /* @__PURE__ */ (0,
|
|
601
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: renderer(entry) });
|
|
580
602
|
}
|
|
581
|
-
return /* @__PURE__ */ (0,
|
|
582
|
-
/* @__PURE__ */ (0,
|
|
583
|
-
/* @__PURE__ */ (0,
|
|
603
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "my-2", "data-type": entry.type, children: [
|
|
604
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
|
|
605
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground", children: safeStringify2(entry.data) })
|
|
584
606
|
] });
|
|
585
607
|
}
|
|
586
608
|
function safeStringify2(value) {
|
|
@@ -592,64 +614,43 @@ function safeStringify2(value) {
|
|
|
592
614
|
}
|
|
593
615
|
|
|
594
616
|
// src/components/doc/DocEntry.tsx
|
|
595
|
-
var
|
|
617
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
596
618
|
function DocEntry({ entry }) {
|
|
597
619
|
switch (entry.kind) {
|
|
598
620
|
case "note":
|
|
599
|
-
return /* @__PURE__ */ (0,
|
|
621
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocNote, { entry });
|
|
600
622
|
case "tag":
|
|
601
|
-
return /* @__PURE__ */ (0,
|
|
623
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocTag, { entry });
|
|
602
624
|
case "kv":
|
|
603
|
-
return /* @__PURE__ */ (0,
|
|
625
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocKv, { entry });
|
|
604
626
|
case "code":
|
|
605
|
-
return /* @__PURE__ */ (0,
|
|
627
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocCode, { entry });
|
|
606
628
|
case "table":
|
|
607
|
-
return /* @__PURE__ */ (0,
|
|
629
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocTable, { entry });
|
|
608
630
|
case "link":
|
|
609
|
-
return /* @__PURE__ */ (0,
|
|
631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocLink, { entry });
|
|
610
632
|
case "section":
|
|
611
|
-
return /* @__PURE__ */ (0,
|
|
633
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocSection, { entry });
|
|
612
634
|
case "mermaid":
|
|
613
|
-
return /* @__PURE__ */ (0,
|
|
635
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocMermaid, { entry });
|
|
614
636
|
case "screenshot":
|
|
615
|
-
return /* @__PURE__ */ (0,
|
|
637
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocScreenshot, { entry });
|
|
616
638
|
case "video":
|
|
617
|
-
return /* @__PURE__ */ (0,
|
|
639
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocVideo, { entry });
|
|
618
640
|
case "html":
|
|
619
|
-
return /* @__PURE__ */ (0,
|
|
641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocHtml, { entry });
|
|
620
642
|
case "state":
|
|
621
|
-
return /* @__PURE__ */ (0,
|
|
643
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocState, { entry });
|
|
622
644
|
case "custom":
|
|
623
|
-
return /* @__PURE__ */ (0,
|
|
645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DocCustom, { entry });
|
|
624
646
|
}
|
|
625
647
|
}
|
|
626
648
|
|
|
627
649
|
// src/components/ReportDocEntries.tsx
|
|
628
|
-
var
|
|
650
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
629
651
|
function ReportDocEntries({ entries }) {
|
|
630
652
|
if (entries.length === 0) return null;
|
|
631
|
-
return /* @__PURE__ */ (0,
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
// src/lib/step-params.tsx
|
|
635
|
-
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
636
|
-
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
637
|
-
function highlightStepParams(text) {
|
|
638
|
-
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
639
|
-
if (matches.length === 0) return text;
|
|
640
|
-
const nodes = [];
|
|
641
|
-
let lastIndex = 0;
|
|
642
|
-
matches.forEach((match, i) => {
|
|
643
|
-
const start = match.index;
|
|
644
|
-
const end = start + match[0].length;
|
|
645
|
-
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
646
|
-
nodes.push(
|
|
647
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
648
|
-
);
|
|
649
|
-
lastIndex = end;
|
|
650
|
-
});
|
|
651
|
-
if (lastIndex < text.length) nodes.push(text.slice(lastIndex));
|
|
652
|
-
return nodes;
|
|
653
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_jsx_runtime18.Fragment, { children: entries.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DocEntry, { entry }, i)) });
|
|
653
654
|
}
|
|
654
655
|
|
|
655
656
|
// src/components/ReportSteps.tsx
|
|
@@ -668,9 +669,22 @@ var STEP_GLYPH_COLOR = {
|
|
|
668
669
|
};
|
|
669
670
|
function ReportSteps({ scenario }) {
|
|
670
671
|
if (scenario.steps.length === 0) return null;
|
|
671
|
-
|
|
672
|
+
const unasserted = new Set(
|
|
673
|
+
(0, import_assertive_steps.assertionState)(scenario.steps) === "unasserted" ? (0, import_assertive_steps.assertiveSteps)(scenario.steps).map((step) => step.id) : []
|
|
674
|
+
);
|
|
675
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
676
|
+
ReportStepItem,
|
|
677
|
+
{
|
|
678
|
+
step,
|
|
679
|
+
unasserted: unasserted.has(step.id)
|
|
680
|
+
},
|
|
681
|
+
step.id
|
|
682
|
+
)) });
|
|
672
683
|
}
|
|
673
|
-
function ReportStepItem({
|
|
684
|
+
function ReportStepItem({
|
|
685
|
+
step,
|
|
686
|
+
unasserted = false
|
|
687
|
+
}) {
|
|
674
688
|
const kw = step.keyword.toLowerCase();
|
|
675
689
|
const continuation = kw === "and" || kw === "but";
|
|
676
690
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
@@ -678,10 +692,23 @@ function ReportStepItem({ step }) {
|
|
|
678
692
|
{
|
|
679
693
|
id: step.id,
|
|
680
694
|
"data-status": step.status,
|
|
681
|
-
className: cn(
|
|
695
|
+
className: cn(
|
|
696
|
+
"py-1.5 text-[0.8125rem] leading-normal",
|
|
697
|
+
continuation && "pl-5"
|
|
698
|
+
),
|
|
682
699
|
children: [
|
|
683
700
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-baseline gap-2", children: [
|
|
684
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
701
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
702
|
+
"span",
|
|
703
|
+
{
|
|
704
|
+
"aria-hidden": true,
|
|
705
|
+
className: cn(
|
|
706
|
+
"w-4 shrink-0 text-center text-xs",
|
|
707
|
+
STEP_GLYPH_COLOR[step.status]
|
|
708
|
+
),
|
|
709
|
+
children: STEP_GLYPH[step.status] ?? "\u25CB"
|
|
710
|
+
}
|
|
711
|
+
),
|
|
685
712
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
686
713
|
"span",
|
|
687
714
|
{
|
|
@@ -693,6 +720,7 @@ function ReportStepItem({ step }) {
|
|
|
693
720
|
}
|
|
694
721
|
),
|
|
695
722
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
|
|
723
|
+
unasserted ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "shrink-0 rounded-full border border-pend-border bg-pend-bg px-2 py-0.5 text-[0.6875rem] font-medium text-pend", children: "No assertion" }) : null,
|
|
696
724
|
step.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: (0, import_duration.formatDuration)(step.durationMs) }) : null
|
|
697
725
|
] }),
|
|
698
726
|
step.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
@@ -1088,28 +1116,102 @@ function ScenarioRunHistory({ scenarioId }) {
|
|
|
1088
1116
|
] });
|
|
1089
1117
|
}
|
|
1090
1118
|
|
|
1091
|
-
// src/
|
|
1119
|
+
// src/components/ScenarioStaleness.tsx
|
|
1120
|
+
var import_react7 = require("react");
|
|
1121
|
+
|
|
1122
|
+
// src/lib/provenance.ts
|
|
1123
|
+
function formatRelativeAge(thenMs, nowMs) {
|
|
1124
|
+
const deltaMs = Math.max(0, nowMs - thenMs);
|
|
1125
|
+
const minutes = Math.floor(deltaMs / 6e4);
|
|
1126
|
+
if (minutes < 1) return "just now";
|
|
1127
|
+
if (minutes < 60) return `${minutes} minute${minutes === 1 ? "" : "s"} ago`;
|
|
1128
|
+
const hours = Math.floor(minutes / 60);
|
|
1129
|
+
if (hours < 24) return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
|
1130
|
+
const days = Math.floor(hours / 24);
|
|
1131
|
+
return `${days} day${days === 1 ? "" : "s"} ago`;
|
|
1132
|
+
}
|
|
1133
|
+
function isReportStale(lastRunMs, staleAfterDays, nowMs) {
|
|
1134
|
+
if (lastRunMs === void 0 || staleAfterDays <= 0) return false;
|
|
1135
|
+
return nowMs - lastRunMs >= staleAfterDays * 864e5;
|
|
1136
|
+
}
|
|
1137
|
+
var CI_DISPLAY_NAMES = {
|
|
1138
|
+
github: "GitHub Actions",
|
|
1139
|
+
gitlab: "GitLab CI",
|
|
1140
|
+
circleci: "CircleCI",
|
|
1141
|
+
jenkins: "Jenkins",
|
|
1142
|
+
azure: "Azure DevOps",
|
|
1143
|
+
buildkite: "Buildkite",
|
|
1144
|
+
travis: "Travis CI",
|
|
1145
|
+
ci: "CI"
|
|
1146
|
+
};
|
|
1147
|
+
function ciDisplayName(name) {
|
|
1148
|
+
return CI_DISPLAY_NAMES[name] ?? name;
|
|
1149
|
+
}
|
|
1150
|
+
function commitUrl(ci, sha) {
|
|
1151
|
+
const commitSha = ci?.commitSha ?? sha;
|
|
1152
|
+
if (!ci?.url || !commitSha) return void 0;
|
|
1153
|
+
const github = ci.url.match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)\/actions\/runs\//);
|
|
1154
|
+
if (github) return `${github[1]}/commit/${commitSha}`;
|
|
1155
|
+
const gitlab = ci.url.match(/^(https?:\/\/.+)\/-\/pipelines\//);
|
|
1156
|
+
if (gitlab) return `${gitlab[1]}/-/commit/${commitSha}`;
|
|
1157
|
+
return void 0;
|
|
1158
|
+
}
|
|
1159
|
+
function prUrl(ci) {
|
|
1160
|
+
if (!ci?.url || !ci.prNumber) return void 0;
|
|
1161
|
+
const github = ci.url.match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)\/actions\/runs\//);
|
|
1162
|
+
if (github) return `${github[1]}/pull/${ci.prNumber}`;
|
|
1163
|
+
return void 0;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
// src/interactive/scenario-freshness-context.tsx
|
|
1092
1167
|
var import_react6 = require("react");
|
|
1093
|
-
var
|
|
1168
|
+
var ScenarioFreshnessContext = (0, import_react6.createContext)(null);
|
|
1169
|
+
var ScenarioFreshnessProvider = ScenarioFreshnessContext.Provider;
|
|
1170
|
+
function useScenarioFreshness() {
|
|
1171
|
+
return (0, import_react6.useContext)(ScenarioFreshnessContext);
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
// src/components/ScenarioStaleness.tsx
|
|
1175
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1176
|
+
function ScenarioStaleness({ scenario }) {
|
|
1177
|
+
const freshness = useScenarioFreshness();
|
|
1178
|
+
const fixedNow = freshness?.nowMs;
|
|
1179
|
+
const [now, setNow] = (0, import_react7.useState)(fixedNow);
|
|
1180
|
+
(0, import_react7.useEffect)(() => {
|
|
1181
|
+
if (fixedNow === void 0) setNow(Date.now());
|
|
1182
|
+
}, [fixedNow]);
|
|
1183
|
+
if (!freshness || now === void 0) return null;
|
|
1184
|
+
const lastRunAtMs = scenario.lastRunAtMs;
|
|
1185
|
+
if (!lastRunAtMs || lastRunAtMs <= 0) return null;
|
|
1186
|
+
if (!isReportStale(lastRunAtMs, freshness.staleAfterDays, now)) return null;
|
|
1187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Badge, { variant: "outline", "aria-label": "Scenario freshness", children: [
|
|
1188
|
+
"Last ran ",
|
|
1189
|
+
formatRelativeAge(lastRunAtMs, now)
|
|
1190
|
+
] });
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// src/interactive/collapse-context.ts
|
|
1194
|
+
var import_react8 = require("react");
|
|
1195
|
+
var CollapseContext = (0, import_react8.createContext)(null);
|
|
1094
1196
|
var CollapseProvider = CollapseContext.Provider;
|
|
1095
1197
|
function useCollapse() {
|
|
1096
|
-
return (0,
|
|
1198
|
+
return (0, import_react8.useContext)(CollapseContext);
|
|
1097
1199
|
}
|
|
1098
1200
|
|
|
1099
1201
|
// src/interactive/scenario-actions.tsx
|
|
1100
|
-
var
|
|
1202
|
+
var import_react9 = require("react");
|
|
1101
1203
|
var import_scenario_markdown = require("executable-stories-core/utils/scenario-markdown");
|
|
1102
|
-
var ScenarioActionsContext = (0,
|
|
1204
|
+
var ScenarioActionsContext = (0, import_react9.createContext)(null);
|
|
1103
1205
|
var ScenarioActionsProvider = ScenarioActionsContext.Provider;
|
|
1104
1206
|
function useScenarioActions() {
|
|
1105
|
-
return (0,
|
|
1207
|
+
return (0, import_react9.useContext)(ScenarioActionsContext);
|
|
1106
1208
|
}
|
|
1107
1209
|
|
|
1108
1210
|
// src/components/ui/card.tsx
|
|
1109
1211
|
var React2 = require("react");
|
|
1110
|
-
var
|
|
1212
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1111
1213
|
function Card({ className, ...props }) {
|
|
1112
|
-
return /* @__PURE__ */ (0,
|
|
1214
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1113
1215
|
"div",
|
|
1114
1216
|
{
|
|
1115
1217
|
"data-slot": "card",
|
|
@@ -1122,7 +1224,7 @@ function Card({ className, ...props }) {
|
|
|
1122
1224
|
);
|
|
1123
1225
|
}
|
|
1124
1226
|
function CardHeader({ className, ...props }) {
|
|
1125
|
-
return /* @__PURE__ */ (0,
|
|
1227
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1126
1228
|
"div",
|
|
1127
1229
|
{
|
|
1128
1230
|
"data-slot": "card-header",
|
|
@@ -1135,7 +1237,7 @@ function CardHeader({ className, ...props }) {
|
|
|
1135
1237
|
);
|
|
1136
1238
|
}
|
|
1137
1239
|
function CardContent({ className, ...props }) {
|
|
1138
|
-
return /* @__PURE__ */ (0,
|
|
1240
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1139
1241
|
"div",
|
|
1140
1242
|
{
|
|
1141
1243
|
"data-slot": "card-content",
|
|
@@ -1149,13 +1251,13 @@ function CardContent({ className, ...props }) {
|
|
|
1149
1251
|
var React3 = require("react");
|
|
1150
1252
|
var import_menu = require("@base-ui/react/menu");
|
|
1151
1253
|
var import_lucide_react = require("lucide-react");
|
|
1152
|
-
var
|
|
1254
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1153
1255
|
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";
|
|
1154
1256
|
function DropdownMenu(props) {
|
|
1155
|
-
return /* @__PURE__ */ (0,
|
|
1257
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_menu.Menu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1156
1258
|
}
|
|
1157
1259
|
function DropdownMenuTrigger(props) {
|
|
1158
|
-
return /* @__PURE__ */ (0,
|
|
1260
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_menu.Menu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
1159
1261
|
}
|
|
1160
1262
|
function DropdownMenuContent({
|
|
1161
1263
|
className,
|
|
@@ -1163,14 +1265,14 @@ function DropdownMenuContent({
|
|
|
1163
1265
|
sideOffset = 4,
|
|
1164
1266
|
...props
|
|
1165
1267
|
}) {
|
|
1166
|
-
return /* @__PURE__ */ (0,
|
|
1268
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_menu.Menu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1167
1269
|
import_menu.Menu.Positioner,
|
|
1168
1270
|
{
|
|
1169
1271
|
"data-slot": "dropdown-menu-positioner",
|
|
1170
1272
|
className: "z-50",
|
|
1171
1273
|
align,
|
|
1172
1274
|
sideOffset,
|
|
1173
|
-
children: /* @__PURE__ */ (0,
|
|
1275
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1174
1276
|
import_menu.Menu.Popup,
|
|
1175
1277
|
{
|
|
1176
1278
|
"data-slot": "dropdown-menu-content",
|
|
@@ -1188,7 +1290,7 @@ function DropdownMenuItem({
|
|
|
1188
1290
|
className,
|
|
1189
1291
|
...props
|
|
1190
1292
|
}) {
|
|
1191
|
-
return /* @__PURE__ */ (0,
|
|
1293
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1192
1294
|
import_menu.Menu.Item,
|
|
1193
1295
|
{
|
|
1194
1296
|
"data-slot": "dropdown-menu-item",
|
|
@@ -1200,7 +1302,7 @@ function DropdownMenuItem({
|
|
|
1200
1302
|
|
|
1201
1303
|
// src/components/ReportScenario.tsx
|
|
1202
1304
|
var import_lucide_react2 = require("lucide-react");
|
|
1203
|
-
var
|
|
1305
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1204
1306
|
var STATUS_META = {
|
|
1205
1307
|
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
1206
1308
|
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
@@ -1216,7 +1318,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1216
1318
|
const collapsible = collapse !== null && !hideTitle;
|
|
1217
1319
|
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
1218
1320
|
const actions = useScenarioActions();
|
|
1219
|
-
return /* @__PURE__ */ (0,
|
|
1321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1220
1322
|
Card,
|
|
1221
1323
|
{
|
|
1222
1324
|
id: scenario.id,
|
|
@@ -1224,10 +1326,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1224
1326
|
...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
|
|
1225
1327
|
className: "gap-0 py-0",
|
|
1226
1328
|
children: [
|
|
1227
|
-
/* @__PURE__ */ (0,
|
|
1228
|
-
/* @__PURE__ */ (0,
|
|
1229
|
-
hideTitle ? null : /* @__PURE__ */ (0,
|
|
1230
|
-
collapsible ? /* @__PURE__ */ (0,
|
|
1329
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(CardHeader, { className: "px-4 py-3", children: [
|
|
1330
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
1331
|
+
hideTitle ? null : /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
1332
|
+
collapsible ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
1231
1333
|
"button",
|
|
1232
1334
|
{
|
|
1233
1335
|
type: "button",
|
|
@@ -1236,49 +1338,50 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1236
1338
|
"aria-controls": bodyId,
|
|
1237
1339
|
"aria-label": `Toggle ${scenario.title}`,
|
|
1238
1340
|
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
1239
|
-
children: /* @__PURE__ */ (0,
|
|
1341
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
1240
1342
|
}
|
|
1241
1343
|
) : null,
|
|
1242
|
-
/* @__PURE__ */ (0,
|
|
1243
|
-
/* @__PURE__ */ (0,
|
|
1344
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
1345
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: scenario.title })
|
|
1244
1346
|
] }),
|
|
1245
|
-
/* @__PURE__ */ (0,
|
|
1246
|
-
/* @__PURE__ */ (0,
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1347
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1348
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1349
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ScenarioStaleness, { scenario }),
|
|
1350
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: (0, import_duration3.formatDuration)(scenario.durationMs) }) : null,
|
|
1351
|
+
meta.showPill ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "sr-only", children: `Status: ${label}` }),
|
|
1352
|
+
actions ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(DropdownMenu, { children: [
|
|
1353
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
1251
1354
|
DropdownMenuTrigger,
|
|
1252
1355
|
{
|
|
1253
1356
|
"aria-label": `Actions for ${scenario.title}`,
|
|
1254
1357
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
1255
|
-
children: /* @__PURE__ */ (0,
|
|
1358
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react2.MoreHorizontalIcon, { "aria-hidden": true })
|
|
1256
1359
|
}
|
|
1257
1360
|
),
|
|
1258
|
-
/* @__PURE__ */ (0,
|
|
1259
|
-
/* @__PURE__ */ (0,
|
|
1260
|
-
/* @__PURE__ */ (0,
|
|
1361
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(DropdownMenuContent, { align: "end", children: [
|
|
1362
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
1363
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react2.LinkIcon, {}),
|
|
1261
1364
|
" Copy link"
|
|
1262
1365
|
] }),
|
|
1263
|
-
/* @__PURE__ */ (0,
|
|
1264
|
-
/* @__PURE__ */ (0,
|
|
1366
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
1367
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react2.FileTextIcon, {}),
|
|
1265
1368
|
" Copy as Markdown"
|
|
1266
1369
|
] }),
|
|
1267
|
-
/* @__PURE__ */ (0,
|
|
1268
|
-
/* @__PURE__ */ (0,
|
|
1370
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
1371
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react2.SparklesIcon, {}),
|
|
1269
1372
|
" Explain with AI"
|
|
1270
1373
|
] })
|
|
1271
1374
|
] })
|
|
1272
1375
|
] }) : null
|
|
1273
1376
|
] })
|
|
1274
1377
|
] }),
|
|
1275
|
-
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0,
|
|
1276
|
-
scenario.tags.map((t) => /* @__PURE__ */ (0,
|
|
1277
|
-
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0,
|
|
1378
|
+
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
|
|
1379
|
+
scenario.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
|
|
1380
|
+
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("li", { children: ticket.url ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
|
|
1278
1381
|
] }) : null
|
|
1279
1382
|
] }),
|
|
1280
|
-
/* @__PURE__ */ (0,
|
|
1281
|
-
scenario.errorMessage ? /* @__PURE__ */ (0,
|
|
1383
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
1384
|
+
scenario.errorMessage ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
1282
1385
|
"pre",
|
|
1283
1386
|
{
|
|
1284
1387
|
role: "alert",
|
|
@@ -1286,11 +1389,11 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1286
1389
|
children: scenario.errorMessage
|
|
1287
1390
|
}
|
|
1288
1391
|
) : null,
|
|
1289
|
-
/* @__PURE__ */ (0,
|
|
1290
|
-
/* @__PURE__ */ (0,
|
|
1291
|
-
scenario.docEntries.length > 0 ? /* @__PURE__ */ (0,
|
|
1292
|
-
/* @__PURE__ */ (0,
|
|
1293
|
-
/* @__PURE__ */ (0,
|
|
1392
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportStoryboard, { scenario }),
|
|
1393
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportSteps, { scenario }),
|
|
1394
|
+
scenario.docEntries.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
|
|
1395
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportAttachments, { attachments: scenario.attachments }),
|
|
1396
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ReportTrace, { spans: scenario.otelSpans })
|
|
1294
1397
|
] })
|
|
1295
1398
|
]
|
|
1296
1399
|
}
|
|
@@ -1298,28 +1401,28 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1298
1401
|
}
|
|
1299
1402
|
|
|
1300
1403
|
// src/components/ReportScenarioList.tsx
|
|
1301
|
-
var
|
|
1404
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1302
1405
|
function ReportScenarioList({ feature }) {
|
|
1303
|
-
return /* @__PURE__ */ (0,
|
|
1406
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_jsx_runtime28.Fragment, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ReportScenario, { scenario }, scenario.id)) });
|
|
1304
1407
|
}
|
|
1305
1408
|
|
|
1306
1409
|
// src/components/ReportFeatureIntro.tsx
|
|
1307
|
-
var
|
|
1410
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1308
1411
|
function ReportFeatureIntro({ feature }) {
|
|
1309
1412
|
const hasNarrative = Boolean(feature.narrative?.trim());
|
|
1310
1413
|
const hasGlossary = Boolean(feature.glossary?.length);
|
|
1311
1414
|
if (!hasNarrative && !hasGlossary) return null;
|
|
1312
|
-
return /* @__PURE__ */ (0,
|
|
1313
|
-
hasNarrative ? /* @__PURE__ */ (0,
|
|
1415
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3 border-l-2 border-border pl-4 text-sm", children: [
|
|
1416
|
+
hasNarrative ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1314
1417
|
"div",
|
|
1315
1418
|
{
|
|
1316
1419
|
className: "es-doc-prose prose prose-sm max-w-none text-muted-foreground",
|
|
1317
1420
|
dangerouslySetInnerHTML: { __html: safeMarkdownHtml(dedent(feature.narrative)) }
|
|
1318
1421
|
}
|
|
1319
1422
|
) : null,
|
|
1320
|
-
hasGlossary ? /* @__PURE__ */ (0,
|
|
1321
|
-
/* @__PURE__ */ (0,
|
|
1322
|
-
/* @__PURE__ */ (0,
|
|
1423
|
+
hasGlossary ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dl", { className: "grid gap-1.5", "aria-label": "Glossary", children: feature.glossary.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-wrap gap-x-2 text-xs", children: [
|
|
1424
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dt", { className: "font-medium text-foreground", children: entry.term }),
|
|
1425
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("dd", { className: "flex-1 text-muted-foreground", children: entry.definition })
|
|
1323
1426
|
] }, entry.term)) }) : null
|
|
1324
1427
|
] });
|
|
1325
1428
|
}
|
|
@@ -1331,7 +1434,7 @@ function featureKindLabel(kind) {
|
|
|
1331
1434
|
}
|
|
1332
1435
|
|
|
1333
1436
|
// src/components/ReportFeature.tsx
|
|
1334
|
-
var
|
|
1437
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1335
1438
|
function ReportFeature({ feature }) {
|
|
1336
1439
|
const titleId = `${feature.id}-title`;
|
|
1337
1440
|
const bodyId = `${feature.id}-body`;
|
|
@@ -1343,7 +1446,7 @@ function ReportFeature({ feature }) {
|
|
|
1343
1446
|
return (
|
|
1344
1447
|
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
1345
1448
|
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1346
|
-
/* @__PURE__ */ (0,
|
|
1449
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
1347
1450
|
"section",
|
|
1348
1451
|
{
|
|
1349
1452
|
id: feature.id,
|
|
@@ -1351,9 +1454,9 @@ function ReportFeature({ feature }) {
|
|
|
1351
1454
|
"aria-labelledby": titleId,
|
|
1352
1455
|
className: "flex flex-col gap-3",
|
|
1353
1456
|
children: [
|
|
1354
|
-
/* @__PURE__ */ (0,
|
|
1355
|
-
/* @__PURE__ */ (0,
|
|
1356
|
-
/* @__PURE__ */ (0,
|
|
1457
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1458
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "min-w-0", children: [
|
|
1459
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
1357
1460
|
"button",
|
|
1358
1461
|
{
|
|
1359
1462
|
type: "button",
|
|
@@ -1362,34 +1465,34 @@ function ReportFeature({ feature }) {
|
|
|
1362
1465
|
"aria-controls": bodyId,
|
|
1363
1466
|
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1364
1467
|
children: [
|
|
1365
|
-
/* @__PURE__ */ (0,
|
|
1366
|
-
/* @__PURE__ */ (0,
|
|
1468
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
|
|
1469
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "truncate", children: feature.title })
|
|
1367
1470
|
]
|
|
1368
1471
|
}
|
|
1369
1472
|
) : feature.title }),
|
|
1370
|
-
/* @__PURE__ */ (0,
|
|
1371
|
-
kindLabel ? /* @__PURE__ */ (0,
|
|
1372
|
-
/* @__PURE__ */ (0,
|
|
1473
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("p", { className: cn("mt-0.5 flex items-center gap-2 text-xs text-muted-foreground", collapse && "pl-5"), children: [
|
|
1474
|
+
kindLabel ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "shrink-0 rounded-sm bg-muted px-1.5 py-0.5 font-medium text-foreground", children: kindLabel }) : null,
|
|
1475
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "truncate font-mono", children: feature.sourceFile })
|
|
1373
1476
|
] })
|
|
1374
1477
|
] }),
|
|
1375
|
-
/* @__PURE__ */ (0,
|
|
1478
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
1376
1479
|
"p",
|
|
1377
1480
|
{
|
|
1378
1481
|
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1379
1482
|
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1380
1483
|
children: [
|
|
1381
|
-
/* @__PURE__ */ (0,
|
|
1484
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { children: [
|
|
1382
1485
|
s.passed,
|
|
1383
1486
|
" passed"
|
|
1384
1487
|
] }),
|
|
1385
|
-
/* @__PURE__ */ (0,
|
|
1386
|
-
/* @__PURE__ */ (0,
|
|
1488
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1489
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1387
1490
|
s.failed,
|
|
1388
1491
|
" failed"
|
|
1389
1492
|
] }),
|
|
1390
|
-
skipped > 0 ? /* @__PURE__ */ (0,
|
|
1391
|
-
/* @__PURE__ */ (0,
|
|
1392
|
-
/* @__PURE__ */ (0,
|
|
1493
|
+
skipped > 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
1494
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1495
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { children: [
|
|
1393
1496
|
skipped,
|
|
1394
1497
|
" skipped"
|
|
1395
1498
|
] })
|
|
@@ -1398,9 +1501,9 @@ function ReportFeature({ feature }) {
|
|
|
1398
1501
|
}
|
|
1399
1502
|
)
|
|
1400
1503
|
] }),
|
|
1401
|
-
/* @__PURE__ */ (0,
|
|
1402
|
-
/* @__PURE__ */ (0,
|
|
1403
|
-
/* @__PURE__ */ (0,
|
|
1504
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: [
|
|
1505
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ReportFeatureIntro, { feature }),
|
|
1506
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ReportScenarioList, { feature })
|
|
1404
1507
|
] })
|
|
1405
1508
|
]
|
|
1406
1509
|
}
|
|
@@ -1409,17 +1512,17 @@ function ReportFeature({ feature }) {
|
|
|
1409
1512
|
}
|
|
1410
1513
|
|
|
1411
1514
|
// src/components/ReportFeatureList.tsx
|
|
1412
|
-
var
|
|
1515
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1413
1516
|
function ReportFeatureList() {
|
|
1414
1517
|
const report = useReport();
|
|
1415
|
-
return /* @__PURE__ */ (0,
|
|
1518
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ReportFeature, { feature }, feature.id)) });
|
|
1416
1519
|
}
|
|
1417
1520
|
|
|
1418
1521
|
// src/components/ui/empty.tsx
|
|
1419
1522
|
var import_class_variance_authority2 = require("class-variance-authority");
|
|
1420
|
-
var
|
|
1523
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1421
1524
|
function Empty({ className, ...props }) {
|
|
1422
|
-
return /* @__PURE__ */ (0,
|
|
1525
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1423
1526
|
"div",
|
|
1424
1527
|
{
|
|
1425
1528
|
"data-slot": "empty",
|
|
@@ -1432,7 +1535,7 @@ function Empty({ className, ...props }) {
|
|
|
1432
1535
|
);
|
|
1433
1536
|
}
|
|
1434
1537
|
function EmptyHeader({ className, ...props }) {
|
|
1435
|
-
return /* @__PURE__ */ (0,
|
|
1538
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1436
1539
|
"div",
|
|
1437
1540
|
{
|
|
1438
1541
|
"data-slot": "empty-header",
|
|
@@ -1459,7 +1562,7 @@ var emptyMediaVariants = (0, import_class_variance_authority2.cva)(
|
|
|
1459
1562
|
}
|
|
1460
1563
|
);
|
|
1461
1564
|
function EmptyTitle({ className, ...props }) {
|
|
1462
|
-
return /* @__PURE__ */ (0,
|
|
1565
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1463
1566
|
"div",
|
|
1464
1567
|
{
|
|
1465
1568
|
"data-slot": "empty-title",
|
|
@@ -1470,16 +1573,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1470
1573
|
}
|
|
1471
1574
|
|
|
1472
1575
|
// src/components/ReportEmpty.tsx
|
|
1473
|
-
var
|
|
1576
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1474
1577
|
function ReportEmpty({ message }) {
|
|
1475
|
-
return /* @__PURE__ */ (0,
|
|
1578
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(EmptyHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
|
|
1476
1579
|
}
|
|
1477
1580
|
|
|
1478
1581
|
// src/components/ReportSummary.tsx
|
|
1479
|
-
var
|
|
1582
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1480
1583
|
function ReportSummary({ className }) {
|
|
1481
1584
|
const report = useReport();
|
|
1482
|
-
return /* @__PURE__ */ (0,
|
|
1585
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
1483
1586
|
ReportSummaryView,
|
|
1484
1587
|
{
|
|
1485
1588
|
summary: report.summary,
|
|
@@ -1505,7 +1608,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1505
1608
|
if (summary.pending > 0) {
|
|
1506
1609
|
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1507
1610
|
}
|
|
1508
|
-
return /* @__PURE__ */ (0,
|
|
1611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
1509
1612
|
"dl",
|
|
1510
1613
|
{
|
|
1511
1614
|
className: cn(
|
|
@@ -1518,17 +1621,17 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1518
1621
|
"aria-label": ariaLabel,
|
|
1519
1622
|
children: cards.map((c) => {
|
|
1520
1623
|
const tone = TONE[c.status];
|
|
1521
|
-
return /* @__PURE__ */ (0,
|
|
1624
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
1522
1625
|
"div",
|
|
1523
1626
|
{
|
|
1524
1627
|
"data-status": c.status,
|
|
1525
1628
|
className: "rounded-lg border bg-card px-4 py-3",
|
|
1526
1629
|
children: [
|
|
1527
|
-
/* @__PURE__ */ (0,
|
|
1528
|
-
/* @__PURE__ */ (0,
|
|
1630
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
|
|
1631
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1529
1632
|
c.label
|
|
1530
1633
|
] }),
|
|
1531
|
-
/* @__PURE__ */ (0,
|
|
1634
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
|
|
1532
1635
|
]
|
|
1533
1636
|
},
|
|
1534
1637
|
c.status
|
|
@@ -1540,39 +1643,7 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1540
1643
|
|
|
1541
1644
|
// src/components/ReportMeta.tsx
|
|
1542
1645
|
var import_duration4 = require("executable-stories-core/utils/duration");
|
|
1543
|
-
|
|
1544
|
-
// src/lib/provenance.ts
|
|
1545
|
-
var CI_DISPLAY_NAMES = {
|
|
1546
|
-
github: "GitHub Actions",
|
|
1547
|
-
gitlab: "GitLab CI",
|
|
1548
|
-
circleci: "CircleCI",
|
|
1549
|
-
jenkins: "Jenkins",
|
|
1550
|
-
azure: "Azure DevOps",
|
|
1551
|
-
buildkite: "Buildkite",
|
|
1552
|
-
travis: "Travis CI",
|
|
1553
|
-
ci: "CI"
|
|
1554
|
-
};
|
|
1555
|
-
function ciDisplayName(name) {
|
|
1556
|
-
return CI_DISPLAY_NAMES[name] ?? name;
|
|
1557
|
-
}
|
|
1558
|
-
function commitUrl(ci, sha) {
|
|
1559
|
-
const commitSha = ci?.commitSha ?? sha;
|
|
1560
|
-
if (!ci?.url || !commitSha) return void 0;
|
|
1561
|
-
const github = ci.url.match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)\/actions\/runs\//);
|
|
1562
|
-
if (github) return `${github[1]}/commit/${commitSha}`;
|
|
1563
|
-
const gitlab = ci.url.match(/^(https?:\/\/.+)\/-\/pipelines\//);
|
|
1564
|
-
if (gitlab) return `${gitlab[1]}/-/commit/${commitSha}`;
|
|
1565
|
-
return void 0;
|
|
1566
|
-
}
|
|
1567
|
-
function prUrl(ci) {
|
|
1568
|
-
if (!ci?.url || !ci.prNumber) return void 0;
|
|
1569
|
-
const github = ci.url.match(/^(https?:\/\/[^/]+\/[^/]+\/[^/]+)\/actions\/runs\//);
|
|
1570
|
-
if (github) return `${github[1]}/pull/${ci.prNumber}`;
|
|
1571
|
-
return void 0;
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
|
-
// src/components/ReportMeta.tsx
|
|
1575
|
-
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1646
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
1576
1647
|
function ReportMeta() {
|
|
1577
1648
|
const report = useReport();
|
|
1578
1649
|
const items = [];
|
|
@@ -1595,13 +1666,13 @@ function ReportMeta() {
|
|
|
1595
1666
|
const short = sha.slice(0, 8);
|
|
1596
1667
|
items.push({
|
|
1597
1668
|
label: "Commit",
|
|
1598
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1669
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1599
1670
|
});
|
|
1600
1671
|
}
|
|
1601
1672
|
if (report.ci) {
|
|
1602
1673
|
items.push({
|
|
1603
1674
|
label: "CI",
|
|
1604
|
-
value: report.ci.url ? /* @__PURE__ */ (0,
|
|
1675
|
+
value: report.ci.url ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1605
1676
|
ciDisplayName(report.ci.name),
|
|
1606
1677
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1607
1678
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1612,7 +1683,7 @@ function ReportMeta() {
|
|
|
1612
1683
|
const label = `#${report.ci.prNumber}`;
|
|
1613
1684
|
items.push({
|
|
1614
1685
|
label: "PR",
|
|
1615
|
-
value: url ? /* @__PURE__ */ (0,
|
|
1686
|
+
value: url ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1616
1687
|
});
|
|
1617
1688
|
}
|
|
1618
1689
|
if (items.length === 0) return null;
|
|
@@ -1620,48 +1691,48 @@ function ReportMeta() {
|
|
|
1620
1691
|
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1621
1692
|
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1622
1693
|
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1623
|
-
/* @__PURE__ */ (0,
|
|
1624
|
-
/* @__PURE__ */ (0,
|
|
1625
|
-
/* @__PURE__ */ (0,
|
|
1694
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
|
|
1695
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.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: [
|
|
1696
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1626
1697
|
"Run details"
|
|
1627
1698
|
] }),
|
|
1628
|
-
/* @__PURE__ */ (0,
|
|
1629
|
-
/* @__PURE__ */ (0,
|
|
1630
|
-
/* @__PURE__ */ (0,
|
|
1699
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.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_runtime35.jsxs)("div", { className: "flex items-baseline gap-1.5", children: [
|
|
1700
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("dt", { className: "font-medium", children: item.label }),
|
|
1701
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1631
1702
|
] }, item.label)) })
|
|
1632
1703
|
] })
|
|
1633
1704
|
);
|
|
1634
1705
|
}
|
|
1635
1706
|
|
|
1636
1707
|
// src/components/ReportSchemaError.tsx
|
|
1637
|
-
var
|
|
1708
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
1638
1709
|
function ReportSchemaError({ error }) {
|
|
1639
|
-
return /* @__PURE__ */ (0,
|
|
1640
|
-
/* @__PURE__ */ (0,
|
|
1641
|
-
/* @__PURE__ */ (0,
|
|
1642
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0,
|
|
1710
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1711
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("strong", { children: "Report could not be displayed." }) }),
|
|
1712
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { children: error.message }),
|
|
1713
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("p", { children: [
|
|
1643
1714
|
"The report bundle is newer than this version of ",
|
|
1644
|
-
/* @__PURE__ */ (0,
|
|
1715
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("code", { children: "executable-stories-react" }),
|
|
1645
1716
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1646
1717
|
] }) : null,
|
|
1647
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0,
|
|
1648
|
-
/* @__PURE__ */ (0,
|
|
1718
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("details", { children: [
|
|
1719
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("summary", { children: [
|
|
1649
1720
|
error.issues.length,
|
|
1650
1721
|
" validation issue",
|
|
1651
1722
|
error.issues.length === 1 ? "" : "s"
|
|
1652
1723
|
] }),
|
|
1653
|
-
/* @__PURE__ */ (0,
|
|
1724
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1654
1725
|
] }) : null
|
|
1655
1726
|
] });
|
|
1656
1727
|
}
|
|
1657
1728
|
|
|
1658
1729
|
// src/components/ReportShell.tsx
|
|
1659
|
-
var
|
|
1730
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
1660
1731
|
function ReportTitleBlock({ title }) {
|
|
1661
|
-
return /* @__PURE__ */ (0,
|
|
1662
|
-
/* @__PURE__ */ (0,
|
|
1663
|
-
/* @__PURE__ */ (0,
|
|
1664
|
-
/* @__PURE__ */ (0,
|
|
1732
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
|
|
1733
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("h1", { children: title ?? "Story Report" }),
|
|
1734
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportSummary, {}),
|
|
1735
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportMeta, {})
|
|
1665
1736
|
] });
|
|
1666
1737
|
}
|
|
1667
1738
|
function ReportErrorShell({
|
|
@@ -1670,22 +1741,22 @@ function ReportErrorShell({
|
|
|
1670
1741
|
title,
|
|
1671
1742
|
dataTheme
|
|
1672
1743
|
}) {
|
|
1673
|
-
return /* @__PURE__ */ (0,
|
|
1744
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ReportSchemaError, { error }) });
|
|
1674
1745
|
}
|
|
1675
1746
|
|
|
1676
1747
|
// src/components/Report.tsx
|
|
1677
|
-
var
|
|
1748
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
1678
1749
|
function Report(props) {
|
|
1679
1750
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1680
1751
|
const result = unwrapReport(report);
|
|
1681
1752
|
if (!result.ok) {
|
|
1682
|
-
return /* @__PURE__ */ (0,
|
|
1753
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1683
1754
|
}
|
|
1684
1755
|
const data = result.data;
|
|
1685
1756
|
const hasContent = data.features.length > 0;
|
|
1686
|
-
return /* @__PURE__ */ (0,
|
|
1687
|
-
/* @__PURE__ */ (0,
|
|
1688
|
-
hasContent ? /* @__PURE__ */ (0,
|
|
1757
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1758
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("header", { className: "es-report-header", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportTitleBlock, { title }) }),
|
|
1759
|
+
hasContent ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportFeatureList, {}) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ReportEmpty, {})
|
|
1689
1760
|
] }) });
|
|
1690
1761
|
}
|
|
1691
1762
|
|
|
@@ -1746,13 +1817,13 @@ function renderReportToHtml(report, options = {}) {
|
|
|
1746
1817
|
scenarioHistory
|
|
1747
1818
|
} = options;
|
|
1748
1819
|
const markup = (0, import_server.renderToStaticMarkup)(
|
|
1749
|
-
(0,
|
|
1820
|
+
(0, import_react10.createElement)(Report, { report, title })
|
|
1750
1821
|
);
|
|
1751
1822
|
const cdn = cdnAssets(syntaxHighlighting, mermaid);
|
|
1752
1823
|
const parsed = unwrapReport(report);
|
|
1753
1824
|
const rawReport = parsed.ok ? parsed.data : void 0;
|
|
1754
1825
|
const interactive = islandScript.length > 0 && rawReport !== void 0;
|
|
1755
|
-
const dataScript =
|
|
1826
|
+
const dataScript = rawReport !== void 0 ? `<script type="application/json" id="${DATA_ID}">${escapeJsonForScript(JSON.stringify(rawReport))}</script>` : "";
|
|
1756
1827
|
const historyScript = interactive && scenarioHistory && Object.keys(scenarioHistory).length > 0 ? `<script type="application/json" id="${HISTORY_ID}">${escapeJsonForScript(JSON.stringify(scenarioHistory))}</script>` : "";
|
|
1757
1828
|
const islandTag = interactive ? `<script>${islandScript}</script>` : "";
|
|
1758
1829
|
const cdnBody = interactive ? "" : cdn.body;
|