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/README.md +0 -37
- package/dist/cli.js +438 -965
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +201 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +78 -6
- package/dist/index.d.ts +78 -6
- package/dist/index.js +196 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
- package/templates/astro-thin/astro.config.mjs +0 -46
- package/templates/astro-thin/executable-stories.config.mjs +0 -76
- package/templates/astro-thin/gitignore +0 -3
- package/templates/astro-thin/package.json +0 -20
- package/templates/astro-thin/reports/sample-run.json +0 -214
- package/templates/astro-thin/src/content/docs/404.md +0 -20
- package/templates/astro-thin/src/content/docs/guides/writing-docs.mdx +0 -58
- package/templates/astro-thin/src/content/docs/index.mdx +0 -51
- package/templates/astro-thin/src/content.config.ts +0 -33
- package/templates/astro-thin/src/styles/stories.css +0 -32
- package/templates/astro-thin/tsconfig.json +0 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "executable-stories-formatters",
|
|
3
|
-
"version": "1.
|
|
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,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; }
|