@deepseek-ai/dsh-client-test-runtime 0.0.1-rc.2 → 0.1.0-rc.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/LICENSE +17 -24
- package/README.i18n.yaml +3 -3
- package/README.md +2 -2
- package/README.zh.md +2 -2
- package/lib/index.js +30 -21
- package/lib/invariant.js +1 -1
- package/lib/types/fixtures.d.ts +1 -1
- package/lib/types/index.d.ts +16 -15
- package/lib/types/sessions.d.ts +4 -4
- package/lib/types/translate.d.ts +1 -1
- package/lib/types/workspaces.d.ts +6 -0
- package/package.json +16 -16
package/LICENSE
CHANGED
|
@@ -1,28 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2026
|
|
3
|
+
Copyright (c) 2026 DeepSeek
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.i18n.yaml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
|
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
|
-
# pnpm run verify-translation-pairing --write packages/
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
4
|
+
# pnpm run verify-translation-pairing --write packages/test-support/client-runtime/README.md
|
|
5
|
+
README.md: 15646d05daae0a39a36639f335a71d6d208da13b
|
|
6
|
+
README.zh.md: 9624bc8ffc997ba786f3cb1bba670344d44ac60d
|
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
English | [中文](README.zh.md)
|
|
4
4
|
|
|
5
|
-
jsdom slot test runtime for client feature specs: a real Cordis `Context`, the production `
|
|
5
|
+
jsdom slot test runtime for client feature specs: a real Cordis `Context`, the production `SlotRegistry` and web-react renderer, assembled around typed session/workspace doubles. Feature suites exercise declaration, registration, scope, store, inject, rendering, updates, and disposal without hand-building the machinery per suite — and without a second implementation of any production logic.
|
|
6
6
|
|
|
7
|
-
The doubles implement the same outward faces features receive through ctx (`TestSessions implements ISessions`, `TestWorkspaces implements IWorkspaces`; each fixture session is a `FixtureSession implements SessionFace`; `stubSettingsScope` is a `SettingsScope` with test-driven publications and a write spy), so a production face change breaks the bench at compile time instead of silently drifting. Provide-bundle materialization runs the production `SessionProvideChannel` — the one implementation shared with `
|
|
7
|
+
The doubles implement the same outward faces features receive through ctx (`TestSessions implements ISessions`, `TestWorkspaces implements IWorkspaces`; each fixture session is a `FixtureSession implements SessionFace`; `stubSettingsScope` is a `SettingsScope` with test-driven publications and a write spy), so a production face change breaks the bench at compile time instead of silently drifting. Provide-bundle materialization runs the production `SessionProvideChannel` — the one implementation shared with `SessionRuntime`. Fixtures feed plain data: list rows, conversation snapshots (immer-patched via `updateSnapshot`), projection values, and `ISession`-typed behavior stubs that fail loud when a spec calls an unstubbed verb. The typed `provide()` constrains fakes for declared service names to `Partial` of that service's outward face.
|
|
8
8
|
|
|
9
9
|
Local DOM snapshots: `declare(children)` registers an auto frame whose per-key `<div data-slot>` wrappers are snapshot roots; `renderSlot(key, owner)` returns the slot-local view (container, scoped Testing Library queries, in-place `update(owner)`); a registered snapshot serializer folds CSS-module class hashes (`_frame_a1b2c3` → `frame`) to keep `.snap` files structural and collapses `<svg>` internals to a `data-content` fingerprint. Suites needing a custom page frame use `root.declare(children, Frame)` instead; `mount(plugin)` runs a real fiber with fail-loud service prechecks, and `dispose()` tears down views, feature fibers, minted scopes, and persisted store state on one axis.
|
|
10
10
|
|
package/README.zh.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) | 中文
|
|
4
4
|
|
|
5
|
-
面向客户端功能测试的 jsdom slot 测试运行时:真实 Cordis `Context`、生产 `
|
|
5
|
+
面向客户端功能测试的 jsdom slot 测试运行时:真实 Cordis `Context`、生产 `SlotRegistry` 与 web-react 渲染器,围绕带类型的 session/workspace 测试替身组装。功能套件无需逐套件手搭机器即可测遍声明、注册、scope、store、inject、渲染、更新与销毁——且不存在任何生产逻辑的第二份实现。
|
|
6
6
|
|
|
7
|
-
替身实现的正是功能通过 ctx 获得的对外接口(`TestSessions implements ISessions`、`TestWorkspaces implements IWorkspaces`;每个 fixture session 是 `FixtureSession implements SessionFace`;`stubSettingsScope` 是发布由测试驱动、带写入 spy 的 `SettingsScope`),生产面一旦改形,测试台在编译期即断,而非静默漂移。provide bundle 材料化直接运行生产 `SessionProvideChannel`——与 `
|
|
7
|
+
替身实现的正是功能通过 ctx 获得的对外接口(`TestSessions implements ISessions`、`TestWorkspaces implements IWorkspaces`;每个 fixture session 是 `FixtureSession implements SessionFace`;`stubSettingsScope` 是发布由测试驱动、带写入 spy 的 `SettingsScope`),生产面一旦改形,测试台在编译期即断,而非静默漂移。provide bundle 材料化直接运行生产 `SessionProvideChannel`——与 `SessionRuntime` 共用同一份实现。fixture 灌入的是普通数据:列表行、会话快照(经 `updateSnapshot` 以 immer 补丁改写)、projection 值,以及按 `ISession` 取型的行为桩——spec 调用未打桩的动词时报错自明。带类型的 `provide()` 将已声明服务名的 fake 约束为该服务对外面的 `Partial` 子集。
|
|
8
8
|
|
|
9
9
|
局部 DOM 快照:`declare(children)` 注册自动 frame,逐 key 的 `<div data-slot>` 包裹层即快照根;`renderSlot(key, owner)` 返回该 slot 的局部视图(container、限定范围的 Testing Library 查询、原位 `update(owner)`);注册的快照序列化器把 CSS-module 哈希类名折回语义名(`_frame_a1b2c3` → `frame`)保持 `.snap` 只含结构,并把 `<svg>` 内部折叠为 `data-content` 指纹。需要自定义页面 frame 的套件改用 `root.declare(children, Frame)`;`mount(plugin)` 在真实 fiber 上运行并对缺失服务先行报错;`dispose()` 沿单一轴拆除视图、feature fiber、已铸 scope 与持久化 store 状态。
|
|
10
10
|
|
package/lib/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Context, Inject } from "@deepseek-ai/cordis";
|
|
2
2
|
import { Fragment, createElement, useSyncExternalStore } from "react";
|
|
3
3
|
import { act, render, within } from "@testing-library/react";
|
|
4
|
-
import { ConversationEventRegistry, ConversationViewRegistry, EMPTY_CHAT_SNAPSHOT, EMPTY_CONVERSATION_VIEWS, SessionProvideChannel,
|
|
4
|
+
import { ConversationEventRegistry, ConversationViewRegistry, EMPTY_CHAT_SNAPSHOT, EMPTY_CONVERSATION_VIEWS, SessionProvideChannel, SlotRegistry, createScope, createSnapshotStore, scopeOf } from "@deepseek-ai/dsh-client-runtime/client";
|
|
5
5
|
import { createSlotRenderer } from "@deepseek-ai/dsh-client-web-react";
|
|
6
6
|
import { afterEach, beforeEach, expect, vi } from "vitest";
|
|
7
7
|
import { SESSION_SEARCH_RESULT_LIMIT } from "@deepseek-ai/dsh-host-apiproxy/api";
|
|
@@ -113,7 +113,7 @@ function conversationSnapshot(sessionId) {
|
|
|
113
113
|
};
|
|
114
114
|
}
|
|
115
115
|
/**
|
|
116
|
-
* A ready workspace list with no workspaces (the shape
|
|
116
|
+
* A ready workspace list with no workspaces (the shape WorkspaceRuntime
|
|
117
117
|
* projects after both baselines land).
|
|
118
118
|
* @returns the initial state of the test workspaces store.
|
|
119
119
|
*/
|
|
@@ -262,9 +262,9 @@ var TestSessions = class {
|
|
|
262
262
|
/** The useSessions standard feed (list rows + current selection). */
|
|
263
263
|
list;
|
|
264
264
|
/**
|
|
265
|
-
* Atomic current-session provide projection (production
|
|
265
|
+
* Atomic current-session provide projection (production SessionRuntime
|
|
266
266
|
* mirror): selection changes and provider-roster changes publish through
|
|
267
|
-
* this one source — the member the
|
|
267
|
+
* this one source — the member the SlotRegistry host face hands the
|
|
268
268
|
* renderer's SessionProvider.
|
|
269
269
|
*/
|
|
270
270
|
currentProvideInfo;
|
|
@@ -290,7 +290,7 @@ var TestSessions = class {
|
|
|
290
290
|
current: void 0,
|
|
291
291
|
phase: "ready",
|
|
292
292
|
subagentsByParent: {},
|
|
293
|
-
|
|
293
|
+
jobsBySession: {},
|
|
294
294
|
currentAddress: void 0
|
|
295
295
|
});
|
|
296
296
|
this.channel = new SessionProvideChannel({
|
|
@@ -387,7 +387,7 @@ var TestSessions = class {
|
|
|
387
387
|
/**
|
|
388
388
|
* Remove a session: list row, scope fiber, and per-session store instances
|
|
389
389
|
* (with persisted state) die together — the same single lifecycle axis the
|
|
390
|
-
* production
|
|
390
|
+
* production SessionRuntime drives on session death, minus staging.
|
|
391
391
|
* @param id - session id.
|
|
392
392
|
*/
|
|
393
393
|
async remove(id) {
|
|
@@ -822,6 +822,18 @@ var TestWorkspaces = class {
|
|
|
822
822
|
await this.stubs.get("delete")?.(workspaceId);
|
|
823
823
|
}
|
|
824
824
|
/**
|
|
825
|
+
* Move a Workspace in display order (recorded; default no-op).
|
|
826
|
+
* @param workspaceId - Workspace to move.
|
|
827
|
+
* @param beforeWorkspaceId - Anchor; omitted appends.
|
|
828
|
+
*/
|
|
829
|
+
async insertBefore(workspaceId, beforeWorkspaceId) {
|
|
830
|
+
this.calls.push({
|
|
831
|
+
method: "insertBefore",
|
|
832
|
+
args: [workspaceId, beforeWorkspaceId]
|
|
833
|
+
});
|
|
834
|
+
await this.stubs.get("insertBefore")?.(workspaceId, beforeWorkspaceId);
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
825
837
|
* Move an accounted session (recorded). The default echoes a minimal view.
|
|
826
838
|
* @param workspaceId - target workspace.
|
|
827
839
|
* @param sessionId - session to move.
|
|
@@ -978,7 +990,7 @@ var TestRemote = class {
|
|
|
978
990
|
//#region lib/types/translate.js
|
|
979
991
|
/**
|
|
980
992
|
* Test double of the locale lookup chain: a translate stub over plain
|
|
981
|
-
* dictionaries, mirroring
|
|
993
|
+
* dictionaries, mirroring LocaleRuntime's resolution order (first dictionary
|
|
982
994
|
* that owns the key wins, then the key itself stays visible) and its
|
|
983
995
|
* `{name}` template interpolation. Specs stub the framework-injected `t`
|
|
984
996
|
* seat with `makeTranslate(zh, commonZh)` instead of re-implementing the
|
|
@@ -1008,7 +1020,7 @@ function makeTranslate(...dicts) {
|
|
|
1008
1020
|
//#region lib/types/locale-env.js
|
|
1009
1021
|
/**
|
|
1010
1022
|
* Browser-language pin for specs that assert localized copy. A fresh
|
|
1011
|
-
*
|
|
1023
|
+
* LocaleRuntime with no stored preference opens in the language `navigator`
|
|
1012
1024
|
* asks for, and jsdom reports the runner's own (`en-US`) — so a spec asserting
|
|
1013
1025
|
* the product's Chinese copy states the browser it assumes instead of
|
|
1014
1026
|
* inheriting the machine's.
|
|
@@ -1041,7 +1053,7 @@ function usePinnedBrowserLanguages(primary, ...rest) {
|
|
|
1041
1053
|
//#region lib/types/index.js
|
|
1042
1054
|
/**
|
|
1043
1055
|
* jsdom slot test runtime: a real small runtime — Cordis `Context`, the
|
|
1044
|
-
* runtime `
|
|
1056
|
+
* runtime `SlotRegistry`, and the web-react renderer — assembled around
|
|
1045
1057
|
* test-owned session/workspace doubles, so feature specs exercise
|
|
1046
1058
|
* declaration, registration, scope, store, inject, rendering, updates, and
|
|
1047
1059
|
* disposal without hand-building the machinery per suite.
|
|
@@ -1099,7 +1111,7 @@ var TestRoot = class {
|
|
|
1099
1111
|
stabilize;
|
|
1100
1112
|
disposeEntry;
|
|
1101
1113
|
/**
|
|
1102
|
-
* @param slots - the runtime
|
|
1114
|
+
* @param slots - the runtime SlotRegistry.
|
|
1103
1115
|
* @param stabilize - the owning runtime's act wrapper.
|
|
1104
1116
|
*/
|
|
1105
1117
|
constructor(slots, stabilize) {
|
|
@@ -1137,7 +1149,7 @@ var TestRoot = class {
|
|
|
1137
1149
|
var SlotTestRuntime = class SlotTestRuntime {
|
|
1138
1150
|
/** The runtime's Cordis root (escape hatch: extra services via `ctx.provide`, raw `ctx.plugin` mounts). */
|
|
1139
1151
|
ctx;
|
|
1140
|
-
/** The production
|
|
1152
|
+
/** The production SlotRegistry mounted on {@link SlotTestRuntime.ctx}. */
|
|
1141
1153
|
slots;
|
|
1142
1154
|
/** The test-owned 'root' occupant. */
|
|
1143
1155
|
root;
|
|
@@ -1173,14 +1185,14 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1173
1185
|
} });
|
|
1174
1186
|
}
|
|
1175
1187
|
/**
|
|
1176
|
-
* Assemble a runtime: real Context, mounted
|
|
1188
|
+
* Assemble a runtime: real Context, mounted SlotRegistry, installed
|
|
1177
1189
|
* renderer, and the session/workspace doubles provided as services.
|
|
1178
1190
|
* @returns the ready runtime.
|
|
1179
1191
|
*/
|
|
1180
1192
|
static async create() {
|
|
1181
1193
|
registerDomSnapshotSerializer();
|
|
1182
1194
|
const ctx = new Context();
|
|
1183
|
-
await ctx.plugin(
|
|
1195
|
+
await ctx.plugin(SlotRegistry).await();
|
|
1184
1196
|
await ctx.plugin(ConversationEventRegistry).await();
|
|
1185
1197
|
await ctx.plugin(ConversationViewRegistry).await();
|
|
1186
1198
|
return new SlotTestRuntime(ctx, ctx.get("slots"));
|
|
@@ -1237,10 +1249,10 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1237
1249
|
/**
|
|
1238
1250
|
* Declare child slots under an auto-generated root frame — the single-slot
|
|
1239
1251
|
* mounting path for local DOM snapshots. Each key later supplied through
|
|
1240
|
-
* {@link SlotTestRuntime.renderSlot} renders inside
|
|
1241
|
-
* `<div data-slot="<key>">`
|
|
1242
|
-
*
|
|
1243
|
-
* runtime.
|
|
1252
|
+
* {@link SlotTestRuntime.renderSlot} renders inside the renderer's own
|
|
1253
|
+
* `<div data-slot="<key>">` outlet anchor (the snapshot root — the frame
|
|
1254
|
+
* adds no wrapper of its own). Mutually exclusive with
|
|
1255
|
+
* {@link TestRoot.declare} ('root' is a single slot); one call per runtime.
|
|
1244
1256
|
* @param children - child-slot declaration table (same contract as TestRoot.declare).
|
|
1245
1257
|
* @returns completion of the act-wrapped registration.
|
|
1246
1258
|
*/
|
|
@@ -1249,10 +1261,7 @@ var SlotTestRuntime = class SlotTestRuntime {
|
|
|
1249
1261
|
const cell = this.ownerCell;
|
|
1250
1262
|
const AutoFrame = (props) => {
|
|
1251
1263
|
useSyncExternalStore(cell.subscribe, cell.getVersion);
|
|
1252
|
-
return createElement(Fragment, null, cell.entries().map(([key, owner]) => createElement(
|
|
1253
|
-
"data-slot": key,
|
|
1254
|
-
key
|
|
1255
|
-
}, props.renderSlot(key, owner))));
|
|
1264
|
+
return createElement(Fragment, null, cell.entries().map(([key, owner]) => createElement(Fragment, { key }, props.renderSlot(key, owner))));
|
|
1256
1265
|
};
|
|
1257
1266
|
await this.root.declare(children, AutoFrame);
|
|
1258
1267
|
}
|
package/lib/invariant.js
CHANGED
|
@@ -10,7 +10,7 @@ const name = "client-test-runtime-invariant";
|
|
|
10
10
|
const inject = ["invariants"];
|
|
11
11
|
/**
|
|
12
12
|
* No runtime invariant: this test-support package owns no production event
|
|
13
|
-
* stream or mutable data — it assembles the runtime
|
|
13
|
+
* stream or mutable data — it assembles the runtime SlotRegistry and renderer
|
|
14
14
|
* (whose packages own their invariants) around test doubles; its own behavior
|
|
15
15
|
* is exercised by its package tests.
|
|
16
16
|
*/
|
package/lib/types/fixtures.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export interface SessionFixture {
|
|
|
38
38
|
*/
|
|
39
39
|
export declare function conversationSnapshot(sessionId: SessionId): ConversationSnapshot;
|
|
40
40
|
/**
|
|
41
|
-
* A ready workspace list with no workspaces (the shape
|
|
41
|
+
* A ready workspace list with no workspaces (the shape WorkspaceRuntime
|
|
42
42
|
* projects after both baselines land).
|
|
43
43
|
* @returns the initial state of the test workspaces store.
|
|
44
44
|
*/
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* jsdom slot test runtime: a real small runtime — Cordis `Context`, the
|
|
3
|
-
* runtime `
|
|
3
|
+
* runtime `SlotRegistry`, and the web-react renderer — assembled around
|
|
4
4
|
* test-owned session/workspace doubles, so feature specs exercise
|
|
5
5
|
* declaration, registration, scope, store, inject, rendering, updates, and
|
|
6
6
|
* disposal without hand-building the machinery per suite.
|
|
@@ -15,7 +15,7 @@ import type { Fiber, Plugin } from '@deepseek-ai/cordis';
|
|
|
15
15
|
import type { RenderResult } from '@testing-library/react';
|
|
16
16
|
import type { queries } from '@testing-library/dom';
|
|
17
17
|
import type { BoundFunctions } from '@testing-library/dom';
|
|
18
|
-
import {
|
|
18
|
+
import { SlotRegistry } from '@deepseek-ai/dsh-client-runtime/client';
|
|
19
19
|
import type { ChildrenDecl, ComposedProps, OwnerOf, SlotComponent, SlotMap, StoreInstanceLike } from '@deepseek-ai/dsh-client-ui-slots';
|
|
20
20
|
import { TestSessions } from './sessions.ts';
|
|
21
21
|
import { TestWorkspaces } from './workspaces.ts';
|
|
@@ -32,12 +32,13 @@ export { makeTranslate } from './translate.ts';
|
|
|
32
32
|
export { usePinnedBrowserLanguages } from './locale-env.ts';
|
|
33
33
|
/**
|
|
34
34
|
* One rendered slot's local view, from {@link SlotTestRuntime.renderSlot}:
|
|
35
|
-
* the `data-slot`
|
|
36
|
-
* .toMatchSnapshot()` captures exactly this slot's
|
|
37
|
-
* queries are bound inside it, and `update`
|
|
35
|
+
* the renderer's own `[data-slot]` outlet anchor is the snapshot root
|
|
36
|
+
* (`expect(view.container).toMatchSnapshot()` captures exactly this slot's
|
|
37
|
+
* output), Testing Library queries are bound inside it, and `update`
|
|
38
|
+
* re-renders with new owner props.
|
|
38
39
|
*/
|
|
39
40
|
export interface SlotView<K extends keyof SlotMap & string> {
|
|
40
|
-
/** The `<div data-slot="<key>">`
|
|
41
|
+
/** The renderer's `<div data-slot="<key>">` anchor around the slot's rendered output. */
|
|
41
42
|
readonly container: HTMLElement;
|
|
42
43
|
/** Testing Library queries scoped to {@link SlotView.container}. */
|
|
43
44
|
readonly view: BoundFunctions<typeof queries>;
|
|
@@ -72,10 +73,10 @@ export declare class TestRoot {
|
|
|
72
73
|
private readonly stabilize;
|
|
73
74
|
private disposeEntry;
|
|
74
75
|
/**
|
|
75
|
-
* @param slots - the runtime
|
|
76
|
+
* @param slots - the runtime SlotRegistry.
|
|
76
77
|
* @param stabilize - the owning runtime's act wrapper.
|
|
77
78
|
*/
|
|
78
|
-
constructor(slots:
|
|
79
|
+
constructor(slots: SlotRegistry, stabilize: Stabilizer);
|
|
79
80
|
/**
|
|
80
81
|
* Register the root frame, declaring (and thereby claiming) the child
|
|
81
82
|
* slots. One declaration per runtime — a second call fails loud in the
|
|
@@ -97,8 +98,8 @@ export declare class TestRoot {
|
|
|
97
98
|
export declare class SlotTestRuntime {
|
|
98
99
|
/** The runtime's Cordis root (escape hatch: extra services via `ctx.provide`, raw `ctx.plugin` mounts). */
|
|
99
100
|
readonly ctx: Context;
|
|
100
|
-
/** The production
|
|
101
|
-
readonly slots:
|
|
101
|
+
/** The production SlotRegistry mounted on {@link SlotTestRuntime.ctx}. */
|
|
102
|
+
readonly slots: SlotRegistry;
|
|
102
103
|
/** The test-owned 'root' occupant. */
|
|
103
104
|
readonly root: TestRoot;
|
|
104
105
|
/** Sessions double (list/current observable, cells, scopes, behavior faces). */
|
|
@@ -116,7 +117,7 @@ export declare class SlotTestRuntime {
|
|
|
116
117
|
private autoRootView;
|
|
117
118
|
private constructor();
|
|
118
119
|
/**
|
|
119
|
-
* Assemble a runtime: real Context, mounted
|
|
120
|
+
* Assemble a runtime: real Context, mounted SlotRegistry, installed
|
|
120
121
|
* renderer, and the session/workspace doubles provided as services.
|
|
121
122
|
* @returns the ready runtime.
|
|
122
123
|
*/
|
|
@@ -149,10 +150,10 @@ export declare class SlotTestRuntime {
|
|
|
149
150
|
/**
|
|
150
151
|
* Declare child slots under an auto-generated root frame — the single-slot
|
|
151
152
|
* mounting path for local DOM snapshots. Each key later supplied through
|
|
152
|
-
* {@link SlotTestRuntime.renderSlot} renders inside
|
|
153
|
-
* `<div data-slot="<key>">`
|
|
154
|
-
*
|
|
155
|
-
* runtime.
|
|
153
|
+
* {@link SlotTestRuntime.renderSlot} renders inside the renderer's own
|
|
154
|
+
* `<div data-slot="<key>">` outlet anchor (the snapshot root — the frame
|
|
155
|
+
* adds no wrapper of its own). Mutually exclusive with
|
|
156
|
+
* {@link TestRoot.declare} ('root' is a single slot); one call per runtime.
|
|
156
157
|
* @param children - child-slot declaration table (same contract as TestRoot.declare).
|
|
157
158
|
* @returns completion of the act-wrapped registration.
|
|
158
159
|
*/
|
package/lib/types/sessions.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Test-owned sessions face: the
|
|
1
|
+
/** Test-owned sessions face: the SlotRegistry host contract over declarative fixtures. */
|
|
2
2
|
import type { Context } from '@deepseek-ai/cordis';
|
|
3
3
|
import type { AttachmentIdType } from '@deepseek-ai/dsh-attachment';
|
|
4
4
|
import type { AgentContext, ConversationSnapshot, ISessions, ProjectionsFace, SessionFace, SessionId, SessionListState, SessionProvideDescriptor, SessionSearchResultItem, SessionSummary, SnapshotStore, SubagentAddress } from '@deepseek-ai/dsh-client-runtime/client';
|
|
@@ -95,9 +95,9 @@ export declare class TestSessions implements ISessions {
|
|
|
95
95
|
/** The useSessions standard feed (list rows + current selection). */
|
|
96
96
|
readonly list: SnapshotStore<SessionListState>;
|
|
97
97
|
/**
|
|
98
|
-
* Atomic current-session provide projection (production
|
|
98
|
+
* Atomic current-session provide projection (production SessionRuntime
|
|
99
99
|
* mirror): selection changes and provider-roster changes publish through
|
|
100
|
-
* this one source — the member the
|
|
100
|
+
* this one source — the member the SlotRegistry host face hands the
|
|
101
101
|
* renderer's SessionProvider.
|
|
102
102
|
*/
|
|
103
103
|
readonly currentProvideInfo: HostObservable<SessionMaybeProvideInfo>;
|
|
@@ -149,7 +149,7 @@ export declare class TestSessions implements ISessions {
|
|
|
149
149
|
/**
|
|
150
150
|
* Remove a session: list row, scope fiber, and per-session store instances
|
|
151
151
|
* (with persisted state) die together — the same single lifecycle axis the
|
|
152
|
-
* production
|
|
152
|
+
* production SessionRuntime drives on session death, minus staging.
|
|
153
153
|
* @param id - session id.
|
|
154
154
|
*/
|
|
155
155
|
remove(id: string): Promise<void>;
|
package/lib/types/translate.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Test double of the locale lookup chain: a translate stub over plain
|
|
3
|
-
* dictionaries, mirroring
|
|
3
|
+
* dictionaries, mirroring LocaleRuntime's resolution order (first dictionary
|
|
4
4
|
* that owns the key wins, then the key itself stays visible) and its
|
|
5
5
|
* `{name}` template interpolation. Specs stub the framework-injected `t`
|
|
6
6
|
* seat with `makeTranslate(zh, commonZh)` instead of re-implementing the
|
|
@@ -91,6 +91,12 @@ export declare class TestWorkspaces implements IWorkspaces {
|
|
|
91
91
|
* @param workspaceId - target workspace.
|
|
92
92
|
*/
|
|
93
93
|
delete(workspaceId: WorkspaceId): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Move a Workspace in display order (recorded; default no-op).
|
|
96
|
+
* @param workspaceId - Workspace to move.
|
|
97
|
+
* @param beforeWorkspaceId - Anchor; omitted appends.
|
|
98
|
+
*/
|
|
99
|
+
insertBefore(workspaceId: WorkspaceId, beforeWorkspaceId?: WorkspaceId): Promise<void>;
|
|
94
100
|
/**
|
|
95
101
|
* Move an accounted session (recorded). The default echoes a minimal view.
|
|
96
102
|
* @param workspaceId - target workspace.
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-client-test-runtime",
|
|
3
|
-
"description": "jsdom slot test runtime: real Cordis Context +
|
|
4
|
-
"version": "0.0
|
|
3
|
+
"description": "jsdom slot test runtime: real Cordis Context + SlotRegistry + web-react renderer with test-owned session/workspace doubles for feature specs",
|
|
4
|
+
"version": "0.1.0-rc.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "restricted"
|
|
7
7
|
},
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
|
11
|
-
"directory": "packages/
|
|
11
|
+
"directory": "packages/test-support/client-runtime"
|
|
12
12
|
},
|
|
13
13
|
"type": "module",
|
|
14
14
|
"main": "lib/index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"./src/*": "./src/*",
|
|
26
26
|
"./package.json": "./package.json"
|
|
27
27
|
},
|
|
28
|
-
"license": "
|
|
28
|
+
"license": "MIT",
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@testing-library/dom": "^10.4.1",
|
|
31
31
|
"@testing-library/react": "^16.3.2",
|
|
@@ -34,24 +34,24 @@
|
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"react": "^18.2.0",
|
|
36
36
|
"react-dom": "^18.2.0",
|
|
37
|
-
"@deepseek-ai/dsh-client-
|
|
38
|
-
"@deepseek-ai/dsh-client-ui-slots": "^0.0
|
|
39
|
-
"@deepseek-ai/dsh-host-apiproxy": "^0.0
|
|
40
|
-
"@deepseek-ai/dsh-
|
|
41
|
-
"@deepseek-ai/
|
|
42
|
-
"@deepseek-ai/
|
|
37
|
+
"@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.2",
|
|
38
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.2",
|
|
39
|
+
"@deepseek-ai/dsh-host-apiproxy": "^0.1.0-rc.2",
|
|
40
|
+
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.2",
|
|
41
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
42
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.2"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/react": "~18.3.1",
|
|
46
46
|
"@types/react-dom": "~18.3.0",
|
|
47
47
|
"react": "^18.2.0",
|
|
48
48
|
"react-dom": "^18.2.0",
|
|
49
|
-
"@deepseek-ai/dsh-client-runtime": "^0.0
|
|
50
|
-
"@deepseek-ai/dsh-client-
|
|
51
|
-
"@deepseek-ai/dsh-
|
|
52
|
-
"@deepseek-ai/dsh-
|
|
53
|
-
"@deepseek-ai/
|
|
54
|
-
"@deepseek-ai/
|
|
49
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.2",
|
|
50
|
+
"@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.2",
|
|
51
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.2",
|
|
52
|
+
"@deepseek-ai/dsh-invariants": "^0.1.0-rc.2",
|
|
53
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
54
|
+
"@deepseek-ai/dsh-host-apiproxy": "^0.1.0-rc.2"
|
|
55
55
|
},
|
|
56
56
|
"files": [
|
|
57
57
|
"lib/index.js",
|