@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,438 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for RoomManagementManager
|
|
3
|
+
* Tests room CRUD operations, validation, caching, and error handling
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
7
|
+
import { RoomManagementManager } from "../../../src/managers/room-management-manager";
|
|
8
|
+
import { WebSocketClient } from "../../../src/core/websocket-client";
|
|
9
|
+
import { Logger, RoomInfo } from "../../../src/types";
|
|
10
|
+
import { ErrorCode } from "../../../src/types/error-codes";
|
|
11
|
+
|
|
12
|
+
describe("RoomManagementManager", () => {
|
|
13
|
+
let manager: RoomManagementManager;
|
|
14
|
+
let mockWsClient: WebSocketClient;
|
|
15
|
+
let mockLogger: Logger;
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
// Create mock logger
|
|
19
|
+
mockLogger = {
|
|
20
|
+
debug: vi.fn(),
|
|
21
|
+
info: vi.fn(),
|
|
22
|
+
warn: vi.fn(),
|
|
23
|
+
error: vi.fn()
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Create mock WebSocket client
|
|
27
|
+
mockWsClient = {
|
|
28
|
+
isConnected: true,
|
|
29
|
+
sendMessage: vi.fn().mockResolvedValue(undefined)
|
|
30
|
+
} as any;
|
|
31
|
+
|
|
32
|
+
// Create manager instance
|
|
33
|
+
manager = new RoomManagementManager(mockWsClient, mockLogger);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe("createRoom", () => {
|
|
37
|
+
it("should create a room successfully", async () => {
|
|
38
|
+
const roomOptions = {
|
|
39
|
+
name: "Test Room",
|
|
40
|
+
description: "Test Description"
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const createdRoom: RoomInfo = {
|
|
44
|
+
id: "room-123",
|
|
45
|
+
name: roomOptions.name,
|
|
46
|
+
description: roomOptions.description,
|
|
47
|
+
is_public: false,
|
|
48
|
+
created_by: "user-123",
|
|
49
|
+
created_at: new Date().toISOString(),
|
|
50
|
+
updated_at: new Date().toISOString(),
|
|
51
|
+
is_owner: true
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Start create operation
|
|
55
|
+
const createPromise = manager.createRoom(roomOptions);
|
|
56
|
+
|
|
57
|
+
// Simulate server response
|
|
58
|
+
setTimeout(() => {
|
|
59
|
+
manager.emit("room:created", createdRoom);
|
|
60
|
+
}, 10);
|
|
61
|
+
|
|
62
|
+
const result = await createPromise;
|
|
63
|
+
|
|
64
|
+
expect(result).toEqual(createdRoom);
|
|
65
|
+
expect(mockWsClient.sendMessage).toHaveBeenCalledWith({
|
|
66
|
+
type: "create_room",
|
|
67
|
+
data: {
|
|
68
|
+
name: roomOptions.name,
|
|
69
|
+
description: roomOptions.description
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("should reject if not connected", async () => {
|
|
75
|
+
mockWsClient.isConnected = false;
|
|
76
|
+
|
|
77
|
+
await expect(
|
|
78
|
+
manager.createRoom({ name: "Test Room" })
|
|
79
|
+
).rejects.toThrow("Not connected to Teneo network");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should validate room name", async () => {
|
|
83
|
+
await expect(manager.createRoom({ name: "" })).rejects.toThrow("Room name cannot be empty");
|
|
84
|
+
|
|
85
|
+
await expect(
|
|
86
|
+
manager.createRoom({ name: "a".repeat(101) })
|
|
87
|
+
).rejects.toThrow("Room name too long");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("should validate room description", async () => {
|
|
91
|
+
await expect(
|
|
92
|
+
manager.createRoom({
|
|
93
|
+
name: "Test",
|
|
94
|
+
description: "a".repeat(501)
|
|
95
|
+
})
|
|
96
|
+
).rejects.toThrow("Room description too long");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("should check room limit before creating private room", async () => {
|
|
100
|
+
manager.setRoomLimit(1);
|
|
101
|
+
manager.setOwnedRooms([
|
|
102
|
+
{
|
|
103
|
+
id: "room-1",
|
|
104
|
+
name: "Existing Room",
|
|
105
|
+
is_owner: true
|
|
106
|
+
} as RoomInfo
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
await expect(
|
|
110
|
+
manager.createRoom({ name: "New Room" })
|
|
111
|
+
).rejects.toThrow("Room limit reached");
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("should timeout if no response", async () => {
|
|
115
|
+
vi.useFakeTimers();
|
|
116
|
+
|
|
117
|
+
const createPromise = manager.createRoom({ name: "Test Room" });
|
|
118
|
+
|
|
119
|
+
vi.advanceTimersByTime(30001);
|
|
120
|
+
|
|
121
|
+
await expect(createPromise).rejects.toThrow("timeout");
|
|
122
|
+
|
|
123
|
+
vi.useRealTimers();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("should handle create errors", async () => {
|
|
127
|
+
const createPromise = manager.createRoom({ name: "Test Room" });
|
|
128
|
+
|
|
129
|
+
setTimeout(() => {
|
|
130
|
+
manager.emit("room:create_error", new Error("Server error"));
|
|
131
|
+
}, 10);
|
|
132
|
+
|
|
133
|
+
await expect(createPromise).rejects.toThrow("Server error");
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe("updateRoom", () => {
|
|
138
|
+
beforeEach(() => {
|
|
139
|
+
manager.setOwnedRooms([
|
|
140
|
+
{
|
|
141
|
+
id: "room-123",
|
|
142
|
+
name: "Original Room",
|
|
143
|
+
is_owner: true
|
|
144
|
+
} as RoomInfo
|
|
145
|
+
]);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("should update a room successfully", async () => {
|
|
149
|
+
const updates = {
|
|
150
|
+
name: "Updated Room",
|
|
151
|
+
description: "Updated Description"
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const updatedRoom: RoomInfo = {
|
|
155
|
+
id: "room-123",
|
|
156
|
+
name: updates.name,
|
|
157
|
+
description: updates.description,
|
|
158
|
+
is_owner: true
|
|
159
|
+
} as RoomInfo;
|
|
160
|
+
|
|
161
|
+
const updatePromise = manager.updateRoom("room-123", updates);
|
|
162
|
+
|
|
163
|
+
setTimeout(() => {
|
|
164
|
+
manager.emit("room:updated", updatedRoom);
|
|
165
|
+
}, 10);
|
|
166
|
+
|
|
167
|
+
const result = await updatePromise;
|
|
168
|
+
|
|
169
|
+
expect(result).toEqual(updatedRoom);
|
|
170
|
+
expect(mockWsClient.sendMessage).toHaveBeenCalledWith({
|
|
171
|
+
type: "update_room",
|
|
172
|
+
data: {
|
|
173
|
+
room_id: "room-123",
|
|
174
|
+
name: updates.name,
|
|
175
|
+
description: updates.description
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("should reject if user doesn't own room", async () => {
|
|
181
|
+
await expect(
|
|
182
|
+
manager.updateRoom("room-999", { name: "New Name" })
|
|
183
|
+
).rejects.toThrow("don't own this room");
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("should require at least one field", async () => {
|
|
187
|
+
await expect(manager.updateRoom("room-123", {})).rejects.toThrow(
|
|
188
|
+
"At least one field"
|
|
189
|
+
);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("should validate updated name", async () => {
|
|
193
|
+
await expect(
|
|
194
|
+
manager.updateRoom("room-123", { name: "" })
|
|
195
|
+
).rejects.toThrow("Room name cannot be empty");
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it("should validate updated description", async () => {
|
|
199
|
+
await expect(
|
|
200
|
+
manager.updateRoom("room-123", { description: "a".repeat(501) })
|
|
201
|
+
).rejects.toThrow("Room description too long");
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
describe("deleteRoom", () => {
|
|
206
|
+
beforeEach(() => {
|
|
207
|
+
manager.setOwnedRooms([
|
|
208
|
+
{
|
|
209
|
+
id: "room-123",
|
|
210
|
+
name: "Room to Delete",
|
|
211
|
+
is_owner: true
|
|
212
|
+
} as RoomInfo
|
|
213
|
+
]);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it("should delete a room successfully", async () => {
|
|
217
|
+
const deletePromise = manager.deleteRoom("room-123");
|
|
218
|
+
|
|
219
|
+
setTimeout(() => {
|
|
220
|
+
manager.emit("room:deleted", "room-123");
|
|
221
|
+
}, 10);
|
|
222
|
+
|
|
223
|
+
await expect(deletePromise).resolves.toBeUndefined();
|
|
224
|
+
expect(mockWsClient.sendMessage).toHaveBeenCalledWith({
|
|
225
|
+
type: "delete_room",
|
|
226
|
+
data: {
|
|
227
|
+
room_id: "room-123"
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("should reject if user doesn't own room", async () => {
|
|
233
|
+
await expect(manager.deleteRoom("room-999")).rejects.toThrow("don't own this room");
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it("should handle delete errors", async () => {
|
|
237
|
+
const deletePromise = manager.deleteRoom("room-123");
|
|
238
|
+
|
|
239
|
+
setTimeout(() => {
|
|
240
|
+
manager.emit("room:delete_error", new Error("Cannot delete"), "room-123");
|
|
241
|
+
}, 10);
|
|
242
|
+
|
|
243
|
+
await expect(deletePromise).rejects.toThrow("Cannot delete");
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
describe("Query Methods", () => {
|
|
248
|
+
it("should return owned rooms", () => {
|
|
249
|
+
const ownedRooms: RoomInfo[] = [
|
|
250
|
+
{ id: "room-1", name: "Room 1", is_owner: true } as RoomInfo,
|
|
251
|
+
{ id: "room-2", name: "Room 2", is_owner: true } as RoomInfo
|
|
252
|
+
];
|
|
253
|
+
|
|
254
|
+
manager.setOwnedRooms(ownedRooms);
|
|
255
|
+
|
|
256
|
+
const result = manager.getOwnedRooms();
|
|
257
|
+
expect(result).toHaveLength(2);
|
|
258
|
+
expect(result[0].id).toBe("room-1");
|
|
259
|
+
expect(result[1].id).toBe("room-2");
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("should return shared rooms", () => {
|
|
263
|
+
const sharedRooms: RoomInfo[] = [
|
|
264
|
+
{ id: "room-3", name: "Shared 1", is_owner: false } as RoomInfo,
|
|
265
|
+
{ id: "room-4", name: "Shared 2", is_owner: false } as RoomInfo
|
|
266
|
+
];
|
|
267
|
+
|
|
268
|
+
manager.setSharedRooms(sharedRooms);
|
|
269
|
+
|
|
270
|
+
const result = manager.getSharedRooms();
|
|
271
|
+
expect(result).toHaveLength(2);
|
|
272
|
+
expect(result[0].id).toBe("room-3");
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it("should get room by ID from owned rooms", () => {
|
|
276
|
+
manager.setOwnedRooms([
|
|
277
|
+
{ id: "room-1", name: "Owned Room", is_owner: true } as RoomInfo
|
|
278
|
+
]);
|
|
279
|
+
|
|
280
|
+
const result = manager.getRoomById("room-1");
|
|
281
|
+
expect(result).toBeDefined();
|
|
282
|
+
expect(result!.name).toBe("Owned Room");
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it("should get room by ID from shared rooms", () => {
|
|
286
|
+
manager.setSharedRooms([
|
|
287
|
+
{ id: "room-2", name: "Shared Room", is_owner: false } as RoomInfo
|
|
288
|
+
]);
|
|
289
|
+
|
|
290
|
+
const result = manager.getRoomById("room-2");
|
|
291
|
+
expect(result).toBeDefined();
|
|
292
|
+
expect(result!.name).toBe("Shared Room");
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it("should return undefined for non-existent room", () => {
|
|
296
|
+
const result = manager.getRoomById("room-999");
|
|
297
|
+
expect(result).toBeUndefined();
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it("should get room limit", () => {
|
|
301
|
+
manager.setRoomLimit(5);
|
|
302
|
+
expect(manager.getRoomLimit()).toBe(5);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it("should get owned room count", () => {
|
|
306
|
+
manager.setOwnedRooms([
|
|
307
|
+
{ id: "room-1", name: "Room 1", is_owner: true } as RoomInfo,
|
|
308
|
+
{ id: "room-2", name: "Room 2", is_owner: true } as RoomInfo,
|
|
309
|
+
{ id: "room-3", name: "Room 3", is_owner: true } as RoomInfo
|
|
310
|
+
]);
|
|
311
|
+
|
|
312
|
+
expect(manager.getOwnedRoomCount()).toBe(3);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it("should check if can create room", () => {
|
|
316
|
+
manager.setRoomLimit(3);
|
|
317
|
+
manager.setOwnedRooms([
|
|
318
|
+
{ id: "room-1", name: "Room 1", is_owner: true } as RoomInfo,
|
|
319
|
+
{ id: "room-2", name: "Room 2", is_owner: true } as RoomInfo
|
|
320
|
+
]);
|
|
321
|
+
|
|
322
|
+
expect(manager.canCreateRoom()).toBe(true);
|
|
323
|
+
|
|
324
|
+
manager.setOwnedRooms([
|
|
325
|
+
{ id: "room-1", name: "Room 1", is_owner: true } as RoomInfo,
|
|
326
|
+
{ id: "room-2", name: "Room 2", is_owner: true } as RoomInfo,
|
|
327
|
+
{ id: "room-3", name: "Room 3", is_owner: true } as RoomInfo
|
|
328
|
+
]);
|
|
329
|
+
|
|
330
|
+
expect(manager.canCreateRoom()).toBe(false);
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
describe("Cache Management", () => {
|
|
335
|
+
it("should upsert owned room", () => {
|
|
336
|
+
const room: RoomInfo = {
|
|
337
|
+
id: "room-1",
|
|
338
|
+
name: "New Room",
|
|
339
|
+
is_owner: true
|
|
340
|
+
} as RoomInfo;
|
|
341
|
+
|
|
342
|
+
manager.upsertRoom(room);
|
|
343
|
+
|
|
344
|
+
const result = manager.getRoomById("room-1");
|
|
345
|
+
expect(result).toBeDefined();
|
|
346
|
+
expect(result!.name).toBe("New Room");
|
|
347
|
+
expect(manager.getOwnedRoomCount()).toBe(1);
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
it("should upsert shared room", () => {
|
|
351
|
+
const room: RoomInfo = {
|
|
352
|
+
id: "room-2",
|
|
353
|
+
name: "Shared Room",
|
|
354
|
+
is_owner: false
|
|
355
|
+
} as RoomInfo;
|
|
356
|
+
|
|
357
|
+
manager.upsertRoom(room);
|
|
358
|
+
|
|
359
|
+
const result = manager.getRoomById("room-2");
|
|
360
|
+
expect(result).toBeDefined();
|
|
361
|
+
expect(result!.name).toBe("Shared Room");
|
|
362
|
+
expect(manager.getSharedRooms()).toHaveLength(1);
|
|
363
|
+
expect(manager.getOwnedRoomCount()).toBe(0);
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
it("should move room from shared to owned when ownership changes", () => {
|
|
367
|
+
const room: RoomInfo = {
|
|
368
|
+
id: "room-1",
|
|
369
|
+
name: "Room",
|
|
370
|
+
is_owner: false
|
|
371
|
+
} as RoomInfo;
|
|
372
|
+
|
|
373
|
+
manager.upsertRoom(room);
|
|
374
|
+
expect(manager.getSharedRooms()).toHaveLength(1);
|
|
375
|
+
expect(manager.getOwnedRoomCount()).toBe(0);
|
|
376
|
+
|
|
377
|
+
// Update to owned
|
|
378
|
+
room.is_owner = true;
|
|
379
|
+
manager.upsertRoom(room);
|
|
380
|
+
expect(manager.getSharedRooms()).toHaveLength(0);
|
|
381
|
+
expect(manager.getOwnedRoomCount()).toBe(1);
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it("should remove room from cache", () => {
|
|
385
|
+
manager.setOwnedRooms([
|
|
386
|
+
{ id: "room-1", name: "Room 1", is_owner: true } as RoomInfo
|
|
387
|
+
]);
|
|
388
|
+
|
|
389
|
+
expect(manager.getRoomById("room-1")).toBeDefined();
|
|
390
|
+
|
|
391
|
+
manager.removeRoom("room-1");
|
|
392
|
+
|
|
393
|
+
expect(manager.getRoomById("room-1")).toBeUndefined();
|
|
394
|
+
expect(manager.getOwnedRoomCount()).toBe(0);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
it("should clear all caches", () => {
|
|
398
|
+
manager.setRoomLimit(5);
|
|
399
|
+
manager.setOwnedRooms([
|
|
400
|
+
{ id: "room-1", name: "Room 1", is_owner: true } as RoomInfo
|
|
401
|
+
]);
|
|
402
|
+
manager.setSharedRooms([
|
|
403
|
+
{ id: "room-2", name: "Room 2", is_owner: false } as RoomInfo
|
|
404
|
+
]);
|
|
405
|
+
|
|
406
|
+
manager.clearCaches();
|
|
407
|
+
|
|
408
|
+
expect(manager.getOwnedRoomCount()).toBe(0);
|
|
409
|
+
expect(manager.getSharedRooms()).toHaveLength(0);
|
|
410
|
+
expect(manager.getRoomLimit()).toBe(1); // Reset to default
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
describe("Return Value Immutability", () => {
|
|
415
|
+
it("should return defensive copies from getOwnedRooms", () => {
|
|
416
|
+
manager.setOwnedRooms([
|
|
417
|
+
{ id: "room-1", name: "Room 1", is_owner: true } as RoomInfo
|
|
418
|
+
]);
|
|
419
|
+
|
|
420
|
+
const rooms1 = manager.getOwnedRooms();
|
|
421
|
+
const rooms2 = manager.getOwnedRooms();
|
|
422
|
+
|
|
423
|
+
expect(rooms1).not.toBe(rooms2);
|
|
424
|
+
expect(rooms1[0]).not.toBe(rooms2[0]);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it("should return defensive copy from getRoomById", () => {
|
|
428
|
+
manager.setOwnedRooms([
|
|
429
|
+
{ id: "room-1", name: "Room 1", is_owner: true } as RoomInfo
|
|
430
|
+
]);
|
|
431
|
+
|
|
432
|
+
const room1 = manager.getRoomById("room-1");
|
|
433
|
+
const room2 = manager.getRoomById("room-1");
|
|
434
|
+
|
|
435
|
+
expect(room1).not.toBe(room2);
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
});
|