@lobehub/chat 1.37.0 → 1.37.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/locales/en-US/common.json +2 -2
- package/package.json +1 -1
- package/src/services/file/_deprecated.test.ts +119 -0
- package/src/services/file/{pglite.ts → _deprecated.ts} +28 -32
- package/src/services/file/client.test.ts +153 -74
- package/src/services/file/client.ts +32 -28
- package/src/services/file/index.ts +2 -2
- package/src/services/import/_deprecated.ts +74 -0
- package/src/services/import/{pglite.test.ts → client.test.ts} +1 -1
- package/src/services/import/client.ts +21 -61
- package/src/services/import/index.ts +2 -2
- package/src/services/message/_deprecated.test.ts +398 -0
- package/src/services/message/_deprecated.ts +121 -0
- package/src/services/message/client.test.ts +191 -159
- package/src/services/message/client.ts +47 -50
- package/src/services/message/index.ts +2 -2
- package/src/services/plugin/_deprecated.test.ts +162 -0
- package/src/services/plugin/_deprecated.ts +42 -0
- package/src/services/plugin/client.test.ts +68 -55
- package/src/services/plugin/client.ts +20 -11
- package/src/services/plugin/index.ts +2 -2
- package/src/services/session/_deprecated.test.ts +440 -0
- package/src/services/session/_deprecated.ts +183 -0
- package/src/services/session/client.test.ts +212 -241
- package/src/services/session/client.ts +61 -60
- package/src/services/session/index.ts +2 -2
- package/src/services/topic/{client.test.ts → _deprecated.test.ts} +1 -1
- package/src/services/topic/_deprecated.ts +70 -0
- package/src/services/topic/client.ts +40 -25
- package/src/services/topic/index.ts +2 -2
- package/src/services/topic/pglite.test.ts +1 -1
- package/src/services/user/{pglite.test.ts → _deprecated.test.ts} +32 -29
- package/src/services/user/_deprecated.ts +57 -0
- package/src/services/user/client.test.ts +28 -31
- package/src/services/user/client.ts +51 -16
- package/src/services/user/index.ts +2 -2
- package/src/store/chat/slices/builtinTool/action.test.ts +1 -1
- package/src/store/user/slices/common/action.test.ts +1 -1
- package/src/services/file/pglite.test.ts +0 -198
- package/src/services/import/pglite.ts +0 -34
- package/src/services/message/pglite.test.ts +0 -430
- package/src/services/message/pglite.ts +0 -118
- package/src/services/plugin/pglite.test.ts +0 -175
- package/src/services/plugin/pglite.ts +0 -51
- package/src/services/session/pglite.test.ts +0 -411
- package/src/services/session/pglite.ts +0 -184
- package/src/services/topic/pglite.ts +0 -85
- package/src/services/user/pglite.ts +0 -92
@@ -1,194 +1,119 @@
|
|
1
|
+
import { eq, not } from 'drizzle-orm/expressions';
|
1
2
|
import { Mock, beforeEach, describe, expect, it, vi } from 'vitest';
|
2
3
|
|
3
|
-
import {
|
4
|
-
import {
|
5
|
-
import {
|
4
|
+
import { INBOX_SESSION_ID } from '@/const/session';
|
5
|
+
import { clientDB, initializeDB } from '@/database/client/db';
|
6
|
+
import {
|
7
|
+
NewSession,
|
8
|
+
SessionItem,
|
9
|
+
agents,
|
10
|
+
agentsToSessions,
|
11
|
+
sessionGroups,
|
12
|
+
sessions,
|
13
|
+
users,
|
14
|
+
} from '@/database/schemas';
|
15
|
+
import { LobeAgentChatConfig, LobeAgentConfig } from '@/types/agent';
|
6
16
|
import { LobeAgentSession, LobeSessionType, SessionGroups } from '@/types/session';
|
7
17
|
|
8
18
|
import { ClientService } from './client';
|
9
19
|
|
10
|
-
const
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
};
|
20
|
+
const userId = 'message-db';
|
21
|
+
const sessionService = new ClientService(userId);
|
22
|
+
|
23
|
+
const mockSessionId = 'mock-session-id';
|
24
|
+
const mockAgentId = 'agent-id';
|
25
|
+
|
26
|
+
// Mock data
|
27
|
+
beforeEach(async () => {
|
28
|
+
await initializeDB();
|
29
|
+
|
30
|
+
// 在每个测试用例之前,清空表
|
31
|
+
await clientDB.transaction(async (trx) => {
|
32
|
+
await trx.insert(users).values([{ id: userId }, { id: '456' }]);
|
33
|
+
await trx.insert(sessions).values([{ id: mockSessionId, userId }]);
|
34
|
+
await trx.insert(agents).values([{ id: mockAgentId, userId }]);
|
35
|
+
await trx.insert(agentsToSessions).values([{ agentId: mockAgentId, sessionId: mockSessionId }]);
|
36
|
+
await trx.insert(sessionGroups).values([
|
37
|
+
{ id: 'group-1', name: 'group-A', sort: 2, userId },
|
38
|
+
{ id: 'group-2', name: 'group-B', sort: 1, userId },
|
39
|
+
{ id: 'group-4', name: 'group-C', sort: 1, userId: '456' },
|
40
|
+
]);
|
41
|
+
});
|
33
42
|
});
|
34
43
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
SessionGroupModel: {
|
39
|
-
create: vi.fn(),
|
40
|
-
query: vi.fn(),
|
41
|
-
delete: vi.fn(),
|
42
|
-
clear: vi.fn(),
|
43
|
-
update: vi.fn(),
|
44
|
-
batchCreate: vi.fn(),
|
45
|
-
isEmpty: vi.fn(),
|
46
|
-
updateOrder: vi.fn(),
|
47
|
-
queryByKeyword: vi.fn(),
|
48
|
-
updateConfig: vi.fn(),
|
49
|
-
queryByGroupIds: vi.fn(),
|
50
|
-
},
|
51
|
-
};
|
44
|
+
afterEach(async () => {
|
45
|
+
// 在每个测试用例之后,清空表
|
46
|
+
await clientDB.delete(users);
|
52
47
|
});
|
53
48
|
|
54
49
|
describe('SessionService', () => {
|
55
|
-
const mockSessionId = 'mock-session-id';
|
56
50
|
const mockSession = {
|
57
51
|
id: mockSessionId,
|
58
52
|
type: 'agent',
|
59
53
|
meta: { title: 'Mock Session' },
|
60
54
|
} as LobeAgentSession;
|
61
|
-
const mockSessions = [mockSession];
|
62
|
-
|
63
|
-
beforeEach(() => {
|
64
|
-
// Reset all mocks before running each test case
|
65
|
-
vi.resetAllMocks();
|
66
|
-
});
|
67
55
|
|
68
56
|
describe('createSession', () => {
|
69
57
|
it('should create a new session and return its id', async () => {
|
70
58
|
// Setup
|
71
59
|
const sessionType = LobeSessionType.Agent;
|
72
60
|
const defaultValue = { meta: { title: 'New Session' } } as Partial<LobeAgentSession>;
|
73
|
-
(SessionModel.create as Mock).mockResolvedValue(mockSession);
|
74
61
|
|
75
62
|
// Execute
|
76
63
|
const sessionId = await sessionService.createSession(sessionType, defaultValue);
|
77
64
|
|
78
65
|
// Assert
|
79
|
-
expect(
|
80
|
-
expect(sessionId).toBe(mockSessionId);
|
81
|
-
});
|
82
|
-
|
83
|
-
it('should throw an error if session creation fails', async () => {
|
84
|
-
// Setup
|
85
|
-
const sessionType = LobeSessionType.Agent;
|
86
|
-
const defaultValue = { meta: { title: 'New Session' } } as Partial<LobeAgentSession>;
|
87
|
-
(SessionModel.create as Mock).mockResolvedValue(null);
|
88
|
-
|
89
|
-
// Execute & Assert
|
90
|
-
await expect(sessionService.createSession(sessionType, defaultValue)).rejects.toThrow(
|
91
|
-
'session create Error',
|
92
|
-
);
|
93
|
-
});
|
94
|
-
});
|
95
|
-
|
96
|
-
describe('batchCreateSessions', () => {
|
97
|
-
it('should batch create sessions', async () => {
|
98
|
-
// Setup
|
99
|
-
(SessionModel.batchCreate as Mock).mockResolvedValue(mockSessions);
|
100
|
-
|
101
|
-
// Execute
|
102
|
-
const result = await sessionService.batchCreateSessions(mockSessions);
|
103
|
-
|
104
|
-
// Assert
|
105
|
-
expect(SessionModel.batchCreate).toHaveBeenCalledWith(mockSessions);
|
106
|
-
expect(result).toBe(mockSessions);
|
107
|
-
});
|
108
|
-
});
|
109
|
-
|
110
|
-
describe('getSessionsByType', () => {
|
111
|
-
it('should retrieve sessions with their group ids', async () => {
|
112
|
-
// Setup
|
113
|
-
(SessionModel.query as Mock).mockResolvedValue(mockSessions);
|
114
|
-
|
115
|
-
// Execute
|
116
|
-
const sessions = await sessionService.getSessionsByType();
|
117
|
-
|
118
|
-
// Assert
|
119
|
-
expect(SessionModel.query).toHaveBeenCalled();
|
120
|
-
expect(sessions).toBe(mockSessions);
|
121
|
-
});
|
122
|
-
|
123
|
-
it('should retrieve all agent sessions', async () => {
|
124
|
-
// Setup
|
125
|
-
// Assuming that SessionModel.query has been modified to accept filters
|
126
|
-
const agentSessions = mockSessions.filter((session) => session.type === 'agent');
|
127
|
-
(SessionModel.query as Mock).mockResolvedValue(agentSessions);
|
128
|
-
|
129
|
-
// Execute
|
130
|
-
const result = await sessionService.getSessionsByType('agent');
|
131
|
-
|
132
|
-
// Assert
|
133
|
-
// Assuming that SessionModel.query would be called with a filter for agents
|
134
|
-
expect(SessionModel.query).toHaveBeenCalled(); // Add filter argument if applicable
|
135
|
-
expect(result).toBe(agentSessions);
|
66
|
+
expect(sessionId).toMatch(/^ssn_/);
|
136
67
|
});
|
137
68
|
});
|
138
69
|
|
139
70
|
describe('removeSession', () => {
|
140
71
|
it('should remove a session by its id', async () => {
|
141
|
-
// Setup
|
142
|
-
(SessionModel.delete as Mock).mockResolvedValue(true);
|
143
|
-
|
144
72
|
// Execute
|
145
|
-
|
73
|
+
await sessionService.removeSession(mockSessionId);
|
146
74
|
|
147
75
|
// Assert
|
148
|
-
|
149
|
-
|
76
|
+
|
77
|
+
const result = await clientDB.query.sessions.findFirst({
|
78
|
+
where: eq(sessions.id, mockSessionId),
|
79
|
+
});
|
80
|
+
// Assert
|
81
|
+
expect(result).toBeUndefined();
|
150
82
|
});
|
151
83
|
});
|
152
84
|
|
153
85
|
describe('removeAllSessions', () => {
|
154
86
|
it('should clear all sessions from the table', async () => {
|
155
87
|
// Setup
|
156
|
-
|
88
|
+
await clientDB
|
89
|
+
.insert(sessions)
|
90
|
+
.values([{ userId: userId }, { userId: userId }, { userId: userId }]);
|
157
91
|
|
158
92
|
// Execute
|
159
|
-
|
93
|
+
await sessionService.removeAllSessions();
|
160
94
|
|
161
95
|
// Assert
|
162
|
-
|
163
|
-
|
96
|
+
const result = await clientDB.query.sessions.findMany({
|
97
|
+
where: eq(sessionGroups.userId, userId),
|
98
|
+
});
|
99
|
+
|
100
|
+
expect(result.length).toBe(0);
|
164
101
|
});
|
165
102
|
});
|
166
103
|
|
167
104
|
describe('updateSession', () => {
|
168
105
|
it('should update the group of a session', async () => {
|
169
106
|
// Setup
|
170
|
-
const groupId = '
|
171
|
-
(SessionModel.update as Mock).mockResolvedValue({ ...mockSession, group: groupId });
|
172
|
-
|
173
|
-
// Execute
|
174
|
-
const result = await sessionService.updateSession(mockSessionId, { group: groupId });
|
175
|
-
|
176
|
-
// Assert
|
177
|
-
expect(SessionModel.update).toHaveBeenCalledWith(mockSessionId, { group: groupId });
|
178
|
-
expect(result).toEqual({ ...mockSession, group: groupId });
|
179
|
-
});
|
180
|
-
|
181
|
-
it('should update the meta of a session', async () => {
|
182
|
-
// Setup
|
183
|
-
const newMeta = { description: 'Updated description' };
|
184
|
-
(SessionModel.update as Mock).mockResolvedValue({ ...mockSession, meta: newMeta });
|
107
|
+
const groupId = 'group-1';
|
185
108
|
|
186
109
|
// Execute
|
187
|
-
|
110
|
+
await sessionService.updateSession(mockSessionId, { group: groupId });
|
188
111
|
|
189
112
|
// Assert
|
190
|
-
|
191
|
-
|
113
|
+
const result = await clientDB.query.sessions.findFirst({
|
114
|
+
where: eq(sessions.id, mockSessionId),
|
115
|
+
});
|
116
|
+
expect(result).toMatchObject({ groupId });
|
192
117
|
});
|
193
118
|
|
194
119
|
it('should update the pinned status of a session', async () => {
|
@@ -199,7 +124,11 @@ describe('SessionService', () => {
|
|
199
124
|
await sessionService.updateSession(mockSessionId, { pinned });
|
200
125
|
|
201
126
|
// Assert
|
202
|
-
|
127
|
+
const result = await clientDB.query.sessions.findFirst({
|
128
|
+
where: eq(sessions.id, mockSessionId),
|
129
|
+
});
|
130
|
+
|
131
|
+
expect(result!.pinned).toBeTruthy();
|
203
132
|
});
|
204
133
|
});
|
205
134
|
|
@@ -207,81 +136,55 @@ describe('SessionService', () => {
|
|
207
136
|
it('should update the config of a session', async () => {
|
208
137
|
// Setup
|
209
138
|
const newConfig = { model: 'abc' } as LobeAgentConfig;
|
210
|
-
(SessionModel.updateConfig as Mock).mockResolvedValue({ ...mockSession, config: newConfig });
|
211
139
|
|
212
140
|
// Execute
|
213
|
-
|
141
|
+
await sessionService.updateSessionConfig(mockSessionId, newConfig);
|
214
142
|
|
215
143
|
// Assert
|
216
|
-
|
217
|
-
expect(result).
|
144
|
+
const result = await sessionService.getSessionConfig(mockSessionId);
|
145
|
+
expect(result).toMatchObject(newConfig);
|
218
146
|
});
|
219
147
|
});
|
220
148
|
|
221
149
|
describe('countSessions', () => {
|
222
150
|
it('should return false if no sessions exist', async () => {
|
223
|
-
|
224
|
-
(SessionModel.count as Mock).mockResolvedValue(0);
|
151
|
+
await clientDB.delete(sessions);
|
225
152
|
|
226
153
|
// Execute
|
227
154
|
const result = await sessionService.countSessions();
|
228
155
|
|
229
156
|
// Assert
|
230
|
-
expect(SessionModel.count).toHaveBeenCalled();
|
231
157
|
expect(result).toBe(0);
|
232
158
|
});
|
233
159
|
|
234
160
|
it('should return true if sessions exist', async () => {
|
235
161
|
// Setup
|
236
|
-
|
162
|
+
await clientDB.delete(sessions);
|
163
|
+
await clientDB.insert(sessions).values([{ userId }]);
|
237
164
|
|
238
165
|
// Execute
|
239
166
|
const result = await sessionService.countSessions();
|
240
167
|
|
241
168
|
// Assert
|
242
|
-
expect(SessionModel.count).toHaveBeenCalled();
|
243
169
|
expect(result).toBe(1);
|
244
170
|
});
|
245
171
|
});
|
246
172
|
|
247
|
-
describe('hasSessions', () => {
|
248
|
-
it('should return false if no sessions exist', async () => {
|
249
|
-
// Setup
|
250
|
-
(SessionModel.count as Mock).mockResolvedValue(0);
|
251
|
-
|
252
|
-
// Execute
|
253
|
-
const result = await sessionService.hasSessions();
|
254
|
-
|
255
|
-
// Assert
|
256
|
-
expect(SessionModel.count).toHaveBeenCalled();
|
257
|
-
expect(result).toBe(false);
|
258
|
-
});
|
259
|
-
|
260
|
-
it('should return true if sessions exist', async () => {
|
261
|
-
// Setup
|
262
|
-
(SessionModel.count as Mock).mockResolvedValue(1);
|
263
|
-
|
264
|
-
// Execute
|
265
|
-
const result = await sessionService.hasSessions();
|
266
|
-
|
267
|
-
// Assert
|
268
|
-
expect(SessionModel.count).toHaveBeenCalled();
|
269
|
-
expect(result).toBe(true);
|
270
|
-
});
|
271
|
-
});
|
272
|
-
|
273
173
|
describe('searchSessions', () => {
|
274
174
|
it('should return sessions that match the keyword', async () => {
|
275
175
|
// Setup
|
276
|
-
|
277
|
-
|
176
|
+
await clientDB.insert(agents).values({ userId, id: 'agent-1', title: 'Session Name' });
|
177
|
+
await clientDB
|
178
|
+
.insert(agentsToSessions)
|
179
|
+
.values({ agentId: 'agent-1', sessionId: mockSessionId });
|
278
180
|
|
279
181
|
// Execute
|
182
|
+
const keyword = 'Name';
|
280
183
|
const result = await sessionService.searchSessions(keyword);
|
281
184
|
|
282
185
|
// Assert
|
283
|
-
|
284
|
-
expect(result).
|
186
|
+
// TODO: 后续需要把这个搜索的标题和描述都加上,现在这个 client 搜索会有问题
|
187
|
+
expect(result).toMatchObject([{ id: mockSessionId }]);
|
285
188
|
});
|
286
189
|
});
|
287
190
|
|
@@ -289,31 +192,112 @@ describe('SessionService', () => {
|
|
289
192
|
it('should duplicate a session and return its id', async () => {
|
290
193
|
// Setup
|
291
194
|
const newTitle = 'Duplicated Session';
|
292
|
-
|
293
|
-
...mockSession,
|
195
|
+
const session: NewSession = {
|
294
196
|
id: 'duplicated-session-id',
|
295
|
-
|
197
|
+
title: '123',
|
198
|
+
userId,
|
199
|
+
};
|
200
|
+
await clientDB.insert(sessions).values([session]);
|
201
|
+
await clientDB.insert(agents).values({ userId, id: 'agent-1' });
|
202
|
+
await clientDB
|
203
|
+
.insert(agentsToSessions)
|
204
|
+
.values({ agentId: 'agent-1', sessionId: 'duplicated-session-id' });
|
296
205
|
|
297
206
|
// Execute
|
298
207
|
const duplicatedSessionId = await sessionService.cloneSession(mockSessionId, newTitle);
|
299
208
|
|
300
209
|
// Assert
|
301
|
-
|
302
|
-
|
210
|
+
|
211
|
+
const result = await clientDB.query.sessions.findFirst({
|
212
|
+
where: eq(sessions.id, duplicatedSessionId!),
|
213
|
+
});
|
214
|
+
expect(result).toMatchObject({ title: 'Duplicated Session' });
|
303
215
|
});
|
304
216
|
});
|
305
217
|
|
306
218
|
describe('getGroupedSessions', () => {
|
307
219
|
it('should retrieve sessions with their group', async () => {
|
308
|
-
// Setup
|
309
|
-
(SessionModel.queryWithGroups as Mock).mockResolvedValue(mockSessions);
|
310
|
-
|
311
220
|
// Execute
|
312
221
|
const sessionsWithGroup = await sessionService.getGroupedSessions();
|
313
222
|
|
314
|
-
|
315
|
-
|
316
|
-
|
223
|
+
expect(sessionsWithGroup).toMatchObject({
|
224
|
+
sessionGroups: [
|
225
|
+
{ id: 'group-2', name: 'group-B', sort: 1 },
|
226
|
+
{ id: 'group-1', name: 'group-A', sort: 2 },
|
227
|
+
],
|
228
|
+
sessions: [{ id: 'mock-session-id', type: 'agent' }],
|
229
|
+
});
|
230
|
+
});
|
231
|
+
});
|
232
|
+
|
233
|
+
describe('getSessionsByType', () => {
|
234
|
+
it('should get sessions by type "all"', async () => {
|
235
|
+
const sessions = await sessionService.getSessionsByType('all');
|
236
|
+
expect(sessions).toBeDefined();
|
237
|
+
});
|
238
|
+
|
239
|
+
it('should get sessions by type "agent"', async () => {
|
240
|
+
const sessions = await sessionService.getSessionsByType('agent');
|
241
|
+
expect(sessions).toBeDefined();
|
242
|
+
});
|
243
|
+
|
244
|
+
it('should get sessions by type "group"', async () => {
|
245
|
+
const sessions = await sessionService.getSessionsByType('group');
|
246
|
+
expect(sessions).toBeDefined();
|
247
|
+
});
|
248
|
+
});
|
249
|
+
|
250
|
+
describe('getSessionConfig', () => {
|
251
|
+
it.skip('should get default config for INBOX_SESSION_ID', async () => {
|
252
|
+
const config = await sessionService.getSessionConfig(INBOX_SESSION_ID);
|
253
|
+
expect(config).toBeDefined();
|
254
|
+
});
|
255
|
+
|
256
|
+
it('should throw error for non-existent session', async () => {
|
257
|
+
await expect(sessionService.getSessionConfig('non-existent')).rejects.toThrow(
|
258
|
+
'Session not found',
|
259
|
+
);
|
260
|
+
});
|
261
|
+
});
|
262
|
+
|
263
|
+
describe('updateSessionMeta', () => {
|
264
|
+
it('should not update meta for INBOX_SESSION_ID', async () => {
|
265
|
+
const result = await sessionService.updateSessionMeta(INBOX_SESSION_ID, {
|
266
|
+
title: 'New Title',
|
267
|
+
});
|
268
|
+
expect(result).toBeUndefined();
|
269
|
+
});
|
270
|
+
|
271
|
+
it('should update meta for normal session', async () => {
|
272
|
+
const meta = { title: 'Updated Title' };
|
273
|
+
await sessionService.updateSessionMeta(mockSessionId, meta);
|
274
|
+
|
275
|
+
const session = await clientDB.query.sessions.findFirst({
|
276
|
+
where: eq(sessions.id, mockSessionId),
|
277
|
+
});
|
278
|
+
expect(session).toBeDefined();
|
279
|
+
});
|
280
|
+
});
|
281
|
+
|
282
|
+
describe('updateSessionChatConfig', () => {
|
283
|
+
it('should update chat config', async () => {
|
284
|
+
const chatConfig = { temperature: 0.8 } as Partial<LobeAgentChatConfig>;
|
285
|
+
const result = await sessionService.updateSessionChatConfig(mockSessionId, chatConfig);
|
286
|
+
expect(result).toBeDefined();
|
287
|
+
});
|
288
|
+
});
|
289
|
+
|
290
|
+
describe('model getters', () => {
|
291
|
+
it('should return session model instance', () => {
|
292
|
+
// @ts-ignore - accessing private getter
|
293
|
+
const model = sessionService.sessionModel;
|
294
|
+
expect(model).toBeDefined();
|
295
|
+
});
|
296
|
+
|
297
|
+
it('should return session group model instance', () => {
|
298
|
+
// @ts-ignore - accessing private getter
|
299
|
+
const model = sessionService.sessionGroupModel;
|
300
|
+
expect(model).toBeDefined();
|
317
301
|
});
|
318
302
|
});
|
319
303
|
|
@@ -323,84 +307,66 @@ describe('SessionService', () => {
|
|
323
307
|
// Setup
|
324
308
|
const groupName = 'New Group';
|
325
309
|
const sort = 1;
|
326
|
-
(SessionGroupModel.create as Mock).mockResolvedValue({
|
327
|
-
id: 'new-group-id',
|
328
|
-
name: groupName,
|
329
|
-
sort,
|
330
|
-
});
|
331
310
|
|
332
311
|
// Execute
|
333
312
|
const groupId = await sessionService.createSessionGroup(groupName, sort);
|
334
313
|
|
335
314
|
// Assert
|
336
|
-
expect(
|
337
|
-
expect(groupId).toBe('new-group-id');
|
338
|
-
});
|
339
|
-
});
|
340
|
-
|
341
|
-
describe('batchCreateSessionGroups', () => {
|
342
|
-
it('should batch create session groups', async () => {
|
343
|
-
// Setup
|
344
|
-
const groups = [
|
345
|
-
{ id: 'group-1', name: 'Group 1', sort: 1 },
|
346
|
-
{ id: 'group-2', name: 'Group 2', sort: 2 },
|
347
|
-
] as SessionGroups;
|
315
|
+
expect(groupId).toMatch(/^sg_/);
|
348
316
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
const result = await sessionService.batchCreateSessionGroups(groups);
|
317
|
+
const result = await clientDB.query.sessionGroups.findFirst({
|
318
|
+
where: eq(sessionGroups.id, groupId),
|
319
|
+
});
|
353
320
|
|
354
|
-
|
355
|
-
expect(SessionGroupModel.batchCreate).toHaveBeenCalledWith(groups);
|
356
|
-
expect(result).toBe(groups);
|
321
|
+
expect(result).toMatchObject({ id: groupId, name: groupName, sort });
|
357
322
|
});
|
358
323
|
});
|
359
324
|
|
360
325
|
describe('removeSessionGroup', () => {
|
361
326
|
it('should remove a session group by its id', async () => {
|
362
|
-
|
363
|
-
const removeChildren = true;
|
364
|
-
(SessionGroupModel.delete as Mock).mockResolvedValue(true);
|
365
|
-
|
327
|
+
const groupId = 'group-1';
|
366
328
|
// Execute
|
367
|
-
|
329
|
+
await sessionService.removeSessionGroup(groupId);
|
368
330
|
|
331
|
+
const result = await clientDB.query.sessionGroups.findFirst({
|
332
|
+
where: eq(sessionGroups.id, groupId),
|
333
|
+
});
|
369
334
|
// Assert
|
370
|
-
expect(
|
371
|
-
expect(result).toBe(true);
|
335
|
+
expect(result).toBeUndefined();
|
372
336
|
});
|
373
337
|
});
|
374
338
|
|
375
339
|
describe('clearSessionGroups', () => {
|
376
340
|
it('should clear all session groups', async () => {
|
377
|
-
// Setup
|
378
|
-
(SessionGroupModel.clear as Mock).mockResolvedValue(true);
|
379
|
-
|
380
341
|
// Execute
|
381
|
-
|
342
|
+
await sessionService.removeSessionGroups();
|
382
343
|
|
383
344
|
// Assert
|
384
|
-
|
385
|
-
|
345
|
+
const result = await clientDB.query.sessionGroups.findMany({
|
346
|
+
where: eq(sessionGroups.userId, userId),
|
347
|
+
});
|
348
|
+
|
349
|
+
expect(result.length).toBe(0);
|
350
|
+
|
351
|
+
const result2 = await clientDB.query.sessionGroups.findMany({
|
352
|
+
where: not(eq(sessionGroups.userId, userId)),
|
353
|
+
});
|
354
|
+
|
355
|
+
expect(result2.length).toBeGreaterThan(0);
|
386
356
|
});
|
387
357
|
});
|
388
358
|
|
389
359
|
describe('getSessionGroups', () => {
|
390
360
|
it('should retrieve all session groups', async () => {
|
391
|
-
// Setup
|
392
|
-
const groups = [
|
393
|
-
{ id: 'group-1', name: 'Group 1', sort: 1 },
|
394
|
-
{ id: 'group-2', name: 'Group 2', sort: 2 },
|
395
|
-
];
|
396
|
-
(SessionGroupModel.query as Mock).mockResolvedValue(groups);
|
397
|
-
|
398
361
|
// Execute
|
399
362
|
const result = await sessionService.getSessionGroups();
|
400
363
|
|
401
364
|
// Assert
|
402
|
-
|
403
|
-
|
365
|
+
const groups = [
|
366
|
+
{ id: 'group-2', name: 'group-B', sort: 1 },
|
367
|
+
{ id: 'group-1', name: 'group-A', sort: 2 },
|
368
|
+
];
|
369
|
+
expect(result).toMatchObject(groups);
|
404
370
|
});
|
405
371
|
});
|
406
372
|
|
@@ -409,14 +375,15 @@ describe('SessionService', () => {
|
|
409
375
|
// Setup
|
410
376
|
const groupId = 'group-1';
|
411
377
|
const data = { name: 'Updated Group', sort: 2 };
|
412
|
-
(SessionGroupModel.update as Mock).mockResolvedValue({ id: groupId, ...data });
|
413
378
|
|
414
379
|
// Execute
|
415
|
-
|
380
|
+
await sessionService.updateSessionGroup(groupId, data);
|
416
381
|
|
417
382
|
// Assert
|
418
|
-
|
419
|
-
|
383
|
+
const result = await clientDB.query.sessionGroups.findFirst({
|
384
|
+
where: eq(sessionGroups.id, groupId),
|
385
|
+
});
|
386
|
+
expect(result).toMatchObject({ id: groupId, ...data });
|
420
387
|
});
|
421
388
|
});
|
422
389
|
|
@@ -427,14 +394,18 @@ describe('SessionService', () => {
|
|
427
394
|
{ id: 'group-1', sort: 2 },
|
428
395
|
{ id: 'group-2', sort: 1 },
|
429
396
|
];
|
430
|
-
(SessionGroupModel.updateOrder as Mock).mockResolvedValue(true);
|
431
397
|
|
432
398
|
// Execute
|
433
|
-
|
399
|
+
await sessionService.updateSessionGroupOrder(sortMap);
|
434
400
|
|
435
401
|
// Assert
|
436
|
-
|
437
|
-
|
402
|
+
const data = await clientDB.query.sessionGroups.findMany({
|
403
|
+
where: eq(sessionGroups.userId, userId),
|
404
|
+
});
|
405
|
+
expect(data).toMatchObject([
|
406
|
+
{ id: 'group-1', sort: 2 },
|
407
|
+
{ id: 'group-2', sort: 1 },
|
408
|
+
]);
|
438
409
|
});
|
439
410
|
});
|
440
411
|
});
|