dreamboard 0.1.21 → 0.1.22

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.
Files changed (186) hide show
  1. package/dist/{chunk-EYYWGWTO.js → chunk-2RCUHMGL.js} +343 -1911
  2. package/dist/chunk-2RCUHMGL.js.map +1 -0
  3. package/dist/{chunk-MOVHYB6E.js → chunk-AQ5UUNJS.js} +1018 -692
  4. package/dist/chunk-AQ5UUNJS.js.map +1 -0
  5. package/dist/{chunk-BMYC6772.js → chunk-H3O43F5P.js} +9765 -3068
  6. package/dist/chunk-H3O43F5P.js.map +1 -0
  7. package/dist/dev-host/dev-api-proxy-plugin.ts +330 -0
  8. package/dist/dev-host/dev-diagnostics.ts +62 -0
  9. package/dist/dev-host/dev-fallback-stylesheet.ts +50 -0
  10. package/dist/dev-host/dev-host-controller.ts +686 -0
  11. package/dist/dev-host/dev-host-player-query.ts +17 -0
  12. package/dist/dev-host/dev-host-session-transport.ts +52 -0
  13. package/dist/dev-host/dev-host-storage.ts +56 -0
  14. package/dist/dev-host/dev-log-relay-plugin.ts +469 -0
  15. package/dist/dev-host/dev-runtime-config.ts +14 -0
  16. package/dist/dev-host/dev-runtime-platform.ts +419 -0
  17. package/dist/dev-host/dev-virtual-modules-plugin.ts +63 -0
  18. package/dist/dev-host/host-main.css +182 -0
  19. package/dist/dev-host/host-main.tsx +754 -0
  20. package/dist/dev-host/index.html +56 -0
  21. package/dist/dev-host/plugin-main.ts +55 -0
  22. package/dist/dev-host/plugin.html +24 -0
  23. package/dist/dev-host/start-dev-server.ts +138 -0
  24. package/dist/dev-host/virtual-modules.d.ts +27 -0
  25. package/dist/dist-FEPN3BDN.js +16543 -0
  26. package/dist/dist-FEPN3BDN.js.map +1 -0
  27. package/dist/{dist-WJRJNFLI.js → dist-FRURQI7Q.js} +4 -2
  28. package/dist/index.js +3 -3
  29. package/dist/internal.js +159 -124
  30. package/dist/internal.js.map +1 -1
  31. package/dist/runtime-packages/tailwind-config/shared-styles.css +146 -0
  32. package/dist/runtime-packages/ui/src/components/.gitkeep +0 -0
  33. package/dist/runtime-packages/ui/src/components/accordion.tsx +66 -0
  34. package/dist/runtime-packages/ui/src/components/ai-elements/actions.tsx +65 -0
  35. package/dist/runtime-packages/ui/src/components/ai-elements/artifact.tsx +147 -0
  36. package/dist/runtime-packages/ui/src/components/ai-elements/branch.tsx +215 -0
  37. package/dist/runtime-packages/ui/src/components/ai-elements/canvas.tsx +22 -0
  38. package/dist/runtime-packages/ui/src/components/ai-elements/chain-of-thought.tsx +228 -0
  39. package/dist/runtime-packages/ui/src/components/ai-elements/code-block.tsx +179 -0
  40. package/dist/runtime-packages/ui/src/components/ai-elements/confirmation.tsx +158 -0
  41. package/dist/runtime-packages/ui/src/components/ai-elements/connection.tsx +28 -0
  42. package/dist/runtime-packages/ui/src/components/ai-elements/context.tsx +408 -0
  43. package/dist/runtime-packages/ui/src/components/ai-elements/controls.tsx +18 -0
  44. package/dist/runtime-packages/ui/src/components/ai-elements/conversation.tsx +97 -0
  45. package/dist/runtime-packages/ui/src/components/ai-elements/edge.tsx +140 -0
  46. package/dist/runtime-packages/ui/src/components/ai-elements/image.tsx +24 -0
  47. package/dist/runtime-packages/ui/src/components/ai-elements/inline-citation.tsx +287 -0
  48. package/dist/runtime-packages/ui/src/components/ai-elements/loader.tsx +96 -0
  49. package/dist/runtime-packages/ui/src/components/ai-elements/message.tsx +463 -0
  50. package/dist/runtime-packages/ui/src/components/ai-elements/node.tsx +71 -0
  51. package/dist/runtime-packages/ui/src/components/ai-elements/open-in-chat.tsx +365 -0
  52. package/dist/runtime-packages/ui/src/components/ai-elements/panel.tsx +15 -0
  53. package/dist/runtime-packages/ui/src/components/ai-elements/plan.tsx +142 -0
  54. package/dist/runtime-packages/ui/src/components/ai-elements/prompt-input.tsx +1380 -0
  55. package/dist/runtime-packages/ui/src/components/ai-elements/queue.tsx +274 -0
  56. package/dist/runtime-packages/ui/src/components/ai-elements/reasoning.tsx +182 -0
  57. package/dist/runtime-packages/ui/src/components/ai-elements/response.tsx +22 -0
  58. package/dist/runtime-packages/ui/src/components/ai-elements/shimmer.tsx +64 -0
  59. package/dist/runtime-packages/ui/src/components/ai-elements/sources.tsx +77 -0
  60. package/dist/runtime-packages/ui/src/components/ai-elements/suggestion.tsx +53 -0
  61. package/dist/runtime-packages/ui/src/components/ai-elements/task.tsx +87 -0
  62. package/dist/runtime-packages/ui/src/components/ai-elements/tool.tsx +165 -0
  63. package/dist/runtime-packages/ui/src/components/ai-elements/toolbar.tsx +16 -0
  64. package/dist/runtime-packages/ui/src/components/ai-elements/web-preview.tsx +263 -0
  65. package/dist/runtime-packages/ui/src/components/alert-dialog.tsx +157 -0
  66. package/dist/runtime-packages/ui/src/components/alert.tsx +66 -0
  67. package/dist/runtime-packages/ui/src/components/avatar.tsx +53 -0
  68. package/dist/runtime-packages/ui/src/components/badge.tsx +46 -0
  69. package/dist/runtime-packages/ui/src/components/button-group.tsx +83 -0
  70. package/dist/runtime-packages/ui/src/components/button.tsx +65 -0
  71. package/dist/runtime-packages/ui/src/components/card.tsx +92 -0
  72. package/dist/runtime-packages/ui/src/components/carousel.tsx +241 -0
  73. package/dist/runtime-packages/ui/src/components/collapsible.tsx +33 -0
  74. package/dist/runtime-packages/ui/src/components/command.tsx +184 -0
  75. package/dist/runtime-packages/ui/src/components/context-menu.tsx +252 -0
  76. package/dist/runtime-packages/ui/src/components/counter.tsx +11 -0
  77. package/dist/runtime-packages/ui/src/components/dialog.tsx +146 -0
  78. package/dist/runtime-packages/ui/src/components/drawer.tsx +132 -0
  79. package/dist/runtime-packages/ui/src/components/dropdown-menu.tsx +257 -0
  80. package/dist/runtime-packages/ui/src/components/form.tsx +168 -0
  81. package/dist/runtime-packages/ui/src/components/header.tsx +13 -0
  82. package/dist/runtime-packages/ui/src/components/hover-card.tsx +44 -0
  83. package/dist/runtime-packages/ui/src/components/input-group.tsx +178 -0
  84. package/dist/runtime-packages/ui/src/components/input.tsx +21 -0
  85. package/dist/runtime-packages/ui/src/components/item.tsx +193 -0
  86. package/dist/runtime-packages/ui/src/components/label.tsx +24 -0
  87. package/dist/runtime-packages/ui/src/components/navigation-menu.tsx +168 -0
  88. package/dist/runtime-packages/ui/src/components/popover.tsx +55 -0
  89. package/dist/runtime-packages/ui/src/components/progress.tsx +31 -0
  90. package/dist/runtime-packages/ui/src/components/radio-group.tsx +45 -0
  91. package/dist/runtime-packages/ui/src/components/resizable.tsx +56 -0
  92. package/dist/runtime-packages/ui/src/components/scroll-area.tsx +58 -0
  93. package/dist/runtime-packages/ui/src/components/select.tsx +187 -0
  94. package/dist/runtime-packages/ui/src/components/separator.tsx +28 -0
  95. package/dist/runtime-packages/ui/src/components/skeleton.tsx +13 -0
  96. package/dist/runtime-packages/ui/src/components/sonner.tsx +25 -0
  97. package/dist/runtime-packages/ui/src/components/spinner.tsx +16 -0
  98. package/dist/runtime-packages/ui/src/components/switch.tsx +31 -0
  99. package/dist/runtime-packages/ui/src/components/table.tsx +137 -0
  100. package/dist/runtime-packages/ui/src/components/tabs.tsx +74 -0
  101. package/dist/runtime-packages/ui/src/components/textarea.tsx +23 -0
  102. package/dist/runtime-packages/ui/src/components/theme-provider.tsx +73 -0
  103. package/dist/runtime-packages/ui/src/components/tooltip.tsx +61 -0
  104. package/dist/runtime-packages/ui/src/components/ui/file-upload.tsx +195 -0
  105. package/dist/runtime-packages/ui/src/hooks/.gitkeep +0 -0
  106. package/dist/runtime-packages/ui/src/index.ts +68 -0
  107. package/dist/runtime-packages/ui/src/lib/utils.ts +6 -0
  108. package/dist/runtime-packages/ui-host-runtime/src/actor-principal.ts +68 -0
  109. package/dist/runtime-packages/ui-host-runtime/src/components/host-controls.tsx +359 -0
  110. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback-toaster.tsx +274 -0
  111. package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback.tsx +214 -0
  112. package/dist/runtime-packages/ui-host-runtime/src/components/host-session-metadata.tsx +135 -0
  113. package/dist/runtime-packages/ui-host-runtime/src/components/index.ts +5 -0
  114. package/dist/runtime-packages/ui-host-runtime/src/components/perf-overlay.tsx +194 -0
  115. package/dist/runtime-packages/ui-host-runtime/src/host-controls.tsx +1 -0
  116. package/dist/runtime-packages/ui-host-runtime/src/host-feedback.tsx +1 -0
  117. package/dist/runtime-packages/ui-host-runtime/src/host-session-transport.ts +162 -0
  118. package/dist/runtime-packages/ui-host-runtime/src/index.ts +2 -0
  119. package/dist/runtime-packages/ui-host-runtime/src/logger.ts +11 -0
  120. package/dist/runtime-packages/ui-host-runtime/src/perf.ts +253 -0
  121. package/dist/runtime-packages/ui-host-runtime/src/plugin-bridge.ts +195 -0
  122. package/dist/runtime-packages/ui-host-runtime/src/plugin-health-check.ts +138 -0
  123. package/dist/runtime-packages/ui-host-runtime/src/plugin-messages.ts +159 -0
  124. package/dist/runtime-packages/ui-host-runtime/src/plugin-session-gateway.ts +524 -0
  125. package/dist/runtime-packages/ui-host-runtime/src/runtime/index.ts +12 -0
  126. package/dist/runtime-packages/ui-host-runtime/src/screenshot/projection-to-snapshot.ts +122 -0
  127. package/dist/runtime-packages/ui-host-runtime/src/screenshot/static-store-api.ts +26 -0
  128. package/dist/runtime-packages/ui-host-runtime/src/session-ingress-controller.ts +477 -0
  129. package/dist/runtime-packages/ui-host-runtime/src/session-ingress.ts +209 -0
  130. package/dist/runtime-packages/ui-host-runtime/src/session-live-runtime.ts +112 -0
  131. package/dist/runtime-packages/ui-host-runtime/src/session-model.ts +318 -0
  132. package/dist/runtime-packages/ui-host-runtime/src/session-projection.ts +211 -0
  133. package/dist/runtime-packages/ui-host-runtime/src/session-state-reducer.ts +814 -0
  134. package/dist/runtime-packages/ui-host-runtime/src/sse-manager.ts +334 -0
  135. package/dist/runtime-packages/ui-host-runtime/src/unified-session-store.ts +180 -0
  136. package/dist/scaffold/assets/static/app/tsconfig.framework.json +3 -1
  137. package/dist/scaffold/assets/static/ui/tsconfig.framework.json +7 -19
  138. package/package.json +52 -17
  139. package/skills/dreamboard/SKILL.md +41 -75
  140. package/LICENSE +0 -89
  141. package/NOTICE +0 -1
  142. package/dist/chunk-BMYC6772.js.map +0 -1
  143. package/dist/chunk-EYYWGWTO.js.map +0 -1
  144. package/dist/chunk-MOVHYB6E.js.map +0 -1
  145. package/dist/scaffold/assets/static/ui/App.tsx +0 -22
  146. package/dist/src-CUL7EGGG.js +0 -634
  147. package/dist/src-CUL7EGGG.js.map +0 -1
  148. package/skills/dreamboard/references/authoring-lifecycle.md +0 -102
  149. package/skills/dreamboard/references/board-surfaces.md +0 -36
  150. package/skills/dreamboard/references/board-topology.md +0 -443
  151. package/skills/dreamboard/references/boards-and-topology.md +0 -100
  152. package/skills/dreamboard/references/card-actions.md +0 -107
  153. package/skills/dreamboard/references/cli.md +0 -120
  154. package/skills/dreamboard/references/core-concepts.md +0 -514
  155. package/skills/dreamboard/references/custom-renderers.md +0 -26
  156. package/skills/dreamboard/references/derived-values.md +0 -55
  157. package/skills/dreamboard/references/effects.md +0 -111
  158. package/skills/dreamboard/references/game-contract.md +0 -89
  159. package/skills/dreamboard/references/game-definition.md +0 -89
  160. package/skills/dreamboard/references/game-shell.md +0 -80
  161. package/skills/dreamboard/references/hand-surfaces.md +0 -33
  162. package/skills/dreamboard/references/index.md +0 -112
  163. package/skills/dreamboard/references/inputs-and-targets.md +0 -160
  164. package/skills/dreamboard/references/interactions.md +0 -158
  165. package/skills/dreamboard/references/manifest-fields.md +0 -137
  166. package/skills/dreamboard/references/manifest.md +0 -81
  167. package/skills/dreamboard/references/package-surfaces.md +0 -69
  168. package/skills/dreamboard/references/phases.md +0 -145
  169. package/skills/dreamboard/references/prompts-and-choices.md +0 -55
  170. package/skills/dreamboard/references/quickstart.md +0 -71
  171. package/skills/dreamboard/references/rule-authoring.md +0 -144
  172. package/skills/dreamboard/references/setup-bootstrap.md +0 -78
  173. package/skills/dreamboard/references/stages-and-zones.md +0 -59
  174. package/skills/dreamboard/references/static-views.md +0 -67
  175. package/skills/dreamboard/references/table-queries-and-ops.md +0 -103
  176. package/skills/dreamboard/references/testing-bases.md +0 -147
  177. package/skills/dreamboard/references/testing-generated-contracts.md +0 -142
  178. package/skills/dreamboard/references/testing-runtime-assertions.md +0 -124
  179. package/skills/dreamboard/references/testing-scenarios.md +0 -148
  180. package/skills/dreamboard/references/testing-ui-tests.md +0 -174
  181. package/skills/dreamboard/references/testing.md +0 -161
  182. package/skills/dreamboard/references/ui-architecture.md +0 -137
  183. package/skills/dreamboard/references/ui-components.md +0 -34
  184. package/skills/dreamboard/references/views.md +0 -72
  185. package/skills/dreamboard/references/workspace-layout.md +0 -136
  186. /package/dist/{dist-WJRJNFLI.js.map → dist-FRURQI7Q.js.map} +0 -0
@@ -1,142 +0,0 @@
1
- # Generated testing contracts
2
-
3
- Understand generated testing files, regeneration, and stale contract failures.
4
-
5
- Dreamboard testing has a small authored surface and a larger generated surface.
6
- The generated surface keeps tests typed to the current manifest, reducer, view,
7
- interaction, and UI contract shape.
8
-
9
- Run generation with:
10
-
11
- ```bash
12
- dreamboard test generate
13
- ```
14
-
15
- ## Generated files
16
-
17
- | Path | Generated by | Purpose |
18
- | --- | --- | --- |
19
- | `test/testing-types.ts` | `dreamboard test generate` | Workspace-narrowed `defineBase`, `defineScenario`, `createTestRuntime`, and re-exports. |
20
- | `test/generated/testing-contract.ts` | `dreamboard test generate` | Player ids, base ids, interaction ids, typed scenario context, phase/stage/view types, known rejection codes. |
21
- | `test/generated/base-states.generated.ts` | `dreamboard test generate` | Deterministic base snapshots and fingerprints. |
22
- | `test/generated/base-states.generated.d.ts` | `dreamboard test generate` | Type declaration for generated base states. |
23
- | `test/generated/scenario-manifest.generated.ts` | `dreamboard test generate` | Scenario id, file path, base id, and runner list. |
24
- | `test/generated/.generation-meta.json` | `dreamboard test generate` | Generation timestamp and artifact counts. |
25
- | `test/generated/bases/**/player-*.projection.json` | `dreamboard test generate` | Per-player projection snapshots for generated bases. |
26
- | `test/generated/snapshots/*.snapshot.json` | `dreamboard test run --update-snapshots` or first snapshot assertion | Scenario snapshot matcher output. |
27
-
28
- Files with a `Generated by` header should not be edited manually.
29
-
30
- ## testing-types.ts
31
-
32
- `test/testing-types.ts` is the only testing import surface base and scenario
33
- files should use:
34
-
35
- ```ts
36
- import {
37
- defineBase,
38
- defineScenario,
39
- createTestRuntime,
40
- type InteractionId,
41
- type PlayerId,
42
- } from "../testing-types";
43
- ```
44
-
45
- It wraps generated types so:
46
-
47
- - `defineBase` receives a workspace `BaseDefinition`
48
- - `defineScenario` narrows `phase`, `stage`, view, and interaction params
49
- - `createTestRuntime` accepts generated base ids and player ids
50
-
51
- UI tests may also import `@dreamboard/ui-sdk` and the generated UI contract
52
- because they render React against projected runtime state.
53
-
54
- If the wrapper is stale, regenerate it. Do not patch it by hand.
55
-
56
- ## testing-contract.ts
57
-
58
- The generated testing contract is derived from the workspace game and
59
- `shared/generated/ui-contract.ts`. It includes:
60
-
61
- - `PlayerId`
62
- - `BaseId`
63
- - `InteractionId`
64
- - `InteractionParamsOf`
65
- - `PhaseName`
66
- - `WorkspaceStageName`
67
- - `GameView`
68
- - `ScenarioContext`
69
- - `KnownRejectionCode`
70
- - `BrowserRunnerDriver` types for internal browser lanes
71
-
72
- Scenario `game.submit` is typed from `InteractionId` to the matching param
73
- shape, so invalid params should fail before runtime.
74
-
75
- ## Base fingerprints
76
-
77
- Generated base artifacts include fingerprints for the files and runtime inputs
78
- that affect replay:
79
-
80
- - base module
81
- - manifest
82
- - reducer bundle
83
- - UI contract
84
- - compiled result and game id when relevant
85
- - seed and player count
86
- - setup profile
87
- - parent base id and parent fingerprint for inherited bases
88
-
89
- When any of these change, `dreamboard test run` fails with a message such as:
90
-
91
- ```text
92
- base module changed; game reducer bundle changed; ui contract changed. Run 'dreamboard test generate' to refresh reducer-native base artifacts.
93
- ```
94
-
95
- That is expected. Regenerate first, then debug scenario behavior.
96
-
97
- ## Scenario manifest
98
-
99
- `scenario-manifest.generated.ts` records which scenario files exist, which base
100
- each uses, and which runners they request:
101
-
102
- ```ts
103
- export const SCENARIO_MANIFEST = [
104
- {
105
- id: "smoke-initial-turn",
106
- filePath: "../scenarios/smoke-initial-turn.scenario.ts",
107
- base: "initial-turn",
108
- runners: ["reducer"],
109
- },
110
- ] as const;
111
- ```
112
-
113
- The CLI uses this to run the right scenario set and to report scenario ids
114
- consistently.
115
-
116
- ## Missing generated files
117
-
118
- Fresh or partially regenerated workspaces may have placeholder generated files
119
- before the first real generation pass. Run:
120
-
121
- ```bash
122
- dreamboard test generate
123
- ```
124
-
125
- Then run:
126
-
127
- ```bash
128
- dreamboard test run
129
- ```
130
-
131
- If `test run` still fails with missing base artifacts, check that:
132
-
133
- - at least one `test/bases/*.base.ts` file exists
134
- - at least one `test/scenarios/*.scenario.ts` file exists
135
- - every scenario `from` references a base id
136
- - inherited parent bases have been generated
137
-
138
- ## Regeneration rule
139
-
140
- Regenerate after changing any authored source that changes runtime behavior or
141
- generated types. It is cheaper and more accurate to regenerate than to debug a
142
- scenario against stale base snapshots.
@@ -1,124 +0,0 @@
1
- # Runtime assertions
2
-
3
- Use generated scenario context helpers and matchers.
4
-
5
- `defineScenario` callbacks receive a typed context. Use that context to submit
6
- interactions, read projected views, inspect interaction descriptors, and assert
7
- behavior.
8
-
9
- ## Context helpers
10
-
11
- | Helper | Available in | Meaning |
12
- | --- | --- | --- |
13
- | `game.start()` | Base setup, `when`, `then` | Starts the game. Usually handled by the harness before scenario setup. |
14
- | `game.submit(playerId, interactionId, params?)` | Base setup, `when`, `then` | Validates and dispatches an interaction. |
15
- | `players()` | Base setup, `when`, `then` | Ordered player ids for the current base. |
16
- | `seat(index)` | Base setup, `when`, `then` | Player id at a seat index; throws when out of range. |
17
- | `state()` | `when`, `then` | Current phase name. |
18
- | `view(playerId)` | `when`, `then` | Reducer-projected `GameView` for a player. |
19
- | `interactions(playerId)` | `when`, `then` | Current interaction descriptors for a player. |
20
- | `expect(value)` | `when`, `then` | Built-in assertion API. |
21
-
22
- `state()` is the phase name, not the raw reducer state. Assert game-specific
23
- state through `view(playerId)` or through projected descriptors.
24
-
25
- ## View assertions
26
-
27
- Use `view(playerId)` for player-facing state:
28
-
29
- ```ts
30
- then: ({ view, expect, seat }) => {
31
- const p1View = view(seat(0));
32
- expect(p1View.resources.brick).toBe(2);
33
- expect(p1View.pathsByEdgeId["edge-a"]).toBeDefined();
34
- };
35
- ```
36
-
37
- When a scenario declares `phase`, generated types narrow `view` in `then` when
38
- the workspace view has phase-tagged variants.
39
-
40
- ## Interaction assertions
41
-
42
- Use `interactions(playerId)` to check what the UI would be allowed to render:
43
-
44
- ```ts
45
- then: ({ interactions, expect, seat }) => {
46
- expect(interactions(seat(0))).toHaveInteraction("judgePlacement", {
47
- kind: "prompt",
48
- });
49
-
50
- expect(interactions(seat(1))).not.toHaveInteraction("judgePlacement");
51
- };
52
- ```
53
-
54
- Descriptor matchers are better than ad hoc descriptor shape checks because they
55
- state the rule being tested: present, absent, active, or gated.
56
-
57
- ## Matchers
58
-
59
- Value matchers:
60
-
61
- | Matcher | Purpose |
62
- | --- | --- |
63
- | `toBe(expected)` | Strict equality. |
64
- | `toEqual(expected)` | Deep equality. |
65
- | `toMatchObject(partial)` | Deep partial object match. |
66
- | `toBeDefined()` | Value is not `undefined`. |
67
- | `toBeUndefined()` | Value is `undefined`. |
68
- | `toBeNull()` | Value is `null`. |
69
- | `toContain(expected)` | Array or string contains value. |
70
- | `toContainEqual(expected)` | Array contains a deeply equal value. |
71
- | `toHaveLength(n)` | Value has exact `length`. |
72
- | `toBeGreaterThanOrEqual(n)` | Numeric lower-bound check. |
73
- | `toThrow(predicate?)` | Synchronous throw assertion. |
74
- | `toMatchSnapshot(filename?)` | Scenario snapshot assertion. |
75
-
76
- Async rejection matcher:
77
-
78
- ```ts
79
- await expect(() =>
80
- game.submit(seat(1), "judgePlacement", { decision: "ring-1" }),
81
- ).toRejectWith({
82
- errorCode: "prompt-not-owned",
83
- message: /prompt/i,
84
- });
85
- ```
86
-
87
- Descriptor matchers:
88
-
89
- | Matcher | Purpose |
90
- | --- | --- |
91
- | `toHaveInteraction(id, opts?)` | Descriptor array contains an interaction. |
92
- | `not.toHaveInteraction(id)` | Descriptor array does not contain an interaction. |
93
- | `toBeGatedBy(reason, opts?)` | Descriptor is unavailable with the expected reason. |
94
- | `toBeActiveFor(playerId, opts?)` | Descriptor targets the player and is available. |
95
-
96
- `toBeGatedBy` and `toBeActiveFor` can operate on a descriptor array when you pass
97
- `opts.interactionId`, or on a single descriptor.
98
-
99
- ## Snapshot assertions
100
-
101
- Use snapshots for large projected objects that are intentionally stable:
102
-
103
- ```ts
104
- then: ({ view, expect, seat }) => {
105
- expect(view(seat(0)).market).toMatchSnapshot("market");
106
- };
107
- ```
108
-
109
- Snapshots are written under `test/generated/snapshots/`. When an existing
110
- snapshot differs, the runner fails and tells you to rerun with
111
- `--update-snapshots`.
112
-
113
- Do not snapshot noisy values unless the noise is the point of the test. Prefer
114
- targeted matchers for a specific rule.
115
-
116
- ## Assertion guidelines
117
-
118
- - Assert public behavior: phase, view, available interactions, and rejection
119
- codes.
120
- - Do not assert raw reducer internals unless the view intentionally exposes the
121
- same fact.
122
- - Use descriptor matchers for actor, prompt, and availability rules.
123
- - Use `toRejectWith` for validation and reducer rejection paths.
124
- - Keep the assertion close to the rule the scenario name promises.
@@ -1,148 +0,0 @@
1
- # Scenarios
2
-
3
- Define reducer-native test scenarios with actions, prompts, effects, and assertions.
4
-
5
- A scenario starts from a generated base, submits reducer interactions, and
6
- asserts the resulting phase, view, and interaction descriptors.
7
-
8
- Scenarios live under `test/scenarios/*.scenario.ts`.
9
-
10
- ## Basic scenario
11
-
12
- ```ts
13
- import { defineScenario } from "../testing-types";
14
-
15
- export default defineScenario({
16
- id: "setup-place",
17
- description: "Seat 0 places a marker and path during setup",
18
- from: "initial-turn",
19
- phase: "setup",
20
- when: async ({ game, seat }) => {
21
- await game.submit(seat(0), "placeSetupMarker", {
22
- vertexId: "hex-vertex:-1,-1,2",
23
- });
24
- await game.submit(seat(0), "placeSetupPath", {
25
- edgeId: "hex-edge:-1,-1,2::-2,-2,4",
26
- });
27
- },
28
- then: ({ expect, state, view, seat }) => {
29
- expect(state()).toBe("setup");
30
- expect(view(seat(0)).markersByVertexId["hex-vertex:-1,-1,2"]).toBeDefined();
31
- },
32
- });
33
- ```
34
-
35
- Fields:
36
-
37
- | Field | Required | Meaning |
38
- | --- | --- | --- |
39
- | `id` | Yes | Unique scenario id. |
40
- | `description` | No | Short human-readable summary. |
41
- | `from` | Yes | Base id to start from. |
42
- | `runners` | No | Defaults to `["reducer"]`. Public tests normally omit it. |
43
- | `phase` | No | Expected phase after `when`. Also narrows `view` in `then` when possible. |
44
- | `stage` | No | Expected stage after `when`, constrained by phase. |
45
- | `when` | Yes | Async action flow. |
46
- | `then` | Yes | Assertions. |
47
-
48
- ## Submit interactions
49
-
50
- Use `game.submit(playerId, interactionId, params)`:
51
-
52
- ```ts
53
- await game.submit(seat(1), "placeThingCard", {
54
- cardId: "a-diamond",
55
- ringId: "ring-1",
56
- });
57
- ```
58
-
59
- The `interactionId` is the generated interaction id, not the phase-qualified UI
60
- key. Params are typed from the generated UI contract.
61
-
62
- Prompts use the same submit path:
63
-
64
- ```ts
65
- await game.submit(seat(0), "judgePlacement", {
66
- decision: "ring-1",
67
- });
68
- ```
69
-
70
- There is no separate prompt-response API in the current reducer-native test
71
- contract. If a player can submit it, model it as an interaction.
72
-
73
- ## Phase and stage checks
74
-
75
- Use `phase` when the scenario should end in a known phase:
76
-
77
- ```ts
78
- export default defineScenario({
79
- id: "reject-non-knower-cannot-judge",
80
- from: "after-first-placement",
81
- phase: "judgeRings",
82
- when: async ({ game, seat, expect }) => {
83
- await expect(() =>
84
- game.submit(seat(1), "judgePlacement", { decision: "ring-1" }),
85
- ).toRejectWith({ errorCode: "prompt-not-owned" });
86
- },
87
- then: ({ state, expect }) => {
88
- expect(state()).toBe("judgeRings");
89
- },
90
- });
91
- ```
92
-
93
- The runner checks `phase` after `when` and before `then`. If the reducer reached
94
- a different phase, the scenario fails before assertions run.
95
-
96
- Use `stage` the same way for phase stages:
97
-
98
- ```ts
99
- export default defineScenario({
100
- id: "main-stage-after-roll",
101
- from: "after-setup",
102
- phase: "playerTurn",
103
- stage: "main",
104
- when: async ({ game, seat }) => {
105
- await game.submit(seat(0), "rollDice");
106
- },
107
- then: ({ state, expect }) => {
108
- expect(state()).toBe("playerTurn");
109
- },
110
- });
111
- ```
112
-
113
- ## Rejection scenarios
114
-
115
- Illegal submissions should be tested directly:
116
-
117
- ```ts
118
- await expect(() =>
119
- game.submit(seat(1), "placeThingCard", {
120
- cardId: "a-diamond",
121
- ringId: "ring-1",
122
- }),
123
- ).toRejectWith({ errorCode: "NOT_YOUR_TURN" });
124
- ```
125
-
126
- Then assert the game remained in the expected state:
127
-
128
- ```ts
129
- then: ({ state, interactions, expect, seat }) => {
130
- expect(state()).toBe("placeThing");
131
- expect(interactions(seat(1))).not.toHaveInteraction("judgePlacement");
132
- };
133
- ```
134
-
135
- ## Scenario shape
136
-
137
- Keep `when` focused on the action being exercised. Keep assertions in `then`.
138
- If a setup flow is required by many scenarios, move it into a base.
139
-
140
- Good scenario ids are stable and behavior-oriented:
141
-
142
- - `smoke-initial-turn`
143
- - `setup-place`
144
- - `trade-full-lifecycle`
145
- - `reject-out-of-turn-placement`
146
- - `reject-non-knower-cannot-judge`
147
-
148
- Avoid ids that describe implementation details or temporary bugs.
@@ -1,174 +0,0 @@
1
- # UI tests
2
-
3
- Test workspace UI with reducer-native runtime providers.
4
-
5
- Use `createTestRuntime` for reducer-backed, backend-free React tests that need real
6
- Dreamboard runtime context. It creates an in-memory runtime from a generated
7
- base state, drives the same reducer bundle as scenarios, and feeds snapshots
8
- through the UI host runtime store.
9
-
10
- This is for UI logic tests, not browser end-to-end tests.
11
-
12
- ## Generate first
13
-
14
- UI tests depend on generated base states:
15
-
16
- ```bash
17
- dreamboard test generate
18
- ```
19
-
20
- If the base state is missing or stale, regenerate before debugging React.
21
-
22
- ## Basic harness
23
-
24
- ```tsx
25
- import assert from "node:assert/strict";
26
- import { test } from "node:test";
27
- import React from "react";
28
- import { renderToStaticMarkup } from "react-dom/server";
29
- import {
30
- PluginStateProvider,
31
- RuntimeProvider,
32
- useGameView,
33
- useIsMyTurn,
34
- } from "@dreamboard/ui-sdk";
35
- import { useInteractionByKey } from "../shared/generated/ui-contract";
36
- import { createTestRuntime } from "../test/testing-types";
37
-
38
- function Probe() {
39
- const view = useGameView();
40
- const placeThing = useInteractionByKey("placeThing.placeThingCard");
41
- const isMyTurn = useIsMyTurn();
42
-
43
- return (
44
- <div
45
- data-is-my-turn={isMyTurn ? "true" : "false"}
46
- data-surface={placeThing?.descriptor.surface ?? "missing"}
47
- data-hand-size={view.handCards.length}
48
- />
49
- );
50
- }
51
-
52
- function renderTree(runtime: ReturnType<typeof createTestRuntime>) {
53
- return renderToStaticMarkup(
54
- <RuntimeProvider runtime={runtime.runtime}>
55
- <PluginStateProvider>
56
- <Probe />
57
- </PluginStateProvider>
58
- </RuntimeProvider>,
59
- );
60
- }
61
-
62
- test("renders the initial playable hand", () => {
63
- const runtime = createTestRuntime({
64
- baseId: "initial-turn",
65
- phase: "placeThing",
66
- controllingPlayerId: "player-2",
67
- });
68
-
69
- const markup = renderTree(runtime);
70
-
71
- assert.match(markup, /data-is-my-turn="true"/);
72
- assert.match(markup, /data-surface="hand"/);
73
- assert.match(markup, /data-hand-size="5"/);
74
- });
75
- ```
76
-
77
- The important providers are:
78
-
79
- | Provider | Purpose |
80
- | --- | --- |
81
- | `RuntimeProvider` | Supplies the in-memory `RuntimeAPI`. |
82
- | `PluginStateProvider` | Supplies reducer-projected plugin state to UI hooks. |
83
-
84
- ## Runtime options
85
-
86
- ```ts
87
- const runtime = createTestRuntime({
88
- baseId: "initial-turn",
89
- phase: "placeThing",
90
- controllingPlayerId: "player-2",
91
- userId: "test-user",
92
- });
93
- ```
94
-
95
- Options:
96
-
97
- | Option | Meaning |
98
- | --- | --- |
99
- | `baseId` | Generated base state id. Required. |
100
- | `phase` | Optional expected phase for the initial snapshot. |
101
- | `controllingPlayerId` | Seat controlled by the rendered UI. |
102
- | `userId` | Test user id; defaults to `"test-user"`. |
103
-
104
- `baseId` is typed to generated `BASE_STATES`, so misspelled bases fail at
105
- compile time.
106
-
107
- ## Submitting interactions
108
-
109
- `createTestRuntime` returns helpers for driving state:
110
-
111
- ```tsx
112
- const runtime = createTestRuntime({
113
- baseId: "initial-turn",
114
- phase: "placeThing",
115
- controllingPlayerId: "player-2",
116
- });
117
-
118
- await runtime.submit(runtime.seat(1), "placeThingCard", {
119
- cardId: "a-diamond",
120
- ringId: "ring-1",
121
- });
122
-
123
- const after = renderTree(runtime);
124
- assert.match(after, /data-hand-size="4"/);
125
- ```
126
-
127
- Submission validates input, dispatches through the reducer bundle, applies a
128
- fresh gameplay snapshot, and notifies UI subscribers.
129
-
130
- ## Switching seats
131
-
132
- Use `setControllingPlayer` to test player-specific views:
133
-
134
- ```tsx
135
- runtime.setControllingPlayer("player-3");
136
-
137
- const markup = renderTree(runtime);
138
- assert.match(markup, /data-is-my-turn="false"/);
139
- ```
140
-
141
- This exercises the same session-store path used by host player switching.
142
-
143
- ## What to test here
144
-
145
- Good UI runtime tests:
146
-
147
- - hooks see the expected phase, view, and available interactions
148
- - `useIsMyTurn` and controlling-player changes behave correctly
149
- - custom primitive renderers receive descriptors
150
- - card hands update after reducer submissions
151
- - prompt or blocker UI appears for the addressed seat only
152
-
153
- Avoid testing browser-only layout here. Use the local dev host or browser runner
154
- for screenshots, pointer events, and CSS layout issues.
155
-
156
- ## Projection fixture tests
157
-
158
- For lighter UI probes, read generated base projection JSON and provide a small
159
- mock `RuntimeAPI`. This is useful when the test only needs hooks and render
160
- behavior, not reducer dispatch.
161
-
162
- Star Settlers uses this pattern in `test/ui/app.test.tsx`: it loads
163
- `test/generated/bases/<base>/player-*.projection.json`, wraps probes in
164
- `RuntimeProvider` and `PluginStateProvider`, then asserts that typed hooks such
165
- as `useGameView`, `useInteractionByKey`, and `useBoardInteractions` see the
166
- expected projected state.
167
-
168
- ## TSX runtime config
169
-
170
- Reducer-native UI tests that import React components from workspace or SDK
171
- sources may need a TSX-specific test tsconfig that enables the React JSX
172
- transform for those sources. Keep that config separate from the normal
173
- `test/tsconfig.json`; broadening the normal typecheck include can pull SDK
174
- fixtures into `tsc --noEmit`.