executable-stories-cypress 2.0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/reporter.ts","../src/store.ts"],"sourcesContent":["/**\n * Cypress/Mocha reporter for executable-stories.\n * Builds RawRun (formatters schema) from run results + stored story meta, then generates reports.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { StoryMeta } from \"executable-stories-formatters\";\n\nimport {\n ReportGenerator,\n canonicalizeRun,\n readGitSha,\n readPackageVersion,\n detectCI,\n type RawRun,\n type RawTestCase,\n type RawAttachment,\n type RawStepEvent,\n type RawStatus,\n type FormatterOptions,\n} from \"executable-stories-formatters\";\n\nimport { getMeta, getAttachments, getAllMeta, clearStore } from \"./store\";\n\n// Re-export types from formatters\nexport type {\n OutputFormat,\n OutputMode,\n ColocatedStyle,\n OutputRule,\n FormatterOptions,\n} from \"executable-stories-formatters\";\n\n// ============================================================================\n// Reporter Options\n// ============================================================================\n\nexport interface StoryReporterOptions extends FormatterOptions {\n /** If set, write raw run JSON (schemaVersion 1) to this path for CLI/binary */\n rawRunPath?: string;\n /** Spec file path (relative to projectRoot) for this run. If omitted, inferred from stored meta when possible. */\n specPath?: string;\n /** Project root. Defaults to process.cwd(). */\n projectRoot?: string;\n}\n\n// ============================================================================\n// Mocha Runner / Test types (minimal for reporter)\n// ============================================================================\n\ninterface MochaSuite {\n title: string;\n suites: MochaSuite[];\n tests: MochaTest[];\n parent?: MochaSuite;\n}\n\ninterface MochaTest {\n title: string;\n state?: string;\n duration?: number;\n err?: Error & { message?: string; stack?: string };\n parent?: MochaSuite;\n}\n\ninterface MochaRunner {\n suite: MochaSuite;\n startTime?: number;\n on?(event: string, callback: () => void): void;\n}\n\nfunction getTitlePath(test: MochaTest): string[] {\n const path: string[] = [];\n let current: MochaSuite | MochaTest | undefined = test;\n while (current) {\n const title = \"title\" in current ? current.title : \"\";\n if (title) path.unshift(title);\n current = \"parent\" in current ? current.parent : undefined;\n }\n return path;\n}\n\nfunction collectTests(suite: MochaSuite): MochaTest[] {\n const tests = [...suite.tests];\n for (const s of suite.suites) {\n tests.push(...collectTests(s));\n }\n return tests;\n}\n\nfunction mapCypressStateToRaw(state: string | undefined): RawStatus {\n switch (state) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"pending\":\n return \"skip\";\n default:\n return \"unknown\";\n }\n}\n\n// ============================================================================\n// Reporter Implementation\n// ============================================================================\n\nconst DEFAULT_OPTIONS: Partial<StoryReporterOptions> = {\n projectRoot: process.cwd(),\n};\n\n/**\n * Create a Mocha reporter function that Cypress can use (--reporter path/to/reporter).\n * Cypress passes (runner, reporterOptions) with reporterOptions as the second argument directly.\n * Also supports options.reporterOptions for wrapped usage.\n */\nfunction createReporter(\n runner: MochaRunner,\n options: StoryReporterOptions | { reporterOptions?: StoryReporterOptions } = {}\n) {\n const reporterOpts =\n \"reporterOptions\" in options && options.reporterOptions\n ? options.reporterOptions\n : (options as StoryReporterOptions);\n const opts: StoryReporterOptions = { ...DEFAULT_OPTIONS, ...reporterOpts };\n const projectRoot = opts.projectRoot ?? process.cwd();\n const specPath = opts.specPath ?? \"unknown\";\n const startTime = runner.startTime ?? Date.now();\n\n runner.suite && runner.on?.(\"end\", () => {\n const tests = collectTests(runner.suite);\n const rawTestCases: RawTestCase[] = [];\n\n // If specPath not provided, infer from first stored meta (all stored entries are for this spec in a single-spec run)\n const effectiveSpecPath =\n specPath !== \"unknown\"\n ? specPath\n : (() => {\n const all = getAllMeta();\n return all.length > 0 ? all[0].specRelative : \"unknown\";\n })();\n\n for (const test of tests) {\n const titlePath = getTitlePath(test);\n const meta = getMeta(effectiveSpecPath, titlePath);\n if (!meta) continue; // only document tests that used story.init()\n\n const status = mapCypressStateToRaw(test.state);\n\n // Map stored attachments to RawAttachment[]\n const storedAttachments = getAttachments(effectiveSpecPath, titlePath);\n const attachments: RawAttachment[] | undefined = storedAttachments?.map((a) => ({\n name: a.name,\n mediaType: a.mediaType,\n path: a.path,\n body: typeof a.body === 'string' ? a.body : a.body instanceof Buffer ? a.body.toString('base64') : undefined,\n encoding: a.encoding ?? (a.body instanceof Buffer ? 'BASE64' : undefined),\n charset: a.charset,\n fileName: a.fileName,\n stepIndex: a.stepIndex,\n stepId: a.stepId,\n }));\n\n // Extract step events (timing)\n const stepEvents: RawStepEvent[] = meta.steps\n .filter((s: { durationMs?: number }) => s.durationMs !== undefined)\n .map((s: { durationMs?: number; text: string }, i: number) => ({\n index: i,\n title: s.text,\n durationMs: s.durationMs,\n }));\n\n rawTestCases.push({\n title: meta.scenario,\n titlePath: meta.suitePath ? [...meta.suitePath, meta.scenario] : [meta.scenario],\n story: meta,\n sourceFile: effectiveSpecPath,\n sourceLine: 1,\n status,\n durationMs: test.duration,\n error: test.err\n ? { message: test.err.message, stack: test.err.stack }\n : undefined,\n attachments: attachments && attachments.length > 0 ? attachments : undefined,\n stepEvents: stepEvents.length > 0 ? stepEvents : undefined,\n retry: 0,\n retries: 0,\n });\n }\n\n if (rawTestCases.length === 0) {\n clearStore();\n return;\n }\n\n const includeMetadata = opts.markdown?.includeMetadata ?? true;\n const rawRun: RawRun = {\n testCases: rawTestCases,\n startedAtMs: startTime,\n finishedAtMs: Date.now(),\n projectRoot,\n packageVersion: includeMetadata ? readPackageVersion(projectRoot) : undefined,\n gitSha: includeMetadata ? readGitSha(projectRoot) : undefined,\n ci: detectCI(),\n };\n\n const rawRunPath = opts.rawRunPath;\n if (rawRunPath) {\n const absolutePath = path.isAbsolute(rawRunPath)\n ? rawRunPath\n : path.join(projectRoot, rawRunPath);\n const dir = path.dirname(absolutePath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(absolutePath, JSON.stringify({ schemaVersion: 1, ...rawRun }, null, 2), \"utf8\");\n }\n\n const canonicalRun = canonicalizeRun(rawRun);\n const generator = new ReportGenerator(opts);\n generator.generate(canonicalRun).catch((err) => {\n console.error(\"Failed to generate reports:\", err);\n });\n\n clearStore();\n });\n}\n\n/**\n * Alternative: build RawRun from Cypress Module API results + stored meta.\n * Use this when not using the Mocha reporter (e.g. in after:run plugin).\n * Call recordMeta via plugin during the run, then call this with cypress.run() result.\n */\nexport interface CypressRunResultTest {\n title: string[];\n state?: string;\n displayError?: string;\n duration?: number;\n attempts?: Array<{\n state?: string;\n duration?: number;\n error?: { message?: string; stack?: string };\n }>;\n}\n\nexport interface CypressRunResultRun {\n spec?: { relative?: string; absolute?: string };\n tests?: CypressRunResultTest[];\n}\n\nexport interface CypressRunResult {\n runs?: CypressRunResultRun[];\n config?: { projectRoot?: string };\n}\n\nexport function buildRawRunFromCypressResult(\n result: CypressRunResult,\n options: StoryReporterOptions = {}\n): RawRun {\n const projectRoot = options.projectRoot ?? result.config?.projectRoot ?? process.cwd();\n const rawTestCases: RawTestCase[] = [];\n\n for (const run of result.runs ?? []) {\n const specRelative = run.spec?.relative ?? \"unknown\";\n for (const test of run.tests ?? []) {\n const titlePath = test.title ?? [];\n const meta = getMeta(specRelative, titlePath);\n if (!meta) continue;\n\n const lastAttempt = test.attempts?.length\n ? test.attempts[test.attempts.length - 1]\n : undefined;\n const state = lastAttempt?.state ?? test.state;\n const err = lastAttempt?.error ?? (test.displayError ? { message: test.displayError } : undefined);\n const duration = lastAttempt?.duration ?? test.duration;\n\n rawTestCases.push({\n title: meta.scenario,\n titlePath: meta.suitePath ? [...meta.suitePath, meta.scenario] : [meta.scenario],\n story: meta,\n sourceFile: specRelative,\n sourceLine: 1,\n status: mapCypressStateToRaw(state),\n durationMs: duration,\n error: err ? { message: err.message, stack: err.stack } : undefined,\n });\n }\n }\n\n const includeMetadata = options.markdown?.includeMetadata ?? true;\n return {\n testCases: rawTestCases,\n startedAtMs: undefined,\n finishedAtMs: Date.now(),\n projectRoot,\n packageVersion: includeMetadata ? readPackageVersion(projectRoot) : undefined,\n gitSha: includeMetadata ? readGitSha(projectRoot) : undefined,\n ci: detectCI(),\n };\n}\n\n/**\n * Generate reports from a RawRun (e.g. after buildRawRunFromCypressResult).\n */\nexport async function generateReportsFromRawRun(\n rawRun: RawRun,\n options: FormatterOptions\n): Promise<void> {\n if (rawRun.testCases.length === 0) return;\n const canonicalRun = canonicalizeRun(rawRun);\n const generator = new ReportGenerator(options);\n await generator.generate(canonicalRun);\n}\n\nexport default createReporter;\n","/**\n * Node-only store for story meta sent from the browser via cy.task.\n * Plugin writes; reporter reads. Keyed by spec + titlePath for merging with run results.\n */\n\nimport type { StoryMeta, ScopedAttachment, RecordMetaPayload } from \"./types\";\n\nexport interface StoredMeta {\n specRelative: string;\n titlePath: string[];\n meta: StoryMeta;\n attachments?: ScopedAttachment[];\n}\n\nfunction key(specRelative: string, titlePath: string[]): string {\n return `${specRelative}\\0${titlePath.join(\"\\0\")}`;\n}\n\nconst store = new Map<string, StoredMeta>();\n\nexport function recordMeta(payload: RecordMetaPayload): null {\n store.set(key(payload.specRelative, payload.titlePath), {\n specRelative: payload.specRelative,\n titlePath: payload.titlePath,\n meta: payload.meta,\n attachments: payload.attachments,\n });\n return null;\n}\n\nexport function getAttachments(specRelative: string, titlePath: string[]): ScopedAttachment[] | undefined {\n return store.get(key(specRelative, titlePath))?.attachments;\n}\n\nexport function getMeta(specRelative: string, titlePath: string[]): StoryMeta | undefined {\n return store.get(key(specRelative, titlePath))?.meta;\n}\n\nexport function getAllMeta(): StoredMeta[] {\n return Array.from(store.values());\n}\n\nexport function clearStore(): void {\n store.clear();\n}\n"],"mappings":"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","names":["path"]}
@@ -0,0 +1,313 @@
1
+ "use strict";
2
+
3
+ // src/story-api.ts
4
+ var activeContext = null;
5
+ var sourceOrderCounter = 0;
6
+ function getContext() {
7
+ if (!activeContext) {
8
+ throw new Error(
9
+ "story.init() must be called first. Use: it('name', () => { story.init(); ... });"
10
+ );
11
+ }
12
+ return activeContext;
13
+ }
14
+ function normalizeTickets(ticket) {
15
+ if (!ticket) return void 0;
16
+ return Array.isArray(ticket) ? ticket : [ticket];
17
+ }
18
+ function convertStoryDocsToEntries(docs) {
19
+ const entries = [];
20
+ if (docs.note) {
21
+ entries.push({ kind: "note", text: docs.note, phase: "runtime" });
22
+ }
23
+ if (docs.tag) {
24
+ const names = Array.isArray(docs.tag) ? docs.tag : [docs.tag];
25
+ entries.push({ kind: "tag", names, phase: "runtime" });
26
+ }
27
+ if (docs.kv) {
28
+ for (const [label, value] of Object.entries(docs.kv)) {
29
+ entries.push({ kind: "kv", label, value, phase: "runtime" });
30
+ }
31
+ }
32
+ if (docs.code) {
33
+ entries.push({
34
+ kind: "code",
35
+ label: docs.code.label,
36
+ content: docs.code.content,
37
+ lang: docs.code.lang,
38
+ phase: "runtime"
39
+ });
40
+ }
41
+ if (docs.json) {
42
+ entries.push({
43
+ kind: "code",
44
+ label: docs.json.label,
45
+ content: JSON.stringify(docs.json.value, null, 2),
46
+ lang: "json",
47
+ phase: "runtime"
48
+ });
49
+ }
50
+ if (docs.table) {
51
+ entries.push({
52
+ kind: "table",
53
+ label: docs.table.label,
54
+ columns: docs.table.columns,
55
+ rows: docs.table.rows,
56
+ phase: "runtime"
57
+ });
58
+ }
59
+ if (docs.link) {
60
+ entries.push({
61
+ kind: "link",
62
+ label: docs.link.label,
63
+ url: docs.link.url,
64
+ phase: "runtime"
65
+ });
66
+ }
67
+ if (docs.section) {
68
+ entries.push({
69
+ kind: "section",
70
+ title: docs.section.title,
71
+ markdown: docs.section.markdown,
72
+ phase: "runtime"
73
+ });
74
+ }
75
+ if (docs.mermaid) {
76
+ entries.push({
77
+ kind: "mermaid",
78
+ code: docs.mermaid.code,
79
+ title: docs.mermaid.title,
80
+ phase: "runtime"
81
+ });
82
+ }
83
+ if (docs.screenshot) {
84
+ entries.push({
85
+ kind: "screenshot",
86
+ path: docs.screenshot.path,
87
+ alt: docs.screenshot.alt,
88
+ phase: "runtime"
89
+ });
90
+ }
91
+ if (docs.custom) {
92
+ entries.push({
93
+ kind: "custom",
94
+ type: docs.custom.type,
95
+ data: docs.custom.data,
96
+ phase: "runtime"
97
+ });
98
+ }
99
+ return entries;
100
+ }
101
+ function attachDoc(entry) {
102
+ const ctx = getContext();
103
+ if (ctx.currentStep) {
104
+ ctx.currentStep.docs ??= [];
105
+ ctx.currentStep.docs.push(entry);
106
+ } else {
107
+ ctx.meta.docs ??= [];
108
+ ctx.meta.docs.push(entry);
109
+ }
110
+ }
111
+ function extractSuitePath(titlePath) {
112
+ if (titlePath.length <= 1) return void 0;
113
+ const suitePath = titlePath.slice(0, -1);
114
+ return suitePath.length > 0 ? suitePath : void 0;
115
+ }
116
+ function createStepMarker(keyword) {
117
+ return function stepMarker(text, docs) {
118
+ const ctx = getContext();
119
+ const step = {
120
+ id: `step-${ctx.stepCounter++}`,
121
+ keyword,
122
+ text,
123
+ docs: docs ? convertStoryDocsToEntries(docs) : []
124
+ };
125
+ ctx.meta.steps.push(step);
126
+ ctx.currentStep = step;
127
+ };
128
+ }
129
+ function init(options) {
130
+ const currentTest = Cypress.currentTest;
131
+ const spec = Cypress.spec;
132
+ if (!currentTest) {
133
+ throw new Error("story.init() must be called inside an it() block so Cypress.currentTest is available.");
134
+ }
135
+ const titlePath = currentTest.titlePath ?? [currentTest.title];
136
+ const scenario = currentTest.title;
137
+ const suitePath = extractSuitePath(titlePath);
138
+ const specRelative = spec?.relative ?? "unknown";
139
+ const meta = {
140
+ scenario,
141
+ steps: [],
142
+ suitePath,
143
+ tags: options?.tags,
144
+ tickets: normalizeTickets(options?.ticket),
145
+ meta: options?.meta,
146
+ sourceOrder: sourceOrderCounter++
147
+ };
148
+ activeContext = {
149
+ meta,
150
+ currentStep: null,
151
+ stepCounter: 0,
152
+ attachments: [],
153
+ activeTimers: /* @__PURE__ */ new Map(),
154
+ timerCounter: 0,
155
+ specRelative,
156
+ titlePath
157
+ };
158
+ }
159
+ function getAndClearMeta() {
160
+ if (!activeContext) return null;
161
+ const payload = {
162
+ specRelative: activeContext.specRelative,
163
+ titlePath: activeContext.titlePath,
164
+ meta: activeContext.meta,
165
+ attachments: activeContext.attachments.length > 0 ? activeContext.attachments : void 0
166
+ };
167
+ activeContext = null;
168
+ return payload;
169
+ }
170
+ function fn(keyword, text, body) {
171
+ const ctx = getContext();
172
+ const step = {
173
+ id: `step-${ctx.stepCounter++}`,
174
+ keyword,
175
+ text,
176
+ docs: [],
177
+ wrapped: true
178
+ };
179
+ ctx.meta.steps.push(step);
180
+ ctx.currentStep = step;
181
+ const start = performance.now();
182
+ try {
183
+ const result = body();
184
+ if (result instanceof Promise) {
185
+ return result.then(
186
+ (val) => {
187
+ step.durationMs = performance.now() - start;
188
+ return val;
189
+ },
190
+ (err) => {
191
+ step.durationMs = performance.now() - start;
192
+ throw err;
193
+ }
194
+ );
195
+ }
196
+ step.durationMs = performance.now() - start;
197
+ return result;
198
+ } catch (err) {
199
+ step.durationMs = performance.now() - start;
200
+ throw err;
201
+ }
202
+ }
203
+ function storyExpect(text, body) {
204
+ return fn("Then", text, body);
205
+ }
206
+ var story = {
207
+ init,
208
+ // BDD step markers
209
+ given: createStepMarker("Given"),
210
+ when: createStepMarker("When"),
211
+ then: createStepMarker("Then"),
212
+ and: createStepMarker("And"),
213
+ but: createStepMarker("But"),
214
+ // AAA pattern aliases
215
+ arrange: createStepMarker("Given"),
216
+ act: createStepMarker("When"),
217
+ assert: createStepMarker("Then"),
218
+ // Additional aliases
219
+ setup: createStepMarker("Given"),
220
+ context: createStepMarker("Given"),
221
+ execute: createStepMarker("When"),
222
+ action: createStepMarker("When"),
223
+ verify: createStepMarker("Then"),
224
+ // Standalone doc methods
225
+ note(text) {
226
+ attachDoc({ kind: "note", text, phase: "runtime" });
227
+ },
228
+ tag(name) {
229
+ const names = Array.isArray(name) ? name : [name];
230
+ attachDoc({ kind: "tag", names, phase: "runtime" });
231
+ },
232
+ kv(options) {
233
+ attachDoc({ kind: "kv", label: options.label, value: options.value, phase: "runtime" });
234
+ },
235
+ json(options) {
236
+ const content = JSON.stringify(options.value, null, 2);
237
+ attachDoc({ kind: "code", label: options.label, content, lang: "json", phase: "runtime" });
238
+ },
239
+ code(options) {
240
+ attachDoc({ kind: "code", label: options.label, content: options.content, lang: options.lang, phase: "runtime" });
241
+ },
242
+ table(options) {
243
+ attachDoc({ kind: "table", label: options.label, columns: options.columns, rows: options.rows, phase: "runtime" });
244
+ },
245
+ link(options) {
246
+ attachDoc({ kind: "link", label: options.label, url: options.url, phase: "runtime" });
247
+ },
248
+ section(options) {
249
+ attachDoc({ kind: "section", title: options.title, markdown: options.markdown, phase: "runtime" });
250
+ },
251
+ mermaid(options) {
252
+ attachDoc({ kind: "mermaid", code: options.code, title: options.title, phase: "runtime" });
253
+ },
254
+ screenshot(options) {
255
+ attachDoc({ kind: "screenshot", path: options.path, alt: options.alt, phase: "runtime" });
256
+ },
257
+ custom(options) {
258
+ attachDoc({ kind: "custom", type: options.type, data: options.data, phase: "runtime" });
259
+ },
260
+ // Attachments
261
+ attach(options) {
262
+ const ctx = getContext();
263
+ const stepIndex = ctx.currentStep ? ctx.meta.steps.indexOf(ctx.currentStep) : void 0;
264
+ ctx.attachments.push({
265
+ ...options,
266
+ stepIndex: stepIndex !== void 0 && stepIndex >= 0 ? stepIndex : void 0,
267
+ stepId: ctx.currentStep?.id
268
+ });
269
+ },
270
+ // Step timing
271
+ startTimer() {
272
+ const ctx = getContext();
273
+ const token = ctx.timerCounter++;
274
+ const stepIndex = ctx.currentStep ? ctx.meta.steps.indexOf(ctx.currentStep) : void 0;
275
+ ctx.activeTimers.set(token, {
276
+ start: performance.now(),
277
+ stepIndex: stepIndex !== void 0 && stepIndex >= 0 ? stepIndex : void 0,
278
+ stepId: ctx.currentStep?.id,
279
+ consumed: false
280
+ });
281
+ return token;
282
+ },
283
+ endTimer(token) {
284
+ const ctx = getContext();
285
+ const entry = ctx.activeTimers.get(token);
286
+ if (!entry || entry.consumed) return;
287
+ entry.consumed = true;
288
+ const durationMs = performance.now() - entry.start;
289
+ let step;
290
+ if (entry.stepId) {
291
+ step = ctx.meta.steps.find((s) => s.id === entry.stepId);
292
+ }
293
+ if (!step && entry.stepIndex !== void 0) {
294
+ step = ctx.meta.steps[entry.stepIndex];
295
+ }
296
+ if (step) {
297
+ step.durationMs = durationMs;
298
+ }
299
+ },
300
+ // Step wrappers
301
+ fn,
302
+ expect: storyExpect
303
+ };
304
+
305
+ // src/support.ts
306
+ var TASK_NAME = "executableStories:recordMeta";
307
+ afterEach(function() {
308
+ const payload = getAndClearMeta();
309
+ if (payload) {
310
+ cy.task(TASK_NAME, payload);
311
+ }
312
+ });
313
+ //# sourceMappingURL=support.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/story-api.ts","../src/support.ts"],"sourcesContent":["/**\n * Cypress story.* API for executable-stories.\n *\n * Uses native Cypress describe/it with opt-in documentation.\n * Story meta is flushed to Node via cy.task from the support file.\n *\n * @example\n * ```ts\n * import { story } from 'executable-stories-cypress';\n *\n * describe('Calculator', () => {\n * it('adds two numbers', () => {\n * story.init();\n *\n * story.given('two numbers 5 and 3');\n * const a = 5, b = 3;\n *\n * story.when('I add them together');\n * const result = a + b;\n *\n * story.then('the result is 8');\n * expect(result).toBe(8);\n * });\n * });\n * ```\n */\n\nimport type {\n StepKeyword,\n StoryMeta,\n StoryStep,\n DocEntry,\n StoryDocs,\n StoryOptions,\n AttachmentOptions,\n ScopedAttachment,\n RecordMetaPayload,\n KvOptions,\n JsonOptions,\n CodeOptions,\n TableOptions,\n LinkOptions,\n SectionOptions,\n MermaidOptions,\n ScreenshotOptions,\n CustomOptions,\n} from './types';\n\n// Re-export types for consumers\nexport type {\n StoryMeta,\n StoryStep,\n DocEntry,\n StepKeyword,\n StoryDocs,\n StoryOptions,\n AttachmentOptions,\n} from './types';\n\nexport type { RecordMetaPayload } from './types';\n\n// ============================================================================\n// Internal types\n// ============================================================================\n\ninterface TimerEntry {\n start: number;\n stepIndex?: number;\n stepId?: string;\n consumed: boolean;\n}\n\ninterface StoryContext {\n meta: StoryMeta;\n currentStep: StoryStep | null;\n stepCounter: number;\n attachments: ScopedAttachment[];\n activeTimers: Map<number, TimerEntry>;\n timerCounter: number;\n specRelative: string;\n titlePath: string[];\n}\n\n// ============================================================================\n// Cypress-specific context\n// ============================================================================\n\n/** Active story context - set by story.init() */\nlet activeContext: StoryContext | null = null;\n\n/** Counter to track source order of stories (increments on each story.init call) */\nlet sourceOrderCounter = 0;\n\n/**\n * Get the current story context. Throws if story.init() wasn't called.\n */\nfunction getContext(): StoryContext {\n if (!activeContext) {\n throw new Error(\n \"story.init() must be called first. Use: it('name', () => { story.init(); ... });\"\n );\n }\n return activeContext;\n}\n\n// ============================================================================\n// Helper functions (inlined from core)\n// ============================================================================\n\nfunction normalizeTickets(ticket: string | string[] | undefined): string[] | undefined {\n if (!ticket) return undefined;\n return Array.isArray(ticket) ? ticket : [ticket];\n}\n\nfunction convertStoryDocsToEntries(docs: StoryDocs): DocEntry[] {\n const entries: DocEntry[] = [];\n\n if (docs.note) {\n entries.push({ kind: 'note', text: docs.note, phase: 'runtime' });\n }\n if (docs.tag) {\n const names = Array.isArray(docs.tag) ? docs.tag : [docs.tag];\n entries.push({ kind: 'tag', names, phase: 'runtime' });\n }\n if (docs.kv) {\n for (const [label, value] of Object.entries(docs.kv)) {\n entries.push({ kind: 'kv', label, value, phase: 'runtime' });\n }\n }\n if (docs.code) {\n entries.push({\n kind: 'code',\n label: docs.code.label,\n content: docs.code.content,\n lang: docs.code.lang,\n phase: 'runtime',\n });\n }\n if (docs.json) {\n entries.push({\n kind: 'code',\n label: docs.json.label,\n content: JSON.stringify(docs.json.value, null, 2),\n lang: 'json',\n phase: 'runtime',\n });\n }\n if (docs.table) {\n entries.push({\n kind: 'table',\n label: docs.table.label,\n columns: docs.table.columns,\n rows: docs.table.rows,\n phase: 'runtime',\n });\n }\n if (docs.link) {\n entries.push({\n kind: 'link',\n label: docs.link.label,\n url: docs.link.url,\n phase: 'runtime',\n });\n }\n if (docs.section) {\n entries.push({\n kind: 'section',\n title: docs.section.title,\n markdown: docs.section.markdown,\n phase: 'runtime',\n });\n }\n if (docs.mermaid) {\n entries.push({\n kind: 'mermaid',\n code: docs.mermaid.code,\n title: docs.mermaid.title,\n phase: 'runtime',\n });\n }\n if (docs.screenshot) {\n entries.push({\n kind: 'screenshot',\n path: docs.screenshot.path,\n alt: docs.screenshot.alt,\n phase: 'runtime',\n });\n }\n if (docs.custom) {\n entries.push({\n kind: 'custom',\n type: docs.custom.type,\n data: docs.custom.data,\n phase: 'runtime',\n });\n }\n\n return entries;\n}\n\nfunction attachDoc(entry: DocEntry): void {\n const ctx = getContext();\n if (ctx.currentStep) {\n ctx.currentStep.docs ??= [];\n ctx.currentStep.docs.push(entry);\n } else {\n ctx.meta.docs ??= [];\n ctx.meta.docs.push(entry);\n }\n}\n\n/**\n * Extract suite path from Cypress.currentTest.titlePath (describe blocks only).\n * titlePath is [describe1, describe2, ..., testTitle] — we want everything except the last.\n */\nfunction extractSuitePath(titlePath: string[]): string[] | undefined {\n if (titlePath.length <= 1) return undefined;\n const suitePath = titlePath.slice(0, -1);\n return suitePath.length > 0 ? suitePath : undefined;\n}\n\n// ============================================================================\n// Step markers\n// ============================================================================\n\nfunction createStepMarker(keyword: StepKeyword) {\n return function stepMarker(text: string, docs?: StoryDocs): void {\n const ctx = getContext();\n const step: StoryStep = {\n id: `step-${ctx.stepCounter++}`,\n keyword,\n text,\n docs: docs ? convertStoryDocsToEntries(docs) : [],\n };\n ctx.meta.steps.push(step);\n ctx.currentStep = step;\n };\n}\n\n// ============================================================================\n// story.init() - Cypress-specific\n// ============================================================================\n\nfunction init(options?: StoryOptions): void {\n const currentTest = Cypress.currentTest;\n const spec = Cypress.spec;\n if (!currentTest) {\n throw new Error(\"story.init() must be called inside an it() block so Cypress.currentTest is available.\");\n }\n\n const titlePath = currentTest.titlePath ?? [currentTest.title];\n const scenario = currentTest.title;\n const suitePath = extractSuitePath(titlePath);\n const specRelative = spec?.relative ?? \"unknown\";\n\n const meta: StoryMeta = {\n scenario,\n steps: [],\n suitePath,\n tags: options?.tags,\n tickets: normalizeTickets(options?.ticket),\n meta: options?.meta,\n sourceOrder: sourceOrderCounter++,\n };\n\n activeContext = {\n meta,\n currentStep: null,\n stepCounter: 0,\n attachments: [],\n activeTimers: new Map(),\n timerCounter: 0,\n specRelative,\n titlePath,\n };\n}\n\n/**\n * Get the current story meta and clear the active context.\n * Called by the support file after each test to send meta to Node via cy.task.\n * Returns null if story.init() was never called for this test.\n */\nexport function getAndClearMeta(): RecordMetaPayload | null {\n if (!activeContext) return null;\n const payload: RecordMetaPayload = {\n specRelative: activeContext.specRelative,\n titlePath: activeContext.titlePath,\n meta: activeContext.meta,\n attachments: activeContext.attachments.length > 0 ? activeContext.attachments : undefined,\n };\n activeContext = null;\n return payload;\n}\n\n// ============================================================================\n// story.fn() and story.expect()\n// ============================================================================\n\n/**\n * Wrap a function as a step with timing and error capture.\n * Records the step with `wrapped: true` and `durationMs`.\n */\nfunction fn<T>(keyword: StepKeyword, text: string, body: () => T): T {\n const ctx = getContext();\n const step: StoryStep = {\n id: `step-${ctx.stepCounter++}`,\n keyword,\n text,\n docs: [],\n wrapped: true,\n };\n ctx.meta.steps.push(step);\n ctx.currentStep = step;\n\n const start = performance.now();\n try {\n const result = body();\n if (result instanceof Promise) {\n return result.then(\n (val) => {\n step.durationMs = performance.now() - start;\n return val;\n },\n (err) => {\n step.durationMs = performance.now() - start;\n throw err;\n },\n ) as T;\n }\n step.durationMs = performance.now() - start;\n return result;\n } catch (err) {\n step.durationMs = performance.now() - start;\n throw err;\n }\n}\n\n/**\n * Wrap an assertion as a Then step with timing and error capture.\n * Shorthand for `story.fn('Then', text, body)`.\n */\nfunction storyExpect<T>(text: string, body: () => T): T {\n return fn('Then', text, body);\n}\n\n// ============================================================================\n// Export story object\n// ============================================================================\n\nexport const story = {\n init,\n\n // BDD step markers\n given: createStepMarker('Given'),\n when: createStepMarker('When'),\n then: createStepMarker('Then'),\n and: createStepMarker('And'),\n but: createStepMarker('But'),\n\n // AAA pattern aliases\n arrange: createStepMarker('Given'),\n act: createStepMarker('When'),\n assert: createStepMarker('Then'),\n\n // Additional aliases\n setup: createStepMarker('Given'),\n context: createStepMarker('Given'),\n execute: createStepMarker('When'),\n action: createStepMarker('When'),\n verify: createStepMarker('Then'),\n\n // Standalone doc methods\n note(text: string): void {\n attachDoc({ kind: 'note', text, phase: 'runtime' });\n },\n\n tag(name: string | string[]): void {\n const names = Array.isArray(name) ? name : [name];\n attachDoc({ kind: 'tag', names, phase: 'runtime' });\n },\n\n kv(options: KvOptions): void {\n attachDoc({ kind: 'kv', label: options.label, value: options.value, phase: 'runtime' });\n },\n\n json(options: JsonOptions): void {\n const content = JSON.stringify(options.value, null, 2);\n attachDoc({ kind: 'code', label: options.label, content, lang: 'json', phase: 'runtime' });\n },\n\n code(options: CodeOptions): void {\n attachDoc({ kind: 'code', label: options.label, content: options.content, lang: options.lang, phase: 'runtime' });\n },\n\n table(options: TableOptions): void {\n attachDoc({ kind: 'table', label: options.label, columns: options.columns, rows: options.rows, phase: 'runtime' });\n },\n\n link(options: LinkOptions): void {\n attachDoc({ kind: 'link', label: options.label, url: options.url, phase: 'runtime' });\n },\n\n section(options: SectionOptions): void {\n attachDoc({ kind: 'section', title: options.title, markdown: options.markdown, phase: 'runtime' });\n },\n\n mermaid(options: MermaidOptions): void {\n attachDoc({ kind: 'mermaid', code: options.code, title: options.title, phase: 'runtime' });\n },\n\n screenshot(options: ScreenshotOptions): void {\n attachDoc({ kind: 'screenshot', path: options.path, alt: options.alt, phase: 'runtime' });\n },\n\n custom(options: CustomOptions): void {\n attachDoc({ kind: 'custom', type: options.type, data: options.data, phase: 'runtime' });\n },\n\n // Attachments\n attach(options: AttachmentOptions): void {\n const ctx = getContext();\n const stepIndex = ctx.currentStep\n ? ctx.meta.steps.indexOf(ctx.currentStep)\n : undefined;\n ctx.attachments.push({\n ...options,\n stepIndex: stepIndex !== undefined && stepIndex >= 0 ? stepIndex : undefined,\n stepId: ctx.currentStep?.id,\n });\n },\n\n // Step timing\n startTimer(): number {\n const ctx = getContext();\n const token = ctx.timerCounter++;\n const stepIndex = ctx.currentStep\n ? ctx.meta.steps.indexOf(ctx.currentStep)\n : undefined;\n ctx.activeTimers.set(token, {\n start: performance.now(),\n stepIndex: stepIndex !== undefined && stepIndex >= 0 ? stepIndex : undefined,\n stepId: ctx.currentStep?.id,\n consumed: false,\n });\n return token;\n },\n\n endTimer(token: number): void {\n const ctx = getContext();\n const entry = ctx.activeTimers.get(token);\n if (!entry || entry.consumed) return;\n\n entry.consumed = true;\n const durationMs = performance.now() - entry.start;\n\n let step: StoryStep | undefined;\n if (entry.stepId) {\n step = ctx.meta.steps.find((s) => s.id === entry.stepId);\n }\n if (!step && entry.stepIndex !== undefined) {\n step = ctx.meta.steps[entry.stepIndex];\n }\n\n if (step) {\n step.durationMs = durationMs;\n }\n },\n\n // Step wrappers\n fn,\n expect: storyExpect,\n};\n\nexport type Story = typeof story;\n","/**\n * Cypress support file for executable-stories.\n * Register this in cypress/support/e2e.ts (or support file) so story meta\n * is sent to Node after each test for the reporter to consume.\n *\n * @example\n * In cypress/support/e2e.ts:\n * import 'executable-stories-cypress/support';\n */\n\nimport { getAndClearMeta } from \"./story-api\";\n\nconst TASK_NAME = \"executableStories:recordMeta\";\n\nafterEach(function () {\n const payload = getAndClearMeta();\n if (payload) {\n cy.task(TASK_NAME, payload);\n }\n});\n"],"mappings":"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","names":[]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }