executable-stories-react 0.5.0 → 0.6.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.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +141 -14
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.js +141 -14
- package/dist/interactive.js.map +1 -1
- package/dist/report-island.global.js +26 -21
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.js.map +1 -1
- package/package.json +1 -1
package/dist/interactive.cjs
CHANGED
|
@@ -241,7 +241,7 @@ function DocTable({ entry }) {
|
|
|
241
241
|
entry.label ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.label }) : null,
|
|
242
242
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("table", { className: "w-full border-collapse text-sm", children: [
|
|
243
243
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { className: "bg-muted/50", children: entry.columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: c }, c)) }) }),
|
|
244
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tbody", { children: entry.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: row.map((
|
|
244
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tbody", { children: entry.rows.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: row.map((cell2, j) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-border px-3 py-2 text-foreground", children: cell2 }, j)) }, i)) })
|
|
245
245
|
] }) })
|
|
246
246
|
] });
|
|
247
247
|
}
|
|
@@ -894,20 +894,118 @@ function useCollapseState(computeDefault) {
|
|
|
894
894
|
|
|
895
895
|
// src/interactive/scenario-actions.tsx
|
|
896
896
|
var import_react7 = require("react");
|
|
897
|
+
|
|
898
|
+
// ../executable-stories-core/dist/utils/scenario-markdown.js
|
|
899
|
+
function cell(value) {
|
|
900
|
+
return value.replaceAll("|", "\\|").replaceAll("\n", " ");
|
|
901
|
+
}
|
|
902
|
+
function stringify(value) {
|
|
903
|
+
if (typeof value === "string") return value;
|
|
904
|
+
try {
|
|
905
|
+
return JSON.stringify(value, null, 2) ?? String(value);
|
|
906
|
+
} catch {
|
|
907
|
+
return String(value);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
function docEntryToMarkdown(entry) {
|
|
911
|
+
const lines = [];
|
|
912
|
+
switch (entry.kind) {
|
|
913
|
+
case "note":
|
|
914
|
+
lines.push(entry.text);
|
|
915
|
+
break;
|
|
916
|
+
case "tag":
|
|
917
|
+
lines.push(entry.names.map((n) => `\`@${n}\``).join(" "));
|
|
918
|
+
break;
|
|
919
|
+
case "kv":
|
|
920
|
+
lines.push(`**${entry.label}:** ${stringify(entry.value)}`);
|
|
921
|
+
break;
|
|
922
|
+
case "code":
|
|
923
|
+
lines.push(`**${entry.label}**`, "", "```" + (entry.lang ?? ""), entry.content, "```");
|
|
924
|
+
break;
|
|
925
|
+
case "table": {
|
|
926
|
+
lines.push(`**${entry.label}**`, "");
|
|
927
|
+
lines.push(`| ${entry.columns.map(cell).join(" | ")} |`);
|
|
928
|
+
lines.push(`| ${entry.columns.map(() => "---").join(" | ")} |`);
|
|
929
|
+
for (const row of entry.rows) lines.push(`| ${row.map(cell).join(" | ")} |`);
|
|
930
|
+
break;
|
|
931
|
+
}
|
|
932
|
+
case "link":
|
|
933
|
+
lines.push(`[${entry.label}](${entry.url})`);
|
|
934
|
+
break;
|
|
935
|
+
case "section":
|
|
936
|
+
lines.push(`### ${entry.title}`, "", entry.markdown);
|
|
937
|
+
break;
|
|
938
|
+
case "mermaid":
|
|
939
|
+
if (entry.title) lines.push(`**${entry.title}**`, "");
|
|
940
|
+
lines.push("```mermaid", entry.code, "```");
|
|
941
|
+
break;
|
|
942
|
+
case "screenshot":
|
|
943
|
+
lines.push(``);
|
|
944
|
+
break;
|
|
945
|
+
case "video":
|
|
946
|
+
lines.push(`Video: ${entry.path}${entry.caption ? ` \u2014 ${entry.caption}` : ""}`);
|
|
947
|
+
break;
|
|
948
|
+
case "html": {
|
|
949
|
+
const htmlTitle = entry.title ?? "Embedded HTML";
|
|
950
|
+
if (entry.content) {
|
|
951
|
+
lines.push(`**${htmlTitle}**`, "", "```html", entry.content, "```");
|
|
952
|
+
} else if (entry.url) {
|
|
953
|
+
lines.push(`[${htmlTitle}](${entry.url})`);
|
|
954
|
+
} else {
|
|
955
|
+
lines.push(`Embedded HTML: ${entry.path ?? "(inline)"}`);
|
|
956
|
+
}
|
|
957
|
+
break;
|
|
958
|
+
}
|
|
959
|
+
case "custom":
|
|
960
|
+
lines.push(`**${entry.type}**`, "", "```json", stringify(entry.data), "```");
|
|
961
|
+
break;
|
|
962
|
+
}
|
|
963
|
+
for (const child of entry.children ?? []) {
|
|
964
|
+
lines.push("", ...docEntryToMarkdown(child));
|
|
965
|
+
}
|
|
966
|
+
return lines;
|
|
967
|
+
}
|
|
968
|
+
function stepLines(step, ordinal, full) {
|
|
969
|
+
const status = step.status === "passed" ? "" : ` \u2014 **${step.status}**`;
|
|
970
|
+
const lines = [`${ordinal}. **${step.keyword}** ${step.text}${status}`];
|
|
971
|
+
if (!full) return lines;
|
|
972
|
+
if (step.errorMessage) {
|
|
973
|
+
lines.push(...step.errorMessage.split("\n").map((l) => ` > ${l}`));
|
|
974
|
+
}
|
|
975
|
+
for (const entry of step.docEntries) {
|
|
976
|
+
lines.push("", ...docEntryToMarkdown(entry).map((l) => l === "" ? l : ` ${l}`));
|
|
977
|
+
}
|
|
978
|
+
return lines;
|
|
979
|
+
}
|
|
980
|
+
function scenarioToMarkdown(scenario, options = {}) {
|
|
981
|
+
const { variant = "full", meta = [] } = options;
|
|
982
|
+
const full = variant === "full";
|
|
983
|
+
const lines = full ? [`# ${scenario.title}`, ""] : [`## ${scenario.title} _(${scenario.status})_`, ""];
|
|
984
|
+
if (full && meta.length > 0) lines.push(...meta);
|
|
985
|
+
if (scenario.steps.length > 0) {
|
|
986
|
+
if (full) lines.push("", "## Steps", "");
|
|
987
|
+
scenario.steps.forEach((step, i) => lines.push(...stepLines(step, i + 1, full)));
|
|
988
|
+
}
|
|
989
|
+
if (scenario.errorMessage) {
|
|
990
|
+
if (full) lines.push("", "## Failure", "");
|
|
991
|
+
else lines.push("");
|
|
992
|
+
lines.push("```", scenario.errorMessage.trim(), "```");
|
|
993
|
+
}
|
|
994
|
+
if (full && scenario.docEntries.length > 0) {
|
|
995
|
+
lines.push("", "## Docs", "");
|
|
996
|
+
for (const entry of scenario.docEntries) lines.push(...docEntryToMarkdown(entry), "");
|
|
997
|
+
}
|
|
998
|
+
return lines.join("\n").replaceAll(/\n{3,}/g, "\n\n").trimEnd() + (full ? "\n" : "");
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
// src/interactive/scenario-actions.tsx
|
|
897
1002
|
var ScenarioActionsContext = (0, import_react7.createContext)(null);
|
|
898
1003
|
var ScenarioActionsProvider = ScenarioActionsContext.Provider;
|
|
899
1004
|
function useScenarioActions() {
|
|
900
1005
|
return (0, import_react7.useContext)(ScenarioActionsContext);
|
|
901
1006
|
}
|
|
902
|
-
function
|
|
903
|
-
|
|
904
|
-
for (const step of scenario.steps) {
|
|
905
|
-
lines.push(`- **${step.keyword}** ${step.text}`);
|
|
906
|
-
}
|
|
907
|
-
if (scenario.errorMessage) {
|
|
908
|
-
lines.push("", "```", scenario.errorMessage.trim(), "```");
|
|
909
|
-
}
|
|
910
|
-
return lines.join("\n");
|
|
1007
|
+
function scenarioToMarkdown2(scenario) {
|
|
1008
|
+
return scenarioToMarkdown(scenario, { variant: "compact" });
|
|
911
1009
|
}
|
|
912
1010
|
function scenarioToPrompt(scenario) {
|
|
913
1011
|
const lines = [
|
|
@@ -2072,6 +2170,33 @@ function listFailures(report) {
|
|
|
2072
2170
|
return out;
|
|
2073
2171
|
}
|
|
2074
2172
|
|
|
2173
|
+
// src/interactive/triage-default.ts
|
|
2174
|
+
function needsAttention(status) {
|
|
2175
|
+
return status === "failed";
|
|
2176
|
+
}
|
|
2177
|
+
function defaultCollapsedIds(report) {
|
|
2178
|
+
const collapsed = /* @__PURE__ */ new Set();
|
|
2179
|
+
if (report.summary.failed === 0) return collapsed;
|
|
2180
|
+
for (const feature of report.features) {
|
|
2181
|
+
const featureHasFailure = feature.scenarios.some((s) => needsAttention(s.status));
|
|
2182
|
+
if (!featureHasFailure) collapsed.add(feature.id);
|
|
2183
|
+
for (const scenario of feature.scenarios) {
|
|
2184
|
+
if (!needsAttention(scenario.status)) collapsed.add(scenario.id);
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
return collapsed;
|
|
2188
|
+
}
|
|
2189
|
+
function failuresFirst(report) {
|
|
2190
|
+
if (report.summary.failed === 0) return report;
|
|
2191
|
+
const withFailures = [];
|
|
2192
|
+
const rest = [];
|
|
2193
|
+
for (const feature of report.features) {
|
|
2194
|
+
(feature.scenarios.some((s) => needsAttention(s.status)) ? withFailures : rest).push(feature);
|
|
2195
|
+
}
|
|
2196
|
+
if (withFailures.length === 0) return report;
|
|
2197
|
+
return { ...report, features: [...withFailures, ...rest] };
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2075
2200
|
// src/interactive/ReportFilters.tsx
|
|
2076
2201
|
var import_react14 = require("react");
|
|
2077
2202
|
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
@@ -2362,7 +2487,9 @@ function ReportInteractiveView({
|
|
|
2362
2487
|
const deferredQuery = (0, import_react18.useDeferredValue)(query);
|
|
2363
2488
|
const failures = (0, import_react18.useMemo)(() => listFailures(report), [report]);
|
|
2364
2489
|
const filtered = (0, import_react18.useMemo)(
|
|
2365
|
-
|
|
2490
|
+
// Features carrying failures float to the top so the first thing on screen
|
|
2491
|
+
// is the thing that needs attention; an all-green run keeps source order.
|
|
2492
|
+
() => failuresFirst(filterReport(report, { query: deferredQuery, status: statusFilter, tags: activeTags })),
|
|
2366
2493
|
[report, deferredQuery, statusFilter, activeTags]
|
|
2367
2494
|
);
|
|
2368
2495
|
const isFiltering = query !== deferredQuery;
|
|
@@ -2400,7 +2527,7 @@ function ReportInteractiveView({
|
|
|
2400
2527
|
const scenarioActions = (0, import_react18.useMemo)(
|
|
2401
2528
|
() => ({
|
|
2402
2529
|
copyLink: (s) => copy(scenarioPermalink(s), "Link copied"),
|
|
2403
|
-
copyMarkdown: (s) => copy(
|
|
2530
|
+
copyMarkdown: (s) => copy(scenarioToMarkdown2(s), "Markdown copied"),
|
|
2404
2531
|
copyPrompt: (s) => copy(scenarioToPrompt(s), "Prompt copied")
|
|
2405
2532
|
}),
|
|
2406
2533
|
[copy]
|
|
@@ -2410,9 +2537,9 @@ function ReportInteractiveView({
|
|
|
2410
2537
|
() => report.features.flatMap((f) => [f.id, ...f.scenarios.map((s) => s.id)]),
|
|
2411
2538
|
[report]
|
|
2412
2539
|
);
|
|
2413
|
-
const collapse = useCollapseState();
|
|
2540
|
+
const collapse = useCollapseState((0, import_react18.useCallback)(() => defaultCollapsedIds(report), [report]));
|
|
2414
2541
|
const collapseAll = (0, import_react18.useCallback)(() => collapse.collapseAll(allCollapsibleIds), [collapse, allCollapsibleIds]);
|
|
2415
|
-
const [expandedAll, setExpandedAll] = (0, import_react18.useState)(
|
|
2542
|
+
const [expandedAll, setExpandedAll] = (0, import_react18.useState)(() => report.summary.failed === 0);
|
|
2416
2543
|
const setExpanded = (0, import_react18.useCallback)(
|
|
2417
2544
|
(expanded) => {
|
|
2418
2545
|
if (expanded) collapse.expandAll();
|