@teneo-protocol/sdk 1.0.1 → 2.0.0
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/.github/workflows/publish-npm.yml +8 -6
- package/CHANGELOG.md +265 -0
- package/README.md +406 -53
- package/dist/core/websocket-client.d.ts +12 -0
- package/dist/core/websocket-client.d.ts.map +1 -1
- package/dist/core/websocket-client.js +22 -2
- package/dist/core/websocket-client.js.map +1 -1
- package/dist/handlers/message-handlers/agent-room-operation-response-handler.d.ts +76 -0
- package/dist/handlers/message-handlers/agent-room-operation-response-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/agent-room-operation-response-handler.js +70 -0
- package/dist/handlers/message-handlers/agent-room-operation-response-handler.js.map +1 -0
- package/dist/handlers/message-handlers/agent-selected-handler.d.ts +92 -38
- package/dist/handlers/message-handlers/agent-selected-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/agent-status-update-handler.d.ts +904 -0
- package/dist/handlers/message-handlers/agent-status-update-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/agent-status-update-handler.js +51 -0
- package/dist/handlers/message-handlers/agent-status-update-handler.js.map +1 -0
- package/dist/handlers/message-handlers/auth-error-handler.d.ts +45 -31
- package/dist/handlers/message-handlers/auth-error-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/auth-message-handler.d.ts +6 -0
- package/dist/handlers/message-handlers/auth-message-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/auth-message-handler.js +65 -5
- package/dist/handlers/message-handlers/auth-message-handler.js.map +1 -1
- package/dist/handlers/message-handlers/auth-required-handler.d.ts +49 -31
- package/dist/handlers/message-handlers/auth-required-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/auth-success-handler.d.ts +6 -0
- package/dist/handlers/message-handlers/auth-success-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/auth-success-handler.js +46 -4
- package/dist/handlers/message-handlers/auth-success-handler.js.map +1 -1
- package/dist/handlers/message-handlers/challenge-handler.d.ts +45 -31
- package/dist/handlers/message-handlers/challenge-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/error-message-handler.d.ts +49 -31
- package/dist/handlers/message-handlers/error-message-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/index.d.ts +5 -0
- package/dist/handlers/message-handlers/index.d.ts.map +1 -1
- package/dist/handlers/message-handlers/index.js +23 -1
- package/dist/handlers/message-handlers/index.js.map +1 -1
- package/dist/handlers/message-handlers/list-available-agents-handler.d.ts +877 -0
- package/dist/handlers/message-handlers/list-available-agents-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/list-available-agents-handler.js +38 -0
- package/dist/handlers/message-handlers/list-available-agents-handler.js.map +1 -0
- package/dist/handlers/message-handlers/list-room-agents-handler.d.ts +886 -0
- package/dist/handlers/message-handlers/list-room-agents-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/list-room-agents-handler.js +51 -0
- package/dist/handlers/message-handlers/list-room-agents-handler.js.map +1 -0
- package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts +178 -89
- package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/ping-pong-handler.d.ts +62 -58
- package/dist/handlers/message-handlers/ping-pong-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/regular-message-handler.d.ts +31 -29
- package/dist/handlers/message-handlers/regular-message-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/room-operation-response-handler.d.ts +328 -0
- package/dist/handlers/message-handlers/room-operation-response-handler.d.ts.map +1 -0
- package/dist/handlers/message-handlers/room-operation-response-handler.js +92 -0
- package/dist/handlers/message-handlers/room-operation-response-handler.js.map +1 -0
- package/dist/handlers/message-handlers/subscribe-response-handler.d.ts +53 -31
- package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -1
- package/dist/handlers/message-handlers/types.d.ts +2 -0
- package/dist/handlers/message-handlers/types.d.ts.map +1 -1
- package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts +53 -31
- package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -1
- package/dist/managers/agent-room-manager.d.ts +222 -0
- package/dist/managers/agent-room-manager.d.ts.map +1 -0
- package/dist/managers/agent-room-manager.js +508 -0
- package/dist/managers/agent-room-manager.js.map +1 -0
- package/dist/managers/index.d.ts +2 -0
- package/dist/managers/index.d.ts.map +1 -1
- package/dist/managers/index.js +5 -1
- package/dist/managers/index.js.map +1 -1
- package/dist/managers/room-management-manager.d.ts +213 -0
- package/dist/managers/room-management-manager.d.ts.map +1 -0
- package/dist/managers/room-management-manager.js +440 -0
- package/dist/managers/room-management-manager.js.map +1 -0
- package/dist/managers/room-manager.d.ts +4 -4
- package/dist/managers/room-manager.d.ts.map +1 -1
- package/dist/managers/room-manager.js.map +1 -1
- package/dist/teneo-sdk.d.ts +333 -13
- package/dist/teneo-sdk.d.ts.map +1 -1
- package/dist/teneo-sdk.js +468 -1
- package/dist/teneo-sdk.js.map +1 -1
- package/dist/types/config.d.ts +63 -54
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +8 -4
- package/dist/types/config.js.map +1 -1
- package/dist/types/error-codes.d.ts +2 -0
- package/dist/types/error-codes.d.ts.map +1 -1
- package/dist/types/error-codes.js +3 -0
- package/dist/types/error-codes.js.map +1 -1
- package/dist/types/events.d.ts +132 -68
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/events.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +27 -2
- package/dist/types/index.js.map +1 -1
- package/dist/types/messages.d.ts +11396 -2559
- package/dist/types/messages.d.ts.map +1 -1
- package/dist/types/messages.js +294 -27
- package/dist/types/messages.js.map +1 -1
- package/examples/.env.example +1 -1
- package/examples/agent-room-management-example.ts +334 -0
- package/examples/claude-agent-x-follower/.env.example +2 -2
- package/examples/claude-agent-x-follower/QUICKSTART.md +1 -1
- package/examples/claude-agent-x-follower/README.md +1 -1
- package/examples/n8n-teneo/.env.example +2 -2
- package/examples/n8n-teneo/README.md +1 -1
- package/examples/openai-teneo/.env.example +2 -2
- package/examples/openai-teneo/README.md +1 -1
- package/examples/production-dashboard/.env.example +2 -2
- package/examples/production-dashboard/README.md +89 -12
- package/examples/production-dashboard/public/dashboard.html +1173 -601
- package/examples/production-dashboard/server.ts +347 -5
- package/examples/room-management-example.ts +285 -0
- package/examples/usage/.env.example +1 -1
- package/examples/usage/01-connect.ts +1 -1
- package/examples/usage/02-list-agents.ts +1 -1
- package/examples/usage/03-pick-agent.ts +1 -1
- package/examples/usage/04-find-by-capability.ts +1 -1
- package/examples/usage/05-webhook-example.ts +1 -1
- package/examples/usage/06-simple-api-server.ts +1 -1
- package/examples/usage/07-event-listener.ts +1 -1
- package/examples/usage/README.md +1 -1
- package/package.json +9 -1
- package/src/core/websocket-client.ts +26 -2
- package/src/handlers/message-handlers/agent-room-operation-response-handler.ts +83 -0
- package/src/handlers/message-handlers/agent-status-update-handler.ts +58 -0
- package/src/handlers/message-handlers/auth-message-handler.ts +73 -5
- package/src/handlers/message-handlers/auth-success-handler.ts +58 -6
- package/src/handlers/message-handlers/index.ts +19 -0
- package/src/handlers/message-handlers/list-available-agents-handler.ts +41 -0
- package/src/handlers/message-handlers/list-room-agents-handler.ts +61 -0
- package/src/handlers/message-handlers/room-operation-response-handler.ts +105 -0
- package/src/handlers/message-handlers/types.ts +6 -0
- package/src/managers/agent-room-manager.ts +609 -0
- package/src/managers/index.ts +2 -0
- package/src/managers/room-management-manager.ts +523 -0
- package/src/managers/room-manager.ts +4 -5
- package/src/teneo-sdk.ts +505 -4
- package/src/types/config.ts +10 -5
- package/src/types/error-codes.ts +4 -0
- package/src/types/events.ts +24 -0
- package/src/types/index.ts +55 -0
- package/src/types/messages.ts +374 -41
- package/tests/integration/room-management.test.ts +514 -0
- package/tests/integration/websocket.test.ts +1 -1
- package/tests/unit/handlers/agent-room-operation-response-handler.test.ts +394 -0
- package/tests/unit/handlers/agent-status-update-handler.test.ts +407 -0
- package/tests/unit/handlers/auth-success-handler-rooms.test.ts +699 -0
- package/tests/unit/handlers/list-available-agents-handler.test.ts +256 -0
- package/tests/unit/handlers/list-room-agents-handler.test.ts +294 -0
- package/tests/unit/handlers/room-operation-response-handler.test.ts +527 -0
- package/tests/unit/managers/agent-room-manager.test.ts +534 -0
- package/tests/unit/managers/room-management-manager.test.ts +438 -0
|
@@ -0,0 +1,699 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for AuthSuccessHandler - Room Management Initialization
|
|
3
|
+
* Tests room categorization and room management manager initialization
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
7
|
+
import { AuthSuccessHandler } from "../../../src/handlers/message-handlers/auth-success-handler";
|
|
8
|
+
import { HandlerContext } from "../../../src/handlers/message-handlers/types";
|
|
9
|
+
import { AuthSuccessMessage, RoomInfo, Logger } from "../../../src/types";
|
|
10
|
+
|
|
11
|
+
describe("AuthSuccessHandler - Room Management", () => {
|
|
12
|
+
let handler: AuthSuccessHandler;
|
|
13
|
+
let mockContext: HandlerContext;
|
|
14
|
+
let mockLogger: Logger;
|
|
15
|
+
let mockRoomManagementManager: any;
|
|
16
|
+
let emitSpy: ReturnType<typeof vi.fn>;
|
|
17
|
+
let updateAuthStateSpy: ReturnType<typeof vi.fn>;
|
|
18
|
+
let updateConnectionStateSpy: ReturnType<typeof vi.fn>;
|
|
19
|
+
let getAuthStateSpy: ReturnType<typeof vi.fn>;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
// Create mock logger
|
|
23
|
+
mockLogger = {
|
|
24
|
+
debug: vi.fn(),
|
|
25
|
+
info: vi.fn(),
|
|
26
|
+
warn: vi.fn(),
|
|
27
|
+
error: vi.fn()
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Create mock room management manager
|
|
31
|
+
mockRoomManagementManager = {
|
|
32
|
+
setRoomLimit: vi.fn(),
|
|
33
|
+
setOwnedRooms: vi.fn(),
|
|
34
|
+
setSharedRooms: vi.fn()
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Create spies
|
|
38
|
+
emitSpy = vi.fn();
|
|
39
|
+
updateAuthStateSpy = vi.fn();
|
|
40
|
+
updateConnectionStateSpy = vi.fn();
|
|
41
|
+
getAuthStateSpy = vi.fn().mockReturnValue({
|
|
42
|
+
authenticated: true,
|
|
43
|
+
clientId: "client-123",
|
|
44
|
+
walletAddress: "0xabc..."
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Create mock context
|
|
48
|
+
mockContext = {
|
|
49
|
+
emit: emitSpy,
|
|
50
|
+
sendWebhook: vi.fn().mockResolvedValue(undefined),
|
|
51
|
+
logger: mockLogger,
|
|
52
|
+
getConnectionState: vi.fn(),
|
|
53
|
+
getAuthState: getAuthStateSpy,
|
|
54
|
+
updateConnectionState: updateConnectionStateSpy,
|
|
55
|
+
updateAuthState: updateAuthStateSpy,
|
|
56
|
+
sendMessage: vi.fn(),
|
|
57
|
+
roomManagementManager: mockRoomManagementManager
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Create handler instance
|
|
61
|
+
handler = new AuthSuccessHandler();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("Room Extraction", () => {
|
|
65
|
+
it("should extract rooms from auth success message", async () => {
|
|
66
|
+
const rooms: RoomInfo[] = [
|
|
67
|
+
{
|
|
68
|
+
id: "room-1",
|
|
69
|
+
name: "My Room",
|
|
70
|
+
is_owner: true
|
|
71
|
+
} as RoomInfo,
|
|
72
|
+
{
|
|
73
|
+
id: "room-2",
|
|
74
|
+
name: "Shared Room",
|
|
75
|
+
is_owner: false
|
|
76
|
+
} as RoomInfo
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
const message: AuthSuccessMessage = {
|
|
80
|
+
type: "auth_success",
|
|
81
|
+
data: {
|
|
82
|
+
id: "client-123",
|
|
83
|
+
type: "user",
|
|
84
|
+
address: "0xabc...",
|
|
85
|
+
rooms
|
|
86
|
+
}
|
|
87
|
+
} as AuthSuccessMessage;
|
|
88
|
+
|
|
89
|
+
await handler.handle(message, mockContext);
|
|
90
|
+
|
|
91
|
+
// Should update auth state with room data
|
|
92
|
+
expect(updateAuthStateSpy).toHaveBeenCalledWith(
|
|
93
|
+
expect.objectContaining({
|
|
94
|
+
roomObjects: rooms
|
|
95
|
+
})
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("should handle missing rooms array", async () => {
|
|
100
|
+
const message: AuthSuccessMessage = {
|
|
101
|
+
type: "auth_success",
|
|
102
|
+
data: {
|
|
103
|
+
id: "client-123",
|
|
104
|
+
type: "user",
|
|
105
|
+
address: "0xabc..."
|
|
106
|
+
// rooms field is undefined
|
|
107
|
+
}
|
|
108
|
+
} as AuthSuccessMessage;
|
|
109
|
+
|
|
110
|
+
await handler.handle(message, mockContext);
|
|
111
|
+
|
|
112
|
+
// Should still work with empty array
|
|
113
|
+
expect(updateAuthStateSpy).toHaveBeenCalledWith(
|
|
114
|
+
expect.objectContaining({
|
|
115
|
+
roomObjects: [],
|
|
116
|
+
privateRoomIds: [],
|
|
117
|
+
sharedRoomIds: []
|
|
118
|
+
})
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("should handle null rooms", async () => {
|
|
123
|
+
const message: AuthSuccessMessage = {
|
|
124
|
+
type: "auth_success",
|
|
125
|
+
data: {
|
|
126
|
+
id: "client-123",
|
|
127
|
+
type: "user",
|
|
128
|
+
address: "0xabc...",
|
|
129
|
+
rooms: null as any
|
|
130
|
+
}
|
|
131
|
+
} as AuthSuccessMessage;
|
|
132
|
+
|
|
133
|
+
await handler.handle(message, mockContext);
|
|
134
|
+
|
|
135
|
+
expect(updateAuthStateSpy).toHaveBeenCalledWith(
|
|
136
|
+
expect.objectContaining({
|
|
137
|
+
roomObjects: []
|
|
138
|
+
})
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("should handle empty rooms array", async () => {
|
|
143
|
+
const message: AuthSuccessMessage = {
|
|
144
|
+
type: "auth_success",
|
|
145
|
+
data: {
|
|
146
|
+
id: "client-123",
|
|
147
|
+
type: "user",
|
|
148
|
+
address: "0xabc...",
|
|
149
|
+
rooms: []
|
|
150
|
+
}
|
|
151
|
+
} as AuthSuccessMessage;
|
|
152
|
+
|
|
153
|
+
await handler.handle(message, mockContext);
|
|
154
|
+
|
|
155
|
+
expect(updateAuthStateSpy).toHaveBeenCalledWith(
|
|
156
|
+
expect.objectContaining({
|
|
157
|
+
roomObjects: [],
|
|
158
|
+
privateRoomIds: [],
|
|
159
|
+
sharedRoomIds: []
|
|
160
|
+
})
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe("Room Categorization", () => {
|
|
166
|
+
it("should categorize owned rooms (is_owner: true)", async () => {
|
|
167
|
+
const rooms: RoomInfo[] = [
|
|
168
|
+
{
|
|
169
|
+
id: "room-1",
|
|
170
|
+
name: "My Room 1",
|
|
171
|
+
is_owner: true
|
|
172
|
+
} as RoomInfo,
|
|
173
|
+
{
|
|
174
|
+
id: "room-2",
|
|
175
|
+
name: "My Room 2",
|
|
176
|
+
is_owner: true
|
|
177
|
+
} as RoomInfo
|
|
178
|
+
];
|
|
179
|
+
|
|
180
|
+
const message: AuthSuccessMessage = {
|
|
181
|
+
type: "auth_success",
|
|
182
|
+
data: {
|
|
183
|
+
id: "client-123",
|
|
184
|
+
type: "user",
|
|
185
|
+
address: "0xabc...",
|
|
186
|
+
rooms
|
|
187
|
+
}
|
|
188
|
+
} as AuthSuccessMessage;
|
|
189
|
+
|
|
190
|
+
await handler.handle(message, mockContext);
|
|
191
|
+
|
|
192
|
+
expect(updateAuthStateSpy).toHaveBeenCalledWith(
|
|
193
|
+
expect.objectContaining({
|
|
194
|
+
privateRoomIds: ["room-1", "room-2"],
|
|
195
|
+
sharedRoomIds: []
|
|
196
|
+
})
|
|
197
|
+
);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("should categorize shared rooms (is_owner: false)", async () => {
|
|
201
|
+
const rooms: RoomInfo[] = [
|
|
202
|
+
{
|
|
203
|
+
id: "room-3",
|
|
204
|
+
name: "Shared Room 1",
|
|
205
|
+
is_owner: false
|
|
206
|
+
} as RoomInfo,
|
|
207
|
+
{
|
|
208
|
+
id: "room-4",
|
|
209
|
+
name: "Shared Room 2",
|
|
210
|
+
is_owner: false
|
|
211
|
+
} as RoomInfo
|
|
212
|
+
];
|
|
213
|
+
|
|
214
|
+
const message: AuthSuccessMessage = {
|
|
215
|
+
type: "auth_success",
|
|
216
|
+
data: {
|
|
217
|
+
id: "client-123",
|
|
218
|
+
type: "user",
|
|
219
|
+
address: "0xabc...",
|
|
220
|
+
rooms
|
|
221
|
+
}
|
|
222
|
+
} as AuthSuccessMessage;
|
|
223
|
+
|
|
224
|
+
await handler.handle(message, mockContext);
|
|
225
|
+
|
|
226
|
+
expect(updateAuthStateSpy).toHaveBeenCalledWith(
|
|
227
|
+
expect.objectContaining({
|
|
228
|
+
privateRoomIds: [],
|
|
229
|
+
sharedRoomIds: ["room-3", "room-4"]
|
|
230
|
+
})
|
|
231
|
+
);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("should categorize mixed owned and shared rooms", async () => {
|
|
235
|
+
const rooms: RoomInfo[] = [
|
|
236
|
+
{
|
|
237
|
+
id: "room-1",
|
|
238
|
+
name: "My Room",
|
|
239
|
+
is_owner: true
|
|
240
|
+
} as RoomInfo,
|
|
241
|
+
{
|
|
242
|
+
id: "room-2",
|
|
243
|
+
name: "Shared Room",
|
|
244
|
+
is_owner: false
|
|
245
|
+
} as RoomInfo,
|
|
246
|
+
{
|
|
247
|
+
id: "room-3",
|
|
248
|
+
name: "Another Owned",
|
|
249
|
+
is_owner: true
|
|
250
|
+
} as RoomInfo,
|
|
251
|
+
{
|
|
252
|
+
id: "room-4",
|
|
253
|
+
name: "Another Shared",
|
|
254
|
+
is_owner: false
|
|
255
|
+
} as RoomInfo
|
|
256
|
+
];
|
|
257
|
+
|
|
258
|
+
const message: AuthSuccessMessage = {
|
|
259
|
+
type: "auth_success",
|
|
260
|
+
data: {
|
|
261
|
+
id: "client-123",
|
|
262
|
+
type: "user",
|
|
263
|
+
address: "0xabc...",
|
|
264
|
+
rooms
|
|
265
|
+
}
|
|
266
|
+
} as AuthSuccessMessage;
|
|
267
|
+
|
|
268
|
+
await handler.handle(message, mockContext);
|
|
269
|
+
|
|
270
|
+
expect(updateAuthStateSpy).toHaveBeenCalledWith(
|
|
271
|
+
expect.objectContaining({
|
|
272
|
+
privateRoomIds: ["room-1", "room-3"],
|
|
273
|
+
sharedRoomIds: ["room-2", "room-4"]
|
|
274
|
+
})
|
|
275
|
+
);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it("should handle rooms with missing is_owner flag", async () => {
|
|
279
|
+
const rooms: RoomInfo[] = [
|
|
280
|
+
{
|
|
281
|
+
id: "room-1",
|
|
282
|
+
name: "Room without flag"
|
|
283
|
+
// is_owner is undefined
|
|
284
|
+
} as RoomInfo
|
|
285
|
+
];
|
|
286
|
+
|
|
287
|
+
const message: AuthSuccessMessage = {
|
|
288
|
+
type: "auth_success",
|
|
289
|
+
data: {
|
|
290
|
+
id: "client-123",
|
|
291
|
+
type: "user",
|
|
292
|
+
address: "0xabc...",
|
|
293
|
+
rooms
|
|
294
|
+
}
|
|
295
|
+
} as AuthSuccessMessage;
|
|
296
|
+
|
|
297
|
+
await handler.handle(message, mockContext);
|
|
298
|
+
|
|
299
|
+
// Undefined is_owner should be treated as falsy (shared room)
|
|
300
|
+
expect(updateAuthStateSpy).toHaveBeenCalledWith(
|
|
301
|
+
expect.objectContaining({
|
|
302
|
+
privateRoomIds: [],
|
|
303
|
+
sharedRoomIds: ["room-1"]
|
|
304
|
+
})
|
|
305
|
+
);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
describe("Room Management Manager Initialization", () => {
|
|
310
|
+
it("should initialize room management manager with room limit", async () => {
|
|
311
|
+
const message: AuthSuccessMessage = {
|
|
312
|
+
type: "auth_success",
|
|
313
|
+
data: {
|
|
314
|
+
id: "client-123",
|
|
315
|
+
type: "user",
|
|
316
|
+
address: "0xabc...",
|
|
317
|
+
rooms: [],
|
|
318
|
+
max_private_rooms: 5
|
|
319
|
+
}
|
|
320
|
+
} as AuthSuccessMessage;
|
|
321
|
+
|
|
322
|
+
await handler.handle(message, mockContext);
|
|
323
|
+
|
|
324
|
+
expect(mockRoomManagementManager.setRoomLimit).toHaveBeenCalledWith(5);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it("should initialize with owned rooms", async () => {
|
|
328
|
+
const ownedRooms: RoomInfo[] = [
|
|
329
|
+
{
|
|
330
|
+
id: "room-1",
|
|
331
|
+
name: "My Room 1",
|
|
332
|
+
is_owner: true
|
|
333
|
+
} as RoomInfo,
|
|
334
|
+
{
|
|
335
|
+
id: "room-2",
|
|
336
|
+
name: "My Room 2",
|
|
337
|
+
is_owner: true
|
|
338
|
+
} as RoomInfo
|
|
339
|
+
];
|
|
340
|
+
|
|
341
|
+
const message: AuthSuccessMessage = {
|
|
342
|
+
type: "auth_success",
|
|
343
|
+
data: {
|
|
344
|
+
id: "client-123",
|
|
345
|
+
type: "user",
|
|
346
|
+
address: "0xabc...",
|
|
347
|
+
rooms: ownedRooms
|
|
348
|
+
}
|
|
349
|
+
} as AuthSuccessMessage;
|
|
350
|
+
|
|
351
|
+
await handler.handle(message, mockContext);
|
|
352
|
+
|
|
353
|
+
expect(mockRoomManagementManager.setOwnedRooms).toHaveBeenCalledWith(ownedRooms);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it("should initialize with shared rooms", async () => {
|
|
357
|
+
const sharedRooms: RoomInfo[] = [
|
|
358
|
+
{
|
|
359
|
+
id: "room-3",
|
|
360
|
+
name: "Shared Room 1",
|
|
361
|
+
is_owner: false
|
|
362
|
+
} as RoomInfo,
|
|
363
|
+
{
|
|
364
|
+
id: "room-4",
|
|
365
|
+
name: "Shared Room 2",
|
|
366
|
+
is_owner: false
|
|
367
|
+
} as RoomInfo
|
|
368
|
+
];
|
|
369
|
+
|
|
370
|
+
const message: AuthSuccessMessage = {
|
|
371
|
+
type: "auth_success",
|
|
372
|
+
data: {
|
|
373
|
+
id: "client-123",
|
|
374
|
+
type: "user",
|
|
375
|
+
address: "0xabc...",
|
|
376
|
+
rooms: sharedRooms
|
|
377
|
+
}
|
|
378
|
+
} as AuthSuccessMessage;
|
|
379
|
+
|
|
380
|
+
await handler.handle(message, mockContext);
|
|
381
|
+
|
|
382
|
+
expect(mockRoomManagementManager.setSharedRooms).toHaveBeenCalledWith(sharedRooms);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
it("should initialize with mixed rooms", async () => {
|
|
386
|
+
const rooms: RoomInfo[] = [
|
|
387
|
+
{
|
|
388
|
+
id: "room-1",
|
|
389
|
+
name: "My Room",
|
|
390
|
+
is_owner: true
|
|
391
|
+
} as RoomInfo,
|
|
392
|
+
{
|
|
393
|
+
id: "room-2",
|
|
394
|
+
name: "Shared Room",
|
|
395
|
+
is_owner: false
|
|
396
|
+
} as RoomInfo,
|
|
397
|
+
{
|
|
398
|
+
id: "room-3",
|
|
399
|
+
name: "Another Owned",
|
|
400
|
+
is_owner: true
|
|
401
|
+
} as RoomInfo
|
|
402
|
+
];
|
|
403
|
+
|
|
404
|
+
const message: AuthSuccessMessage = {
|
|
405
|
+
type: "auth_success",
|
|
406
|
+
data: {
|
|
407
|
+
id: "client-123",
|
|
408
|
+
type: "user",
|
|
409
|
+
address: "0xabc...",
|
|
410
|
+
rooms,
|
|
411
|
+
max_private_rooms: 3
|
|
412
|
+
}
|
|
413
|
+
} as AuthSuccessMessage;
|
|
414
|
+
|
|
415
|
+
await handler.handle(message, mockContext);
|
|
416
|
+
|
|
417
|
+
const ownedRooms = rooms.filter((r) => r.is_owner);
|
|
418
|
+
const sharedRooms = rooms.filter((r) => !r.is_owner);
|
|
419
|
+
|
|
420
|
+
expect(mockRoomManagementManager.setRoomLimit).toHaveBeenCalledWith(3);
|
|
421
|
+
expect(mockRoomManagementManager.setOwnedRooms).toHaveBeenCalledWith(ownedRooms);
|
|
422
|
+
expect(mockRoomManagementManager.setSharedRooms).toHaveBeenCalledWith(sharedRooms);
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
it("should log debug info after initialization", async () => {
|
|
426
|
+
const rooms: RoomInfo[] = [
|
|
427
|
+
{ id: "room-1", name: "Owned", is_owner: true } as RoomInfo,
|
|
428
|
+
{ id: "room-2", name: "Shared", is_owner: false } as RoomInfo
|
|
429
|
+
];
|
|
430
|
+
|
|
431
|
+
const message: AuthSuccessMessage = {
|
|
432
|
+
type: "auth_success",
|
|
433
|
+
data: {
|
|
434
|
+
id: "client-123",
|
|
435
|
+
type: "user",
|
|
436
|
+
address: "0xabc...",
|
|
437
|
+
rooms,
|
|
438
|
+
max_private_rooms: 5
|
|
439
|
+
}
|
|
440
|
+
} as AuthSuccessMessage;
|
|
441
|
+
|
|
442
|
+
await handler.handle(message, mockContext);
|
|
443
|
+
|
|
444
|
+
expect(mockLogger.debug).toHaveBeenCalledWith(
|
|
445
|
+
"Room management initialized",
|
|
446
|
+
expect.objectContaining({
|
|
447
|
+
owned: 1,
|
|
448
|
+
shared: 1,
|
|
449
|
+
limit: 5
|
|
450
|
+
})
|
|
451
|
+
);
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
it("should work without room limit", async () => {
|
|
455
|
+
const message: AuthSuccessMessage = {
|
|
456
|
+
type: "auth_success",
|
|
457
|
+
data: {
|
|
458
|
+
id: "client-123",
|
|
459
|
+
type: "user",
|
|
460
|
+
address: "0xabc...",
|
|
461
|
+
rooms: []
|
|
462
|
+
// max_private_rooms is undefined
|
|
463
|
+
}
|
|
464
|
+
} as AuthSuccessMessage;
|
|
465
|
+
|
|
466
|
+
await handler.handle(message, mockContext);
|
|
467
|
+
|
|
468
|
+
// Should not call setRoomLimit
|
|
469
|
+
expect(mockRoomManagementManager.setRoomLimit).not.toHaveBeenCalled();
|
|
470
|
+
|
|
471
|
+
// Should still initialize room lists
|
|
472
|
+
expect(mockRoomManagementManager.setOwnedRooms).toHaveBeenCalledWith([]);
|
|
473
|
+
expect(mockRoomManagementManager.setSharedRooms).toHaveBeenCalledWith([]);
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
describe("Backward Compatibility", () => {
|
|
478
|
+
it("should include deprecated fields in auth state", async () => {
|
|
479
|
+
const rooms: RoomInfo[] = [
|
|
480
|
+
{ id: "room-1", name: "Room 1", is_owner: true } as RoomInfo,
|
|
481
|
+
{ id: "room-2", name: "Room 2", is_owner: false } as RoomInfo
|
|
482
|
+
];
|
|
483
|
+
|
|
484
|
+
const message: AuthSuccessMessage = {
|
|
485
|
+
type: "auth_success",
|
|
486
|
+
data: {
|
|
487
|
+
id: "client-123",
|
|
488
|
+
type: "user",
|
|
489
|
+
address: "0xabc...",
|
|
490
|
+
rooms,
|
|
491
|
+
private_room_id: "room-1" // DEPRECATED field
|
|
492
|
+
}
|
|
493
|
+
} as AuthSuccessMessage;
|
|
494
|
+
|
|
495
|
+
await handler.handle(message, mockContext);
|
|
496
|
+
|
|
497
|
+
expect(updateAuthStateSpy).toHaveBeenCalledWith(
|
|
498
|
+
expect.objectContaining({
|
|
499
|
+
rooms: ["room-1", "room-2"], // DEPRECATED: flat list of IDs
|
|
500
|
+
privateRoomId: "room-1" // DEPRECATED: single ID
|
|
501
|
+
})
|
|
502
|
+
);
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
it("should include new v2.0 fields in auth state", async () => {
|
|
506
|
+
const rooms: RoomInfo[] = [
|
|
507
|
+
{ id: "room-1", name: "Room 1", is_owner: true } as RoomInfo,
|
|
508
|
+
{ id: "room-2", name: "Room 2", is_owner: false } as RoomInfo
|
|
509
|
+
];
|
|
510
|
+
|
|
511
|
+
const message: AuthSuccessMessage = {
|
|
512
|
+
type: "auth_success",
|
|
513
|
+
data: {
|
|
514
|
+
id: "client-123",
|
|
515
|
+
type: "user",
|
|
516
|
+
address: "0xabc...",
|
|
517
|
+
rooms,
|
|
518
|
+
max_private_rooms: 3
|
|
519
|
+
}
|
|
520
|
+
} as AuthSuccessMessage;
|
|
521
|
+
|
|
522
|
+
await handler.handle(message, mockContext);
|
|
523
|
+
|
|
524
|
+
expect(updateAuthStateSpy).toHaveBeenCalledWith(
|
|
525
|
+
expect.objectContaining({
|
|
526
|
+
roomObjects: rooms, // v2.0: Full objects
|
|
527
|
+
privateRoomIds: ["room-1"], // v2.0: Owned room IDs
|
|
528
|
+
sharedRoomIds: ["room-2"], // v2.0: Shared room IDs
|
|
529
|
+
maxPrivateRooms: 3 // v2.0: Room limit
|
|
530
|
+
})
|
|
531
|
+
);
|
|
532
|
+
});
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
describe("Without Room Management Manager", () => {
|
|
536
|
+
it("should work without roomManagementManager in context", async () => {
|
|
537
|
+
const contextWithoutManager = { ...mockContext, roomManagementManager: undefined };
|
|
538
|
+
|
|
539
|
+
const message: AuthSuccessMessage = {
|
|
540
|
+
type: "auth_success",
|
|
541
|
+
data: {
|
|
542
|
+
id: "client-123",
|
|
543
|
+
type: "user",
|
|
544
|
+
address: "0xabc...",
|
|
545
|
+
rooms: [
|
|
546
|
+
{ id: "room-1", name: "Room", is_owner: true } as RoomInfo
|
|
547
|
+
],
|
|
548
|
+
max_private_rooms: 3
|
|
549
|
+
}
|
|
550
|
+
} as AuthSuccessMessage;
|
|
551
|
+
|
|
552
|
+
// Should not throw
|
|
553
|
+
await handler.handle(message, contextWithoutManager);
|
|
554
|
+
|
|
555
|
+
// Should still update auth state
|
|
556
|
+
expect(updateAuthStateSpy).toHaveBeenCalledWith(
|
|
557
|
+
expect.objectContaining({
|
|
558
|
+
roomObjects: expect.any(Array),
|
|
559
|
+
maxPrivateRooms: 3
|
|
560
|
+
})
|
|
561
|
+
);
|
|
562
|
+
|
|
563
|
+
// Should still emit events
|
|
564
|
+
expect(emitSpy).toHaveBeenCalledWith("auth:success", expect.anything());
|
|
565
|
+
expect(emitSpy).toHaveBeenCalledWith("ready");
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
it("should handle null roomManagementManager", async () => {
|
|
569
|
+
const contextWithNullManager = { ...mockContext, roomManagementManager: null };
|
|
570
|
+
|
|
571
|
+
const message: AuthSuccessMessage = {
|
|
572
|
+
type: "auth_success",
|
|
573
|
+
data: {
|
|
574
|
+
id: "client-123",
|
|
575
|
+
type: "user",
|
|
576
|
+
address: "0xabc...",
|
|
577
|
+
rooms: []
|
|
578
|
+
}
|
|
579
|
+
} as AuthSuccessMessage;
|
|
580
|
+
|
|
581
|
+
// Should not throw
|
|
582
|
+
await handler.handle(message, contextWithNullManager);
|
|
583
|
+
|
|
584
|
+
expect(emitSpy).toHaveBeenCalledWith("ready");
|
|
585
|
+
});
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
describe("Event Emission", () => {
|
|
589
|
+
it("should emit auth:success event with auth state", async () => {
|
|
590
|
+
const message: AuthSuccessMessage = {
|
|
591
|
+
type: "auth_success",
|
|
592
|
+
data: {
|
|
593
|
+
id: "client-123",
|
|
594
|
+
type: "user",
|
|
595
|
+
address: "0xabc..."
|
|
596
|
+
}
|
|
597
|
+
} as AuthSuccessMessage;
|
|
598
|
+
|
|
599
|
+
const mockAuthState = {
|
|
600
|
+
authenticated: true,
|
|
601
|
+
clientId: "client-123",
|
|
602
|
+
walletAddress: "0xabc..."
|
|
603
|
+
};
|
|
604
|
+
getAuthStateSpy.mockReturnValue(mockAuthState);
|
|
605
|
+
|
|
606
|
+
await handler.handle(message, mockContext);
|
|
607
|
+
|
|
608
|
+
expect(emitSpy).toHaveBeenCalledWith("auth:success", mockAuthState);
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
it("should emit ready event after auth:success", async () => {
|
|
612
|
+
const message: AuthSuccessMessage = {
|
|
613
|
+
type: "auth_success",
|
|
614
|
+
data: {
|
|
615
|
+
id: "client-123",
|
|
616
|
+
type: "user",
|
|
617
|
+
address: "0xabc..."
|
|
618
|
+
}
|
|
619
|
+
} as AuthSuccessMessage;
|
|
620
|
+
|
|
621
|
+
await handler.handle(message, mockContext);
|
|
622
|
+
|
|
623
|
+
// Check that ready was emitted
|
|
624
|
+
expect(emitSpy).toHaveBeenCalledWith("ready");
|
|
625
|
+
|
|
626
|
+
// Check order: auth:success before ready
|
|
627
|
+
const calls = emitSpy.mock.calls;
|
|
628
|
+
const authSuccessIndex = calls.findIndex((call) => call[0] === "auth:success");
|
|
629
|
+
const readyIndex = calls.findIndex((call) => call[0] === "ready");
|
|
630
|
+
|
|
631
|
+
expect(authSuccessIndex).toBeGreaterThanOrEqual(0);
|
|
632
|
+
expect(readyIndex).toBeGreaterThan(authSuccessIndex);
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
it("should log authentication success", async () => {
|
|
636
|
+
const message: AuthSuccessMessage = {
|
|
637
|
+
type: "auth_success",
|
|
638
|
+
data: {
|
|
639
|
+
id: "client-123",
|
|
640
|
+
type: "user",
|
|
641
|
+
address: "0xabc..."
|
|
642
|
+
}
|
|
643
|
+
} as AuthSuccessMessage;
|
|
644
|
+
|
|
645
|
+
await handler.handle(message, mockContext);
|
|
646
|
+
|
|
647
|
+
expect(mockLogger.info).toHaveBeenCalledWith("Authentication successful");
|
|
648
|
+
});
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
describe("State Updates", () => {
|
|
652
|
+
it("should update connection state to authenticated", async () => {
|
|
653
|
+
const message: AuthSuccessMessage = {
|
|
654
|
+
type: "auth_success",
|
|
655
|
+
data: {
|
|
656
|
+
id: "client-123",
|
|
657
|
+
type: "user",
|
|
658
|
+
address: "0xabc..."
|
|
659
|
+
}
|
|
660
|
+
} as AuthSuccessMessage;
|
|
661
|
+
|
|
662
|
+
await handler.handle(message, mockContext);
|
|
663
|
+
|
|
664
|
+
expect(updateConnectionStateSpy).toHaveBeenCalledWith(
|
|
665
|
+
expect.objectContaining({
|
|
666
|
+
authenticated: true
|
|
667
|
+
})
|
|
668
|
+
);
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
it("should update auth state with all user data", async () => {
|
|
672
|
+
const message: AuthSuccessMessage = {
|
|
673
|
+
type: "auth_success",
|
|
674
|
+
data: {
|
|
675
|
+
id: "client-123",
|
|
676
|
+
type: "user",
|
|
677
|
+
address: "0xabc...",
|
|
678
|
+
is_whitelisted: true,
|
|
679
|
+
is_admin_whitelisted: false,
|
|
680
|
+
nft_verified: true,
|
|
681
|
+
rooms: []
|
|
682
|
+
}
|
|
683
|
+
} as AuthSuccessMessage;
|
|
684
|
+
|
|
685
|
+
await handler.handle(message, mockContext);
|
|
686
|
+
|
|
687
|
+
expect(updateAuthStateSpy).toHaveBeenCalledWith(
|
|
688
|
+
expect.objectContaining({
|
|
689
|
+
authenticated: true,
|
|
690
|
+
clientId: "client-123",
|
|
691
|
+
walletAddress: "0xabc...",
|
|
692
|
+
isWhitelisted: true,
|
|
693
|
+
isAdmin: false,
|
|
694
|
+
nftVerified: true
|
|
695
|
+
})
|
|
696
|
+
);
|
|
697
|
+
});
|
|
698
|
+
});
|
|
699
|
+
});
|