executable-stories-formatters 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,205 @@
1
+ # executable-stories-formatters
2
+
3
+ Cucumber-compatible report formats (HTML, Markdown, JUnit XML, Cucumber JSON) for executable-stories test results.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install executable-stories-formatters
9
+ ```
10
+
11
+ ## Quick Start — Programmatic API
12
+
13
+ ```ts
14
+ import {
15
+ canonicalizeRun,
16
+ ReportGenerator,
17
+ } from "executable-stories-formatters";
18
+ import type { RawRun } from "executable-stories-formatters";
19
+
20
+ // 1. Build a RawRun from your test framework (or use a built-in adapter)
21
+ const raw: RawRun = {
22
+ projectRoot: process.cwd(),
23
+ testCases: [
24
+ {
25
+ status: "pass",
26
+ story: {
27
+ scenario: "User logs in",
28
+ steps: [
29
+ { keyword: "Given", text: "the user is on the login page" },
30
+ { keyword: "When", text: "they enter valid credentials" },
31
+ { keyword: "Then", text: "they see the dashboard" },
32
+ ],
33
+ },
34
+ },
35
+ ],
36
+ };
37
+
38
+ // 2. Canonicalize the raw run
39
+ const run = canonicalizeRun(raw);
40
+
41
+ // 3. Generate reports
42
+ const generator = new ReportGenerator({
43
+ formats: ["html", "markdown"],
44
+ outputDir: "reports",
45
+ });
46
+ const results = await generator.generate(run);
47
+ // results: Map<"html" | "markdown", string[]> (file paths written)
48
+ ```
49
+
50
+ ## Quick Start — CLI
51
+
52
+ ```bash
53
+ # Generate an HTML report from a JSON run file
54
+ executable-stories format run.json --format html
55
+
56
+ # Generate multiple formats
57
+ executable-stories format run.json --format html --format markdown
58
+
59
+ # Validate a run file against the schema
60
+ executable-stories validate run.json
61
+
62
+ # Include only test cases from matching source files (glob patterns)
63
+ executable-stories format raw-run.json --include "**/*.Story*.cs" --format html
64
+
65
+ # Exclude test cases by source file glob
66
+ executable-stories format raw-run.json --exclude "**/obj/**" --format markdown
67
+ ```
68
+
69
+ ### Filtering by source file
70
+
71
+ You can limit which test cases appear in reports using **include** and **exclude** glob patterns on `sourceFile`:
72
+
73
+ - **`--include <globs>`** — Comma-separated globs; only test cases whose `sourceFile` matches at least one pattern are included. If omitted, all test cases are considered.
74
+ - **`--exclude <globs>`** — Comma-separated globs; test cases whose `sourceFile` matches any pattern are excluded. Applied after include.
75
+
76
+ Patterns use the same glob semantics as output rules (`*` and `**`). Paths are normalized to forward slashes. This works with any framework that sets `sourceFile` on raw test cases (Jest, Vitest, Playwright, xUnit, etc.).
77
+
78
+ Programmatic API:
79
+
80
+ ```ts
81
+ const generator = new ReportGenerator({
82
+ include: ["**/auth/**", "**/*.Story*.cs"],
83
+ exclude: ["**/Generated/**"],
84
+ formats: ["html", "markdown"],
85
+ outputDir: "reports",
86
+ });
87
+ ```
88
+
89
+ ## Architecture
90
+
91
+ ```
92
+ ┌──────────────────────────┐
93
+ │ Framework Test Results │
94
+ │ (Jest / Vitest / PW) │
95
+ └───────────┬──────────────┘
96
+
97
+
98
+ ┌──────────────────────────┐
99
+ │ Layer 1: Adapters │ RawRun
100
+ │ adaptJestRun() │
101
+ │ adaptVitestRun() │
102
+ │ adaptPlaywrightRun() │
103
+ └───────────┬──────────────┘
104
+
105
+
106
+ ┌──────────────────────────┐
107
+ │ Layer 2: ACL │ TestRunResult
108
+ │ canonicalizeRun() │
109
+ └───────────┬──────────────┘
110
+
111
+
112
+ ┌──────────────────────────┐
113
+ │ Layer 3: Formatters │ HTML / Markdown / JUnit / Cucumber JSON
114
+ │ ReportGenerator │
115
+ └──────────────────────────┘
116
+ ```
117
+
118
+ ## Output Formats
119
+
120
+ | Format | Description | File Extension |
121
+ | --- | --- | --- |
122
+ | `html` | Interactive HTML report with search and screenshots | `.html` |
123
+ | `markdown` | Markdown user-story documentation | `.md` |
124
+ | `junit` | JUnit XML for CI integration | `.junit.xml` |
125
+ | `cucumber-json` | Cucumber JSON for tooling compatibility | `.cucumber.json` |
126
+
127
+ ## Writing a Custom Adapter
128
+
129
+ To integrate a new test framework, build a `RawRun` object from your framework's results, then pass it through `canonicalizeRun()`.
130
+
131
+ ### `RawRun` Interface
132
+
133
+ ```ts
134
+ interface RawRun {
135
+ testCases: RawTestCase[];
136
+ startedAtMs?: number; // Run start time (epoch ms)
137
+ finishedAtMs?: number; // Run finish time (epoch ms)
138
+ projectRoot: string; // Project root directory
139
+ packageVersion?: string; // Package version
140
+ gitSha?: string; // Git commit SHA
141
+ ci?: RawCIInfo; // CI environment info
142
+ }
143
+ ```
144
+
145
+ ### `RawTestCase` Interface
146
+
147
+ ```ts
148
+ interface RawTestCase {
149
+ status: RawStatus; // "pass" | "fail" | "skip" | "todo" | "pending" | "timeout" | "interrupted" | "unknown"
150
+ story?: StoryMeta; // Story metadata from test (from executable-stories-core)
151
+ externalId?: string; // Framework's test ID
152
+ title?: string; // Test title/name
153
+ titlePath?: string[]; // Full title path (describe blocks + test name)
154
+ sourceFile?: string; // Source file path
155
+ sourceLine?: number; // Source line number (1-based)
156
+ durationMs?: number; // Duration in milliseconds
157
+ error?: { // Error information
158
+ message?: string;
159
+ stack?: string;
160
+ };
161
+ stepEvents?: RawStepEvent[]; // Step-level info if framework provides it
162
+ attachments?: RawAttachment[]; // Screenshots, logs, etc.
163
+ retry?: number; // Retry attempt number (0-based)
164
+ retries?: number; // Total retry count configured
165
+ projectName?: string; // Playwright project name
166
+ meta?: Record<string, unknown>; // Framework-specific metadata
167
+ }
168
+ ```
169
+
170
+ ## API Reference
171
+
172
+ ### Core
173
+
174
+ - `canonicalizeRun(raw, options?)` — Normalize a `RawRun` into a canonical `TestRunResult`
175
+ - `validateCanonicalRun(run)` — Validate a canonical run, returning errors
176
+ - `assertValidRun(run)` — Validate and throw on invalid data
177
+ - `ReportGenerator` — High-level report generator combining all formatters
178
+ - `createReportGenerator(options?, deps?)` — Factory for `ReportGenerator`
179
+
180
+ ### Formatters
181
+
182
+ - `CucumberJsonFormatter` — Cucumber JSON output
183
+ - `HtmlFormatter` — Interactive HTML report
184
+ - `JUnitFormatter` — JUnit XML output
185
+ - `MarkdownFormatter` — Markdown documentation
186
+
187
+ ### Built-in Adapters
188
+
189
+ - `adaptJestRun(results, storyReports, options?)` — Convert Jest results to `RawRun`
190
+ - `adaptVitestRun(testModules, options?)` — Convert Vitest results to `RawRun`
191
+ - `adaptPlaywrightRun(testResults, options?)` — Convert Playwright results to `RawRun`
192
+
193
+ ### Convenience Functions
194
+
195
+ - `normalizeJestResults(...)` — `adaptJestRun` + `canonicalizeRun` in one call
196
+ - `normalizeVitestResults(...)` — `adaptVitestRun` + `canonicalizeRun` in one call
197
+ - `normalizePlaywrightResults(...)` — `adaptPlaywrightRun` + `canonicalizeRun` in one call
198
+
199
+ ### Types
200
+
201
+ See the TypeScript type exports for `TestRunResult`, `RawRun`, `RawTestCase`, `FormatterOptions`, and more. `FormatterOptions` supports `include` and `exclude` (string arrays of glob patterns) to filter test cases by `sourceFile` before generating reports.
202
+
203
+ ## License
204
+
205
+ MIT
@@ -0,0 +1,324 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/converters/adapters/index.ts
21
+ var adapters_exports = {};
22
+ __export(adapters_exports, {
23
+ adaptJestRun: () => adaptJestRun,
24
+ adaptPlaywrightRun: () => adaptPlaywrightRun,
25
+ adaptVitestRun: () => adaptVitestRun
26
+ });
27
+ module.exports = __toCommonJS(adapters_exports);
28
+
29
+ // src/converters/adapters/jest.ts
30
+ function mapJestStatus(status) {
31
+ switch (status) {
32
+ case "passed":
33
+ return "pass";
34
+ case "failed":
35
+ return "fail";
36
+ case "pending":
37
+ return "pending";
38
+ case "todo":
39
+ return "todo";
40
+ default:
41
+ return "unknown";
42
+ }
43
+ }
44
+ function adaptJestRun(jestResults, storyReports, options = {}) {
45
+ const testCases = [];
46
+ const fileResultsMap = /* @__PURE__ */ new Map();
47
+ for (const fileResult of jestResults.testResults) {
48
+ fileResultsMap.set(fileResult.testFilePath, fileResult);
49
+ }
50
+ for (const report of storyReports) {
51
+ const fileResult = fileResultsMap.get(report.testFilePath);
52
+ for (const meta of report.scenarios) {
53
+ if (!meta?.scenario) continue;
54
+ const matchingTest = findMatchingJestTest(fileResult, meta);
55
+ testCases.push({
56
+ externalId: matchingTest?.fullName,
57
+ title: meta.scenario,
58
+ titlePath: meta.suitePath ? [...meta.suitePath, meta.scenario] : [meta.scenario],
59
+ story: meta,
60
+ sourceFile: report.testFilePath,
61
+ sourceLine: void 0,
62
+ // Jest doesn't provide line numbers
63
+ status: matchingTest ? mapJestStatus(matchingTest.status) : "unknown",
64
+ durationMs: matchingTest?.duration,
65
+ error: matchingTest?.failureMessages?.length ? { message: matchingTest.failureMessages.join("\n") } : void 0,
66
+ stepEvents: void 0,
67
+ // Jest doesn't provide step-level results
68
+ attachments: void 0,
69
+ // Jest doesn't capture attachments
70
+ meta: { jestStatus: matchingTest?.status },
71
+ retry: 0,
72
+ retries: 0,
73
+ projectName: void 0
74
+ });
75
+ }
76
+ }
77
+ return {
78
+ testCases,
79
+ startedAtMs: jestResults.startTime,
80
+ finishedAtMs: Date.now(),
81
+ projectRoot: options.projectRoot ?? process.cwd(),
82
+ packageVersion: options.packageVersion,
83
+ gitSha: options.gitSha,
84
+ ci: detectCI()
85
+ };
86
+ }
87
+ function findMatchingJestTest(fileResult, meta) {
88
+ if (!fileResult) return void 0;
89
+ const expectedFullName = meta.suitePath ? [...meta.suitePath, meta.scenario].join(" > ") : meta.scenario;
90
+ return fileResult.testResults.find((test) => test.fullName === expectedFullName);
91
+ }
92
+ function detectCI() {
93
+ if (process.env.GITHUB_ACTIONS === "true") {
94
+ return {
95
+ name: "GitHub Actions",
96
+ url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}` : void 0,
97
+ buildNumber: process.env.GITHUB_RUN_NUMBER
98
+ };
99
+ }
100
+ if (process.env.JENKINS_URL) {
101
+ return {
102
+ name: "Jenkins",
103
+ url: process.env.BUILD_URL,
104
+ buildNumber: process.env.BUILD_NUMBER
105
+ };
106
+ }
107
+ if (process.env.CI) {
108
+ return {
109
+ name: "CI",
110
+ url: void 0,
111
+ buildNumber: void 0
112
+ };
113
+ }
114
+ return void 0;
115
+ }
116
+
117
+ // src/converters/adapters/vitest.ts
118
+ function mapVitestStatus(state) {
119
+ switch (state) {
120
+ case "passed":
121
+ return "pass";
122
+ case "failed":
123
+ return "fail";
124
+ case "skipped":
125
+ return "skip";
126
+ case "pending":
127
+ return "pending";
128
+ default:
129
+ return "unknown";
130
+ }
131
+ }
132
+ function adaptVitestRun(testModules, options = {}) {
133
+ const testCases = [];
134
+ const projectRoot = options.projectRoot ?? process.cwd();
135
+ for (const mod of testModules) {
136
+ const collection = mod.children;
137
+ if (!collection) continue;
138
+ const moduleId = mod.moduleId ?? mod.relativeModuleId ?? "";
139
+ const sourcePath = moduleId.startsWith("/") ? moduleId : `${projectRoot}/${moduleId}`;
140
+ for (const test of collection.allTests()) {
141
+ const meta = test.meta();
142
+ const story = meta?.["story"];
143
+ if (!story?.scenario || !Array.isArray(story.steps)) continue;
144
+ const result = test.result();
145
+ const state = result?.state;
146
+ const errors = state === "failed" && result ? result.errors : void 0;
147
+ testCases.push({
148
+ externalId: test.name,
149
+ title: story.scenario,
150
+ titlePath: story.suitePath ? [...story.suitePath, story.scenario] : [story.scenario],
151
+ story,
152
+ sourceFile: sourcePath,
153
+ sourceLine: void 0,
154
+ // Vitest doesn't provide line numbers easily
155
+ status: mapVitestStatus(state),
156
+ durationMs: result?.duration,
157
+ error: errors?.length ? {
158
+ message: formatVitestError(errors[0]),
159
+ stack: errors[0].stack
160
+ } : void 0,
161
+ stepEvents: void 0,
162
+ // Vitest doesn't provide step-level results
163
+ attachments: void 0,
164
+ // Vitest doesn't capture attachments
165
+ meta: { vitestState: state },
166
+ retry: 0,
167
+ retries: 0,
168
+ projectName: void 0
169
+ });
170
+ }
171
+ }
172
+ return {
173
+ testCases,
174
+ startedAtMs: options.startedAtMs,
175
+ finishedAtMs: Date.now(),
176
+ projectRoot,
177
+ packageVersion: options.packageVersion,
178
+ gitSha: options.gitSha,
179
+ ci: detectCI2()
180
+ };
181
+ }
182
+ function formatVitestError(error) {
183
+ const parts = [];
184
+ if (error.message) {
185
+ parts.push(error.message);
186
+ }
187
+ if (error.diff) {
188
+ parts.push("", error.diff);
189
+ }
190
+ return parts.join("\n") || "Unknown error";
191
+ }
192
+ function detectCI2() {
193
+ if (process.env.GITHUB_ACTIONS === "true") {
194
+ return {
195
+ name: "GitHub Actions",
196
+ url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}` : void 0,
197
+ buildNumber: process.env.GITHUB_RUN_NUMBER
198
+ };
199
+ }
200
+ if (process.env.JENKINS_URL) {
201
+ return {
202
+ name: "Jenkins",
203
+ url: process.env.BUILD_URL,
204
+ buildNumber: process.env.BUILD_NUMBER
205
+ };
206
+ }
207
+ if (process.env.CI) {
208
+ return {
209
+ name: "CI",
210
+ url: void 0,
211
+ buildNumber: void 0
212
+ };
213
+ }
214
+ return void 0;
215
+ }
216
+
217
+ // src/converters/adapters/playwright.ts
218
+ function mapPlaywrightStatus(status) {
219
+ switch (status) {
220
+ case "passed":
221
+ return "pass";
222
+ case "failed":
223
+ return "fail";
224
+ case "skipped":
225
+ return "skip";
226
+ case "timedOut":
227
+ return "timeout";
228
+ case "interrupted":
229
+ return "interrupted";
230
+ default:
231
+ return "unknown";
232
+ }
233
+ }
234
+ function adaptPlaywrightRun(testResults, options = {}) {
235
+ const testCases = [];
236
+ const projectRoot = options.projectRoot ?? process.cwd();
237
+ for (const [test, result] of testResults) {
238
+ const storyAnnotation = test.annotations.find((a) => a.type === "story-meta");
239
+ if (!storyAnnotation?.description) continue;
240
+ let story;
241
+ try {
242
+ story = JSON.parse(storyAnnotation.description);
243
+ } catch {
244
+ continue;
245
+ }
246
+ if (!story?.scenario || !Array.isArray(story.steps)) continue;
247
+ const attachments = convertAttachments(result.attachments);
248
+ const error = result.errors?.length ? {
249
+ message: result.errors[0].message,
250
+ stack: result.errors[0].stack
251
+ } : void 0;
252
+ testCases.push({
253
+ externalId: test.titlePath().join(" > "),
254
+ title: story.scenario,
255
+ titlePath: test.titlePath(),
256
+ story,
257
+ sourceFile: test.location.file,
258
+ sourceLine: test.location.line,
259
+ status: mapPlaywrightStatus(result.status),
260
+ durationMs: result.duration,
261
+ error,
262
+ stepEvents: void 0,
263
+ // Playwright could provide step info, but we don't capture it yet
264
+ attachments,
265
+ meta: {
266
+ playwrightStatus: result.status,
267
+ column: test.location.column
268
+ },
269
+ retry: result.retry,
270
+ retries: test.retries,
271
+ projectName: options.projectName
272
+ });
273
+ }
274
+ return {
275
+ testCases,
276
+ startedAtMs: options.startedAtMs,
277
+ finishedAtMs: Date.now(),
278
+ projectRoot,
279
+ packageVersion: options.packageVersion,
280
+ gitSha: options.gitSha,
281
+ ci: detectCI3()
282
+ };
283
+ }
284
+ function convertAttachments(attachments) {
285
+ return attachments.map((att) => ({
286
+ name: att.name,
287
+ mediaType: att.contentType,
288
+ path: att.path,
289
+ body: att.body ? att.body.toString("base64") : void 0,
290
+ encoding: att.body ? "BASE64" : void 0,
291
+ byteLength: att.body?.length
292
+ }));
293
+ }
294
+ function detectCI3() {
295
+ if (process.env.GITHUB_ACTIONS === "true") {
296
+ return {
297
+ name: "GitHub Actions",
298
+ url: process.env.GITHUB_SERVER_URL && process.env.GITHUB_REPOSITORY ? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}` : void 0,
299
+ buildNumber: process.env.GITHUB_RUN_NUMBER
300
+ };
301
+ }
302
+ if (process.env.JENKINS_URL) {
303
+ return {
304
+ name: "Jenkins",
305
+ url: process.env.BUILD_URL,
306
+ buildNumber: process.env.BUILD_NUMBER
307
+ };
308
+ }
309
+ if (process.env.CI) {
310
+ return {
311
+ name: "CI",
312
+ url: void 0,
313
+ buildNumber: void 0
314
+ };
315
+ }
316
+ return void 0;
317
+ }
318
+ // Annotate the CommonJS export names for ESM import in node:
319
+ 0 && (module.exports = {
320
+ adaptJestRun,
321
+ adaptPlaywrightRun,
322
+ adaptVitestRun
323
+ });
324
+ //# sourceMappingURL=adapters.cjs.map
@@ -0,0 +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}\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 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: undefined, // Playwright could provide step info, but we don't capture it yet\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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACgDA,SAAS,cAAc,QAA6C;AAClE,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAUO,SAAS,aACd,aACA,cACA,UAA8B,CAAC,GACvB;AACR,QAAM,YAA2B,CAAC;AAGlC,QAAM,iBAAiB,oBAAI,IAA4B;AACvD,aAAW,cAAc,YAAY,aAAa;AAChD,mBAAe,IAAI,WAAW,cAAc,UAAU;AAAA,EACxD;AAGA,aAAW,UAAU,cAAc;AACjC,UAAM,aAAa,eAAe,IAAI,OAAO,YAAY;AAEzD,eAAW,QAAQ,OAAO,WAAW;AACnC,UAAI,CAAC,MAAM,SAAU;AAGrB,YAAM,eAAe,qBAAqB,YAAY,IAAI;AAE1D,gBAAU,KAAK;AAAA,QACb,YAAY,cAAc;AAAA,QAC1B,OAAO,KAAK;AAAA,QACZ,WAAW,KAAK,YACZ,CAAC,GAAG,KAAK,WAAW,KAAK,QAAQ,IACjC,CAAC,KAAK,QAAQ;AAAA,QAClB,OAAO;AAAA,QACP,YAAY,OAAO;AAAA,QACnB,YAAY;AAAA;AAAA,QACZ,QAAQ,eAAe,cAAc,aAAa,MAAM,IAAI;AAAA,QAC5D,YAAY,cAAc;AAAA,QAC1B,OAAO,cAAc,iBAAiB,SAClC,EAAE,SAAS,aAAa,gBAAgB,KAAK,IAAI,EAAE,IACnD;AAAA,QACJ,YAAY;AAAA;AAAA,QACZ,aAAa;AAAA;AAAA,QACb,MAAM,EAAE,YAAY,cAAc,OAAO;AAAA,QACzC,OAAO;AAAA,QACP,SAAS;AAAA,QACT,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,aAAa,YAAY;AAAA,IACzB,cAAc,KAAK,IAAI;AAAA,IACvB,aAAa,QAAQ,eAAe,QAAQ,IAAI;AAAA,IAChD,gBAAgB,QAAQ;AAAA,IACxB,QAAQ,QAAQ;AAAA,IAChB,IAAI,SAAS;AAAA,EACf;AACF;AAOA,SAAS,qBACP,YACA,MAC4B;AAC5B,MAAI,CAAC,WAAY,QAAO;AAGxB,QAAM,mBAAmB,KAAK,YAC1B,CAAC,GAAG,KAAK,WAAW,KAAK,QAAQ,EAAE,KAAK,KAAK,IAC7C,KAAK;AAET,SAAO,WAAW,YAAY,KAAK,CAAC,SAAS,KAAK,aAAa,gBAAgB;AACjF;AAKA,SAAS,WAAW;AAClB,MAAI,QAAQ,IAAI,mBAAmB,QAAQ;AACzC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,KAAK,QAAQ,IAAI,qBAAqB,QAAQ,IAAI,oBAC9C,GAAG,QAAQ,IAAI,iBAAiB,IAAI,QAAQ,IAAI,iBAAiB,iBAAiB,QAAQ,IAAI,aAAa,KAC3G;AAAA,MACJ,aAAa,QAAQ,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,QAAQ,IAAI,aAAa;AAC3B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,KAAK,QAAQ,IAAI;AAAA,MACjB,aAAa,QAAQ,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,QAAQ,IAAI,IAAI;AAClB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,KAAK;AAAA,MACL,aAAa;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;;;AC1HA,SAAS,gBAAgB,OAAgC;AACvD,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AASO,SAAS,eACd,aACA,UAAgC,CAAC,GACzB;AACR,QAAM,YAA2B,CAAC;AAClC,QAAM,cAAc,QAAQ,eAAe,QAAQ,IAAI;AAEvD,aAAW,OAAO,aAAa;AAC7B,UAAM,aAAa,IAAI;AACvB,QAAI,CAAC,WAAY;AAGjB,UAAM,WAAW,IAAI,YAAY,IAAI,oBAAoB;AACzD,UAAM,aAAa,SAAS,WAAW,GAAG,IACtC,WACA,GAAG,WAAW,IAAI,QAAQ;AAE9B,eAAW,QAAQ,WAAW,SAAS,GAAG;AACxC,YAAM,OAAO,KAAK,KAAK;AACvB,YAAM,QAAQ,OAAO,OAAO;AAE5B,UAAI,CAAC,OAAO,YAAY,CAAC,MAAM,QAAQ,MAAM,KAAK,EAAG;AAErD,YAAM,SAAS,KAAK,OAAO;AAC3B,YAAM,QAAQ,QAAQ;AACtB,YAAM,SAAS,UAAU,YAAY,SAAS,OAAO,SAAS;AAE9D,gBAAU,KAAK;AAAA,QACb,YAAY,KAAK;AAAA,QACjB,OAAO,MAAM;AAAA,QACb,WAAW,MAAM,YACb,CAAC,GAAG,MAAM,WAAW,MAAM,QAAQ,IACnC,CAAC,MAAM,QAAQ;AAAA,QACnB;AAAA,QACA,YAAY;AAAA,QACZ,YAAY;AAAA;AAAA,QACZ,QAAQ,gBAAgB,KAAK;AAAA,QAC7B,YAAY,QAAQ;AAAA,QACpB,OAAO,QAAQ,SACX;AAAA,UACE,SAAS,kBAAkB,OAAO,CAAC,CAAC;AAAA,UACpC,OAAO,OAAO,CAAC,EAAE;AAAA,QACnB,IACA;AAAA,QACJ,YAAY;AAAA;AAAA,QACZ,aAAa;AAAA;AAAA,QACb,MAAM,EAAE,aAAa,MAAM;AAAA,QAC3B,OAAO;AAAA,QACP,SAAS;AAAA,QACT,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB,cAAc,KAAK,IAAI;AAAA,IACvB;AAAA,IACA,gBAAgB,QAAQ;AAAA,IACxB,QAAQ,QAAQ;AAAA,IAChB,IAAIA,UAAS;AAAA,EACf;AACF;AAKA,SAAS,kBAAkB,OAAsC;AAC/D,QAAM,QAAkB,CAAC;AAEzB,MAAI,MAAM,SAAS;AACjB,UAAM,KAAK,MAAM,OAAO;AAAA,EAC1B;AAEA,MAAI,MAAM,MAAM;AACd,UAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EAC3B;AAEA,SAAO,MAAM,KAAK,IAAI,KAAK;AAC7B;AAKA,SAASA,YAAW;AAClB,MAAI,QAAQ,IAAI,mBAAmB,QAAQ;AACzC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,KAAK,QAAQ,IAAI,qBAAqB,QAAQ,IAAI,oBAC9C,GAAG,QAAQ,IAAI,iBAAiB,IAAI,QAAQ,IAAI,iBAAiB,iBAAiB,QAAQ,IAAI,aAAa,KAC3G;AAAA,MACJ,aAAa,QAAQ,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,QAAQ,IAAI,aAAa;AAC3B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,KAAK,QAAQ,IAAI;AAAA,MACjB,aAAa,QAAQ,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,QAAQ,IAAI,IAAI;AAClB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,KAAK;AAAA,MACL,aAAa;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;;;ACjHA,SAAS,oBAAoB,QAAqC;AAChE,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AASO,SAAS,mBACd,aACA,UAAoC,CAAC,GAC7B;AACR,QAAM,YAA2B,CAAC;AAClC,QAAM,cAAc,QAAQ,eAAe,QAAQ,IAAI;AAEvD,aAAW,CAAC,MAAM,MAAM,KAAK,aAAa;AAExC,UAAM,kBAAkB,KAAK,YAAY,KAAK,CAAC,MAAM,EAAE,SAAS,YAAY;AAC5E,QAAI,CAAC,iBAAiB,YAAa;AAEnC,QAAI;AACJ,QAAI;AACF,cAAQ,KAAK,MAAM,gBAAgB,WAAW;AAAA,IAChD,QAAQ;AACN;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,YAAY,CAAC,MAAM,QAAQ,MAAM,KAAK,EAAG;AAGrD,UAAM,cAAc,mBAAmB,OAAO,WAAW;AAGzD,UAAM,QAAQ,OAAO,QAAQ,SACzB;AAAA,MACE,SAAS,OAAO,OAAO,CAAC,EAAE;AAAA,MAC1B,OAAO,OAAO,OAAO,CAAC,EAAE;AAAA,IAC1B,IACA;AAEJ,cAAU,KAAK;AAAA,MACb,YAAY,KAAK,UAAU,EAAE,KAAK,KAAK;AAAA,MACvC,OAAO,MAAM;AAAA,MACb,WAAW,KAAK,UAAU;AAAA,MAC1B;AAAA,MACA,YAAY,KAAK,SAAS;AAAA,MAC1B,YAAY,KAAK,SAAS;AAAA,MAC1B,QAAQ,oBAAoB,OAAO,MAAM;AAAA,MACzC,YAAY,OAAO;AAAA,MACnB;AAAA,MACA,YAAY;AAAA;AAAA,MACZ;AAAA,MACA,MAAM;AAAA,QACJ,kBAAkB,OAAO;AAAA,QACzB,QAAQ,KAAK,SAAS;AAAA,MACxB;AAAA,MACA,OAAO,OAAO;AAAA,MACd,SAAS,KAAK;AAAA,MACd,aAAa,QAAQ;AAAA,IACvB,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB,cAAc,KAAK,IAAI;AAAA,IACvB;AAAA,IACA,gBAAgB,QAAQ;AAAA,IACxB,QAAQ,QAAQ;AAAA,IAChB,IAAIC,UAAS;AAAA,EACf;AACF;AAKA,SAAS,mBACP,aACiB;AACjB,SAAO,YAAY,IAAI,CAAC,SAAS;AAAA,IAC/B,MAAM,IAAI;AAAA,IACV,WAAW,IAAI;AAAA,IACf,MAAM,IAAI;AAAA,IACV,MAAM,IAAI,OAAO,IAAI,KAAK,SAAS,QAAQ,IAAI;AAAA,IAC/C,UAAU,IAAI,OAAO,WAAoB;AAAA,IACzC,YAAY,IAAI,MAAM;AAAA,EACxB,EAAE;AACJ;AAKA,SAASA,YAAW;AAClB,MAAI,QAAQ,IAAI,mBAAmB,QAAQ;AACzC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,KAAK,QAAQ,IAAI,qBAAqB,QAAQ,IAAI,oBAC9C,GAAG,QAAQ,IAAI,iBAAiB,IAAI,QAAQ,IAAI,iBAAiB,iBAAiB,QAAQ,IAAI,aAAa,KAC3G;AAAA,MACJ,aAAa,QAAQ,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,QAAQ,IAAI,aAAa;AAC3B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,KAAK,QAAQ,IAAI;AAAA,MACjB,aAAa,QAAQ,IAAI;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,QAAQ,IAAI,IAAI;AAClB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,KAAK;AAAA,MACL,aAAa;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;","names":["detectCI","detectCI"]}
@@ -0,0 +1 @@
1
+ export { J as JestAdapterOptions, i as JestAggregatedResult, j as JestFileResult, k as JestTestResult, P as PlaywrightAdapterOptions, l as PlaywrightAnnotation, m as PlaywrightAttachment, n as PlaywrightError, o as PlaywrightLocation, p as PlaywrightStatus, q as PlaywrightTestCase, r as PlaywrightTestResult, x as StoryFileReport, V as VitestAdapterOptions, y as VitestSerializedError, z as VitestState, A as VitestTestCase, B as VitestTestModule, C as VitestTestResult, e as adaptJestRun, f as adaptPlaywrightRun, g as adaptVitestRun } from './index-DCJ0NvAp.cjs';
@@ -0,0 +1 @@
1
+ export { J as JestAdapterOptions, i as JestAggregatedResult, j as JestFileResult, k as JestTestResult, P as PlaywrightAdapterOptions, l as PlaywrightAnnotation, m as PlaywrightAttachment, n as PlaywrightError, o as PlaywrightLocation, p as PlaywrightStatus, q as PlaywrightTestCase, r as PlaywrightTestResult, x as StoryFileReport, V as VitestAdapterOptions, y as VitestSerializedError, z as VitestState, A as VitestTestCase, B as VitestTestModule, C as VitestTestResult, e as adaptJestRun, f as adaptPlaywrightRun, g as adaptVitestRun } from './index-DCJ0NvAp.js';