macro-agent 0.0.13 → 0.0.15
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/.claude/settings.local.json +59 -0
- package/dist/agent/agent-manager.d.ts.map +1 -1
- package/dist/agent/agent-manager.js +10 -4
- package/dist/agent/agent-manager.js.map +1 -1
- package/dist/cli/acp.d.ts +6 -0
- package/dist/cli/acp.d.ts.map +1 -1
- package/dist/cli/acp.js +16 -2
- package/dist/cli/acp.js.map +1 -1
- package/dist/map/adapter/index.d.ts +1 -1
- package/dist/map/adapter/index.d.ts.map +1 -1
- package/dist/map/adapter/index.js +1 -1
- package/dist/map/adapter/index.js.map +1 -1
- package/dist/map/utils/address-translation.d.ts +99 -0
- package/dist/map/utils/address-translation.d.ts.map +1 -0
- package/dist/map/utils/address-translation.js +285 -0
- package/dist/map/utils/address-translation.js.map +1 -0
- package/dist/map/utils/index.d.ts +7 -0
- package/dist/map/utils/index.d.ts.map +1 -0
- package/dist/map/utils/index.js +7 -0
- package/dist/map/utils/index.js.map +1 -0
- package/dist/server/combined-server.d.ts.map +1 -1
- package/dist/server/combined-server.js +8 -1
- package/dist/server/combined-server.js.map +1 -1
- package/dist/store/event-store.js +9 -2
- package/dist/store/event-store.js.map +1 -1
- package/dist/store/types/agents.d.ts +2 -0
- package/dist/store/types/agents.d.ts.map +1 -1
- package/package.json +4 -4
- package/references/acp-factory-ref/CHANGELOG.md +33 -0
- package/references/acp-factory-ref/LICENSE +21 -0
- package/references/acp-factory-ref/README.md +341 -0
- package/references/acp-factory-ref/package-lock.json +3102 -0
- package/references/acp-factory-ref/package.json +96 -0
- package/references/acp-factory-ref/python/CHANGELOG.md +33 -0
- package/references/acp-factory-ref/python/LICENSE +21 -0
- package/references/acp-factory-ref/python/Makefile +57 -0
- package/references/acp-factory-ref/python/README.md +253 -0
- package/references/acp-factory-ref/python/pyproject.toml +73 -0
- package/references/acp-factory-ref/python/tests/__init__.py +0 -0
- package/references/acp-factory-ref/python/tests/e2e/__init__.py +1 -0
- package/references/acp-factory-ref/python/tests/e2e/test_codex_e2e.py +349 -0
- package/references/acp-factory-ref/python/tests/e2e/test_gemini_e2e.py +165 -0
- package/references/acp-factory-ref/python/tests/e2e/test_opencode_e2e.py +296 -0
- package/references/acp-factory-ref/python/tests/test_client_handler.py +543 -0
- package/references/acp-factory-ref/python/tests/test_pushable.py +199 -0
- package/references/claude-code-acp/.github/workflows/ci.yml +45 -0
- package/references/claude-code-acp/.github/workflows/publish.yml +34 -0
- package/references/claude-code-acp/.prettierrc.json +4 -0
- package/references/claude-code-acp/CHANGELOG.md +249 -0
- package/references/claude-code-acp/LICENSE +222 -0
- package/references/claude-code-acp/README.md +53 -0
- package/references/claude-code-acp/docs/RELEASES.md +24 -0
- package/references/claude-code-acp/eslint.config.js +48 -0
- package/references/claude-code-acp/package-lock.json +4570 -0
- package/references/claude-code-acp/package.json +88 -0
- package/references/claude-code-acp/scripts/release.sh +119 -0
- package/references/claude-code-acp/src/acp-agent.ts +2079 -0
- package/references/claude-code-acp/src/index.ts +26 -0
- package/references/claude-code-acp/src/lib.ts +38 -0
- package/references/claude-code-acp/src/mcp-server.ts +911 -0
- package/references/claude-code-acp/src/settings.ts +522 -0
- package/references/claude-code-acp/src/tests/.claude/commands/quick-math.md +5 -0
- package/references/claude-code-acp/src/tests/.claude/commands/say-hello.md +6 -0
- package/references/claude-code-acp/src/tests/acp-agent-fork.test.ts +479 -0
- package/references/claude-code-acp/src/tests/acp-agent.test.ts +1502 -0
- package/references/claude-code-acp/src/tests/extract-lines.test.ts +103 -0
- package/references/claude-code-acp/src/tests/fork-session.test.ts +335 -0
- package/references/claude-code-acp/src/tests/replace-and-calculate-location.test.ts +334 -0
- package/references/claude-code-acp/src/tests/settings.test.ts +617 -0
- package/references/claude-code-acp/src/tests/skills-options.test.ts +187 -0
- package/references/claude-code-acp/src/tests/tools.test.ts +318 -0
- package/references/claude-code-acp/src/tests/typescript-declarations.test.ts +558 -0
- package/references/claude-code-acp/src/tools.ts +819 -0
- package/references/claude-code-acp/src/utils.ts +171 -0
- package/references/claude-code-acp/tsconfig.json +18 -0
- package/references/claude-code-acp/vitest.config.ts +19 -0
- package/references/multi-agent-protocol/.sudocode/issues.jsonl +111 -0
- package/references/multi-agent-protocol/.sudocode/specs.jsonl +13 -0
- package/references/multi-agent-protocol/LICENSE +21 -0
- package/references/multi-agent-protocol/README.md +113 -0
- package/references/multi-agent-protocol/docs/00-design-specification.md +496 -0
- package/references/multi-agent-protocol/docs/01-open-questions.md +1050 -0
- package/references/multi-agent-protocol/docs/02-wire-protocol.md +296 -0
- package/references/multi-agent-protocol/docs/03-streaming-semantics.md +252 -0
- package/references/multi-agent-protocol/docs/04-error-handling.md +231 -0
- package/references/multi-agent-protocol/docs/05-connection-model.md +244 -0
- package/references/multi-agent-protocol/docs/06-visibility-permissions.md +243 -0
- package/references/multi-agent-protocol/docs/07-federation.md +259 -0
- package/references/multi-agent-protocol/docs/08-macro-agent-migration.md +253 -0
- package/references/multi-agent-protocol/docs/09-authentication.md +680 -0
- package/references/multi-agent-protocol/docs/10-mail-protocol.md +553 -0
- package/references/multi-agent-protocol/docs/agent-iam-integration.md +877 -0
- package/references/multi-agent-protocol/docs/agentic-mesh-integration-draft.md +459 -0
- package/references/multi-agent-protocol/docs/git-transport-draft.md +251 -0
- package/references/multi-agent-protocol/docs-site/Gemfile +22 -0
- package/references/multi-agent-protocol/docs-site/README.md +82 -0
- package/references/multi-agent-protocol/docs-site/_config.yml +91 -0
- package/references/multi-agent-protocol/docs-site/_includes/head_custom.html +20 -0
- package/references/multi-agent-protocol/docs-site/_sass/color_schemes/map.scss +42 -0
- package/references/multi-agent-protocol/docs-site/_sass/custom/custom.scss +34 -0
- package/references/multi-agent-protocol/docs-site/examples/full-integration.md +510 -0
- package/references/multi-agent-protocol/docs-site/examples/index.md +138 -0
- package/references/multi-agent-protocol/docs-site/examples/simple-chat.md +282 -0
- package/references/multi-agent-protocol/docs-site/examples/task-queue.md +399 -0
- package/references/multi-agent-protocol/docs-site/getting-started/index.md +98 -0
- package/references/multi-agent-protocol/docs-site/getting-started/installation.md +219 -0
- package/references/multi-agent-protocol/docs-site/getting-started/overview.md +172 -0
- package/references/multi-agent-protocol/docs-site/getting-started/quickstart.md +237 -0
- package/references/multi-agent-protocol/docs-site/index.md +136 -0
- package/references/multi-agent-protocol/docs-site/protocol/authentication.md +391 -0
- package/references/multi-agent-protocol/docs-site/protocol/connection-model.md +376 -0
- package/references/multi-agent-protocol/docs-site/protocol/design.md +284 -0
- package/references/multi-agent-protocol/docs-site/protocol/error-handling.md +312 -0
- package/references/multi-agent-protocol/docs-site/protocol/federation.md +449 -0
- package/references/multi-agent-protocol/docs-site/protocol/index.md +129 -0
- package/references/multi-agent-protocol/docs-site/protocol/permissions.md +398 -0
- package/references/multi-agent-protocol/docs-site/protocol/streaming.md +353 -0
- package/references/multi-agent-protocol/docs-site/protocol/wire-protocol.md +369 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/agent.md +357 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/client.md +380 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/index.md +62 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/server.md +453 -0
- package/references/multi-agent-protocol/docs-site/sdk/api/types.md +468 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/agent.md +375 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/authentication.md +405 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/client.md +352 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/index.md +89 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/server.md +360 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/testing.md +446 -0
- package/references/multi-agent-protocol/docs-site/sdk/guides/transports.md +363 -0
- package/references/multi-agent-protocol/docs-site/sdk/index.md +206 -0
- package/references/multi-agent-protocol/package-lock.json +3886 -0
- package/references/multi-agent-protocol/package.json +56 -0
- package/references/multi-agent-protocol/schema/meta.json +467 -0
- package/references/multi-agent-protocol/schema/schema.json +2558 -0
- package/src/agent/__tests__/agent-manager.test.ts +67 -1
- package/src/agent/agent-manager.ts +10 -4
- package/src/cli/__tests__/stable-instance-id.test.ts +57 -0
- package/src/cli/acp.ts +17 -2
- package/src/map/adapter/index.ts +3 -0
- package/src/server/combined-server.ts +10 -0
- package/src/store/event-store.ts +10 -3
- package/src/store/types/agents.ts +2 -0
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Testing
|
|
3
|
+
parent: Guides
|
|
4
|
+
grand_parent: SDK
|
|
5
|
+
nav_order: 6
|
|
6
|
+
description: "Test your MAP integrations"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Testing
|
|
10
|
+
{: .no_toc }
|
|
11
|
+
|
|
12
|
+
Test your MAP integrations effectively.
|
|
13
|
+
{: .fs-6 .fw-300 }
|
|
14
|
+
|
|
15
|
+
## Table of contents
|
|
16
|
+
{: .no_toc .text-delta }
|
|
17
|
+
|
|
18
|
+
1. TOC
|
|
19
|
+
{:toc}
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Overview
|
|
24
|
+
|
|
25
|
+
The SDK provides utilities for testing MAP integrations without network overhead.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## In-Memory Testing
|
|
30
|
+
|
|
31
|
+
Use `createStreamPair()` to create connected streams for testing:
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { createStreamPair } from "@multi-agent-protocol/sdk/stream";
|
|
35
|
+
import { MAPServer } from "@multi-agent-protocol/sdk/server";
|
|
36
|
+
import { ClientConnection, AgentConnection } from "@multi-agent-protocol/sdk";
|
|
37
|
+
|
|
38
|
+
describe("MAP Integration", () => {
|
|
39
|
+
let server: MAPServer;
|
|
40
|
+
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
server = new MAPServer({ name: "TestServer" });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
afterEach(async () => {
|
|
46
|
+
await server.close();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should connect a client", async () => {
|
|
50
|
+
const [clientStream, serverStream] = createStreamPair();
|
|
51
|
+
server.accept(serverStream).start();
|
|
52
|
+
|
|
53
|
+
const client = new ClientConnection(clientStream, { name: "TestClient" });
|
|
54
|
+
const result = await client.connect();
|
|
55
|
+
|
|
56
|
+
expect(result.sessionId).toBeDefined();
|
|
57
|
+
expect(result.systemInfo?.name).toBe("TestServer");
|
|
58
|
+
|
|
59
|
+
await client.disconnect();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Testing Agents
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { createStreamPair } from "@multi-agent-protocol/sdk/stream";
|
|
70
|
+
import { MAPServer } from "@multi-agent-protocol/sdk/server";
|
|
71
|
+
import { AgentConnection } from "@multi-agent-protocol/sdk";
|
|
72
|
+
|
|
73
|
+
describe("Agent", () => {
|
|
74
|
+
let server: MAPServer;
|
|
75
|
+
|
|
76
|
+
beforeEach(() => {
|
|
77
|
+
server = new MAPServer({ name: "TestServer" });
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
afterEach(async () => {
|
|
81
|
+
await server.close();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("should register an agent", async () => {
|
|
85
|
+
const [agentStream, serverStream] = createStreamPair();
|
|
86
|
+
server.accept(serverStream).start();
|
|
87
|
+
|
|
88
|
+
const agent = new AgentConnection(agentStream, {
|
|
89
|
+
name: "TestAgent",
|
|
90
|
+
role: "worker",
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const { agent: registered } = await agent.connect();
|
|
94
|
+
|
|
95
|
+
expect(registered.id).toBeDefined();
|
|
96
|
+
expect(registered.name).toBe("TestAgent");
|
|
97
|
+
expect(registered.role).toBe("worker");
|
|
98
|
+
|
|
99
|
+
// Verify agent is in registry
|
|
100
|
+
const agents = server.agents.list();
|
|
101
|
+
expect(agents).toHaveLength(1);
|
|
102
|
+
expect(agents[0].name).toBe("TestAgent");
|
|
103
|
+
|
|
104
|
+
await agent.disconnect();
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("should handle messages", async () => {
|
|
108
|
+
const [agentStream, serverStream] = createStreamPair();
|
|
109
|
+
server.accept(serverStream).start();
|
|
110
|
+
|
|
111
|
+
const agent = new AgentConnection(agentStream, {
|
|
112
|
+
name: "TestAgent",
|
|
113
|
+
role: "worker",
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const receivedMessages: any[] = [];
|
|
117
|
+
agent.onMessage((message) => {
|
|
118
|
+
receivedMessages.push(message);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
await agent.connect();
|
|
122
|
+
|
|
123
|
+
// Send message directly through server
|
|
124
|
+
server.messages.send({
|
|
125
|
+
to: { agentId: agent.id },
|
|
126
|
+
payload: { type: "test", data: "hello" },
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Wait for message delivery
|
|
130
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
131
|
+
|
|
132
|
+
expect(receivedMessages).toHaveLength(1);
|
|
133
|
+
expect(receivedMessages[0].payload.type).toBe("test");
|
|
134
|
+
|
|
135
|
+
await agent.disconnect();
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Testing Client Subscriptions
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
describe("Client Subscriptions", () => {
|
|
146
|
+
let server: MAPServer;
|
|
147
|
+
|
|
148
|
+
beforeEach(() => {
|
|
149
|
+
server = new MAPServer({ name: "TestServer" });
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
afterEach(async () => {
|
|
153
|
+
await server.close();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("should receive events", async () => {
|
|
157
|
+
const [clientStream, serverStream] = createStreamPair();
|
|
158
|
+
server.accept(serverStream).start();
|
|
159
|
+
|
|
160
|
+
const client = new ClientConnection(clientStream, { name: "TestClient" });
|
|
161
|
+
await client.connect();
|
|
162
|
+
|
|
163
|
+
// Subscribe to agent events
|
|
164
|
+
const subscription = await client.subscribe({
|
|
165
|
+
eventTypes: ["agent.registered"],
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Collect events
|
|
169
|
+
const events: any[] = [];
|
|
170
|
+
const eventPromise = (async () => {
|
|
171
|
+
for await (const event of subscription) {
|
|
172
|
+
events.push(event);
|
|
173
|
+
if (events.length >= 1) break;
|
|
174
|
+
}
|
|
175
|
+
})();
|
|
176
|
+
|
|
177
|
+
// Register an agent
|
|
178
|
+
const [agentStream, agentServerStream] = createStreamPair();
|
|
179
|
+
server.accept(agentServerStream).start();
|
|
180
|
+
const agent = new AgentConnection(agentStream, { name: "NewAgent" });
|
|
181
|
+
await agent.connect();
|
|
182
|
+
|
|
183
|
+
// Wait for event
|
|
184
|
+
await eventPromise;
|
|
185
|
+
|
|
186
|
+
expect(events).toHaveLength(1);
|
|
187
|
+
expect(events[0].type).toBe("agent.registered");
|
|
188
|
+
expect(events[0].data.agent.name).toBe("NewAgent");
|
|
189
|
+
|
|
190
|
+
await subscription.unsubscribe();
|
|
191
|
+
await agent.disconnect();
|
|
192
|
+
await client.disconnect();
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Testing Agent-to-Agent Messaging
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
describe("Agent Messaging", () => {
|
|
203
|
+
let server: MAPServer;
|
|
204
|
+
|
|
205
|
+
beforeEach(() => {
|
|
206
|
+
server = new MAPServer({ name: "TestServer" });
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
afterEach(async () => {
|
|
210
|
+
await server.close();
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it("should send messages between agents", async () => {
|
|
214
|
+
// Create two agents
|
|
215
|
+
const [stream1, serverStream1] = createStreamPair();
|
|
216
|
+
const [stream2, serverStream2] = createStreamPair();
|
|
217
|
+
server.accept(serverStream1).start();
|
|
218
|
+
server.accept(serverStream2).start();
|
|
219
|
+
|
|
220
|
+
const agent1 = new AgentConnection(stream1, { name: "Agent1" });
|
|
221
|
+
const agent2 = new AgentConnection(stream2, { name: "Agent2" });
|
|
222
|
+
|
|
223
|
+
const agent2Messages: any[] = [];
|
|
224
|
+
agent2.onMessage((message) => {
|
|
225
|
+
agent2Messages.push(message);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const { agent: registered1 } = await agent1.connect();
|
|
229
|
+
const { agent: registered2 } = await agent2.connect();
|
|
230
|
+
|
|
231
|
+
// Agent1 sends to Agent2
|
|
232
|
+
await agent1.send({
|
|
233
|
+
to: { agentId: registered2.id },
|
|
234
|
+
payload: { type: "greeting", message: "Hello from Agent1" },
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// Wait for delivery
|
|
238
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
239
|
+
|
|
240
|
+
expect(agent2Messages).toHaveLength(1);
|
|
241
|
+
expect(agent2Messages[0].payload.message).toBe("Hello from Agent1");
|
|
242
|
+
expect(agent2Messages[0].from).toBe(registered1.id);
|
|
243
|
+
|
|
244
|
+
await agent1.disconnect();
|
|
245
|
+
await agent2.disconnect();
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Testing Scopes
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
describe("Scopes", () => {
|
|
256
|
+
let server: MAPServer;
|
|
257
|
+
|
|
258
|
+
beforeEach(() => {
|
|
259
|
+
server = new MAPServer({ name: "TestServer" });
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
afterEach(async () => {
|
|
263
|
+
await server.close();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it("should broadcast to scope members", async () => {
|
|
267
|
+
// Create three agents
|
|
268
|
+
const connections = await Promise.all([
|
|
269
|
+
createAgent(server, "Agent1"),
|
|
270
|
+
createAgent(server, "Agent2"),
|
|
271
|
+
createAgent(server, "Agent3"),
|
|
272
|
+
]);
|
|
273
|
+
|
|
274
|
+
const [agent1, agent2, agent3] = connections;
|
|
275
|
+
|
|
276
|
+
// Collect messages for agents 2 and 3
|
|
277
|
+
const messages2: any[] = [];
|
|
278
|
+
const messages3: any[] = [];
|
|
279
|
+
agent2.conn.onMessage((m) => messages2.push(m));
|
|
280
|
+
agent3.conn.onMessage((m) => messages3.push(m));
|
|
281
|
+
|
|
282
|
+
// Agent1 creates scope
|
|
283
|
+
const scope = await agent1.conn.createScope({ name: "team" });
|
|
284
|
+
|
|
285
|
+
// Agent2 joins, Agent3 doesn't
|
|
286
|
+
await agent2.conn.joinScope(scope.id);
|
|
287
|
+
|
|
288
|
+
// Agent1 broadcasts to scope
|
|
289
|
+
await agent1.conn.send({
|
|
290
|
+
to: { scopeId: scope.id },
|
|
291
|
+
payload: { type: "announcement", text: "Team meeting!" },
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
295
|
+
|
|
296
|
+
// Only Agent2 (scope member) receives the message
|
|
297
|
+
expect(messages2).toHaveLength(1);
|
|
298
|
+
expect(messages3).toHaveLength(0);
|
|
299
|
+
|
|
300
|
+
// Cleanup
|
|
301
|
+
for (const { conn } of connections) {
|
|
302
|
+
await conn.disconnect();
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
async function createAgent(server: MAPServer, name: string) {
|
|
308
|
+
const [stream, serverStream] = createStreamPair();
|
|
309
|
+
server.accept(serverStream).start();
|
|
310
|
+
const conn = new AgentConnection(stream, { name });
|
|
311
|
+
const { agent } = await conn.connect();
|
|
312
|
+
return { conn, agent };
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Test Utilities
|
|
319
|
+
|
|
320
|
+
### Helper for Multiple Connections
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
class TestHarness {
|
|
324
|
+
server: MAPServer;
|
|
325
|
+
connections: Array<{
|
|
326
|
+
stream: Stream;
|
|
327
|
+
client?: ClientConnection;
|
|
328
|
+
agent?: AgentConnection;
|
|
329
|
+
}> = [];
|
|
330
|
+
|
|
331
|
+
constructor() {
|
|
332
|
+
this.server = new MAPServer({ name: "TestServer" });
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
async createClient(name: string): Promise<ClientConnection> {
|
|
336
|
+
const [clientStream, serverStream] = createStreamPair();
|
|
337
|
+
this.server.accept(serverStream).start();
|
|
338
|
+
|
|
339
|
+
const client = new ClientConnection(clientStream, { name });
|
|
340
|
+
await client.connect();
|
|
341
|
+
|
|
342
|
+
this.connections.push({ stream: clientStream, client });
|
|
343
|
+
return client;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
async createAgent(name: string, role?: string): Promise<AgentConnection> {
|
|
347
|
+
const [agentStream, serverStream] = createStreamPair();
|
|
348
|
+
this.server.accept(serverStream).start();
|
|
349
|
+
|
|
350
|
+
const agent = new AgentConnection(agentStream, { name, role });
|
|
351
|
+
await agent.connect();
|
|
352
|
+
|
|
353
|
+
this.connections.push({ stream: agentStream, agent });
|
|
354
|
+
return agent;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
async cleanup() {
|
|
358
|
+
for (const { client, agent } of this.connections) {
|
|
359
|
+
if (client) await client.disconnect().catch(() => {});
|
|
360
|
+
if (agent) await agent.disconnect().catch(() => {});
|
|
361
|
+
}
|
|
362
|
+
await this.server.close();
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Usage
|
|
367
|
+
describe("With TestHarness", () => {
|
|
368
|
+
let harness: TestHarness;
|
|
369
|
+
|
|
370
|
+
beforeEach(() => {
|
|
371
|
+
harness = new TestHarness();
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
afterEach(async () => {
|
|
375
|
+
await harness.cleanup();
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
it("should work", async () => {
|
|
379
|
+
const client = await harness.createClient("TestClient");
|
|
380
|
+
const agent = await harness.createAgent("TestAgent", "worker");
|
|
381
|
+
|
|
382
|
+
const { agents } = await client.listAgents();
|
|
383
|
+
expect(agents).toHaveLength(1);
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Mocking
|
|
391
|
+
|
|
392
|
+
### Mock Event Emission
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
it("should handle events", async () => {
|
|
396
|
+
const harness = new TestHarness();
|
|
397
|
+
const client = await harness.createClient("TestClient");
|
|
398
|
+
|
|
399
|
+
const subscription = await client.subscribe({
|
|
400
|
+
eventTypes: ["custom.event"],
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
const events: any[] = [];
|
|
404
|
+
const eventPromise = collectEvents(subscription, events, 1);
|
|
405
|
+
|
|
406
|
+
// Emit custom event directly
|
|
407
|
+
harness.server.emit({
|
|
408
|
+
type: "custom.event",
|
|
409
|
+
data: { foo: "bar" },
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
await eventPromise;
|
|
413
|
+
expect(events[0].data.foo).toBe("bar");
|
|
414
|
+
|
|
415
|
+
await harness.cleanup();
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
async function collectEvents(
|
|
419
|
+
subscription: Subscription,
|
|
420
|
+
events: any[],
|
|
421
|
+
count: number
|
|
422
|
+
) {
|
|
423
|
+
for await (const event of subscription) {
|
|
424
|
+
events.push(event);
|
|
425
|
+
if (events.length >= count) break;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## Best Practices
|
|
433
|
+
|
|
434
|
+
1. **Use in-memory streams** - Avoid network in unit tests
|
|
435
|
+
2. **Clean up connections** - Always disconnect and close server
|
|
436
|
+
3. **Use timeouts wisely** - Allow time for async message delivery
|
|
437
|
+
4. **Test error cases** - Verify error handling works correctly
|
|
438
|
+
5. **Isolate tests** - Fresh server instance per test
|
|
439
|
+
6. **Use helpers** - Create utilities for common patterns
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## Next Steps
|
|
444
|
+
|
|
445
|
+
- [Server Setup](./server.html) - Configure test servers
|
|
446
|
+
- [Transports](./transports.html) - Understand transport options
|