executable-stories-formatters 1.4.0 → 1.6.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.
@@ -17,28 +17,12 @@ export default defineConfig({
17
17
  // Set this to your deployed URL to enable canonical links + the sitemap
18
18
  // Starlight ships (otherwise `astro build` prints a harmless sitemap notice).
19
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
- },
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.
42
26
  integrations: [
43
27
  // React renderer for the report islands — must come before executableStories.
44
28
  react(),
@@ -32,6 +32,25 @@ export default defineExecutableStories({
32
32
  // { name: 'api', label: 'API', source: '../apps/api/reports/raw-run.json' },
33
33
  // ],
34
34
 
35
+ // Audience lenses (optional): each view mounts a filtered, re-grouped index
36
+ // at its own URL — same tests, a different lens per audience. Tag scenarios
37
+ // in your tests (e.g. tags: ['audience:stakeholder']) and filter on them:
38
+ // views: [
39
+ // { base: '/for/product', include: { tags: ['audience:stakeholder'] }, groupBy: 'tag' },
40
+ // { base: '/for/design', include: { tags: ['storyboard'] } },
41
+ // { base: '/for/support', include: { tags: ['support'] } },
42
+ // ],
43
+
44
+ // Journeys are on by default at /journeys: tag scenarios with
45
+ // `journey:<id>:<order>` (e.g. tags: ['journey:guest-checkout:1']) and each
46
+ // id becomes an ordered multi-scenario walkthrough page.
47
+ // journeysBase: '/journeys',
48
+
49
+ // The UI-state catalog is on by default at /states: tag scenarios with
50
+ // `state:<name>` (plus optional `viewport:mobile` / `viewport:desktop`) and
51
+ // they appear as a thumbnail grid, viewport variants side by side.
52
+ // statesBase: '/states',
53
+
35
54
  // Theme the story pages (optional). `preset` picks a built-in palette
36
55
  // ('default' | 'terminal' | 'minimal' | 'vibrant'); `accent` is a shorthand;
37
56
  // `tokens` overrides any individual token (accent, pass, fail, warn, fg,
@@ -44,4 +63,9 @@ export default defineExecutableStories({
44
63
  // Starlight, and falls back to standalone pages otherwise. Force it with
45
64
  // 'starlight' or 'standalone' if you embed the integration in your own site.
46
65
  // shell: 'auto',
66
+
67
+ // Agent-readable endpoints (on by default): /llms.txt indexes every scenario
68
+ // and each story page gets a plain-Markdown twin at /stories/<slug>.md, so
69
+ // the deployed site is consumable by agents/curl, not just browsers.
70
+ // agentEndpoints: true,
47
71
  });
@@ -1,5 +1,6 @@
1
1
  {
2
- "schemaVersion": "1.0",
2
+ "$schema": "https://executable-stories.dev/schemas/raw-run.schema.json",
3
+ "schemaVersion": 1,
3
4
  "projectRoot": "/sample",
4
5
  "startedAtMs": 0,
5
6
  "finishedAtMs": 1234,
@@ -13,12 +14,26 @@
13
14
  "durationMs": 41,
14
15
  "story": {
15
16
  "scenario": "A returning customer checks out with a saved card",
16
- "tags": ["checkout", "payments"],
17
- "covers": ["src/checkout/**"],
17
+ "tags": [
18
+ "checkout",
19
+ "payments"
20
+ ],
21
+ "covers": [
22
+ "src/checkout/**"
23
+ ],
18
24
  "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" },
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
+ },
22
37
  {
23
38
  "keyword": "Then",
24
39
  "text": "the payment is captured and an order id is returned",
@@ -27,8 +42,24 @@
27
42
  "kind": "table",
28
43
  "phase": "runtime",
29
44
  "label": "Captured payment",
30
- "columns": ["Field", "Value"],
31
- "rows": [["amount", "£42.00"], ["status", "captured"], ["order", "ord_1A2B"]]
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
+ ]
32
63
  }
33
64
  ]
34
65
  }
@@ -48,16 +79,35 @@
48
79
  "sourceLine": 34,
49
80
  "status": "fail",
50
81
  "durationMs": 28,
51
- "error": { "message": "Expected order to be created, but payment was declined (card_declined)" },
82
+ "error": {
83
+ "message": "Expected order to be created, but payment was declined (card_declined)"
84
+ },
52
85
  "story": {
53
86
  "scenario": "Checkout is blocked when the card is declined",
54
- "tags": ["checkout", "payments"],
55
- "covers": ["src/checkout/**"],
87
+ "tags": [
88
+ "checkout",
89
+ "payments"
90
+ ],
91
+ "covers": [
92
+ "src/checkout/**"
93
+ ],
56
94
  "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" }
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
+ }
61
111
  ]
62
112
  }
63
113
  },
@@ -69,10 +119,18 @@
69
119
  "durationMs": 0,
70
120
  "story": {
71
121
  "scenario": "Gift wrapping is offered above the free-wrap threshold",
72
- "tags": ["checkout"],
122
+ "tags": [
123
+ "checkout"
124
+ ],
73
125
  "steps": [
74
- { "keyword": "Given", "text": "a basket above the free-wrap threshold" },
75
- { "keyword": "Then", "text": "free gift wrapping is offered" }
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
+ }
76
134
  ]
77
135
  }
78
136
  },
@@ -84,11 +142,21 @@
84
142
  "durationMs": 17,
85
143
  "story": {
86
144
  "scenario": "Search ranks exact title matches first",
87
- "tags": ["search"],
88
- "covers": ["src/search/**"],
145
+ "tags": [
146
+ "search"
147
+ ],
148
+ "covers": [
149
+ "src/search/**"
150
+ ],
89
151
  "steps": [
90
- { "keyword": "Given", "text": "products titled 'Wireless Mouse' and 'Mouse Pad'" },
91
- { "keyword": "When", "text": "the shopper searches for 'mouse'" },
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
+ },
92
160
  {
93
161
  "keyword": "Then",
94
162
  "text": "the exact title match is ranked first",
@@ -120,12 +188,25 @@
120
188
  "durationMs": 23,
121
189
  "story": {
122
190
  "scenario": "Search tolerates a single typo",
123
- "tags": ["search"],
124
- "covers": ["src/search/**"],
191
+ "tags": [
192
+ "search"
193
+ ],
194
+ "covers": [
195
+ "src/search/**"
196
+ ],
125
197
  "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" }
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
+ }
129
210
  ]
130
211
  }
131
212
  }
@@ -5,3 +5,54 @@ title: Writing docs
5
5
  Add your own `.mdx` files under `src/content/docs/` — they appear in the sidebar
6
6
  alongside the generated Stories. The generated pages are derived from tests and
7
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`.
@@ -35,6 +35,13 @@ the matching page change.
35
35
  - **Trajectory** — pins a baseline when the dev server starts and shows what
36
36
  changed *since you started this session* (e.g. "+2 passing, 1 regressed") — the
37
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/>`.
38
45
 
39
46
  ## Wiring (one-time)
40
47