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