executable-stories-cypress 8.1.0 → 8.1.3
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 +55 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -13
- package/dist/index.d.ts +31 -13
- package/dist/index.js +55 -25
- package/dist/index.js.map +1 -1
- package/dist/support.cjs +55 -25
- package/dist/support.cjs.map +1 -1
- package/dist/support.js +55 -25
- package/dist/support.js.map +1 -1
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -38,7 +38,8 @@ function getContext() {
|
|
|
38
38
|
}
|
|
39
39
|
function normalizeTickets(ticket) {
|
|
40
40
|
if (!ticket) return void 0;
|
|
41
|
-
|
|
41
|
+
const arr = Array.isArray(ticket) ? ticket : [ticket];
|
|
42
|
+
return arr.map((t) => typeof t === "string" ? { id: t } : t);
|
|
42
43
|
}
|
|
43
44
|
function convertStoryDocsToEntries(docs) {
|
|
44
45
|
const entries = [];
|
|
@@ -123,8 +124,17 @@ function convertStoryDocsToEntries(docs) {
|
|
|
123
124
|
}
|
|
124
125
|
return entries;
|
|
125
126
|
}
|
|
126
|
-
function attachDoc(entry) {
|
|
127
|
+
function attachDoc(entry, children) {
|
|
127
128
|
const ctx = getContext();
|
|
129
|
+
if (children && children.length > 0) {
|
|
130
|
+
entry.children = children;
|
|
131
|
+
const childSet = new Set(children);
|
|
132
|
+
const filterDocs = (docs) => docs.filter((d) => !childSet.has(d));
|
|
133
|
+
ctx.meta.docs = filterDocs(ctx.meta.docs ?? []);
|
|
134
|
+
for (const step of ctx.meta.steps) {
|
|
135
|
+
if (step.docs) step.docs = filterDocs(step.docs);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
128
138
|
if (ctx.currentStep) {
|
|
129
139
|
ctx.currentStep.docs ??= [];
|
|
130
140
|
ctx.currentStep.docs.push(entry);
|
|
@@ -132,6 +142,7 @@ function attachDoc(entry) {
|
|
|
132
142
|
ctx.meta.docs ??= [];
|
|
133
143
|
ctx.meta.docs.push(entry);
|
|
134
144
|
}
|
|
145
|
+
return entry;
|
|
135
146
|
}
|
|
136
147
|
function extractSuitePath(titlePath) {
|
|
137
148
|
if (titlePath.length <= 1) return void 0;
|
|
@@ -142,16 +153,35 @@ function createStepMarker(keyword) {
|
|
|
142
153
|
function stepMarker(text, docsOrBody) {
|
|
143
154
|
const ctx = getContext();
|
|
144
155
|
const isCallback = typeof docsOrBody === "function";
|
|
156
|
+
const isChildrenArray = Array.isArray(docsOrBody);
|
|
145
157
|
const resolvedKeyword = (keyword === "Given" || keyword === "When" || keyword === "Then") && ctx.meta.steps.some((s) => s.keyword === keyword) ? "And" : keyword;
|
|
158
|
+
let stepDocs = [];
|
|
159
|
+
if (!isCallback && !isChildrenArray && docsOrBody) {
|
|
160
|
+
stepDocs = convertStoryDocsToEntries(docsOrBody);
|
|
161
|
+
}
|
|
146
162
|
const step = {
|
|
147
163
|
id: `step-${ctx.stepCounter++}`,
|
|
148
164
|
keyword: resolvedKeyword,
|
|
149
165
|
text,
|
|
150
|
-
docs:
|
|
166
|
+
docs: stepDocs,
|
|
151
167
|
...isCallback ? { wrapped: true } : {}
|
|
152
168
|
};
|
|
153
169
|
ctx.meta.steps.push(step);
|
|
154
170
|
ctx.currentStep = step;
|
|
171
|
+
if (isChildrenArray) {
|
|
172
|
+
const children = docsOrBody;
|
|
173
|
+
if (children.length > 0) {
|
|
174
|
+
const childSet = new Set(children);
|
|
175
|
+
ctx.meta.docs = (ctx.meta.docs ?? []).filter((d) => !childSet.has(d));
|
|
176
|
+
for (const prevStep of ctx.meta.steps) {
|
|
177
|
+
if (prevStep !== step && prevStep.docs) {
|
|
178
|
+
prevStep.docs = prevStep.docs.filter((d) => !childSet.has(d));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
step.docs = [...step.docs ?? [], ...children];
|
|
182
|
+
}
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
155
185
|
if (!isCallback) return;
|
|
156
186
|
const body = docsOrBody;
|
|
157
187
|
const start = performance.now();
|
|
@@ -276,40 +306,40 @@ var story = {
|
|
|
276
306
|
action: createStepMarker("When"),
|
|
277
307
|
verify: createStepMarker("Then"),
|
|
278
308
|
// Standalone doc methods
|
|
279
|
-
note(text) {
|
|
280
|
-
attachDoc({ kind: "note", text, phase: "runtime" });
|
|
309
|
+
note(text, children) {
|
|
310
|
+
return attachDoc({ kind: "note", text, phase: "runtime" }, children);
|
|
281
311
|
},
|
|
282
|
-
tag(name) {
|
|
312
|
+
tag(name, children) {
|
|
283
313
|
const names = Array.isArray(name) ? name : [name];
|
|
284
|
-
attachDoc({ kind: "tag", names, phase: "runtime" });
|
|
314
|
+
return attachDoc({ kind: "tag", names, phase: "runtime" }, children);
|
|
285
315
|
},
|
|
286
|
-
kv(options) {
|
|
287
|
-
attachDoc({ kind: "kv", label: options.label, value: options.value, phase: "runtime" });
|
|
316
|
+
kv(options, children) {
|
|
317
|
+
return attachDoc({ kind: "kv", label: options.label, value: options.value, phase: "runtime" }, children);
|
|
288
318
|
},
|
|
289
|
-
json(options) {
|
|
319
|
+
json(options, children) {
|
|
290
320
|
const content = JSON.stringify(options.value, null, 2);
|
|
291
|
-
attachDoc({ kind: "code", label: options.label, content, lang: "json", phase: "runtime" });
|
|
321
|
+
return attachDoc({ kind: "code", label: options.label, content, lang: "json", phase: "runtime" }, children);
|
|
292
322
|
},
|
|
293
|
-
code(options) {
|
|
294
|
-
attachDoc({ kind: "code", label: options.label, content: options.content, lang: options.lang, phase: "runtime" });
|
|
323
|
+
code(options, children) {
|
|
324
|
+
return attachDoc({ kind: "code", label: options.label, content: options.content, lang: options.lang, phase: "runtime" }, children);
|
|
295
325
|
},
|
|
296
|
-
table(options) {
|
|
297
|
-
attachDoc({ kind: "table", label: options.label, columns: options.columns, rows: options.rows, phase: "runtime" });
|
|
326
|
+
table(options, children) {
|
|
327
|
+
return attachDoc({ kind: "table", label: options.label, columns: options.columns, rows: options.rows, phase: "runtime" }, children);
|
|
298
328
|
},
|
|
299
|
-
link(options) {
|
|
300
|
-
attachDoc({ kind: "link", label: options.label, url: options.url, phase: "runtime" });
|
|
329
|
+
link(options, children) {
|
|
330
|
+
return attachDoc({ kind: "link", label: options.label, url: options.url, phase: "runtime" }, children);
|
|
301
331
|
},
|
|
302
|
-
section(options) {
|
|
303
|
-
attachDoc({ kind: "section", title: options.title, markdown: options.markdown, phase: "runtime" });
|
|
332
|
+
section(options, children) {
|
|
333
|
+
return attachDoc({ kind: "section", title: options.title, markdown: options.markdown, phase: "runtime" }, children);
|
|
304
334
|
},
|
|
305
|
-
mermaid(options) {
|
|
306
|
-
attachDoc({ kind: "mermaid", code: options.code, title: options.title, phase: "runtime" });
|
|
335
|
+
mermaid(options, children) {
|
|
336
|
+
return attachDoc({ kind: "mermaid", code: options.code, title: options.title, phase: "runtime" }, children);
|
|
307
337
|
},
|
|
308
|
-
screenshot(options) {
|
|
309
|
-
attachDoc({ kind: "screenshot", path: options.path, alt: options.alt, phase: "runtime" });
|
|
338
|
+
screenshot(options, children) {
|
|
339
|
+
return attachDoc({ kind: "screenshot", path: options.path, alt: options.alt, phase: "runtime" }, children);
|
|
310
340
|
},
|
|
311
|
-
custom(options) {
|
|
312
|
-
attachDoc({ kind: "custom", type: options.type, data: options.data, phase: "runtime" });
|
|
341
|
+
custom(options, children) {
|
|
342
|
+
return attachDoc({ kind: "custom", type: options.type, data: options.data, phase: "runtime" }, children);
|
|
313
343
|
},
|
|
314
344
|
// Attachments
|
|
315
345
|
attach(options) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/story-api.ts"],"sourcesContent":["/**\n * Cypress Executable Stories\n *\n * BDD-style executable documentation for Cypress.\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\n// Story API\nexport { story, getAndClearMeta } from './story-api';\nexport type { Story, RecordMetaPayload } from './story-api';\n\n// Re-export types from local types module\nexport type {\n StoryMeta,\n StoryStep,\n DocEntry,\n StepKeyword,\n StoryDocs,\n StoryOptions,\n KvOptions,\n JsonOptions,\n CodeOptions,\n TableOptions,\n LinkOptions,\n SectionOptions,\n MermaidOptions,\n ScreenshotOptions,\n CustomOptions,\n} from './types';\n","/**\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 otelSpans?: ReadonlyArray<Record<string, unknown>>;\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 function stepMarker(text: string, docs?: StoryDocs): void;\n function stepMarker<T>(text: string, body: () => T): T;\n function stepMarker<T>(text: string, docsOrBody?: StoryDocs | (() => T)): T | void {\n const ctx = getContext();\n const isCallback = typeof docsOrBody === 'function';\n\n const resolvedKeyword: StepKeyword =\n (keyword === 'Given' || keyword === 'When' || keyword === 'Then') &&\n ctx.meta.steps.some((s) => s.keyword === keyword)\n ? 'And'\n : keyword;\n\n const step: StoryStep = {\n id: `step-${ctx.stepCounter++}`,\n keyword: resolvedKeyword,\n text,\n docs: (!isCallback && docsOrBody) ? convertStoryDocsToEntries(docsOrBody) : [],\n ...(isCallback ? { wrapped: true } : {}),\n };\n\n ctx.meta.steps.push(step);\n ctx.currentStep = step;\n\n if (!isCallback) return;\n\n const body = docsOrBody as () => T;\n const start = performance.now();\n\n try {\n const result = body();\n if (result instanceof Promise) {\n return result.then(\n (val) => { step.durationMs = performance.now() - start; return val; },\n (err) => { step.durationMs = performance.now() - start; throw err; },\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 return stepMarker;\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 otelSpans: activeContext.otelSpans,\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\n const resolvedKeyword: StepKeyword =\n (keyword === 'Given' || keyword === 'When' || keyword === 'Then') &&\n ctx.meta.steps.some((s) => s.keyword === keyword)\n ? 'And'\n : keyword;\n\n const step: StoryStep = {\n id: `step-${ctx.stepCounter++}`,\n keyword: resolvedKeyword,\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 // OTel span attachment\n attachSpans(spans: ReadonlyArray<Record<string, unknown>>): void {\n const ctx = getContext();\n ctx.otelSpans = spans;\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"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/story-api.ts"],"sourcesContent":["/**\n * Cypress Executable Stories\n *\n * BDD-style executable documentation for Cypress.\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\n// Story API\nexport { story, getAndClearMeta } from './story-api';\nexport type { Story, RecordMetaPayload } from './story-api';\n\n// Re-export types from local types module\nexport type {\n StoryMeta,\n StoryStep,\n DocEntry,\n StepKeyword,\n StoryDocs,\n StoryOptions,\n KvOptions,\n JsonOptions,\n CodeOptions,\n TableOptions,\n LinkOptions,\n SectionOptions,\n MermaidOptions,\n ScreenshotOptions,\n CustomOptions,\n} from './types';\n","/**\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 NormalizedTicket,\n TicketInput,\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 NormalizedTicket,\n TicketInput,\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 otelSpans?: ReadonlyArray<Record<string, unknown>>;\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(\n ticket: TicketInput | TicketInput[] | undefined,\n): NormalizedTicket[] | undefined {\n if (!ticket) return undefined;\n const arr = Array.isArray(ticket) ? ticket : [ticket];\n return arr.map((t) => (typeof t === 'string' ? { id: t } : t));\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, children?: DocEntry[]): DocEntry {\n const ctx = getContext();\n if (children && children.length > 0) {\n entry.children = children;\n const childSet = new Set<DocEntry>(children);\n const filterDocs = (docs: DocEntry[]) => docs.filter((d) => !childSet.has(d));\n // Remove children from ALL containers (story-level + every step)\n ctx.meta.docs = filterDocs(ctx.meta.docs ?? []);\n for (const step of ctx.meta.steps) {\n if (step.docs) step.docs = filterDocs(step.docs);\n }\n }\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 return entry;\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 function stepMarker(text: string, docs?: StoryDocs): void;\n function stepMarker(text: string, children: DocEntry[]): void;\n function stepMarker<T>(text: string, body: () => T): T;\n function stepMarker<T>(text: string, docsOrBody?: StoryDocs | DocEntry[] | (() => T)): T | void {\n const ctx = getContext();\n const isCallback = typeof docsOrBody === 'function';\n const isChildrenArray = Array.isArray(docsOrBody);\n\n const resolvedKeyword: StepKeyword =\n (keyword === 'Given' || keyword === 'When' || keyword === 'Then') &&\n ctx.meta.steps.some((s) => s.keyword === keyword)\n ? 'And'\n : keyword;\n\n let stepDocs: DocEntry[] = [];\n if (!isCallback && !isChildrenArray && docsOrBody) {\n stepDocs = convertStoryDocsToEntries(docsOrBody as StoryDocs);\n }\n\n const step: StoryStep = {\n id: `step-${ctx.stepCounter++}`,\n keyword: resolvedKeyword,\n text,\n docs: stepDocs,\n ...(isCallback ? { wrapped: true } : {}),\n };\n\n ctx.meta.steps.push(step);\n ctx.currentStep = step;\n\n // Handle DocEntry[] children: attach as step docs and deduplicate from story-level\n if (isChildrenArray) {\n const children = docsOrBody as DocEntry[];\n if (children.length > 0) {\n const childSet = new Set<DocEntry>(children);\n // Deduplicate from story-level docs\n ctx.meta.docs = (ctx.meta.docs ?? []).filter((d) => !childSet.has(d));\n // Deduplicate from step docs of earlier steps\n for (const prevStep of ctx.meta.steps) {\n if (prevStep !== step && prevStep.docs) {\n prevStep.docs = prevStep.docs.filter((d) => !childSet.has(d));\n }\n }\n step.docs = [...(step.docs ?? []), ...children];\n }\n return;\n }\n\n if (!isCallback) return;\n\n const body = docsOrBody as () => T;\n const start = performance.now();\n\n try {\n const result = body();\n if (result instanceof Promise) {\n return result.then(\n (val) => { step.durationMs = performance.now() - start; return val; },\n (err) => { step.durationMs = performance.now() - start; throw err; },\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 return stepMarker;\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 otelSpans: activeContext.otelSpans,\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\n const resolvedKeyword: StepKeyword =\n (keyword === 'Given' || keyword === 'When' || keyword === 'Then') &&\n ctx.meta.steps.some((s) => s.keyword === keyword)\n ? 'And'\n : keyword;\n\n const step: StoryStep = {\n id: `step-${ctx.stepCounter++}`,\n keyword: resolvedKeyword,\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, children?: DocEntry[]): DocEntry {\n return attachDoc({ kind: 'note', text, phase: 'runtime' }, children);\n },\n\n tag(name: string | string[], children?: DocEntry[]): DocEntry {\n const names = Array.isArray(name) ? name : [name];\n return attachDoc({ kind: 'tag', names, phase: 'runtime' }, children);\n },\n\n kv(options: KvOptions, children?: DocEntry[]): DocEntry {\n return attachDoc({ kind: 'kv', label: options.label, value: options.value, phase: 'runtime' }, children);\n },\n\n json(options: JsonOptions, children?: DocEntry[]): DocEntry {\n const content = JSON.stringify(options.value, null, 2);\n return attachDoc({ kind: 'code', label: options.label, content, lang: 'json', phase: 'runtime' }, children);\n },\n\n code(options: CodeOptions, children?: DocEntry[]): DocEntry {\n return attachDoc({ kind: 'code', label: options.label, content: options.content, lang: options.lang, phase: 'runtime' }, children);\n },\n\n table(options: TableOptions, children?: DocEntry[]): DocEntry {\n return attachDoc({ kind: 'table', label: options.label, columns: options.columns, rows: options.rows, phase: 'runtime' }, children);\n },\n\n link(options: LinkOptions, children?: DocEntry[]): DocEntry {\n return attachDoc({ kind: 'link', label: options.label, url: options.url, phase: 'runtime' }, children);\n },\n\n section(options: SectionOptions, children?: DocEntry[]): DocEntry {\n return attachDoc({ kind: 'section', title: options.title, markdown: options.markdown, phase: 'runtime' }, children);\n },\n\n mermaid(options: MermaidOptions, children?: DocEntry[]): DocEntry {\n return attachDoc({ kind: 'mermaid', code: options.code, title: options.title, phase: 'runtime' }, children);\n },\n\n screenshot(options: ScreenshotOptions, children?: DocEntry[]): DocEntry {\n return attachDoc({ kind: 'screenshot', path: options.path, alt: options.alt, phase: 'runtime' }, children);\n },\n\n custom(options: CustomOptions, children?: DocEntry[]): DocEntry {\n return attachDoc({ kind: 'custom', type: options.type, data: options.data, phase: 'runtime' }, children);\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 // OTel span attachment\n attachSpans(spans: ReadonlyArray<Record<string, unknown>>): void {\n const ctx = getContext();\n ctx.otelSpans = spans;\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"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StoryMeta as StoryMeta$1, StepKeyword } from 'executable-stories-formatters';
|
|
1
|
+
import { StoryMeta as StoryMeta$1, DocEntry, StepKeyword } from 'executable-stories-formatters';
|
|
2
2
|
export { DocEntry, StepKeyword, StoryMeta, StoryStep } from 'executable-stories-formatters';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -6,6 +6,11 @@ export { DocEntry, StepKeyword, StoryMeta, StoryStep } from 'executable-stories-
|
|
|
6
6
|
* No Cypress or Node-only imports so both environments can use them.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
/** A ticket reference: either a plain string ID or an object with id and optional url */
|
|
10
|
+
type TicketInput = string | {
|
|
11
|
+
id: string;
|
|
12
|
+
url?: string;
|
|
13
|
+
};
|
|
9
14
|
type StoryMeta = StoryMeta$1;
|
|
10
15
|
/** Scoped attachment stored in context. */
|
|
11
16
|
interface ScopedAttachment {
|
|
@@ -44,7 +49,7 @@ interface StoryDocs {
|
|
|
44
49
|
/** Options for story.init(). */
|
|
45
50
|
interface StoryOptions {
|
|
46
51
|
tags?: string[];
|
|
47
|
-
ticket?:
|
|
52
|
+
ticket?: TicketInput | TicketInput[];
|
|
48
53
|
meta?: Record<string, unknown>;
|
|
49
54
|
}
|
|
50
55
|
/** Options for story.attach(). */
|
|
@@ -141,67 +146,80 @@ declare const story: {
|
|
|
141
146
|
init: typeof init;
|
|
142
147
|
given: {
|
|
143
148
|
(text: string, docs?: StoryDocs): void;
|
|
149
|
+
(text: string, children: DocEntry[]): void;
|
|
144
150
|
<T>(text: string, body: () => T): T;
|
|
145
151
|
};
|
|
146
152
|
when: {
|
|
147
153
|
(text: string, docs?: StoryDocs): void;
|
|
154
|
+
(text: string, children: DocEntry[]): void;
|
|
148
155
|
<T>(text: string, body: () => T): T;
|
|
149
156
|
};
|
|
150
157
|
then: {
|
|
151
158
|
(text: string, docs?: StoryDocs): void;
|
|
159
|
+
(text: string, children: DocEntry[]): void;
|
|
152
160
|
<T>(text: string, body: () => T): T;
|
|
153
161
|
};
|
|
154
162
|
and: {
|
|
155
163
|
(text: string, docs?: StoryDocs): void;
|
|
164
|
+
(text: string, children: DocEntry[]): void;
|
|
156
165
|
<T>(text: string, body: () => T): T;
|
|
157
166
|
};
|
|
158
167
|
but: {
|
|
159
168
|
(text: string, docs?: StoryDocs): void;
|
|
169
|
+
(text: string, children: DocEntry[]): void;
|
|
160
170
|
<T>(text: string, body: () => T): T;
|
|
161
171
|
};
|
|
162
172
|
arrange: {
|
|
163
173
|
(text: string, docs?: StoryDocs): void;
|
|
174
|
+
(text: string, children: DocEntry[]): void;
|
|
164
175
|
<T>(text: string, body: () => T): T;
|
|
165
176
|
};
|
|
166
177
|
act: {
|
|
167
178
|
(text: string, docs?: StoryDocs): void;
|
|
179
|
+
(text: string, children: DocEntry[]): void;
|
|
168
180
|
<T>(text: string, body: () => T): T;
|
|
169
181
|
};
|
|
170
182
|
assert: {
|
|
171
183
|
(text: string, docs?: StoryDocs): void;
|
|
184
|
+
(text: string, children: DocEntry[]): void;
|
|
172
185
|
<T>(text: string, body: () => T): T;
|
|
173
186
|
};
|
|
174
187
|
setup: {
|
|
175
188
|
(text: string, docs?: StoryDocs): void;
|
|
189
|
+
(text: string, children: DocEntry[]): void;
|
|
176
190
|
<T>(text: string, body: () => T): T;
|
|
177
191
|
};
|
|
178
192
|
context: {
|
|
179
193
|
(text: string, docs?: StoryDocs): void;
|
|
194
|
+
(text: string, children: DocEntry[]): void;
|
|
180
195
|
<T>(text: string, body: () => T): T;
|
|
181
196
|
};
|
|
182
197
|
execute: {
|
|
183
198
|
(text: string, docs?: StoryDocs): void;
|
|
199
|
+
(text: string, children: DocEntry[]): void;
|
|
184
200
|
<T>(text: string, body: () => T): T;
|
|
185
201
|
};
|
|
186
202
|
action: {
|
|
187
203
|
(text: string, docs?: StoryDocs): void;
|
|
204
|
+
(text: string, children: DocEntry[]): void;
|
|
188
205
|
<T>(text: string, body: () => T): T;
|
|
189
206
|
};
|
|
190
207
|
verify: {
|
|
191
208
|
(text: string, docs?: StoryDocs): void;
|
|
209
|
+
(text: string, children: DocEntry[]): void;
|
|
192
210
|
<T>(text: string, body: () => T): T;
|
|
193
211
|
};
|
|
194
|
-
note(text: string):
|
|
195
|
-
tag(name: string | string[]):
|
|
196
|
-
kv(options: KvOptions):
|
|
197
|
-
json(options: JsonOptions):
|
|
198
|
-
code(options: CodeOptions):
|
|
199
|
-
table(options: TableOptions):
|
|
200
|
-
link(options: LinkOptions):
|
|
201
|
-
section(options: SectionOptions):
|
|
202
|
-
mermaid(options: MermaidOptions):
|
|
203
|
-
screenshot(options: ScreenshotOptions):
|
|
204
|
-
custom(options: CustomOptions):
|
|
212
|
+
note(text: string, children?: DocEntry[]): DocEntry;
|
|
213
|
+
tag(name: string | string[], children?: DocEntry[]): DocEntry;
|
|
214
|
+
kv(options: KvOptions, children?: DocEntry[]): DocEntry;
|
|
215
|
+
json(options: JsonOptions, children?: DocEntry[]): DocEntry;
|
|
216
|
+
code(options: CodeOptions, children?: DocEntry[]): DocEntry;
|
|
217
|
+
table(options: TableOptions, children?: DocEntry[]): DocEntry;
|
|
218
|
+
link(options: LinkOptions, children?: DocEntry[]): DocEntry;
|
|
219
|
+
section(options: SectionOptions, children?: DocEntry[]): DocEntry;
|
|
220
|
+
mermaid(options: MermaidOptions, children?: DocEntry[]): DocEntry;
|
|
221
|
+
screenshot(options: ScreenshotOptions, children?: DocEntry[]): DocEntry;
|
|
222
|
+
custom(options: CustomOptions, children?: DocEntry[]): DocEntry;
|
|
205
223
|
attach(options: AttachmentOptions): void;
|
|
206
224
|
attachSpans(spans: ReadonlyArray<Record<string, unknown>>): void;
|
|
207
225
|
startTimer(): number;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StoryMeta as StoryMeta$1, StepKeyword } from 'executable-stories-formatters';
|
|
1
|
+
import { StoryMeta as StoryMeta$1, DocEntry, StepKeyword } from 'executable-stories-formatters';
|
|
2
2
|
export { DocEntry, StepKeyword, StoryMeta, StoryStep } from 'executable-stories-formatters';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -6,6 +6,11 @@ export { DocEntry, StepKeyword, StoryMeta, StoryStep } from 'executable-stories-
|
|
|
6
6
|
* No Cypress or Node-only imports so both environments can use them.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
/** A ticket reference: either a plain string ID or an object with id and optional url */
|
|
10
|
+
type TicketInput = string | {
|
|
11
|
+
id: string;
|
|
12
|
+
url?: string;
|
|
13
|
+
};
|
|
9
14
|
type StoryMeta = StoryMeta$1;
|
|
10
15
|
/** Scoped attachment stored in context. */
|
|
11
16
|
interface ScopedAttachment {
|
|
@@ -44,7 +49,7 @@ interface StoryDocs {
|
|
|
44
49
|
/** Options for story.init(). */
|
|
45
50
|
interface StoryOptions {
|
|
46
51
|
tags?: string[];
|
|
47
|
-
ticket?:
|
|
52
|
+
ticket?: TicketInput | TicketInput[];
|
|
48
53
|
meta?: Record<string, unknown>;
|
|
49
54
|
}
|
|
50
55
|
/** Options for story.attach(). */
|
|
@@ -141,67 +146,80 @@ declare const story: {
|
|
|
141
146
|
init: typeof init;
|
|
142
147
|
given: {
|
|
143
148
|
(text: string, docs?: StoryDocs): void;
|
|
149
|
+
(text: string, children: DocEntry[]): void;
|
|
144
150
|
<T>(text: string, body: () => T): T;
|
|
145
151
|
};
|
|
146
152
|
when: {
|
|
147
153
|
(text: string, docs?: StoryDocs): void;
|
|
154
|
+
(text: string, children: DocEntry[]): void;
|
|
148
155
|
<T>(text: string, body: () => T): T;
|
|
149
156
|
};
|
|
150
157
|
then: {
|
|
151
158
|
(text: string, docs?: StoryDocs): void;
|
|
159
|
+
(text: string, children: DocEntry[]): void;
|
|
152
160
|
<T>(text: string, body: () => T): T;
|
|
153
161
|
};
|
|
154
162
|
and: {
|
|
155
163
|
(text: string, docs?: StoryDocs): void;
|
|
164
|
+
(text: string, children: DocEntry[]): void;
|
|
156
165
|
<T>(text: string, body: () => T): T;
|
|
157
166
|
};
|
|
158
167
|
but: {
|
|
159
168
|
(text: string, docs?: StoryDocs): void;
|
|
169
|
+
(text: string, children: DocEntry[]): void;
|
|
160
170
|
<T>(text: string, body: () => T): T;
|
|
161
171
|
};
|
|
162
172
|
arrange: {
|
|
163
173
|
(text: string, docs?: StoryDocs): void;
|
|
174
|
+
(text: string, children: DocEntry[]): void;
|
|
164
175
|
<T>(text: string, body: () => T): T;
|
|
165
176
|
};
|
|
166
177
|
act: {
|
|
167
178
|
(text: string, docs?: StoryDocs): void;
|
|
179
|
+
(text: string, children: DocEntry[]): void;
|
|
168
180
|
<T>(text: string, body: () => T): T;
|
|
169
181
|
};
|
|
170
182
|
assert: {
|
|
171
183
|
(text: string, docs?: StoryDocs): void;
|
|
184
|
+
(text: string, children: DocEntry[]): void;
|
|
172
185
|
<T>(text: string, body: () => T): T;
|
|
173
186
|
};
|
|
174
187
|
setup: {
|
|
175
188
|
(text: string, docs?: StoryDocs): void;
|
|
189
|
+
(text: string, children: DocEntry[]): void;
|
|
176
190
|
<T>(text: string, body: () => T): T;
|
|
177
191
|
};
|
|
178
192
|
context: {
|
|
179
193
|
(text: string, docs?: StoryDocs): void;
|
|
194
|
+
(text: string, children: DocEntry[]): void;
|
|
180
195
|
<T>(text: string, body: () => T): T;
|
|
181
196
|
};
|
|
182
197
|
execute: {
|
|
183
198
|
(text: string, docs?: StoryDocs): void;
|
|
199
|
+
(text: string, children: DocEntry[]): void;
|
|
184
200
|
<T>(text: string, body: () => T): T;
|
|
185
201
|
};
|
|
186
202
|
action: {
|
|
187
203
|
(text: string, docs?: StoryDocs): void;
|
|
204
|
+
(text: string, children: DocEntry[]): void;
|
|
188
205
|
<T>(text: string, body: () => T): T;
|
|
189
206
|
};
|
|
190
207
|
verify: {
|
|
191
208
|
(text: string, docs?: StoryDocs): void;
|
|
209
|
+
(text: string, children: DocEntry[]): void;
|
|
192
210
|
<T>(text: string, body: () => T): T;
|
|
193
211
|
};
|
|
194
|
-
note(text: string):
|
|
195
|
-
tag(name: string | string[]):
|
|
196
|
-
kv(options: KvOptions):
|
|
197
|
-
json(options: JsonOptions):
|
|
198
|
-
code(options: CodeOptions):
|
|
199
|
-
table(options: TableOptions):
|
|
200
|
-
link(options: LinkOptions):
|
|
201
|
-
section(options: SectionOptions):
|
|
202
|
-
mermaid(options: MermaidOptions):
|
|
203
|
-
screenshot(options: ScreenshotOptions):
|
|
204
|
-
custom(options: CustomOptions):
|
|
212
|
+
note(text: string, children?: DocEntry[]): DocEntry;
|
|
213
|
+
tag(name: string | string[], children?: DocEntry[]): DocEntry;
|
|
214
|
+
kv(options: KvOptions, children?: DocEntry[]): DocEntry;
|
|
215
|
+
json(options: JsonOptions, children?: DocEntry[]): DocEntry;
|
|
216
|
+
code(options: CodeOptions, children?: DocEntry[]): DocEntry;
|
|
217
|
+
table(options: TableOptions, children?: DocEntry[]): DocEntry;
|
|
218
|
+
link(options: LinkOptions, children?: DocEntry[]): DocEntry;
|
|
219
|
+
section(options: SectionOptions, children?: DocEntry[]): DocEntry;
|
|
220
|
+
mermaid(options: MermaidOptions, children?: DocEntry[]): DocEntry;
|
|
221
|
+
screenshot(options: ScreenshotOptions, children?: DocEntry[]): DocEntry;
|
|
222
|
+
custom(options: CustomOptions, children?: DocEntry[]): DocEntry;
|
|
205
223
|
attach(options: AttachmentOptions): void;
|
|
206
224
|
attachSpans(spans: ReadonlyArray<Record<string, unknown>>): void;
|
|
207
225
|
startTimer(): number;
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,8 @@ function getContext() {
|
|
|
11
11
|
}
|
|
12
12
|
function normalizeTickets(ticket) {
|
|
13
13
|
if (!ticket) return void 0;
|
|
14
|
-
|
|
14
|
+
const arr = Array.isArray(ticket) ? ticket : [ticket];
|
|
15
|
+
return arr.map((t) => typeof t === "string" ? { id: t } : t);
|
|
15
16
|
}
|
|
16
17
|
function convertStoryDocsToEntries(docs) {
|
|
17
18
|
const entries = [];
|
|
@@ -96,8 +97,17 @@ function convertStoryDocsToEntries(docs) {
|
|
|
96
97
|
}
|
|
97
98
|
return entries;
|
|
98
99
|
}
|
|
99
|
-
function attachDoc(entry) {
|
|
100
|
+
function attachDoc(entry, children) {
|
|
100
101
|
const ctx = getContext();
|
|
102
|
+
if (children && children.length > 0) {
|
|
103
|
+
entry.children = children;
|
|
104
|
+
const childSet = new Set(children);
|
|
105
|
+
const filterDocs = (docs) => docs.filter((d) => !childSet.has(d));
|
|
106
|
+
ctx.meta.docs = filterDocs(ctx.meta.docs ?? []);
|
|
107
|
+
for (const step of ctx.meta.steps) {
|
|
108
|
+
if (step.docs) step.docs = filterDocs(step.docs);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
101
111
|
if (ctx.currentStep) {
|
|
102
112
|
ctx.currentStep.docs ??= [];
|
|
103
113
|
ctx.currentStep.docs.push(entry);
|
|
@@ -105,6 +115,7 @@ function attachDoc(entry) {
|
|
|
105
115
|
ctx.meta.docs ??= [];
|
|
106
116
|
ctx.meta.docs.push(entry);
|
|
107
117
|
}
|
|
118
|
+
return entry;
|
|
108
119
|
}
|
|
109
120
|
function extractSuitePath(titlePath) {
|
|
110
121
|
if (titlePath.length <= 1) return void 0;
|
|
@@ -115,16 +126,35 @@ function createStepMarker(keyword) {
|
|
|
115
126
|
function stepMarker(text, docsOrBody) {
|
|
116
127
|
const ctx = getContext();
|
|
117
128
|
const isCallback = typeof docsOrBody === "function";
|
|
129
|
+
const isChildrenArray = Array.isArray(docsOrBody);
|
|
118
130
|
const resolvedKeyword = (keyword === "Given" || keyword === "When" || keyword === "Then") && ctx.meta.steps.some((s) => s.keyword === keyword) ? "And" : keyword;
|
|
131
|
+
let stepDocs = [];
|
|
132
|
+
if (!isCallback && !isChildrenArray && docsOrBody) {
|
|
133
|
+
stepDocs = convertStoryDocsToEntries(docsOrBody);
|
|
134
|
+
}
|
|
119
135
|
const step = {
|
|
120
136
|
id: `step-${ctx.stepCounter++}`,
|
|
121
137
|
keyword: resolvedKeyword,
|
|
122
138
|
text,
|
|
123
|
-
docs:
|
|
139
|
+
docs: stepDocs,
|
|
124
140
|
...isCallback ? { wrapped: true } : {}
|
|
125
141
|
};
|
|
126
142
|
ctx.meta.steps.push(step);
|
|
127
143
|
ctx.currentStep = step;
|
|
144
|
+
if (isChildrenArray) {
|
|
145
|
+
const children = docsOrBody;
|
|
146
|
+
if (children.length > 0) {
|
|
147
|
+
const childSet = new Set(children);
|
|
148
|
+
ctx.meta.docs = (ctx.meta.docs ?? []).filter((d) => !childSet.has(d));
|
|
149
|
+
for (const prevStep of ctx.meta.steps) {
|
|
150
|
+
if (prevStep !== step && prevStep.docs) {
|
|
151
|
+
prevStep.docs = prevStep.docs.filter((d) => !childSet.has(d));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
step.docs = [...step.docs ?? [], ...children];
|
|
155
|
+
}
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
128
158
|
if (!isCallback) return;
|
|
129
159
|
const body = docsOrBody;
|
|
130
160
|
const start = performance.now();
|
|
@@ -249,40 +279,40 @@ var story = {
|
|
|
249
279
|
action: createStepMarker("When"),
|
|
250
280
|
verify: createStepMarker("Then"),
|
|
251
281
|
// Standalone doc methods
|
|
252
|
-
note(text) {
|
|
253
|
-
attachDoc({ kind: "note", text, phase: "runtime" });
|
|
282
|
+
note(text, children) {
|
|
283
|
+
return attachDoc({ kind: "note", text, phase: "runtime" }, children);
|
|
254
284
|
},
|
|
255
|
-
tag(name) {
|
|
285
|
+
tag(name, children) {
|
|
256
286
|
const names = Array.isArray(name) ? name : [name];
|
|
257
|
-
attachDoc({ kind: "tag", names, phase: "runtime" });
|
|
287
|
+
return attachDoc({ kind: "tag", names, phase: "runtime" }, children);
|
|
258
288
|
},
|
|
259
|
-
kv(options) {
|
|
260
|
-
attachDoc({ kind: "kv", label: options.label, value: options.value, phase: "runtime" });
|
|
289
|
+
kv(options, children) {
|
|
290
|
+
return attachDoc({ kind: "kv", label: options.label, value: options.value, phase: "runtime" }, children);
|
|
261
291
|
},
|
|
262
|
-
json(options) {
|
|
292
|
+
json(options, children) {
|
|
263
293
|
const content = JSON.stringify(options.value, null, 2);
|
|
264
|
-
attachDoc({ kind: "code", label: options.label, content, lang: "json", phase: "runtime" });
|
|
294
|
+
return attachDoc({ kind: "code", label: options.label, content, lang: "json", phase: "runtime" }, children);
|
|
265
295
|
},
|
|
266
|
-
code(options) {
|
|
267
|
-
attachDoc({ kind: "code", label: options.label, content: options.content, lang: options.lang, phase: "runtime" });
|
|
296
|
+
code(options, children) {
|
|
297
|
+
return attachDoc({ kind: "code", label: options.label, content: options.content, lang: options.lang, phase: "runtime" }, children);
|
|
268
298
|
},
|
|
269
|
-
table(options) {
|
|
270
|
-
attachDoc({ kind: "table", label: options.label, columns: options.columns, rows: options.rows, phase: "runtime" });
|
|
299
|
+
table(options, children) {
|
|
300
|
+
return attachDoc({ kind: "table", label: options.label, columns: options.columns, rows: options.rows, phase: "runtime" }, children);
|
|
271
301
|
},
|
|
272
|
-
link(options) {
|
|
273
|
-
attachDoc({ kind: "link", label: options.label, url: options.url, phase: "runtime" });
|
|
302
|
+
link(options, children) {
|
|
303
|
+
return attachDoc({ kind: "link", label: options.label, url: options.url, phase: "runtime" }, children);
|
|
274
304
|
},
|
|
275
|
-
section(options) {
|
|
276
|
-
attachDoc({ kind: "section", title: options.title, markdown: options.markdown, phase: "runtime" });
|
|
305
|
+
section(options, children) {
|
|
306
|
+
return attachDoc({ kind: "section", title: options.title, markdown: options.markdown, phase: "runtime" }, children);
|
|
277
307
|
},
|
|
278
|
-
mermaid(options) {
|
|
279
|
-
attachDoc({ kind: "mermaid", code: options.code, title: options.title, phase: "runtime" });
|
|
308
|
+
mermaid(options, children) {
|
|
309
|
+
return attachDoc({ kind: "mermaid", code: options.code, title: options.title, phase: "runtime" }, children);
|
|
280
310
|
},
|
|
281
|
-
screenshot(options) {
|
|
282
|
-
attachDoc({ kind: "screenshot", path: options.path, alt: options.alt, phase: "runtime" });
|
|
311
|
+
screenshot(options, children) {
|
|
312
|
+
return attachDoc({ kind: "screenshot", path: options.path, alt: options.alt, phase: "runtime" }, children);
|
|
283
313
|
},
|
|
284
|
-
custom(options) {
|
|
285
|
-
attachDoc({ kind: "custom", type: options.type, data: options.data, phase: "runtime" });
|
|
314
|
+
custom(options, children) {
|
|
315
|
+
return attachDoc({ kind: "custom", type: options.type, data: options.data, phase: "runtime" }, children);
|
|
286
316
|
},
|
|
287
317
|
// Attachments
|
|
288
318
|
attach(options) {
|