executable-stories-react 0.4.1 → 0.5.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 +303 -240
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +301 -238
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +843 -471
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +10 -1
- package/dist/interactive.d.ts +10 -1
- package/dist/interactive.js +806 -443
- package/dist/interactive.js.map +1 -1
- package/dist/report-island.global.js +103 -59
- package/dist/ssr.cjs +269 -206
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.js +269 -206
- package/dist/ssr.js.map +1 -1
- package/dist/styles.css +18 -42
- package/dist/tailwind.css +1 -1
- package/package.json +1 -1
package/dist/ssr.js
CHANGED
|
@@ -99,11 +99,15 @@ var badgeVariants = cva(
|
|
|
99
99
|
outline: "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
100
100
|
ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
101
101
|
link: "text-primary underline-offset-4 [a&]:hover:underline",
|
|
102
|
-
|
|
102
|
+
// Pass/skip/pending are the quiet states: outline + coloured text, no
|
|
103
|
+
// fill, so a green report reads calm. Only `failed` keeps a tinted
|
|
104
|
+
// fill, making it the single loud badge on the page, so red pops the
|
|
105
|
+
// instant something breaks. Colour-as-accent, matching the KPI cards.
|
|
106
|
+
passed: "border-pass-border text-pass font-mono uppercase",
|
|
103
107
|
failed: "border-fail-border bg-fail-bg text-fail font-mono uppercase",
|
|
104
|
-
skipped: "border-skip-border
|
|
105
|
-
pending: "border-pend-border
|
|
106
|
-
tag: "border-
|
|
108
|
+
skipped: "border-skip-border text-skip font-mono uppercase",
|
|
109
|
+
pending: "border-pend-border text-pend font-mono uppercase",
|
|
110
|
+
tag: "border-border text-muted-foreground font-mono font-medium [a&]:hover:bg-muted"
|
|
107
111
|
}
|
|
108
112
|
},
|
|
109
113
|
defaultVariants: {
|
|
@@ -656,7 +660,7 @@ function ReportTrace({ spans }) {
|
|
|
656
660
|
{
|
|
657
661
|
className: "min-w-0 flex-1 truncate text-foreground",
|
|
658
662
|
style: { paddingLeft: `${row.depth * 12}px` },
|
|
659
|
-
title: row.statusMessage ? `${row.name}
|
|
663
|
+
title: row.statusMessage ? `${row.name}: ${row.statusMessage}` : row.name,
|
|
660
664
|
children: row.name
|
|
661
665
|
}
|
|
662
666
|
),
|
|
@@ -793,7 +797,7 @@ function Card({ className, ...props }) {
|
|
|
793
797
|
{
|
|
794
798
|
"data-slot": "card",
|
|
795
799
|
className: cn(
|
|
796
|
-
"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-
|
|
800
|
+
"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-xs",
|
|
797
801
|
className
|
|
798
802
|
),
|
|
799
803
|
...props
|
|
@@ -824,52 +828,89 @@ function CardContent({ className, ...props }) {
|
|
|
824
828
|
);
|
|
825
829
|
}
|
|
826
830
|
|
|
827
|
-
// src/components/
|
|
831
|
+
// src/components/ui/dropdown-menu.tsx
|
|
832
|
+
import "react";
|
|
833
|
+
import { Menu as MenuPrimitive } from "@base-ui/react/menu";
|
|
834
|
+
import { CheckIcon } from "lucide-react";
|
|
828
835
|
import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
829
|
-
var
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
};
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
836
|
+
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";
|
|
837
|
+
function DropdownMenu(props) {
|
|
838
|
+
return /* @__PURE__ */ jsx22(MenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
839
|
+
}
|
|
840
|
+
function DropdownMenuTrigger(props) {
|
|
841
|
+
return /* @__PURE__ */ jsx22(MenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
|
|
842
|
+
}
|
|
843
|
+
function DropdownMenuContent({
|
|
844
|
+
className,
|
|
845
|
+
align = "end",
|
|
846
|
+
sideOffset = 4,
|
|
847
|
+
...props
|
|
848
|
+
}) {
|
|
849
|
+
return /* @__PURE__ */ jsx22(MenuPrimitive.Portal, { children: /* @__PURE__ */ jsx22(
|
|
850
|
+
MenuPrimitive.Positioner,
|
|
851
|
+
{
|
|
852
|
+
"data-slot": "dropdown-menu-positioner",
|
|
853
|
+
className: "z-50",
|
|
854
|
+
align,
|
|
855
|
+
sideOffset,
|
|
856
|
+
children: /* @__PURE__ */ jsx22(
|
|
857
|
+
MenuPrimitive.Popup,
|
|
858
|
+
{
|
|
859
|
+
"data-slot": "dropdown-menu-content",
|
|
860
|
+
className: cn(
|
|
861
|
+
"z-50 min-w-[11rem] origin-[var(--transform-origin)] overflow-hidden rounded-md border border-border bg-popover p-1 font-sans text-sm text-popover-foreground shadow-md transition-[opacity,transform] data-[ending-style]:scale-95 data-[ending-style]:opacity-0 data-[starting-style]:scale-95 data-[starting-style]:opacity-0",
|
|
862
|
+
className
|
|
863
|
+
),
|
|
864
|
+
...props
|
|
865
|
+
}
|
|
866
|
+
)
|
|
867
|
+
}
|
|
868
|
+
) });
|
|
869
|
+
}
|
|
870
|
+
function DropdownMenuItem({
|
|
871
|
+
className,
|
|
872
|
+
...props
|
|
873
|
+
}) {
|
|
874
|
+
return /* @__PURE__ */ jsx22(
|
|
875
|
+
MenuPrimitive.Item,
|
|
876
|
+
{
|
|
877
|
+
"data-slot": "dropdown-menu-item",
|
|
878
|
+
className: cn(itemClasses, className),
|
|
879
|
+
...props
|
|
880
|
+
}
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// src/components/ReportScenario.tsx
|
|
885
|
+
import { LinkIcon, FileTextIcon, SparklesIcon, MoreHorizontalIcon } from "lucide-react";
|
|
886
|
+
import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
887
|
+
var STATUS_META = {
|
|
888
|
+
passed: { label: "Passed", glyph: "\u2713", glyphColor: "text-pass", badgeVariant: "passed", showPill: false },
|
|
889
|
+
failed: { label: "Failed", glyph: "\u2717", glyphColor: "text-fail", badgeVariant: "failed", showPill: true },
|
|
890
|
+
skipped: { label: "Skipped", glyph: "\u25CB", glyphColor: "text-skip", badgeVariant: "skipped", showPill: true },
|
|
891
|
+
pending: { label: "Pending", glyph: "\u25CB", glyphColor: "text-pend", badgeVariant: "pending", showPill: true }
|
|
852
892
|
};
|
|
853
893
|
function ReportScenario({ scenario, hideTitle = false }) {
|
|
854
894
|
const titleId = `${scenario.id}-title`;
|
|
855
895
|
const bodyId = `${scenario.id}-body`;
|
|
856
|
-
const
|
|
896
|
+
const meta = STATUS_META[scenario.status];
|
|
897
|
+
const label = scenario.planned ? "Planned" : meta.label;
|
|
857
898
|
const collapse = useCollapse();
|
|
858
899
|
const collapsible = collapse !== null && !hideTitle;
|
|
859
900
|
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
860
901
|
const actions = useScenarioActions();
|
|
861
|
-
return /* @__PURE__ */
|
|
902
|
+
return /* @__PURE__ */ jsxs15(
|
|
862
903
|
Card,
|
|
863
904
|
{
|
|
864
905
|
id: scenario.id,
|
|
865
906
|
"data-status": scenario.status,
|
|
866
|
-
...hideTitle ? { "aria-label": `${scenario.title}
|
|
907
|
+
...hideTitle ? { "aria-label": `${scenario.title}, ${label}` } : { "aria-labelledby": titleId },
|
|
867
908
|
className: "gap-0 py-0",
|
|
868
909
|
children: [
|
|
869
|
-
/* @__PURE__ */
|
|
870
|
-
/* @__PURE__ */
|
|
871
|
-
hideTitle ? null : /* @__PURE__ */
|
|
872
|
-
collapsible ? /* @__PURE__ */
|
|
910
|
+
/* @__PURE__ */ jsxs15(CardHeader, { className: "px-4 py-3", children: [
|
|
911
|
+
/* @__PURE__ */ jsxs15("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
912
|
+
hideTitle ? null : /* @__PURE__ */ jsxs15("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
913
|
+
collapsible ? /* @__PURE__ */ jsx23(
|
|
873
914
|
"button",
|
|
874
915
|
{
|
|
875
916
|
type: "button",
|
|
@@ -878,60 +919,49 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
878
919
|
"aria-controls": bodyId,
|
|
879
920
|
"aria-label": `Toggle ${scenario.title}`,
|
|
880
921
|
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
881
|
-
children: /* @__PURE__ */
|
|
922
|
+
children: /* @__PURE__ */ jsx23("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
882
923
|
}
|
|
883
924
|
) : null,
|
|
884
|
-
/* @__PURE__ */
|
|
885
|
-
/* @__PURE__ */
|
|
925
|
+
/* @__PURE__ */ jsx23("span", { "aria-hidden": true, className: cn("text-sm leading-none", meta.glyphColor), children: meta.glyph }),
|
|
926
|
+
/* @__PURE__ */ jsx23("span", { children: scenario.title })
|
|
886
927
|
] }),
|
|
887
|
-
/* @__PURE__ */
|
|
888
|
-
/* @__PURE__ */
|
|
889
|
-
scenario.durationMs > 0 ? /* @__PURE__ */
|
|
890
|
-
/* @__PURE__ */
|
|
891
|
-
actions ? /* @__PURE__ */
|
|
892
|
-
/* @__PURE__ */
|
|
893
|
-
|
|
894
|
-
{
|
|
895
|
-
type: "button",
|
|
896
|
-
onClick: () => actions.copyLink(scenario),
|
|
897
|
-
"aria-label": `Copy link to ${scenario.title}`,
|
|
898
|
-
title: "Copy permalink",
|
|
899
|
-
className: "cursor-pointer rounded px-1 py-0.5 font-mono text-[0.625rem] text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
900
|
-
children: "link"
|
|
901
|
-
}
|
|
902
|
-
),
|
|
903
|
-
/* @__PURE__ */ jsx22(
|
|
904
|
-
"button",
|
|
928
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
929
|
+
/* @__PURE__ */ jsx23(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
930
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ jsx23("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(scenario.durationMs) }) : null,
|
|
931
|
+
meta.showPill ? /* @__PURE__ */ jsx23(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ jsx23("span", { className: "sr-only", children: `Status: ${label}` }),
|
|
932
|
+
actions ? /* @__PURE__ */ jsxs15(DropdownMenu, { children: [
|
|
933
|
+
/* @__PURE__ */ jsx23(
|
|
934
|
+
DropdownMenuTrigger,
|
|
905
935
|
{
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
"aria-
|
|
909
|
-
title: "Copy as Markdown",
|
|
910
|
-
className: "cursor-pointer rounded px-1 py-0.5 font-mono text-[0.625rem] text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
911
|
-
children: "md"
|
|
936
|
+
"aria-label": `Actions for ${scenario.title}`,
|
|
937
|
+
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
938
|
+
children: /* @__PURE__ */ jsx23(MoreHorizontalIcon, { "aria-hidden": true })
|
|
912
939
|
}
|
|
913
940
|
),
|
|
914
|
-
/* @__PURE__ */
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
941
|
+
/* @__PURE__ */ jsxs15(DropdownMenuContent, { align: "end", children: [
|
|
942
|
+
/* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: () => actions.copyLink(scenario), children: [
|
|
943
|
+
/* @__PURE__ */ jsx23(LinkIcon, {}),
|
|
944
|
+
" Copy link"
|
|
945
|
+
] }),
|
|
946
|
+
/* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: () => actions.copyMarkdown(scenario), children: [
|
|
947
|
+
/* @__PURE__ */ jsx23(FileTextIcon, {}),
|
|
948
|
+
" Copy as Markdown"
|
|
949
|
+
] }),
|
|
950
|
+
/* @__PURE__ */ jsxs15(DropdownMenuItem, { onClick: () => actions.copyPrompt(scenario), children: [
|
|
951
|
+
/* @__PURE__ */ jsx23(SparklesIcon, {}),
|
|
952
|
+
" Explain with AI"
|
|
953
|
+
] })
|
|
954
|
+
] })
|
|
925
955
|
] }) : null
|
|
926
956
|
] })
|
|
927
957
|
] }),
|
|
928
|
-
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */
|
|
929
|
-
scenario.tags.map((t) => /* @__PURE__ */
|
|
930
|
-
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */
|
|
958
|
+
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs15("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
|
|
959
|
+
scenario.tags.map((t) => /* @__PURE__ */ jsx23("li", { children: /* @__PURE__ */ jsx23(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
|
|
960
|
+
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ jsx23("li", { children: ticket.url ? /* @__PURE__ */ jsx23("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ jsx23(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ jsx23(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
|
|
931
961
|
] }) : null
|
|
932
962
|
] }),
|
|
933
|
-
/* @__PURE__ */
|
|
934
|
-
scenario.errorMessage ? /* @__PURE__ */
|
|
963
|
+
/* @__PURE__ */ jsxs15(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
964
|
+
scenario.errorMessage ? /* @__PURE__ */ jsx23(
|
|
935
965
|
"pre",
|
|
936
966
|
{
|
|
937
967
|
role: "alert",
|
|
@@ -939,10 +969,10 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
939
969
|
children: scenario.errorMessage
|
|
940
970
|
}
|
|
941
971
|
) : null,
|
|
942
|
-
/* @__PURE__ */
|
|
943
|
-
scenario.docEntries.length > 0 ? /* @__PURE__ */
|
|
944
|
-
/* @__PURE__ */
|
|
945
|
-
/* @__PURE__ */
|
|
972
|
+
/* @__PURE__ */ jsx23(ReportSteps, { scenario }),
|
|
973
|
+
scenario.docEntries.length > 0 ? /* @__PURE__ */ jsx23("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ jsx23(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
|
|
974
|
+
/* @__PURE__ */ jsx23(ReportAttachments, { attachments: scenario.attachments }),
|
|
975
|
+
/* @__PURE__ */ jsx23(ReportTrace, { spans: scenario.otelSpans })
|
|
946
976
|
] })
|
|
947
977
|
]
|
|
948
978
|
}
|
|
@@ -950,13 +980,13 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
950
980
|
}
|
|
951
981
|
|
|
952
982
|
// src/components/ReportScenarioList.tsx
|
|
953
|
-
import { Fragment as Fragment8, jsx as
|
|
983
|
+
import { Fragment as Fragment8, jsx as jsx24 } from "react/jsx-runtime";
|
|
954
984
|
function ReportScenarioList({ feature }) {
|
|
955
|
-
return /* @__PURE__ */
|
|
985
|
+
return /* @__PURE__ */ jsx24(Fragment8, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ jsx24(ReportScenario, { scenario }, scenario.id)) });
|
|
956
986
|
}
|
|
957
987
|
|
|
958
988
|
// src/components/ReportFeature.tsx
|
|
959
|
-
import { jsx as
|
|
989
|
+
import { Fragment as Fragment9, jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
960
990
|
function ReportFeature({ feature }) {
|
|
961
991
|
const titleId = `${feature.id}-title`;
|
|
962
992
|
const bodyId = `${feature.id}-body`;
|
|
@@ -964,74 +994,80 @@ function ReportFeature({ feature }) {
|
|
|
964
994
|
const skipped = s.skipped + s.pending;
|
|
965
995
|
const collapse = useCollapse();
|
|
966
996
|
const collapsed = collapse?.isCollapsed(feature.id) ?? false;
|
|
967
|
-
return
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
"
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
997
|
+
return (
|
|
998
|
+
// Suite = a section heading + a divider, NOT another bordered card. Drops a
|
|
999
|
+
// layer of nesting so the scenario cards below read as the primary unit.
|
|
1000
|
+
/* @__PURE__ */ jsxs16(
|
|
1001
|
+
"section",
|
|
1002
|
+
{
|
|
1003
|
+
id: feature.id,
|
|
1004
|
+
"data-slot": "feature",
|
|
1005
|
+
"aria-labelledby": titleId,
|
|
1006
|
+
className: "flex flex-col gap-3",
|
|
1007
|
+
children: [
|
|
1008
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-end justify-between gap-4 border-b border-border pb-2", children: [
|
|
1009
|
+
/* @__PURE__ */ jsxs16("div", { className: "min-w-0", children: [
|
|
1010
|
+
/* @__PURE__ */ jsx25("h2", { id: titleId, className: "text-base font-semibold tracking-tight text-foreground", children: collapse ? /* @__PURE__ */ jsxs16(
|
|
1011
|
+
"button",
|
|
1012
|
+
{
|
|
1013
|
+
type: "button",
|
|
1014
|
+
onClick: () => collapse.toggle(feature.id),
|
|
1015
|
+
"aria-expanded": !collapsed,
|
|
1016
|
+
"aria-controls": bodyId,
|
|
1017
|
+
className: "flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80",
|
|
1018
|
+
children: [
|
|
1019
|
+
/* @__PURE__ */ jsx25("span", { "aria-hidden": true, className: cn("shrink-0 text-xs text-muted-foreground transition-transform", !collapsed && "rotate-90"), children: "\u25B8" }),
|
|
1020
|
+
/* @__PURE__ */ jsx25("span", { className: "truncate", children: feature.title })
|
|
1021
|
+
]
|
|
1022
|
+
}
|
|
1023
|
+
) : feature.title }),
|
|
1024
|
+
/* @__PURE__ */ jsx25("p", { className: cn("mt-0.5 truncate font-mono text-xs text-muted-foreground", collapse && "pl-5"), children: feature.sourceFile })
|
|
1025
|
+
] }),
|
|
1026
|
+
/* @__PURE__ */ jsxs16(
|
|
1027
|
+
"p",
|
|
979
1028
|
{
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1029
|
+
className: "flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground",
|
|
1030
|
+
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1031
|
+
children: [
|
|
1032
|
+
/* @__PURE__ */ jsxs16("span", { children: [
|
|
1033
|
+
s.passed,
|
|
1034
|
+
" passed"
|
|
1035
|
+
] }),
|
|
1036
|
+
/* @__PURE__ */ jsx25("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1037
|
+
/* @__PURE__ */ jsxs16("span", { className: cn(s.failed > 0 && "font-medium text-fail"), children: [
|
|
1038
|
+
s.failed,
|
|
1039
|
+
" failed"
|
|
1040
|
+
] }),
|
|
1041
|
+
skipped > 0 ? /* @__PURE__ */ jsxs16(Fragment9, { children: [
|
|
1042
|
+
/* @__PURE__ */ jsx25("span", { "aria-hidden": true, children: "\xB7" }),
|
|
1043
|
+
/* @__PURE__ */ jsxs16("span", { children: [
|
|
1044
|
+
skipped,
|
|
1045
|
+
" skipped"
|
|
1046
|
+
] })
|
|
1047
|
+
] }) : null
|
|
1048
|
+
]
|
|
987
1049
|
}
|
|
988
|
-
)
|
|
989
|
-
/* @__PURE__ */ jsxs15("div", { className: "min-w-0", children: [
|
|
990
|
-
/* @__PURE__ */ jsx24("h2", { id: titleId, className: "text-sm font-semibold tracking-tight text-foreground", children: feature.title }),
|
|
991
|
-
/* @__PURE__ */ jsx24("p", { className: "mt-0.5 truncate font-mono text-xs text-muted-foreground", children: feature.sourceFile })
|
|
992
|
-
] })
|
|
1050
|
+
)
|
|
993
1051
|
] }),
|
|
994
|
-
/* @__PURE__ */
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
className: "flex shrink-0 items-center gap-2.5 font-mono text-xs font-medium",
|
|
999
|
-
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
1000
|
-
children: [
|
|
1001
|
-
/* @__PURE__ */ jsxs15("span", { "aria-hidden": true, className: "text-pass", children: [
|
|
1002
|
-
"\u2713",
|
|
1003
|
-
s.passed
|
|
1004
|
-
] }),
|
|
1005
|
-
/* @__PURE__ */ jsxs15("span", { "aria-hidden": true, className: "text-fail", children: [
|
|
1006
|
-
"\u2717",
|
|
1007
|
-
s.failed
|
|
1008
|
-
] }),
|
|
1009
|
-
/* @__PURE__ */ jsxs15("span", { "aria-hidden": true, className: "text-skip", children: [
|
|
1010
|
-
"\u25CB",
|
|
1011
|
-
skipped
|
|
1012
|
-
] })
|
|
1013
|
-
]
|
|
1014
|
-
}
|
|
1015
|
-
)
|
|
1016
|
-
] }),
|
|
1017
|
-
/* @__PURE__ */ jsx24("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-2 p-3", children: /* @__PURE__ */ jsx24(ReportScenarioList, { feature }) })
|
|
1018
|
-
]
|
|
1019
|
-
}
|
|
1052
|
+
/* @__PURE__ */ jsx25("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx25(ReportScenarioList, { feature }) })
|
|
1053
|
+
]
|
|
1054
|
+
}
|
|
1055
|
+
)
|
|
1020
1056
|
);
|
|
1021
1057
|
}
|
|
1022
1058
|
|
|
1023
1059
|
// src/components/ReportFeatureList.tsx
|
|
1024
|
-
import {
|
|
1060
|
+
import { jsx as jsx26 } from "react/jsx-runtime";
|
|
1025
1061
|
function ReportFeatureList() {
|
|
1026
1062
|
const report = useReport();
|
|
1027
|
-
return /* @__PURE__ */
|
|
1063
|
+
return /* @__PURE__ */ jsx26("div", { className: "flex flex-col gap-8", children: report.features.map((feature) => /* @__PURE__ */ jsx26(ReportFeature, { feature }, feature.id)) });
|
|
1028
1064
|
}
|
|
1029
1065
|
|
|
1030
1066
|
// src/components/ui/empty.tsx
|
|
1031
1067
|
import { cva as cva2 } from "class-variance-authority";
|
|
1032
|
-
import { jsx as
|
|
1068
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
1033
1069
|
function Empty({ className, ...props }) {
|
|
1034
|
-
return /* @__PURE__ */
|
|
1070
|
+
return /* @__PURE__ */ jsx27(
|
|
1035
1071
|
"div",
|
|
1036
1072
|
{
|
|
1037
1073
|
"data-slot": "empty",
|
|
@@ -1044,7 +1080,7 @@ function Empty({ className, ...props }) {
|
|
|
1044
1080
|
);
|
|
1045
1081
|
}
|
|
1046
1082
|
function EmptyHeader({ className, ...props }) {
|
|
1047
|
-
return /* @__PURE__ */
|
|
1083
|
+
return /* @__PURE__ */ jsx27(
|
|
1048
1084
|
"div",
|
|
1049
1085
|
{
|
|
1050
1086
|
"data-slot": "empty-header",
|
|
@@ -1071,7 +1107,7 @@ var emptyMediaVariants = cva2(
|
|
|
1071
1107
|
}
|
|
1072
1108
|
);
|
|
1073
1109
|
function EmptyTitle({ className, ...props }) {
|
|
1074
|
-
return /* @__PURE__ */
|
|
1110
|
+
return /* @__PURE__ */ jsx27(
|
|
1075
1111
|
"div",
|
|
1076
1112
|
{
|
|
1077
1113
|
"data-slot": "empty-title",
|
|
@@ -1082,16 +1118,16 @@ function EmptyTitle({ className, ...props }) {
|
|
|
1082
1118
|
}
|
|
1083
1119
|
|
|
1084
1120
|
// src/components/ReportEmpty.tsx
|
|
1085
|
-
import { jsx as
|
|
1121
|
+
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
1086
1122
|
function ReportEmpty({ message }) {
|
|
1087
|
-
return /* @__PURE__ */
|
|
1123
|
+
return /* @__PURE__ */ jsx28(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ jsx28(EmptyHeader, { children: /* @__PURE__ */ jsx28(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
|
|
1088
1124
|
}
|
|
1089
1125
|
|
|
1090
1126
|
// src/components/ReportSummary.tsx
|
|
1091
|
-
import {
|
|
1127
|
+
import { jsx as jsx29, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1092
1128
|
function ReportSummary({ className }) {
|
|
1093
1129
|
const report = useReport();
|
|
1094
|
-
return /* @__PURE__ */
|
|
1130
|
+
return /* @__PURE__ */ jsx29(
|
|
1095
1131
|
ReportSummaryView,
|
|
1096
1132
|
{
|
|
1097
1133
|
summary: report.summary,
|
|
@@ -1100,38 +1136,54 @@ function ReportSummary({ className }) {
|
|
|
1100
1136
|
}
|
|
1101
1137
|
);
|
|
1102
1138
|
}
|
|
1139
|
+
var TONE = {
|
|
1140
|
+
total: { num: "text-foreground", dot: "bg-muted-foreground/50" },
|
|
1141
|
+
passed: { num: "text-pass", dot: "bg-pass" },
|
|
1142
|
+
failed: { num: "text-fail", dot: "bg-fail" },
|
|
1143
|
+
skipped: { num: "text-skip", dot: "bg-skip" },
|
|
1144
|
+
pending: { num: "text-pend", dot: "bg-pend" }
|
|
1145
|
+
};
|
|
1103
1146
|
function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1147
|
+
const cards = [
|
|
1148
|
+
{ status: "total", label: "Total", value: summary.total },
|
|
1149
|
+
{ status: "passed", label: "Passed", value: summary.passed },
|
|
1150
|
+
{ status: "failed", label: "Failed", value: summary.failed },
|
|
1151
|
+
{ status: "skipped", label: "Skipped", value: summary.skipped }
|
|
1152
|
+
];
|
|
1153
|
+
if (summary.pending > 0) {
|
|
1154
|
+
cards.push({ status: "pending", label: "Pending", value: summary.pending });
|
|
1155
|
+
}
|
|
1156
|
+
return /* @__PURE__ */ jsx29(
|
|
1157
|
+
"dl",
|
|
1158
|
+
{
|
|
1159
|
+
className: cn(
|
|
1160
|
+
"grid grid-cols-2 gap-3",
|
|
1161
|
+
// Columns follow the card count so the row is always full — 5 statuses
|
|
1162
|
+
// (pending present) never leave a lone orphan card below a row of four.
|
|
1163
|
+
cards.length === 5 ? "sm:grid-cols-5" : "sm:grid-cols-4",
|
|
1164
|
+
className
|
|
1165
|
+
),
|
|
1166
|
+
"aria-label": ariaLabel,
|
|
1167
|
+
children: cards.map((c) => {
|
|
1168
|
+
const tone = TONE[c.status];
|
|
1169
|
+
return /* @__PURE__ */ jsxs17(
|
|
1170
|
+
"div",
|
|
1171
|
+
{
|
|
1172
|
+
"data-status": c.status,
|
|
1173
|
+
className: "rounded-lg border bg-card px-4 py-3",
|
|
1174
|
+
children: [
|
|
1175
|
+
/* @__PURE__ */ jsxs17("dt", { className: "flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground", children: [
|
|
1176
|
+
/* @__PURE__ */ jsx29("span", { className: cn("size-1.5 shrink-0 rounded-full", tone.dot), "aria-hidden": "true" }),
|
|
1177
|
+
c.label
|
|
1178
|
+
] }),
|
|
1179
|
+
/* @__PURE__ */ jsx29("dd", { className: cn("mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums", tone.num), children: c.value })
|
|
1180
|
+
]
|
|
1181
|
+
},
|
|
1182
|
+
c.status
|
|
1183
|
+
);
|
|
1184
|
+
})
|
|
1185
|
+
}
|
|
1186
|
+
);
|
|
1135
1187
|
}
|
|
1136
1188
|
|
|
1137
1189
|
// src/lib/provenance.ts
|
|
@@ -1165,7 +1217,7 @@ function prUrl(ci) {
|
|
|
1165
1217
|
}
|
|
1166
1218
|
|
|
1167
1219
|
// src/components/ReportMeta.tsx
|
|
1168
|
-
import { jsx as
|
|
1220
|
+
import { jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1169
1221
|
function ReportMeta() {
|
|
1170
1222
|
const report = useReport();
|
|
1171
1223
|
const items = [];
|
|
@@ -1188,13 +1240,13 @@ function ReportMeta() {
|
|
|
1188
1240
|
const short = sha.slice(0, 8);
|
|
1189
1241
|
items.push({
|
|
1190
1242
|
label: "Commit",
|
|
1191
|
-
value: url ? /* @__PURE__ */
|
|
1243
|
+
value: url ? /* @__PURE__ */ jsx30("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: short }) : short
|
|
1192
1244
|
});
|
|
1193
1245
|
}
|
|
1194
1246
|
if (report.ci) {
|
|
1195
1247
|
items.push({
|
|
1196
1248
|
label: "CI",
|
|
1197
|
-
value: report.ci.url ? /* @__PURE__ */
|
|
1249
|
+
value: report.ci.url ? /* @__PURE__ */ jsxs18("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: [
|
|
1198
1250
|
ciDisplayName(report.ci.name),
|
|
1199
1251
|
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1200
1252
|
] }) : `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
@@ -1205,45 +1257,56 @@ function ReportMeta() {
|
|
|
1205
1257
|
const label = `#${report.ci.prNumber}`;
|
|
1206
1258
|
items.push({
|
|
1207
1259
|
label: "PR",
|
|
1208
|
-
value: url ? /* @__PURE__ */
|
|
1260
|
+
value: url ? /* @__PURE__ */ jsx30("a", { href: url, target: "_blank", rel: "noreferrer noopener", className: linkClass, children: label }) : label
|
|
1209
1261
|
});
|
|
1210
1262
|
}
|
|
1211
1263
|
if (items.length === 0) return null;
|
|
1212
|
-
return
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1264
|
+
return (
|
|
1265
|
+
// Run metadata is useful but secondary to "what failed" — tuck it into a
|
|
1266
|
+
// collapsed disclosure so it doesn't push the result down. Native <details>
|
|
1267
|
+
// so it works with no JS (the SSR/no-hydration report still toggles).
|
|
1268
|
+
/* @__PURE__ */ jsxs18("details", { "data-es-meta-card": true, className: "es-run-details group rounded-lg border border-border bg-card text-xs", children: [
|
|
1269
|
+
/* @__PURE__ */ jsxs18("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: [
|
|
1270
|
+
/* @__PURE__ */ jsx30("span", { "aria-hidden": true, className: "text-xs transition-transform group-open:rotate-90", children: "\u25B8" }),
|
|
1271
|
+
"Run details"
|
|
1272
|
+
] }),
|
|
1273
|
+
/* @__PURE__ */ jsx30("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__ */ jsxs18("div", { className: "flex items-baseline gap-1.5", children: [
|
|
1274
|
+
/* @__PURE__ */ jsx30("dt", { className: "font-medium", children: item.label }),
|
|
1275
|
+
/* @__PURE__ */ jsx30("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1276
|
+
] }, item.label)) })
|
|
1277
|
+
] })
|
|
1278
|
+
);
|
|
1216
1279
|
}
|
|
1217
1280
|
|
|
1218
1281
|
// src/components/ReportSchemaError.tsx
|
|
1219
|
-
import { jsx as
|
|
1282
|
+
import { jsx as jsx31, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1220
1283
|
function ReportSchemaError({ error }) {
|
|
1221
|
-
return /* @__PURE__ */
|
|
1222
|
-
/* @__PURE__ */
|
|
1223
|
-
/* @__PURE__ */
|
|
1224
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */
|
|
1284
|
+
return /* @__PURE__ */ jsxs19("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1285
|
+
/* @__PURE__ */ jsx31("p", { children: /* @__PURE__ */ jsx31("strong", { children: "Report could not be displayed." }) }),
|
|
1286
|
+
/* @__PURE__ */ jsx31("p", { children: error.message }),
|
|
1287
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ jsxs19("p", { children: [
|
|
1225
1288
|
"The report bundle is newer than this version of ",
|
|
1226
|
-
/* @__PURE__ */
|
|
1289
|
+
/* @__PURE__ */ jsx31("code", { children: "executable-stories-react" }),
|
|
1227
1290
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
1228
1291
|
] }) : null,
|
|
1229
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */
|
|
1230
|
-
/* @__PURE__ */
|
|
1292
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ jsxs19("details", { children: [
|
|
1293
|
+
/* @__PURE__ */ jsxs19("summary", { children: [
|
|
1231
1294
|
error.issues.length,
|
|
1232
1295
|
" validation issue",
|
|
1233
1296
|
error.issues.length === 1 ? "" : "s"
|
|
1234
1297
|
] }),
|
|
1235
|
-
/* @__PURE__ */
|
|
1298
|
+
/* @__PURE__ */ jsx31("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
1236
1299
|
] }) : null
|
|
1237
1300
|
] });
|
|
1238
1301
|
}
|
|
1239
1302
|
|
|
1240
1303
|
// src/components/ReportShell.tsx
|
|
1241
|
-
import { Fragment as
|
|
1304
|
+
import { Fragment as Fragment10, jsx as jsx32, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1242
1305
|
function ReportTitleBlock({ title }) {
|
|
1243
|
-
return /* @__PURE__ */
|
|
1244
|
-
/* @__PURE__ */
|
|
1245
|
-
/* @__PURE__ */
|
|
1246
|
-
/* @__PURE__ */
|
|
1306
|
+
return /* @__PURE__ */ jsxs20(Fragment10, { children: [
|
|
1307
|
+
/* @__PURE__ */ jsx32("h1", { children: title ?? "Story Report" }),
|
|
1308
|
+
/* @__PURE__ */ jsx32(ReportSummary, {}),
|
|
1309
|
+
/* @__PURE__ */ jsx32(ReportMeta, {})
|
|
1247
1310
|
] });
|
|
1248
1311
|
}
|
|
1249
1312
|
function ReportErrorShell({
|
|
@@ -1252,22 +1315,22 @@ function ReportErrorShell({
|
|
|
1252
1315
|
title,
|
|
1253
1316
|
dataTheme
|
|
1254
1317
|
}) {
|
|
1255
|
-
return /* @__PURE__ */
|
|
1318
|
+
return /* @__PURE__ */ jsx32("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx32(ReportSchemaError, { error }) });
|
|
1256
1319
|
}
|
|
1257
1320
|
|
|
1258
1321
|
// src/components/Report.tsx
|
|
1259
|
-
import { jsx as
|
|
1322
|
+
import { jsx as jsx33, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1260
1323
|
function Report(props) {
|
|
1261
1324
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
1262
1325
|
const result = unwrapReport(report);
|
|
1263
1326
|
if (!result.ok) {
|
|
1264
|
-
return /* @__PURE__ */
|
|
1327
|
+
return /* @__PURE__ */ jsx33(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1265
1328
|
}
|
|
1266
1329
|
const data = result.data;
|
|
1267
1330
|
const hasContent = data.features.length > 0;
|
|
1268
|
-
return /* @__PURE__ */
|
|
1269
|
-
/* @__PURE__ */
|
|
1270
|
-
hasContent ? /* @__PURE__ */
|
|
1331
|
+
return /* @__PURE__ */ jsx33(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ jsxs21("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1332
|
+
/* @__PURE__ */ jsx33("header", { className: "es-report-header", children: /* @__PURE__ */ jsx33(ReportTitleBlock, { title }) }),
|
|
1333
|
+
hasContent ? /* @__PURE__ */ jsx33(ReportFeatureList, {}) : /* @__PURE__ */ jsx33(ReportEmpty, {})
|
|
1271
1334
|
] }) });
|
|
1272
1335
|
}
|
|
1273
1336
|
|