@deepseek-ai/dsh-client-test-runtime 0.1.1-rc.2 → 0.1.2-alpha.3
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 +132 -6
- package/README.zh.md +133 -7
- package/lib/index.js +246 -239
- package/lib/types/fixtures.d.ts +35 -10
- package/lib/types/index.d.ts +12 -18
- package/lib/types/remote.d.ts +22 -13
- package/lib/types/sessions.d.ts +70 -62
- package/lib/types/settings-remote.d.ts +83 -0
- package/lib/types/settings-scope.d.ts +3 -1
- package/lib/types/workspaces.d.ts +17 -43
- package/package.json +33 -13
package/lib/types/fixtures.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
import type {
|
|
1
|
+
/** Controller and UI-domain fixture shapes for the client test runtime. */
|
|
2
|
+
import type { ISession, SessionEventLikeEntry, SessionSnapshot, SessionSummary } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
3
|
+
import type { WorkspaceSnapshot } from '@deepseek-ai/dsh-api-workspace-controller/client';
|
|
4
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
5
|
+
import { type ConversationSnapshot } from '@deepseek-ai/dsh-client-ui-conversation/client';
|
|
6
|
+
import { type ChatSnapshot } from '@deepseek-ai/dsh-client-ui-chat/client';
|
|
3
7
|
/**
|
|
4
8
|
* Fixture overrides for the session behavior face: any subset of the
|
|
5
9
|
* production ISession verbs (typed against it, so a face change surfaces
|
|
@@ -16,6 +20,12 @@ export type SessionBehaviorOverrides = Partial<ISession> & Record<string, unknow
|
|
|
16
20
|
* React act themselves.
|
|
17
21
|
*/
|
|
18
22
|
export type Stabilizer = (fn: () => void | Promise<void>) => Promise<void>;
|
|
23
|
+
/** Mutable top-level snapshot fields accepted by fixture update callbacks. */
|
|
24
|
+
export type FixtureSnapshot<T> = {
|
|
25
|
+
-readonly [Key in keyof T]: T[Key];
|
|
26
|
+
};
|
|
27
|
+
/** Writable test representation of the immutable Session Controller snapshot. */
|
|
28
|
+
export type SessionFixtureSnapshot = FixtureSnapshot<SessionSnapshot>;
|
|
19
29
|
/**
|
|
20
30
|
* Session fixture accepted by {@link TestSessions.add}: identity plus optional
|
|
21
31
|
* snapshot/list-row overrides and the session behavior face the feature under
|
|
@@ -24,23 +34,38 @@ export type Stabilizer = (fn: () => void | Promise<void>) => Promise<void>;
|
|
|
24
34
|
*/
|
|
25
35
|
export interface SessionFixture {
|
|
26
36
|
id: string;
|
|
27
|
-
/** Overrides merged over {@link
|
|
28
|
-
snapshot?: Partial<Omit<
|
|
37
|
+
/** Overrides merged over {@link sessionSnapshot}; Conversation data arrives through the event feed. */
|
|
38
|
+
snapshot?: Partial<Omit<SessionSnapshot, 'sessionId'>>;
|
|
29
39
|
/** List-row overrides merged over the defaults derived from `id`. */
|
|
30
40
|
summary?: Partial<Omit<SessionSummary, 'id'>>;
|
|
31
41
|
/** Session behavior face: exactly the methods the feature under test calls (ISession subset + extras). */
|
|
32
42
|
session?: SessionBehaviorOverrides;
|
|
43
|
+
/** Initial contiguous event window consumed by Conversation assembly. */
|
|
44
|
+
events?: readonly SessionEventLikeEntry[];
|
|
45
|
+
/** Whether the initial event window has an older page. */
|
|
46
|
+
hasMore?: boolean;
|
|
33
47
|
}
|
|
34
48
|
/**
|
|
35
|
-
* A complete quiescent
|
|
49
|
+
* A complete quiescent Session Controller snapshot.
|
|
36
50
|
* @param sessionId - owning session id.
|
|
37
51
|
* @returns the snapshot; spread fixture overrides on top.
|
|
38
52
|
*/
|
|
39
|
-
export declare function
|
|
53
|
+
export declare function sessionSnapshot(sessionId: SessionId): SessionSnapshot;
|
|
40
54
|
/**
|
|
41
|
-
* A
|
|
42
|
-
*
|
|
43
|
-
* @returns
|
|
55
|
+
* A target-neutral Conversation snapshot.
|
|
56
|
+
* @param overrides - target roster or activity overrides.
|
|
57
|
+
* @returns an immutable fixture value.
|
|
44
58
|
*/
|
|
45
|
-
export declare function
|
|
59
|
+
export declare function conversationSnapshot(overrides?: Partial<ConversationSnapshot>): ConversationSnapshot;
|
|
60
|
+
/**
|
|
61
|
+
* A Chat target snapshot.
|
|
62
|
+
* @param overrides - Chat target overrides.
|
|
63
|
+
* @returns an immutable fixture value.
|
|
64
|
+
*/
|
|
65
|
+
export declare function chatSnapshot(overrides?: Partial<ChatSnapshot>): ChatSnapshot;
|
|
66
|
+
/**
|
|
67
|
+
* A ready Workspace Controller snapshot with no Workspace rows.
|
|
68
|
+
* @returns the initial state of the test Workspace source.
|
|
69
|
+
*/
|
|
70
|
+
export declare function workspaceSnapshot(): WorkspaceSnapshot;
|
|
46
71
|
//# sourceMappingURL=fixtures.d.ts.map
|
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
|
-
*
|
|
3
|
+
* renderer-owned `SlotRegistry`, the `ui-session` adapter, and the UI 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,20 +15,22 @@ 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 { SlotRegistry } from '@deepseek-ai/dsh-client-
|
|
18
|
+
import { SlotRegistry } from '@deepseek-ai/dsh-client-ui-renderer/client';
|
|
19
19
|
import type { ChildrenDecl, ComposedProps, HostObservable, OwnerOf, SlotComponent, SlotMap, SlotRenderer, SnapshotSelectorHook, StoreInstanceLike } from '@deepseek-ai/dsh-client-ui-slots';
|
|
20
20
|
import { TestSessions } from './sessions.ts';
|
|
21
21
|
import { TestWorkspaces } from './workspaces.ts';
|
|
22
22
|
import type { Stabilizer } from './fixtures.ts';
|
|
23
|
-
export type { UseSession } from '@deepseek-ai/dsh-client-ui-
|
|
23
|
+
export type { UseSession } from '@deepseek-ai/dsh-client-ui-session/client';
|
|
24
24
|
export { domSnapshotSerializer, registerDomSnapshotSerializer } from './snapshot.ts';
|
|
25
25
|
export { FixtureSession, TestSessions } from './sessions.ts';
|
|
26
26
|
export { stubSettingsScope } from './settings-scope.ts';
|
|
27
27
|
export type { StubSettingsScope } from './settings-scope.ts';
|
|
28
|
+
export { scriptedSettingsRemote } from './settings-remote.ts';
|
|
29
|
+
export type { ScriptedNamespace, ScriptedSettingsRemote } from './settings-remote.ts';
|
|
28
30
|
export { TestWorkspaces } from './workspaces.ts';
|
|
29
|
-
export { TestRemote } from './remote.ts';
|
|
30
|
-
export { conversationSnapshot,
|
|
31
|
-
export type { SessionBehaviorOverrides, SessionFixture, Stabilizer } from './fixtures.ts';
|
|
31
|
+
export { RemoteError, TestRemote } from './remote.ts';
|
|
32
|
+
export { chatSnapshot, conversationSnapshot, sessionSnapshot, workspaceSnapshot, } from './fixtures.ts';
|
|
33
|
+
export type { FixtureSnapshot, SessionBehaviorOverrides, SessionFixture, SessionFixtureSnapshot, Stabilizer, } from './fixtures.ts';
|
|
32
34
|
export { makeTranslate } from './translate.ts';
|
|
33
35
|
export { usePinnedBrowserLanguages } from './locale-env.ts';
|
|
34
36
|
/**
|
|
@@ -108,7 +110,7 @@ export declare class TestRoot {
|
|
|
108
110
|
* batching or React act themselves.
|
|
109
111
|
*/
|
|
110
112
|
export declare class SlotTestRuntime {
|
|
111
|
-
/** The runtime's Cordis root
|
|
113
|
+
/** The runtime's Cordis root for owner APIs and explicit test-only services. */
|
|
112
114
|
readonly ctx: Context;
|
|
113
115
|
/** The production SlotRegistry mounted on {@link SlotTestRuntime.ctx}. */
|
|
114
116
|
readonly slots: SlotRegistry;
|
|
@@ -127,6 +129,7 @@ export declare class SlotTestRuntime {
|
|
|
127
129
|
private readonly ownerCell;
|
|
128
130
|
private readonly autoDeclared;
|
|
129
131
|
private autoRootView;
|
|
132
|
+
private readonly disposeWorkspaceSource;
|
|
130
133
|
private constructor();
|
|
131
134
|
/**
|
|
132
135
|
* Assemble a runtime: real Context, mounted SlotRegistry, installed
|
|
@@ -134,17 +137,6 @@ export declare class SlotTestRuntime {
|
|
|
134
137
|
* @returns the ready runtime.
|
|
135
138
|
*/
|
|
136
139
|
static create(): Promise<SlotTestRuntime>;
|
|
137
|
-
/**
|
|
138
|
-
* Provide an extra service the feature under test injects (e.g. a layout
|
|
139
|
-
* fake). Sugar over `ctx.provide`, typed against the Context declaration
|
|
140
|
-
* merge: for a declared service name the fake must be a subset of that
|
|
141
|
-
* service's outward face (Partial — supply only what the feature calls),
|
|
142
|
-
* so a production face change breaks the fake at compile time. Undeclared
|
|
143
|
-
* names stay unchecked (ad-hoc test services).
|
|
144
|
-
* @param name - service name.
|
|
145
|
-
* @param value - service implementation (test double).
|
|
146
|
-
*/
|
|
147
|
-
provide<K extends string>(name: K, value: K extends keyof Context ? Partial<Context[K]> : unknown): void;
|
|
148
140
|
/**
|
|
149
141
|
* Mount a feature plugin on a real fiber. Required services are prechecked
|
|
150
142
|
* so a missing provider fails loud instead of suspending the fiber forever
|
|
@@ -153,6 +145,8 @@ export declare class SlotTestRuntime {
|
|
|
153
145
|
* @returns handle owning the fiber's explicit disposal.
|
|
154
146
|
*/
|
|
155
147
|
mount(plugin: Plugin): Promise<FeatureHandle>;
|
|
148
|
+
/** Release the default Workspace hook before mounting its production owner. */
|
|
149
|
+
releaseWorkspaceSource(): void;
|
|
156
150
|
/**
|
|
157
151
|
* Render the root slot tree through the ctx-level entry (the shell's own
|
|
158
152
|
* entry point): `ctx.slots.renderSlot('root', {})` under Testing Library.
|
package/lib/types/remote.d.ts
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
/** Test-owned Remote face: `$on` subscriptions
|
|
1
|
+
/** Test-owned Remote face: `$on` subscriptions with an explicit test event driver. */
|
|
2
2
|
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
export { RemoteError } from '@deepseek-ai/dsh-typert-protocol';
|
|
3
4
|
/**
|
|
4
5
|
* Remote service test double for the forwarded-event path. Feature specs need
|
|
5
6
|
* `ctx.remote.$on` to exist (their plugins inject `remote`) and need forwarded
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* Host events to reach those subscribers, but not the wire — so this double
|
|
8
|
+
* implements subscription plus an explicit `emit` driver available only on the
|
|
9
|
+
* concrete test object. A spec that also calls one namespace scripts it through
|
|
10
|
+
* the constructor rather than reaching the real Client Remote service.
|
|
8
11
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* `$dispatch(name, args)` on this double.
|
|
13
|
-
*
|
|
14
|
-
* `$mount` rejects: a spec that reaches a generated namespace through this
|
|
15
|
-
* double has outgrown it and needs the real Client Remote service.
|
|
12
|
+
* `$mount` rejects: a spec that needs a real generated contribution installed —
|
|
13
|
+
* codecs, descriptors, and the wire — has outgrown this double and needs the
|
|
14
|
+
* real Client Remote service.
|
|
16
15
|
*
|
|
17
16
|
* One deliberate asymmetry with production: a throwing listener propagates out
|
|
18
17
|
* of the emit instead of being contained and logged, so a spec cannot lean on
|
|
@@ -22,17 +21,27 @@ import type { Context } from '@deepseek-ai/cordis';
|
|
|
22
21
|
export declare class TestRemote {
|
|
23
22
|
private readonly subscriptions;
|
|
24
23
|
/**
|
|
25
|
-
*
|
|
24
|
+
* Fixed Host facts mirrored from the production `ctx.remote.$host`. Plain
|
|
25
|
+
* mutable field: a spec assigns it to script a non-loopback or homed Host.
|
|
26
|
+
*/
|
|
27
|
+
$host: {
|
|
28
|
+
home: string | undefined;
|
|
29
|
+
isLoopback: boolean;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Register the double as `ctx.remote`, plus one service per scripted
|
|
33
|
+
* namespace so a plugin injecting `remote.<name>` also unparks.
|
|
26
34
|
* @param ctx - the spec's root Context.
|
|
35
|
+
* @param namespaces - scripted namespace faces reached as `ctx.remote.<name>`.
|
|
27
36
|
*/
|
|
28
|
-
constructor(ctx: Context);
|
|
37
|
+
constructor(ctx: Context, namespaces?: Readonly<Record<string, object>>);
|
|
29
38
|
/**
|
|
30
39
|
* Deliver one forwarded host event to its subscribers, standing in for the
|
|
31
40
|
* carrier that owns the frame sink.
|
|
32
41
|
* @param event - forwarded host event name.
|
|
33
42
|
* @param args - the Host argument list, verbatim.
|
|
34
43
|
*/
|
|
35
|
-
|
|
44
|
+
emit(event: string, args: readonly unknown[]): void;
|
|
36
45
|
/**
|
|
37
46
|
* Subscribe to one forwarded host event.
|
|
38
47
|
* @param event - forwarded host event name.
|
package/lib/types/sessions.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
/** Test-owned
|
|
1
|
+
/** Test-owned Session Controller faces over declarative fixtures. */
|
|
2
2
|
import type { Context } from '@deepseek-ai/cordis';
|
|
3
3
|
import type { AttachmentIdType } from '@deepseek-ai/dsh-attachment';
|
|
4
|
-
import
|
|
5
|
-
import type {
|
|
6
|
-
import type {
|
|
4
|
+
import { MutableSessionEventSource } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
5
|
+
import type { AgentContext, ISessions, ProjectionsFace, SessionBinding, SessionFace, SessionListState, SessionEventLikeEntry, SessionLiveEventEntry, SessionSearchResultItem, SessionSnapshot, SessionSummary, SubmissionHandle } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
6
|
+
import type { SubagentAddress } from '@deepseek-ai/dsh-subagent/client';
|
|
7
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
8
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
9
|
+
import type { SessionFixture, SessionFixtureSnapshot, Stabilizer } from './fixtures.ts';
|
|
7
10
|
/**
|
|
8
|
-
* The fixture-backed session face:
|
|
9
|
-
*
|
|
11
|
+
* The fixture-backed session face: lifecycle reads delegate to the fixture's
|
|
12
|
+
* snapshot store; Session verbs are fail-loud stubs unless the
|
|
10
13
|
* fixture supplies them (the runtime never fakes behavior a test did not
|
|
11
14
|
* declare — an unstubbed call names itself instead of half-working). Extra
|
|
12
15
|
* fixture methods are grafted verbatim for feature-side casts.
|
|
@@ -14,21 +17,22 @@ import type { SessionFixture, Stabilizer } from './fixtures.ts';
|
|
|
14
17
|
export declare class FixtureSession implements SessionFace {
|
|
15
18
|
readonly sessionId: SessionId;
|
|
16
19
|
private readonly store;
|
|
20
|
+
/** Mutable event source consumed only by Conversation assembly. */
|
|
21
|
+
readonly eventSource: MutableSessionEventSource;
|
|
17
22
|
/**
|
|
18
|
-
*
|
|
19
|
-
* projection values (set via {@link TestSessions.setProjection}).
|
|
23
|
+
* Identity-stable per-key faces over fixture-controlled projection values.
|
|
20
24
|
*/
|
|
21
25
|
readonly projections: ProjectionsFace & {
|
|
22
26
|
set(key: string, value: unknown): void;
|
|
23
27
|
};
|
|
24
28
|
/**
|
|
25
29
|
* @param sessionId - host identity (branded view of the fixture id).
|
|
26
|
-
* @param store -
|
|
30
|
+
* @param store - Session Controller snapshot store.
|
|
27
31
|
* @param overrides - fixture-declared behavior face, grafted over the stubs.
|
|
28
32
|
*/
|
|
29
|
-
constructor(sessionId: SessionId, store: SnapshotStore<
|
|
30
|
-
/** @returns the fixture
|
|
31
|
-
getSnapshot():
|
|
33
|
+
constructor(sessionId: SessionId, store: SnapshotStore<SessionFixtureSnapshot>, overrides: Record<string, unknown>);
|
|
34
|
+
/** @returns the fixture Session Controller snapshot (useSession read side). */
|
|
35
|
+
getSnapshot(): SessionSnapshot;
|
|
32
36
|
/**
|
|
33
37
|
* Subscribe to fixture snapshot changes.
|
|
34
38
|
* @param fn - change callback.
|
|
@@ -40,6 +44,14 @@ export declare class FixtureSession implements SessionFace {
|
|
|
40
44
|
* @returns never — always throws.
|
|
41
45
|
*/
|
|
42
46
|
prompt(): never;
|
|
47
|
+
/**
|
|
48
|
+
* Minimal local-echo registration: mints an identity without touching the
|
|
49
|
+
* fixture snapshot (submission echoes are client-only presentation state).
|
|
50
|
+
* Supply `beginSubmission` on the fixture's session face to observe echoes.
|
|
51
|
+
* @returns a handle whose abandon is a no-op.
|
|
52
|
+
*/
|
|
53
|
+
beginSubmission(): SubmissionHandle;
|
|
54
|
+
private submissionSeq;
|
|
43
55
|
/**
|
|
44
56
|
* Fail-loud stub; supply `readAttachment` on the fixture's session face to exercise it.
|
|
45
57
|
* @param _attachmentId - opaque durable attachment id.
|
|
@@ -66,53 +78,44 @@ export declare class FixtureSession implements SessionFace {
|
|
|
66
78
|
* @returns never — always throws.
|
|
67
79
|
*/
|
|
68
80
|
loadOlder(): never;
|
|
81
|
+
/**
|
|
82
|
+
* Fail-loud stub; supply `loadThrough` on the fixture's session face to exercise it.
|
|
83
|
+
* @returns never — always throws.
|
|
84
|
+
*/
|
|
85
|
+
loadThrough(): never;
|
|
69
86
|
/**
|
|
70
87
|
* Fail-loud stub; supply `rename` on the fixture's session face to exercise it.
|
|
71
88
|
* @returns never — always throws.
|
|
72
89
|
*/
|
|
73
90
|
rename(): never;
|
|
74
91
|
}
|
|
75
|
-
/** Test binding shape handed to provider resolvers and feature injects (a SessionBinding whose session is the fixture face). */
|
|
76
|
-
export interface TestSessionBinding {
|
|
77
|
-
readonly sessionId: SessionId;
|
|
78
|
-
readonly session: FixtureSession;
|
|
79
|
-
readonly ctx: AgentContext;
|
|
80
|
-
}
|
|
81
92
|
/**
|
|
82
93
|
* Sessions test double behind the renderer host and feature injects: owns the
|
|
83
|
-
* list/current observable,
|
|
84
|
-
*
|
|
85
|
-
* `
|
|
94
|
+
* list/current observable, scope minting through the production `createScope`,
|
|
95
|
+
* stable Controller bindings, and the session behavior face supplied per
|
|
96
|
+
* fixture. `ui-session` owns standard-source materialization.
|
|
86
97
|
*
|
|
87
98
|
* Implements the same ISessions face features receive as `ctx.sessions`, so
|
|
88
99
|
* a production face change breaks this double at compile time; the extra
|
|
89
|
-
* members (add/
|
|
90
|
-
*
|
|
100
|
+
* members (add/updateSessionSnapshot/event-window drivers/setCurrent/remove/
|
|
101
|
+
* behavior/calls/stubs) are bench-only surface.
|
|
91
102
|
*/
|
|
92
103
|
export declare class TestSessions implements ISessions {
|
|
93
104
|
private readonly stabilize;
|
|
94
105
|
private readonly rootCtx;
|
|
95
106
|
/** The useSessions standard feed (list rows + current selection). */
|
|
96
107
|
readonly list: SnapshotStore<SessionListState>;
|
|
97
|
-
/**
|
|
98
|
-
* Atomic current-session provide projection (production SessionRuntime
|
|
99
|
-
* mirror): selection changes and provider-roster changes publish through
|
|
100
|
-
* this one source — the member the SlotRegistry host face hands the
|
|
101
|
-
* renderer's SessionProvider.
|
|
102
|
-
*/
|
|
103
|
-
readonly currentProvideInfo: HostObservable<SessionMaybeProvideInfo>;
|
|
104
108
|
private readonly records;
|
|
105
|
-
/** The production provide channel (roster, materialization rules, current projection) — no test-side mirror. */
|
|
106
|
-
private readonly channel;
|
|
107
109
|
/** Calls observed on the service-level face, newest last. */
|
|
108
110
|
readonly calls: {
|
|
109
|
-
method: 'open' | 'openSubagent' | 'setSubagentCatalogOpen' | 'refreshSubagents' | 'clear' | 'search' | 'fork';
|
|
111
|
+
method: 'create' | 'open' | 'openSubagent' | 'setSubagentCatalogOpen' | 'refreshSubagents' | 'clear' | 'refresh' | 'search' | 'fork';
|
|
110
112
|
args: unknown[];
|
|
111
113
|
}[];
|
|
112
114
|
/** The wire schema's `session.search` result bound (production parity). */
|
|
113
115
|
readonly searchResultLimit = 20;
|
|
114
116
|
/** Replaceable search behavior (see {@link TestSessions.stubSearch}). */
|
|
115
117
|
private searchStub;
|
|
118
|
+
private createStub;
|
|
116
119
|
/**
|
|
117
120
|
* @param stabilize - the owning runtime's act wrapper.
|
|
118
121
|
* @param rootCtx - the runtime's Cordis root; scope fibers mount under it.
|
|
@@ -128,12 +131,31 @@ export declare class TestSessions implements ISessions {
|
|
|
128
131
|
current?: boolean;
|
|
129
132
|
}): Promise<SessionId>;
|
|
130
133
|
/**
|
|
131
|
-
* Update
|
|
132
|
-
* live-stream stand-in: components subscribed via useSession re-render).
|
|
134
|
+
* Update Session Controller lifecycle state through an immer draft.
|
|
133
135
|
* @param id - session id.
|
|
134
136
|
* @param mutate - draft mutator.
|
|
135
137
|
*/
|
|
136
|
-
|
|
138
|
+
updateSessionSnapshot(id: string, mutate: (draft: SessionFixtureSnapshot) => void): Promise<void>;
|
|
139
|
+
/**
|
|
140
|
+
* Replace a Session's complete contiguous event window.
|
|
141
|
+
* @param id - Session identity.
|
|
142
|
+
* @param entries - complete event window.
|
|
143
|
+
* @param hasMore - whether older history remains.
|
|
144
|
+
*/
|
|
145
|
+
replaceEvents(id: string, entries: readonly SessionEventLikeEntry[], hasMore?: boolean): Promise<void>;
|
|
146
|
+
/**
|
|
147
|
+
* Prepend one older contiguous event page.
|
|
148
|
+
* @param id - Session identity.
|
|
149
|
+
* @param entries - older entries.
|
|
150
|
+
* @param hasMore - whether another older page remains.
|
|
151
|
+
*/
|
|
152
|
+
prependEvents(id: string, entries: readonly SessionEventLikeEntry[], hasMore?: boolean): Promise<void>;
|
|
153
|
+
/**
|
|
154
|
+
* Append one live event to a Session's contiguous window.
|
|
155
|
+
* @param id - Session identity.
|
|
156
|
+
* @param entry - live event entry.
|
|
157
|
+
*/
|
|
158
|
+
appendEvent(id: string, entry: SessionLiveEventEntry): Promise<void>;
|
|
137
159
|
/**
|
|
138
160
|
* Update a session's list row (the wire-echo stand-in: title settles,
|
|
139
161
|
* running flips — components subscribed via useSessions re-render).
|
|
@@ -149,31 +171,10 @@ export declare class TestSessions implements ISessions {
|
|
|
149
171
|
/**
|
|
150
172
|
* Remove a session: list row, scope fiber, and per-session store instances
|
|
151
173
|
* (with persisted state) die together — the same single lifecycle axis the
|
|
152
|
-
* production
|
|
174
|
+
* production Client Sessions service drives on session death, minus staging.
|
|
153
175
|
* @param id - session id.
|
|
154
176
|
*/
|
|
155
177
|
remove(id: string): Promise<void>;
|
|
156
|
-
/**
|
|
157
|
-
* Register a per-session standard-props provider (production `provide`
|
|
158
|
-
* contract: hooks become `use<Name>` selector hooks on the render side,
|
|
159
|
-
* props spread verbatim; duplicate names fail loud at materialization).
|
|
160
|
-
* @param descriptor - static member roster plus per-session resolver.
|
|
161
|
-
* @returns disposer removing the provider.
|
|
162
|
-
*/
|
|
163
|
-
provide(descriptor: SessionProvideDescriptor): () => void;
|
|
164
|
-
/**
|
|
165
|
-
* Resolve the definite per-session standard-props bundle (host face member).
|
|
166
|
-
* @param id - session id.
|
|
167
|
-
* @returns the identity-stable bundle, or undefined for unknown sessions.
|
|
168
|
-
*/
|
|
169
|
-
provideInfo(id: string): SessionProvideInfo | undefined;
|
|
170
|
-
/**
|
|
171
|
-
* Resolve the current-session-optional standard kit (host face member):
|
|
172
|
-
* unknown or absent ids return the static no-session projection.
|
|
173
|
-
* @param id - current session id, when selected.
|
|
174
|
-
* @returns a definite or no-session provide bundle.
|
|
175
|
-
*/
|
|
176
|
-
maybeProvideInfo(id: string | undefined): SessionMaybeProvideInfo;
|
|
177
178
|
/**
|
|
178
179
|
* Resolve (mint on first touch) the session-scoped Cordis context through
|
|
179
180
|
* the production `createScope`, so real `scopeOf`/scope-addressed services
|
|
@@ -187,7 +188,7 @@ export declare class TestSessions implements ISessions {
|
|
|
187
188
|
* @param id - session id.
|
|
188
189
|
* @returns sessionId + behavior face + scoped ctx, or undefined when unknown.
|
|
189
190
|
*/
|
|
190
|
-
binding(id: string):
|
|
191
|
+
binding(id: string): SessionBinding | undefined;
|
|
191
192
|
/**
|
|
192
193
|
* Read the session scope tag off a context (service-method boundary mirror).
|
|
193
194
|
* @param ctx - any client context.
|
|
@@ -201,6 +202,13 @@ export declare class TestSessions implements ISessions {
|
|
|
201
202
|
* @returns the fixture session face, or undefined off-scope.
|
|
202
203
|
*/
|
|
203
204
|
sessionOf(ctx: Context): SessionFace | undefined;
|
|
205
|
+
/**
|
|
206
|
+
* Install Session creation behavior for navigation tests.
|
|
207
|
+
* @param impl - implementation that must return an already-added fixture id.
|
|
208
|
+
*/
|
|
209
|
+
stubCreate(impl: (opts: Parameters<ISessions['create']>[0]) => Promise<SessionId>): void;
|
|
210
|
+
/** Create through the installed test behavior and require an addressable binding. */
|
|
211
|
+
create(opts?: Parameters<ISessions['create']>[0]): Promise<SessionId>;
|
|
204
212
|
/**
|
|
205
213
|
* Service-level selection call (recorded, then applied to the list store
|
|
206
214
|
* synchronously — inject callbacks call this outside any act window; the
|
|
@@ -216,10 +224,10 @@ export declare class TestSessions implements ISessions {
|
|
|
216
224
|
setSubagentCatalogOpen(parentSessionId: SessionId, open: boolean): void;
|
|
217
225
|
/** Record a catalog refresh; fixture callers drive snapshots explicitly. */
|
|
218
226
|
refreshSubagents(parentSessionId: SessionId): Promise<void>;
|
|
219
|
-
/** Apply a confirmed preset switch into the fixture list, as production does. */
|
|
220
|
-
noteAgentPreset(sessionId: SessionId, agentPreset: string): void;
|
|
221
227
|
/** Clear the current selection (recorded; the production no-session flow). */
|
|
222
228
|
clear(): void;
|
|
229
|
+
/** Record a list refresh; fixture callers publish list state explicitly. */
|
|
230
|
+
refresh(): Promise<void>;
|
|
223
231
|
/**
|
|
224
232
|
* Replace the sidebar-search result page (the call is still recorded).
|
|
225
233
|
* @param impl - hits for a query, as the Host would rank them.
|
|
@@ -252,7 +260,7 @@ export declare class TestSessions implements ISessions {
|
|
|
252
260
|
* The session face of a fixture (typed view for assertions; fixture
|
|
253
261
|
* behavior methods are grafted onto it).
|
|
254
262
|
* @param id - session id.
|
|
255
|
-
* @returns the FixtureSession
|
|
263
|
+
* @returns the FixtureSession carried by the Controller binding.
|
|
256
264
|
*/
|
|
257
265
|
behavior(id: string): FixtureSession;
|
|
258
266
|
/** Dispose minted scope fibers (runtime dispose path). */
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/** Test double for the `settings` Remote namespace a bench's plugins inject. */
|
|
2
|
+
import { vi } from 'vitest';
|
|
3
|
+
/** The minimum a scripted namespace view carries for the double's own bookkeeping. */
|
|
4
|
+
export interface ScriptedNamespace {
|
|
5
|
+
/** Namespace key the write addresses. */
|
|
6
|
+
ns: string;
|
|
7
|
+
}
|
|
8
|
+
/** One scripted `settings` namespace face plus the controls a bench drives it with. */
|
|
9
|
+
export interface ScriptedSettingsRemote<View extends ScriptedNamespace> {
|
|
10
|
+
/**
|
|
11
|
+
* The namespace face handed to `TestRemote` as `settings`. A plugin injecting
|
|
12
|
+
* `remote.settings` unparks on it, which is what most benches need; the
|
|
13
|
+
* describe answer is the same one the shared mirror would read.
|
|
14
|
+
*/
|
|
15
|
+
settings: {
|
|
16
|
+
describe(): Promise<{
|
|
17
|
+
ok: true;
|
|
18
|
+
value: {
|
|
19
|
+
writable: boolean;
|
|
20
|
+
hasDocument: boolean;
|
|
21
|
+
namespaces: readonly View[];
|
|
22
|
+
};
|
|
23
|
+
}>;
|
|
24
|
+
update(ns: string, patch: unknown, expectedRevision: number | undefined): Promise<{
|
|
25
|
+
ok: true;
|
|
26
|
+
value: View;
|
|
27
|
+
} | {
|
|
28
|
+
ok: false;
|
|
29
|
+
error: {
|
|
30
|
+
code: string;
|
|
31
|
+
message: string;
|
|
32
|
+
details: object;
|
|
33
|
+
};
|
|
34
|
+
}>;
|
|
35
|
+
replace(ns: string, section: unknown, expectedRevision: number | undefined): Promise<{
|
|
36
|
+
ok: true;
|
|
37
|
+
value: View;
|
|
38
|
+
} | {
|
|
39
|
+
ok: false;
|
|
40
|
+
error: {
|
|
41
|
+
code: string;
|
|
42
|
+
message: string;
|
|
43
|
+
details: object;
|
|
44
|
+
};
|
|
45
|
+
}>;
|
|
46
|
+
mutate(ns: string, ops: unknown, expectedRevision: number | undefined): Promise<{
|
|
47
|
+
ok: true;
|
|
48
|
+
value: View;
|
|
49
|
+
} | {
|
|
50
|
+
ok: false;
|
|
51
|
+
error: {
|
|
52
|
+
code: string;
|
|
53
|
+
message: string;
|
|
54
|
+
details: object;
|
|
55
|
+
};
|
|
56
|
+
}>;
|
|
57
|
+
};
|
|
58
|
+
/** Spy behind `settings.update`, for argument assertions. */
|
|
59
|
+
update: ReturnType<typeof vi.fn>;
|
|
60
|
+
/** Spy behind `settings.replace`, for argument assertions. */
|
|
61
|
+
replace: ReturnType<typeof vi.fn>;
|
|
62
|
+
/** Spy behind `settings.mutate`, for argument assertions. */
|
|
63
|
+
mutate: ReturnType<typeof vi.fn>;
|
|
64
|
+
/**
|
|
65
|
+
* Replace what the next describe answers with, as a Host commit would.
|
|
66
|
+
* @param namespaces - the namespace views to serve from now on.
|
|
67
|
+
*/
|
|
68
|
+
publish(namespaces: readonly View[]): void;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Build a scripted `settings` Remote namespace for a bench. Each write answers
|
|
72
|
+
* with the addressed namespace unchanged, so a bench that only needs its
|
|
73
|
+
* plugins to activate scripts nothing; one asserting a write reads the
|
|
74
|
+
* corresponding spy or replaces the face.
|
|
75
|
+
* @param namespaces - namespace views the first describe answers with.
|
|
76
|
+
* @param options - deployment facts the describe answer reports.
|
|
77
|
+
* @returns the face and its controls.
|
|
78
|
+
*/
|
|
79
|
+
export declare function scriptedSettingsRemote<View extends ScriptedNamespace>(namespaces?: readonly View[], options?: {
|
|
80
|
+
writable?: boolean;
|
|
81
|
+
hasDocument?: boolean;
|
|
82
|
+
}): ScriptedSettingsRemote<View>;
|
|
83
|
+
//# sourceMappingURL=settings-remote.d.ts.map
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/** Test double for the client settings-scope seam. */
|
|
2
2
|
import { vi } from 'vitest';
|
|
3
|
-
import type { SettingsScope, SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-
|
|
3
|
+
import type { SettingsScope, SettingsScopeSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
4
4
|
/** Handle over one stubbed scope: the scope, its write spy, and publication controls. */
|
|
5
5
|
export interface StubSettingsScope<T> {
|
|
6
6
|
/** The scope face handed to the service under test. */
|
|
7
7
|
scope: SettingsScope<T>;
|
|
8
8
|
/** Spy behind `scope.set`; resolves immediately. */
|
|
9
9
|
set: ReturnType<typeof vi.fn>;
|
|
10
|
+
/** Spy behind `scope.mutate`; resolves immediately. */
|
|
11
|
+
mutate: ReturnType<typeof vi.fn>;
|
|
10
12
|
/** Spy behind `scope.unset`; resolves immediately. */
|
|
11
13
|
unset: ReturnType<typeof vi.fn>;
|
|
12
14
|
/** @returns how many listeners are currently subscribed (disposal assertions). */
|
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type { IWorkspaces, WorkspaceId, WorkspaceSnapshot, WorkspaceView } from '@deepseek-ai/dsh-api-workspace-controller/client';
|
|
2
|
+
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
3
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
4
|
+
import type { FixtureSnapshot, Stabilizer } from './fixtures.ts';
|
|
5
|
+
/** Writable test representation of the immutable Workspace Controller snapshot. */
|
|
6
|
+
type WorkspaceFixtureSnapshot = FixtureSnapshot<WorkspaceSnapshot>;
|
|
7
|
+
/** Callable command names on the production Workspace Controller face. */
|
|
8
|
+
type WorkspaceAction = {
|
|
9
|
+
[Key in keyof IWorkspaces]: IWorkspaces[Key] extends (...args: never[]) => unknown ? Key : never;
|
|
10
|
+
}[keyof IWorkspaces];
|
|
11
|
+
/** Test replacement retaining one Controller command's parameters and result. */
|
|
12
|
+
type WorkspaceStub<Key extends WorkspaceAction> = (...args: Parameters<IWorkspaces[Key]>) => ReturnType<IWorkspaces[Key]>;
|
|
3
13
|
/**
|
|
4
14
|
* Workspaces test double. Implements the same IWorkspaces face features
|
|
5
15
|
* receive as `ctx.workspaces`, so a production face change breaks this
|
|
@@ -10,7 +20,7 @@ import type { Stabilizer } from './fixtures.ts';
|
|
|
10
20
|
export declare class TestWorkspaces implements IWorkspaces {
|
|
11
21
|
private readonly stabilize;
|
|
12
22
|
/** The useWorkspaces standard feed. */
|
|
13
|
-
readonly list: SnapshotStore<
|
|
23
|
+
readonly list: SnapshotStore<WorkspaceFixtureSnapshot>;
|
|
14
24
|
/** Calls observed on the action face, newest last. */
|
|
15
25
|
readonly calls: {
|
|
16
26
|
method: string;
|
|
@@ -26,26 +36,13 @@ export declare class TestWorkspaces implements IWorkspaces {
|
|
|
26
36
|
* Update the workspace list state through an immer draft.
|
|
27
37
|
* @param mutate - draft mutator.
|
|
28
38
|
*/
|
|
29
|
-
update(mutate: (draft:
|
|
39
|
+
update(mutate: (draft: WorkspaceFixtureSnapshot) => void): Promise<void>;
|
|
30
40
|
/**
|
|
31
41
|
* Replace an action's behavior (the recorded call is still appended first).
|
|
32
|
-
* @param method - action name (e.g. '
|
|
42
|
+
* @param method - Controller action name (e.g. 'create').
|
|
33
43
|
* @param impl - replacement behavior.
|
|
34
44
|
*/
|
|
35
|
-
stub(method:
|
|
36
|
-
/**
|
|
37
|
-
* Connect a workspace to its reusable/new blank session (recorded). The
|
|
38
|
-
* default resolves the workspace id back as the session id; stub for
|
|
39
|
-
* cross-session flows.
|
|
40
|
-
* @param workspaceId - target workspace.
|
|
41
|
-
* @returns the connected session id.
|
|
42
|
-
*/
|
|
43
|
-
connectWorkspace(workspaceId: WorkspaceId): Promise<SessionId>;
|
|
44
|
-
/**
|
|
45
|
-
* New-session flow (recorded; stubbed behavior runs when installed).
|
|
46
|
-
* @param workspaceId - optional explicit workspace target.
|
|
47
|
-
*/
|
|
48
|
-
startSession(workspaceId?: WorkspaceId): void;
|
|
45
|
+
stub<Key extends WorkspaceAction>(method: Key, impl: WorkspaceStub<Key>): void;
|
|
49
46
|
/**
|
|
50
47
|
* Create a Workspace (recorded). The default echoes a view derived from
|
|
51
48
|
* the input; stub for failure or list-coupled flows.
|
|
@@ -55,30 +52,6 @@ export declare class TestWorkspaces implements IWorkspaces {
|
|
|
55
52
|
create(input: {
|
|
56
53
|
path: string;
|
|
57
54
|
}): Promise<WorkspaceView>;
|
|
58
|
-
/**
|
|
59
|
-
* Open a path with the host OS default application (recorded; default no-op).
|
|
60
|
-
* @param path - host-resolvable path.
|
|
61
|
-
*/
|
|
62
|
-
openPath(path: string): Promise<void>;
|
|
63
|
-
/**
|
|
64
|
-
* Directory picker (recorded). The default cancels (null); stub to select.
|
|
65
|
-
* @returns the picked path, or null.
|
|
66
|
-
*/
|
|
67
|
-
pickDirectory(): Promise<string | null>;
|
|
68
|
-
/**
|
|
69
|
-
* Browse listing (recorded). The default serves an empty home level; stub
|
|
70
|
-
* to shape a tree.
|
|
71
|
-
* @param path - absolute directory to list; absent lists the home level.
|
|
72
|
-
* @returns the level's listing.
|
|
73
|
-
*/
|
|
74
|
-
listDirectory(path?: string, signal?: AbortSignal): Promise<DirectoryListing>;
|
|
75
|
-
/**
|
|
76
|
-
* Browse child creation (recorded). The default joins parent and name.
|
|
77
|
-
* @param path - absolute existing parent directory.
|
|
78
|
-
* @param name - single path segment.
|
|
79
|
-
* @returns the created directory's absolute path.
|
|
80
|
-
*/
|
|
81
|
-
createDirectory(path: string, name: string): Promise<string>;
|
|
82
55
|
/**
|
|
83
56
|
* Rename a Workspace (recorded). The default echoes a minimal view.
|
|
84
57
|
* @param workspaceId - target workspace.
|
|
@@ -112,4 +85,5 @@ export declare class TestWorkspaces implements IWorkspaces {
|
|
|
112
85
|
*/
|
|
113
86
|
archiveSession(sessionId: SessionId): Promise<void>;
|
|
114
87
|
}
|
|
88
|
+
export {};
|
|
115
89
|
//# sourceMappingURL=workspaces.d.ts.map
|