executable-stories-react 0.1.16 → 0.2.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 +1767 -371
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +148 -14
- package/dist/index.d.ts +148 -14
- package/dist/index.js +1748 -370
- package/dist/index.js.map +1 -1
- package/dist/interactive.cjs +1485 -265
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.d.cts +55 -4
- package/dist/interactive.d.ts +55 -4
- package/dist/interactive.js +1474 -255
- package/dist/interactive.js.map +1 -1
- package/dist/parse.cjs +631 -154
- package/dist/parse.cjs.map +1 -1
- package/dist/parse.d.cts +12 -4
- package/dist/parse.d.ts +12 -4
- package/dist/parse.js +631 -154
- package/dist/parse.js.map +1 -1
- package/dist/report-island.global.js +132 -0
- package/dist/ssr.cjs +1235 -0
- package/dist/ssr.cjs.map +1 -0
- package/dist/ssr.d.cts +72 -0
- package/dist/ssr.d.ts +72 -0
- package/dist/ssr.js +1210 -0
- package/dist/ssr.js.map +1 -0
- package/dist/styles.css +21 -6
- package/dist/tailwind.css +2 -0
- package/package.json +43 -8
package/dist/index.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
// src/result.ts
|
|
4
|
+
var ok = (data) => ({ ok: true, data });
|
|
5
|
+
var err = (error) => ({ ok: false, error });
|
|
6
|
+
function unwrapReport(value) {
|
|
7
|
+
if (typeof value === "object" && value !== null && "ok" in value && typeof value.ok === "boolean") {
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
return ok(value);
|
|
11
|
+
}
|
|
12
|
+
|
|
3
13
|
// src/context/ReportRoot.tsx
|
|
4
14
|
import { useMemo } from "react";
|
|
5
15
|
|
|
@@ -40,74 +50,80 @@ function useReport() {
|
|
|
40
50
|
return ctx.report;
|
|
41
51
|
}
|
|
42
52
|
|
|
43
|
-
// src/components/
|
|
44
|
-
import {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
ReportSummaryView,
|
|
49
|
-
{
|
|
50
|
-
summary: report.summary,
|
|
51
|
-
...className !== void 0 && { className },
|
|
52
|
-
ariaLabel: "Run summary"
|
|
53
|
-
}
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
57
|
-
return /* @__PURE__ */ jsxs(
|
|
58
|
-
"p",
|
|
59
|
-
{
|
|
60
|
-
className: ["es-report-summary", className].filter(Boolean).join(" "),
|
|
61
|
-
"aria-label": ariaLabel,
|
|
62
|
-
children: [
|
|
63
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
64
|
-
/* @__PURE__ */ jsx2("strong", { children: summary.total }),
|
|
65
|
-
" scenario",
|
|
66
|
-
summary.total === 1 ? "" : "s"
|
|
67
|
-
] }),
|
|
68
|
-
" \xB7 ",
|
|
69
|
-
/* @__PURE__ */ jsxs("span", { "data-status": "passed", children: [
|
|
70
|
-
summary.passed,
|
|
71
|
-
" passed"
|
|
72
|
-
] }),
|
|
73
|
-
" \xB7 ",
|
|
74
|
-
/* @__PURE__ */ jsxs("span", { "data-status": "failed", children: [
|
|
75
|
-
summary.failed,
|
|
76
|
-
" failed"
|
|
77
|
-
] }),
|
|
78
|
-
summary.skipped > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
79
|
-
" \xB7 ",
|
|
80
|
-
/* @__PURE__ */ jsxs("span", { "data-status": "skipped", children: [
|
|
81
|
-
summary.skipped,
|
|
82
|
-
" skipped"
|
|
83
|
-
] })
|
|
84
|
-
] }) : null,
|
|
85
|
-
summary.pending > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
86
|
-
" \xB7 ",
|
|
87
|
-
/* @__PURE__ */ jsxs("span", { "data-status": "pending", children: [
|
|
88
|
-
summary.pending,
|
|
89
|
-
" pending"
|
|
90
|
-
] })
|
|
91
|
-
] }) : null
|
|
92
|
-
]
|
|
93
|
-
}
|
|
94
|
-
);
|
|
95
|
-
}
|
|
53
|
+
// src/components/ReportScenario.tsx
|
|
54
|
+
import { formatDuration as formatDuration3 } from "executable-stories-core/utils/duration";
|
|
55
|
+
|
|
56
|
+
// src/components/ReportSteps.tsx
|
|
57
|
+
import { formatDuration } from "executable-stories-core/utils/duration";
|
|
96
58
|
|
|
97
59
|
// src/components/doc/DocNote.tsx
|
|
98
|
-
import { jsx as
|
|
60
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
99
61
|
function DocNote({ entry }) {
|
|
100
|
-
return /* @__PURE__ */
|
|
62
|
+
return /* @__PURE__ */ jsx2("p", { className: "my-2 text-sm text-muted-foreground", children: entry.text });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/components/ui/badge.tsx
|
|
66
|
+
import "react";
|
|
67
|
+
import { cva } from "class-variance-authority";
|
|
68
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
69
|
+
|
|
70
|
+
// src/lib/utils.ts
|
|
71
|
+
import { clsx } from "clsx";
|
|
72
|
+
import { twMerge } from "tailwind-merge";
|
|
73
|
+
function cn(...inputs) {
|
|
74
|
+
return twMerge(clsx(inputs));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/components/ui/badge.tsx
|
|
78
|
+
var badgeVariants = cva(
|
|
79
|
+
"inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3",
|
|
80
|
+
{
|
|
81
|
+
variants: {
|
|
82
|
+
variant: {
|
|
83
|
+
default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
84
|
+
secondary: "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
85
|
+
destructive: "bg-destructive text-white focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90",
|
|
86
|
+
outline: "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
87
|
+
ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
88
|
+
link: "text-primary underline-offset-4 [a&]:hover:underline",
|
|
89
|
+
passed: "border-pass-border bg-pass-bg text-pass font-mono uppercase",
|
|
90
|
+
failed: "border-fail-border bg-fail-bg text-fail font-mono uppercase",
|
|
91
|
+
skipped: "border-skip-border bg-skip-bg text-skip font-mono uppercase",
|
|
92
|
+
pending: "border-pend-border bg-pend-bg text-pend font-mono uppercase",
|
|
93
|
+
tag: "border-pass-border bg-pass-bg text-pass font-mono font-medium"
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
defaultVariants: {
|
|
97
|
+
variant: "default"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
function Badge({
|
|
102
|
+
className,
|
|
103
|
+
variant = "default",
|
|
104
|
+
render,
|
|
105
|
+
...props
|
|
106
|
+
}) {
|
|
107
|
+
return useRender({
|
|
108
|
+
defaultTagName: "span",
|
|
109
|
+
render,
|
|
110
|
+
props: {
|
|
111
|
+
"data-slot": "badge",
|
|
112
|
+
"data-variant": variant,
|
|
113
|
+
className: cn(badgeVariants({ variant }), className),
|
|
114
|
+
...props
|
|
115
|
+
}
|
|
116
|
+
});
|
|
101
117
|
}
|
|
102
118
|
|
|
103
119
|
// src/components/doc/DocTag.tsx
|
|
104
|
-
import { jsx as
|
|
120
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
105
121
|
function DocTag({ entry }) {
|
|
106
|
-
return /* @__PURE__ */
|
|
122
|
+
return /* @__PURE__ */ jsx3("ul", { className: "my-2 flex flex-wrap gap-1.5", "aria-label": "Tags", children: entry.names.map((n) => /* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsx3(Badge, { variant: "tag", children: n }) }, n)) });
|
|
107
123
|
}
|
|
108
124
|
|
|
109
125
|
// src/components/doc/DocKv.tsx
|
|
110
|
-
import { jsx as
|
|
126
|
+
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
111
127
|
function formatValue(value) {
|
|
112
128
|
if (value === null) return "null";
|
|
113
129
|
if (typeof value === "string") return value;
|
|
@@ -119,9 +135,9 @@ function formatValue(value) {
|
|
|
119
135
|
}
|
|
120
136
|
}
|
|
121
137
|
function DocKv({ entry }) {
|
|
122
|
-
return /* @__PURE__ */
|
|
123
|
-
/* @__PURE__ */
|
|
124
|
-
/* @__PURE__ */
|
|
138
|
+
return /* @__PURE__ */ jsxs("dl", { className: "my-2 flex flex-wrap items-baseline gap-x-2 text-sm", children: [
|
|
139
|
+
/* @__PURE__ */ jsx4("dt", { className: "font-semibold text-muted-foreground", children: entry.label }),
|
|
140
|
+
/* @__PURE__ */ jsx4("dd", { className: "font-mono text-foreground", children: formatValue(entry.value) })
|
|
125
141
|
] });
|
|
126
142
|
}
|
|
127
143
|
|
|
@@ -139,37 +155,40 @@ function useBuiltinRenderers() {
|
|
|
139
155
|
}
|
|
140
156
|
|
|
141
157
|
// src/components/doc/DocCode.tsx
|
|
142
|
-
import { Fragment
|
|
158
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
159
|
+
function CodeFigure({ label, children }) {
|
|
160
|
+
return /* @__PURE__ */ jsxs2("figure", { className: "my-3", children: [
|
|
161
|
+
label ? /* @__PURE__ */ jsx5("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: label }) : null,
|
|
162
|
+
/* @__PURE__ */ jsx5("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3", children })
|
|
163
|
+
] });
|
|
164
|
+
}
|
|
143
165
|
function DocCode({ entry }) {
|
|
144
166
|
const renderers = useBuiltinRenderers();
|
|
145
167
|
if (renderers.code) {
|
|
146
|
-
return /* @__PURE__ */
|
|
168
|
+
return /* @__PURE__ */ jsx5(Fragment, { children: renderers.code(entry) });
|
|
147
169
|
}
|
|
148
|
-
return /* @__PURE__ */
|
|
149
|
-
/* @__PURE__ */ jsx6("figcaption", { children: entry.label }),
|
|
150
|
-
/* @__PURE__ */ jsx6("pre", { children: /* @__PURE__ */ jsx6("code", { className: entry.lang ? `language-${entry.lang}` : void 0, children: entry.content }) })
|
|
151
|
-
] });
|
|
170
|
+
return /* @__PURE__ */ jsx5(CodeFigure, { label: entry.label, children: /* @__PURE__ */ jsx5("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
152
171
|
}
|
|
153
172
|
|
|
154
173
|
// src/components/doc/DocTable.tsx
|
|
155
|
-
import { jsx as
|
|
174
|
+
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
156
175
|
function DocTable({ entry }) {
|
|
157
|
-
return /* @__PURE__ */
|
|
158
|
-
/* @__PURE__ */
|
|
159
|
-
/* @__PURE__ */
|
|
160
|
-
/* @__PURE__ */
|
|
161
|
-
/* @__PURE__ */
|
|
162
|
-
] })
|
|
176
|
+
return /* @__PURE__ */ jsxs3("figure", { className: "my-3", children: [
|
|
177
|
+
entry.label ? /* @__PURE__ */ jsx6("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.label }) : null,
|
|
178
|
+
/* @__PURE__ */ jsx6("div", { tabIndex: 0, className: "overflow-x-auto rounded-md border border-border", children: /* @__PURE__ */ jsxs3("table", { className: "w-full border-collapse text-sm", children: [
|
|
179
|
+
/* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsx6("tr", { className: "bg-muted/50", children: entry.columns.map((c) => /* @__PURE__ */ jsx6("th", { scope: "col", className: "border-b border-border px-3 py-2 text-left font-semibold", children: c }, c)) }) }),
|
|
180
|
+
/* @__PURE__ */ jsx6("tbody", { children: entry.rows.map((row, i) => /* @__PURE__ */ jsx6("tr", { children: row.map((cell, j) => /* @__PURE__ */ jsx6("td", { className: "border-b border-border px-3 py-2 text-foreground", children: cell }, j)) }, i)) })
|
|
181
|
+
] }) })
|
|
163
182
|
] });
|
|
164
183
|
}
|
|
165
184
|
|
|
166
185
|
// src/components/doc/DocLink.tsx
|
|
167
|
-
import { jsx as
|
|
186
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
168
187
|
function DocLink({ entry }) {
|
|
169
|
-
return /* @__PURE__ */
|
|
188
|
+
return /* @__PURE__ */ jsx7(
|
|
170
189
|
"a",
|
|
171
190
|
{
|
|
172
|
-
className: "
|
|
191
|
+
className: "text-sm font-medium text-primary underline underline-offset-2 hover:no-underline",
|
|
173
192
|
href: entry.url,
|
|
174
193
|
rel: "noreferrer noopener",
|
|
175
194
|
target: "_blank",
|
|
@@ -180,23 +199,46 @@ function DocLink({ entry }) {
|
|
|
180
199
|
|
|
181
200
|
// src/components/doc/DocSection.tsx
|
|
182
201
|
import { marked } from "marked";
|
|
183
|
-
|
|
202
|
+
|
|
203
|
+
// src/lib/url.ts
|
|
204
|
+
function safeUrl(value) {
|
|
205
|
+
if (!value) return void 0;
|
|
206
|
+
const trimmed = value.trim();
|
|
207
|
+
const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(trimmed);
|
|
208
|
+
if (scheme && !/^https?$/i.test(scheme[1] ?? "")) return void 0;
|
|
209
|
+
return trimmed;
|
|
210
|
+
}
|
|
211
|
+
function safeImageUrl(value) {
|
|
212
|
+
if (!value) return void 0;
|
|
213
|
+
const trimmed = value.trim();
|
|
214
|
+
if (/^data:image\//i.test(trimmed)) return trimmed;
|
|
215
|
+
return safeUrl(trimmed);
|
|
216
|
+
}
|
|
217
|
+
function isLocalFsPath(value) {
|
|
218
|
+
return /^(?:[/\\]|[A-Za-z]:[/\\])/.test(value);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// src/components/doc/DocSection.tsx
|
|
222
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
223
|
+
function neutralizeUrl(value) {
|
|
224
|
+
return safeUrl(value) ?? "#";
|
|
225
|
+
}
|
|
184
226
|
function safeMarkdownHtml(markdown) {
|
|
185
227
|
const raw = marked.parse(markdown, { async: false });
|
|
186
|
-
return raw.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "").replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, "").replace(/\son[a-z]+\s*=\s*'[^']*'/gi, "").replace(/\son[a-z]+\s*=\s*[^\s>]+/gi, "").replace(/(href|src)\s*=\s*"
|
|
228
|
+
return raw.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<\/?(?:iframe|object|embed|form|base)\b[^>]*>/gi, "").replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, "").replace(/\son[a-z]+\s*=\s*'[^']*'/gi, "").replace(/\son[a-z]+\s*=\s*[^\s>]+/gi, "").replace(/(href|src)\s*=\s*"([^"]*)"/gi, (_m, attr, val) => `${attr}="${neutralizeUrl(val)}"`).replace(/(href|src)\s*=\s*'([^']*)'/gi, (_m, attr, val) => `${attr}='${neutralizeUrl(val)}'`);
|
|
187
229
|
}
|
|
188
230
|
function DocSection({ entry }) {
|
|
189
231
|
const renderers = useBuiltinRenderers();
|
|
190
232
|
if (renderers.section) {
|
|
191
|
-
return /* @__PURE__ */
|
|
233
|
+
return /* @__PURE__ */ jsx8(Fragment2, { children: renderers.section(entry) });
|
|
192
234
|
}
|
|
193
235
|
const html = safeMarkdownHtml(entry.markdown);
|
|
194
|
-
return /* @__PURE__ */
|
|
195
|
-
entry.title ? /* @__PURE__ */
|
|
196
|
-
/* @__PURE__ */
|
|
236
|
+
return /* @__PURE__ */ jsxs4("section", { className: "my-3 text-sm", "aria-label": entry.title, children: [
|
|
237
|
+
entry.title ? /* @__PURE__ */ jsx8("h4", { className: "mb-1 font-semibold text-foreground", children: entry.title }) : null,
|
|
238
|
+
/* @__PURE__ */ jsx8(
|
|
197
239
|
"div",
|
|
198
240
|
{
|
|
199
|
-
className: "es-doc-
|
|
241
|
+
className: "es-doc-prose text-muted-foreground",
|
|
200
242
|
dangerouslySetInnerHTML: { __html: html }
|
|
201
243
|
}
|
|
202
244
|
)
|
|
@@ -204,45 +246,129 @@ function DocSection({ entry }) {
|
|
|
204
246
|
}
|
|
205
247
|
|
|
206
248
|
// src/components/doc/DocMermaid.tsx
|
|
207
|
-
import { Fragment as
|
|
249
|
+
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
250
|
+
function MermaidSource({ entry, ref }) {
|
|
251
|
+
return /* @__PURE__ */ jsxs5("figure", { ref, className: "my-3", "aria-label": entry.title ?? "Diagram", children: [
|
|
252
|
+
entry.title ? /* @__PURE__ */ jsx9("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
253
|
+
/* @__PURE__ */ jsx9(
|
|
254
|
+
"pre",
|
|
255
|
+
{
|
|
256
|
+
"data-mermaid": true,
|
|
257
|
+
tabIndex: 0,
|
|
258
|
+
className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground",
|
|
259
|
+
children: entry.code
|
|
260
|
+
}
|
|
261
|
+
)
|
|
262
|
+
] });
|
|
263
|
+
}
|
|
208
264
|
function DocMermaid({ entry }) {
|
|
209
265
|
const renderers = useBuiltinRenderers();
|
|
210
266
|
if (renderers.mermaid) {
|
|
211
|
-
return /* @__PURE__ */
|
|
267
|
+
return /* @__PURE__ */ jsx9(Fragment3, { children: renderers.mermaid(entry) });
|
|
212
268
|
}
|
|
213
|
-
return /* @__PURE__ */
|
|
214
|
-
"figure",
|
|
215
|
-
{
|
|
216
|
-
className: "es-doc es-doc-mermaid",
|
|
217
|
-
"aria-label": entry.title ?? "Diagram",
|
|
218
|
-
children: [
|
|
219
|
-
entry.title ? /* @__PURE__ */ jsx10("figcaption", { children: entry.title }) : null,
|
|
220
|
-
/* @__PURE__ */ jsx10("pre", { "data-mermaid": true, children: entry.code })
|
|
221
|
-
]
|
|
222
|
-
}
|
|
223
|
-
);
|
|
269
|
+
return /* @__PURE__ */ jsx9(MermaidSource, { entry });
|
|
224
270
|
}
|
|
225
271
|
|
|
226
272
|
// src/components/doc/DocScreenshot.tsx
|
|
227
|
-
import { jsx as
|
|
273
|
+
import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
228
274
|
function DocScreenshot({ entry }) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
275
|
+
const src = isLocalFsPath(entry.path) ? void 0 : safeImageUrl(entry.path);
|
|
276
|
+
if (!src) {
|
|
277
|
+
return /* @__PURE__ */ jsxs6("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
|
|
278
|
+
/* @__PURE__ */ jsx10("div", { className: "font-medium", children: "Screenshot unavailable" }),
|
|
279
|
+
/* @__PURE__ */ jsx10("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
280
|
+
entry.alt ? /* @__PURE__ */ jsx10("figcaption", { className: "mt-1.5 text-xs", children: entry.alt }) : null
|
|
281
|
+
] });
|
|
282
|
+
}
|
|
283
|
+
return /* @__PURE__ */ jsxs6("figure", { className: "my-3", children: [
|
|
284
|
+
/* @__PURE__ */ jsx10(
|
|
285
|
+
"img",
|
|
286
|
+
{
|
|
287
|
+
src,
|
|
288
|
+
alt: entry.alt ?? "",
|
|
289
|
+
loading: "lazy",
|
|
290
|
+
className: "max-w-full rounded-md border border-border"
|
|
291
|
+
}
|
|
292
|
+
),
|
|
293
|
+
entry.alt ? /* @__PURE__ */ jsx10("figcaption", { className: "mt-1.5 text-xs text-muted-foreground", children: entry.alt }) : null
|
|
294
|
+
] });
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// src/components/doc/DocVideo.tsx
|
|
298
|
+
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
299
|
+
function DocVideo({ entry }) {
|
|
300
|
+
if (isLocalFsPath(entry.path)) {
|
|
301
|
+
return /* @__PURE__ */ jsxs7("figure", { className: "my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground", children: [
|
|
302
|
+
/* @__PURE__ */ jsx11("div", { className: "font-medium", children: "Video unavailable" }),
|
|
303
|
+
/* @__PURE__ */ jsx11("div", { className: "mt-1 break-all font-mono text-xs", children: entry.path }),
|
|
304
|
+
entry.caption ? /* @__PURE__ */ jsx11("figcaption", { className: "mt-1.5 text-xs", children: entry.caption }) : null
|
|
305
|
+
] });
|
|
306
|
+
}
|
|
307
|
+
const src = safeUrl(entry.path);
|
|
308
|
+
const poster = safeUrl(entry.poster);
|
|
309
|
+
return /* @__PURE__ */ jsxs7("figure", { className: "my-3", children: [
|
|
310
|
+
/* @__PURE__ */ jsx11(
|
|
311
|
+
"video",
|
|
312
|
+
{
|
|
313
|
+
controls: true,
|
|
314
|
+
preload: "metadata",
|
|
315
|
+
...src ? { src } : {},
|
|
316
|
+
...poster ? { poster } : {},
|
|
317
|
+
className: "max-w-full rounded-md border border-border"
|
|
318
|
+
}
|
|
319
|
+
),
|
|
320
|
+
entry.caption ? /* @__PURE__ */ jsx11("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: entry.caption }) : null
|
|
321
|
+
] });
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// src/components/doc/DocHtml.tsx
|
|
325
|
+
import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
326
|
+
function DocHtml({ entry }) {
|
|
327
|
+
const height = typeof entry.height === "number" ? `${entry.height}px` : entry.height ?? "400px";
|
|
328
|
+
const title = entry.title ?? "Embedded HTML";
|
|
329
|
+
const safeHref = safeUrl(entry.url ?? entry.path);
|
|
330
|
+
const frameProps = entry.content !== void 0 ? { srcDoc: entry.content } : { src: safeHref ?? "" };
|
|
331
|
+
return /* @__PURE__ */ jsxs8("figure", { className: "my-3 overflow-hidden rounded-md border border-border", children: [
|
|
332
|
+
/* @__PURE__ */ jsxs8("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: [
|
|
333
|
+
/* @__PURE__ */ jsx12("span", { children: entry.title ?? "HTML" }),
|
|
334
|
+
safeHref ? /* @__PURE__ */ jsx12(
|
|
335
|
+
"a",
|
|
336
|
+
{
|
|
337
|
+
href: safeHref,
|
|
338
|
+
target: "_blank",
|
|
339
|
+
rel: "noreferrer noopener",
|
|
340
|
+
"aria-label": "Open in new tab",
|
|
341
|
+
title: "Open in new tab",
|
|
342
|
+
className: "text-primary",
|
|
343
|
+
children: "\u2197"
|
|
344
|
+
}
|
|
345
|
+
) : null
|
|
346
|
+
] }),
|
|
347
|
+
/* @__PURE__ */ jsx12(
|
|
348
|
+
"iframe",
|
|
349
|
+
{
|
|
350
|
+
...frameProps,
|
|
351
|
+
sandbox: "allow-scripts",
|
|
352
|
+
loading: "lazy",
|
|
353
|
+
title,
|
|
354
|
+
className: "block w-full border-0",
|
|
355
|
+
style: { height }
|
|
356
|
+
}
|
|
357
|
+
)
|
|
232
358
|
] });
|
|
233
359
|
}
|
|
234
360
|
|
|
235
361
|
// src/components/doc/DocCustom.tsx
|
|
236
|
-
import { Fragment as
|
|
362
|
+
import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
237
363
|
function DocCustom({ entry }) {
|
|
238
364
|
const renderers = useCustomRenderers();
|
|
239
365
|
const renderer = renderers[entry.type];
|
|
240
366
|
if (renderer) {
|
|
241
|
-
return /* @__PURE__ */
|
|
367
|
+
return /* @__PURE__ */ jsx13(Fragment4, { children: renderer(entry) });
|
|
242
368
|
}
|
|
243
|
-
return /* @__PURE__ */
|
|
244
|
-
/* @__PURE__ */
|
|
245
|
-
/* @__PURE__ */
|
|
369
|
+
return /* @__PURE__ */ jsxs9("div", { className: "my-2", "data-type": entry.type, children: [
|
|
370
|
+
/* @__PURE__ */ jsx13("p", { className: "mb-1 text-xs font-medium text-muted-foreground", children: entry.type }),
|
|
371
|
+
/* @__PURE__ */ jsx13("pre", { tabIndex: 0, className: "overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground", children: safeStringify(entry.data) })
|
|
246
372
|
] });
|
|
247
373
|
}
|
|
248
374
|
function safeStringify(value) {
|
|
@@ -254,231 +380,998 @@ function safeStringify(value) {
|
|
|
254
380
|
}
|
|
255
381
|
|
|
256
382
|
// src/components/doc/DocEntry.tsx
|
|
257
|
-
import { jsx as
|
|
383
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
258
384
|
function DocEntry({ entry }) {
|
|
259
385
|
switch (entry.kind) {
|
|
260
386
|
case "note":
|
|
261
|
-
return /* @__PURE__ */
|
|
387
|
+
return /* @__PURE__ */ jsx14(DocNote, { entry });
|
|
262
388
|
case "tag":
|
|
263
|
-
return /* @__PURE__ */
|
|
389
|
+
return /* @__PURE__ */ jsx14(DocTag, { entry });
|
|
264
390
|
case "kv":
|
|
265
|
-
return /* @__PURE__ */
|
|
391
|
+
return /* @__PURE__ */ jsx14(DocKv, { entry });
|
|
266
392
|
case "code":
|
|
267
|
-
return /* @__PURE__ */
|
|
393
|
+
return /* @__PURE__ */ jsx14(DocCode, { entry });
|
|
268
394
|
case "table":
|
|
269
|
-
return /* @__PURE__ */
|
|
395
|
+
return /* @__PURE__ */ jsx14(DocTable, { entry });
|
|
270
396
|
case "link":
|
|
271
|
-
return /* @__PURE__ */
|
|
397
|
+
return /* @__PURE__ */ jsx14(DocLink, { entry });
|
|
272
398
|
case "section":
|
|
273
|
-
return /* @__PURE__ */
|
|
399
|
+
return /* @__PURE__ */ jsx14(DocSection, { entry });
|
|
274
400
|
case "mermaid":
|
|
275
|
-
return /* @__PURE__ */
|
|
401
|
+
return /* @__PURE__ */ jsx14(DocMermaid, { entry });
|
|
276
402
|
case "screenshot":
|
|
277
|
-
return /* @__PURE__ */
|
|
403
|
+
return /* @__PURE__ */ jsx14(DocScreenshot, { entry });
|
|
404
|
+
case "video":
|
|
405
|
+
return /* @__PURE__ */ jsx14(DocVideo, { entry });
|
|
406
|
+
case "html":
|
|
407
|
+
return /* @__PURE__ */ jsx14(DocHtml, { entry });
|
|
278
408
|
case "custom":
|
|
279
|
-
return /* @__PURE__ */
|
|
409
|
+
return /* @__PURE__ */ jsx14(DocCustom, { entry });
|
|
280
410
|
}
|
|
281
411
|
}
|
|
282
412
|
|
|
283
413
|
// src/components/ReportDocEntries.tsx
|
|
284
|
-
import { Fragment as
|
|
414
|
+
import { Fragment as Fragment5, jsx as jsx15 } from "react/jsx-runtime";
|
|
285
415
|
function ReportDocEntries({ entries }) {
|
|
286
416
|
if (entries.length === 0) return null;
|
|
287
|
-
return /* @__PURE__ */
|
|
417
|
+
return /* @__PURE__ */ jsx15(Fragment5, { children: entries.map((entry, i) => /* @__PURE__ */ jsx15(DocEntry, { entry }, i)) });
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// src/lib/step-params.tsx
|
|
421
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
422
|
+
var STEP_PARAM_PATTERN = /"[^"]*"|(?<![\w.-])\d+(?:\.\d+)?(?![\w.-])/g;
|
|
423
|
+
function highlightStepParams(text) {
|
|
424
|
+
const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));
|
|
425
|
+
if (matches.length === 0) return text;
|
|
426
|
+
const nodes = [];
|
|
427
|
+
let lastIndex = 0;
|
|
428
|
+
matches.forEach((match, i) => {
|
|
429
|
+
const start = match.index;
|
|
430
|
+
const end = start + match[0].length;
|
|
431
|
+
if (start > lastIndex) nodes.push(text.slice(lastIndex, start));
|
|
432
|
+
nodes.push(
|
|
433
|
+
/* @__PURE__ */ jsx16("span", { className: "font-medium text-step-param italic", children: match[0] }, i)
|
|
434
|
+
);
|
|
435
|
+
lastIndex = end;
|
|
436
|
+
});
|
|
437
|
+
if (lastIndex < text.length) nodes.push(text.slice(lastIndex));
|
|
438
|
+
return nodes;
|
|
288
439
|
}
|
|
289
440
|
|
|
290
441
|
// src/components/ReportSteps.tsx
|
|
291
|
-
import { jsx as
|
|
442
|
+
import { jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
443
|
+
var STEP_GLYPH = {
|
|
444
|
+
passed: "\u2713",
|
|
445
|
+
failed: "\u2717",
|
|
446
|
+
skipped: "\u25CB",
|
|
447
|
+
pending: "\u25CB"
|
|
448
|
+
};
|
|
449
|
+
var STEP_GLYPH_COLOR = {
|
|
450
|
+
passed: "text-pass",
|
|
451
|
+
failed: "text-fail",
|
|
452
|
+
skipped: "text-skip",
|
|
453
|
+
pending: "text-pend"
|
|
454
|
+
};
|
|
292
455
|
function ReportSteps({ scenario }) {
|
|
293
456
|
if (scenario.steps.length === 0) return null;
|
|
294
|
-
return /* @__PURE__ */
|
|
457
|
+
return /* @__PURE__ */ jsx17("ol", { "data-slot": "steps", className: "flex flex-col", children: scenario.steps.map((step) => /* @__PURE__ */ jsx17(ReportStepItem, { step }, step.id)) });
|
|
295
458
|
}
|
|
296
459
|
function ReportStepItem({ step }) {
|
|
297
|
-
|
|
460
|
+
const kw = step.keyword.toLowerCase();
|
|
461
|
+
const continuation = kw === "and" || kw === "but";
|
|
462
|
+
return /* @__PURE__ */ jsxs10(
|
|
298
463
|
"li",
|
|
299
464
|
{
|
|
300
465
|
id: step.id,
|
|
301
|
-
className: `es-step es-step-${step.status}`,
|
|
302
466
|
"data-status": step.status,
|
|
467
|
+
className: cn("py-1.5 text-[0.8125rem] leading-normal", continuation && "pl-5"),
|
|
303
468
|
children: [
|
|
304
|
-
/* @__PURE__ */
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
469
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-baseline gap-2", children: [
|
|
470
|
+
/* @__PURE__ */ jsx17("span", { "aria-hidden": true, className: cn("w-4 shrink-0 text-center text-xs", STEP_GLYPH_COLOR[step.status]), children: STEP_GLYPH[step.status] ?? "\u25CB" }),
|
|
471
|
+
/* @__PURE__ */ jsx17(
|
|
472
|
+
"span",
|
|
473
|
+
{
|
|
474
|
+
className: cn(
|
|
475
|
+
"min-w-[52px] shrink-0 font-mono text-xs font-semibold capitalize",
|
|
476
|
+
continuation ? "font-medium text-muted-foreground" : "text-keyword"
|
|
477
|
+
),
|
|
478
|
+
children: step.keyword
|
|
479
|
+
}
|
|
480
|
+
),
|
|
481
|
+
/* @__PURE__ */ jsx17("span", { className: "flex-1 text-foreground", children: highlightStepParams(step.text) }),
|
|
482
|
+
step.durationMs > 0 ? /* @__PURE__ */ jsx17("span", { className: "shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration(step.durationMs) }) : null
|
|
483
|
+
] }),
|
|
484
|
+
step.errorMessage ? /* @__PURE__ */ jsx17(
|
|
485
|
+
"pre",
|
|
486
|
+
{
|
|
487
|
+
role: "alert",
|
|
488
|
+
className: "mt-2.5 ml-6 overflow-x-auto rounded-md border border-fail-border bg-fail-bg px-4 py-3.5 font-mono text-xs leading-relaxed whitespace-pre-wrap text-fail",
|
|
489
|
+
children: step.errorMessage
|
|
490
|
+
}
|
|
491
|
+
) : null,
|
|
492
|
+
step.docEntries.length > 0 ? /* @__PURE__ */ jsx17("div", { "data-es-docs": true, className: "mt-2 ml-6", children: /* @__PURE__ */ jsx17(ReportDocEntries, { entries: step.docEntries }) }) : null
|
|
308
493
|
]
|
|
309
494
|
}
|
|
310
495
|
);
|
|
311
496
|
}
|
|
312
497
|
|
|
498
|
+
// src/components/ReportAttachments.tsx
|
|
499
|
+
import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
500
|
+
function ReportAttachments({ attachments }) {
|
|
501
|
+
if (attachments.length === 0) return null;
|
|
502
|
+
return (
|
|
503
|
+
// role="group" (not a labelled <section>) so multiple scenarios' attachment
|
|
504
|
+
// blocks don't create duplicate "Attachments" region landmarks.
|
|
505
|
+
/* @__PURE__ */ jsx18("div", { role: "group", "aria-label": "Attachments", className: "mt-3 flex flex-col gap-2", children: attachments.map((att, i) => {
|
|
506
|
+
const dataUri = att.contentEncoding === "BASE64" ? `data:${att.mediaType};base64,${att.body}` : `data:${att.mediaType},${encodeURIComponent(att.body)}`;
|
|
507
|
+
const isImage = att.mediaType.startsWith("image/");
|
|
508
|
+
return /* @__PURE__ */ jsx18("figure", { className: "m-0", children: isImage ? /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
509
|
+
/* @__PURE__ */ jsx18(
|
|
510
|
+
"img",
|
|
511
|
+
{
|
|
512
|
+
src: dataUri,
|
|
513
|
+
alt: att.name,
|
|
514
|
+
loading: "lazy",
|
|
515
|
+
className: "max-w-full rounded-md border border-border"
|
|
516
|
+
}
|
|
517
|
+
),
|
|
518
|
+
/* @__PURE__ */ jsx18("figcaption", { className: "mt-1 text-xs text-muted-foreground", children: att.name })
|
|
519
|
+
] }) : /* @__PURE__ */ jsxs11(
|
|
520
|
+
"a",
|
|
521
|
+
{
|
|
522
|
+
href: dataUri,
|
|
523
|
+
download: att.name,
|
|
524
|
+
className: "text-xs text-link underline underline-offset-2",
|
|
525
|
+
children: [
|
|
526
|
+
att.name,
|
|
527
|
+
" ",
|
|
528
|
+
/* @__PURE__ */ jsxs11("span", { className: "text-muted-foreground", children: [
|
|
529
|
+
"(",
|
|
530
|
+
att.mediaType,
|
|
531
|
+
")"
|
|
532
|
+
] })
|
|
533
|
+
]
|
|
534
|
+
}
|
|
535
|
+
) }, `${att.name}-${i}`);
|
|
536
|
+
}) })
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// src/components/ReportTrace.tsx
|
|
541
|
+
import { formatDuration as formatDuration2 } from "executable-stories-core/utils/duration";
|
|
542
|
+
|
|
543
|
+
// src/lib/trace.ts
|
|
544
|
+
var VALID = /* @__PURE__ */ new Set(["ok", "error", "unset"]);
|
|
545
|
+
var safeStatus = (s) => VALID.has(s) ? s : "unset";
|
|
546
|
+
function normalizeSpans(spans) {
|
|
547
|
+
const out = [];
|
|
548
|
+
for (const span of spans) {
|
|
549
|
+
if (!span || typeof span.spanId !== "string" || typeof span.name !== "string") continue;
|
|
550
|
+
let startTimeMs;
|
|
551
|
+
let durationMs;
|
|
552
|
+
if (span.startTimeMs != null && span.durationMs != null) {
|
|
553
|
+
startTimeMs = span.startTimeMs;
|
|
554
|
+
durationMs = span.durationMs;
|
|
555
|
+
} else if (span.startTimeUnixNano != null && span.endTimeUnixNano != null) {
|
|
556
|
+
startTimeMs = span.startTimeUnixNano / 1e6;
|
|
557
|
+
durationMs = (span.endTimeUnixNano - span.startTimeUnixNano) / 1e6;
|
|
558
|
+
} else {
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
durationMs = Math.max(0, durationMs);
|
|
562
|
+
if (!isFinite(startTimeMs) || !isFinite(durationMs)) continue;
|
|
563
|
+
out.push({
|
|
564
|
+
spanId: span.spanId,
|
|
565
|
+
parentSpanId: span.parentSpanId,
|
|
566
|
+
name: span.name,
|
|
567
|
+
startTimeMs,
|
|
568
|
+
durationMs,
|
|
569
|
+
status: safeStatus(span.status),
|
|
570
|
+
statusMessage: span.statusMessage
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
return out;
|
|
574
|
+
}
|
|
575
|
+
function toTraceRows(spans) {
|
|
576
|
+
const normalized = normalizeSpans(spans);
|
|
577
|
+
if (normalized.length === 0) return [];
|
|
578
|
+
const byId = /* @__PURE__ */ new Map();
|
|
579
|
+
for (const span of normalized) {
|
|
580
|
+
let key = span.spanId;
|
|
581
|
+
let suffix = 2;
|
|
582
|
+
while (byId.has(key)) key = `${span.spanId}__dup${suffix++}`;
|
|
583
|
+
byId.set(key, { span: { ...span, spanId: key }, children: [], depth: 0 });
|
|
584
|
+
}
|
|
585
|
+
const roots = [];
|
|
586
|
+
for (const node of byId.values()) {
|
|
587
|
+
const parent = node.span.parentSpanId ? byId.get(node.span.parentSpanId) : void 0;
|
|
588
|
+
if (parent && parent !== node) parent.children.push(node);
|
|
589
|
+
else roots.push(node);
|
|
590
|
+
}
|
|
591
|
+
for (const node of byId.values()) node.children.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
592
|
+
roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);
|
|
593
|
+
const rows = [];
|
|
594
|
+
const seen = /* @__PURE__ */ new Set();
|
|
595
|
+
const walk = (node, depth) => {
|
|
596
|
+
if (seen.has(node.span.spanId)) return;
|
|
597
|
+
seen.add(node.span.spanId);
|
|
598
|
+
rows.push({ ...node.span, depth });
|
|
599
|
+
for (const child of node.children) walk(child, depth + 1);
|
|
600
|
+
};
|
|
601
|
+
for (const root of roots) walk(root, 0);
|
|
602
|
+
for (const node of byId.values()) {
|
|
603
|
+
if (!seen.has(node.span.spanId)) walk(node, 0);
|
|
604
|
+
}
|
|
605
|
+
return rows;
|
|
606
|
+
}
|
|
607
|
+
function traceWindow(rows) {
|
|
608
|
+
let min = Infinity;
|
|
609
|
+
let max = -Infinity;
|
|
610
|
+
for (const r of rows) {
|
|
611
|
+
min = Math.min(min, r.startTimeMs);
|
|
612
|
+
max = Math.max(max, r.startTimeMs + r.durationMs);
|
|
613
|
+
}
|
|
614
|
+
const total = max - min;
|
|
615
|
+
return { minStartMs: isFinite(min) ? min : 0, totalMs: total > 0 ? total : 1 };
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// src/components/ReportTrace.tsx
|
|
619
|
+
import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
620
|
+
var BAR_COLOR = {
|
|
621
|
+
ok: "bg-pass",
|
|
622
|
+
error: "bg-fail",
|
|
623
|
+
unset: "bg-skip"
|
|
624
|
+
};
|
|
625
|
+
function ReportTrace({ spans }) {
|
|
626
|
+
if (!spans || spans.length === 0) return null;
|
|
627
|
+
const rows = toTraceRows(spans);
|
|
628
|
+
if (rows.length === 0) return null;
|
|
629
|
+
const { minStartMs, totalMs } = traceWindow(rows);
|
|
630
|
+
return /* @__PURE__ */ jsxs12("details", { className: "mt-3 rounded-md border border-border bg-muted/30", children: [
|
|
631
|
+
/* @__PURE__ */ jsxs12("summary", { className: "cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground", children: [
|
|
632
|
+
"Trace (",
|
|
633
|
+
rows.length,
|
|
634
|
+
" span",
|
|
635
|
+
rows.length === 1 ? "" : "s",
|
|
636
|
+
", ",
|
|
637
|
+
formatDuration2(totalMs),
|
|
638
|
+
")"
|
|
639
|
+
] }),
|
|
640
|
+
/* @__PURE__ */ jsx19("ul", { className: "flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]", children: rows.map((row, i) => {
|
|
641
|
+
const leftPct = (row.startTimeMs - minStartMs) / totalMs * 100;
|
|
642
|
+
const widthPct = Math.max(row.durationMs / totalMs * 100, 0.5);
|
|
643
|
+
return /* @__PURE__ */ jsxs12("li", { className: "flex items-center gap-2", children: [
|
|
644
|
+
/* @__PURE__ */ jsx19(
|
|
645
|
+
"span",
|
|
646
|
+
{
|
|
647
|
+
className: "min-w-0 flex-1 truncate text-foreground",
|
|
648
|
+
style: { paddingLeft: `${row.depth * 12}px` },
|
|
649
|
+
title: row.statusMessage ? `${row.name} \u2014 ${row.statusMessage}` : row.name,
|
|
650
|
+
children: row.name
|
|
651
|
+
}
|
|
652
|
+
),
|
|
653
|
+
/* @__PURE__ */ jsx19("span", { className: "relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40", children: /* @__PURE__ */ jsx19(
|
|
654
|
+
"span",
|
|
655
|
+
{
|
|
656
|
+
className: cn("absolute top-0 h-full rounded-sm", BAR_COLOR[row.status]),
|
|
657
|
+
style: { left: `${leftPct}%`, width: `${widthPct}%` }
|
|
658
|
+
}
|
|
659
|
+
) }),
|
|
660
|
+
/* @__PURE__ */ jsx19("span", { className: "w-16 shrink-0 text-right text-muted-foreground", children: formatDuration2(row.durationMs) })
|
|
661
|
+
] }, `${row.spanId}-${i}`);
|
|
662
|
+
}) })
|
|
663
|
+
] });
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// src/interactive/collapse-context.ts
|
|
667
|
+
import { createContext as createContext2, useCallback, useContext as useContext3, useState } from "react";
|
|
668
|
+
var CollapseContext = createContext2(null);
|
|
669
|
+
var CollapseProvider = CollapseContext.Provider;
|
|
670
|
+
function useCollapse() {
|
|
671
|
+
return useContext3(CollapseContext);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// src/interactive/scenario-actions.tsx
|
|
675
|
+
import { createContext as createContext3, useContext as useContext4 } from "react";
|
|
676
|
+
var ScenarioActionsContext = createContext3(null);
|
|
677
|
+
var ScenarioActionsProvider = ScenarioActionsContext.Provider;
|
|
678
|
+
function useScenarioActions() {
|
|
679
|
+
return useContext4(ScenarioActionsContext);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// src/components/ui/card.tsx
|
|
683
|
+
import "react";
|
|
684
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
685
|
+
function Card({ className, ...props }) {
|
|
686
|
+
return /* @__PURE__ */ jsx20(
|
|
687
|
+
"div",
|
|
688
|
+
{
|
|
689
|
+
"data-slot": "card",
|
|
690
|
+
className: cn(
|
|
691
|
+
"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm",
|
|
692
|
+
className
|
|
693
|
+
),
|
|
694
|
+
...props
|
|
695
|
+
}
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
function CardHeader({ className, ...props }) {
|
|
699
|
+
return /* @__PURE__ */ jsx20(
|
|
700
|
+
"div",
|
|
701
|
+
{
|
|
702
|
+
"data-slot": "card-header",
|
|
703
|
+
className: cn(
|
|
704
|
+
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
|
705
|
+
className
|
|
706
|
+
),
|
|
707
|
+
...props
|
|
708
|
+
}
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
function CardContent({ className, ...props }) {
|
|
712
|
+
return /* @__PURE__ */ jsx20(
|
|
713
|
+
"div",
|
|
714
|
+
{
|
|
715
|
+
"data-slot": "card-content",
|
|
716
|
+
className: cn("px-6", className),
|
|
717
|
+
...props
|
|
718
|
+
}
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
|
|
313
722
|
// src/components/ReportScenario.tsx
|
|
314
|
-
import { jsx as
|
|
723
|
+
import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
315
724
|
var STATUS_LABEL = {
|
|
316
725
|
passed: "Passed",
|
|
317
726
|
failed: "Failed",
|
|
318
727
|
skipped: "Skipped",
|
|
319
728
|
pending: "Pending"
|
|
320
729
|
};
|
|
321
|
-
|
|
730
|
+
var STATUS_GLYPH = {
|
|
731
|
+
passed: "\u2713",
|
|
732
|
+
failed: "\u2717",
|
|
733
|
+
skipped: "\u25CB",
|
|
734
|
+
pending: "\u25CB"
|
|
735
|
+
};
|
|
736
|
+
var STATUS_GLYPH_COLOR = {
|
|
737
|
+
passed: "text-pass",
|
|
738
|
+
failed: "text-fail",
|
|
739
|
+
skipped: "text-skip",
|
|
740
|
+
pending: "text-pend"
|
|
741
|
+
};
|
|
742
|
+
var STATUS_BADGE = {
|
|
743
|
+
passed: "passed",
|
|
744
|
+
failed: "failed",
|
|
745
|
+
skipped: "skipped",
|
|
746
|
+
pending: "pending"
|
|
747
|
+
};
|
|
748
|
+
function ReportScenario({ scenario, hideTitle = false }) {
|
|
322
749
|
const titleId = `${scenario.id}-title`;
|
|
323
|
-
|
|
324
|
-
|
|
750
|
+
const bodyId = `${scenario.id}-body`;
|
|
751
|
+
const label = STATUS_LABEL[scenario.status];
|
|
752
|
+
const collapse = useCollapse();
|
|
753
|
+
const collapsible = collapse !== null && !hideTitle;
|
|
754
|
+
const collapsed = collapsible ? collapse.isCollapsed(scenario.id) : false;
|
|
755
|
+
const actions = useScenarioActions();
|
|
756
|
+
return /* @__PURE__ */ jsxs13(
|
|
757
|
+
Card,
|
|
325
758
|
{
|
|
326
759
|
id: scenario.id,
|
|
327
|
-
className: `es-scenario es-status-${scenario.status}`,
|
|
328
|
-
"aria-labelledby": titleId,
|
|
329
760
|
"data-status": scenario.status,
|
|
761
|
+
...hideTitle ? { "aria-label": `${scenario.title} \u2014 ${label}` } : { "aria-labelledby": titleId },
|
|
762
|
+
className: "gap-0 py-0",
|
|
330
763
|
children: [
|
|
331
|
-
/* @__PURE__ */
|
|
332
|
-
/* @__PURE__ */
|
|
333
|
-
|
|
764
|
+
/* @__PURE__ */ jsxs13(CardHeader, { className: "px-4 py-3", children: [
|
|
765
|
+
/* @__PURE__ */ jsxs13("div", { className: cn("flex items-start gap-4", hideTitle ? "justify-end" : "justify-between"), children: [
|
|
766
|
+
hideTitle ? null : /* @__PURE__ */ jsxs13("h3", { id: titleId, className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
767
|
+
collapsible ? /* @__PURE__ */ jsx21(
|
|
768
|
+
"button",
|
|
769
|
+
{
|
|
770
|
+
type: "button",
|
|
771
|
+
onClick: () => collapse.toggle(scenario.id),
|
|
772
|
+
"aria-expanded": !collapsed,
|
|
773
|
+
"aria-controls": bodyId,
|
|
774
|
+
"aria-label": `Toggle ${scenario.title}`,
|
|
775
|
+
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
776
|
+
children: /* @__PURE__ */ jsx21("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
777
|
+
}
|
|
778
|
+
) : null,
|
|
779
|
+
/* @__PURE__ */ jsx21("span", { "aria-hidden": true, className: cn("text-sm leading-none", STATUS_GLYPH_COLOR[scenario.status]), children: STATUS_GLYPH[scenario.status] }),
|
|
780
|
+
/* @__PURE__ */ jsx21("span", { children: scenario.title })
|
|
781
|
+
] }),
|
|
782
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
783
|
+
scenario.durationMs > 0 ? /* @__PURE__ */ jsx21("span", { className: "whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground", children: formatDuration3(scenario.durationMs) }) : null,
|
|
784
|
+
/* @__PURE__ */ jsx21(Badge, { variant: STATUS_BADGE[scenario.status], "aria-label": `Status: ${label}`, children: label }),
|
|
785
|
+
actions ? /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-0.5", children: [
|
|
786
|
+
/* @__PURE__ */ jsx21(
|
|
787
|
+
"button",
|
|
788
|
+
{
|
|
789
|
+
type: "button",
|
|
790
|
+
onClick: () => actions.copyLink(scenario),
|
|
791
|
+
"aria-label": `Copy link to ${scenario.title}`,
|
|
792
|
+
title: "Copy permalink",
|
|
793
|
+
className: "cursor-pointer rounded px-1 py-0.5 font-mono text-[0.625rem] text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
794
|
+
children: "link"
|
|
795
|
+
}
|
|
796
|
+
),
|
|
797
|
+
/* @__PURE__ */ jsx21(
|
|
798
|
+
"button",
|
|
799
|
+
{
|
|
800
|
+
type: "button",
|
|
801
|
+
onClick: () => actions.copyMarkdown(scenario),
|
|
802
|
+
"aria-label": `Copy ${scenario.title} as Markdown`,
|
|
803
|
+
title: "Copy as Markdown",
|
|
804
|
+
className: "cursor-pointer rounded px-1 py-0.5 font-mono text-[0.625rem] text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
805
|
+
children: "md"
|
|
806
|
+
}
|
|
807
|
+
),
|
|
808
|
+
/* @__PURE__ */ jsx21(
|
|
809
|
+
"button",
|
|
810
|
+
{
|
|
811
|
+
type: "button",
|
|
812
|
+
onClick: () => actions.copyPrompt(scenario),
|
|
813
|
+
"aria-label": `Copy ${scenario.title} as an AI investigation prompt`,
|
|
814
|
+
title: "Copy as AI prompt",
|
|
815
|
+
className: "cursor-pointer rounded px-1 py-0.5 font-mono text-[0.625rem] text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
816
|
+
children: "ai"
|
|
817
|
+
}
|
|
818
|
+
)
|
|
819
|
+
] }) : null
|
|
820
|
+
] })
|
|
821
|
+
] }),
|
|
822
|
+
scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? /* @__PURE__ */ jsxs13("ul", { "aria-label": "Tags and tickets", className: "flex flex-wrap gap-1.5", children: [
|
|
823
|
+
scenario.tags.map((t) => /* @__PURE__ */ jsx21("li", { children: /* @__PURE__ */ jsx21(Badge, { variant: "tag", children: t }) }, `tag-${t}`)),
|
|
824
|
+
(scenario.tickets ?? []).map((ticket) => /* @__PURE__ */ jsx21("li", { children: ticket.url ? /* @__PURE__ */ jsx21("a", { href: ticket.url, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ jsx21(Badge, { variant: "outline", children: ticket.id }) }) : /* @__PURE__ */ jsx21(Badge, { variant: "outline", children: ticket.id }) }, `ticket-${ticket.id}`))
|
|
825
|
+
] }) : null
|
|
334
826
|
] }),
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
827
|
+
/* @__PURE__ */ jsxs13(CardContent, { id: bodyId, hidden: collapsed, className: "px-4 pt-0 pb-4", children: [
|
|
828
|
+
scenario.errorMessage ? /* @__PURE__ */ jsx21(
|
|
829
|
+
"pre",
|
|
830
|
+
{
|
|
831
|
+
role: "alert",
|
|
832
|
+
className: "mb-1 overflow-x-auto rounded-md border border-fail-border bg-fail-bg px-4 py-3.5 font-mono text-xs leading-relaxed whitespace-pre-wrap text-fail",
|
|
833
|
+
children: scenario.errorMessage
|
|
834
|
+
}
|
|
835
|
+
) : null,
|
|
836
|
+
/* @__PURE__ */ jsx21(ReportSteps, { scenario }),
|
|
837
|
+
scenario.docEntries.length > 0 ? /* @__PURE__ */ jsx21("div", { "data-es-docs": true, className: "mt-3", children: /* @__PURE__ */ jsx21(ReportDocEntries, { entries: scenario.docEntries }) }) : null,
|
|
838
|
+
/* @__PURE__ */ jsx21(ReportAttachments, { attachments: scenario.attachments }),
|
|
839
|
+
/* @__PURE__ */ jsx21(ReportTrace, { spans: scenario.otelSpans })
|
|
840
|
+
] })
|
|
339
841
|
]
|
|
340
842
|
}
|
|
341
843
|
);
|
|
342
844
|
}
|
|
343
845
|
|
|
344
846
|
// src/components/ReportScenarioList.tsx
|
|
345
|
-
import { Fragment as Fragment7, jsx as
|
|
847
|
+
import { Fragment as Fragment7, jsx as jsx22 } from "react/jsx-runtime";
|
|
346
848
|
function ReportScenarioList({ feature }) {
|
|
347
|
-
return /* @__PURE__ */
|
|
849
|
+
return /* @__PURE__ */ jsx22(Fragment7, { children: feature.scenarios.map((scenario) => /* @__PURE__ */ jsx22(ReportScenario, { scenario }, scenario.id)) });
|
|
348
850
|
}
|
|
349
851
|
|
|
350
852
|
// src/components/ReportFeature.tsx
|
|
351
|
-
import { jsx as
|
|
853
|
+
import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
352
854
|
function ReportFeature({ feature }) {
|
|
353
855
|
const titleId = `${feature.id}-title`;
|
|
354
|
-
|
|
856
|
+
const bodyId = `${feature.id}-body`;
|
|
857
|
+
const s = feature.summary;
|
|
858
|
+
const skipped = s.skipped + s.pending;
|
|
859
|
+
const collapse = useCollapse();
|
|
860
|
+
const collapsed = collapse?.isCollapsed(feature.id) ?? false;
|
|
861
|
+
return /* @__PURE__ */ jsxs14(
|
|
355
862
|
"section",
|
|
356
863
|
{
|
|
357
864
|
id: feature.id,
|
|
358
|
-
|
|
865
|
+
"data-slot": "feature",
|
|
359
866
|
"aria-labelledby": titleId,
|
|
867
|
+
className: "overflow-hidden rounded-xl border border-border bg-card shadow-sm",
|
|
360
868
|
children: [
|
|
361
|
-
/* @__PURE__ */
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
869
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between gap-4 border-b border-border bg-muted/40 px-4 py-3", children: [
|
|
870
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
871
|
+
collapse ? /* @__PURE__ */ jsx23(
|
|
872
|
+
"button",
|
|
873
|
+
{
|
|
874
|
+
type: "button",
|
|
875
|
+
onClick: () => collapse.toggle(feature.id),
|
|
876
|
+
"aria-expanded": !collapsed,
|
|
877
|
+
"aria-controls": bodyId,
|
|
878
|
+
"aria-label": `Toggle ${feature.title}`,
|
|
879
|
+
className: "shrink-0 cursor-pointer text-muted-foreground hover:text-foreground",
|
|
880
|
+
children: /* @__PURE__ */ jsx23("span", { "aria-hidden": true, className: cn("inline-block text-xs transition-transform", !collapsed && "rotate-90"), children: "\u25B8" })
|
|
881
|
+
}
|
|
882
|
+
) : null,
|
|
883
|
+
/* @__PURE__ */ jsxs14("div", { className: "min-w-0", children: [
|
|
884
|
+
/* @__PURE__ */ jsx23("h2", { id: titleId, className: "text-sm font-semibold tracking-tight text-foreground", children: feature.title }),
|
|
885
|
+
/* @__PURE__ */ jsx23("p", { className: "mt-0.5 truncate font-mono text-xs text-muted-foreground", children: feature.sourceFile })
|
|
886
|
+
] })
|
|
887
|
+
] }),
|
|
888
|
+
/* @__PURE__ */ jsxs14(
|
|
889
|
+
"div",
|
|
890
|
+
{
|
|
891
|
+
role: "img",
|
|
892
|
+
className: "flex shrink-0 items-center gap-2.5 font-mono text-xs font-medium",
|
|
893
|
+
"aria-label": `${s.passed} passed, ${s.failed} failed, ${skipped} skipped`,
|
|
894
|
+
children: [
|
|
895
|
+
/* @__PURE__ */ jsxs14("span", { "aria-hidden": true, className: "text-pass", children: [
|
|
896
|
+
"\u2713",
|
|
897
|
+
s.passed
|
|
898
|
+
] }),
|
|
899
|
+
/* @__PURE__ */ jsxs14("span", { "aria-hidden": true, className: "text-fail", children: [
|
|
900
|
+
"\u2717",
|
|
901
|
+
s.failed
|
|
902
|
+
] }),
|
|
903
|
+
/* @__PURE__ */ jsxs14("span", { "aria-hidden": true, className: "text-skip", children: [
|
|
904
|
+
"\u25CB",
|
|
905
|
+
skipped
|
|
906
|
+
] })
|
|
907
|
+
]
|
|
908
|
+
}
|
|
909
|
+
)
|
|
910
|
+
] }),
|
|
911
|
+
/* @__PURE__ */ jsx23("div", { id: bodyId, hidden: collapsed, className: "flex flex-col gap-2 p-3", children: /* @__PURE__ */ jsx23(ReportScenarioList, { feature }) })
|
|
365
912
|
]
|
|
366
913
|
}
|
|
367
914
|
);
|
|
368
915
|
}
|
|
369
916
|
|
|
370
917
|
// src/components/ReportFeatureList.tsx
|
|
371
|
-
import { Fragment as Fragment8, jsx as
|
|
918
|
+
import { Fragment as Fragment8, jsx as jsx24 } from "react/jsx-runtime";
|
|
372
919
|
function ReportFeatureList() {
|
|
373
920
|
const report = useReport();
|
|
374
|
-
return /* @__PURE__ */
|
|
921
|
+
return /* @__PURE__ */ jsx24(Fragment8, { children: report.features.map((feature) => /* @__PURE__ */ jsx24(ReportFeature, { feature }, feature.id)) });
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
// src/components/ui/empty.tsx
|
|
925
|
+
import { cva as cva2 } from "class-variance-authority";
|
|
926
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
927
|
+
function Empty({ className, ...props }) {
|
|
928
|
+
return /* @__PURE__ */ jsx25(
|
|
929
|
+
"div",
|
|
930
|
+
{
|
|
931
|
+
"data-slot": "empty",
|
|
932
|
+
className: cn(
|
|
933
|
+
"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12",
|
|
934
|
+
className
|
|
935
|
+
),
|
|
936
|
+
...props
|
|
937
|
+
}
|
|
938
|
+
);
|
|
939
|
+
}
|
|
940
|
+
function EmptyHeader({ className, ...props }) {
|
|
941
|
+
return /* @__PURE__ */ jsx25(
|
|
942
|
+
"div",
|
|
943
|
+
{
|
|
944
|
+
"data-slot": "empty-header",
|
|
945
|
+
className: cn(
|
|
946
|
+
"flex max-w-sm flex-col items-center gap-2 text-center",
|
|
947
|
+
className
|
|
948
|
+
),
|
|
949
|
+
...props
|
|
950
|
+
}
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
var emptyMediaVariants = cva2(
|
|
954
|
+
"mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
955
|
+
{
|
|
956
|
+
variants: {
|
|
957
|
+
variant: {
|
|
958
|
+
default: "bg-transparent",
|
|
959
|
+
icon: "flex size-10 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-6"
|
|
960
|
+
}
|
|
961
|
+
},
|
|
962
|
+
defaultVariants: {
|
|
963
|
+
variant: "default"
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
);
|
|
967
|
+
function EmptyTitle({ className, ...props }) {
|
|
968
|
+
return /* @__PURE__ */ jsx25(
|
|
969
|
+
"div",
|
|
970
|
+
{
|
|
971
|
+
"data-slot": "empty-title",
|
|
972
|
+
className: cn("text-lg font-medium tracking-tight", className),
|
|
973
|
+
...props
|
|
974
|
+
}
|
|
975
|
+
);
|
|
375
976
|
}
|
|
376
977
|
|
|
377
978
|
// src/components/ReportEmpty.tsx
|
|
378
|
-
import { jsx as
|
|
979
|
+
import { jsx as jsx26 } from "react/jsx-runtime";
|
|
379
980
|
function ReportEmpty({ message }) {
|
|
380
|
-
return /* @__PURE__ */
|
|
981
|
+
return /* @__PURE__ */ jsx26(Empty, { "aria-live": "polite", className: "border", children: /* @__PURE__ */ jsx26(EmptyHeader, { children: /* @__PURE__ */ jsx26(EmptyTitle, { children: message ?? "No scenarios in this report." }) }) });
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// src/components/ReportSummary.tsx
|
|
985
|
+
import { Fragment as Fragment9, jsx as jsx27, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
986
|
+
function ReportSummary({ className }) {
|
|
987
|
+
const report = useReport();
|
|
988
|
+
return /* @__PURE__ */ jsx27(
|
|
989
|
+
ReportSummaryView,
|
|
990
|
+
{
|
|
991
|
+
summary: report.summary,
|
|
992
|
+
...className !== void 0 && { className },
|
|
993
|
+
ariaLabel: "Run summary"
|
|
994
|
+
}
|
|
995
|
+
);
|
|
996
|
+
}
|
|
997
|
+
function ReportSummaryView({ summary, className, ariaLabel }) {
|
|
998
|
+
return /* @__PURE__ */ jsxs15("p", { className: cn("text-sm text-muted-foreground", className), "aria-label": ariaLabel, children: [
|
|
999
|
+
/* @__PURE__ */ jsxs15("span", { children: [
|
|
1000
|
+
/* @__PURE__ */ jsx27("strong", { className: "font-semibold text-foreground", children: summary.total }),
|
|
1001
|
+
" scenario",
|
|
1002
|
+
summary.total === 1 ? "" : "s"
|
|
1003
|
+
] }),
|
|
1004
|
+
" \xB7 ",
|
|
1005
|
+
/* @__PURE__ */ jsxs15("span", { "data-status": "passed", className: "text-pass", children: [
|
|
1006
|
+
summary.passed,
|
|
1007
|
+
" passed"
|
|
1008
|
+
] }),
|
|
1009
|
+
" \xB7 ",
|
|
1010
|
+
/* @__PURE__ */ jsxs15("span", { "data-status": "failed", className: "text-fail", children: [
|
|
1011
|
+
summary.failed,
|
|
1012
|
+
" failed"
|
|
1013
|
+
] }),
|
|
1014
|
+
summary.skipped > 0 ? /* @__PURE__ */ jsxs15(Fragment9, { children: [
|
|
1015
|
+
" \xB7 ",
|
|
1016
|
+
/* @__PURE__ */ jsxs15("span", { "data-status": "skipped", className: "text-skip", children: [
|
|
1017
|
+
summary.skipped,
|
|
1018
|
+
" skipped"
|
|
1019
|
+
] })
|
|
1020
|
+
] }) : null,
|
|
1021
|
+
summary.pending > 0 ? /* @__PURE__ */ jsxs15(Fragment9, { children: [
|
|
1022
|
+
" \xB7 ",
|
|
1023
|
+
/* @__PURE__ */ jsxs15("span", { "data-status": "pending", className: "text-pend", children: [
|
|
1024
|
+
summary.pending,
|
|
1025
|
+
" pending"
|
|
1026
|
+
] })
|
|
1027
|
+
] }) : null
|
|
1028
|
+
] });
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// src/components/ReportMeta.tsx
|
|
1032
|
+
import { formatDuration as formatDuration4 } from "executable-stories-core/utils/duration";
|
|
1033
|
+
import { jsx as jsx28, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1034
|
+
function ReportMeta() {
|
|
1035
|
+
const report = useReport();
|
|
1036
|
+
const items = [];
|
|
1037
|
+
if (report.startedAtMs) {
|
|
1038
|
+
items.push({ label: "Started", value: new Date(report.startedAtMs).toLocaleString() });
|
|
1039
|
+
}
|
|
1040
|
+
if (report.durationMs) {
|
|
1041
|
+
items.push({ label: "Duration", value: formatDuration4(report.durationMs) });
|
|
1042
|
+
}
|
|
1043
|
+
if (report.packageVersion) {
|
|
1044
|
+
items.push({ label: "Version", value: report.packageVersion });
|
|
1045
|
+
}
|
|
1046
|
+
if (report.gitSha) {
|
|
1047
|
+
items.push({ label: "Commit", value: report.gitSha.slice(0, 8) });
|
|
1048
|
+
}
|
|
1049
|
+
if (report.ci) {
|
|
1050
|
+
items.push({
|
|
1051
|
+
label: "CI",
|
|
1052
|
+
value: report.ci.url ? /* @__PURE__ */ jsxs16("a", { href: report.ci.url, target: "_blank", rel: "noreferrer noopener", className: "text-primary underline underline-offset-2", children: [
|
|
1053
|
+
report.ci.name,
|
|
1054
|
+
report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""
|
|
1055
|
+
] }) : `${report.ci.name}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : ""}`
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
if (items.length === 0) return null;
|
|
1059
|
+
return /* @__PURE__ */ jsx28("dl", { "aria-label": "Run metadata", className: "flex flex-wrap gap-x-6 gap-y-1 text-xs text-muted-foreground", children: items.map((item) => /* @__PURE__ */ jsxs16("div", { className: "flex gap-1.5", children: [
|
|
1060
|
+
/* @__PURE__ */ jsx28("dt", { className: "font-medium", children: item.label }),
|
|
1061
|
+
/* @__PURE__ */ jsx28("dd", { className: "font-mono text-foreground", children: item.value })
|
|
1062
|
+
] }, item.label)) });
|
|
381
1063
|
}
|
|
382
1064
|
|
|
383
1065
|
// src/components/ReportSchemaError.tsx
|
|
384
|
-
import { jsx as
|
|
1066
|
+
import { jsx as jsx29, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
385
1067
|
function ReportSchemaError({ error }) {
|
|
386
|
-
return /* @__PURE__ */
|
|
387
|
-
/* @__PURE__ */
|
|
388
|
-
/* @__PURE__ */
|
|
389
|
-
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */
|
|
1068
|
+
return /* @__PURE__ */ jsxs17("section", { className: "es-schema-error", role: "alert", "aria-live": "assertive", children: [
|
|
1069
|
+
/* @__PURE__ */ jsx29("p", { children: /* @__PURE__ */ jsx29("strong", { children: "Report could not be displayed." }) }),
|
|
1070
|
+
/* @__PURE__ */ jsx29("p", { children: error.message }),
|
|
1071
|
+
error.code === "SCHEMA_VERSION_MISMATCH" ? /* @__PURE__ */ jsxs17("p", { children: [
|
|
390
1072
|
"The report bundle is newer than this version of ",
|
|
391
|
-
/* @__PURE__ */
|
|
1073
|
+
/* @__PURE__ */ jsx29("code", { children: "executable-stories-react" }),
|
|
392
1074
|
". Upgrade the package, or regenerate the report with an older formatters CLI."
|
|
393
1075
|
] }) : null,
|
|
394
|
-
error.issues && error.issues.length > 0 ? /* @__PURE__ */
|
|
395
|
-
/* @__PURE__ */
|
|
1076
|
+
error.issues && error.issues.length > 0 ? /* @__PURE__ */ jsxs17("details", { children: [
|
|
1077
|
+
/* @__PURE__ */ jsxs17("summary", { children: [
|
|
396
1078
|
error.issues.length,
|
|
397
1079
|
" validation issue",
|
|
398
1080
|
error.issues.length === 1 ? "" : "s"
|
|
399
1081
|
] }),
|
|
400
|
-
/* @__PURE__ */
|
|
1082
|
+
/* @__PURE__ */ jsx29("pre", { children: error.issues.slice(0, 20).map((i) => `${i.path}: ${i.message}`).join("\n") })
|
|
401
1083
|
] }) : null
|
|
402
1084
|
] });
|
|
403
1085
|
}
|
|
404
1086
|
|
|
405
|
-
// src/components/
|
|
406
|
-
import { jsx as
|
|
407
|
-
function
|
|
408
|
-
return
|
|
1087
|
+
// src/components/ReportShell.tsx
|
|
1088
|
+
import { Fragment as Fragment10, jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1089
|
+
function ReportTitleBlock({ title }) {
|
|
1090
|
+
return /* @__PURE__ */ jsxs18(Fragment10, { children: [
|
|
1091
|
+
/* @__PURE__ */ jsx30("h1", { children: title ?? "Story Report" }),
|
|
1092
|
+
/* @__PURE__ */ jsx30(ReportSummary, {}),
|
|
1093
|
+
/* @__PURE__ */ jsx30(ReportMeta, {})
|
|
1094
|
+
] });
|
|
1095
|
+
}
|
|
1096
|
+
function ReportErrorShell({
|
|
1097
|
+
error,
|
|
1098
|
+
className,
|
|
1099
|
+
title,
|
|
1100
|
+
dataTheme
|
|
1101
|
+
}) {
|
|
1102
|
+
return /* @__PURE__ */ jsx30("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: /* @__PURE__ */ jsx30(ReportSchemaError, { error }) });
|
|
409
1103
|
}
|
|
1104
|
+
|
|
1105
|
+
// src/components/Report.tsx
|
|
1106
|
+
import { jsx as jsx31, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
410
1107
|
function Report(props) {
|
|
411
1108
|
const { report, customRenderers, renderers, className, title, dataTheme } = props;
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
1109
|
+
const result = unwrapReport(report);
|
|
1110
|
+
if (!result.ok) {
|
|
1111
|
+
return /* @__PURE__ */ jsx31(ReportErrorShell, { error: result.error, className, title, dataTheme });
|
|
1112
|
+
}
|
|
1113
|
+
const data = result.data;
|
|
1114
|
+
const hasContent = data.features.length > 0;
|
|
1115
|
+
return /* @__PURE__ */ jsx31(ReportRoot, { report: data, customRenderers, renderers, children: /* @__PURE__ */ jsxs19("main", { className: cn("es-report", className), "aria-label": title ?? "Test report", "data-theme": dataTheme, children: [
|
|
1116
|
+
/* @__PURE__ */ jsx31("header", { className: "es-report-header", children: /* @__PURE__ */ jsx31(ReportTitleBlock, { title }) }),
|
|
1117
|
+
hasContent ? /* @__PURE__ */ jsx31(ReportFeatureList, {}) : /* @__PURE__ */ jsx31(ReportEmpty, {})
|
|
1118
|
+
] }) });
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
// src/components/doc/MermaidView.tsx
|
|
1122
|
+
import { useEffect, useRef, useState as useState2 } from "react";
|
|
1123
|
+
import { jsx as jsx32, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1124
|
+
function prefersDark(el) {
|
|
1125
|
+
const themed = el?.closest("[data-theme]");
|
|
1126
|
+
if (themed?.dataset.theme === "dark") return true;
|
|
1127
|
+
if (themed?.dataset.theme === "light") return false;
|
|
1128
|
+
return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
|
|
1129
|
+
}
|
|
1130
|
+
function MermaidView({ entry, load }) {
|
|
1131
|
+
const ref = useRef(null);
|
|
1132
|
+
const [svg, setSvg] = useState2(null);
|
|
1133
|
+
useEffect(() => {
|
|
1134
|
+
let cancelled = false;
|
|
1135
|
+
const draw = async () => {
|
|
1136
|
+
try {
|
|
1137
|
+
const mermaid = await load();
|
|
1138
|
+
mermaid.initialize({
|
|
1139
|
+
startOnLoad: false,
|
|
1140
|
+
securityLevel: "strict",
|
|
1141
|
+
theme: prefersDark(ref.current) ? "dark" : "default"
|
|
1142
|
+
});
|
|
1143
|
+
const id = `es-mermaid-${Math.random().toString(36).slice(2)}`;
|
|
1144
|
+
const { svg: rendered } = await mermaid.render(id, entry.code);
|
|
1145
|
+
if (!cancelled) setSvg(rendered);
|
|
1146
|
+
} catch {
|
|
1147
|
+
if (!cancelled) setSvg(null);
|
|
1148
|
+
}
|
|
1149
|
+
};
|
|
1150
|
+
void draw();
|
|
1151
|
+
const themed = ref.current?.closest("[data-theme]");
|
|
1152
|
+
const observer = themed ? new MutationObserver(() => void draw()) : void 0;
|
|
1153
|
+
observer?.observe(themed, { attributes: true, attributeFilter: ["data-theme"] });
|
|
1154
|
+
return () => {
|
|
1155
|
+
cancelled = true;
|
|
1156
|
+
observer?.disconnect();
|
|
1157
|
+
};
|
|
1158
|
+
}, [entry.code, load]);
|
|
1159
|
+
if (svg) {
|
|
1160
|
+
return /* @__PURE__ */ jsxs20("figure", { ref, className: "my-3", children: [
|
|
1161
|
+
entry.title ? /* @__PURE__ */ jsx32("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
1162
|
+
/* @__PURE__ */ jsx32(
|
|
1163
|
+
"div",
|
|
416
1164
|
{
|
|
417
|
-
|
|
418
|
-
"aria-label": title ?? "
|
|
419
|
-
"
|
|
420
|
-
|
|
1165
|
+
role: "img",
|
|
1166
|
+
"aria-label": entry.title ?? "Mermaid diagram",
|
|
1167
|
+
className: "overflow-x-auto rounded-md border border-border bg-card p-3 [&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-full",
|
|
1168
|
+
dangerouslySetInnerHTML: { __html: svg }
|
|
421
1169
|
}
|
|
422
|
-
)
|
|
423
|
-
}
|
|
424
|
-
return /* @__PURE__ */ jsx22(
|
|
425
|
-
ReportView,
|
|
426
|
-
{
|
|
427
|
-
report: report.data,
|
|
428
|
-
customRenderers,
|
|
429
|
-
renderers,
|
|
430
|
-
className,
|
|
431
|
-
title,
|
|
432
|
-
dataTheme
|
|
433
|
-
}
|
|
434
|
-
);
|
|
1170
|
+
)
|
|
1171
|
+
] });
|
|
435
1172
|
}
|
|
436
|
-
return /* @__PURE__ */
|
|
437
|
-
|
|
1173
|
+
return /* @__PURE__ */ jsx32(MermaidSource, { entry, ref });
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
// src/components/doc/MermaidDiagram.tsx
|
|
1177
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
1178
|
+
var mermaidLoader;
|
|
1179
|
+
function loadMermaid() {
|
|
1180
|
+
mermaidLoader ??= import("mermaid").then((m) => m.default);
|
|
1181
|
+
return mermaidLoader;
|
|
1182
|
+
}
|
|
1183
|
+
function MermaidDiagram({ entry, load = loadMermaid }) {
|
|
1184
|
+
return /* @__PURE__ */ jsx33(MermaidView, { entry, load });
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
// src/components/ScenarioExplorer.tsx
|
|
1188
|
+
import { useState as useState3 } from "react";
|
|
1189
|
+
|
|
1190
|
+
// src/components/ui/command.tsx
|
|
1191
|
+
import "react";
|
|
1192
|
+
import { Command as CommandPrimitive } from "cmdk";
|
|
1193
|
+
import { SearchIcon } from "lucide-react";
|
|
1194
|
+
import { jsx as jsx34, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1195
|
+
function Command({
|
|
1196
|
+
className,
|
|
1197
|
+
...props
|
|
1198
|
+
}) {
|
|
1199
|
+
return /* @__PURE__ */ jsx34(
|
|
1200
|
+
CommandPrimitive,
|
|
438
1201
|
{
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
1202
|
+
"data-slot": "command",
|
|
1203
|
+
className: cn(
|
|
1204
|
+
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
|
1205
|
+
className
|
|
1206
|
+
),
|
|
1207
|
+
...props
|
|
445
1208
|
}
|
|
446
1209
|
);
|
|
447
1210
|
}
|
|
448
|
-
function
|
|
449
|
-
report,
|
|
450
|
-
customRenderers,
|
|
451
|
-
renderers,
|
|
1211
|
+
function CommandInput({
|
|
452
1212
|
className,
|
|
453
|
-
|
|
454
|
-
dataTheme
|
|
1213
|
+
...props
|
|
455
1214
|
}) {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
"main",
|
|
1215
|
+
return /* @__PURE__ */ jsxs21(
|
|
1216
|
+
"div",
|
|
459
1217
|
{
|
|
460
|
-
|
|
461
|
-
"
|
|
462
|
-
"data-theme": dataTheme,
|
|
1218
|
+
"data-slot": "command-input-wrapper",
|
|
1219
|
+
className: "flex h-9 items-center gap-2 border-b px-3",
|
|
463
1220
|
children: [
|
|
464
|
-
/* @__PURE__ */
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
1221
|
+
/* @__PURE__ */ jsx34(SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
|
|
1222
|
+
/* @__PURE__ */ jsx34(
|
|
1223
|
+
CommandPrimitive.Input,
|
|
1224
|
+
{
|
|
1225
|
+
"data-slot": "command-input",
|
|
1226
|
+
className: cn(
|
|
1227
|
+
"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
1228
|
+
className
|
|
1229
|
+
),
|
|
1230
|
+
...props
|
|
1231
|
+
}
|
|
1232
|
+
)
|
|
469
1233
|
]
|
|
470
1234
|
}
|
|
471
|
-
)
|
|
1235
|
+
);
|
|
1236
|
+
}
|
|
1237
|
+
function CommandList({
|
|
1238
|
+
className,
|
|
1239
|
+
...props
|
|
1240
|
+
}) {
|
|
1241
|
+
return /* @__PURE__ */ jsx34(
|
|
1242
|
+
CommandPrimitive.List,
|
|
1243
|
+
{
|
|
1244
|
+
"data-slot": "command-list",
|
|
1245
|
+
className: cn(
|
|
1246
|
+
"max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
|
|
1247
|
+
className
|
|
1248
|
+
),
|
|
1249
|
+
...props
|
|
1250
|
+
}
|
|
1251
|
+
);
|
|
1252
|
+
}
|
|
1253
|
+
function CommandEmpty({
|
|
1254
|
+
...props
|
|
1255
|
+
}) {
|
|
1256
|
+
return /* @__PURE__ */ jsx34(
|
|
1257
|
+
CommandPrimitive.Empty,
|
|
1258
|
+
{
|
|
1259
|
+
"data-slot": "command-empty",
|
|
1260
|
+
className: "py-6 text-center text-sm",
|
|
1261
|
+
...props
|
|
1262
|
+
}
|
|
1263
|
+
);
|
|
1264
|
+
}
|
|
1265
|
+
function CommandGroup({
|
|
1266
|
+
className,
|
|
1267
|
+
...props
|
|
1268
|
+
}) {
|
|
1269
|
+
return /* @__PURE__ */ jsx34(
|
|
1270
|
+
CommandPrimitive.Group,
|
|
1271
|
+
{
|
|
1272
|
+
"data-slot": "command-group",
|
|
1273
|
+
className: cn(
|
|
1274
|
+
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
|
1275
|
+
className
|
|
1276
|
+
),
|
|
1277
|
+
...props
|
|
1278
|
+
}
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
function CommandItem({
|
|
1282
|
+
className,
|
|
1283
|
+
...props
|
|
1284
|
+
}) {
|
|
1285
|
+
return /* @__PURE__ */ jsx34(
|
|
1286
|
+
CommandPrimitive.Item,
|
|
1287
|
+
{
|
|
1288
|
+
"data-slot": "command-item",
|
|
1289
|
+
className: cn(
|
|
1290
|
+
"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
1291
|
+
className
|
|
1292
|
+
),
|
|
1293
|
+
...props
|
|
1294
|
+
}
|
|
1295
|
+
);
|
|
472
1296
|
}
|
|
473
1297
|
|
|
474
|
-
// src/
|
|
475
|
-
|
|
476
|
-
var
|
|
1298
|
+
// src/components/ScenarioExplorer.tsx
|
|
1299
|
+
import { jsx as jsx35, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1300
|
+
var STATUS_FILTERS = [
|
|
1301
|
+
{ value: "all", label: "All" },
|
|
1302
|
+
{ value: "passed", label: "Passed" },
|
|
1303
|
+
{ value: "failed", label: "Failed" },
|
|
1304
|
+
{ value: "skipped", label: "Skipped" },
|
|
1305
|
+
{ value: "pending", label: "Pending" }
|
|
1306
|
+
];
|
|
1307
|
+
function ScenarioExplorer({ scenarios, summary }) {
|
|
1308
|
+
const [status, setStatus] = useState3("all");
|
|
1309
|
+
const visible = status === "all" ? scenarios : scenarios.filter((s) => s.status === status);
|
|
1310
|
+
return /* @__PURE__ */ jsxs22("div", { className: "font-sans text-foreground", children: [
|
|
1311
|
+
summary ? /* @__PURE__ */ jsxs22("p", { className: "mb-3 text-sm text-muted-foreground", children: [
|
|
1312
|
+
summary.total,
|
|
1313
|
+
" scenarios \xB7 ",
|
|
1314
|
+
/* @__PURE__ */ jsxs22("span", { className: "text-pass", children: [
|
|
1315
|
+
summary.passed,
|
|
1316
|
+
" passed"
|
|
1317
|
+
] }),
|
|
1318
|
+
" \xB7",
|
|
1319
|
+
" ",
|
|
1320
|
+
/* @__PURE__ */ jsxs22("span", { className: "text-fail", children: [
|
|
1321
|
+
summary.failed,
|
|
1322
|
+
" failed"
|
|
1323
|
+
] })
|
|
1324
|
+
] }) : null,
|
|
1325
|
+
/* @__PURE__ */ jsx35("div", { className: "mb-2 flex flex-wrap gap-1.5", role: "group", "aria-label": "Filter by status", children: STATUS_FILTERS.map((f) => /* @__PURE__ */ jsx35(
|
|
1326
|
+
"button",
|
|
1327
|
+
{
|
|
1328
|
+
type: "button",
|
|
1329
|
+
"aria-pressed": status === f.value,
|
|
1330
|
+
onClick: () => setStatus(f.value),
|
|
1331
|
+
className: cn(
|
|
1332
|
+
"rounded-full border px-2.5 py-1 text-xs font-medium transition-colors",
|
|
1333
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
1334
|
+
status === f.value ? "border-primary bg-primary text-primary-foreground" : "border-border bg-card text-muted-foreground hover:bg-accent hover:text-accent-foreground"
|
|
1335
|
+
),
|
|
1336
|
+
children: f.label
|
|
1337
|
+
},
|
|
1338
|
+
f.value
|
|
1339
|
+
)) }),
|
|
1340
|
+
/* @__PURE__ */ jsxs22(
|
|
1341
|
+
Command,
|
|
1342
|
+
{
|
|
1343
|
+
className: "rounded-lg border border-border bg-card",
|
|
1344
|
+
filter: (value, search) => value.toLowerCase().includes(search.toLowerCase()) ? 1 : 0,
|
|
1345
|
+
children: [
|
|
1346
|
+
/* @__PURE__ */ jsx35(CommandInput, { placeholder: "Search scenarios\u2026" }),
|
|
1347
|
+
/* @__PURE__ */ jsxs22(CommandList, { className: "max-h-none", children: [
|
|
1348
|
+
/* @__PURE__ */ jsx35(CommandEmpty, { children: "No scenarios match your filters." }),
|
|
1349
|
+
/* @__PURE__ */ jsx35(CommandGroup, { children: visible.map((s) => /* @__PURE__ */ jsx35(
|
|
1350
|
+
CommandItem,
|
|
1351
|
+
{
|
|
1352
|
+
value: `${s.title} ${s.feature} ${s.tags.join(" ")}`,
|
|
1353
|
+
asChild: true,
|
|
1354
|
+
className: "cursor-pointer",
|
|
1355
|
+
children: /* @__PURE__ */ jsxs22("a", { href: s.href, className: "flex items-center gap-3", children: [
|
|
1356
|
+
/* @__PURE__ */ jsx35(Badge, { variant: s.status, children: s.status }),
|
|
1357
|
+
/* @__PURE__ */ jsx35("span", { className: "min-w-0 flex-1 truncate font-medium", children: s.title }),
|
|
1358
|
+
s.tags.slice(0, 3).map((t) => /* @__PURE__ */ jsx35(Badge, { variant: "tag", className: "hidden sm:inline-flex", children: t }, t)),
|
|
1359
|
+
/* @__PURE__ */ jsx35("code", { className: "hidden font-mono text-xs text-muted-foreground md:inline", children: s.feature })
|
|
1360
|
+
] })
|
|
1361
|
+
},
|
|
1362
|
+
s.id
|
|
1363
|
+
)) })
|
|
1364
|
+
] })
|
|
1365
|
+
]
|
|
1366
|
+
}
|
|
1367
|
+
)
|
|
1368
|
+
] });
|
|
1369
|
+
}
|
|
477
1370
|
|
|
478
1371
|
// src/schema/story-report.schema.ts
|
|
479
1372
|
import { z } from "zod";
|
|
480
1373
|
|
|
481
|
-
// ../executable-stories-
|
|
1374
|
+
// ../executable-stories-core/schemas/story-report-v1.json
|
|
482
1375
|
var story_report_v1_default = {
|
|
483
1376
|
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
484
1377
|
$id: "https://executable-stories.dev/schemas/story-report-v1.schema.json",
|
|
@@ -541,25 +1434,61 @@ var story_report_v1_default = {
|
|
|
541
1434
|
},
|
|
542
1435
|
features: {
|
|
543
1436
|
type: "array",
|
|
544
|
-
items: {
|
|
1437
|
+
items: {
|
|
1438
|
+
$ref: "#/$defs/Feature"
|
|
1439
|
+
},
|
|
545
1440
|
description: "Features grouped by sourceFile, sorted by title."
|
|
546
1441
|
}
|
|
547
1442
|
},
|
|
548
|
-
required: [
|
|
1443
|
+
required: [
|
|
1444
|
+
"schemaVersion",
|
|
1445
|
+
"runId",
|
|
1446
|
+
"startedAtMs",
|
|
1447
|
+
"finishedAtMs",
|
|
1448
|
+
"durationMs",
|
|
1449
|
+
"projectRoot",
|
|
1450
|
+
"summary",
|
|
1451
|
+
"features"
|
|
1452
|
+
],
|
|
549
1453
|
additionalProperties: false
|
|
550
1454
|
},
|
|
551
1455
|
Summary: {
|
|
552
1456
|
type: "object",
|
|
553
1457
|
description: "Counts by status. Sums equal 'total'.",
|
|
554
1458
|
properties: {
|
|
555
|
-
total: {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
1459
|
+
total: {
|
|
1460
|
+
type: "integer",
|
|
1461
|
+
minimum: 0
|
|
1462
|
+
},
|
|
1463
|
+
passed: {
|
|
1464
|
+
type: "integer",
|
|
1465
|
+
minimum: 0
|
|
1466
|
+
},
|
|
1467
|
+
failed: {
|
|
1468
|
+
type: "integer",
|
|
1469
|
+
minimum: 0
|
|
1470
|
+
},
|
|
1471
|
+
skipped: {
|
|
1472
|
+
type: "integer",
|
|
1473
|
+
minimum: 0
|
|
1474
|
+
},
|
|
1475
|
+
pending: {
|
|
1476
|
+
type: "integer",
|
|
1477
|
+
minimum: 0
|
|
1478
|
+
},
|
|
1479
|
+
durationMs: {
|
|
1480
|
+
type: "number",
|
|
1481
|
+
minimum: 0
|
|
1482
|
+
}
|
|
561
1483
|
},
|
|
562
|
-
required: [
|
|
1484
|
+
required: [
|
|
1485
|
+
"total",
|
|
1486
|
+
"passed",
|
|
1487
|
+
"failed",
|
|
1488
|
+
"skipped",
|
|
1489
|
+
"pending",
|
|
1490
|
+
"durationMs"
|
|
1491
|
+
],
|
|
563
1492
|
additionalProperties: false
|
|
564
1493
|
},
|
|
565
1494
|
Feature: {
|
|
@@ -581,14 +1510,24 @@ var story_report_v1_default = {
|
|
|
581
1510
|
minLength: 1,
|
|
582
1511
|
description: "Source path, relative to projectRoot when possible."
|
|
583
1512
|
},
|
|
584
|
-
summary: {
|
|
1513
|
+
summary: {
|
|
1514
|
+
$ref: "#/$defs/Summary"
|
|
1515
|
+
},
|
|
585
1516
|
scenarios: {
|
|
586
1517
|
type: "array",
|
|
587
|
-
items: {
|
|
1518
|
+
items: {
|
|
1519
|
+
$ref: "#/$defs/Scenario"
|
|
1520
|
+
},
|
|
588
1521
|
description: "Scenarios in this feature, in declaration order."
|
|
589
1522
|
}
|
|
590
1523
|
},
|
|
591
|
-
required: [
|
|
1524
|
+
required: [
|
|
1525
|
+
"id",
|
|
1526
|
+
"title",
|
|
1527
|
+
"sourceFile",
|
|
1528
|
+
"summary",
|
|
1529
|
+
"scenarios"
|
|
1530
|
+
],
|
|
592
1531
|
additionalProperties: false
|
|
593
1532
|
},
|
|
594
1533
|
Scenario: {
|
|
@@ -600,346 +1539,777 @@ var story_report_v1_default = {
|
|
|
600
1539
|
minLength: 1,
|
|
601
1540
|
description: "Stable identifier: '<feature.id>--<slug-of-title>'. Suitable for use as a deep-link anchor."
|
|
602
1541
|
},
|
|
603
|
-
title: {
|
|
604
|
-
|
|
605
|
-
|
|
1542
|
+
title: {
|
|
1543
|
+
type: "string",
|
|
1544
|
+
minLength: 1
|
|
1545
|
+
},
|
|
1546
|
+
status: {
|
|
1547
|
+
$ref: "#/$defs/TestStatus"
|
|
1548
|
+
},
|
|
1549
|
+
durationMs: {
|
|
1550
|
+
type: "number",
|
|
1551
|
+
minimum: 0
|
|
1552
|
+
},
|
|
606
1553
|
tags: {
|
|
607
1554
|
type: "array",
|
|
608
|
-
items: {
|
|
1555
|
+
items: {
|
|
1556
|
+
type: "string"
|
|
1557
|
+
},
|
|
609
1558
|
description: "Normalized tags, deduplicated, lowercased."
|
|
610
1559
|
},
|
|
611
1560
|
tickets: {
|
|
612
1561
|
type: "array",
|
|
613
|
-
items: {
|
|
1562
|
+
items: {
|
|
1563
|
+
$ref: "#/$defs/Ticket"
|
|
1564
|
+
}
|
|
614
1565
|
},
|
|
615
1566
|
covers: {
|
|
616
1567
|
type: "array",
|
|
617
|
-
items: {
|
|
1568
|
+
items: {
|
|
1569
|
+
type: "string"
|
|
1570
|
+
},
|
|
618
1571
|
description: "Product-code paths/globs this scenario exercises."
|
|
619
1572
|
},
|
|
620
|
-
sourceLine: {
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
1573
|
+
sourceLine: {
|
|
1574
|
+
type: "integer",
|
|
1575
|
+
minimum: 1
|
|
1576
|
+
},
|
|
1577
|
+
errorMessage: {
|
|
1578
|
+
type: "string"
|
|
1579
|
+
},
|
|
1580
|
+
errorStack: {
|
|
1581
|
+
type: "string"
|
|
1582
|
+
},
|
|
1583
|
+
retry: {
|
|
1584
|
+
type: "integer",
|
|
1585
|
+
minimum: 0
|
|
1586
|
+
},
|
|
1587
|
+
retries: {
|
|
1588
|
+
type: "integer",
|
|
1589
|
+
minimum: 0
|
|
1590
|
+
},
|
|
625
1591
|
docEntries: {
|
|
626
1592
|
type: "array",
|
|
627
|
-
items: {
|
|
1593
|
+
items: {
|
|
1594
|
+
$ref: "#/$defs/DocEntry"
|
|
1595
|
+
},
|
|
628
1596
|
description: "Story-level doc entries (rendered before steps)."
|
|
629
1597
|
},
|
|
630
1598
|
steps: {
|
|
631
1599
|
type: "array",
|
|
632
|
-
items: {
|
|
1600
|
+
items: {
|
|
1601
|
+
$ref: "#/$defs/Step"
|
|
1602
|
+
}
|
|
633
1603
|
},
|
|
634
1604
|
attachments: {
|
|
635
1605
|
type: "array",
|
|
636
|
-
items: {
|
|
1606
|
+
items: {
|
|
1607
|
+
$ref: "#/$defs/Attachment"
|
|
1608
|
+
}
|
|
1609
|
+
},
|
|
1610
|
+
otelSpans: {
|
|
1611
|
+
type: "array",
|
|
1612
|
+
items: {
|
|
1613
|
+
$ref: "#/$defs/OtelSpan"
|
|
1614
|
+
}
|
|
637
1615
|
}
|
|
638
1616
|
},
|
|
639
|
-
required: [
|
|
1617
|
+
required: [
|
|
1618
|
+
"id",
|
|
1619
|
+
"title",
|
|
1620
|
+
"status",
|
|
1621
|
+
"durationMs",
|
|
1622
|
+
"tags",
|
|
1623
|
+
"retry",
|
|
1624
|
+
"retries",
|
|
1625
|
+
"docEntries",
|
|
1626
|
+
"steps",
|
|
1627
|
+
"attachments"
|
|
1628
|
+
],
|
|
640
1629
|
additionalProperties: false
|
|
641
1630
|
},
|
|
642
1631
|
Step: {
|
|
643
1632
|
type: "object",
|
|
644
1633
|
description: "A single BDD step.",
|
|
645
1634
|
properties: {
|
|
646
|
-
id: {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
1635
|
+
id: {
|
|
1636
|
+
type: "string",
|
|
1637
|
+
minLength: 1
|
|
1638
|
+
},
|
|
1639
|
+
index: {
|
|
1640
|
+
type: "integer",
|
|
1641
|
+
minimum: 0
|
|
1642
|
+
},
|
|
1643
|
+
keyword: {
|
|
1644
|
+
$ref: "#/$defs/StepKeyword"
|
|
1645
|
+
},
|
|
1646
|
+
text: {
|
|
1647
|
+
type: "string"
|
|
1648
|
+
},
|
|
1649
|
+
status: {
|
|
1650
|
+
$ref: "#/$defs/TestStatus"
|
|
1651
|
+
},
|
|
1652
|
+
durationMs: {
|
|
1653
|
+
type: "number",
|
|
1654
|
+
minimum: 0
|
|
1655
|
+
},
|
|
1656
|
+
errorMessage: {
|
|
1657
|
+
type: "string"
|
|
1658
|
+
},
|
|
1659
|
+
mode: {
|
|
1660
|
+
$ref: "#/$defs/StepMode"
|
|
1661
|
+
},
|
|
654
1662
|
docEntries: {
|
|
655
1663
|
type: "array",
|
|
656
|
-
items: {
|
|
1664
|
+
items: {
|
|
1665
|
+
$ref: "#/$defs/DocEntry"
|
|
1666
|
+
},
|
|
657
1667
|
description: "Doc entries attached to this step."
|
|
658
1668
|
}
|
|
659
1669
|
},
|
|
660
|
-
required: [
|
|
1670
|
+
required: [
|
|
1671
|
+
"id",
|
|
1672
|
+
"index",
|
|
1673
|
+
"keyword",
|
|
1674
|
+
"text",
|
|
1675
|
+
"status",
|
|
1676
|
+
"durationMs",
|
|
1677
|
+
"docEntries"
|
|
1678
|
+
],
|
|
661
1679
|
additionalProperties: false
|
|
662
1680
|
},
|
|
663
1681
|
StepKeyword: {
|
|
664
1682
|
type: "string",
|
|
665
|
-
enum: [
|
|
1683
|
+
enum: [
|
|
1684
|
+
"Given",
|
|
1685
|
+
"When",
|
|
1686
|
+
"Then",
|
|
1687
|
+
"And",
|
|
1688
|
+
"But"
|
|
1689
|
+
]
|
|
666
1690
|
},
|
|
667
1691
|
StepMode: {
|
|
668
1692
|
type: "string",
|
|
669
|
-
enum: [
|
|
1693
|
+
enum: [
|
|
1694
|
+
"normal",
|
|
1695
|
+
"skip",
|
|
1696
|
+
"only",
|
|
1697
|
+
"todo",
|
|
1698
|
+
"fails",
|
|
1699
|
+
"concurrent"
|
|
1700
|
+
]
|
|
670
1701
|
},
|
|
671
1702
|
TestStatus: {
|
|
672
1703
|
type: "string",
|
|
673
|
-
enum: [
|
|
1704
|
+
enum: [
|
|
1705
|
+
"passed",
|
|
1706
|
+
"failed",
|
|
1707
|
+
"skipped",
|
|
1708
|
+
"pending"
|
|
1709
|
+
]
|
|
674
1710
|
},
|
|
675
1711
|
Ticket: {
|
|
676
1712
|
type: "object",
|
|
677
1713
|
properties: {
|
|
678
|
-
id: {
|
|
679
|
-
|
|
1714
|
+
id: {
|
|
1715
|
+
type: "string",
|
|
1716
|
+
minLength: 1
|
|
1717
|
+
},
|
|
1718
|
+
url: {
|
|
1719
|
+
type: "string"
|
|
1720
|
+
}
|
|
680
1721
|
},
|
|
681
|
-
required: [
|
|
1722
|
+
required: [
|
|
1723
|
+
"id"
|
|
1724
|
+
],
|
|
682
1725
|
additionalProperties: false
|
|
683
1726
|
},
|
|
684
1727
|
Attachment: {
|
|
685
1728
|
type: "object",
|
|
686
1729
|
properties: {
|
|
687
|
-
name: {
|
|
688
|
-
|
|
689
|
-
|
|
1730
|
+
name: {
|
|
1731
|
+
type: "string"
|
|
1732
|
+
},
|
|
1733
|
+
mediaType: {
|
|
1734
|
+
type: "string",
|
|
1735
|
+
minLength: 1
|
|
1736
|
+
},
|
|
1737
|
+
body: {
|
|
1738
|
+
type: "string"
|
|
1739
|
+
},
|
|
690
1740
|
contentEncoding: {
|
|
691
1741
|
type: "string",
|
|
692
|
-
enum: [
|
|
1742
|
+
enum: [
|
|
1743
|
+
"BASE64",
|
|
1744
|
+
"IDENTITY"
|
|
1745
|
+
]
|
|
693
1746
|
}
|
|
694
1747
|
},
|
|
695
|
-
required: [
|
|
1748
|
+
required: [
|
|
1749
|
+
"name",
|
|
1750
|
+
"mediaType",
|
|
1751
|
+
"body",
|
|
1752
|
+
"contentEncoding"
|
|
1753
|
+
],
|
|
696
1754
|
additionalProperties: false
|
|
697
1755
|
},
|
|
698
1756
|
CIInfo: {
|
|
699
1757
|
type: "object",
|
|
700
1758
|
properties: {
|
|
701
|
-
name: {
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
1759
|
+
name: {
|
|
1760
|
+
type: "string"
|
|
1761
|
+
},
|
|
1762
|
+
url: {
|
|
1763
|
+
type: "string"
|
|
1764
|
+
},
|
|
1765
|
+
buildNumber: {
|
|
1766
|
+
type: "string"
|
|
1767
|
+
},
|
|
1768
|
+
branch: {
|
|
1769
|
+
type: "string"
|
|
1770
|
+
},
|
|
1771
|
+
commitSha: {
|
|
1772
|
+
type: "string"
|
|
1773
|
+
},
|
|
1774
|
+
prNumber: {
|
|
1775
|
+
type: "string"
|
|
1776
|
+
}
|
|
707
1777
|
},
|
|
708
|
-
required: [
|
|
1778
|
+
required: [
|
|
1779
|
+
"name"
|
|
1780
|
+
],
|
|
709
1781
|
additionalProperties: false
|
|
710
1782
|
},
|
|
711
1783
|
CoverageSummary: {
|
|
712
1784
|
type: "object",
|
|
713
1785
|
properties: {
|
|
714
|
-
linesPct: {
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
1786
|
+
linesPct: {
|
|
1787
|
+
type: "number",
|
|
1788
|
+
minimum: 0,
|
|
1789
|
+
maximum: 100
|
|
1790
|
+
},
|
|
1791
|
+
branchesPct: {
|
|
1792
|
+
type: "number",
|
|
1793
|
+
minimum: 0,
|
|
1794
|
+
maximum: 100
|
|
1795
|
+
},
|
|
1796
|
+
functionsPct: {
|
|
1797
|
+
type: "number",
|
|
1798
|
+
minimum: 0,
|
|
1799
|
+
maximum: 100
|
|
1800
|
+
},
|
|
1801
|
+
statementsPct: {
|
|
1802
|
+
type: "number",
|
|
1803
|
+
minimum: 0,
|
|
1804
|
+
maximum: 100
|
|
1805
|
+
}
|
|
718
1806
|
},
|
|
719
1807
|
additionalProperties: false
|
|
720
1808
|
},
|
|
721
1809
|
DocPhase: {
|
|
722
1810
|
type: "string",
|
|
723
|
-
enum: [
|
|
1811
|
+
enum: [
|
|
1812
|
+
"static",
|
|
1813
|
+
"runtime"
|
|
1814
|
+
]
|
|
724
1815
|
},
|
|
725
1816
|
DocEntry: {
|
|
726
1817
|
oneOf: [
|
|
727
|
-
{
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
{
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
{
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
{
|
|
737
|
-
|
|
738
|
-
|
|
1818
|
+
{
|
|
1819
|
+
$ref: "#/$defs/DocNote"
|
|
1820
|
+
},
|
|
1821
|
+
{
|
|
1822
|
+
$ref: "#/$defs/DocTag"
|
|
1823
|
+
},
|
|
1824
|
+
{
|
|
1825
|
+
$ref: "#/$defs/DocKv"
|
|
1826
|
+
},
|
|
1827
|
+
{
|
|
1828
|
+
$ref: "#/$defs/DocCode"
|
|
1829
|
+
},
|
|
1830
|
+
{
|
|
1831
|
+
$ref: "#/$defs/DocTable"
|
|
1832
|
+
},
|
|
1833
|
+
{
|
|
1834
|
+
$ref: "#/$defs/DocLink"
|
|
1835
|
+
},
|
|
1836
|
+
{
|
|
1837
|
+
$ref: "#/$defs/DocSection"
|
|
1838
|
+
},
|
|
1839
|
+
{
|
|
1840
|
+
$ref: "#/$defs/DocMermaid"
|
|
1841
|
+
},
|
|
1842
|
+
{
|
|
1843
|
+
$ref: "#/$defs/DocScreenshot"
|
|
1844
|
+
},
|
|
1845
|
+
{
|
|
1846
|
+
$ref: "#/$defs/DocVideo"
|
|
1847
|
+
},
|
|
1848
|
+
{
|
|
1849
|
+
$ref: "#/$defs/DocHtml"
|
|
1850
|
+
},
|
|
1851
|
+
{
|
|
1852
|
+
$ref: "#/$defs/DocCustom"
|
|
1853
|
+
}
|
|
739
1854
|
]
|
|
740
1855
|
},
|
|
741
1856
|
DocNote: {
|
|
742
1857
|
type: "object",
|
|
743
1858
|
properties: {
|
|
744
|
-
kind: {
|
|
745
|
-
|
|
746
|
-
|
|
1859
|
+
kind: {
|
|
1860
|
+
const: "note"
|
|
1861
|
+
},
|
|
1862
|
+
text: {
|
|
1863
|
+
type: "string"
|
|
1864
|
+
},
|
|
1865
|
+
phase: {
|
|
1866
|
+
$ref: "#/$defs/DocPhase"
|
|
1867
|
+
},
|
|
747
1868
|
children: {
|
|
748
1869
|
type: "array",
|
|
749
|
-
items: {
|
|
1870
|
+
items: {
|
|
1871
|
+
$ref: "#/$defs/DocEntry"
|
|
1872
|
+
}
|
|
750
1873
|
}
|
|
751
1874
|
},
|
|
752
|
-
required: [
|
|
1875
|
+
required: [
|
|
1876
|
+
"kind",
|
|
1877
|
+
"text",
|
|
1878
|
+
"phase"
|
|
1879
|
+
],
|
|
753
1880
|
additionalProperties: false
|
|
754
1881
|
},
|
|
755
1882
|
DocTag: {
|
|
756
1883
|
type: "object",
|
|
757
1884
|
properties: {
|
|
758
|
-
kind: {
|
|
759
|
-
|
|
760
|
-
|
|
1885
|
+
kind: {
|
|
1886
|
+
const: "tag"
|
|
1887
|
+
},
|
|
1888
|
+
names: {
|
|
1889
|
+
type: "array",
|
|
1890
|
+
items: {
|
|
1891
|
+
type: "string"
|
|
1892
|
+
}
|
|
1893
|
+
},
|
|
1894
|
+
phase: {
|
|
1895
|
+
$ref: "#/$defs/DocPhase"
|
|
1896
|
+
},
|
|
761
1897
|
children: {
|
|
762
1898
|
type: "array",
|
|
763
|
-
items: {
|
|
1899
|
+
items: {
|
|
1900
|
+
$ref: "#/$defs/DocEntry"
|
|
1901
|
+
}
|
|
764
1902
|
}
|
|
765
1903
|
},
|
|
766
|
-
required: [
|
|
1904
|
+
required: [
|
|
1905
|
+
"kind",
|
|
1906
|
+
"names",
|
|
1907
|
+
"phase"
|
|
1908
|
+
],
|
|
767
1909
|
additionalProperties: false
|
|
768
1910
|
},
|
|
769
1911
|
DocKv: {
|
|
770
1912
|
type: "object",
|
|
771
1913
|
properties: {
|
|
772
|
-
kind: {
|
|
773
|
-
|
|
1914
|
+
kind: {
|
|
1915
|
+
const: "kv"
|
|
1916
|
+
},
|
|
1917
|
+
label: {
|
|
1918
|
+
type: "string"
|
|
1919
|
+
},
|
|
774
1920
|
value: {},
|
|
775
|
-
phase: {
|
|
1921
|
+
phase: {
|
|
1922
|
+
$ref: "#/$defs/DocPhase"
|
|
1923
|
+
},
|
|
776
1924
|
children: {
|
|
777
1925
|
type: "array",
|
|
778
|
-
items: {
|
|
1926
|
+
items: {
|
|
1927
|
+
$ref: "#/$defs/DocEntry"
|
|
1928
|
+
}
|
|
779
1929
|
}
|
|
780
1930
|
},
|
|
781
|
-
required: [
|
|
1931
|
+
required: [
|
|
1932
|
+
"kind",
|
|
1933
|
+
"label",
|
|
1934
|
+
"value",
|
|
1935
|
+
"phase"
|
|
1936
|
+
],
|
|
782
1937
|
additionalProperties: false
|
|
783
1938
|
},
|
|
784
1939
|
DocCode: {
|
|
785
1940
|
type: "object",
|
|
786
1941
|
properties: {
|
|
787
|
-
kind: {
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
1942
|
+
kind: {
|
|
1943
|
+
const: "code"
|
|
1944
|
+
},
|
|
1945
|
+
label: {
|
|
1946
|
+
type: "string"
|
|
1947
|
+
},
|
|
1948
|
+
content: {
|
|
1949
|
+
type: "string"
|
|
1950
|
+
},
|
|
1951
|
+
lang: {
|
|
1952
|
+
type: "string"
|
|
1953
|
+
},
|
|
1954
|
+
phase: {
|
|
1955
|
+
$ref: "#/$defs/DocPhase"
|
|
1956
|
+
},
|
|
792
1957
|
children: {
|
|
793
1958
|
type: "array",
|
|
794
|
-
items: {
|
|
1959
|
+
items: {
|
|
1960
|
+
$ref: "#/$defs/DocEntry"
|
|
1961
|
+
}
|
|
795
1962
|
}
|
|
796
1963
|
},
|
|
797
|
-
required: [
|
|
1964
|
+
required: [
|
|
1965
|
+
"kind",
|
|
1966
|
+
"label",
|
|
1967
|
+
"content",
|
|
1968
|
+
"phase"
|
|
1969
|
+
],
|
|
798
1970
|
additionalProperties: false
|
|
799
1971
|
},
|
|
800
1972
|
DocTable: {
|
|
801
1973
|
type: "object",
|
|
802
1974
|
properties: {
|
|
803
|
-
kind: {
|
|
804
|
-
|
|
805
|
-
|
|
1975
|
+
kind: {
|
|
1976
|
+
const: "table"
|
|
1977
|
+
},
|
|
1978
|
+
label: {
|
|
1979
|
+
type: "string"
|
|
1980
|
+
},
|
|
1981
|
+
columns: {
|
|
1982
|
+
type: "array",
|
|
1983
|
+
items: {
|
|
1984
|
+
type: "string"
|
|
1985
|
+
}
|
|
1986
|
+
},
|
|
806
1987
|
rows: {
|
|
807
1988
|
type: "array",
|
|
808
1989
|
items: {
|
|
809
1990
|
type: "array",
|
|
810
|
-
items: {
|
|
1991
|
+
items: {
|
|
1992
|
+
type: "string"
|
|
1993
|
+
}
|
|
811
1994
|
}
|
|
812
1995
|
},
|
|
813
|
-
phase: {
|
|
1996
|
+
phase: {
|
|
1997
|
+
$ref: "#/$defs/DocPhase"
|
|
1998
|
+
},
|
|
814
1999
|
children: {
|
|
815
2000
|
type: "array",
|
|
816
|
-
items: {
|
|
2001
|
+
items: {
|
|
2002
|
+
$ref: "#/$defs/DocEntry"
|
|
2003
|
+
}
|
|
817
2004
|
}
|
|
818
2005
|
},
|
|
819
|
-
required: [
|
|
2006
|
+
required: [
|
|
2007
|
+
"kind",
|
|
2008
|
+
"label",
|
|
2009
|
+
"columns",
|
|
2010
|
+
"rows",
|
|
2011
|
+
"phase"
|
|
2012
|
+
],
|
|
820
2013
|
additionalProperties: false
|
|
821
2014
|
},
|
|
822
2015
|
DocLink: {
|
|
823
2016
|
type: "object",
|
|
824
2017
|
properties: {
|
|
825
|
-
kind: {
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
2018
|
+
kind: {
|
|
2019
|
+
const: "link"
|
|
2020
|
+
},
|
|
2021
|
+
label: {
|
|
2022
|
+
type: "string"
|
|
2023
|
+
},
|
|
2024
|
+
url: {
|
|
2025
|
+
type: "string"
|
|
2026
|
+
},
|
|
2027
|
+
phase: {
|
|
2028
|
+
$ref: "#/$defs/DocPhase"
|
|
2029
|
+
},
|
|
829
2030
|
children: {
|
|
830
2031
|
type: "array",
|
|
831
|
-
items: {
|
|
2032
|
+
items: {
|
|
2033
|
+
$ref: "#/$defs/DocEntry"
|
|
2034
|
+
}
|
|
832
2035
|
}
|
|
833
2036
|
},
|
|
834
|
-
required: [
|
|
2037
|
+
required: [
|
|
2038
|
+
"kind",
|
|
2039
|
+
"label",
|
|
2040
|
+
"url",
|
|
2041
|
+
"phase"
|
|
2042
|
+
],
|
|
835
2043
|
additionalProperties: false
|
|
836
2044
|
},
|
|
837
2045
|
DocSection: {
|
|
838
2046
|
type: "object",
|
|
839
2047
|
properties: {
|
|
840
|
-
kind: {
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
2048
|
+
kind: {
|
|
2049
|
+
const: "section"
|
|
2050
|
+
},
|
|
2051
|
+
title: {
|
|
2052
|
+
type: "string"
|
|
2053
|
+
},
|
|
2054
|
+
markdown: {
|
|
2055
|
+
type: "string"
|
|
2056
|
+
},
|
|
2057
|
+
phase: {
|
|
2058
|
+
$ref: "#/$defs/DocPhase"
|
|
2059
|
+
},
|
|
844
2060
|
children: {
|
|
845
2061
|
type: "array",
|
|
846
|
-
items: {
|
|
2062
|
+
items: {
|
|
2063
|
+
$ref: "#/$defs/DocEntry"
|
|
2064
|
+
}
|
|
847
2065
|
}
|
|
848
2066
|
},
|
|
849
|
-
required: [
|
|
2067
|
+
required: [
|
|
2068
|
+
"kind",
|
|
2069
|
+
"title",
|
|
2070
|
+
"markdown",
|
|
2071
|
+
"phase"
|
|
2072
|
+
],
|
|
850
2073
|
additionalProperties: false
|
|
851
2074
|
},
|
|
852
2075
|
DocMermaid: {
|
|
853
2076
|
type: "object",
|
|
854
2077
|
properties: {
|
|
855
|
-
kind: {
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
2078
|
+
kind: {
|
|
2079
|
+
const: "mermaid"
|
|
2080
|
+
},
|
|
2081
|
+
code: {
|
|
2082
|
+
type: "string"
|
|
2083
|
+
},
|
|
2084
|
+
title: {
|
|
2085
|
+
type: "string"
|
|
2086
|
+
},
|
|
2087
|
+
phase: {
|
|
2088
|
+
$ref: "#/$defs/DocPhase"
|
|
2089
|
+
},
|
|
859
2090
|
children: {
|
|
860
2091
|
type: "array",
|
|
861
|
-
items: {
|
|
2092
|
+
items: {
|
|
2093
|
+
$ref: "#/$defs/DocEntry"
|
|
2094
|
+
}
|
|
862
2095
|
}
|
|
863
2096
|
},
|
|
864
|
-
required: [
|
|
2097
|
+
required: [
|
|
2098
|
+
"kind",
|
|
2099
|
+
"code",
|
|
2100
|
+
"phase"
|
|
2101
|
+
],
|
|
865
2102
|
additionalProperties: false
|
|
866
2103
|
},
|
|
867
2104
|
DocScreenshot: {
|
|
868
2105
|
type: "object",
|
|
869
2106
|
properties: {
|
|
870
|
-
kind: {
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
2107
|
+
kind: {
|
|
2108
|
+
const: "screenshot"
|
|
2109
|
+
},
|
|
2110
|
+
path: {
|
|
2111
|
+
type: "string"
|
|
2112
|
+
},
|
|
2113
|
+
alt: {
|
|
2114
|
+
type: "string"
|
|
2115
|
+
},
|
|
2116
|
+
phase: {
|
|
2117
|
+
$ref: "#/$defs/DocPhase"
|
|
2118
|
+
},
|
|
874
2119
|
children: {
|
|
875
2120
|
type: "array",
|
|
876
|
-
items: {
|
|
2121
|
+
items: {
|
|
2122
|
+
$ref: "#/$defs/DocEntry"
|
|
2123
|
+
}
|
|
877
2124
|
}
|
|
878
2125
|
},
|
|
879
|
-
required: [
|
|
2126
|
+
required: [
|
|
2127
|
+
"kind",
|
|
2128
|
+
"path",
|
|
2129
|
+
"phase"
|
|
2130
|
+
],
|
|
880
2131
|
additionalProperties: false
|
|
881
2132
|
},
|
|
882
2133
|
DocVideo: {
|
|
883
2134
|
type: "object",
|
|
884
2135
|
properties: {
|
|
885
|
-
kind: {
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
2136
|
+
kind: {
|
|
2137
|
+
const: "video"
|
|
2138
|
+
},
|
|
2139
|
+
path: {
|
|
2140
|
+
type: "string"
|
|
2141
|
+
},
|
|
2142
|
+
caption: {
|
|
2143
|
+
type: "string"
|
|
2144
|
+
},
|
|
2145
|
+
poster: {
|
|
2146
|
+
type: "string"
|
|
2147
|
+
},
|
|
2148
|
+
phase: {
|
|
2149
|
+
$ref: "#/$defs/DocPhase"
|
|
2150
|
+
},
|
|
890
2151
|
children: {
|
|
891
2152
|
type: "array",
|
|
892
|
-
items: {
|
|
2153
|
+
items: {
|
|
2154
|
+
$ref: "#/$defs/DocEntry"
|
|
2155
|
+
}
|
|
893
2156
|
}
|
|
894
2157
|
},
|
|
895
|
-
required: [
|
|
2158
|
+
required: [
|
|
2159
|
+
"kind",
|
|
2160
|
+
"path",
|
|
2161
|
+
"phase"
|
|
2162
|
+
],
|
|
896
2163
|
additionalProperties: false
|
|
897
2164
|
},
|
|
898
2165
|
DocHtml: {
|
|
899
2166
|
type: "object",
|
|
900
2167
|
properties: {
|
|
901
|
-
kind: {
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
2168
|
+
kind: {
|
|
2169
|
+
const: "html"
|
|
2170
|
+
},
|
|
2171
|
+
path: {
|
|
2172
|
+
type: "string"
|
|
2173
|
+
},
|
|
2174
|
+
url: {
|
|
2175
|
+
type: "string"
|
|
2176
|
+
},
|
|
2177
|
+
content: {
|
|
2178
|
+
type: "string"
|
|
2179
|
+
},
|
|
2180
|
+
title: {
|
|
2181
|
+
type: "string"
|
|
2182
|
+
},
|
|
2183
|
+
height: {
|
|
2184
|
+
oneOf: [
|
|
2185
|
+
{
|
|
2186
|
+
type: "number"
|
|
2187
|
+
},
|
|
2188
|
+
{
|
|
2189
|
+
type: "string"
|
|
2190
|
+
}
|
|
2191
|
+
]
|
|
2192
|
+
},
|
|
2193
|
+
phase: {
|
|
2194
|
+
$ref: "#/$defs/DocPhase"
|
|
2195
|
+
},
|
|
908
2196
|
children: {
|
|
909
2197
|
type: "array",
|
|
910
|
-
items: {
|
|
2198
|
+
items: {
|
|
2199
|
+
$ref: "#/$defs/DocEntry"
|
|
2200
|
+
}
|
|
911
2201
|
}
|
|
912
2202
|
},
|
|
913
|
-
required: [
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
{ required: ["url"] },
|
|
917
|
-
{ required: ["content"] }
|
|
2203
|
+
required: [
|
|
2204
|
+
"kind",
|
|
2205
|
+
"phase"
|
|
918
2206
|
],
|
|
919
|
-
additionalProperties: false
|
|
2207
|
+
additionalProperties: false,
|
|
2208
|
+
oneOf: [
|
|
2209
|
+
{
|
|
2210
|
+
required: [
|
|
2211
|
+
"path"
|
|
2212
|
+
]
|
|
2213
|
+
},
|
|
2214
|
+
{
|
|
2215
|
+
required: [
|
|
2216
|
+
"url"
|
|
2217
|
+
]
|
|
2218
|
+
},
|
|
2219
|
+
{
|
|
2220
|
+
required: [
|
|
2221
|
+
"content"
|
|
2222
|
+
]
|
|
2223
|
+
}
|
|
2224
|
+
]
|
|
920
2225
|
},
|
|
921
2226
|
DocCustom: {
|
|
922
2227
|
type: "object",
|
|
923
2228
|
properties: {
|
|
924
|
-
kind: {
|
|
925
|
-
|
|
2229
|
+
kind: {
|
|
2230
|
+
const: "custom"
|
|
2231
|
+
},
|
|
2232
|
+
type: {
|
|
2233
|
+
type: "string",
|
|
2234
|
+
minLength: 1
|
|
2235
|
+
},
|
|
926
2236
|
data: {},
|
|
927
|
-
phase: {
|
|
2237
|
+
phase: {
|
|
2238
|
+
$ref: "#/$defs/DocPhase"
|
|
2239
|
+
},
|
|
928
2240
|
children: {
|
|
929
2241
|
type: "array",
|
|
930
|
-
items: {
|
|
2242
|
+
items: {
|
|
2243
|
+
$ref: "#/$defs/DocEntry"
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
},
|
|
2247
|
+
required: [
|
|
2248
|
+
"kind",
|
|
2249
|
+
"type",
|
|
2250
|
+
"data",
|
|
2251
|
+
"phase"
|
|
2252
|
+
],
|
|
2253
|
+
additionalProperties: false
|
|
2254
|
+
},
|
|
2255
|
+
OtelSpan: {
|
|
2256
|
+
type: "object",
|
|
2257
|
+
required: [
|
|
2258
|
+
"spanId",
|
|
2259
|
+
"name",
|
|
2260
|
+
"status"
|
|
2261
|
+
],
|
|
2262
|
+
properties: {
|
|
2263
|
+
spanId: {
|
|
2264
|
+
type: "string"
|
|
2265
|
+
},
|
|
2266
|
+
parentSpanId: {
|
|
2267
|
+
type: "string"
|
|
2268
|
+
},
|
|
2269
|
+
name: {
|
|
2270
|
+
type: "string"
|
|
2271
|
+
},
|
|
2272
|
+
startTimeMs: {
|
|
2273
|
+
type: "number"
|
|
2274
|
+
},
|
|
2275
|
+
durationMs: {
|
|
2276
|
+
type: "number"
|
|
2277
|
+
},
|
|
2278
|
+
startTimeUnixNano: {
|
|
2279
|
+
type: "number"
|
|
2280
|
+
},
|
|
2281
|
+
endTimeUnixNano: {
|
|
2282
|
+
type: "number"
|
|
2283
|
+
},
|
|
2284
|
+
status: {
|
|
2285
|
+
enum: [
|
|
2286
|
+
"ok",
|
|
2287
|
+
"error",
|
|
2288
|
+
"unset"
|
|
2289
|
+
]
|
|
2290
|
+
},
|
|
2291
|
+
statusMessage: {
|
|
2292
|
+
type: "string"
|
|
2293
|
+
},
|
|
2294
|
+
attributes: {
|
|
2295
|
+
type: "object"
|
|
931
2296
|
}
|
|
932
2297
|
},
|
|
933
|
-
required: ["kind", "type", "data", "phase"],
|
|
934
2298
|
additionalProperties: false
|
|
935
2299
|
}
|
|
936
2300
|
}
|
|
937
2301
|
};
|
|
938
2302
|
|
|
2303
|
+
// src/schema/version.ts
|
|
2304
|
+
var STORY_REPORT_SCHEMA_MAJOR = 1;
|
|
2305
|
+
|
|
939
2306
|
// src/schema/story-report.schema.ts
|
|
940
|
-
var
|
|
2307
|
+
var schemaForZod = structuredClone(story_report_v1_default);
|
|
2308
|
+
if (schemaForZod.$defs?.DocHtml) {
|
|
2309
|
+
delete schemaForZod.$defs.DocHtml.oneOf;
|
|
2310
|
+
}
|
|
2311
|
+
var compiled = z.fromJSONSchema(schemaForZod);
|
|
941
2312
|
var storyReportSchema = compiled;
|
|
942
|
-
var STORY_REPORT_SCHEMA_MAJOR = 1;
|
|
943
2313
|
|
|
944
2314
|
// src/schema/parse.ts
|
|
945
2315
|
function parseStoryReport(input) {
|
|
@@ -977,6 +2347,7 @@ export {
|
|
|
977
2347
|
DocCode,
|
|
978
2348
|
DocCustom,
|
|
979
2349
|
DocEntry,
|
|
2350
|
+
DocHtml,
|
|
980
2351
|
DocKv,
|
|
981
2352
|
DocLink,
|
|
982
2353
|
DocMermaid,
|
|
@@ -985,11 +2356,16 @@ export {
|
|
|
985
2356
|
DocSection,
|
|
986
2357
|
DocTable,
|
|
987
2358
|
DocTag,
|
|
2359
|
+
DocVideo,
|
|
2360
|
+
MermaidDiagram,
|
|
2361
|
+
MermaidSource,
|
|
988
2362
|
Report,
|
|
2363
|
+
ReportAttachments,
|
|
989
2364
|
ReportDocEntries,
|
|
990
2365
|
ReportEmpty,
|
|
991
2366
|
ReportFeature,
|
|
992
2367
|
ReportFeatureList,
|
|
2368
|
+
ReportMeta,
|
|
993
2369
|
ReportRoot,
|
|
994
2370
|
ReportScenario,
|
|
995
2371
|
ReportScenarioList,
|
|
@@ -998,7 +2374,9 @@ export {
|
|
|
998
2374
|
ReportSteps,
|
|
999
2375
|
ReportSummary,
|
|
1000
2376
|
ReportSummaryView,
|
|
2377
|
+
ReportTrace,
|
|
1001
2378
|
STORY_REPORT_SCHEMA_MAJOR,
|
|
2379
|
+
ScenarioExplorer,
|
|
1002
2380
|
err,
|
|
1003
2381
|
ok,
|
|
1004
2382
|
parseStoryReport,
|