@app-connect/core 1.7.8 → 1.7.10
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/handlers/auth.js +10 -4
- package/handlers/contact.js +42 -9
- package/handlers/log.js +4 -4
- package/index.js +101 -79
- package/lib/oauth.js +0 -2
- package/models/accountDataModel.js +34 -0
- package/package.json +70 -69
- package/releaseNotes.json +24 -0
- package/test/connector/registry.test.js +145 -0
- package/test/handlers/admin.test.js +583 -0
- package/test/handlers/auth.test.js +355 -0
- package/test/handlers/contact.test.js +852 -0
- package/test/handlers/log.test.js +868 -0
- package/test/lib/callLogComposer.test.js +1231 -0
- package/test/lib/debugTracer.test.js +328 -0
- package/test/lib/oauth.test.js +359 -0
- package/test/lib/ringcentral.test.js +473 -0
- package/test/lib/util.test.js +282 -0
- package/test/models/accountDataModel.test.js +98 -0
- package/test/models/dynamo/connectorSchema.test.js +189 -0
- package/test/models/models.test.js +539 -0
- package/test/setup.js +176 -176
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
// Use in-memory SQLite for isolated model tests
|
|
2
|
+
jest.mock('../../models/sequelize', () => {
|
|
3
|
+
const { Sequelize } = require('sequelize');
|
|
4
|
+
return {
|
|
5
|
+
sequelize: new Sequelize({
|
|
6
|
+
dialect: 'sqlite',
|
|
7
|
+
storage: ':memory:',
|
|
8
|
+
logging: false,
|
|
9
|
+
}),
|
|
10
|
+
};
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const { CallLogModel } = require('../../models/callLogModel');
|
|
14
|
+
const { MessageLogModel } = require('../../models/messageLogModel');
|
|
15
|
+
const { UserModel } = require('../../models/userModel');
|
|
16
|
+
const { CacheModel } = require('../../models/cacheModel');
|
|
17
|
+
const { AdminConfigModel } = require('../../models/adminConfigModel');
|
|
18
|
+
const { sequelize } = require('../../models/sequelize');
|
|
19
|
+
|
|
20
|
+
describe('Core Models', () => {
|
|
21
|
+
beforeAll(async () => {
|
|
22
|
+
await CallLogModel.sync({ force: true });
|
|
23
|
+
await MessageLogModel.sync({ force: true });
|
|
24
|
+
await UserModel.sync({ force: true });
|
|
25
|
+
await CacheModel.sync({ force: true });
|
|
26
|
+
await AdminConfigModel.sync({ force: true });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
afterEach(async () => {
|
|
30
|
+
await CallLogModel.destroy({ where: {} });
|
|
31
|
+
await MessageLogModel.destroy({ where: {} });
|
|
32
|
+
await UserModel.destroy({ where: {} });
|
|
33
|
+
await CacheModel.destroy({ where: {} });
|
|
34
|
+
await AdminConfigModel.destroy({ where: {} });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterAll(async () => {
|
|
38
|
+
await sequelize.close();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('UserModel', () => {
|
|
42
|
+
test('should create user with required fields', async () => {
|
|
43
|
+
// Arrange & Act
|
|
44
|
+
const user = await UserModel.create({
|
|
45
|
+
id: 'user-1',
|
|
46
|
+
platform: 'testCRM',
|
|
47
|
+
accessToken: 'token-123'
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Assert
|
|
51
|
+
expect(user.id).toBe('user-1');
|
|
52
|
+
expect(user.platform).toBe('testCRM');
|
|
53
|
+
expect(user.accessToken).toBe('token-123');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('should create user with all optional fields', async () => {
|
|
57
|
+
// Arrange
|
|
58
|
+
const tokenExpiry = new Date('2024-12-31');
|
|
59
|
+
|
|
60
|
+
// Act
|
|
61
|
+
const user = await UserModel.create({
|
|
62
|
+
id: 'user-full',
|
|
63
|
+
platform: 'testCRM',
|
|
64
|
+
hostname: 'test.example.com',
|
|
65
|
+
accessToken: 'token-123',
|
|
66
|
+
refreshToken: 'refresh-123',
|
|
67
|
+
tokenExpiry: tokenExpiry,
|
|
68
|
+
rcAccountId: 'rc-account-123',
|
|
69
|
+
timezoneOffset: '-08:00',
|
|
70
|
+
timezoneName: 'America/Los_Angeles',
|
|
71
|
+
platformAdditionalInfo: { customField: 'value' },
|
|
72
|
+
userSettings: { autoLog: true }
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Assert
|
|
76
|
+
expect(user.hostname).toBe('test.example.com');
|
|
77
|
+
expect(user.refreshToken).toBe('refresh-123');
|
|
78
|
+
expect(user.rcAccountId).toBe('rc-account-123');
|
|
79
|
+
expect(user.platformAdditionalInfo).toEqual({ customField: 'value' });
|
|
80
|
+
expect(user.userSettings).toEqual({ autoLog: true });
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('should find user by primary key', async () => {
|
|
84
|
+
// Arrange
|
|
85
|
+
await UserModel.create({
|
|
86
|
+
id: 'user-find',
|
|
87
|
+
platform: 'testCRM',
|
|
88
|
+
accessToken: 'token'
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Act
|
|
92
|
+
const user = await UserModel.findByPk('user-find');
|
|
93
|
+
|
|
94
|
+
// Assert
|
|
95
|
+
expect(user).not.toBeNull();
|
|
96
|
+
expect(user.id).toBe('user-find');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('should find user by platform and id', async () => {
|
|
100
|
+
// Arrange
|
|
101
|
+
await UserModel.create({
|
|
102
|
+
id: 'user-platform',
|
|
103
|
+
platform: 'testCRM',
|
|
104
|
+
accessToken: 'token'
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Act
|
|
108
|
+
const user = await UserModel.findOne({
|
|
109
|
+
where: { id: 'user-platform', platform: 'testCRM' }
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Assert
|
|
113
|
+
expect(user).not.toBeNull();
|
|
114
|
+
expect(user.platform).toBe('testCRM');
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('should update user fields', async () => {
|
|
118
|
+
// Arrange
|
|
119
|
+
const user = await UserModel.create({
|
|
120
|
+
id: 'user-update',
|
|
121
|
+
platform: 'testCRM',
|
|
122
|
+
accessToken: 'old-token'
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Act
|
|
126
|
+
await user.update({ accessToken: 'new-token' });
|
|
127
|
+
|
|
128
|
+
// Assert
|
|
129
|
+
const updated = await UserModel.findByPk('user-update');
|
|
130
|
+
expect(updated.accessToken).toBe('new-token');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test('should delete user', async () => {
|
|
134
|
+
// Arrange
|
|
135
|
+
await UserModel.create({
|
|
136
|
+
id: 'user-delete',
|
|
137
|
+
platform: 'testCRM',
|
|
138
|
+
accessToken: 'token'
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Act
|
|
142
|
+
await UserModel.destroy({ where: { id: 'user-delete' } });
|
|
143
|
+
|
|
144
|
+
// Assert
|
|
145
|
+
const user = await UserModel.findByPk('user-delete');
|
|
146
|
+
expect(user).toBeNull();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
describe('CallLogModel', () => {
|
|
151
|
+
test('should create call log with required fields', async () => {
|
|
152
|
+
// Arrange & Act
|
|
153
|
+
const log = await CallLogModel.create({
|
|
154
|
+
id: 'call-1',
|
|
155
|
+
sessionId: 'session-123',
|
|
156
|
+
platform: 'testCRM',
|
|
157
|
+
thirdPartyLogId: 'third-party-1',
|
|
158
|
+
userId: 'user-1'
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Assert
|
|
162
|
+
expect(log.id).toBe('call-1');
|
|
163
|
+
expect(log.sessionId).toBe('session-123');
|
|
164
|
+
expect(log.thirdPartyLogId).toBe('third-party-1');
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('should create call log with optional contactId', async () => {
|
|
168
|
+
// Act
|
|
169
|
+
const log = await CallLogModel.create({
|
|
170
|
+
id: 'call-contact',
|
|
171
|
+
sessionId: 'session-456',
|
|
172
|
+
platform: 'testCRM',
|
|
173
|
+
thirdPartyLogId: 'third-party-2',
|
|
174
|
+
userId: 'user-1',
|
|
175
|
+
contactId: 'contact-123'
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Assert
|
|
179
|
+
expect(log.contactId).toBe('contact-123');
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test('should find call logs by session ID', async () => {
|
|
183
|
+
// Arrange
|
|
184
|
+
await CallLogModel.create({
|
|
185
|
+
id: 'call-session',
|
|
186
|
+
sessionId: 'unique-session',
|
|
187
|
+
platform: 'testCRM',
|
|
188
|
+
thirdPartyLogId: 'third-party-3',
|
|
189
|
+
userId: 'user-1'
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Act
|
|
193
|
+
const log = await CallLogModel.findOne({
|
|
194
|
+
where: { sessionId: 'unique-session' }
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Assert
|
|
198
|
+
expect(log).not.toBeNull();
|
|
199
|
+
expect(log.id).toBe('call-session');
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test('should find multiple call logs by session IDs', async () => {
|
|
203
|
+
// Arrange
|
|
204
|
+
await CallLogModel.bulkCreate([
|
|
205
|
+
{ id: 'call-multi-1', sessionId: 'session-a', platform: 'testCRM', thirdPartyLogId: 'tp-1', userId: 'user-1' },
|
|
206
|
+
{ id: 'call-multi-2', sessionId: 'session-b', platform: 'testCRM', thirdPartyLogId: 'tp-2', userId: 'user-1' },
|
|
207
|
+
{ id: 'call-multi-3', sessionId: 'session-c', platform: 'testCRM', thirdPartyLogId: 'tp-3', userId: 'user-1' }
|
|
208
|
+
]);
|
|
209
|
+
|
|
210
|
+
// Act
|
|
211
|
+
const { Op } = require('sequelize');
|
|
212
|
+
const logs = await CallLogModel.findAll({
|
|
213
|
+
where: {
|
|
214
|
+
sessionId: { [Op.in]: ['session-a', 'session-c'] }
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Assert
|
|
219
|
+
expect(logs).toHaveLength(2);
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
describe('MessageLogModel', () => {
|
|
224
|
+
test('should create message log with required fields', async () => {
|
|
225
|
+
// Arrange & Act
|
|
226
|
+
const log = await MessageLogModel.create({
|
|
227
|
+
id: 'msg-1',
|
|
228
|
+
platform: 'testCRM',
|
|
229
|
+
conversationId: 'conv-123',
|
|
230
|
+
thirdPartyLogId: 'third-party-msg-1',
|
|
231
|
+
userId: 'user-1'
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// Assert
|
|
235
|
+
expect(log.id).toBe('msg-1');
|
|
236
|
+
expect(log.conversationId).toBe('conv-123');
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test('should create message log with conversationLogId', async () => {
|
|
240
|
+
// Act
|
|
241
|
+
const log = await MessageLogModel.create({
|
|
242
|
+
id: 'msg-conv',
|
|
243
|
+
platform: 'testCRM',
|
|
244
|
+
conversationId: 'conv-456',
|
|
245
|
+
conversationLogId: 'conv-log-456',
|
|
246
|
+
thirdPartyLogId: 'third-party-msg-2',
|
|
247
|
+
userId: 'user-1'
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// Assert
|
|
251
|
+
expect(log.conversationLogId).toBe('conv-log-456');
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
test('should find message logs by conversation ID', async () => {
|
|
255
|
+
// Arrange
|
|
256
|
+
await MessageLogModel.create({
|
|
257
|
+
id: 'msg-find',
|
|
258
|
+
platform: 'testCRM',
|
|
259
|
+
conversationId: 'conv-find',
|
|
260
|
+
thirdPartyLogId: 'third-party-find',
|
|
261
|
+
userId: 'user-1'
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// Act
|
|
265
|
+
const log = await MessageLogModel.findOne({
|
|
266
|
+
where: { conversationId: 'conv-find' }
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// Assert
|
|
270
|
+
expect(log).not.toBeNull();
|
|
271
|
+
expect(log.id).toBe('msg-find');
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test('should find message logs by conversationLogId', async () => {
|
|
275
|
+
// Arrange
|
|
276
|
+
await MessageLogModel.create({
|
|
277
|
+
id: 'msg-conv-log',
|
|
278
|
+
platform: 'testCRM',
|
|
279
|
+
conversationId: 'conv-789',
|
|
280
|
+
conversationLogId: 'conv-log-789',
|
|
281
|
+
thirdPartyLogId: 'third-party-789',
|
|
282
|
+
userId: 'user-1'
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Act
|
|
286
|
+
const log = await MessageLogModel.findOne({
|
|
287
|
+
where: { conversationLogId: 'conv-log-789' }
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Assert
|
|
291
|
+
expect(log).not.toBeNull();
|
|
292
|
+
expect(log.conversationLogId).toBe('conv-log-789');
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
describe('CacheModel', () => {
|
|
297
|
+
test('should create cache entry', async () => {
|
|
298
|
+
// Arrange & Act
|
|
299
|
+
const cache = await CacheModel.create({
|
|
300
|
+
id: 'cache-1',
|
|
301
|
+
userId: 'user-123',
|
|
302
|
+
cacheKey: 'contacts',
|
|
303
|
+
status: 'active'
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// Assert
|
|
307
|
+
expect(cache.id).toBe('cache-1');
|
|
308
|
+
expect(cache.userId).toBe('user-123');
|
|
309
|
+
expect(cache.cacheKey).toBe('contacts');
|
|
310
|
+
expect(cache.status).toBe('active');
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
test('should update cache status', async () => {
|
|
314
|
+
// Arrange
|
|
315
|
+
const cache = await CacheModel.create({
|
|
316
|
+
id: 'cache-update',
|
|
317
|
+
userId: 'user-123',
|
|
318
|
+
cacheKey: 'contacts',
|
|
319
|
+
status: 'pending'
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
// Act
|
|
323
|
+
await cache.update({ status: 'completed' });
|
|
324
|
+
|
|
325
|
+
// Assert
|
|
326
|
+
const updated = await CacheModel.findByPk('cache-update');
|
|
327
|
+
expect(updated.status).toBe('completed');
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
test('should find cache by userId and cacheKey', async () => {
|
|
331
|
+
// Arrange
|
|
332
|
+
await CacheModel.create({
|
|
333
|
+
id: 'cache-find',
|
|
334
|
+
userId: 'user-find',
|
|
335
|
+
cacheKey: 'contacts-cache',
|
|
336
|
+
status: 'active'
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
// Act
|
|
340
|
+
const cache = await CacheModel.findOne({
|
|
341
|
+
where: { userId: 'user-find', cacheKey: 'contacts-cache' }
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// Assert
|
|
345
|
+
expect(cache).not.toBeNull();
|
|
346
|
+
expect(cache.status).toBe('active');
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
describe('AdminConfigModel', () => {
|
|
351
|
+
test('should create admin config with basic settings', async () => {
|
|
352
|
+
// Arrange & Act
|
|
353
|
+
const config = await AdminConfigModel.create({
|
|
354
|
+
id: 'admin-1',
|
|
355
|
+
userSettings: { autoLogCalls: true, autoLogMessages: false }
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// Assert
|
|
359
|
+
expect(config.id).toBe('admin-1');
|
|
360
|
+
expect(config.userSettings).toEqual({ autoLogCalls: true, autoLogMessages: false });
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
test('should create admin config with tokens', async () => {
|
|
364
|
+
// Arrange
|
|
365
|
+
const expiry = new Date('2024-12-31');
|
|
366
|
+
|
|
367
|
+
// Act
|
|
368
|
+
const config = await AdminConfigModel.create({
|
|
369
|
+
id: 'admin-tokens',
|
|
370
|
+
adminAccessToken: 'access-token',
|
|
371
|
+
adminRefreshToken: 'refresh-token',
|
|
372
|
+
adminTokenExpiry: expiry
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
// Assert
|
|
376
|
+
expect(config.adminAccessToken).toBe('access-token');
|
|
377
|
+
expect(config.adminRefreshToken).toBe('refresh-token');
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
test('should create admin config with user mappings', async () => {
|
|
381
|
+
// Arrange
|
|
382
|
+
const userMappings = [
|
|
383
|
+
{ crmUserId: 'crm-1', rcExtensionId: ['ext-1'] },
|
|
384
|
+
{ crmUserId: 'crm-2', rcExtensionId: ['ext-2', 'ext-3'] }
|
|
385
|
+
];
|
|
386
|
+
|
|
387
|
+
// Act
|
|
388
|
+
const config = await AdminConfigModel.create({
|
|
389
|
+
id: 'admin-mappings',
|
|
390
|
+
userMappings: userMappings
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
// Assert
|
|
394
|
+
expect(config.userMappings).toEqual(userMappings);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
test('should update admin config settings', async () => {
|
|
398
|
+
// Arrange
|
|
399
|
+
const config = await AdminConfigModel.create({
|
|
400
|
+
id: 'admin-update',
|
|
401
|
+
userSettings: { autoLog: false }
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
// Act
|
|
405
|
+
await config.update({ userSettings: { autoLog: true } });
|
|
406
|
+
|
|
407
|
+
// Assert
|
|
408
|
+
const updated = await AdminConfigModel.findByPk('admin-update');
|
|
409
|
+
expect(updated.userSettings).toEqual({ autoLog: true });
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
test('should find admin config by primary key', async () => {
|
|
413
|
+
// Arrange
|
|
414
|
+
await AdminConfigModel.create({
|
|
415
|
+
id: 'admin-find',
|
|
416
|
+
userSettings: { enabled: true }
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
// Act
|
|
420
|
+
const config = await AdminConfigModel.findByPk('admin-find');
|
|
421
|
+
|
|
422
|
+
// Assert
|
|
423
|
+
expect(config).not.toBeNull();
|
|
424
|
+
expect(config.id).toBe('admin-find');
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
describe('Model Relationships and Edge Cases', () => {
|
|
429
|
+
test('should handle null JSON fields', async () => {
|
|
430
|
+
// Act
|
|
431
|
+
const user = await UserModel.create({
|
|
432
|
+
id: 'user-null-json',
|
|
433
|
+
platform: 'testCRM',
|
|
434
|
+
accessToken: 'token',
|
|
435
|
+
platformAdditionalInfo: null,
|
|
436
|
+
userSettings: null
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// Assert
|
|
440
|
+
expect(user.platformAdditionalInfo).toBeNull();
|
|
441
|
+
expect(user.userSettings).toBeNull();
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
test('should handle empty JSON objects', async () => {
|
|
445
|
+
// Act
|
|
446
|
+
const user = await UserModel.create({
|
|
447
|
+
id: 'user-empty-json',
|
|
448
|
+
platform: 'testCRM',
|
|
449
|
+
accessToken: 'token',
|
|
450
|
+
platformAdditionalInfo: {},
|
|
451
|
+
userSettings: {}
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// Assert
|
|
455
|
+
expect(user.platformAdditionalInfo).toEqual({});
|
|
456
|
+
expect(user.userSettings).toEqual({});
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
test('should handle complex nested JSON', async () => {
|
|
460
|
+
// Arrange
|
|
461
|
+
const complexData = {
|
|
462
|
+
level1: {
|
|
463
|
+
level2: {
|
|
464
|
+
level3: {
|
|
465
|
+
value: 'deep',
|
|
466
|
+
array: [1, 2, 3]
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
items: [
|
|
470
|
+
{ id: 1, name: 'Item 1' },
|
|
471
|
+
{ id: 2, name: 'Item 2' }
|
|
472
|
+
]
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
// Act
|
|
477
|
+
const user = await UserModel.create({
|
|
478
|
+
id: 'user-complex-json',
|
|
479
|
+
platform: 'testCRM',
|
|
480
|
+
accessToken: 'token',
|
|
481
|
+
platformAdditionalInfo: complexData
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
// Assert
|
|
485
|
+
expect(user.platformAdditionalInfo).toEqual(complexData);
|
|
486
|
+
expect(user.platformAdditionalInfo.level1.level2.level3.value).toBe('deep');
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
test('should enforce unique primary key constraint', async () => {
|
|
490
|
+
// Arrange
|
|
491
|
+
await UserModel.create({
|
|
492
|
+
id: 'unique-user',
|
|
493
|
+
platform: 'testCRM',
|
|
494
|
+
accessToken: 'token-1'
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
// Act & Assert
|
|
498
|
+
await expect(
|
|
499
|
+
UserModel.create({
|
|
500
|
+
id: 'unique-user',
|
|
501
|
+
platform: 'testCRM',
|
|
502
|
+
accessToken: 'token-2'
|
|
503
|
+
})
|
|
504
|
+
).rejects.toThrow();
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
test('should handle bulk create', async () => {
|
|
508
|
+
// Arrange
|
|
509
|
+
const users = [
|
|
510
|
+
{ id: 'bulk-1', platform: 'testCRM', accessToken: 'token-1' },
|
|
511
|
+
{ id: 'bulk-2', platform: 'testCRM', accessToken: 'token-2' },
|
|
512
|
+
{ id: 'bulk-3', platform: 'testCRM', accessToken: 'token-3' }
|
|
513
|
+
];
|
|
514
|
+
|
|
515
|
+
// Act
|
|
516
|
+
await UserModel.bulkCreate(users);
|
|
517
|
+
|
|
518
|
+
// Assert
|
|
519
|
+
const count = await UserModel.count({ where: { platform: 'testCRM' } });
|
|
520
|
+
expect(count).toBe(3);
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
test('should handle bulk destroy', async () => {
|
|
524
|
+
// Arrange
|
|
525
|
+
await UserModel.bulkCreate([
|
|
526
|
+
{ id: 'destroy-1', platform: 'destroyTest', accessToken: 'token-1' },
|
|
527
|
+
{ id: 'destroy-2', platform: 'destroyTest', accessToken: 'token-2' }
|
|
528
|
+
]);
|
|
529
|
+
|
|
530
|
+
// Act
|
|
531
|
+
await UserModel.destroy({ where: { platform: 'destroyTest' } });
|
|
532
|
+
|
|
533
|
+
// Assert
|
|
534
|
+
const count = await UserModel.count({ where: { platform: 'destroyTest' } });
|
|
535
|
+
expect(count).toBe(0);
|
|
536
|
+
});
|
|
537
|
+
});
|
|
538
|
+
});
|
|
539
|
+
|