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.
- package/dist/{chunk-EYYWGWTO.js → chunk-2RCUHMGL.js} +343 -1911
- package/dist/chunk-2RCUHMGL.js.map +1 -0
- package/dist/{chunk-MOVHYB6E.js → chunk-AQ5UUNJS.js} +1018 -692
- package/dist/chunk-AQ5UUNJS.js.map +1 -0
- package/dist/{chunk-BMYC6772.js → chunk-H3O43F5P.js} +9765 -3068
- package/dist/chunk-H3O43F5P.js.map +1 -0
- package/dist/dev-host/dev-api-proxy-plugin.ts +330 -0
- package/dist/dev-host/dev-diagnostics.ts +62 -0
- package/dist/dev-host/dev-fallback-stylesheet.ts +50 -0
- package/dist/dev-host/dev-host-controller.ts +686 -0
- package/dist/dev-host/dev-host-player-query.ts +17 -0
- package/dist/dev-host/dev-host-session-transport.ts +52 -0
- package/dist/dev-host/dev-host-storage.ts +56 -0
- package/dist/dev-host/dev-log-relay-plugin.ts +469 -0
- package/dist/dev-host/dev-runtime-config.ts +14 -0
- package/dist/dev-host/dev-runtime-platform.ts +419 -0
- package/dist/dev-host/dev-virtual-modules-plugin.ts +63 -0
- package/dist/dev-host/host-main.css +182 -0
- package/dist/dev-host/host-main.tsx +754 -0
- package/dist/dev-host/index.html +56 -0
- package/dist/dev-host/plugin-main.ts +55 -0
- package/dist/dev-host/plugin.html +24 -0
- package/dist/dev-host/start-dev-server.ts +138 -0
- package/dist/dev-host/virtual-modules.d.ts +27 -0
- package/dist/dist-FEPN3BDN.js +16543 -0
- package/dist/dist-FEPN3BDN.js.map +1 -0
- package/dist/{dist-WJRJNFLI.js → dist-FRURQI7Q.js} +4 -2
- package/dist/index.js +3 -3
- package/dist/internal.js +159 -124
- package/dist/internal.js.map +1 -1
- package/dist/runtime-packages/tailwind-config/shared-styles.css +146 -0
- package/dist/runtime-packages/ui/src/components/.gitkeep +0 -0
- package/dist/runtime-packages/ui/src/components/accordion.tsx +66 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/actions.tsx +65 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/artifact.tsx +147 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/branch.tsx +215 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/canvas.tsx +22 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/chain-of-thought.tsx +228 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/code-block.tsx +179 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/confirmation.tsx +158 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/connection.tsx +28 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/context.tsx +408 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/controls.tsx +18 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/conversation.tsx +97 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/edge.tsx +140 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/image.tsx +24 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/inline-citation.tsx +287 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/loader.tsx +96 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/message.tsx +463 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/node.tsx +71 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/open-in-chat.tsx +365 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/panel.tsx +15 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/plan.tsx +142 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/prompt-input.tsx +1380 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/queue.tsx +274 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/reasoning.tsx +182 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/response.tsx +22 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/shimmer.tsx +64 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/sources.tsx +77 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/suggestion.tsx +53 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/task.tsx +87 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/tool.tsx +165 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/toolbar.tsx +16 -0
- package/dist/runtime-packages/ui/src/components/ai-elements/web-preview.tsx +263 -0
- package/dist/runtime-packages/ui/src/components/alert-dialog.tsx +157 -0
- package/dist/runtime-packages/ui/src/components/alert.tsx +66 -0
- package/dist/runtime-packages/ui/src/components/avatar.tsx +53 -0
- package/dist/runtime-packages/ui/src/components/badge.tsx +46 -0
- package/dist/runtime-packages/ui/src/components/button-group.tsx +83 -0
- package/dist/runtime-packages/ui/src/components/button.tsx +65 -0
- package/dist/runtime-packages/ui/src/components/card.tsx +92 -0
- package/dist/runtime-packages/ui/src/components/carousel.tsx +241 -0
- package/dist/runtime-packages/ui/src/components/collapsible.tsx +33 -0
- package/dist/runtime-packages/ui/src/components/command.tsx +184 -0
- package/dist/runtime-packages/ui/src/components/context-menu.tsx +252 -0
- package/dist/runtime-packages/ui/src/components/counter.tsx +11 -0
- package/dist/runtime-packages/ui/src/components/dialog.tsx +146 -0
- package/dist/runtime-packages/ui/src/components/drawer.tsx +132 -0
- package/dist/runtime-packages/ui/src/components/dropdown-menu.tsx +257 -0
- package/dist/runtime-packages/ui/src/components/form.tsx +168 -0
- package/dist/runtime-packages/ui/src/components/header.tsx +13 -0
- package/dist/runtime-packages/ui/src/components/hover-card.tsx +44 -0
- package/dist/runtime-packages/ui/src/components/input-group.tsx +178 -0
- package/dist/runtime-packages/ui/src/components/input.tsx +21 -0
- package/dist/runtime-packages/ui/src/components/item.tsx +193 -0
- package/dist/runtime-packages/ui/src/components/label.tsx +24 -0
- package/dist/runtime-packages/ui/src/components/navigation-menu.tsx +168 -0
- package/dist/runtime-packages/ui/src/components/popover.tsx +55 -0
- package/dist/runtime-packages/ui/src/components/progress.tsx +31 -0
- package/dist/runtime-packages/ui/src/components/radio-group.tsx +45 -0
- package/dist/runtime-packages/ui/src/components/resizable.tsx +56 -0
- package/dist/runtime-packages/ui/src/components/scroll-area.tsx +58 -0
- package/dist/runtime-packages/ui/src/components/select.tsx +187 -0
- package/dist/runtime-packages/ui/src/components/separator.tsx +28 -0
- package/dist/runtime-packages/ui/src/components/skeleton.tsx +13 -0
- package/dist/runtime-packages/ui/src/components/sonner.tsx +25 -0
- package/dist/runtime-packages/ui/src/components/spinner.tsx +16 -0
- package/dist/runtime-packages/ui/src/components/switch.tsx +31 -0
- package/dist/runtime-packages/ui/src/components/table.tsx +137 -0
- package/dist/runtime-packages/ui/src/components/tabs.tsx +74 -0
- package/dist/runtime-packages/ui/src/components/textarea.tsx +23 -0
- package/dist/runtime-packages/ui/src/components/theme-provider.tsx +73 -0
- package/dist/runtime-packages/ui/src/components/tooltip.tsx +61 -0
- package/dist/runtime-packages/ui/src/components/ui/file-upload.tsx +195 -0
- package/dist/runtime-packages/ui/src/hooks/.gitkeep +0 -0
- package/dist/runtime-packages/ui/src/index.ts +68 -0
- package/dist/runtime-packages/ui/src/lib/utils.ts +6 -0
- package/dist/runtime-packages/ui-host-runtime/src/actor-principal.ts +68 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/host-controls.tsx +359 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback-toaster.tsx +274 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/host-feedback.tsx +214 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/host-session-metadata.tsx +135 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/index.ts +5 -0
- package/dist/runtime-packages/ui-host-runtime/src/components/perf-overlay.tsx +194 -0
- package/dist/runtime-packages/ui-host-runtime/src/host-controls.tsx +1 -0
- package/dist/runtime-packages/ui-host-runtime/src/host-feedback.tsx +1 -0
- package/dist/runtime-packages/ui-host-runtime/src/host-session-transport.ts +162 -0
- package/dist/runtime-packages/ui-host-runtime/src/index.ts +2 -0
- package/dist/runtime-packages/ui-host-runtime/src/logger.ts +11 -0
- package/dist/runtime-packages/ui-host-runtime/src/perf.ts +253 -0
- package/dist/runtime-packages/ui-host-runtime/src/plugin-bridge.ts +195 -0
- package/dist/runtime-packages/ui-host-runtime/src/plugin-health-check.ts +138 -0
- package/dist/runtime-packages/ui-host-runtime/src/plugin-messages.ts +159 -0
- package/dist/runtime-packages/ui-host-runtime/src/plugin-session-gateway.ts +524 -0
- package/dist/runtime-packages/ui-host-runtime/src/runtime/index.ts +12 -0
- package/dist/runtime-packages/ui-host-runtime/src/screenshot/projection-to-snapshot.ts +122 -0
- package/dist/runtime-packages/ui-host-runtime/src/screenshot/static-store-api.ts +26 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-ingress-controller.ts +477 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-ingress.ts +209 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-live-runtime.ts +112 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-model.ts +318 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-projection.ts +211 -0
- package/dist/runtime-packages/ui-host-runtime/src/session-state-reducer.ts +814 -0
- package/dist/runtime-packages/ui-host-runtime/src/sse-manager.ts +334 -0
- package/dist/runtime-packages/ui-host-runtime/src/unified-session-store.ts +180 -0
- package/dist/scaffold/assets/static/app/tsconfig.framework.json +3 -1
- package/dist/scaffold/assets/static/ui/tsconfig.framework.json +7 -19
- package/package.json +52 -17
- package/skills/dreamboard/SKILL.md +41 -75
- package/LICENSE +0 -89
- package/NOTICE +0 -1
- package/dist/chunk-BMYC6772.js.map +0 -1
- package/dist/chunk-EYYWGWTO.js.map +0 -1
- package/dist/chunk-MOVHYB6E.js.map +0 -1
- package/dist/scaffold/assets/static/ui/App.tsx +0 -22
- package/dist/src-CUL7EGGG.js +0 -634
- package/dist/src-CUL7EGGG.js.map +0 -1
- package/skills/dreamboard/references/authoring-lifecycle.md +0 -102
- package/skills/dreamboard/references/board-surfaces.md +0 -36
- package/skills/dreamboard/references/board-topology.md +0 -443
- package/skills/dreamboard/references/boards-and-topology.md +0 -100
- package/skills/dreamboard/references/card-actions.md +0 -107
- package/skills/dreamboard/references/cli.md +0 -120
- package/skills/dreamboard/references/core-concepts.md +0 -514
- package/skills/dreamboard/references/custom-renderers.md +0 -26
- package/skills/dreamboard/references/derived-values.md +0 -55
- package/skills/dreamboard/references/effects.md +0 -111
- package/skills/dreamboard/references/game-contract.md +0 -89
- package/skills/dreamboard/references/game-definition.md +0 -89
- package/skills/dreamboard/references/game-shell.md +0 -80
- package/skills/dreamboard/references/hand-surfaces.md +0 -33
- package/skills/dreamboard/references/index.md +0 -112
- package/skills/dreamboard/references/inputs-and-targets.md +0 -160
- package/skills/dreamboard/references/interactions.md +0 -158
- package/skills/dreamboard/references/manifest-fields.md +0 -137
- package/skills/dreamboard/references/manifest.md +0 -81
- package/skills/dreamboard/references/package-surfaces.md +0 -69
- package/skills/dreamboard/references/phases.md +0 -145
- package/skills/dreamboard/references/prompts-and-choices.md +0 -55
- package/skills/dreamboard/references/quickstart.md +0 -71
- package/skills/dreamboard/references/rule-authoring.md +0 -144
- package/skills/dreamboard/references/setup-bootstrap.md +0 -78
- package/skills/dreamboard/references/stages-and-zones.md +0 -59
- package/skills/dreamboard/references/static-views.md +0 -67
- package/skills/dreamboard/references/table-queries-and-ops.md +0 -103
- package/skills/dreamboard/references/testing-bases.md +0 -147
- package/skills/dreamboard/references/testing-generated-contracts.md +0 -142
- package/skills/dreamboard/references/testing-runtime-assertions.md +0 -124
- package/skills/dreamboard/references/testing-scenarios.md +0 -148
- package/skills/dreamboard/references/testing-ui-tests.md +0 -174
- package/skills/dreamboard/references/testing.md +0 -161
- package/skills/dreamboard/references/ui-architecture.md +0 -137
- package/skills/dreamboard/references/ui-components.md +0 -34
- package/skills/dreamboard/references/views.md +0 -72
- package/skills/dreamboard/references/workspace-layout.md +0 -136
- /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`.
|