executable-stories-formatters 0.17.0 → 1.0.1
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 +6 -4
- package/dist/adapters.cjs.map +1 -1
- package/dist/adapters.d.cts +183 -1
- package/dist/adapters.d.ts +183 -1
- package/dist/adapters.js.map +1 -1
- package/dist/cli.js +2525 -16783
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +2336 -15957
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +117 -1259
- package/dist/index.d.ts +117 -1259
- package/dist/index.js +2335 -15950
- package/dist/index.js.map +1 -1
- package/package.json +15 -11
- package/schemas/README.md +0 -1
- package/templates/astro-thin/astro.config.mjs +62 -0
- package/templates/astro-thin/executable-stories.config.mjs +47 -0
- package/templates/astro-thin/gitignore +3 -0
- package/templates/astro-thin/package.json +20 -0
- package/templates/astro-thin/reports/sample-run.json +133 -0
- package/templates/astro-thin/src/content/docs/404.md +20 -0
- package/templates/astro-thin/src/content/docs/guides/writing-docs.mdx +7 -0
- package/templates/astro-thin/src/content/docs/index.mdx +44 -0
- package/templates/astro-thin/src/content.config.ts +26 -0
- package/templates/astro-thin/src/styles/stories.css +32 -0
- package/templates/astro-thin/tsconfig.json +5 -0
- package/dist/index-CXrzCk9p.d.cts +0 -628
- package/dist/index-CXrzCk9p.d.ts +0 -628
- package/schemas/story-report-v1.json +0 -456
- package/templates/astro-starlight/astro.config.mjs +0 -57
- package/templates/astro-starlight/gitignore +0 -14
- package/templates/astro-starlight/package.json +0 -20
- package/templates/astro-starlight/public/stories/assets/.gitkeep +0 -0
- package/templates/astro-starlight/public/stories/notes-index.json +0 -4
- package/templates/astro-starlight/public/stories/story-report.json +0 -17
- package/templates/astro-starlight/src/components/ApiOperations.astro +0 -366
- package/templates/astro-starlight/src/components/Checklist.astro +0 -15
- package/templates/astro-starlight/src/components/HealthDashboard.astro +0 -171
- package/templates/astro-starlight/src/components/PageTitle.astro +0 -53
- package/templates/astro-starlight/src/components/VerifiedBy.astro +0 -281
- package/templates/astro-starlight/src/components/VerifiedStep.astro +0 -91
- package/templates/astro-starlight/src/content/docs/examples/example-adr.mdx +0 -45
- package/templates/astro-starlight/src/content/docs/guides/behavior-portal.mdx +0 -41
- package/templates/astro-starlight/src/content/docs/guides/writing-docs.mdx +0 -49
- package/templates/astro-starlight/src/content/docs/index.mdx +0 -49
- package/templates/astro-starlight/src/content/docs/stories/.gitkeep +0 -0
- package/templates/astro-starlight/src/content.config.ts +0 -18
- package/templates/astro-starlight/src/lib/config.ts +0 -50
- package/templates/astro-starlight/src/lib/render-doc-entry.ts +0 -154
- package/templates/astro-starlight/src/lib/report-health.ts +0 -61
- package/templates/astro-starlight/src/lib/verification.ts +0 -247
- package/templates/astro-starlight/src/pages/explorer/explorer.css +0 -729
- package/templates/astro-starlight/src/pages/explorer/index.astro +0 -404
- package/templates/astro-starlight/src/styles/global.css +0 -293
- package/templates/astro-starlight/src/styles/themes/corporate.css +0 -83
- package/templates/astro-starlight/src/styles/themes/dashboard.css +0 -76
- package/templates/astro-starlight/src/styles/themes/default.css +0 -86
- package/templates/astro-starlight/src/styles/themes/minimal.css +0 -87
- package/templates/astro-starlight/src/styles/themes/playful.css +0 -77
- package/templates/astro-starlight/src/styles/themes/terminal.css +0 -77
- package/templates/astro-starlight/tsconfig.json +0 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "executable-stories-formatters",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.1",
|
|
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",
|
|
@@ -59,14 +59,18 @@
|
|
|
59
59
|
"@cucumber/messages": "^32.3.1",
|
|
60
60
|
"ajv": "^8.20.0",
|
|
61
61
|
"github-slugger": "^2.0.0",
|
|
62
|
-
"yaml": "^2.9.0"
|
|
62
|
+
"yaml": "^2.9.0",
|
|
63
|
+
"react": "^19.2.7",
|
|
64
|
+
"react-dom": "^19.2.7",
|
|
65
|
+
"executable-stories-core": "0.18.0",
|
|
66
|
+
"executable-stories-react": "0.2.1"
|
|
63
67
|
},
|
|
64
68
|
"devDependencies": {
|
|
65
69
|
"@faker-js/faker": "^10.4.0",
|
|
66
|
-
"@storybook/html": "^10.4.
|
|
67
|
-
"@storybook/html-vite": "^10.4.
|
|
70
|
+
"@storybook/html": "^10.4.6",
|
|
71
|
+
"@storybook/html-vite": "^10.4.6",
|
|
68
72
|
"@types/node": "^25.9.2",
|
|
69
|
-
"storybook": "^10.4.
|
|
73
|
+
"storybook": "^10.4.6",
|
|
70
74
|
"tsup": "^8.5.1",
|
|
71
75
|
"tsx": "^4.22.4",
|
|
72
76
|
"typescript": "~6.0.3",
|
|
@@ -74,12 +78,12 @@
|
|
|
74
78
|
"vitest-mock-extended": "^4.0.0"
|
|
75
79
|
},
|
|
76
80
|
"scripts": {
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"test
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
"compile": "bun build src/cli.ts --compile --outfile executable-stories",
|
|
81
|
+
"embed-assets": "node scripts/embed-react-assets.mjs",
|
|
82
|
+
"build": "node scripts/embed-react-assets.mjs && tsup",
|
|
83
|
+
"test": "node scripts/embed-react-assets.mjs && vitest run",
|
|
84
|
+
"test:watch": "node scripts/embed-react-assets.mjs && vitest",
|
|
85
|
+
"type-check": "node scripts/embed-react-assets.mjs && tsc --noEmit",
|
|
86
|
+
"compile": "node scripts/embed-react-assets.mjs && bun build src/cli.ts --compile --outfile executable-stories",
|
|
83
87
|
"storybook": "storybook dev -p 6006",
|
|
84
88
|
"build-storybook": "storybook build"
|
|
85
89
|
}
|
package/schemas/README.md
CHANGED
|
@@ -178,7 +178,6 @@ SUBCOMMANDS
|
|
|
178
178
|
| `--html-title <title>` | `Test Results` | HTML report title |
|
|
179
179
|
| `--html-no-syntax-highlighting` | | Disable syntax highlighting in HTML (enabled by default) |
|
|
180
180
|
| `--html-no-mermaid` | | Disable Mermaid diagrams in HTML (enabled by default) |
|
|
181
|
-
| `--html-no-markdown` | | Disable markdown parsing in HTML (enabled by default) |
|
|
182
181
|
| `--stdin` | | Read JSON from stdin instead of file |
|
|
183
182
|
| `--json-summary` | off | Print machine-parsable JSON summary |
|
|
184
183
|
| `--emit-canonical <path>` | | Write canonical JSON to given path |
|
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
vite: {
|
|
21
|
+
// The Stories page is a `client:load` React island. Pre-bundle React and the
|
|
22
|
+
// report component subtree in ONE optimize pass at startup so Astro's dev
|
|
23
|
+
// server never re-optimizes them mid-render when the island first hydrates.
|
|
24
|
+
// That mid-render re-optimize otherwise drops `react-dom/client`'s
|
|
25
|
+
// `createRoot` export and 504s the page ("Outdated Optimize Dep"), leaving
|
|
26
|
+
// the island unhydrated and the page rendered as unstyled SSR fallback.
|
|
27
|
+
// If you add your OWN React islands, add their heavy deps to `include` too.
|
|
28
|
+
optimizeDeps: {
|
|
29
|
+
include: [
|
|
30
|
+
'react',
|
|
31
|
+
'react-dom',
|
|
32
|
+
'react-dom/client',
|
|
33
|
+
'react/jsx-runtime',
|
|
34
|
+
'executable-stories-react',
|
|
35
|
+
'executable-stories-react/interactive',
|
|
36
|
+
],
|
|
37
|
+
noDiscovery: true,
|
|
38
|
+
},
|
|
39
|
+
// Keep a single React copy so hooks/context work across the island boundary.
|
|
40
|
+
resolve: { dedupe: ['react', 'react-dom'] },
|
|
41
|
+
},
|
|
42
|
+
integrations: [
|
|
43
|
+
// React renderer for the report islands — must come before executableStories.
|
|
44
|
+
react(),
|
|
45
|
+
// Mermaid diagrams are rendered by a small inline loader on
|
|
46
|
+
// `pre[data-mermaid]`. Don't add astro-mermaid — both would process the same
|
|
47
|
+
// element and double-render.
|
|
48
|
+
executableStories(esConfig),
|
|
49
|
+
starlight({
|
|
50
|
+
title: 'Story Docs',
|
|
51
|
+
description: 'Living documentation generated from executable stories.',
|
|
52
|
+
customCss: ['./src/styles/stories.css'],
|
|
53
|
+
// Nav is built straight from the config (Stories + Explorer, plus a group
|
|
54
|
+
// per `docs` source). Edit the array to taste.
|
|
55
|
+
sidebar: [
|
|
56
|
+
{ label: 'Home', slug: 'index' },
|
|
57
|
+
...storiesSidebar(esConfig),
|
|
58
|
+
{ label: 'Guides', items: [{ autogenerate: { directory: 'guides' } }] },
|
|
59
|
+
],
|
|
60
|
+
}),
|
|
61
|
+
],
|
|
62
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
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 run JSON your test adapter writes. Emit it by setting
|
|
9
|
+
* `rawRunPath: "reports/raw-run.json"` in your StoryReporter config, then run
|
|
10
|
+
* your tests in watch mode + `astro dev` to hot-reload these pages.
|
|
11
|
+
*/
|
|
12
|
+
export default defineExecutableStories({
|
|
13
|
+
source: process.env.ES_RUN_JSON ?? '../reports/raw-run.json',
|
|
14
|
+
|
|
15
|
+
// Shown only until your tests emit the run JSON above, so `astro dev` is
|
|
16
|
+
// populated on first run instead of empty. Replaced automatically the moment
|
|
17
|
+
// real results land; the Stories page labels these as sample data. Delete the
|
|
18
|
+
// file (and this line) once you're wired up.
|
|
19
|
+
sampleSource: './reports/sample-run.json',
|
|
20
|
+
|
|
21
|
+
// How scenarios are categorised in the index/explorer/nav:
|
|
22
|
+
// 'feature' (default) | 'tag' | 'source' | 'status' | 'none'
|
|
23
|
+
groupBy: 'feature',
|
|
24
|
+
|
|
25
|
+
// Only show some scenarios (optional):
|
|
26
|
+
// include: { tags: ['security', 'observability'] },
|
|
27
|
+
// exclude: { status: ['skipped'] },
|
|
28
|
+
|
|
29
|
+
// Combine several test suites in one site (optional):
|
|
30
|
+
// sources: [
|
|
31
|
+
// { name: 'web', label: 'Web app', source: '../apps/web/reports/raw-run.json' },
|
|
32
|
+
// { name: 'api', label: 'API', source: '../apps/api/reports/raw-run.json' },
|
|
33
|
+
// ],
|
|
34
|
+
|
|
35
|
+
// Theme the story pages (optional). `preset` picks a built-in palette
|
|
36
|
+
// ('default' | 'terminal' | 'minimal' | 'vibrant'); `accent` is a shorthand;
|
|
37
|
+
// `tokens` overrides any individual token (accent, pass, fail, warn, fg,
|
|
38
|
+
// muted, border, surface). These restyle the story content only — the
|
|
39
|
+
// Starlight shell keeps its own light/dark theme.
|
|
40
|
+
// theme: { preset: 'terminal', accent: '#3245ff', tokens: { pass: '#16a34a' } },
|
|
41
|
+
|
|
42
|
+
// Where the Stories/Explorer pages render (optional). 'auto' (default) uses
|
|
43
|
+
// the Starlight shell — sidebar, search, theme toggle — when this site has
|
|
44
|
+
// Starlight, and falls back to standalone pages otherwise. Force it with
|
|
45
|
+
// 'starlight' or 'standalone' if you embed the integration in your own site.
|
|
46
|
+
// shell: 'auto',
|
|
47
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0",
|
|
3
|
+
"projectRoot": "/sample",
|
|
4
|
+
"startedAtMs": 0,
|
|
5
|
+
"finishedAtMs": 1234,
|
|
6
|
+
"packageVersion": "sample",
|
|
7
|
+
"testCases": [
|
|
8
|
+
{
|
|
9
|
+
"title": "A returning customer checks out with a saved card",
|
|
10
|
+
"sourceFile": "src/checkout.story.test.ts",
|
|
11
|
+
"sourceLine": 12,
|
|
12
|
+
"status": "pass",
|
|
13
|
+
"durationMs": 41,
|
|
14
|
+
"story": {
|
|
15
|
+
"scenario": "A returning customer checks out with a saved card",
|
|
16
|
+
"tags": ["checkout", "payments"],
|
|
17
|
+
"covers": ["src/checkout/**"],
|
|
18
|
+
"steps": [
|
|
19
|
+
{ "keyword": "Given", "text": "a signed-in customer with a saved card" },
|
|
20
|
+
{ "keyword": "And", "text": "a basket worth £42.00" },
|
|
21
|
+
{ "keyword": "When", "text": "they confirm the order" },
|
|
22
|
+
{
|
|
23
|
+
"keyword": "Then",
|
|
24
|
+
"text": "the payment is captured and an order id is returned",
|
|
25
|
+
"docs": [
|
|
26
|
+
{
|
|
27
|
+
"kind": "table",
|
|
28
|
+
"phase": "runtime",
|
|
29
|
+
"label": "Captured payment",
|
|
30
|
+
"columns": ["Field", "Value"],
|
|
31
|
+
"rows": [["amount", "£42.00"], ["status", "captured"], ["order", "ord_1A2B"]]
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"docs": [
|
|
37
|
+
{
|
|
38
|
+
"kind": "mermaid",
|
|
39
|
+
"phase": "static",
|
|
40
|
+
"code": "flowchart LR\n Basket --> Confirm --> Capture --> Order"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"title": "Checkout is blocked when the card is declined",
|
|
47
|
+
"sourceFile": "src/checkout.story.test.ts",
|
|
48
|
+
"sourceLine": 34,
|
|
49
|
+
"status": "fail",
|
|
50
|
+
"durationMs": 28,
|
|
51
|
+
"error": { "message": "Expected order to be created, but payment was declined (card_declined)" },
|
|
52
|
+
"story": {
|
|
53
|
+
"scenario": "Checkout is blocked when the card is declined",
|
|
54
|
+
"tags": ["checkout", "payments"],
|
|
55
|
+
"covers": ["src/checkout/**"],
|
|
56
|
+
"steps": [
|
|
57
|
+
{ "keyword": "Given", "text": "a customer whose card will be declined" },
|
|
58
|
+
{ "keyword": "When", "text": "they confirm the order" },
|
|
59
|
+
{ "keyword": "Then", "text": "they see a clear decline message" },
|
|
60
|
+
{ "keyword": "But", "text": "no order is created" }
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"title": "Gift wrapping is offered above the free-wrap threshold",
|
|
66
|
+
"sourceFile": "src/checkout.story.test.ts",
|
|
67
|
+
"sourceLine": 58,
|
|
68
|
+
"status": "skip",
|
|
69
|
+
"durationMs": 0,
|
|
70
|
+
"story": {
|
|
71
|
+
"scenario": "Gift wrapping is offered above the free-wrap threshold",
|
|
72
|
+
"tags": ["checkout"],
|
|
73
|
+
"steps": [
|
|
74
|
+
{ "keyword": "Given", "text": "a basket above the free-wrap threshold" },
|
|
75
|
+
{ "keyword": "Then", "text": "free gift wrapping is offered" }
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"title": "Search ranks exact title matches first",
|
|
81
|
+
"sourceFile": "src/search.story.test.ts",
|
|
82
|
+
"sourceLine": 9,
|
|
83
|
+
"status": "pass",
|
|
84
|
+
"durationMs": 17,
|
|
85
|
+
"story": {
|
|
86
|
+
"scenario": "Search ranks exact title matches first",
|
|
87
|
+
"tags": ["search"],
|
|
88
|
+
"covers": ["src/search/**"],
|
|
89
|
+
"steps": [
|
|
90
|
+
{ "keyword": "Given", "text": "products titled 'Wireless Mouse' and 'Mouse Pad'" },
|
|
91
|
+
{ "keyword": "When", "text": "the shopper searches for 'mouse'" },
|
|
92
|
+
{
|
|
93
|
+
"keyword": "Then",
|
|
94
|
+
"text": "the exact title match is ranked first",
|
|
95
|
+
"docs": [
|
|
96
|
+
{
|
|
97
|
+
"kind": "code",
|
|
98
|
+
"phase": "runtime",
|
|
99
|
+
"label": "Ranked results",
|
|
100
|
+
"lang": "json",
|
|
101
|
+
"content": "[\n { \"title\": \"Wireless Mouse\", \"score\": 0.98 },\n { \"title\": \"Mouse Pad\", \"score\": 0.61 }\n]"
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
"docs": [
|
|
107
|
+
{
|
|
108
|
+
"kind": "note",
|
|
109
|
+
"phase": "static",
|
|
110
|
+
"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."
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"title": "Search tolerates a single typo",
|
|
117
|
+
"sourceFile": "src/search.story.test.ts",
|
|
118
|
+
"sourceLine": 31,
|
|
119
|
+
"status": "pass",
|
|
120
|
+
"durationMs": 23,
|
|
121
|
+
"story": {
|
|
122
|
+
"scenario": "Search tolerates a single typo",
|
|
123
|
+
"tags": ["search"],
|
|
124
|
+
"covers": ["src/search/**"],
|
|
125
|
+
"steps": [
|
|
126
|
+
{ "keyword": "Given", "text": "a product titled 'Keyboard'" },
|
|
127
|
+
{ "keyword": "When", "text": "the shopper searches for 'keybord'" },
|
|
128
|
+
{ "keyword": "Then", "text": "the product is still found" }
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
---
|
|
@@ -0,0 +1,7 @@
|
|
|
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.
|
|
@@ -0,0 +1,44 @@
|
|
|
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/raw-run.json 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
|
+
|
|
39
|
+
## Wiring (one-time)
|
|
40
|
+
|
|
41
|
+
The site reads the run JSON your test adapter writes. Point `source` in
|
|
42
|
+
`executable-stories.config.mjs` at it (default `../reports/raw-run.json`), and set
|
|
43
|
+
the matching `rawRunPath` in your StoryReporter config. That's the only wiring —
|
|
44
|
+
no per-test setup.
|
|
@@ -0,0 +1,26 @@
|
|
|
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, and rewrites relative `*.md` cross-links to their routes — so you can
|
|
14
|
+
// drop in plain GitHub-style docs without edits.
|
|
15
|
+
docs: defineCollection({
|
|
16
|
+
loader: authoredDocsLoader({ path: 'src/content/docs' }),
|
|
17
|
+
schema: docsSchema({
|
|
18
|
+
extend: z.object({ verifiedBy: z.union([z.string(), z.array(z.string())]).optional() }),
|
|
19
|
+
}),
|
|
20
|
+
}),
|
|
21
|
+
// Generated scenarios (executable-stories) — in-memory, never written to disk.
|
|
22
|
+
stories: defineCollection({ loader: storiesLoader(esConfig) }),
|
|
23
|
+
// Session trajectory ("passed N → M since you started"). Render with the
|
|
24
|
+
// shipped <Trajectory /> component (executable-stories-astro/components/Trajectory.astro).
|
|
25
|
+
trajectory: defineCollection({ loader: trajectoryLoader(esConfig) }),
|
|
26
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
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; }
|