executable-stories-formatters 0.7.3 → 0.7.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "executable-stories-formatters",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "description": "Cucumber-compatible report formats (HTML, Markdown, JUnit XML, Cucumber JSON) for executable-stories test results.",
5
5
  "author": "Jag Reehal <jag@jagreehal.com>",
6
6
  "license": "MIT",
@@ -61,13 +61,13 @@
61
61
  "ajv": "^8.18.0"
62
62
  },
63
63
  "devDependencies": {
64
- "@faker-js/faker": "^10.3.0",
65
- "@types/node": "^25.5.0",
64
+ "@faker-js/faker": "^10.4.0",
65
+ "@types/node": "^25.6.0",
66
66
  "tsup": "^8.5.1",
67
67
  "tsx": "^4.21.0",
68
- "typescript": "~5.9.3",
69
- "vitest": "^4.1.0",
70
- "vitest-mock-extended": "^3.1.0"
68
+ "typescript": "~6.0.2",
69
+ "vitest": "^4.1.4",
70
+ "vitest-mock-extended": "^4.0.0"
71
71
  },
72
72
  "scripts": {
73
73
  "build": "tsup",
@@ -1,293 +0,0 @@
1
- ---
2
- name: formatters-cli
3
- description: >
4
- executable-stories CLI: format and validate subcommands. Pipeline: RawRun
5
- JSON from stdin or file, canonicalizeRun() normalization, 6 output formats
6
- (HTML, Markdown, JUnit, Cucumber JSON/HTML/Messages). fn(args, deps)
7
- dependency injection. Exit codes 0=success, 1=schema, 2=canonical,
8
- 3=generation, 4=usage. ReportGenerator programmatic API. Aggregated and
9
- colocated output modes. canonicalizeRun, assertValidRun, validateCanonicalRun.
10
- type: core
11
- library: executable-stories-formatters
12
- library_version: "0.6.1"
13
- sources:
14
- - "jagreehal/executable-stories:packages/executable-stories-formatters/src/cli.ts"
15
- - "jagreehal/executable-stories:packages/executable-stories-formatters/src/index.ts"
16
- - "jagreehal/executable-stories:apps/docs-site/src/content/docs/formatters/formatters-api.md"
17
- ---
18
-
19
- # executable-stories-formatters — CLI & API
20
-
21
- ## Setup
22
-
23
- ```bash
24
- npm install -D executable-stories-formatters
25
- ```
26
-
27
- ### CLI usage
28
-
29
- ```bash
30
- # Generate markdown from raw run JSON
31
- executable-stories format raw-run.json --format markdown --output-dir docs
32
-
33
- # Generate multiple formats
34
- executable-stories format raw-run.json --format html,markdown,junit
35
-
36
- # Read from stdin
37
- cat raw-run.json | executable-stories format --stdin --format markdown
38
-
39
- # Compare two canonical runs for review-friendly output
40
- executable-stories compare baseline.json current.json \
41
- --input-type canonical \
42
- --format html,markdown \
43
- --output-name review-diff
44
-
45
- # Validate JSON against schema
46
- executable-stories validate raw-run.json
47
- ```
48
-
49
- ### Programmatic usage
50
-
51
- ```typescript
52
- import {
53
- canonicalizeRun,
54
- ReportGenerator,
55
- } from "executable-stories-formatters";
56
-
57
- const rawRun = JSON.parse(await readFile("raw-run.json", "utf-8"));
58
- const canonical = canonicalizeRun(rawRun);
59
-
60
- const generator = new ReportGenerator({
61
- formats: ["markdown", "html"],
62
- outputDir: "docs",
63
- outputName: "user-stories",
64
- outputNameTimestamp: true, // optional: unique filenames per run (e.g. user-stories-1739123456.md)
65
- sortTestCases: "id", // optional: stable order for diff-friendly reports
66
- });
67
-
68
- const outputs = await generator.generate(canonical);
69
- // Map<OutputFormat, string[]> — file paths written per format
70
- ```
71
-
72
- ## Core Patterns
73
-
74
- ### Three-layer pipeline
75
-
76
- ```
77
- Test code (story.given/when/then)
78
- → Framework adapter (vitest/jest/playwright/cypress)
79
- → RawRun JSON (schemaVersion: 1)
80
- → canonicalizeRun() → TestRunResult
81
- → Formatters (HTML, Markdown, JUnit, Cucumber JSON/HTML/Messages)
82
- ```
83
-
84
- ### Individual formatters
85
-
86
- ```typescript
87
- import {
88
- canonicalizeRun,
89
- MarkdownFormatter,
90
- HtmlFormatter,
91
- JUnitFormatter,
92
- CucumberJsonFormatter,
93
- } from "executable-stories-formatters";
94
-
95
- const canonical = canonicalizeRun(rawRun);
96
-
97
- const md = new MarkdownFormatter().format(canonical);
98
- const html = new HtmlFormatter().format(canonical);
99
- const junit = new JUnitFormatter().format(canonical);
100
- const cucumberJson = new CucumberJsonFormatter().formatToString(canonical);
101
- ```
102
-
103
- ### CLI flags
104
-
105
- ```bash
106
- # Output control
107
- --format html,markdown,junit,cucumber-json,cucumber-html,cucumber-messages
108
- --output-dir reports # Base directory (default: reports)
109
- --output-name test-results # Base filename (default: test-results)
110
- --output-name-timestamp # Append run timestamp (UTC seconds) to filename for before/after diffs
111
- --sort-test-cases id|source|none # Deterministic scenario order (default: none). Use id for diff-friendly output
112
- --input-type raw # raw | canonical | ndjson
113
-
114
- # Filtering
115
- --include "test/api/**" # Glob patterns to include
116
- --exclude "test/fixtures/**" # Glob patterns to exclude
117
-
118
- # HTML options
119
- --html-title "Test Report"
120
- --html-no-syntax-highlighting
121
- --html-no-mermaid
122
- --html-no-markdown
123
-
124
- # Story synthesis
125
- --synthesize-stories # Enabled by default
126
- --no-synthesize-stories # Disable
127
-
128
- # Machine output
129
- --json-summary # Print JSON summary to stdout
130
- --emit-canonical path.json # Write canonical JSON
131
-
132
- # Asset Bundling
133
- --asset-mode none|copy # Asset bundling strategy (default: none)
134
- --allow-missing-assets # Warn on missing assets instead of failing
135
- ```
136
-
137
- ## Asset Bundling
138
-
139
- Use `--asset-mode copy` to produce a portable report directory. All locally-referenced assets
140
- (Playwright videos, screenshots, attachment files) are copied into an `assets/` subdirectory
141
- and HTML paths are rewritten.
142
-
143
- ```bash
144
- executable-stories format raw-run.json --format html --output-dir report --asset-mode copy
145
- ```
146
-
147
- Output:
148
- ```
149
- report/
150
- test-results.html # paths rewritten to assets/
151
- assets/
152
- video-3f2c1a7b.webm
153
- step-1-91ab22de.png
154
- ```
155
-
156
- ### GitHub Actions usage
157
-
158
- ```yaml
159
- - run: npx executable-stories format .executable-stories/raw-run.json --format html --output-dir report --asset-mode copy
160
- - uses: actions/upload-artifact@v4
161
- with:
162
- name: test-report
163
- path: report/
164
- ```
165
-
166
- ### Options
167
-
168
- | Flag | Description |
169
- |------|-------------|
170
- | `--asset-mode none` | Default. No asset bundling. |
171
- | `--asset-mode copy` | Copy local assets to `assets/`, rewrite paths. |
172
- | `--allow-missing-assets` | Warn on missing assets instead of failing. |
173
-
174
- ### Validation
175
-
176
- ```typescript
177
- import {
178
- canonicalizeRun,
179
- validateCanonicalRun,
180
- assertValidRun,
181
- } from "executable-stories-formatters";
182
-
183
- const canonical = canonicalizeRun(rawRun);
184
-
185
- // Returns { valid: boolean, errors: string[] }
186
- const result = validateCanonicalRun(canonical);
187
-
188
- // Throws if invalid
189
- assertValidRun(canonical);
190
- ```
191
-
192
- ### Before/after diffs (evolution of tests)
193
-
194
- To compare reports across runs (e.g. in CI or locally), use timestamped filenames and deterministic ordering so diffs show real changes instead of random reordering from parallel test execution:
195
-
196
- ```bash
197
- executable-stories format raw-run.json --format markdown,html \
198
- --output-name-timestamp \
199
- --sort-test-cases id
200
- ```
201
-
202
- - `--output-name-timestamp`: appends run start time in UTC seconds (e.g. `test-results-1739123456.md`), so each run produces a unique, chronologically sortable file.
203
- - `--sort-test-cases id`: sorts scenarios by deterministic id (hash of source file + scenario name) so report content order is stable across runs.
204
-
205
- Programmatic: set `outputNameTimestamp: true` and `sortTestCases: "id"` (or `"source"` for file/line order) on `FormatterOptions`.
206
-
207
- For first-class run comparisons, use the dedicated compare subcommand:
208
-
209
- ```bash
210
- executable-stories compare baseline.json current.json \
211
- --input-type canonical \
212
- --format html,markdown \
213
- --output-dir reports \
214
- --output-name test-results-diff
215
- ```
216
-
217
- - Generates a standalone HTML review report with filter chips for `Regressed`, `Fixed`, `Added`, `Removed`, and `Changed`.
218
- - Generates Markdown with per-scenario before/after summaries for PR discussion or artifact storage.
219
- - Use canonical input when you already persist prior runs; raw and ndjson inputs are also supported as long as both files use the same `--input-type`.
220
-
221
- ### Notifications
222
-
223
- ```bash
224
- executable-stories format raw-run.json \
225
- --format markdown \
226
- --slack-webhook "$SLACK_WEBHOOK_URL" \
227
- --notify on-failure \
228
- --report-url "https://ci.example.com/reports" \
229
- --max-failed-tests 5
230
- ```
231
-
232
- ## Common Mistakes
233
-
234
- ### HIGH Passing invalid RawRun JSON
235
-
236
- Wrong:
237
-
238
- ```json
239
- { "tests": [{ "name": "my test" }] }
240
- ```
241
-
242
- Correct:
243
-
244
- ```json
245
- {
246
- "schemaVersion": 1,
247
- "metadata": { "startedAt": "2024-01-01T00:00:00Z" },
248
- "testCases": [
249
- {
250
- "id": "test-1",
251
- "name": "my test",
252
- "sourceFile": "test/example.test.ts",
253
- "status": "passed"
254
- }
255
- ]
256
- }
257
- ```
258
-
259
- The CLI validates against the RawRun schema. Invalid input exits with code 1. The `schemaVersion`, `metadata`, and `testCases` fields are required.
260
-
261
- Source: packages/executable-stories-formatters/src/cli.ts
262
-
263
- ### MEDIUM Tests without story metadata silently filtered
264
-
265
- ```typescript
266
- // This test has no story.init() — it will be excluded from reports
267
- it("adds numbers", () => {
268
- expect(add(2, 3)).toBe(5);
269
- });
270
- ```
271
-
272
- `canonicalizeRun()` filters out test cases where `story == null` by default. Use `--synthesize-stories` (enabled by default) to include non-story tests with synthesized metadata, or add `story.init()` to your tests.
273
-
274
- Source: packages/executable-stories-formatters/src/index.ts
275
-
276
- ### MEDIUM Exit codes not checked in CI
277
-
278
- ```bash
279
- # Wrong — ignores failures
280
- executable-stories format raw-run.json --format markdown || true
281
- ```
282
-
283
- ```bash
284
- # Correct — CI fails on error
285
- executable-stories format raw-run.json --format markdown
286
- # Exit 0: success
287
- # Exit 1: schema validation failure
288
- # Exit 2: canonical validation failure
289
- # Exit 3: formatter/generation failure
290
- # Exit 4: bad arguments
291
- ```
292
-
293
- Source: packages/executable-stories-formatters/src/cli.ts