executable-stories-formatters 0.16.0 → 1.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.
Files changed (61) hide show
  1. package/README.md +6 -4
  2. package/dist/adapters.cjs.map +1 -1
  3. package/dist/adapters.d.cts +183 -1
  4. package/dist/adapters.d.ts +183 -1
  5. package/dist/adapters.js.map +1 -1
  6. package/dist/cli.js +1945 -15988
  7. package/dist/cli.js.map +1 -1
  8. package/dist/index.cjs +2353 -15773
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +127 -1174
  11. package/dist/index.d.ts +127 -1174
  12. package/dist/index.js +2350 -15770
  13. package/dist/index.js.map +1 -1
  14. package/package.json +15 -11
  15. package/schemas/README.md +0 -1
  16. package/templates/astro-thin/astro.config.mjs +62 -0
  17. package/templates/astro-thin/executable-stories.config.mjs +47 -0
  18. package/templates/astro-thin/gitignore +3 -0
  19. package/templates/astro-thin/package.json +20 -0
  20. package/templates/astro-thin/reports/sample-run.json +133 -0
  21. package/templates/astro-thin/src/content/docs/404.md +20 -0
  22. package/templates/astro-thin/src/content/docs/guides/writing-docs.mdx +7 -0
  23. package/templates/astro-thin/src/content/docs/index.mdx +44 -0
  24. package/templates/astro-thin/src/content.config.ts +26 -0
  25. package/templates/astro-thin/src/styles/stories.css +32 -0
  26. package/templates/astro-thin/tsconfig.json +5 -0
  27. package/dist/index-CXrzCk9p.d.cts +0 -628
  28. package/dist/index-CXrzCk9p.d.ts +0 -628
  29. package/schemas/story-report-v1.json +0 -456
  30. package/templates/astro-starlight/astro.config.mjs +0 -57
  31. package/templates/astro-starlight/gitignore +0 -14
  32. package/templates/astro-starlight/package.json +0 -20
  33. package/templates/astro-starlight/public/stories/assets/.gitkeep +0 -0
  34. package/templates/astro-starlight/public/stories/notes-index.json +0 -4
  35. package/templates/astro-starlight/public/stories/story-report.json +0 -17
  36. package/templates/astro-starlight/src/components/ApiOperations.astro +0 -366
  37. package/templates/astro-starlight/src/components/Checklist.astro +0 -15
  38. package/templates/astro-starlight/src/components/HealthDashboard.astro +0 -171
  39. package/templates/astro-starlight/src/components/PageTitle.astro +0 -53
  40. package/templates/astro-starlight/src/components/VerifiedBy.astro +0 -281
  41. package/templates/astro-starlight/src/components/VerifiedStep.astro +0 -91
  42. package/templates/astro-starlight/src/content/docs/examples/example-adr.mdx +0 -45
  43. package/templates/astro-starlight/src/content/docs/guides/behavior-portal.mdx +0 -41
  44. package/templates/astro-starlight/src/content/docs/guides/writing-docs.mdx +0 -49
  45. package/templates/astro-starlight/src/content/docs/index.mdx +0 -49
  46. package/templates/astro-starlight/src/content/docs/stories/.gitkeep +0 -0
  47. package/templates/astro-starlight/src/content.config.ts +0 -18
  48. package/templates/astro-starlight/src/lib/config.ts +0 -50
  49. package/templates/astro-starlight/src/lib/render-doc-entry.ts +0 -154
  50. package/templates/astro-starlight/src/lib/report-health.ts +0 -61
  51. package/templates/astro-starlight/src/lib/verification.ts +0 -247
  52. package/templates/astro-starlight/src/pages/explorer/explorer.css +0 -729
  53. package/templates/astro-starlight/src/pages/explorer/index.astro +0 -404
  54. package/templates/astro-starlight/src/styles/global.css +0 -293
  55. package/templates/astro-starlight/src/styles/themes/corporate.css +0 -83
  56. package/templates/astro-starlight/src/styles/themes/dashboard.css +0 -76
  57. package/templates/astro-starlight/src/styles/themes/default.css +0 -86
  58. package/templates/astro-starlight/src/styles/themes/minimal.css +0 -87
  59. package/templates/astro-starlight/src/styles/themes/playful.css +0 -77
  60. package/templates/astro-starlight/src/styles/themes/terminal.css +0 -77
  61. package/templates/astro-starlight/tsconfig.json +0 -13
package/README.md CHANGED
@@ -163,12 +163,14 @@ work for stories written in **any language** (TypeScript, Python, Go, Ruby,
163
163
  Java/Kotlin, Rust, C#).
164
164
 
165
165
  ```bash
166
- # 1. Scaffold the site (ships verified-by badges, a health dashboard, explorer)
166
+ # 1. Scaffold the thin site (the executable-stories-astro integration ships the
167
+ # verified-by badges, health dashboard, and Scenario Explorer)
167
168
  executable-stories init-astro story-docs
168
169
 
169
- # 2. Generate story pages + report data from any test run
170
- executable-stories format run.json --format astro --output-dir story-docs/src/content/docs/stories --asset-mode copy
171
- executable-stories format run.json --format story-report-json --output-dir story-docs/public/stories --output-name story-report
170
+ # 2. Run your tests to write run.json, then start the Astro dev server.
171
+ # The integration loads run.json as a live `stories` collection — pages at
172
+ # /stories hot-reload as tests re-run; no Markdown generation step.
173
+ cd story-docs && npm install && npm run dev
172
174
 
173
175
  # 3. Start hand-written pages from a verified template
174
176
  executable-stories new adr "Cap combined discount at 30%" # also: runbook, decision-log, incident
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/converters/adapters/index.ts","../src/converters/adapters/jest.ts","../src/converters/adapters/vitest.ts","../src/converters/adapters/playwright.ts"],"sourcesContent":["/**\n * Framework adapters - Layer 1.\n *\n * Transform framework-specific data to RawRun for ACL processing.\n */\n\nexport {\n adaptJestRun,\n type JestTestResult,\n type JestFileResult,\n type JestAggregatedResult,\n type StoryFileReport,\n type JestAdapterOptions,\n} from \"./jest\";\n\nexport {\n adaptVitestRun,\n type VitestState,\n type VitestSerializedError,\n type VitestTestResult,\n type VitestTestCase,\n type VitestTestModule,\n type VitestAdapterOptions,\n} from \"./vitest\";\n\nexport {\n adaptPlaywrightRun,\n type PlaywrightStatus,\n type PlaywrightError,\n type PlaywrightAttachment,\n type PlaywrightTestResult,\n type PlaywrightAnnotation,\n type PlaywrightLocation,\n type PlaywrightTestCase,\n type PlaywrightAdapterOptions,\n} from \"./playwright\";\n","/**\n * Jest Adapter - Layer 1.\n *\n * Transforms Jest test results and story reports into RawRun.\n */\n\nimport type { StoryMeta } from \"../../types/story\";\nimport type { RawRun, RawTestCase, RawStatus } from \"../../types/raw\";\n\n/** Jest test result shape (subset of what Jest provides) */\nexport interface JestTestResult {\n fullName: string;\n status: \"passed\" | \"failed\" | \"pending\" | \"todo\";\n duration?: number;\n failureMessages?: string[];\n}\n\n/** Jest file result shape */\nexport interface JestFileResult {\n testFilePath: string;\n testResults: JestTestResult[];\n}\n\n/** Jest aggregated result shape */\nexport interface JestAggregatedResult {\n testResults: JestFileResult[];\n startTime?: number;\n}\n\n/** Story file report written by story.init() */\nexport interface StoryFileReport {\n testFilePath: string;\n scenarios: StoryMeta[];\n}\n\n/** Options for Jest adapter */\nexport interface JestAdapterOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Package version */\n packageVersion?: string;\n /** Git SHA */\n gitSha?: string;\n}\n\n/**\n * Map Jest status to RawStatus.\n */\nfunction mapJestStatus(status: JestTestResult[\"status\"]): RawStatus {\n switch (status) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"pending\":\n return \"pending\";\n case \"todo\":\n return \"todo\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Adapt Jest results and story reports to RawRun.\n *\n * @param jestResults - Jest aggregated results\n * @param storyReports - Story reports from story.init()\n * @param options - Adapter options\n * @returns RawRun for ACL processing\n */\nexport function adaptJestRun(\n jestResults: JestAggregatedResult,\n storyReports: StoryFileReport[],\n options: JestAdapterOptions = {}\n): RawRun {\n const testCases: RawTestCase[] = [];\n\n // Build map of Jest results by file for lookup\n const fileResultsMap = new Map<string, JestFileResult>();\n for (const fileResult of jestResults.testResults) {\n fileResultsMap.set(fileResult.testFilePath, fileResult);\n }\n\n // Process each story report\n for (const report of storyReports) {\n const fileResult = fileResultsMap.get(report.testFilePath);\n\n for (const meta of report.scenarios) {\n if (!meta?.scenario) continue;\n\n // Find matching Jest test result\n const matchingTest = findMatchingJestTest(fileResult, meta);\n\n testCases.push({\n externalId: matchingTest?.fullName,\n title: meta.scenario,\n titlePath: meta.suitePath\n ? [...meta.suitePath, meta.scenario]\n : [meta.scenario],\n story: meta,\n sourceFile: report.testFilePath,\n sourceLine: undefined, // Jest doesn't provide line numbers\n status: matchingTest ? mapJestStatus(matchingTest.status) : \"unknown\",\n durationMs: matchingTest?.duration,\n error: matchingTest?.failureMessages?.length\n ? { message: matchingTest.failureMessages.join(\"\\n\") }\n : undefined,\n stepEvents: undefined, // Jest doesn't provide step-level results\n attachments: undefined, // Jest doesn't capture attachments\n meta: { jestStatus: matchingTest?.status },\n retry: 0,\n retries: 0,\n projectName: undefined,\n });\n }\n }\n\n return {\n testCases,\n startedAtMs: jestResults.startTime,\n finishedAtMs: Date.now(),\n projectRoot: options.projectRoot ?? process.cwd(),\n packageVersion: options.packageVersion,\n gitSha: options.gitSha,\n ci: detectCI(),\n };\n}\n\n/**\n * Find matching Jest test result for a story.\n *\n * Matches by constructing fullName from suitePath and scenario.\n */\nfunction findMatchingJestTest(\n fileResult: JestFileResult | undefined,\n meta: StoryMeta\n): JestTestResult | undefined {\n if (!fileResult) return undefined;\n\n // Construct expected fullName\n const expectedFullName = meta.suitePath\n ? [...meta.suitePath, meta.scenario].join(\" > \")\n : meta.scenario;\n\n return fileResult.testResults.find((test) => test.fullName === expectedFullName);\n}\n\n/**\n * Detect CI environment.\n */\nfunction detectCI() {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n return {\n name: \"GitHub Actions\",\n url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`\n : undefined,\n buildNumber: process.env.GITHUB_RUN_NUMBER,\n };\n }\n\n if (process.env.JENKINS_URL) {\n return {\n name: \"Jenkins\",\n url: process.env.BUILD_URL,\n buildNumber: process.env.BUILD_NUMBER,\n };\n }\n\n if (process.env.CI) {\n return {\n name: \"CI\",\n url: undefined,\n buildNumber: undefined,\n };\n }\n\n return undefined;\n}\n","/**\n * Vitest Adapter - Layer 1.\n *\n * Transforms Vitest test results into RawRun.\n */\n\nimport type { StoryMeta } from \"../../types/story\";\nimport type { RawRun, RawTestCase, RawStatus } from \"../../types/raw\";\n\n/** Vitest test state */\nexport type VitestState = \"passed\" | \"failed\" | \"skipped\" | \"pending\";\n\n/** Vitest serialized error */\nexport interface VitestSerializedError {\n message?: string;\n stack?: string;\n diff?: string;\n}\n\n/** Vitest test result shape */\nexport interface VitestTestResult {\n state?: VitestState;\n duration?: number;\n errors?: VitestSerializedError[];\n}\n\n/** Vitest test case shape (minimal) */\nexport interface VitestTestCase {\n name: string;\n meta: () => Record<string, unknown>;\n result: () => VitestTestResult | undefined;\n}\n\n/** Vitest test module shape (minimal) */\nexport interface VitestTestModule {\n moduleId?: string;\n relativeModuleId?: string;\n children?: {\n allTests: () => Iterable<VitestTestCase>;\n };\n}\n\n/** Options for Vitest adapter */\nexport interface VitestAdapterOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Package version */\n packageVersion?: string;\n /** Git SHA */\n gitSha?: string;\n /** Start time (epoch ms) */\n startedAtMs?: number;\n}\n\n/**\n * Map Vitest state to RawStatus.\n */\nfunction mapVitestStatus(state?: VitestState): RawStatus {\n switch (state) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"skipped\":\n return \"skip\";\n case \"pending\":\n return \"pending\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Adapt Vitest test modules to RawRun.\n *\n * @param testModules - Vitest test modules\n * @param options - Adapter options\n * @returns RawRun for ACL processing\n */\nexport function adaptVitestRun(\n testModules: ReadonlyArray<VitestTestModule>,\n options: VitestAdapterOptions = {}\n): RawRun {\n const testCases: RawTestCase[] = [];\n const projectRoot = options.projectRoot ?? process.cwd();\n\n for (const mod of testModules) {\n const collection = mod.children;\n if (!collection) continue;\n\n // Get module path\n const moduleId = mod.moduleId ?? mod.relativeModuleId ?? \"\";\n const sourcePath = moduleId.startsWith(\"/\")\n ? moduleId\n : `${projectRoot}/${moduleId}`;\n\n for (const test of collection.allTests()) {\n const meta = test.meta();\n const story = meta?.[\"story\"] as StoryMeta | undefined;\n\n if (!story?.scenario || !Array.isArray(story.steps)) continue;\n\n const result = test.result();\n const state = result?.state;\n const errors = state === \"failed\" && result ? result.errors : undefined;\n\n testCases.push({\n externalId: test.name,\n title: story.scenario,\n titlePath: story.suitePath\n ? [...story.suitePath, story.scenario]\n : [story.scenario],\n story,\n sourceFile: sourcePath,\n sourceLine: undefined, // Vitest doesn't provide line numbers easily\n status: mapVitestStatus(state),\n durationMs: result?.duration,\n error: errors?.length\n ? {\n message: formatVitestError(errors[0]),\n stack: errors[0].stack,\n }\n : undefined,\n stepEvents: undefined, // Vitest doesn't provide step-level results\n attachments: undefined, // Vitest doesn't capture attachments\n meta: { vitestState: state },\n retry: 0,\n retries: 0,\n projectName: undefined,\n });\n }\n }\n\n return {\n testCases,\n startedAtMs: options.startedAtMs,\n finishedAtMs: Date.now(),\n projectRoot,\n packageVersion: options.packageVersion,\n gitSha: options.gitSha,\n ci: detectCI(),\n };\n}\n\n/**\n * Format Vitest error message.\n */\nfunction formatVitestError(error: VitestSerializedError): string {\n const parts: string[] = [];\n\n if (error.message) {\n parts.push(error.message);\n }\n\n if (error.diff) {\n parts.push(\"\", error.diff);\n }\n\n return parts.join(\"\\n\") || \"Unknown error\";\n}\n\n/**\n * Detect CI environment.\n */\nfunction detectCI() {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n return {\n name: \"GitHub Actions\",\n url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`\n : undefined,\n buildNumber: process.env.GITHUB_RUN_NUMBER,\n };\n }\n\n if (process.env.JENKINS_URL) {\n return {\n name: \"Jenkins\",\n url: process.env.BUILD_URL,\n buildNumber: process.env.BUILD_NUMBER,\n };\n }\n\n if (process.env.CI) {\n return {\n name: \"CI\",\n url: undefined,\n buildNumber: undefined,\n };\n }\n\n return undefined;\n}\n","/**\n * Playwright Adapter - Layer 1.\n *\n * Transforms Playwright test results into RawRun.\n */\n\nimport type { StoryMeta } from \"../../types/story\";\nimport type { RawRun, RawTestCase, RawStatus, RawAttachment } from \"../../types/raw\";\n\n/** Playwright test status */\nexport type PlaywrightStatus =\n | \"passed\"\n | \"failed\"\n | \"skipped\"\n | \"timedOut\"\n | \"interrupted\";\n\n/** Playwright test error */\nexport interface PlaywrightError {\n message?: string;\n stack?: string;\n}\n\n/** Playwright attachment */\nexport interface PlaywrightAttachment {\n name: string;\n contentType: string;\n path?: string;\n body?: Buffer;\n}\n\n/** Playwright test result */\nexport interface PlaywrightTestResult {\n status: PlaywrightStatus;\n duration: number;\n errors: PlaywrightError[];\n attachments: PlaywrightAttachment[];\n retry: number;\n /** Optional step events if caller captures Playwright step timing. */\n stepEvents?: Array<{\n index?: number;\n stepId?: string;\n title?: string;\n status?: RawStatus;\n durationMs?: number;\n errorMessage?: string;\n }>;\n}\n\n/** Playwright test case annotation */\nexport interface PlaywrightAnnotation {\n type: string;\n description?: string;\n}\n\n/** Playwright test location */\nexport interface PlaywrightLocation {\n file: string;\n line: number;\n column: number;\n}\n\n/** Playwright test case shape (minimal) */\nexport interface PlaywrightTestCase {\n title: string;\n titlePath: () => string[];\n annotations: PlaywrightAnnotation[];\n location: PlaywrightLocation;\n retries: number;\n}\n\n/** Options for Playwright adapter */\nexport interface PlaywrightAdapterOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Package version */\n packageVersion?: string;\n /** Git SHA */\n gitSha?: string;\n /** Start time (epoch ms) */\n startedAtMs?: number;\n /** Playwright project name */\n projectName?: string;\n}\n\n/**\n * Map Playwright status to RawStatus.\n */\nfunction mapPlaywrightStatus(status: PlaywrightStatus): RawStatus {\n switch (status) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"skipped\":\n return \"skip\";\n case \"timedOut\":\n return \"timeout\";\n case \"interrupted\":\n return \"interrupted\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Adapt Playwright test results to RawRun.\n *\n * @param testResults - Array of [testCase, result] tuples\n * @param options - Adapter options\n * @returns RawRun for ACL processing\n */\nexport function adaptPlaywrightRun(\n testResults: Array<[PlaywrightTestCase, PlaywrightTestResult]>,\n options: PlaywrightAdapterOptions = {}\n): RawRun {\n const testCases: RawTestCase[] = [];\n const projectRoot = options.projectRoot ?? process.cwd();\n\n for (const [test, result] of testResults) {\n // Find story-meta annotation\n const storyAnnotation = test.annotations.find((a) => a.type === \"story-meta\");\n if (!storyAnnotation?.description) continue;\n\n let story: StoryMeta;\n try {\n story = JSON.parse(storyAnnotation.description);\n } catch {\n continue; // Skip if annotation is not valid JSON\n }\n\n if (!story?.scenario || !Array.isArray(story.steps)) continue;\n\n // Convert attachments\n const attachments = convertAttachments(result.attachments);\n\n // Get error info\n const error = result.errors?.length\n ? {\n message: result.errors[0].message,\n stack: result.errors[0].stack,\n }\n : undefined;\n\n const stepEvents =\n result.stepEvents?.length\n ? result.stepEvents\n : story.steps\n .map((step, index) =>\n step.durationMs !== undefined\n ? {\n index,\n stepId: step.id,\n title: step.text,\n durationMs: step.durationMs,\n }\n : undefined,\n )\n .filter((e): e is NonNullable<typeof e> => e !== undefined);\n\n testCases.push({\n externalId: test.titlePath().join(\" > \"),\n title: story.scenario,\n titlePath: test.titlePath(),\n story,\n sourceFile: test.location.file,\n sourceLine: test.location.line,\n status: mapPlaywrightStatus(result.status),\n durationMs: result.duration,\n error,\n stepEvents: stepEvents.length > 0 ? stepEvents : undefined,\n attachments,\n meta: {\n playwrightStatus: result.status,\n column: test.location.column,\n },\n retry: result.retry,\n retries: test.retries,\n projectName: options.projectName,\n });\n }\n\n return {\n testCases,\n startedAtMs: options.startedAtMs,\n finishedAtMs: Date.now(),\n projectRoot,\n packageVersion: options.packageVersion,\n gitSha: options.gitSha,\n ci: detectCI(),\n };\n}\n\n/**\n * Convert Playwright attachments to raw attachments.\n */\nfunction convertAttachments(\n attachments: PlaywrightAttachment[]\n): RawAttachment[] {\n return attachments.map((att) => ({\n name: att.name,\n mediaType: att.contentType,\n path: att.path,\n body: att.body ? att.body.toString(\"base64\") : undefined,\n encoding: att.body ? \"BASE64\" as const : undefined,\n byteLength: att.body?.length,\n }));\n}\n\n/**\n * Detect CI environment.\n */\nfunction detectCI() {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n return {\n name: \"GitHub Actions\",\n url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`\n : undefined,\n buildNumber: process.env.GITHUB_RUN_NUMBER,\n };\n }\n\n if (process.env.JENKINS_URL) {\n return {\n name: \"Jenkins\",\n url: process.env.BUILD_URL,\n buildNumber: process.env.BUILD_NUMBER,\n };\n }\n\n if (process.env.CI) {\n return {\n name: \"CI\",\n url: undefined,\n buildNumber: undefined,\n };\n }\n\n return undefined;\n}\n"],"mappings":"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","names":["detectCI","detectCI"]}
1
+ {"version":3,"sources":["../src/converters/adapters/index.ts","../src/converters/adapters/jest.ts","../src/converters/adapters/vitest.ts","../src/converters/adapters/playwright.ts"],"sourcesContent":["/**\n * Framework adapters - Layer 1.\n *\n * Transform framework-specific data to RawRun for ACL processing.\n */\n\nexport {\n adaptJestRun,\n type JestTestResult,\n type JestFileResult,\n type JestAggregatedResult,\n type StoryFileReport,\n type JestAdapterOptions,\n} from \"./jest\";\n\nexport {\n adaptVitestRun,\n type VitestState,\n type VitestSerializedError,\n type VitestTestResult,\n type VitestTestCase,\n type VitestTestModule,\n type VitestAdapterOptions,\n} from \"./vitest\";\n\nexport {\n adaptPlaywrightRun,\n type PlaywrightStatus,\n type PlaywrightError,\n type PlaywrightAttachment,\n type PlaywrightTestResult,\n type PlaywrightAnnotation,\n type PlaywrightLocation,\n type PlaywrightTestCase,\n type PlaywrightAdapterOptions,\n} from \"./playwright\";\n","/**\n * Jest Adapter - Layer 1.\n *\n * Transforms Jest test results and story reports into RawRun.\n */\n\nimport type { StoryMeta } from \"executable-stories-core/types/story\";\nimport type { RawRun, RawTestCase, RawStatus } from \"executable-stories-core/types/raw\";\n\n/** Jest test result shape (subset of what Jest provides) */\nexport interface JestTestResult {\n fullName: string;\n status: \"passed\" | \"failed\" | \"pending\" | \"todo\";\n duration?: number;\n failureMessages?: string[];\n}\n\n/** Jest file result shape */\nexport interface JestFileResult {\n testFilePath: string;\n testResults: JestTestResult[];\n}\n\n/** Jest aggregated result shape */\nexport interface JestAggregatedResult {\n testResults: JestFileResult[];\n startTime?: number;\n}\n\n/** Story file report written by story.init() */\nexport interface StoryFileReport {\n testFilePath: string;\n scenarios: StoryMeta[];\n}\n\n/** Options for Jest adapter */\nexport interface JestAdapterOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Package version */\n packageVersion?: string;\n /** Git SHA */\n gitSha?: string;\n}\n\n/**\n * Map Jest status to RawStatus.\n */\nfunction mapJestStatus(status: JestTestResult[\"status\"]): RawStatus {\n switch (status) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"pending\":\n return \"pending\";\n case \"todo\":\n return \"todo\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Adapt Jest results and story reports to RawRun.\n *\n * @param jestResults - Jest aggregated results\n * @param storyReports - Story reports from story.init()\n * @param options - Adapter options\n * @returns RawRun for ACL processing\n */\nexport function adaptJestRun(\n jestResults: JestAggregatedResult,\n storyReports: StoryFileReport[],\n options: JestAdapterOptions = {}\n): RawRun {\n const testCases: RawTestCase[] = [];\n\n // Build map of Jest results by file for lookup\n const fileResultsMap = new Map<string, JestFileResult>();\n for (const fileResult of jestResults.testResults) {\n fileResultsMap.set(fileResult.testFilePath, fileResult);\n }\n\n // Process each story report\n for (const report of storyReports) {\n const fileResult = fileResultsMap.get(report.testFilePath);\n\n for (const meta of report.scenarios) {\n if (!meta?.scenario) continue;\n\n // Find matching Jest test result\n const matchingTest = findMatchingJestTest(fileResult, meta);\n\n testCases.push({\n externalId: matchingTest?.fullName,\n title: meta.scenario,\n titlePath: meta.suitePath\n ? [...meta.suitePath, meta.scenario]\n : [meta.scenario],\n story: meta,\n sourceFile: report.testFilePath,\n sourceLine: undefined, // Jest doesn't provide line numbers\n status: matchingTest ? mapJestStatus(matchingTest.status) : \"unknown\",\n durationMs: matchingTest?.duration,\n error: matchingTest?.failureMessages?.length\n ? { message: matchingTest.failureMessages.join(\"\\n\") }\n : undefined,\n stepEvents: undefined, // Jest doesn't provide step-level results\n attachments: undefined, // Jest doesn't capture attachments\n meta: { jestStatus: matchingTest?.status },\n retry: 0,\n retries: 0,\n projectName: undefined,\n });\n }\n }\n\n return {\n testCases,\n startedAtMs: jestResults.startTime,\n finishedAtMs: Date.now(),\n projectRoot: options.projectRoot ?? process.cwd(),\n packageVersion: options.packageVersion,\n gitSha: options.gitSha,\n ci: detectCI(),\n };\n}\n\n/**\n * Find matching Jest test result for a story.\n *\n * Matches by constructing fullName from suitePath and scenario.\n */\nfunction findMatchingJestTest(\n fileResult: JestFileResult | undefined,\n meta: StoryMeta\n): JestTestResult | undefined {\n if (!fileResult) return undefined;\n\n // Construct expected fullName\n const expectedFullName = meta.suitePath\n ? [...meta.suitePath, meta.scenario].join(\" > \")\n : meta.scenario;\n\n return fileResult.testResults.find((test) => test.fullName === expectedFullName);\n}\n\n/**\n * Detect CI environment.\n */\nfunction detectCI() {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n return {\n name: \"GitHub Actions\",\n url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`\n : undefined,\n buildNumber: process.env.GITHUB_RUN_NUMBER,\n };\n }\n\n if (process.env.JENKINS_URL) {\n return {\n name: \"Jenkins\",\n url: process.env.BUILD_URL,\n buildNumber: process.env.BUILD_NUMBER,\n };\n }\n\n if (process.env.CI) {\n return {\n name: \"CI\",\n url: undefined,\n buildNumber: undefined,\n };\n }\n\n return undefined;\n}\n","/**\n * Vitest Adapter - Layer 1.\n *\n * Transforms Vitest test results into RawRun.\n */\n\nimport type { StoryMeta } from \"executable-stories-core/types/story\";\nimport type { RawRun, RawTestCase, RawStatus } from \"executable-stories-core/types/raw\";\n\n/** Vitest test state */\nexport type VitestState = \"passed\" | \"failed\" | \"skipped\" | \"pending\";\n\n/** Vitest serialized error */\nexport interface VitestSerializedError {\n message?: string;\n stack?: string;\n diff?: string;\n}\n\n/** Vitest test result shape */\nexport interface VitestTestResult {\n state?: VitestState;\n duration?: number;\n errors?: VitestSerializedError[];\n}\n\n/** Vitest test case shape (minimal) */\nexport interface VitestTestCase {\n name: string;\n meta: () => Record<string, unknown>;\n result: () => VitestTestResult | undefined;\n}\n\n/** Vitest test module shape (minimal) */\nexport interface VitestTestModule {\n moduleId?: string;\n relativeModuleId?: string;\n children?: {\n allTests: () => Iterable<VitestTestCase>;\n };\n}\n\n/** Options for Vitest adapter */\nexport interface VitestAdapterOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Package version */\n packageVersion?: string;\n /** Git SHA */\n gitSha?: string;\n /** Start time (epoch ms) */\n startedAtMs?: number;\n}\n\n/**\n * Map Vitest state to RawStatus.\n */\nfunction mapVitestStatus(state?: VitestState): RawStatus {\n switch (state) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"skipped\":\n return \"skip\";\n case \"pending\":\n return \"pending\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Adapt Vitest test modules to RawRun.\n *\n * @param testModules - Vitest test modules\n * @param options - Adapter options\n * @returns RawRun for ACL processing\n */\nexport function adaptVitestRun(\n testModules: ReadonlyArray<VitestTestModule>,\n options: VitestAdapterOptions = {}\n): RawRun {\n const testCases: RawTestCase[] = [];\n const projectRoot = options.projectRoot ?? process.cwd();\n\n for (const mod of testModules) {\n const collection = mod.children;\n if (!collection) continue;\n\n // Get module path\n const moduleId = mod.moduleId ?? mod.relativeModuleId ?? \"\";\n const sourcePath = moduleId.startsWith(\"/\")\n ? moduleId\n : `${projectRoot}/${moduleId}`;\n\n for (const test of collection.allTests()) {\n const meta = test.meta();\n const story = meta?.[\"story\"] as StoryMeta | undefined;\n\n if (!story?.scenario || !Array.isArray(story.steps)) continue;\n\n const result = test.result();\n const state = result?.state;\n const errors = state === \"failed\" && result ? result.errors : undefined;\n\n testCases.push({\n externalId: test.name,\n title: story.scenario,\n titlePath: story.suitePath\n ? [...story.suitePath, story.scenario]\n : [story.scenario],\n story,\n sourceFile: sourcePath,\n sourceLine: undefined, // Vitest doesn't provide line numbers easily\n status: mapVitestStatus(state),\n durationMs: result?.duration,\n error: errors?.length\n ? {\n message: formatVitestError(errors[0]),\n stack: errors[0].stack,\n }\n : undefined,\n stepEvents: undefined, // Vitest doesn't provide step-level results\n attachments: undefined, // Vitest doesn't capture attachments\n meta: { vitestState: state },\n retry: 0,\n retries: 0,\n projectName: undefined,\n });\n }\n }\n\n return {\n testCases,\n startedAtMs: options.startedAtMs,\n finishedAtMs: Date.now(),\n projectRoot,\n packageVersion: options.packageVersion,\n gitSha: options.gitSha,\n ci: detectCI(),\n };\n}\n\n/**\n * Format Vitest error message.\n */\nfunction formatVitestError(error: VitestSerializedError): string {\n const parts: string[] = [];\n\n if (error.message) {\n parts.push(error.message);\n }\n\n if (error.diff) {\n parts.push(\"\", error.diff);\n }\n\n return parts.join(\"\\n\") || \"Unknown error\";\n}\n\n/**\n * Detect CI environment.\n */\nfunction detectCI() {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n return {\n name: \"GitHub Actions\",\n url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`\n : undefined,\n buildNumber: process.env.GITHUB_RUN_NUMBER,\n };\n }\n\n if (process.env.JENKINS_URL) {\n return {\n name: \"Jenkins\",\n url: process.env.BUILD_URL,\n buildNumber: process.env.BUILD_NUMBER,\n };\n }\n\n if (process.env.CI) {\n return {\n name: \"CI\",\n url: undefined,\n buildNumber: undefined,\n };\n }\n\n return undefined;\n}\n","/**\n * Playwright Adapter - Layer 1.\n *\n * Transforms Playwright test results into RawRun.\n */\n\nimport type { StoryMeta } from \"executable-stories-core/types/story\";\nimport type { RawRun, RawTestCase, RawStatus, RawAttachment } from \"executable-stories-core/types/raw\";\n\n/** Playwright test status */\nexport type PlaywrightStatus =\n | \"passed\"\n | \"failed\"\n | \"skipped\"\n | \"timedOut\"\n | \"interrupted\";\n\n/** Playwright test error */\nexport interface PlaywrightError {\n message?: string;\n stack?: string;\n}\n\n/** Playwright attachment */\nexport interface PlaywrightAttachment {\n name: string;\n contentType: string;\n path?: string;\n body?: Buffer;\n}\n\n/** Playwright test result */\nexport interface PlaywrightTestResult {\n status: PlaywrightStatus;\n duration: number;\n errors: PlaywrightError[];\n attachments: PlaywrightAttachment[];\n retry: number;\n /** Optional step events if caller captures Playwright step timing. */\n stepEvents?: Array<{\n index?: number;\n stepId?: string;\n title?: string;\n status?: RawStatus;\n durationMs?: number;\n errorMessage?: string;\n }>;\n}\n\n/** Playwright test case annotation */\nexport interface PlaywrightAnnotation {\n type: string;\n description?: string;\n}\n\n/** Playwright test location */\nexport interface PlaywrightLocation {\n file: string;\n line: number;\n column: number;\n}\n\n/** Playwright test case shape (minimal) */\nexport interface PlaywrightTestCase {\n title: string;\n titlePath: () => string[];\n annotations: PlaywrightAnnotation[];\n location: PlaywrightLocation;\n retries: number;\n}\n\n/** Options for Playwright adapter */\nexport interface PlaywrightAdapterOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Package version */\n packageVersion?: string;\n /** Git SHA */\n gitSha?: string;\n /** Start time (epoch ms) */\n startedAtMs?: number;\n /** Playwright project name */\n projectName?: string;\n}\n\n/**\n * Map Playwright status to RawStatus.\n */\nfunction mapPlaywrightStatus(status: PlaywrightStatus): RawStatus {\n switch (status) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"skipped\":\n return \"skip\";\n case \"timedOut\":\n return \"timeout\";\n case \"interrupted\":\n return \"interrupted\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Adapt Playwright test results to RawRun.\n *\n * @param testResults - Array of [testCase, result] tuples\n * @param options - Adapter options\n * @returns RawRun for ACL processing\n */\nexport function adaptPlaywrightRun(\n testResults: Array<[PlaywrightTestCase, PlaywrightTestResult]>,\n options: PlaywrightAdapterOptions = {}\n): RawRun {\n const testCases: RawTestCase[] = [];\n const projectRoot = options.projectRoot ?? process.cwd();\n\n for (const [test, result] of testResults) {\n // Find story-meta annotation\n const storyAnnotation = test.annotations.find((a) => a.type === \"story-meta\");\n if (!storyAnnotation?.description) continue;\n\n let story: StoryMeta;\n try {\n story = JSON.parse(storyAnnotation.description);\n } catch {\n continue; // Skip if annotation is not valid JSON\n }\n\n if (!story?.scenario || !Array.isArray(story.steps)) continue;\n\n // Convert attachments\n const attachments = convertAttachments(result.attachments);\n\n // Get error info\n const error = result.errors?.length\n ? {\n message: result.errors[0].message,\n stack: result.errors[0].stack,\n }\n : undefined;\n\n const stepEvents =\n result.stepEvents?.length\n ? result.stepEvents\n : story.steps\n .map((step, index) =>\n step.durationMs !== undefined\n ? {\n index,\n stepId: step.id,\n title: step.text,\n durationMs: step.durationMs,\n }\n : undefined,\n )\n .filter((e): e is NonNullable<typeof e> => e !== undefined);\n\n testCases.push({\n externalId: test.titlePath().join(\" > \"),\n title: story.scenario,\n titlePath: test.titlePath(),\n story,\n sourceFile: test.location.file,\n sourceLine: test.location.line,\n status: mapPlaywrightStatus(result.status),\n durationMs: result.duration,\n error,\n stepEvents: stepEvents.length > 0 ? stepEvents : undefined,\n attachments,\n meta: {\n playwrightStatus: result.status,\n column: test.location.column,\n },\n retry: result.retry,\n retries: test.retries,\n projectName: options.projectName,\n });\n }\n\n return {\n testCases,\n startedAtMs: options.startedAtMs,\n finishedAtMs: Date.now(),\n projectRoot,\n packageVersion: options.packageVersion,\n gitSha: options.gitSha,\n ci: detectCI(),\n };\n}\n\n/**\n * Convert Playwright attachments to raw attachments.\n */\nfunction convertAttachments(\n attachments: PlaywrightAttachment[]\n): RawAttachment[] {\n return attachments.map((att) => ({\n name: att.name,\n mediaType: att.contentType,\n path: att.path,\n body: att.body ? att.body.toString(\"base64\") : undefined,\n encoding: att.body ? \"BASE64\" as const : undefined,\n byteLength: att.body?.length,\n }));\n}\n\n/**\n * Detect CI environment.\n */\nfunction detectCI() {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n return {\n name: \"GitHub Actions\",\n url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`\n : undefined,\n buildNumber: process.env.GITHUB_RUN_NUMBER,\n };\n }\n\n if (process.env.JENKINS_URL) {\n return {\n name: \"Jenkins\",\n url: process.env.BUILD_URL,\n buildNumber: process.env.BUILD_NUMBER,\n };\n }\n\n if (process.env.CI) {\n return {\n name: \"CI\",\n url: undefined,\n buildNumber: undefined,\n };\n }\n\n return undefined;\n}\n"],"mappings":"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","names":["detectCI","detectCI"]}
@@ -1 +1,183 @@
1
- export { J as JestAdapterOptions, o as JestAggregatedResult, p as JestFileResult, q as JestTestResult, P as PlaywrightAdapterOptions, s as PlaywrightAnnotation, t as PlaywrightAttachment, u as PlaywrightError, v as PlaywrightLocation, w as PlaywrightStatus, x as PlaywrightTestCase, y as PlaywrightTestResult, G as StoryFileReport, V as VitestAdapterOptions, L as VitestSerializedError, M as VitestState, Q as VitestTestCase, U as VitestTestModule, W as VitestTestResult, j as adaptJestRun, k as adaptPlaywrightRun, l as adaptVitestRun } from './index-CXrzCk9p.cjs';
1
+ import { StoryMeta } from 'executable-stories-core/types/story';
2
+ import { RawRun, RawStatus } from 'executable-stories-core/types/raw';
3
+
4
+ /**
5
+ * Jest Adapter - Layer 1.
6
+ *
7
+ * Transforms Jest test results and story reports into RawRun.
8
+ */
9
+
10
+ /** Jest test result shape (subset of what Jest provides) */
11
+ interface JestTestResult {
12
+ fullName: string;
13
+ status: "passed" | "failed" | "pending" | "todo";
14
+ duration?: number;
15
+ failureMessages?: string[];
16
+ }
17
+ /** Jest file result shape */
18
+ interface JestFileResult {
19
+ testFilePath: string;
20
+ testResults: JestTestResult[];
21
+ }
22
+ /** Jest aggregated result shape */
23
+ interface JestAggregatedResult {
24
+ testResults: JestFileResult[];
25
+ startTime?: number;
26
+ }
27
+ /** Story file report written by story.init() */
28
+ interface StoryFileReport {
29
+ testFilePath: string;
30
+ scenarios: StoryMeta[];
31
+ }
32
+ /** Options for Jest adapter */
33
+ interface JestAdapterOptions {
34
+ /** Project root directory */
35
+ projectRoot?: string;
36
+ /** Package version */
37
+ packageVersion?: string;
38
+ /** Git SHA */
39
+ gitSha?: string;
40
+ }
41
+ /**
42
+ * Adapt Jest results and story reports to RawRun.
43
+ *
44
+ * @param jestResults - Jest aggregated results
45
+ * @param storyReports - Story reports from story.init()
46
+ * @param options - Adapter options
47
+ * @returns RawRun for ACL processing
48
+ */
49
+ declare function adaptJestRun(jestResults: JestAggregatedResult, storyReports: StoryFileReport[], options?: JestAdapterOptions): RawRun;
50
+
51
+ /**
52
+ * Vitest Adapter - Layer 1.
53
+ *
54
+ * Transforms Vitest test results into RawRun.
55
+ */
56
+
57
+ /** Vitest test state */
58
+ type VitestState = "passed" | "failed" | "skipped" | "pending";
59
+ /** Vitest serialized error */
60
+ interface VitestSerializedError {
61
+ message?: string;
62
+ stack?: string;
63
+ diff?: string;
64
+ }
65
+ /** Vitest test result shape */
66
+ interface VitestTestResult {
67
+ state?: VitestState;
68
+ duration?: number;
69
+ errors?: VitestSerializedError[];
70
+ }
71
+ /** Vitest test case shape (minimal) */
72
+ interface VitestTestCase {
73
+ name: string;
74
+ meta: () => Record<string, unknown>;
75
+ result: () => VitestTestResult | undefined;
76
+ }
77
+ /** Vitest test module shape (minimal) */
78
+ interface VitestTestModule {
79
+ moduleId?: string;
80
+ relativeModuleId?: string;
81
+ children?: {
82
+ allTests: () => Iterable<VitestTestCase>;
83
+ };
84
+ }
85
+ /** Options for Vitest adapter */
86
+ interface VitestAdapterOptions {
87
+ /** Project root directory */
88
+ projectRoot?: string;
89
+ /** Package version */
90
+ packageVersion?: string;
91
+ /** Git SHA */
92
+ gitSha?: string;
93
+ /** Start time (epoch ms) */
94
+ startedAtMs?: number;
95
+ }
96
+ /**
97
+ * Adapt Vitest test modules to RawRun.
98
+ *
99
+ * @param testModules - Vitest test modules
100
+ * @param options - Adapter options
101
+ * @returns RawRun for ACL processing
102
+ */
103
+ declare function adaptVitestRun(testModules: ReadonlyArray<VitestTestModule>, options?: VitestAdapterOptions): RawRun;
104
+
105
+ /**
106
+ * Playwright Adapter - Layer 1.
107
+ *
108
+ * Transforms Playwright test results into RawRun.
109
+ */
110
+
111
+ /** Playwright test status */
112
+ type PlaywrightStatus = "passed" | "failed" | "skipped" | "timedOut" | "interrupted";
113
+ /** Playwright test error */
114
+ interface PlaywrightError {
115
+ message?: string;
116
+ stack?: string;
117
+ }
118
+ /** Playwright attachment */
119
+ interface PlaywrightAttachment {
120
+ name: string;
121
+ contentType: string;
122
+ path?: string;
123
+ body?: Buffer;
124
+ }
125
+ /** Playwright test result */
126
+ interface PlaywrightTestResult {
127
+ status: PlaywrightStatus;
128
+ duration: number;
129
+ errors: PlaywrightError[];
130
+ attachments: PlaywrightAttachment[];
131
+ retry: number;
132
+ /** Optional step events if caller captures Playwright step timing. */
133
+ stepEvents?: Array<{
134
+ index?: number;
135
+ stepId?: string;
136
+ title?: string;
137
+ status?: RawStatus;
138
+ durationMs?: number;
139
+ errorMessage?: string;
140
+ }>;
141
+ }
142
+ /** Playwright test case annotation */
143
+ interface PlaywrightAnnotation {
144
+ type: string;
145
+ description?: string;
146
+ }
147
+ /** Playwright test location */
148
+ interface PlaywrightLocation {
149
+ file: string;
150
+ line: number;
151
+ column: number;
152
+ }
153
+ /** Playwright test case shape (minimal) */
154
+ interface PlaywrightTestCase {
155
+ title: string;
156
+ titlePath: () => string[];
157
+ annotations: PlaywrightAnnotation[];
158
+ location: PlaywrightLocation;
159
+ retries: number;
160
+ }
161
+ /** Options for Playwright adapter */
162
+ interface PlaywrightAdapterOptions {
163
+ /** Project root directory */
164
+ projectRoot?: string;
165
+ /** Package version */
166
+ packageVersion?: string;
167
+ /** Git SHA */
168
+ gitSha?: string;
169
+ /** Start time (epoch ms) */
170
+ startedAtMs?: number;
171
+ /** Playwright project name */
172
+ projectName?: string;
173
+ }
174
+ /**
175
+ * Adapt Playwright test results to RawRun.
176
+ *
177
+ * @param testResults - Array of [testCase, result] tuples
178
+ * @param options - Adapter options
179
+ * @returns RawRun for ACL processing
180
+ */
181
+ declare function adaptPlaywrightRun(testResults: Array<[PlaywrightTestCase, PlaywrightTestResult]>, options?: PlaywrightAdapterOptions): RawRun;
182
+
183
+ export { type JestAdapterOptions, type JestAggregatedResult, type JestFileResult, type JestTestResult, type PlaywrightAdapterOptions, type PlaywrightAnnotation, type PlaywrightAttachment, type PlaywrightError, type PlaywrightLocation, type PlaywrightStatus, type PlaywrightTestCase, type PlaywrightTestResult, type StoryFileReport, type VitestAdapterOptions, type VitestSerializedError, type VitestState, type VitestTestCase, type VitestTestModule, type VitestTestResult, adaptJestRun, adaptPlaywrightRun, adaptVitestRun };
@@ -1 +1,183 @@
1
- export { J as JestAdapterOptions, o as JestAggregatedResult, p as JestFileResult, q as JestTestResult, P as PlaywrightAdapterOptions, s as PlaywrightAnnotation, t as PlaywrightAttachment, u as PlaywrightError, v as PlaywrightLocation, w as PlaywrightStatus, x as PlaywrightTestCase, y as PlaywrightTestResult, G as StoryFileReport, V as VitestAdapterOptions, L as VitestSerializedError, M as VitestState, Q as VitestTestCase, U as VitestTestModule, W as VitestTestResult, j as adaptJestRun, k as adaptPlaywrightRun, l as adaptVitestRun } from './index-CXrzCk9p.js';
1
+ import { StoryMeta } from 'executable-stories-core/types/story';
2
+ import { RawRun, RawStatus } from 'executable-stories-core/types/raw';
3
+
4
+ /**
5
+ * Jest Adapter - Layer 1.
6
+ *
7
+ * Transforms Jest test results and story reports into RawRun.
8
+ */
9
+
10
+ /** Jest test result shape (subset of what Jest provides) */
11
+ interface JestTestResult {
12
+ fullName: string;
13
+ status: "passed" | "failed" | "pending" | "todo";
14
+ duration?: number;
15
+ failureMessages?: string[];
16
+ }
17
+ /** Jest file result shape */
18
+ interface JestFileResult {
19
+ testFilePath: string;
20
+ testResults: JestTestResult[];
21
+ }
22
+ /** Jest aggregated result shape */
23
+ interface JestAggregatedResult {
24
+ testResults: JestFileResult[];
25
+ startTime?: number;
26
+ }
27
+ /** Story file report written by story.init() */
28
+ interface StoryFileReport {
29
+ testFilePath: string;
30
+ scenarios: StoryMeta[];
31
+ }
32
+ /** Options for Jest adapter */
33
+ interface JestAdapterOptions {
34
+ /** Project root directory */
35
+ projectRoot?: string;
36
+ /** Package version */
37
+ packageVersion?: string;
38
+ /** Git SHA */
39
+ gitSha?: string;
40
+ }
41
+ /**
42
+ * Adapt Jest results and story reports to RawRun.
43
+ *
44
+ * @param jestResults - Jest aggregated results
45
+ * @param storyReports - Story reports from story.init()
46
+ * @param options - Adapter options
47
+ * @returns RawRun for ACL processing
48
+ */
49
+ declare function adaptJestRun(jestResults: JestAggregatedResult, storyReports: StoryFileReport[], options?: JestAdapterOptions): RawRun;
50
+
51
+ /**
52
+ * Vitest Adapter - Layer 1.
53
+ *
54
+ * Transforms Vitest test results into RawRun.
55
+ */
56
+
57
+ /** Vitest test state */
58
+ type VitestState = "passed" | "failed" | "skipped" | "pending";
59
+ /** Vitest serialized error */
60
+ interface VitestSerializedError {
61
+ message?: string;
62
+ stack?: string;
63
+ diff?: string;
64
+ }
65
+ /** Vitest test result shape */
66
+ interface VitestTestResult {
67
+ state?: VitestState;
68
+ duration?: number;
69
+ errors?: VitestSerializedError[];
70
+ }
71
+ /** Vitest test case shape (minimal) */
72
+ interface VitestTestCase {
73
+ name: string;
74
+ meta: () => Record<string, unknown>;
75
+ result: () => VitestTestResult | undefined;
76
+ }
77
+ /** Vitest test module shape (minimal) */
78
+ interface VitestTestModule {
79
+ moduleId?: string;
80
+ relativeModuleId?: string;
81
+ children?: {
82
+ allTests: () => Iterable<VitestTestCase>;
83
+ };
84
+ }
85
+ /** Options for Vitest adapter */
86
+ interface VitestAdapterOptions {
87
+ /** Project root directory */
88
+ projectRoot?: string;
89
+ /** Package version */
90
+ packageVersion?: string;
91
+ /** Git SHA */
92
+ gitSha?: string;
93
+ /** Start time (epoch ms) */
94
+ startedAtMs?: number;
95
+ }
96
+ /**
97
+ * Adapt Vitest test modules to RawRun.
98
+ *
99
+ * @param testModules - Vitest test modules
100
+ * @param options - Adapter options
101
+ * @returns RawRun for ACL processing
102
+ */
103
+ declare function adaptVitestRun(testModules: ReadonlyArray<VitestTestModule>, options?: VitestAdapterOptions): RawRun;
104
+
105
+ /**
106
+ * Playwright Adapter - Layer 1.
107
+ *
108
+ * Transforms Playwright test results into RawRun.
109
+ */
110
+
111
+ /** Playwright test status */
112
+ type PlaywrightStatus = "passed" | "failed" | "skipped" | "timedOut" | "interrupted";
113
+ /** Playwright test error */
114
+ interface PlaywrightError {
115
+ message?: string;
116
+ stack?: string;
117
+ }
118
+ /** Playwright attachment */
119
+ interface PlaywrightAttachment {
120
+ name: string;
121
+ contentType: string;
122
+ path?: string;
123
+ body?: Buffer;
124
+ }
125
+ /** Playwright test result */
126
+ interface PlaywrightTestResult {
127
+ status: PlaywrightStatus;
128
+ duration: number;
129
+ errors: PlaywrightError[];
130
+ attachments: PlaywrightAttachment[];
131
+ retry: number;
132
+ /** Optional step events if caller captures Playwright step timing. */
133
+ stepEvents?: Array<{
134
+ index?: number;
135
+ stepId?: string;
136
+ title?: string;
137
+ status?: RawStatus;
138
+ durationMs?: number;
139
+ errorMessage?: string;
140
+ }>;
141
+ }
142
+ /** Playwright test case annotation */
143
+ interface PlaywrightAnnotation {
144
+ type: string;
145
+ description?: string;
146
+ }
147
+ /** Playwright test location */
148
+ interface PlaywrightLocation {
149
+ file: string;
150
+ line: number;
151
+ column: number;
152
+ }
153
+ /** Playwright test case shape (minimal) */
154
+ interface PlaywrightTestCase {
155
+ title: string;
156
+ titlePath: () => string[];
157
+ annotations: PlaywrightAnnotation[];
158
+ location: PlaywrightLocation;
159
+ retries: number;
160
+ }
161
+ /** Options for Playwright adapter */
162
+ interface PlaywrightAdapterOptions {
163
+ /** Project root directory */
164
+ projectRoot?: string;
165
+ /** Package version */
166
+ packageVersion?: string;
167
+ /** Git SHA */
168
+ gitSha?: string;
169
+ /** Start time (epoch ms) */
170
+ startedAtMs?: number;
171
+ /** Playwright project name */
172
+ projectName?: string;
173
+ }
174
+ /**
175
+ * Adapt Playwright test results to RawRun.
176
+ *
177
+ * @param testResults - Array of [testCase, result] tuples
178
+ * @param options - Adapter options
179
+ * @returns RawRun for ACL processing
180
+ */
181
+ declare function adaptPlaywrightRun(testResults: Array<[PlaywrightTestCase, PlaywrightTestResult]>, options?: PlaywrightAdapterOptions): RawRun;
182
+
183
+ export { type JestAdapterOptions, type JestAggregatedResult, type JestFileResult, type JestTestResult, type PlaywrightAdapterOptions, type PlaywrightAnnotation, type PlaywrightAttachment, type PlaywrightError, type PlaywrightLocation, type PlaywrightStatus, type PlaywrightTestCase, type PlaywrightTestResult, type StoryFileReport, type VitestAdapterOptions, type VitestSerializedError, type VitestState, type VitestTestCase, type VitestTestModule, type VitestTestResult, adaptJestRun, adaptPlaywrightRun, adaptVitestRun };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/converters/adapters/jest.ts","../src/converters/adapters/vitest.ts","../src/converters/adapters/playwright.ts"],"sourcesContent":["/**\n * Jest Adapter - Layer 1.\n *\n * Transforms Jest test results and story reports into RawRun.\n */\n\nimport type { StoryMeta } from \"../../types/story\";\nimport type { RawRun, RawTestCase, RawStatus } from \"../../types/raw\";\n\n/** Jest test result shape (subset of what Jest provides) */\nexport interface JestTestResult {\n fullName: string;\n status: \"passed\" | \"failed\" | \"pending\" | \"todo\";\n duration?: number;\n failureMessages?: string[];\n}\n\n/** Jest file result shape */\nexport interface JestFileResult {\n testFilePath: string;\n testResults: JestTestResult[];\n}\n\n/** Jest aggregated result shape */\nexport interface JestAggregatedResult {\n testResults: JestFileResult[];\n startTime?: number;\n}\n\n/** Story file report written by story.init() */\nexport interface StoryFileReport {\n testFilePath: string;\n scenarios: StoryMeta[];\n}\n\n/** Options for Jest adapter */\nexport interface JestAdapterOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Package version */\n packageVersion?: string;\n /** Git SHA */\n gitSha?: string;\n}\n\n/**\n * Map Jest status to RawStatus.\n */\nfunction mapJestStatus(status: JestTestResult[\"status\"]): RawStatus {\n switch (status) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"pending\":\n return \"pending\";\n case \"todo\":\n return \"todo\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Adapt Jest results and story reports to RawRun.\n *\n * @param jestResults - Jest aggregated results\n * @param storyReports - Story reports from story.init()\n * @param options - Adapter options\n * @returns RawRun for ACL processing\n */\nexport function adaptJestRun(\n jestResults: JestAggregatedResult,\n storyReports: StoryFileReport[],\n options: JestAdapterOptions = {}\n): RawRun {\n const testCases: RawTestCase[] = [];\n\n // Build map of Jest results by file for lookup\n const fileResultsMap = new Map<string, JestFileResult>();\n for (const fileResult of jestResults.testResults) {\n fileResultsMap.set(fileResult.testFilePath, fileResult);\n }\n\n // Process each story report\n for (const report of storyReports) {\n const fileResult = fileResultsMap.get(report.testFilePath);\n\n for (const meta of report.scenarios) {\n if (!meta?.scenario) continue;\n\n // Find matching Jest test result\n const matchingTest = findMatchingJestTest(fileResult, meta);\n\n testCases.push({\n externalId: matchingTest?.fullName,\n title: meta.scenario,\n titlePath: meta.suitePath\n ? [...meta.suitePath, meta.scenario]\n : [meta.scenario],\n story: meta,\n sourceFile: report.testFilePath,\n sourceLine: undefined, // Jest doesn't provide line numbers\n status: matchingTest ? mapJestStatus(matchingTest.status) : \"unknown\",\n durationMs: matchingTest?.duration,\n error: matchingTest?.failureMessages?.length\n ? { message: matchingTest.failureMessages.join(\"\\n\") }\n : undefined,\n stepEvents: undefined, // Jest doesn't provide step-level results\n attachments: undefined, // Jest doesn't capture attachments\n meta: { jestStatus: matchingTest?.status },\n retry: 0,\n retries: 0,\n projectName: undefined,\n });\n }\n }\n\n return {\n testCases,\n startedAtMs: jestResults.startTime,\n finishedAtMs: Date.now(),\n projectRoot: options.projectRoot ?? process.cwd(),\n packageVersion: options.packageVersion,\n gitSha: options.gitSha,\n ci: detectCI(),\n };\n}\n\n/**\n * Find matching Jest test result for a story.\n *\n * Matches by constructing fullName from suitePath and scenario.\n */\nfunction findMatchingJestTest(\n fileResult: JestFileResult | undefined,\n meta: StoryMeta\n): JestTestResult | undefined {\n if (!fileResult) return undefined;\n\n // Construct expected fullName\n const expectedFullName = meta.suitePath\n ? [...meta.suitePath, meta.scenario].join(\" > \")\n : meta.scenario;\n\n return fileResult.testResults.find((test) => test.fullName === expectedFullName);\n}\n\n/**\n * Detect CI environment.\n */\nfunction detectCI() {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n return {\n name: \"GitHub Actions\",\n url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`\n : undefined,\n buildNumber: process.env.GITHUB_RUN_NUMBER,\n };\n }\n\n if (process.env.JENKINS_URL) {\n return {\n name: \"Jenkins\",\n url: process.env.BUILD_URL,\n buildNumber: process.env.BUILD_NUMBER,\n };\n }\n\n if (process.env.CI) {\n return {\n name: \"CI\",\n url: undefined,\n buildNumber: undefined,\n };\n }\n\n return undefined;\n}\n","/**\n * Vitest Adapter - Layer 1.\n *\n * Transforms Vitest test results into RawRun.\n */\n\nimport type { StoryMeta } from \"../../types/story\";\nimport type { RawRun, RawTestCase, RawStatus } from \"../../types/raw\";\n\n/** Vitest test state */\nexport type VitestState = \"passed\" | \"failed\" | \"skipped\" | \"pending\";\n\n/** Vitest serialized error */\nexport interface VitestSerializedError {\n message?: string;\n stack?: string;\n diff?: string;\n}\n\n/** Vitest test result shape */\nexport interface VitestTestResult {\n state?: VitestState;\n duration?: number;\n errors?: VitestSerializedError[];\n}\n\n/** Vitest test case shape (minimal) */\nexport interface VitestTestCase {\n name: string;\n meta: () => Record<string, unknown>;\n result: () => VitestTestResult | undefined;\n}\n\n/** Vitest test module shape (minimal) */\nexport interface VitestTestModule {\n moduleId?: string;\n relativeModuleId?: string;\n children?: {\n allTests: () => Iterable<VitestTestCase>;\n };\n}\n\n/** Options for Vitest adapter */\nexport interface VitestAdapterOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Package version */\n packageVersion?: string;\n /** Git SHA */\n gitSha?: string;\n /** Start time (epoch ms) */\n startedAtMs?: number;\n}\n\n/**\n * Map Vitest state to RawStatus.\n */\nfunction mapVitestStatus(state?: VitestState): RawStatus {\n switch (state) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"skipped\":\n return \"skip\";\n case \"pending\":\n return \"pending\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Adapt Vitest test modules to RawRun.\n *\n * @param testModules - Vitest test modules\n * @param options - Adapter options\n * @returns RawRun for ACL processing\n */\nexport function adaptVitestRun(\n testModules: ReadonlyArray<VitestTestModule>,\n options: VitestAdapterOptions = {}\n): RawRun {\n const testCases: RawTestCase[] = [];\n const projectRoot = options.projectRoot ?? process.cwd();\n\n for (const mod of testModules) {\n const collection = mod.children;\n if (!collection) continue;\n\n // Get module path\n const moduleId = mod.moduleId ?? mod.relativeModuleId ?? \"\";\n const sourcePath = moduleId.startsWith(\"/\")\n ? moduleId\n : `${projectRoot}/${moduleId}`;\n\n for (const test of collection.allTests()) {\n const meta = test.meta();\n const story = meta?.[\"story\"] as StoryMeta | undefined;\n\n if (!story?.scenario || !Array.isArray(story.steps)) continue;\n\n const result = test.result();\n const state = result?.state;\n const errors = state === \"failed\" && result ? result.errors : undefined;\n\n testCases.push({\n externalId: test.name,\n title: story.scenario,\n titlePath: story.suitePath\n ? [...story.suitePath, story.scenario]\n : [story.scenario],\n story,\n sourceFile: sourcePath,\n sourceLine: undefined, // Vitest doesn't provide line numbers easily\n status: mapVitestStatus(state),\n durationMs: result?.duration,\n error: errors?.length\n ? {\n message: formatVitestError(errors[0]),\n stack: errors[0].stack,\n }\n : undefined,\n stepEvents: undefined, // Vitest doesn't provide step-level results\n attachments: undefined, // Vitest doesn't capture attachments\n meta: { vitestState: state },\n retry: 0,\n retries: 0,\n projectName: undefined,\n });\n }\n }\n\n return {\n testCases,\n startedAtMs: options.startedAtMs,\n finishedAtMs: Date.now(),\n projectRoot,\n packageVersion: options.packageVersion,\n gitSha: options.gitSha,\n ci: detectCI(),\n };\n}\n\n/**\n * Format Vitest error message.\n */\nfunction formatVitestError(error: VitestSerializedError): string {\n const parts: string[] = [];\n\n if (error.message) {\n parts.push(error.message);\n }\n\n if (error.diff) {\n parts.push(\"\", error.diff);\n }\n\n return parts.join(\"\\n\") || \"Unknown error\";\n}\n\n/**\n * Detect CI environment.\n */\nfunction detectCI() {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n return {\n name: \"GitHub Actions\",\n url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`\n : undefined,\n buildNumber: process.env.GITHUB_RUN_NUMBER,\n };\n }\n\n if (process.env.JENKINS_URL) {\n return {\n name: \"Jenkins\",\n url: process.env.BUILD_URL,\n buildNumber: process.env.BUILD_NUMBER,\n };\n }\n\n if (process.env.CI) {\n return {\n name: \"CI\",\n url: undefined,\n buildNumber: undefined,\n };\n }\n\n return undefined;\n}\n","/**\n * Playwright Adapter - Layer 1.\n *\n * Transforms Playwright test results into RawRun.\n */\n\nimport type { StoryMeta } from \"../../types/story\";\nimport type { RawRun, RawTestCase, RawStatus, RawAttachment } from \"../../types/raw\";\n\n/** Playwright test status */\nexport type PlaywrightStatus =\n | \"passed\"\n | \"failed\"\n | \"skipped\"\n | \"timedOut\"\n | \"interrupted\";\n\n/** Playwright test error */\nexport interface PlaywrightError {\n message?: string;\n stack?: string;\n}\n\n/** Playwright attachment */\nexport interface PlaywrightAttachment {\n name: string;\n contentType: string;\n path?: string;\n body?: Buffer;\n}\n\n/** Playwright test result */\nexport interface PlaywrightTestResult {\n status: PlaywrightStatus;\n duration: number;\n errors: PlaywrightError[];\n attachments: PlaywrightAttachment[];\n retry: number;\n /** Optional step events if caller captures Playwright step timing. */\n stepEvents?: Array<{\n index?: number;\n stepId?: string;\n title?: string;\n status?: RawStatus;\n durationMs?: number;\n errorMessage?: string;\n }>;\n}\n\n/** Playwright test case annotation */\nexport interface PlaywrightAnnotation {\n type: string;\n description?: string;\n}\n\n/** Playwright test location */\nexport interface PlaywrightLocation {\n file: string;\n line: number;\n column: number;\n}\n\n/** Playwright test case shape (minimal) */\nexport interface PlaywrightTestCase {\n title: string;\n titlePath: () => string[];\n annotations: PlaywrightAnnotation[];\n location: PlaywrightLocation;\n retries: number;\n}\n\n/** Options for Playwright adapter */\nexport interface PlaywrightAdapterOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Package version */\n packageVersion?: string;\n /** Git SHA */\n gitSha?: string;\n /** Start time (epoch ms) */\n startedAtMs?: number;\n /** Playwright project name */\n projectName?: string;\n}\n\n/**\n * Map Playwright status to RawStatus.\n */\nfunction mapPlaywrightStatus(status: PlaywrightStatus): RawStatus {\n switch (status) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"skipped\":\n return \"skip\";\n case \"timedOut\":\n return \"timeout\";\n case \"interrupted\":\n return \"interrupted\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Adapt Playwright test results to RawRun.\n *\n * @param testResults - Array of [testCase, result] tuples\n * @param options - Adapter options\n * @returns RawRun for ACL processing\n */\nexport function adaptPlaywrightRun(\n testResults: Array<[PlaywrightTestCase, PlaywrightTestResult]>,\n options: PlaywrightAdapterOptions = {}\n): RawRun {\n const testCases: RawTestCase[] = [];\n const projectRoot = options.projectRoot ?? process.cwd();\n\n for (const [test, result] of testResults) {\n // Find story-meta annotation\n const storyAnnotation = test.annotations.find((a) => a.type === \"story-meta\");\n if (!storyAnnotation?.description) continue;\n\n let story: StoryMeta;\n try {\n story = JSON.parse(storyAnnotation.description);\n } catch {\n continue; // Skip if annotation is not valid JSON\n }\n\n if (!story?.scenario || !Array.isArray(story.steps)) continue;\n\n // Convert attachments\n const attachments = convertAttachments(result.attachments);\n\n // Get error info\n const error = result.errors?.length\n ? {\n message: result.errors[0].message,\n stack: result.errors[0].stack,\n }\n : undefined;\n\n const stepEvents =\n result.stepEvents?.length\n ? result.stepEvents\n : story.steps\n .map((step, index) =>\n step.durationMs !== undefined\n ? {\n index,\n stepId: step.id,\n title: step.text,\n durationMs: step.durationMs,\n }\n : undefined,\n )\n .filter((e): e is NonNullable<typeof e> => e !== undefined);\n\n testCases.push({\n externalId: test.titlePath().join(\" > \"),\n title: story.scenario,\n titlePath: test.titlePath(),\n story,\n sourceFile: test.location.file,\n sourceLine: test.location.line,\n status: mapPlaywrightStatus(result.status),\n durationMs: result.duration,\n error,\n stepEvents: stepEvents.length > 0 ? stepEvents : undefined,\n attachments,\n meta: {\n playwrightStatus: result.status,\n column: test.location.column,\n },\n retry: result.retry,\n retries: test.retries,\n projectName: options.projectName,\n });\n }\n\n return {\n testCases,\n startedAtMs: options.startedAtMs,\n finishedAtMs: Date.now(),\n projectRoot,\n packageVersion: options.packageVersion,\n gitSha: options.gitSha,\n ci: detectCI(),\n };\n}\n\n/**\n * Convert Playwright attachments to raw attachments.\n */\nfunction convertAttachments(\n attachments: PlaywrightAttachment[]\n): RawAttachment[] {\n return attachments.map((att) => ({\n name: att.name,\n mediaType: att.contentType,\n path: att.path,\n body: att.body ? att.body.toString(\"base64\") : undefined,\n encoding: att.body ? \"BASE64\" as const : undefined,\n byteLength: att.body?.length,\n }));\n}\n\n/**\n * Detect CI environment.\n */\nfunction detectCI() {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n return {\n name: \"GitHub Actions\",\n url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`\n : undefined,\n buildNumber: process.env.GITHUB_RUN_NUMBER,\n };\n }\n\n if (process.env.JENKINS_URL) {\n return {\n name: \"Jenkins\",\n url: process.env.BUILD_URL,\n buildNumber: process.env.BUILD_NUMBER,\n };\n }\n\n if (process.env.CI) {\n return {\n name: \"CI\",\n url: undefined,\n buildNumber: undefined,\n };\n }\n\n return undefined;\n}\n"],"mappings":"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","names":["detectCI","detectCI"]}
1
+ {"version":3,"sources":["../src/converters/adapters/jest.ts","../src/converters/adapters/vitest.ts","../src/converters/adapters/playwright.ts"],"sourcesContent":["/**\n * Jest Adapter - Layer 1.\n *\n * Transforms Jest test results and story reports into RawRun.\n */\n\nimport type { StoryMeta } from \"executable-stories-core/types/story\";\nimport type { RawRun, RawTestCase, RawStatus } from \"executable-stories-core/types/raw\";\n\n/** Jest test result shape (subset of what Jest provides) */\nexport interface JestTestResult {\n fullName: string;\n status: \"passed\" | \"failed\" | \"pending\" | \"todo\";\n duration?: number;\n failureMessages?: string[];\n}\n\n/** Jest file result shape */\nexport interface JestFileResult {\n testFilePath: string;\n testResults: JestTestResult[];\n}\n\n/** Jest aggregated result shape */\nexport interface JestAggregatedResult {\n testResults: JestFileResult[];\n startTime?: number;\n}\n\n/** Story file report written by story.init() */\nexport interface StoryFileReport {\n testFilePath: string;\n scenarios: StoryMeta[];\n}\n\n/** Options for Jest adapter */\nexport interface JestAdapterOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Package version */\n packageVersion?: string;\n /** Git SHA */\n gitSha?: string;\n}\n\n/**\n * Map Jest status to RawStatus.\n */\nfunction mapJestStatus(status: JestTestResult[\"status\"]): RawStatus {\n switch (status) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"pending\":\n return \"pending\";\n case \"todo\":\n return \"todo\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Adapt Jest results and story reports to RawRun.\n *\n * @param jestResults - Jest aggregated results\n * @param storyReports - Story reports from story.init()\n * @param options - Adapter options\n * @returns RawRun for ACL processing\n */\nexport function adaptJestRun(\n jestResults: JestAggregatedResult,\n storyReports: StoryFileReport[],\n options: JestAdapterOptions = {}\n): RawRun {\n const testCases: RawTestCase[] = [];\n\n // Build map of Jest results by file for lookup\n const fileResultsMap = new Map<string, JestFileResult>();\n for (const fileResult of jestResults.testResults) {\n fileResultsMap.set(fileResult.testFilePath, fileResult);\n }\n\n // Process each story report\n for (const report of storyReports) {\n const fileResult = fileResultsMap.get(report.testFilePath);\n\n for (const meta of report.scenarios) {\n if (!meta?.scenario) continue;\n\n // Find matching Jest test result\n const matchingTest = findMatchingJestTest(fileResult, meta);\n\n testCases.push({\n externalId: matchingTest?.fullName,\n title: meta.scenario,\n titlePath: meta.suitePath\n ? [...meta.suitePath, meta.scenario]\n : [meta.scenario],\n story: meta,\n sourceFile: report.testFilePath,\n sourceLine: undefined, // Jest doesn't provide line numbers\n status: matchingTest ? mapJestStatus(matchingTest.status) : \"unknown\",\n durationMs: matchingTest?.duration,\n error: matchingTest?.failureMessages?.length\n ? { message: matchingTest.failureMessages.join(\"\\n\") }\n : undefined,\n stepEvents: undefined, // Jest doesn't provide step-level results\n attachments: undefined, // Jest doesn't capture attachments\n meta: { jestStatus: matchingTest?.status },\n retry: 0,\n retries: 0,\n projectName: undefined,\n });\n }\n }\n\n return {\n testCases,\n startedAtMs: jestResults.startTime,\n finishedAtMs: Date.now(),\n projectRoot: options.projectRoot ?? process.cwd(),\n packageVersion: options.packageVersion,\n gitSha: options.gitSha,\n ci: detectCI(),\n };\n}\n\n/**\n * Find matching Jest test result for a story.\n *\n * Matches by constructing fullName from suitePath and scenario.\n */\nfunction findMatchingJestTest(\n fileResult: JestFileResult | undefined,\n meta: StoryMeta\n): JestTestResult | undefined {\n if (!fileResult) return undefined;\n\n // Construct expected fullName\n const expectedFullName = meta.suitePath\n ? [...meta.suitePath, meta.scenario].join(\" > \")\n : meta.scenario;\n\n return fileResult.testResults.find((test) => test.fullName === expectedFullName);\n}\n\n/**\n * Detect CI environment.\n */\nfunction detectCI() {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n return {\n name: \"GitHub Actions\",\n url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`\n : undefined,\n buildNumber: process.env.GITHUB_RUN_NUMBER,\n };\n }\n\n if (process.env.JENKINS_URL) {\n return {\n name: \"Jenkins\",\n url: process.env.BUILD_URL,\n buildNumber: process.env.BUILD_NUMBER,\n };\n }\n\n if (process.env.CI) {\n return {\n name: \"CI\",\n url: undefined,\n buildNumber: undefined,\n };\n }\n\n return undefined;\n}\n","/**\n * Vitest Adapter - Layer 1.\n *\n * Transforms Vitest test results into RawRun.\n */\n\nimport type { StoryMeta } from \"executable-stories-core/types/story\";\nimport type { RawRun, RawTestCase, RawStatus } from \"executable-stories-core/types/raw\";\n\n/** Vitest test state */\nexport type VitestState = \"passed\" | \"failed\" | \"skipped\" | \"pending\";\n\n/** Vitest serialized error */\nexport interface VitestSerializedError {\n message?: string;\n stack?: string;\n diff?: string;\n}\n\n/** Vitest test result shape */\nexport interface VitestTestResult {\n state?: VitestState;\n duration?: number;\n errors?: VitestSerializedError[];\n}\n\n/** Vitest test case shape (minimal) */\nexport interface VitestTestCase {\n name: string;\n meta: () => Record<string, unknown>;\n result: () => VitestTestResult | undefined;\n}\n\n/** Vitest test module shape (minimal) */\nexport interface VitestTestModule {\n moduleId?: string;\n relativeModuleId?: string;\n children?: {\n allTests: () => Iterable<VitestTestCase>;\n };\n}\n\n/** Options for Vitest adapter */\nexport interface VitestAdapterOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Package version */\n packageVersion?: string;\n /** Git SHA */\n gitSha?: string;\n /** Start time (epoch ms) */\n startedAtMs?: number;\n}\n\n/**\n * Map Vitest state to RawStatus.\n */\nfunction mapVitestStatus(state?: VitestState): RawStatus {\n switch (state) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"skipped\":\n return \"skip\";\n case \"pending\":\n return \"pending\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Adapt Vitest test modules to RawRun.\n *\n * @param testModules - Vitest test modules\n * @param options - Adapter options\n * @returns RawRun for ACL processing\n */\nexport function adaptVitestRun(\n testModules: ReadonlyArray<VitestTestModule>,\n options: VitestAdapterOptions = {}\n): RawRun {\n const testCases: RawTestCase[] = [];\n const projectRoot = options.projectRoot ?? process.cwd();\n\n for (const mod of testModules) {\n const collection = mod.children;\n if (!collection) continue;\n\n // Get module path\n const moduleId = mod.moduleId ?? mod.relativeModuleId ?? \"\";\n const sourcePath = moduleId.startsWith(\"/\")\n ? moduleId\n : `${projectRoot}/${moduleId}`;\n\n for (const test of collection.allTests()) {\n const meta = test.meta();\n const story = meta?.[\"story\"] as StoryMeta | undefined;\n\n if (!story?.scenario || !Array.isArray(story.steps)) continue;\n\n const result = test.result();\n const state = result?.state;\n const errors = state === \"failed\" && result ? result.errors : undefined;\n\n testCases.push({\n externalId: test.name,\n title: story.scenario,\n titlePath: story.suitePath\n ? [...story.suitePath, story.scenario]\n : [story.scenario],\n story,\n sourceFile: sourcePath,\n sourceLine: undefined, // Vitest doesn't provide line numbers easily\n status: mapVitestStatus(state),\n durationMs: result?.duration,\n error: errors?.length\n ? {\n message: formatVitestError(errors[0]),\n stack: errors[0].stack,\n }\n : undefined,\n stepEvents: undefined, // Vitest doesn't provide step-level results\n attachments: undefined, // Vitest doesn't capture attachments\n meta: { vitestState: state },\n retry: 0,\n retries: 0,\n projectName: undefined,\n });\n }\n }\n\n return {\n testCases,\n startedAtMs: options.startedAtMs,\n finishedAtMs: Date.now(),\n projectRoot,\n packageVersion: options.packageVersion,\n gitSha: options.gitSha,\n ci: detectCI(),\n };\n}\n\n/**\n * Format Vitest error message.\n */\nfunction formatVitestError(error: VitestSerializedError): string {\n const parts: string[] = [];\n\n if (error.message) {\n parts.push(error.message);\n }\n\n if (error.diff) {\n parts.push(\"\", error.diff);\n }\n\n return parts.join(\"\\n\") || \"Unknown error\";\n}\n\n/**\n * Detect CI environment.\n */\nfunction detectCI() {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n return {\n name: \"GitHub Actions\",\n url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`\n : undefined,\n buildNumber: process.env.GITHUB_RUN_NUMBER,\n };\n }\n\n if (process.env.JENKINS_URL) {\n return {\n name: \"Jenkins\",\n url: process.env.BUILD_URL,\n buildNumber: process.env.BUILD_NUMBER,\n };\n }\n\n if (process.env.CI) {\n return {\n name: \"CI\",\n url: undefined,\n buildNumber: undefined,\n };\n }\n\n return undefined;\n}\n","/**\n * Playwright Adapter - Layer 1.\n *\n * Transforms Playwright test results into RawRun.\n */\n\nimport type { StoryMeta } from \"executable-stories-core/types/story\";\nimport type { RawRun, RawTestCase, RawStatus, RawAttachment } from \"executable-stories-core/types/raw\";\n\n/** Playwright test status */\nexport type PlaywrightStatus =\n | \"passed\"\n | \"failed\"\n | \"skipped\"\n | \"timedOut\"\n | \"interrupted\";\n\n/** Playwright test error */\nexport interface PlaywrightError {\n message?: string;\n stack?: string;\n}\n\n/** Playwright attachment */\nexport interface PlaywrightAttachment {\n name: string;\n contentType: string;\n path?: string;\n body?: Buffer;\n}\n\n/** Playwright test result */\nexport interface PlaywrightTestResult {\n status: PlaywrightStatus;\n duration: number;\n errors: PlaywrightError[];\n attachments: PlaywrightAttachment[];\n retry: number;\n /** Optional step events if caller captures Playwright step timing. */\n stepEvents?: Array<{\n index?: number;\n stepId?: string;\n title?: string;\n status?: RawStatus;\n durationMs?: number;\n errorMessage?: string;\n }>;\n}\n\n/** Playwright test case annotation */\nexport interface PlaywrightAnnotation {\n type: string;\n description?: string;\n}\n\n/** Playwright test location */\nexport interface PlaywrightLocation {\n file: string;\n line: number;\n column: number;\n}\n\n/** Playwright test case shape (minimal) */\nexport interface PlaywrightTestCase {\n title: string;\n titlePath: () => string[];\n annotations: PlaywrightAnnotation[];\n location: PlaywrightLocation;\n retries: number;\n}\n\n/** Options for Playwright adapter */\nexport interface PlaywrightAdapterOptions {\n /** Project root directory */\n projectRoot?: string;\n /** Package version */\n packageVersion?: string;\n /** Git SHA */\n gitSha?: string;\n /** Start time (epoch ms) */\n startedAtMs?: number;\n /** Playwright project name */\n projectName?: string;\n}\n\n/**\n * Map Playwright status to RawStatus.\n */\nfunction mapPlaywrightStatus(status: PlaywrightStatus): RawStatus {\n switch (status) {\n case \"passed\":\n return \"pass\";\n case \"failed\":\n return \"fail\";\n case \"skipped\":\n return \"skip\";\n case \"timedOut\":\n return \"timeout\";\n case \"interrupted\":\n return \"interrupted\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Adapt Playwright test results to RawRun.\n *\n * @param testResults - Array of [testCase, result] tuples\n * @param options - Adapter options\n * @returns RawRun for ACL processing\n */\nexport function adaptPlaywrightRun(\n testResults: Array<[PlaywrightTestCase, PlaywrightTestResult]>,\n options: PlaywrightAdapterOptions = {}\n): RawRun {\n const testCases: RawTestCase[] = [];\n const projectRoot = options.projectRoot ?? process.cwd();\n\n for (const [test, result] of testResults) {\n // Find story-meta annotation\n const storyAnnotation = test.annotations.find((a) => a.type === \"story-meta\");\n if (!storyAnnotation?.description) continue;\n\n let story: StoryMeta;\n try {\n story = JSON.parse(storyAnnotation.description);\n } catch {\n continue; // Skip if annotation is not valid JSON\n }\n\n if (!story?.scenario || !Array.isArray(story.steps)) continue;\n\n // Convert attachments\n const attachments = convertAttachments(result.attachments);\n\n // Get error info\n const error = result.errors?.length\n ? {\n message: result.errors[0].message,\n stack: result.errors[0].stack,\n }\n : undefined;\n\n const stepEvents =\n result.stepEvents?.length\n ? result.stepEvents\n : story.steps\n .map((step, index) =>\n step.durationMs !== undefined\n ? {\n index,\n stepId: step.id,\n title: step.text,\n durationMs: step.durationMs,\n }\n : undefined,\n )\n .filter((e): e is NonNullable<typeof e> => e !== undefined);\n\n testCases.push({\n externalId: test.titlePath().join(\" > \"),\n title: story.scenario,\n titlePath: test.titlePath(),\n story,\n sourceFile: test.location.file,\n sourceLine: test.location.line,\n status: mapPlaywrightStatus(result.status),\n durationMs: result.duration,\n error,\n stepEvents: stepEvents.length > 0 ? stepEvents : undefined,\n attachments,\n meta: {\n playwrightStatus: result.status,\n column: test.location.column,\n },\n retry: result.retry,\n retries: test.retries,\n projectName: options.projectName,\n });\n }\n\n return {\n testCases,\n startedAtMs: options.startedAtMs,\n finishedAtMs: Date.now(),\n projectRoot,\n packageVersion: options.packageVersion,\n gitSha: options.gitSha,\n ci: detectCI(),\n };\n}\n\n/**\n * Convert Playwright attachments to raw attachments.\n */\nfunction convertAttachments(\n attachments: PlaywrightAttachment[]\n): RawAttachment[] {\n return attachments.map((att) => ({\n name: att.name,\n mediaType: att.contentType,\n path: att.path,\n body: att.body ? att.body.toString(\"base64\") : undefined,\n encoding: att.body ? \"BASE64\" as const : undefined,\n byteLength: att.body?.length,\n }));\n}\n\n/**\n * Detect CI environment.\n */\nfunction detectCI() {\n if (process.env.GITHUB_ACTIONS === \"true\") {\n return {\n name: \"GitHub Actions\",\n url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY\n ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`\n : undefined,\n buildNumber: process.env.GITHUB_RUN_NUMBER,\n };\n }\n\n if (process.env.JENKINS_URL) {\n return {\n name: \"Jenkins\",\n url: process.env.BUILD_URL,\n buildNumber: process.env.BUILD_NUMBER,\n };\n }\n\n if (process.env.CI) {\n return {\n name: \"CI\",\n url: undefined,\n buildNumber: undefined,\n };\n }\n\n return undefined;\n}\n"],"mappings":"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","names":["detectCI","detectCI"]}