@crazx/dsh-client-test-runtime 0.1.5-alpha.1.zw.3 → 0.1.5-rc.1.zw.2
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.i18n.yaml +2 -2
- package/README.md +3 -1
- package/README.zh.md +15 -13
- package/lib/index.js +28 -16
- package/lib/types/index.d.ts +13 -3
- package/lib/types/sessions.d.ts +0 -5
- package/package.json +30 -29
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/test-support/client-runtime/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 0b6caf7237520ca1a10fe0bbdf3c12c6d793461f
|
|
6
|
+
README.zh.md: ce78a0ad623247ad769e0ea91895daa1db8e7f1b
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ This package gives a browser feature spec a real runtime to mount against: creat
|
|
|
29
29
|
|
|
30
30
|
### Setting up a feature spec
|
|
31
31
|
|
|
32
|
-
`SlotTestRuntime.create()` assembles the runtime, `declare(children)` registers an auto frame whose per-key `<div data-slot>` wrappers become snapshot roots, `mount(plugin)` runs the feature on a real fiber, and `renderSlot(key, owner)` returns the slot-local view with scoped queries and in-place updates:
|
|
32
|
+
`SlotTestRuntime.create()` assembles the runtime, `declare(children)` registers an auto frame whose per-key `<div data-slot>` wrappers become snapshot roots, `mount(plugin)` runs the feature on a real fiber, and `renderSlot(key, owner, opts?)` returns the slot-local view with scoped queries and in-place updates:
|
|
33
33
|
|
|
34
34
|
```text
|
|
35
35
|
const runtime = await SlotTestRuntime.create()
|
|
@@ -42,6 +42,8 @@ await runtime.dispose()
|
|
|
42
42
|
|
|
43
43
|
`mount` prechecks required services and fails loud when one is missing — `provide(name, value)` supplies an extra service first. The runtime provides an unavailable `fileUpload` stub so assemblies can mount; replace `runtime.fileUpload.upload` before mounting when a test exercises upload behavior. `storeOf(key, scopeKey)` returns the live store instance the renderer hands a slot's component for identity and action-driven-write assertions.
|
|
44
44
|
|
|
45
|
+
The optional render options select a keyed entry with `entryKey` or a list item with `only`; `view.update(owner)` retains that selection. `runtime.panelInfo` supplies the default `usePanelInfo` source with no global panel selected. Release it with `releasePanelInfoSource()` before mounting the production Layout owner. `dispose()` releases both default Workspace and panel-info root sources; early release is idempotent and does not remove replacement owners.
|
|
46
|
+
|
|
45
47
|
### Local DOM snapshots
|
|
46
48
|
|
|
47
49
|
A registered snapshot serializer folds CSS-module class hashes (`_frame_a1b2c3` → `frame`) so `.snap` files stay structural, and collapses `<svg>` internals to a `data-content` fingerprint. Suites needing a custom page frame use `root.declare(children, Frame)` instead of the auto frame; `dispose()` tears down views, feature fibers, minted scopes, and persisted store state on one axis and is idempotent.
|
package/README.zh.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "面向浏览器功能测试的 jsdom slot 测试运行时,供测试作者针对生产机制检验 slot
|
|
2
|
+
description: "面向浏览器功能测试的 jsdom slot 测试运行时,供测试作者针对生产机制检验 slot、存储与渲染。"
|
|
3
3
|
kind: "package-library"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -9,7 +9,7 @@ kind: "package-library"
|
|
|
9
9
|
|
|
10
10
|
## 概述
|
|
11
11
|
|
|
12
|
-
`dsh-client-test-runtime` 让浏览器功能测试在 jsdom 中检验生产 slot
|
|
12
|
+
`dsh-client-test-runtime` 让浏览器功能测试在 jsdom 中检验生产 slot、存储、渲染、更新与销毁行为,而无需重实现 UI 运行时。测试作者可以发布带类型的 Session、Workspace、projection 与 Conversation fixture(测试前置数据),查询 slot 局部 DOM 根,并脚本化 Remote 应答或失败。缺失服务、未打桩的会话行为与意外文件上传都会在调用点失败,销毁则保持幂等。仅限仓内、面向浏览器的 Vitest 套件通过 `devDependencies` 使用本包;它不是产品插件或通用 Node 测试 harness。
|
|
13
13
|
|
|
14
14
|
## 目录
|
|
15
15
|
|
|
@@ -29,7 +29,7 @@ kind: "package-library"
|
|
|
29
29
|
|
|
30
30
|
### 搭建功能测试
|
|
31
31
|
|
|
32
|
-
`SlotTestRuntime.create()` 组装运行时,`declare(children)` 注册一个自动 frame,其逐 key 的 `<div data-slot>` 包裹层成为快照根,`mount(plugin)` 在真实 fiber 上运行功能,`renderSlot(key, owner)` 返回带限定查询与原位更新的 slot 局部视图:
|
|
32
|
+
`SlotTestRuntime.create()` 组装运行时,`declare(children)` 注册一个自动 frame,其逐 key 的 `<div data-slot>` 包裹层成为快照根,`mount(plugin)` 在真实 fiber 上运行功能,`renderSlot(key, owner, opts?)` 返回带限定查询与原位更新的 slot 局部视图:
|
|
33
33
|
|
|
34
34
|
```text
|
|
35
35
|
const runtime = await SlotTestRuntime.create()
|
|
@@ -40,11 +40,13 @@ expect(view.container).toMatchSnapshot()
|
|
|
40
40
|
await runtime.dispose()
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
`mount` 会预检必需服务,缺失时自明报错——先用 `provide(name, value)` 提供额外服务。运行时会提供不可用的 `fileUpload` 替身,使装配可以挂载;测试上传行为时,需要在挂载前替换 `runtime.fileUpload.upload`。`storeOf(key, scopeKey)` 返回渲染器交给 slot
|
|
43
|
+
`mount` 会预检必需服务,缺失时自明报错——先用 `provide(name, value)` 提供额外服务。运行时会提供不可用的 `fileUpload` 替身,使装配可以挂载;测试上传行为时,需要在挂载前替换 `runtime.fileUpload.upload`。`storeOf(key, scopeKey)` 返回渲染器交给 slot 组件的实时存储实例,用于身份与动作驱动写入断言。
|
|
44
|
+
|
|
45
|
+
可选渲染参数通过 `entryKey` 选择 keyed 条目,或通过 `only` 选择 list 条目;`view.update(owner)` 保留该选择。`runtime.panelInfo` 提供默认的 `usePanelInfo` 数据源,初始不选中全局面板。挂载生产 Layout 所有者之前,先调用 `releasePanelInfoSource()` 释放该数据源。`dispose()` 同时释放默认的工作区与面板信息根数据源;提前释放是幂等的,不会移除替代它们的所有者。
|
|
44
46
|
|
|
45
47
|
### 局部 DOM 快照
|
|
46
48
|
|
|
47
|
-
注册的快照序列化器把 CSS-module 哈希类名折回语义名(`_frame_a1b2c3` → `frame`),使 `.snap` 文件只含结构,并把 `<svg>` 内部折叠为 `data-content` 指纹。需要自定义页面 frame 的套件改用 `root.declare(children, Frame)` 而非自动 frame;`dispose()`
|
|
49
|
+
注册的快照序列化器把 CSS-module 哈希类名折回语义名(`_frame_a1b2c3` → `frame`),使 `.snap` 文件只含结构,并把 `<svg>` 内部折叠为 `data-content` 指纹。需要自定义页面 frame 的套件改用 `root.declare(children, Frame)` 而非自动 frame;`dispose()` 沿单一轴拆除视图、功能 fiber、已铸 scope 与持久化存储状态,且幂等。
|
|
48
50
|
|
|
49
51
|
### 脚本化 Remote 应答与失败
|
|
50
52
|
|
|
@@ -64,7 +66,7 @@ expect(view.getByRole('alert')).toHaveTextContent('goal/not-found')
|
|
|
64
66
|
|
|
65
67
|
### 何时使用
|
|
66
68
|
|
|
67
|
-
当功能套件要在真实运行时下检验 slot
|
|
69
|
+
当功能套件要在真实运行时下检验 slot、存储、渲染与销毁时使用本测试台——生产 `SlotRegistry`、渲染器与 provide bundle 物化都会被挂载,绝不重实现。它是浏览器侧测试基础设施:永远不触及模型请求,功能包仅以 `devDependencies` 依赖之。
|
|
68
70
|
|
|
69
71
|
### 可能出什么问题
|
|
70
72
|
|
|
@@ -84,7 +86,7 @@ expect(view.getByRole('alert')).toHaveTextContent('goal/not-found')
|
|
|
84
86
|
|
|
85
87
|
### 设计
|
|
86
88
|
|
|
87
|
-
测试台不复制生产逻辑:它挂载生产 `SlotRegistry`、生产渲染器与 `UiSession` 适配器。`TestSessions` 与 `TestWorkspaces` 实现功能通过 Cordis 消费的 owner 接口,每个 fixture Session 实现 `SessionFace`,`stubSettingsScope` 实现 `SettingsScope`。`UiSession`
|
|
89
|
+
测试台不复制生产逻辑:它挂载生产 `SlotRegistry`、生产渲染器与 `UiSession` 适配器。`TestSessions` 与 `TestWorkspaces` 实现功能通过 Cordis 消费的 owner 接口,每个 fixture Session 实现 `SessionFace`,`stubSettingsScope` 实现 `SettingsScope`。`UiSession` 从这些控制器绑定派生标准渲染器数据源。未 stub 的 `ISession` 行为会携缺失方法名失败。
|
|
88
90
|
|
|
89
91
|
### 源码地图
|
|
90
92
|
|
|
@@ -97,11 +99,11 @@ expect(view.getByRole('alert')).toHaveTextContent('goal/not-found')
|
|
|
97
99
|
| [`src/remote.ts`](src/remote.ts) | 用于 host RPC 的 `TestRemote` 替身、`RemoteError` 值转出 |
|
|
98
100
|
| [`src/translate.ts`](src/translate.ts) + [`src/locale-env.ts`](src/locale-env.ts) | 翻译与固定浏览器语言测试辅助 |
|
|
99
101
|
| [`src/settings-scope.ts`](src/settings-scope.ts) | 带测试驱动发布与写入 spy 的 `stubSettingsScope` |
|
|
100
|
-
| — |
|
|
102
|
+
| — | 不发布运行时不变式伴生入口;本测试支持包不拥有任何生产事件流或可变数据;它围绕测试替身组装运行时 SlotRegistry 与渲染器,其所属包拥有各自的不变式;本包自身行为由本包测试检验。 |
|
|
101
103
|
|
|
102
104
|
### 生命周期
|
|
103
105
|
|
|
104
|
-
`create()` 构建全新上下文,挂载 slot 与会话注册表,安装渲染器,并提供 session/workspace 替身和明确失败的文件上传替身。`mount` 在启动 fiber 前对照上下文检查每个已声明注入,使缺失提供方自明报错而非永久挂起。`dispose()` 先卸载 React 树,再 dispose
|
|
106
|
+
`create()` 构建全新上下文,挂载 slot 与会话注册表,安装渲染器,并提供 session/workspace 替身和明确失败的文件上传替身。`mount` 在启动 fiber 前对照上下文检查每个已声明注入,使缺失提供方自明报错而非永久挂起。`dispose()` 先卸载 React 树,再 dispose 功能 fiber、释放根注册、dispose 已铸 session scope 并清除持久化存储状态;每个公共修改器都包裹在 act 中,因此测试无需自行处理 SlotCore 微任务批处理或 React `act`。
|
|
105
107
|
|
|
106
108
|
</details>
|
|
107
109
|
|
|
@@ -112,7 +114,7 @@ expect(view.getByRole('alert')).toHaveTextContent('goal/not-found')
|
|
|
112
114
|
|
|
113
115
|
当包级约定不够用时阅读以下页面。它们从测试台逐步进入它所挂载的生产机制以及使用它的测试。
|
|
114
116
|
|
|
115
|
-
- [ui-session](../../client/ui-session/README.zh.md)
|
|
117
|
+
- [ui-session](../../client/ui-session/README.zh.md)——从控制器替身派生标准 Slot 数据源的生产适配器。
|
|
116
118
|
- [UI slots 包](../../client/ui-slots/README.zh.md)——测试台挂载的 `SlotRegistry` 约定。
|
|
117
119
|
- [UI renderer 包](../../client/ui-renderer/README.zh.md)——测试台安装的渲染器。
|
|
118
120
|
- [测试策略](../../../docs/testing.zh.md)——覆盖层级与浏览器快照流水线。
|
|
@@ -123,7 +125,7 @@ expect(view.getByRole('alert')).toHaveTextContent('goal/not-found')
|
|
|
123
125
|
<a id="model-experience"></a>
|
|
124
126
|
## 模型体验
|
|
125
127
|
|
|
126
|
-
|
|
128
|
+
无;本包是浏览器侧测试基础设施,不会发起任何模型请求。
|
|
127
129
|
|
|
128
130
|
#### KV Cache 影响
|
|
129
131
|
|
|
@@ -136,8 +138,8 @@ expect(view.getByRole('alert')).toHaveTextContent('goal/not-found')
|
|
|
136
138
|
|
|
137
139
|
这些限制说明本测试台如何被消费。它们是当前包约束,不是任务积压。
|
|
138
140
|
|
|
139
|
-
- **仅限 Vitest 与 jsdom**——所有消费方都是仓内、面向浏览器的 Vitest 套件。本包不是产品插件,也不是通用 Node
|
|
140
|
-
- **Session、Conversation 与 Chat fixture 保持分离**——`sessionSnapshot` 只包含 Session
|
|
141
|
+
- **仅限 Vitest 与 jsdom**——所有消费方都是仓内、面向浏览器的 Vitest 套件。本包不是产品插件,也不是通用 Node 测试 harness。
|
|
142
|
+
- **Session、Conversation 与 Chat fixture 保持分离**——`sessionSnapshot` 只包含 Session 控制器状态,`conversationSnapshot` 包含与目标无关的 Conversation 状态,`chatSnapshot` 包含 Chat 目标状态。组装测试提供 Session 事件条目,而不是向 `SessionSnapshot` 添加 Conversation 或 Chat 字段。
|
|
141
143
|
|
|
142
144
|
<a id="dev-note"></a>
|
|
143
145
|
### 开发备注
|
package/lib/index.js
CHANGED
|
@@ -5,9 +5,9 @@ import { SlotRegistry } from "@deepseek-ai/dsh-client-ui-renderer/client";
|
|
|
5
5
|
import { bindSnapshotSelector as bindSnapshotSelector$1 } from "@deepseek-ai/dsh-client-ui-renderer/src/client/bind.ts";
|
|
6
6
|
import { createSlotRenderer as createSlotRenderer$1 } from "@deepseek-ai/dsh-client-ui-renderer/src/client/scoped-slots.tsx";
|
|
7
7
|
import { apply, inject } from "@deepseek-ai/dsh-client-ui-session/client";
|
|
8
|
+
import { createSnapshotStore } from "@deepseek-ai/dsh-client-store";
|
|
8
9
|
import { afterEach, beforeEach, expect, vi } from "vitest";
|
|
9
10
|
import { MutableSessionEventSource, SESSION_SEARCH_RESULT_LIMIT, createScope, scopeOf } from "@deepseek-ai/dsh-api-session-controller/client";
|
|
10
|
-
import { createSnapshotStore } from "@deepseek-ai/dsh-client-store";
|
|
11
11
|
import { EMPTY_CONVERSATION_SNAPSHOT } from "@deepseek-ai/dsh-client-ui-conversation/client";
|
|
12
12
|
import { EMPTY_CHAT_SNAPSHOT } from "@deepseek-ai/dsh-client-ui-chat/client";
|
|
13
13
|
import { RemoteError } from "@deepseek-ai/dsh-typert-protocol";
|
|
@@ -584,15 +584,6 @@ var TestSessions = class {
|
|
|
584
584
|
draft.currentAddress = void 0;
|
|
585
585
|
});
|
|
586
586
|
}
|
|
587
|
-
/** History stubs: the test runtime has no selection history — both bounds report empty. */
|
|
588
|
-
canBack() {
|
|
589
|
-
return false;
|
|
590
|
-
}
|
|
591
|
-
canForward() {
|
|
592
|
-
return false;
|
|
593
|
-
}
|
|
594
|
-
back() {}
|
|
595
|
-
forward() {}
|
|
596
587
|
/** Record a list refresh; fixture callers publish list state explicitly. */
|
|
597
588
|
refresh() {
|
|
598
589
|
this.calls.push({
|
|
@@ -1124,9 +1115,13 @@ var OwnerPropsCell = class {
|
|
|
1124
1115
|
* caller wraps in act).
|
|
1125
1116
|
* @param key - slot key.
|
|
1126
1117
|
* @param owner - owner props share.
|
|
1118
|
+
* @param opts - explicit keyed or list selection for the render site.
|
|
1127
1119
|
*/
|
|
1128
|
-
set(key, owner) {
|
|
1129
|
-
this.owners.set(key,
|
|
1120
|
+
set(key, owner, opts) {
|
|
1121
|
+
this.owners.set(key, {
|
|
1122
|
+
owner,
|
|
1123
|
+
opts
|
|
1124
|
+
});
|
|
1130
1125
|
this.version += 1;
|
|
1131
1126
|
for (const fn of [...this.listeners]) fn();
|
|
1132
1127
|
}
|
|
@@ -1191,6 +1186,10 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1191
1186
|
sessions;
|
|
1192
1187
|
/** Workspaces double (list observable, recorded intent actions). */
|
|
1193
1188
|
workspaces;
|
|
1189
|
+
/** Test-owned panel selection used by the framework's usePanelInfo hook. */
|
|
1190
|
+
panelInfo = createSnapshotStore({ activePanelId: null });
|
|
1191
|
+
/** Test-owned toolbar portal hosts used by the framework's useToolbarHosts hook (null = no toolbar). */
|
|
1192
|
+
toolbarHosts = createSnapshotStore(null);
|
|
1194
1193
|
/** Mutable file-upload stub; replace `upload` in suites that exercise the capability. */
|
|
1195
1194
|
fileUpload;
|
|
1196
1195
|
stabilizer = async (fn) => {
|
|
@@ -1207,6 +1206,8 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1207
1206
|
autoDeclared = /* @__PURE__ */ new Set();
|
|
1208
1207
|
autoRootView;
|
|
1209
1208
|
disposeWorkspaceSource;
|
|
1209
|
+
disposePanelInfoSource;
|
|
1210
|
+
disposeToolbarHostsSource;
|
|
1210
1211
|
constructor(ctx, slots) {
|
|
1211
1212
|
this.ctx = ctx;
|
|
1212
1213
|
this.slots = slots;
|
|
@@ -1221,6 +1222,8 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1221
1222
|
ctx.provide("workspaces", this.workspaces);
|
|
1222
1223
|
ctx.provide("fileUpload", this.fileUpload);
|
|
1223
1224
|
this.disposeWorkspaceSource = slots.provideRoot({ hooks: { workspaces: this.workspaces.list } });
|
|
1225
|
+
this.disposePanelInfoSource = slots.provideRoot({ hooks: { panelInfo: this.panelInfo } });
|
|
1226
|
+
this.disposeToolbarHostsSource = slots.provideRoot({ hooks: { toolbarHosts: this.toolbarHosts } });
|
|
1224
1227
|
const renderer = createSlotRenderer();
|
|
1225
1228
|
slots.install({ renderRoot: (host, ownerProps) => {
|
|
1226
1229
|
this.host = host;
|
|
@@ -1273,6 +1276,11 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1273
1276
|
releaseWorkspaceSource() {
|
|
1274
1277
|
this.disposeWorkspaceSource();
|
|
1275
1278
|
}
|
|
1279
|
+
/** Release the default panel hook before mounting the production Layout owner. */
|
|
1280
|
+
releasePanelInfoSource() {
|
|
1281
|
+
this.disposePanelInfoSource();
|
|
1282
|
+
this.disposeToolbarHostsSource();
|
|
1283
|
+
}
|
|
1276
1284
|
/**
|
|
1277
1285
|
* Render the root slot tree through the ctx-level entry (the shell's own
|
|
1278
1286
|
* entry point): `ctx.slots.renderSlot('root', {})` under Testing Library.
|
|
@@ -1298,7 +1306,7 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1298
1306
|
const cell = this.ownerCell;
|
|
1299
1307
|
const AutoFrame = (props) => {
|
|
1300
1308
|
useSyncExternalStore(cell.subscribe, cell.getVersion);
|
|
1301
|
-
return createElement(Fragment, null, cell.entries().map(([key, owner]) => createElement(Fragment, { key }, props.renderSlot(key, owner))));
|
|
1309
|
+
return createElement(Fragment, null, cell.entries().map(([key, { owner, opts }]) => createElement(Fragment, { key }, props.renderSlot(key, owner, opts))));
|
|
1302
1310
|
};
|
|
1303
1311
|
await this.root.declare(children, AutoFrame);
|
|
1304
1312
|
}
|
|
@@ -1310,13 +1318,14 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1310
1318
|
* slot of the same tree.
|
|
1311
1319
|
* @param key - a key declared through {@link SlotTestRuntime.declare}.
|
|
1312
1320
|
* @param owner - owner props share for the render site.
|
|
1321
|
+
* @param opts - explicit keyed or list selection; retained by view updates.
|
|
1313
1322
|
* @returns the slot-local view (snapshot container, scoped queries, owner updates).
|
|
1314
1323
|
*/
|
|
1315
|
-
renderSlot(key, owner) {
|
|
1324
|
+
renderSlot(key, owner, opts) {
|
|
1316
1325
|
if (!this.autoDeclared.has(key)) throw new Error(`renderSlot('${key}') without declare() — declare the key first (or use root.declare for a custom frame)`);
|
|
1317
1326
|
const install = (next) => {
|
|
1318
1327
|
act(() => {
|
|
1319
|
-
this.ownerCell.set(key, next);
|
|
1328
|
+
this.ownerCell.set(key, next, opts);
|
|
1320
1329
|
});
|
|
1321
1330
|
};
|
|
1322
1331
|
install(owner);
|
|
@@ -1358,7 +1367,7 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1358
1367
|
}
|
|
1359
1368
|
/**
|
|
1360
1369
|
* Tear down: unmount React trees first, then dispose feature fibers, the
|
|
1361
|
-
* root registration, minted session scopes, and persisted test state.
|
|
1370
|
+
* root registration and standard sources, minted session scopes, and persisted test state.
|
|
1362
1371
|
* Idempotent.
|
|
1363
1372
|
* @returns completion of the teardown.
|
|
1364
1373
|
*/
|
|
@@ -1369,6 +1378,9 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1369
1378
|
for (const view of this.views.splice(0)) view.unmount();
|
|
1370
1379
|
for (const handle of this.handles.splice(0)) await handle.dispose();
|
|
1371
1380
|
this.root.release();
|
|
1381
|
+
this.disposeWorkspaceSource();
|
|
1382
|
+
this.disposePanelInfoSource();
|
|
1383
|
+
this.disposeToolbarHostsSource();
|
|
1372
1384
|
await this.sessions.disposeScopes();
|
|
1373
1385
|
localStorage.clear();
|
|
1374
1386
|
}
|
package/lib/types/index.d.ts
CHANGED
|
@@ -17,7 +17,8 @@ import type { queries } from '@testing-library/dom';
|
|
|
17
17
|
import type { BoundFunctions } from '@testing-library/dom';
|
|
18
18
|
import { SlotRegistry } from '@deepseek-ai/dsh-client-ui-renderer/client';
|
|
19
19
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
20
|
-
import type {
|
|
20
|
+
import type { PanelInfo, ToolbarHosts } from '@deepseek-ai/dsh-client-ui-layout/client';
|
|
21
|
+
import type { ChildrenDecl, ComposedProps, HostObservable, OwnerOf, RenderOpts, SlotComponent, SlotMap, SlotRenderer, SnapshotSelectorHook, StoreInstanceLike } from '@deepseek-ai/dsh-client-ui-slots';
|
|
21
22
|
import { TestSessions } from './sessions.ts';
|
|
22
23
|
import { TestWorkspaces } from './workspaces.ts';
|
|
23
24
|
import type { Stabilizer } from './fixtures.ts';
|
|
@@ -128,6 +129,10 @@ export declare class SlotTestRuntime {
|
|
|
128
129
|
readonly sessions: TestSessions;
|
|
129
130
|
/** Workspaces double (list observable, recorded intent actions). */
|
|
130
131
|
readonly workspaces: TestWorkspaces;
|
|
132
|
+
/** Test-owned panel selection used by the framework's usePanelInfo hook. */
|
|
133
|
+
readonly panelInfo: import("@deepseek-ai/dsh-client-store").SnapshotStore<PanelInfo>;
|
|
134
|
+
/** Test-owned toolbar portal hosts used by the framework's useToolbarHosts hook (null = no toolbar). */
|
|
135
|
+
readonly toolbarHosts: import("@deepseek-ai/dsh-client-store").SnapshotStore<ToolbarHosts | null>;
|
|
131
136
|
/** Mutable file-upload stub; replace `upload` in suites that exercise the capability. */
|
|
132
137
|
readonly fileUpload: TestFileUpload;
|
|
133
138
|
private readonly stabilizer;
|
|
@@ -140,6 +145,8 @@ export declare class SlotTestRuntime {
|
|
|
140
145
|
private readonly autoDeclared;
|
|
141
146
|
private autoRootView;
|
|
142
147
|
private readonly disposeWorkspaceSource;
|
|
148
|
+
private readonly disposePanelInfoSource;
|
|
149
|
+
private readonly disposeToolbarHostsSource;
|
|
143
150
|
private constructor();
|
|
144
151
|
/**
|
|
145
152
|
* Assemble a runtime: real Context, mounted SlotRegistry, installed
|
|
@@ -157,6 +164,8 @@ export declare class SlotTestRuntime {
|
|
|
157
164
|
mount(plugin: Plugin): Promise<FeatureHandle>;
|
|
158
165
|
/** Release the default Workspace hook before mounting its production owner. */
|
|
159
166
|
releaseWorkspaceSource(): void;
|
|
167
|
+
/** Release the default panel hook before mounting the production Layout owner. */
|
|
168
|
+
releasePanelInfoSource(): void;
|
|
160
169
|
/**
|
|
161
170
|
* Render the root slot tree through the ctx-level entry (the shell's own
|
|
162
171
|
* entry point): `ctx.slots.renderSlot('root', {})` under Testing Library.
|
|
@@ -182,9 +191,10 @@ export declare class SlotTestRuntime {
|
|
|
182
191
|
* slot of the same tree.
|
|
183
192
|
* @param key - a key declared through {@link SlotTestRuntime.declare}.
|
|
184
193
|
* @param owner - owner props share for the render site.
|
|
194
|
+
* @param opts - explicit keyed or list selection; retained by view updates.
|
|
185
195
|
* @returns the slot-local view (snapshot container, scoped queries, owner updates).
|
|
186
196
|
*/
|
|
187
|
-
renderSlot<K extends keyof SlotMap & string>(key: K, owner: OwnerOf<K
|
|
197
|
+
renderSlot<K extends keyof SlotMap & string>(key: K, owner: OwnerOf<K>, opts?: RenderOpts): SlotView<K>;
|
|
188
198
|
/**
|
|
189
199
|
* Resolve the store instance the renderer would hand a slot's component
|
|
190
200
|
* (identity assertions, action-driven writes). Requires a prior
|
|
@@ -203,7 +213,7 @@ export declare class SlotTestRuntime {
|
|
|
203
213
|
flush(): Promise<void>;
|
|
204
214
|
/**
|
|
205
215
|
* Tear down: unmount React trees first, then dispose feature fibers, the
|
|
206
|
-
* root registration, minted session scopes, and persisted test state.
|
|
216
|
+
* root registration and standard sources, minted session scopes, and persisted test state.
|
|
207
217
|
* Idempotent.
|
|
208
218
|
* @returns completion of the teardown.
|
|
209
219
|
*/
|
package/lib/types/sessions.d.ts
CHANGED
|
@@ -226,11 +226,6 @@ export declare class TestSessions implements ISessions {
|
|
|
226
226
|
refreshSubagents(parentSessionId: SessionId): Promise<void>;
|
|
227
227
|
/** Clear the current selection (recorded; the production no-session flow). */
|
|
228
228
|
clear(): void;
|
|
229
|
-
/** History stubs: the test runtime has no selection history — both bounds report empty. */
|
|
230
|
-
canBack(): boolean;
|
|
231
|
-
canForward(): boolean;
|
|
232
|
-
back(): void;
|
|
233
|
-
forward(): void;
|
|
234
229
|
/** Record a list refresh; fixture callers publish list state explicitly. */
|
|
235
230
|
refresh(): Promise<void>;
|
|
236
231
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crazx/dsh-client-test-runtime",
|
|
3
3
|
"description": "jsdom slot test runtime: real Cordis Context + SlotRegistry + UI renderer with test-owned session/workspace doubles for feature specs",
|
|
4
|
-
"version": "0.1.5-
|
|
4
|
+
"version": "0.1.5-rc.1.zw.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -28,39 +28,40 @@
|
|
|
28
28
|
"vitest": "^4.1.8"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@deepseek-ai/dsh-api-session-controller": "
|
|
32
|
-
"@deepseek-ai/dsh-api-workspace-controller": "^0.1.5-
|
|
33
|
-
"@deepseek-ai/dsh-attachment": "^0.1.5-
|
|
34
|
-
"@deepseek-ai/dsh-client-connection": "^0.1.5-
|
|
35
|
-
"@deepseek-ai/dsh-client-store": "^0.1.5-
|
|
36
|
-
"@deepseek-ai/dsh-client-ui-chat": "^0.1.5-
|
|
37
|
-
"@deepseek-ai/dsh-client-ui-conversation": "
|
|
38
|
-
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-
|
|
39
|
-
"@deepseek-ai/dsh-client-ui-session": "^0.1.5-
|
|
40
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-
|
|
41
|
-
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-
|
|
42
|
-
"@deepseek-ai/dsh-session": "^0.1.5-
|
|
43
|
-
"@deepseek-ai/dsh-subagent": "^0.1.5-
|
|
44
|
-
"@deepseek-ai/dsh-typert-protocol": "^0.1.5-
|
|
31
|
+
"@deepseek-ai/dsh-api-session-controller": "0.1.5-rc.1.zw.2",
|
|
32
|
+
"@deepseek-ai/dsh-api-workspace-controller": "^0.1.5-rc.1",
|
|
33
|
+
"@deepseek-ai/dsh-attachment": "^0.1.5-rc.1",
|
|
34
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.5-rc.1",
|
|
35
|
+
"@deepseek-ai/dsh-client-store": "^0.1.5-rc.1",
|
|
36
|
+
"@deepseek-ai/dsh-client-ui-chat": "^0.1.5-rc.1",
|
|
37
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.5-rc.1.zw.2",
|
|
38
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.1",
|
|
39
|
+
"@deepseek-ai/dsh-client-ui-session": "^0.1.5-rc.1",
|
|
40
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.1",
|
|
41
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.1",
|
|
42
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.1",
|
|
43
|
+
"@deepseek-ai/dsh-subagent": "^0.1.5-rc.1",
|
|
44
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.5-rc.1",
|
|
45
45
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
46
46
|
"react": "^18.2.0",
|
|
47
47
|
"react-dom": "^18.2.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@deepseek-ai/dsh-api-session-controller": "npm:@crazx/dsh-api-session-controller@0.1.5-
|
|
51
|
-
"@deepseek-ai/dsh-api-workspace-controller": "^0.1.5-
|
|
52
|
-
"@deepseek-ai/dsh-attachment": "^0.1.5-
|
|
53
|
-
"@deepseek-ai/dsh-client-connection": "^0.1.5-
|
|
54
|
-
"@deepseek-ai/dsh-client-store": "^0.1.5-
|
|
55
|
-
"@deepseek-ai/dsh-client-ui-chat": "^0.1.5-
|
|
56
|
-
"@deepseek-ai/dsh-client-ui-conversation": "npm:@crazx/dsh-client-ui-conversation@0.1.5-
|
|
57
|
-
"@deepseek-ai/dsh-client-ui-
|
|
58
|
-
"@deepseek-ai/dsh-client-ui-
|
|
59
|
-
"@deepseek-ai/dsh-client-ui-
|
|
60
|
-
"@deepseek-ai/dsh-client-ui-
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"@deepseek-ai/dsh-
|
|
63
|
-
"@deepseek-ai/dsh-
|
|
50
|
+
"@deepseek-ai/dsh-api-session-controller": "npm:@crazx/dsh-api-session-controller@0.1.5-rc.1.zw.2",
|
|
51
|
+
"@deepseek-ai/dsh-api-workspace-controller": "^0.1.5-rc.1",
|
|
52
|
+
"@deepseek-ai/dsh-attachment": "^0.1.5-rc.1",
|
|
53
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.5-rc.1",
|
|
54
|
+
"@deepseek-ai/dsh-client-store": "^0.1.5-rc.1",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-chat": "^0.1.5-rc.1",
|
|
56
|
+
"@deepseek-ai/dsh-client-ui-conversation": "npm:@crazx/dsh-client-ui-conversation@0.1.5-rc.1.zw.2",
|
|
57
|
+
"@deepseek-ai/dsh-client-ui-layout": "npm:@crazx/dsh-client-ui-layout@0.1.5-rc.1.zw.2",
|
|
58
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.1",
|
|
59
|
+
"@deepseek-ai/dsh-client-ui-session": "^0.1.5-rc.1",
|
|
60
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.1",
|
|
61
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.1",
|
|
62
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.1",
|
|
63
|
+
"@deepseek-ai/dsh-subagent": "^0.1.5-rc.1",
|
|
64
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.5-rc.1",
|
|
64
65
|
"@types/react": "~18.3.1",
|
|
65
66
|
"@types/react-dom": "~18.3.0",
|
|
66
67
|
"@deepseek-ai/cordis": "^4.0.2",
|