executable-stories-react 0.10.0 → 0.10.1
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 +35 -170
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -235
- package/dist/index.d.ts +6 -235
- package/dist/index.js +26 -161
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +39 -291
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +1 -233
- package/dist/interactive.d.ts +1 -233
- package/dist/interactive.js +30 -282
- package/dist/interactive.js.map +1 -1
- package/dist/parse.d.cts +3 -234
- package/dist/parse.d.ts +3 -234
- package/dist/ssr.cjs +35 -170
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.d.cts +1 -232
- package/dist/ssr.d.ts +1 -232
- package/dist/ssr.js +26 -161
- package/dist/ssr.js.map +1 -1
- package/package.json +4 -4
package/dist/ssr.js
CHANGED
|
@@ -287,23 +287,11 @@ function useReport() {
|
|
|
287
287
|
return ctx.report;
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
-
//
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
if (ms < 6e4) {
|
|
296
|
-
return `${(ms / 1e3).toFixed(2)} s`;
|
|
297
|
-
}
|
|
298
|
-
const minutes = Math.floor(ms / 6e4);
|
|
299
|
-
const seconds = Math.floor(ms % 6e4 / 1e3);
|
|
300
|
-
if (minutes < 60) {
|
|
301
|
-
return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
302
|
-
}
|
|
303
|
-
const hours = Math.floor(minutes / 60);
|
|
304
|
-
const remainingMinutes = minutes % 60;
|
|
305
|
-
return `${hours}h ${remainingMinutes}m`;
|
|
306
|
-
}
|
|
290
|
+
// src/components/ReportScenario.tsx
|
|
291
|
+
import { formatDuration as formatDuration3 } from "executable-stories-core/utils/duration";
|
|
292
|
+
|
|
293
|
+
// src/components/ReportSteps.tsx
|
|
294
|
+
import { formatDuration } from "executable-stories-core/utils/duration";
|
|
307
295
|
|
|
308
296
|
// src/components/doc/DocNote.tsx
|
|
309
297
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
@@ -395,23 +383,8 @@ function DocLink({ entry }) {
|
|
|
395
383
|
// src/components/doc/DocSection.tsx
|
|
396
384
|
import { marked } from "marked";
|
|
397
385
|
|
|
398
|
-
//
|
|
399
|
-
|
|
400
|
-
if (!value) return void 0;
|
|
401
|
-
const trimmed = value.trim();
|
|
402
|
-
const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(trimmed);
|
|
403
|
-
if (scheme && !/^https?$/i.test(scheme[1] ?? "")) return void 0;
|
|
404
|
-
return trimmed;
|
|
405
|
-
}
|
|
406
|
-
function safeImageUrl(value) {
|
|
407
|
-
if (!value) return void 0;
|
|
408
|
-
const trimmed = value.trim();
|
|
409
|
-
if (/^data:image\//i.test(trimmed)) return trimmed;
|
|
410
|
-
return safeUrl(trimmed);
|
|
411
|
-
}
|
|
412
|
-
function isLocalFsPath(value) {
|
|
413
|
-
return /^(?:[/\\]|[A-Za-z]:[/\\])/.test(value);
|
|
414
|
-
}
|
|
386
|
+
// src/lib/url.ts
|
|
387
|
+
import { safeUrl, safeImageUrl, isLocalFsPath } from "executable-stories-core/utils/url";
|
|
415
388
|
|
|
416
389
|
// src/components/doc/DocSection.tsx
|
|
417
390
|
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
@@ -704,125 +677,10 @@ function ReportStepItem({ step }) {
|
|
|
704
677
|
);
|
|
705
678
|
}
|
|
706
679
|
|
|
707
|
-
// ../executable-stories-core/dist/state-diff.js
|
|
708
|
-
var isPlainObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
709
|
-
function deepEqual(a, b) {
|
|
710
|
-
if (Object.is(a, b)) return true;
|
|
711
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
712
|
-
return a.length === b.length && a.every((v, i) => deepEqual(v, b[i]));
|
|
713
|
-
}
|
|
714
|
-
if (isPlainObject(a) && isPlainObject(b)) {
|
|
715
|
-
const ak = Object.keys(a);
|
|
716
|
-
const bk = Object.keys(b);
|
|
717
|
-
return ak.length === bk.length && ak.every((k) => k in b && deepEqual(a[k], b[k]));
|
|
718
|
-
}
|
|
719
|
-
return false;
|
|
720
|
-
}
|
|
721
|
-
var joinKey = (path, key) => path === "" ? key : `${path}.${key}`;
|
|
722
|
-
function walk(path, before, after, out) {
|
|
723
|
-
if (Object.is(before, after)) return;
|
|
724
|
-
if (Array.isArray(before) && Array.isArray(after)) {
|
|
725
|
-
const shared = Math.min(before.length, after.length);
|
|
726
|
-
for (let i = 0; i < shared; i++) walk(`${path}[${i}]`, before[i], after[i], out);
|
|
727
|
-
for (let i = shared; i < after.length; i++) out.push({ path: `${path}[${i}]`, kind: "added", after: after[i] });
|
|
728
|
-
for (let i = shared; i < before.length; i++) out.push({ path: `${path}[${i}]`, kind: "removed", before: before[i] });
|
|
729
|
-
return;
|
|
730
|
-
}
|
|
731
|
-
if (isPlainObject(before) && isPlainObject(after)) {
|
|
732
|
-
for (const key of Object.keys(after)) {
|
|
733
|
-
const p = joinKey(path, key);
|
|
734
|
-
if (key in before) walk(p, before[key], after[key], out);
|
|
735
|
-
else out.push({ path: p, kind: "added", after: after[key] });
|
|
736
|
-
}
|
|
737
|
-
for (const key of Object.keys(before)) {
|
|
738
|
-
if (!(key in after)) out.push({ path: joinKey(path, key), kind: "removed", before: before[key] });
|
|
739
|
-
}
|
|
740
|
-
return;
|
|
741
|
-
}
|
|
742
|
-
if (!deepEqual(before, after)) out.push({ path, kind: "changed", before, after });
|
|
743
|
-
}
|
|
744
|
-
function diffStateValues(before, after) {
|
|
745
|
-
const out = [];
|
|
746
|
-
walk("", before, after, out);
|
|
747
|
-
return out;
|
|
748
|
-
}
|
|
749
|
-
function formatStateValue(value, maxLen = 60) {
|
|
750
|
-
const s = value === void 0 ? "undefined" : JSON.stringify(value);
|
|
751
|
-
return s.length > maxLen ? `${s.slice(0, maxLen - 1)}\u2026` : s;
|
|
752
|
-
}
|
|
753
|
-
function summarizeStateChanges(changes) {
|
|
754
|
-
return changes.map((c) => {
|
|
755
|
-
const at = c.path === "" ? "(root)" : c.path;
|
|
756
|
-
switch (c.kind) {
|
|
757
|
-
case "added":
|
|
758
|
-
return `+ ${at}: ${formatStateValue(c.after)}`;
|
|
759
|
-
case "removed":
|
|
760
|
-
return `\u2212 ${at}`;
|
|
761
|
-
case "changed":
|
|
762
|
-
return `${at}: ${formatStateValue(c.before)} \u2192 ${formatStateValue(c.after)}`;
|
|
763
|
-
}
|
|
764
|
-
});
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
// ../executable-stories-core/dist/storyboard.js
|
|
768
|
-
function findScreenshot(entries) {
|
|
769
|
-
for (const entry of entries) {
|
|
770
|
-
if (entry.kind === "screenshot") return entry;
|
|
771
|
-
if (entry.children) {
|
|
772
|
-
const nested = findScreenshot(entry.children);
|
|
773
|
-
if (nested) return nested;
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
return void 0;
|
|
777
|
-
}
|
|
778
|
-
function findStates(entries, out = []) {
|
|
779
|
-
for (const entry of entries) {
|
|
780
|
-
if (entry.kind === "state") out.push(entry);
|
|
781
|
-
if (entry.children) findStates(entry.children, out);
|
|
782
|
-
}
|
|
783
|
-
return out;
|
|
784
|
-
}
|
|
785
|
-
var laneOf = (label) => label ?? "";
|
|
786
|
-
function extractStoryboardFrames(scenario) {
|
|
787
|
-
const frames = [];
|
|
788
|
-
const laneOrder = [];
|
|
789
|
-
const previous = /* @__PURE__ */ new Map();
|
|
790
|
-
for (const step of scenario.steps) {
|
|
791
|
-
const shot = findScreenshot(step.docEntries);
|
|
792
|
-
const stateDocs = findStates(step.docEntries);
|
|
793
|
-
if (!shot && stateDocs.length === 0) continue;
|
|
794
|
-
const byLane = /* @__PURE__ */ new Map();
|
|
795
|
-
for (const doc of stateDocs) {
|
|
796
|
-
const lane = laneOf(doc.label);
|
|
797
|
-
if (!byLane.has(lane) && !laneOrder.includes(lane)) laneOrder.push(lane);
|
|
798
|
-
byLane.set(lane, doc);
|
|
799
|
-
}
|
|
800
|
-
const states = [];
|
|
801
|
-
for (const lane of laneOrder) {
|
|
802
|
-
const doc = byLane.get(lane);
|
|
803
|
-
if (!doc) continue;
|
|
804
|
-
const card = {
|
|
805
|
-
...doc.label !== void 0 && { label: doc.label },
|
|
806
|
-
value: doc.value
|
|
807
|
-
};
|
|
808
|
-
if (previous.has(lane)) card.changes = diffStateValues(previous.get(lane), doc.value);
|
|
809
|
-
previous.set(lane, doc.value);
|
|
810
|
-
states.push(card);
|
|
811
|
-
}
|
|
812
|
-
frames.push({
|
|
813
|
-
stepId: step.id,
|
|
814
|
-
stepIndex: step.index,
|
|
815
|
-
keyword: step.keyword,
|
|
816
|
-
text: step.text,
|
|
817
|
-
status: step.status,
|
|
818
|
-
...shot && { screenshot: { path: shot.path, ...shot.alt !== void 0 && { alt: shot.alt } } },
|
|
819
|
-
states
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
return frames;
|
|
823
|
-
}
|
|
824
|
-
|
|
825
680
|
// src/components/ReportStoryboard.tsx
|
|
681
|
+
import { extractStoryboardFrames } from "executable-stories-core/storyboard";
|
|
682
|
+
import { summarizeStateChanges } from "executable-stories-core/state-diff";
|
|
683
|
+
import { isLocalFsPath as isLocalFsPath2, safeImageUrl as safeImageUrl2 } from "executable-stories-core/utils/url";
|
|
826
684
|
import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
827
685
|
var FRAME_GLYPH = {
|
|
828
686
|
passed: "\u2713",
|
|
@@ -871,7 +729,7 @@ function StoryboardFrameItem({ frame }) {
|
|
|
871
729
|
}
|
|
872
730
|
function FrameScreenshot({ frame, label }) {
|
|
873
731
|
const path = frame.screenshot?.path ?? "";
|
|
874
|
-
const src =
|
|
732
|
+
const src = isLocalFsPath2(path) ? void 0 : safeImageUrl2(path);
|
|
875
733
|
return /* @__PURE__ */ jsx20(
|
|
876
734
|
"a",
|
|
877
735
|
{
|
|
@@ -977,6 +835,9 @@ function ReportAttachments({ attachments }) {
|
|
|
977
835
|
);
|
|
978
836
|
}
|
|
979
837
|
|
|
838
|
+
// src/components/ReportTrace.tsx
|
|
839
|
+
import { formatDuration as formatDuration2 } from "executable-stories-core/utils/duration";
|
|
840
|
+
|
|
980
841
|
// src/lib/trace.ts
|
|
981
842
|
var VALID = /* @__PURE__ */ new Set(["ok", "error", "unset"]);
|
|
982
843
|
var safeStatus = (s) => VALID.has(s) ? s : "unset";
|
|
@@ -1029,15 +890,15 @@ function toTraceRows(spans) {
|
|
|
1029
890
|
roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
1030
891
|
const rows = [];
|
|
1031
892
|
const seen = /* @__PURE__ */ new Set();
|
|
1032
|
-
const
|
|
893
|
+
const walk = (node, depth) => {
|
|
1033
894
|
if (seen.has(node.span.spanId)) return;
|
|
1034
895
|
seen.add(node.span.spanId);
|
|
1035
896
|
rows.push({ ...node.span, depth });
|
|
1036
|
-
for (const child of node.children)
|
|
897
|
+
for (const child of node.children) walk(child, depth + 1);
|
|
1037
898
|
};
|
|
1038
|
-
for (const root of roots)
|
|
899
|
+
for (const root of roots) walk(root, 0);
|
|
1039
900
|
for (const node of byId.values()) {
|
|
1040
|
-
if (!seen.has(node.span.spanId))
|
|
901
|
+
if (!seen.has(node.span.spanId)) walk(node, 0);
|
|
1041
902
|
}
|
|
1042
903
|
return rows;
|
|
1043
904
|
}
|
|
@@ -1071,7 +932,7 @@ function ReportTrace({ spans }) {
|
|
|
1071
932
|
" span",
|
|
1072
933
|
rows.length === 1 ? "" : "s",
|
|
1073
934
|
", ",
|
|
1074
|
-
|
|
935
|
+
formatDuration2(totalMs),
|
|
1075
936
|
")"
|
|
1076
937
|
] }),
|
|
1077
938
|
/* @__PURE__ */ jsx22("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
|
|
@@ -1094,7 +955,7 @@ function ReportTrace({ spans }) {
|
|
|
1094
955
|
style: { left: `${leftPct}%`, width: `${widthPct}%` }
|
|
1095
956
|
}
|
|
1096
957
|
) }),
|
|
1097
|
-
/* @__PURE__ */ jsx22("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children:
|
|
958
|
+
/* @__PURE__ */ jsx22("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration2(row.durationMs) })
|
|
1098
959
|
] }, `${row.spanId}-${i}`);
|
|
1099
960
|
}) })
|
|
1100
961
|
] });
|
|
@@ -1205,6 +1066,7 @@ function useCollapse() {
|
|
|
1205
1066
|
|
|
1206
1067
|
// src/interactive/scenario-actions.tsx
|
|
1207
1068
|
import { createContext as createContext4, useContext as useContext5 } from "react";
|
|
1069
|
+
import { scenarioToMarkdown as coreScenarioToMarkdown } from "executable-stories-core/utils/scenario-markdown";
|
|
1208
1070
|
var ScenarioActionsContext = createContext4(null);
|
|
1209
1071
|
var ScenarioActionsProvider = ScenarioActionsContext.Provider;
|
|
1210
1072
|
function useScenarioActions() {
|
|
@@ -1350,7 +1212,7 @@ function ReportScenario({ scenario, hideTitle = false }) {
|
|
|
1350
1212
|
] }),
|
|
1351
1213
|
/* @__PURE__ */ jsxs17("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1352
1214
|
/* @__PURE__ */ jsx26(ScenarioRunHistory, { scenarioId: scenario.id }),
|
|
1353
|
-
scenario.durationMs > 0 ? /* @__PURE__ */ jsx26("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children:
|
|
1215
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ jsx26("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration3(scenario.durationMs) }) : null,
|
|
1354
1216
|
meta.showPill ? /* @__PURE__ */ jsx26(Badge, { variant: meta.badgeVariant, "aria-label": `Status: ${label}`, children: label }) : /* @__PURE__ */ jsx26("span", { className: "sr-only", children: `Status: ${label}` }),
|
|
1355
1217
|
actions ? /* @__PURE__ */ jsxs17(DropdownMenu, { children: [
|
|
1356
1218
|
/* @__PURE__ */ jsx26(
|
|
@@ -1610,6 +1472,9 @@ function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
|
1610
1472
|
);
|
|
1611
1473
|
}
|
|
1612
1474
|
|
|
1475
|
+
// src/components/ReportMeta.tsx
|
|
1476
|
+
import { formatDuration as formatDuration4 } from "executable-stories-core/utils/duration";
|
|
1477
|
+
|
|
1613
1478
|
// src/lib/provenance.ts
|
|
1614
1479
|
var CI_DISPLAY_NAMES = {
|
|
1615
1480
|
github: "GitHub Actions",
|
|
@@ -1650,7 +1515,7 @@ function ReportMeta() {
|
|
|
1650
1515
|
items.push({ label: "Started", value: new Date(report.startedAtMs).toLocaleString() });
|
|
1651
1516
|
}
|
|
1652
1517
|
if (report.durationMs) {
|
|
1653
|
-
items.push({ label: "Duration", value:
|
|
1518
|
+
items.push({ label: "Duration", value: formatDuration4(report.durationMs) });
|
|
1654
1519
|
}
|
|
1655
1520
|
if (report.packageVersion) {
|
|
1656
1521
|
items.push({ label: "Version", value: report.packageVersion });
|