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