executable-stories-vitest 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/reporter.ts"],"sourcesContent":["/**\n * Vitest reporter that reads task.meta.story from tests and writes reports\n * using the executable-stories-formatters package.\n *\n * Do not add value imports from \"vitest\" or \"./story-api.js\" here; this entry is loaded in vitest.config\n * before Vitest is ready. Use only `import type` from those modules.\n */\nimport type {\n Reporter,\n SerializedError,\n TestModule,\n TestCase,\n TestRunEndReason,\n Vitest,\n} from \"vitest/node\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { StoryMeta } from \"./types\";\n\n// Import from formatters package\nimport {\n ReportGenerator,\n canonicalizeRun,\n readGitSha,\n readPackageVersion,\n detectCI,\n type RawRun,\n type RawTestCase,\n type RawAttachment,\n type RawStepEvent,\n type FormatterOptions,\n type CoverageSummary,\n} from \"executable-stories-formatters\";\n\n// Re-export types from formatters for convenience\nexport type {\n OutputFormat,\n OutputMode,\n ColocatedStyle,\n OutputRule,\n FormatterOptions,\n} from \"executable-stories-formatters\";\n\n// ============================================================================\n// Reporter Options (delegates to FormatterOptions)\n// ============================================================================\n\nexport interface StoryReporterOptions extends FormatterOptions {\n /** When GITHUB_ACTIONS, append report to job summary via @actions/core. Default: true */\n enableGithubActionsSummary?: boolean;\n /** If set, write raw run JSON (schemaVersion 1) to this path for use with the executable-stories CLI/binary */\n rawRunPath?: string;\n}\n\n// ============================================================================\n// Coverage Types\n// ============================================================================\n\ntype CoverageMetric = { total: number; covered: number; pct: number };\ntype CoverageData = {\n statements: CoverageMetric;\n branches: CoverageMetric;\n functions: CoverageMetric;\n lines?: CoverageMetric;\n};\ntype CoverageFile = {\n s: Record<string, number>;\n f: Record<string, number>;\n b: Record<string, number[]>;\n l?: Record<string, number>;\n};\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Normalize Vitest onCoverage payload to coverage data.\n */\nfunction normalizeCoveragePayload(\n coverage: unknown\n): Record<string, CoverageFile> | undefined {\n if (!coverage || typeof coverage !== \"object\" || Array.isArray(coverage))\n return undefined;\n const raw = coverage as Record<string, unknown>;\n const data: Record<string, CoverageFile> = {};\n for (const [filePath, file] of Object.entries(raw)) {\n if (\n file &&\n typeof file === \"object\" &&\n \"s\" in file &&\n \"f\" in file &&\n \"b\" in file\n ) {\n data[filePath] = file as CoverageFile;\n }\n }\n if (Object.keys(data).length === 0) return undefined;\n return data;\n}\n\n/**\n * Summarize coverage data.\n */\nfunction summarizeCoverage(\n data: Record<string, CoverageFile>\n): CoverageData | undefined {\n let statementsTotal = 0;\n let statementsCovered = 0;\n let functionsTotal = 0;\n let functionsCovered = 0;\n let branchesTotal = 0;\n let branchesCovered = 0;\n let linesTotal = 0;\n let linesCovered = 0;\n let hasLines = false;\n\n for (const file of Object.values(data)) {\n for (const count of Object.values(file.s)) {\n statementsTotal += 1;\n if (count > 0) statementsCovered += 1;\n }\n for (const count of Object.values(file.f)) {\n functionsTotal += 1;\n if (count > 0) functionsCovered += 1;\n }\n for (const counts of Object.values(file.b)) {\n for (const count of counts) {\n branchesTotal += 1;\n if (count > 0) branchesCovered += 1;\n }\n }\n if (file.l) {\n hasLines = true;\n for (const count of Object.values(file.l)) {\n linesTotal += 1;\n if (count > 0) linesCovered += 1;\n }\n }\n }\n\n if (\n statementsTotal === 0 &&\n functionsTotal === 0 &&\n branchesTotal === 0 &&\n !hasLines\n ) {\n return undefined;\n }\n\n const metric = (covered: number, total: number): CoverageMetric => ({\n total,\n covered,\n pct: total === 0 ? 100 : Math.round((covered / total) * 100),\n });\n\n const summary: CoverageData = {\n statements: metric(statementsCovered, statementsTotal),\n branches: metric(branchesCovered, branchesTotal),\n functions: metric(functionsCovered, functionsTotal),\n };\n if (hasLines) {\n summary.lines = metric(linesCovered, linesTotal);\n }\n return summary;\n}\n\n/**\n * Convert internal coverage data to formatters CoverageSummary.\n */\nfunction toCoverageSummary(\n data: CoverageData | undefined\n): CoverageSummary | undefined {\n if (!data) return undefined;\n return {\n statementsPct: data.statements.pct,\n branchesPct: data.branches.pct,\n functionsPct: data.functions.pct,\n linesPct: data.lines?.pct,\n };\n}\n\n/**\n * Convert path to relative posix format.\n */\nfunction toRelativePosix(absolutePath: string, projectRoot: string): string {\n return path.relative(projectRoot, absolutePath).split(path.sep).join(\"/\");\n}\n\n// ============================================================================\n// Reporter Implementation\n// ============================================================================\n\n/**\n * Vitest reporter that generates reports using executable-stories-formatters.\n *\n * Reads `task.meta.story` from each test and generates reports in configured formats.\n * Supports output routing (aggregated/colocated) and multiple output formats.\n */\nexport default class StoryReporter implements Reporter {\n private options: StoryReporterOptions;\n private ctx: Vitest | undefined;\n private startTime: number = 0;\n private packageVersion: string | undefined;\n private gitSha: string | undefined;\n private coverageData: CoverageData | undefined;\n\n constructor(options: StoryReporterOptions = {}) {\n this.options = options;\n }\n\n onInit(ctx: Vitest): void {\n this.ctx = ctx;\n this.startTime = Date.now();\n const root = ctx.config?.root ?? process.cwd();\n\n // Read metadata if needed\n const includeMetadata = this.options.markdown?.includeMetadata ?? true;\n if (includeMetadata) {\n this.packageVersion = readPackageVersion(root);\n this.gitSha = readGitSha(root);\n }\n }\n\n onCoverage(coverage: unknown): void {\n const data = normalizeCoveragePayload(coverage);\n if (data) {\n this.coverageData = summarizeCoverage(data);\n }\n }\n\n async onTestRunEnd(\n testModules: ReadonlyArray<TestModule>,\n _unhandledErrors: ReadonlyArray<SerializedError>,\n reason: TestRunEndReason\n ): Promise<void> {\n if (reason === \"interrupted\") return;\n\n const root = this.ctx?.config?.root ?? process.cwd();\n\n // Collect test cases\n const rawTestCases = this.collectTestCases(testModules, root);\n\n // Build RawRun\n const rawRun: RawRun = {\n testCases: rawTestCases,\n startedAtMs: this.startTime,\n finishedAtMs: Date.now(),\n projectRoot: root,\n packageVersion: this.packageVersion,\n gitSha: this.gitSha,\n ci: detectCI(),\n };\n\n // Optionally write raw run JSON for CLI/binary consumption\n const rawRunPath = this.options.rawRunPath;\n if (rawRunPath) {\n const absolutePath = path.isAbsolute(rawRunPath)\n ? rawRunPath\n : path.join(root, rawRunPath);\n const dir = path.dirname(absolutePath);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n const payload = { schemaVersion: 1, ...rawRun };\n fs.writeFileSync(absolutePath, JSON.stringify(payload, null, 2), \"utf8\");\n }\n\n // Canonicalize\n const canonicalRun = canonicalizeRun(rawRun);\n\n // Add coverage if available\n if (this.coverageData) {\n canonicalRun.coverage = toCoverageSummary(this.coverageData);\n }\n\n // Generate reports\n const generator = new ReportGenerator(this.options);\n try {\n const results = await generator.generate(canonicalRun);\n\n // Append to GitHub Actions summary if enabled\n const enableGithubSummary = this.options.enableGithubActionsSummary ?? true;\n if (process.env.GITHUB_ACTIONS === \"true\" && enableGithubSummary) {\n const markdownPaths = results.get(\"markdown\") ?? [];\n if (markdownPaths.length > 0) {\n const firstPath = markdownPaths[0];\n const content = fs.readFileSync(firstPath, \"utf8\");\n await this.appendGithubSummary(content).catch(() => {});\n }\n }\n } catch (err) {\n console.error(\"Failed to generate reports:\", err);\n }\n }\n\n /**\n * Collect test cases from Vitest test modules.\n */\n private collectTestCases(\n testModules: ReadonlyArray<TestModule>,\n root: string\n ): RawTestCase[] {\n const testCases: RawTestCase[] = [];\n\n for (const mod of testModules) {\n const collection = mod.children;\n if (!collection) continue;\n\n const moduleId =\n mod.moduleId ??\n (mod as { relativeModuleId?: string }).relativeModuleId ??\n \"\";\n const absoluteModuleId = path.isAbsolute(moduleId)\n ? moduleId\n : path.resolve(root, moduleId);\n const sourceFile = toRelativePosix(absoluteModuleId, root);\n\n for (const test of collection.allTests()) {\n const meta = this.getStoryMeta(test);\n if (!meta?.scenario || !Array.isArray(meta.steps)) continue;\n\n const result = test.result?.();\n const state = result?.state ?? \"pending\";\n const durationMs =\n typeof (result as { duration?: number } | undefined)?.duration ===\n \"number\"\n ? (result as unknown as { duration: number }).duration\n : 0;\n\n // Get error details\n let errorMessage: string | undefined;\n let errorStack: string | undefined;\n if (state === \"failed\" && result) {\n const errors = (result as { errors?: SerializedError[] }).errors;\n if (errors?.length) {\n const err = errors[0];\n errorMessage = err.message;\n errorStack = err.stack;\n }\n }\n\n // Map Vitest state to raw status\n const statusMap: Record<string, string> = {\n passed: \"pass\",\n failed: \"fail\",\n skipped: \"skip\",\n pending: \"pending\",\n todo: \"pending\",\n };\n\n // Extract attachments from task.meta.storyAttachments\n const taskMeta = test.meta() as Record<string, unknown>;\n const scopedAttachments = (taskMeta?.storyAttachments ?? []) as Array<{\n name: string;\n mediaType: string;\n path?: string;\n body?: string;\n encoding?: \"BASE64\" | \"IDENTITY\";\n charset?: string;\n fileName?: string;\n stepIndex?: number;\n stepId?: string;\n }>;\n const attachments: RawAttachment[] = scopedAttachments.map((a) => ({\n name: a.name,\n mediaType: a.mediaType,\n path: a.path,\n body: a.body,\n encoding: a.encoding,\n charset: a.charset,\n fileName: a.fileName,\n stepIndex: a.stepIndex,\n stepId: a.stepId,\n }));\n\n // Extract step events (timing) from story steps\n const stepEvents: RawStepEvent[] = meta.steps\n .filter((s: { durationMs?: number }) => s.durationMs !== undefined)\n .map((s: { durationMs?: number }, i: number) => ({\n index: i,\n title: (s as { text: string }).text,\n durationMs: s.durationMs,\n }));\n\n // Retry info from Vitest result\n const retryCount = (result as { retryCount?: number } | undefined)?.retryCount ?? 0;\n\n testCases.push({\n title: meta.scenario,\n titlePath: meta.suitePath\n ? [...meta.suitePath, meta.scenario]\n : [meta.scenario],\n story: meta,\n sourceFile,\n sourceLine: Math.max(1, meta.sourceOrder ?? 1),\n status: (statusMap[state] ?? \"unknown\") as RawTestCase[\"status\"],\n durationMs,\n error: errorMessage\n ? { message: errorMessage, stack: errorStack }\n : undefined,\n attachments: attachments.length > 0 ? attachments : undefined,\n stepEvents: stepEvents.length > 0 ? stepEvents : undefined,\n retry: retryCount,\n retries: 0,\n });\n }\n }\n\n return testCases;\n }\n\n private getStoryMeta(test: TestCase): StoryMeta | undefined {\n const meta = test.meta() as Record<string, unknown>;\n return meta?.[\"story\"] as StoryMeta | undefined;\n }\n\n private async appendGithubSummary(reportText: string): Promise<void> {\n try {\n const { summary } = await import(\"@actions/core\");\n summary.addRaw(reportText);\n await summary.write();\n } catch {\n // @actions/core not available or not in Actions\n }\n }\n}\n\nexport { StoryReporter };\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "executable-stories-vitest",
3
+ "version": "2.0.0",
4
+ "description": "TS-first story/given/when/then helpers for Vitest with Markdown user-story doc generation.",
5
+ "author": "Jag Reehal <jag@jagreehal.com>",
6
+ "homepage": "https://github.com/jagreehal/executable-stories#readme",
7
+ "bugs": {
8
+ "url": "https://github.com/jagreehal/executable-stories/issues"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/jagreehal/executable-stories.git"
13
+ },
14
+ "license": "MIT",
15
+ "type": "module",
16
+ "main": "./dist/index.cjs",
17
+ "module": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "sideEffects": false,
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js",
24
+ "require": "./dist/index.cjs"
25
+ },
26
+ "./reporter": {
27
+ "types": "./dist/reporter.d.ts",
28
+ "import": "./dist/reporter.js",
29
+ "require": "./dist/reporter.cjs"
30
+ }
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "README.md"
35
+ ],
36
+ "peerDependencies": {
37
+ "vitest": ">=4.0.18"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^25.2.1",
41
+ "@types/picomatch": "^4.0.2",
42
+ "eslint-config-executable-stories": "workspace:*",
43
+ "tsup": "^8.5.1",
44
+ "typescript": "^5.9.3",
45
+ "vitest": "^4.0.18"
46
+ },
47
+ "keywords": [
48
+ "vitest",
49
+ "bdd",
50
+ "gherkin",
51
+ "user-story",
52
+ "markdown",
53
+ "confluence",
54
+ "scenario",
55
+ "given",
56
+ "when",
57
+ "then"
58
+ ],
59
+ "scripts": {
60
+ "build": "tsup",
61
+ "type-check": "tsc --noEmit",
62
+ "lint": "eslint .",
63
+ "clean": "rm -rf dist",
64
+ "test": "vitest run",
65
+ "quality": "pnpm type-check && pnpm test && pnpm lint"
66
+ },
67
+ "dependencies": {
68
+ "executable-stories-formatters": "workspace:*",
69
+ "fast-glob": "^3.3.3",
70
+ "picomatch": "^4.0.3"
71
+ }
72
+ }