executable-stories-formatters 1.20.0 → 1.21.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "executable-stories-formatters",
3
- "version": "1.20.0",
3
+ "version": "1.21.0",
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": "Apache-2.0",
@@ -36,8 +36,7 @@
36
36
  "files": [
37
37
  "dist",
38
38
  "skills",
39
- "schemas",
40
- "templates"
39
+ "schemas"
41
40
  ],
42
41
  "engines": {
43
42
  "node": ">=22"
@@ -1,46 +0,0 @@
1
- // @ts-check
2
- import { defineConfig } from 'astro/config';
3
- import react from '@astrojs/react';
4
- import starlight from '@astrojs/starlight';
5
- import { executableStories, storiesSidebar } from 'executable-stories-astro';
6
- import esConfig from './executable-stories.config.mjs';
7
-
8
- // The story pages render the React report components from
9
- // executable-stories-react (the SAME components the standalone single-file HTML
10
- // report uses), so a React renderer must be registered. executable-stories-astro
11
- // can't auto-add it on Astro 7 — wire `react()` here, before the integration.
12
-
13
- // Run your tests in watch mode in one terminal and `astro dev` in another —
14
- // editing tests hot-reloads the Stories pages here. Nothing is written to disk;
15
- // tests stay the source of truth.
16
- export default defineConfig({
17
- // Set this to your deployed URL to enable canonical links + the sitemap
18
- // Starlight ships (otherwise `astro build` prints a harmless sitemap notice).
19
- // site: 'https://docs.example.com',
20
-
21
- // No vite tuning needed here: the integration pre-bundles React + the report
22
- // components (optimizeDeps) and dedupes React itself, so fixes ship with
23
- // `pnpm update executable-stories-astro`. If you add your OWN React islands,
24
- // list their heavy deps in a `vite.optimizeDeps.include` of your own — it
25
- // merges with the integration's list.
26
- integrations: [
27
- // React renderer for the report islands — must come before executableStories.
28
- react(),
29
- // Mermaid diagrams are rendered by a small inline loader on
30
- // `pre[data-mermaid]`. Don't add astro-mermaid — both would process the same
31
- // element and double-render.
32
- executableStories(esConfig),
33
- starlight({
34
- title: 'Story Docs',
35
- description: 'Living documentation generated from executable stories.',
36
- customCss: ['./src/styles/stories.css'],
37
- // Nav is built straight from the config (Stories + Explorer, plus a group
38
- // per `docs` source). Edit the array to taste.
39
- sidebar: [
40
- { label: 'Home', slug: 'index' },
41
- ...storiesSidebar(esConfig),
42
- { label: 'Guides', items: [{ autogenerate: { directory: 'guides' } }] },
43
- ],
44
- }),
45
- ],
46
- });
@@ -1,76 +0,0 @@
1
- import { defineExecutableStories } from 'executable-stories-astro';
2
-
3
- /**
4
- * One config object drives the whole docs site. It is imported by BOTH
5
- * astro.config.mjs (route injection, nav, theme) and src/content.config.ts
6
- * (the loaders) — so everything lives in one place.
7
- *
8
- * `source` points at the directory of per-file reports your test run writes,
9
- * one per test source file. Pointing at the directory rather than a single run
10
- * JSON is what keeps the site showing your whole suite when you have only run
11
- * part of it. Run your tests in watch mode + `astro dev` to hot-reload these
12
- * pages; new test files appear without a restart.
13
- *
14
- * A single run JSON still works if you want only the last run:
15
- * `source: '../reports/raw-run.json'`.
16
- */
17
- export default defineExecutableStories({
18
- source: process.env.ES_RUN_JSON ?? '../reports/by-file',
19
-
20
- // Shown only until your tests emit the run JSON above, so `astro dev` is
21
- // populated on first run instead of empty. Replaced automatically the moment
22
- // real results land; the Stories page labels these as sample data. Delete the
23
- // file (and this line) once you're wired up.
24
- sampleSource: './reports/sample-run.json',
25
-
26
- // How scenarios are categorised in the index/explorer/nav:
27
- // 'feature' (default) | 'tag' | 'source' | 'status' | 'none'
28
- groupBy: 'feature',
29
-
30
- // Only show some scenarios (optional):
31
- // include: { tags: ['security', 'observability'] },
32
- // exclude: { status: ['skipped'] },
33
-
34
- // Combine several test suites in one site (optional):
35
- // sources: [
36
- // { name: 'web', label: 'Web app', source: '../apps/web/reports/by-file' },
37
- // { name: 'api', label: 'API', source: '../apps/api/reports/by-file' },
38
- // ],
39
-
40
- // Audience lenses (optional): each view mounts a filtered, re-grouped index
41
- // at its own URL — same tests, a different lens per audience. Tag scenarios
42
- // in your tests (e.g. tags: ['audience:stakeholder']) and filter on them:
43
- // views: [
44
- // { base: '/for/product', include: { tags: ['audience:stakeholder'] }, groupBy: 'tag' },
45
- // { base: '/for/design', include: { tags: ['storyboard'] } },
46
- // { base: '/for/support', include: { tags: ['support'] } },
47
- // ],
48
-
49
- // Journeys are on by default at /journeys: tag scenarios with
50
- // `journey:<id>:<order>` (e.g. tags: ['journey:guest-checkout:1']) and each
51
- // id becomes an ordered multi-scenario walkthrough page.
52
- // journeysBase: '/journeys',
53
-
54
- // The UI-state catalog is on by default at /states: tag scenarios with
55
- // `state:<name>` (plus optional `viewport:mobile` / `viewport:desktop`) and
56
- // they appear as a thumbnail grid, viewport variants side by side.
57
- // statesBase: '/states',
58
-
59
- // Theme the story pages (optional). `preset` picks a built-in palette
60
- // ('default' | 'terminal' | 'minimal' | 'vibrant'); `accent` is a shorthand;
61
- // `tokens` overrides any individual token (accent, pass, fail, warn, fg,
62
- // muted, border, surface). These restyle the story content only — the
63
- // Starlight shell keeps its own light/dark theme.
64
- // theme: { preset: 'terminal', accent: '#3245ff', tokens: { pass: '#16a34a' } },
65
-
66
- // Where the Stories/Explorer pages render (optional). 'auto' (default) uses
67
- // the Starlight shell — sidebar, search, theme toggle — when this site has
68
- // Starlight, and falls back to standalone pages otherwise. Force it with
69
- // 'starlight' or 'standalone' if you embed the integration in your own site.
70
- // shell: 'auto',
71
-
72
- // Agent-readable endpoints (on by default): /llms.txt indexes every scenario
73
- // and each story page gets a plain-Markdown twin at /stories/<slug>.md, so
74
- // the deployed site is consumable by agents/curl, not just browsers.
75
- // agentEndpoints: true,
76
- });
@@ -1,3 +0,0 @@
1
- dist/
2
- .astro/
3
- node_modules/
@@ -1,20 +0,0 @@
1
- {
2
- "name": "story-docs",
3
- "type": "module",
4
- "version": "0.0.1",
5
- "private": true,
6
- "scripts": {
7
- "dev": "astro dev",
8
- "build": "astro build",
9
- "preview": "astro preview"
10
- },
11
- "dependencies": {
12
- "@astrojs/react": "^4.4.2",
13
- "@astrojs/starlight": "^0.41.0",
14
- "astro": "^7.0.0",
15
- "executable-stories-astro": "^0.1.0",
16
- "executable-stories-react": "^0.1.0",
17
- "react": "^19.2.7",
18
- "react-dom": "^19.2.7"
19
- }
20
- }
@@ -1,214 +0,0 @@
1
- {
2
- "$schema": "https://executable-stories.dev/schemas/raw-run.schema.json",
3
- "schemaVersion": 1,
4
- "projectRoot": "/sample",
5
- "startedAtMs": 0,
6
- "finishedAtMs": 1234,
7
- "packageVersion": "sample",
8
- "testCases": [
9
- {
10
- "title": "A returning customer checks out with a saved card",
11
- "sourceFile": "src/checkout.story.test.ts",
12
- "sourceLine": 12,
13
- "status": "pass",
14
- "durationMs": 41,
15
- "story": {
16
- "scenario": "A returning customer checks out with a saved card",
17
- "tags": [
18
- "checkout",
19
- "payments"
20
- ],
21
- "covers": [
22
- "src/checkout/**"
23
- ],
24
- "steps": [
25
- {
26
- "keyword": "Given",
27
- "text": "a signed-in customer with a saved card"
28
- },
29
- {
30
- "keyword": "And",
31
- "text": "a basket worth \u00a342.00"
32
- },
33
- {
34
- "keyword": "When",
35
- "text": "they confirm the order"
36
- },
37
- {
38
- "keyword": "Then",
39
- "text": "the payment is captured and an order id is returned",
40
- "docs": [
41
- {
42
- "kind": "table",
43
- "phase": "runtime",
44
- "label": "Captured payment",
45
- "columns": [
46
- "Field",
47
- "Value"
48
- ],
49
- "rows": [
50
- [
51
- "amount",
52
- "\u00a342.00"
53
- ],
54
- [
55
- "status",
56
- "captured"
57
- ],
58
- [
59
- "order",
60
- "ord_1A2B"
61
- ]
62
- ]
63
- }
64
- ]
65
- }
66
- ],
67
- "docs": [
68
- {
69
- "kind": "mermaid",
70
- "phase": "static",
71
- "code": "flowchart LR\n Basket --> Confirm --> Capture --> Order"
72
- }
73
- ]
74
- }
75
- },
76
- {
77
- "title": "Checkout is blocked when the card is declined",
78
- "sourceFile": "src/checkout.story.test.ts",
79
- "sourceLine": 34,
80
- "status": "fail",
81
- "durationMs": 28,
82
- "error": {
83
- "message": "Expected order to be created, but payment was declined (card_declined)"
84
- },
85
- "story": {
86
- "scenario": "Checkout is blocked when the card is declined",
87
- "tags": [
88
- "checkout",
89
- "payments"
90
- ],
91
- "covers": [
92
- "src/checkout/**"
93
- ],
94
- "steps": [
95
- {
96
- "keyword": "Given",
97
- "text": "a customer whose card will be declined"
98
- },
99
- {
100
- "keyword": "When",
101
- "text": "they confirm the order"
102
- },
103
- {
104
- "keyword": "Then",
105
- "text": "they see a clear decline message"
106
- },
107
- {
108
- "keyword": "But",
109
- "text": "no order is created"
110
- }
111
- ]
112
- }
113
- },
114
- {
115
- "title": "Gift wrapping is offered above the free-wrap threshold",
116
- "sourceFile": "src/checkout.story.test.ts",
117
- "sourceLine": 58,
118
- "status": "skip",
119
- "durationMs": 0,
120
- "story": {
121
- "scenario": "Gift wrapping is offered above the free-wrap threshold",
122
- "tags": [
123
- "checkout"
124
- ],
125
- "steps": [
126
- {
127
- "keyword": "Given",
128
- "text": "a basket above the free-wrap threshold"
129
- },
130
- {
131
- "keyword": "Then",
132
- "text": "free gift wrapping is offered"
133
- }
134
- ]
135
- }
136
- },
137
- {
138
- "title": "Search ranks exact title matches first",
139
- "sourceFile": "src/search.story.test.ts",
140
- "sourceLine": 9,
141
- "status": "pass",
142
- "durationMs": 17,
143
- "story": {
144
- "scenario": "Search ranks exact title matches first",
145
- "tags": [
146
- "search"
147
- ],
148
- "covers": [
149
- "src/search/**"
150
- ],
151
- "steps": [
152
- {
153
- "keyword": "Given",
154
- "text": "products titled 'Wireless Mouse' and 'Mouse Pad'"
155
- },
156
- {
157
- "keyword": "When",
158
- "text": "the shopper searches for 'mouse'"
159
- },
160
- {
161
- "keyword": "Then",
162
- "text": "the exact title match is ranked first",
163
- "docs": [
164
- {
165
- "kind": "code",
166
- "phase": "runtime",
167
- "label": "Ranked results",
168
- "lang": "json",
169
- "content": "[\n { \"title\": \"Wireless Mouse\", \"score\": 0.98 },\n { \"title\": \"Mouse Pad\", \"score\": 0.61 }\n]"
170
- }
171
- ]
172
- }
173
- ],
174
- "docs": [
175
- {
176
- "kind": "note",
177
- "phase": "static",
178
- "text": "This is **sample data** shipped with the scaffold so the site is populated on first run. It is replaced automatically the moment your tests emit their run JSON."
179
- }
180
- ]
181
- }
182
- },
183
- {
184
- "title": "Search tolerates a single typo",
185
- "sourceFile": "src/search.story.test.ts",
186
- "sourceLine": 31,
187
- "status": "pass",
188
- "durationMs": 23,
189
- "story": {
190
- "scenario": "Search tolerates a single typo",
191
- "tags": [
192
- "search"
193
- ],
194
- "covers": [
195
- "src/search/**"
196
- ],
197
- "steps": [
198
- {
199
- "keyword": "Given",
200
- "text": "a product titled 'Keyboard'"
201
- },
202
- {
203
- "keyword": "When",
204
- "text": "the shopper searches for 'keybord'"
205
- },
206
- {
207
- "keyword": "Then",
208
- "text": "the product is still found"
209
- }
210
- ]
211
- }
212
- }
213
- ]
214
- }
@@ -1,20 +0,0 @@
1
- ---
2
- title: Page not found
3
- template: splash
4
- editUrl: false
5
- # Keep this out of the routable `[...slug]` paths so it doesn't collide with
6
- # Starlight's dedicated 404 route; Starlight still reads it via getEntry to
7
- # populate that route. (Without this, the build warns about a /404 conflict.)
8
- draft: true
9
- hero:
10
- title: "404"
11
- tagline: That page isn't here. The Stories are generated live from your test runs, so a link can go stale if a scenario is renamed or removed.
12
- actions:
13
- - text: Browse the Stories
14
- link: /stories/
15
- icon: right-arrow
16
- variant: primary
17
- - text: Back to docs home
18
- link: /
19
- variant: minimal
20
- ---
@@ -1,58 +0,0 @@
1
- ---
2
- title: Writing docs
3
- ---
4
-
5
- Add your own `.mdx` files under `src/content/docs/` — they appear in the sidebar
6
- alongside the generated Stories. The generated pages are derived from tests and
7
- are never written to disk, so you can't accidentally edit them into a lie.
8
-
9
- ## Embed live scenarios in your own pages
10
-
11
- Your hand-written pages can pull scenarios in as live evidence — rendered from
12
- the latest test run, so the embedded card can never drift from reality:
13
-
14
- ```mdx
15
- ---
16
- title: Discount policy
17
- ---
18
- import StoryScenario from 'executable-stories-astro/components/StoryScenario.astro';
19
- import StoryStatus from 'executable-stories-astro/components/StoryStatus.astro';
20
-
21
- We cap discounts at 30% — enforced end-to-end
22
- (currently <StoryStatus id="checkout--caps-the-discount-at-30-percent" />):
23
-
24
- <StoryScenario id="checkout--caps-the-discount-at-30-percent" />
25
- ```
26
-
27
- - `<StoryScenario id="…" />` embeds the full scenario card — steps, status,
28
- failure output, and any docs the test attached.
29
- - `<StoryStatus id="…" />` is an inline status pill linked to the story page,
30
- for referencing evidence mid-sentence.
31
- - `id` accepts the stable scenario id (copy it from the **Explorer** page), the
32
- URL slug, or the exact title. An id that no longer matches renders a visible
33
- callout — embedded evidence never silently disappears.
34
-
35
- ## Prove a page is still true
36
-
37
- Declare which stories verify a page in its frontmatter and render a live badge:
38
-
39
- ```mdx
40
- ---
41
- title: ADR 0007 — cap discount at 30%
42
- verifiedBy: [checkout--caps-the-discount-at-30-percent]
43
- ---
44
- import VerifiedBy from 'executable-stories-astro/components/VerifiedBy.astro';
45
-
46
- <VerifiedBy refs={frontmatter.verifiedBy} />
47
- ```
48
-
49
- ## For agents and tooling
50
-
51
- The site also publishes machine-readable twins (on by default):
52
-
53
- - `/llms.txt` — an index of every scenario with links to its Markdown form.
54
- - `/stories/<slug>.md` — a plain-Markdown twin of each story page.
55
-
56
- Point an agent at your deployed site's `/llms.txt` and it can read every
57
- scenario without an HTML parser. Disable with `agentEndpoints: false` in
58
- `executable-stories.config.mjs`.
@@ -1,51 +0,0 @@
1
- ---
2
- title: Story Docs
3
- description: Living documentation generated from executable stories.
4
- ---
5
-
6
- The **Stories** section is generated live from your test-run JSON by the
7
- `executable-stories-astro` integration — there is no build/generate step and the
8
- pages are never written to disk, so they can't drift into a lie. Everything under
9
- **Guides** is hand-authored by your team.
10
-
11
- ## The loop
12
-
13
- Run two things side by side and leave them running:
14
-
15
- ```bash
16
- # Terminal 1 — your tests in watch mode (rewrites reports/by-file/ on every run)
17
- pnpm test --watch # or: vitest, jest --watch, playwright --ui, …
18
-
19
- # Terminal 2 — this docs site
20
- npm run dev # Astro dev server
21
- ```
22
-
23
- Each time your tests re-run, they rewrite the run JSON; the integration reloads
24
- it and these pages hot-update in place. Edit a `*.story.test.ts`, save, and watch
25
- the matching page change.
26
-
27
- ## Where to look
28
-
29
- - **[Stories](/stories)** — one page per scenario, grouped by feature (change the
30
- grouping with `groupBy` in `executable-stories.config.mjs`). Add a story and it
31
- appears; delete it and its page is pruned. On a fresh scaffold this shows a few
32
- **sample scenarios** (labelled as such) so the site isn't empty — they vanish
33
- the moment your tests emit their run JSON.
34
- - **[Explorer](/explorer)** — a searchable index of every scenario with its status.
35
- - **Trajectory** — pins a baseline when the dev server starts and shows what
36
- changed *since you started this session* (e.g. "+2 passing, 1 regressed") — the
37
- signal to watch while iterating in an agent loop.
38
- - **[/llms.txt](/llms.txt)** — a machine-readable index of every scenario; each
39
- story page also has a plain-Markdown twin at `/stories/<slug>.md`, so agents
40
- can read the published site without an HTML parser.
41
-
42
- Your own pages can embed scenarios as live evidence too — see
43
- **[Writing docs](/guides/writing-docs/)** for `<StoryScenario/>` and
44
- `<StoryStatus/>`.
45
-
46
- ## Wiring (one-time)
47
-
48
- The site reads the run JSON your test adapter writes. Point `source` in
49
- `executable-stories.config.mjs` at it (default `../reports/by-file`), and set
50
- the matching `rawRunPath` in your StoryReporter config. That's the only wiring —
51
- no per-test setup.
@@ -1,33 +0,0 @@
1
- import { defineCollection, z } from 'astro:content';
2
- import { docsSchema } from '@astrojs/starlight/schema';
3
- import {
4
- storiesLoader,
5
- trajectoryLoader,
6
- authoredDocsLoader,
7
- } from 'executable-stories-astro';
8
- import esConfig from '../executable-stories.config.mjs';
9
-
10
- export const collections = {
11
- // Hand-authored docs. `authoredDocsLoader` is a drop-in for Starlight's
12
- // docsLoader that ALSO: auto-titles frontmatter-free markdown from its first
13
- // H1, rewrites relative `*.md` cross-links to their routes, and (because the
14
- // shared config is passed as `explainers`) injects a fresh/stale banner into
15
- // any doc carrying an `explainer` provenance block (explain-change skill) —
16
- // with deep links to the cited scenarios' story pages.
17
- docs: defineCollection({
18
- loader: authoredDocsLoader({ path: 'src/content/docs', explainers: esConfig }),
19
- schema: docsSchema({
20
- extend: z.object({
21
- verifiedBy: z.union([z.string(), z.array(z.string())]).optional(),
22
- // Explainer provenance block — kept loose here (zod would otherwise
23
- // strip it); `executable-stories check-explainers` validates strictly.
24
- explainer: z.record(z.unknown()).optional(),
25
- }),
26
- }),
27
- }),
28
- // Generated scenarios (executable-stories) — in-memory, never written to disk.
29
- stories: defineCollection({ loader: storiesLoader(esConfig) }),
30
- // Session trajectory ("passed N → M since you started"). Render with the
31
- // shipped <Trajectory /> component (executable-stories-astro/components/Trajectory.astro).
32
- trajectory: defineCollection({ loader: trajectoryLoader(esConfig) }),
33
- };
@@ -1,32 +0,0 @@
1
- /**
2
- * Site theme for the executable-stories docs site. Loaded as Starlight
3
- * `customCss`, so unlike the package's `es.css` (which styles only the
4
- * /stories + /explorer content), this reaches the WHOLE shell — home page,
5
- * sidebar, header, search — and gives the site the look & feel of the HTML
6
- * report the formatters produce: IBM Plex type + a green primary accent.
7
- *
8
- * Edit freely (or delete) to match your own brand. To re-theme just the story
9
- * content, prefer the `theme` field in executable-stories.config.mjs.
10
- */
11
- @import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:wght@400;500;600;700&display=swap");
12
-
13
- :root {
14
- --sl-font: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
15
- --sl-font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
16
-
17
- /* Dark theme (Starlight's default :root) — green primary to match the report. */
18
- --sl-color-accent-low: #11341f;
19
- --sl-color-accent: #1f9d4d;
20
- --sl-color-accent-high: #b8f0cb;
21
- --sl-color-text-accent: #4ade80;
22
- }
23
-
24
- :root[data-theme="light"] {
25
- --sl-color-accent-low: #d6f3e0;
26
- --sl-color-accent: #1a7f37;
27
- --sl-color-accent-high: #0c4a23;
28
- --sl-color-text-accent: #15803d;
29
- }
30
-
31
- /* Tighten the brand wordmark + nav to feel a touch more product/Storybook-like. */
32
- .site-title { font-weight: 700; letter-spacing: -0.01em; }
@@ -1,5 +0,0 @@
1
- {
2
- "extends": "astro/tsconfigs/strict",
3
- "include": [".astro/types.d.ts", "**/*"],
4
- "exclude": ["dist"]
5
- }