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 +6 -6
- package/skills/formatters-cli/SKILL.md +0 -293
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "executable-stories-formatters",
|
|
3
|
-
"version": "0.7.
|
|
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.
|
|
65
|
-
"@types/node": "^25.
|
|
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": "~
|
|
69
|
-
"vitest": "^4.1.
|
|
70
|
-
"vitest-mock-extended": "^
|
|
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
|