@app-connect/core 1.7.8 → 1.7.11
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/connector/developerPortal.js +43 -0
- package/connector/proxy/index.js +10 -3
- package/connector/registry.js +8 -6
- package/handlers/admin.js +44 -21
- package/handlers/auth.js +97 -69
- package/handlers/calldown.js +10 -4
- package/handlers/contact.js +45 -112
- package/handlers/disposition.js +4 -142
- package/handlers/log.js +174 -259
- package/handlers/user.js +19 -6
- package/index.js +310 -122
- package/lib/analytics.js +3 -1
- package/lib/authSession.js +68 -0
- package/lib/callLogComposer.js +498 -420
- package/lib/errorHandler.js +206 -0
- package/lib/jwt.js +2 -0
- package/lib/logger.js +190 -0
- package/lib/oauth.js +21 -12
- package/lib/ringcentral.js +2 -10
- package/lib/sharedSMSComposer.js +471 -0
- package/mcp/SupportedPlatforms.md +12 -0
- package/mcp/lib/validator.js +91 -0
- package/mcp/mcpHandler.js +166 -0
- package/mcp/tools/checkAuthStatus.js +90 -0
- package/mcp/tools/collectAuthInfo.js +86 -0
- package/mcp/tools/createCallLog.js +299 -0
- package/mcp/tools/createMessageLog.js +283 -0
- package/mcp/tools/doAuth.js +185 -0
- package/mcp/tools/findContactByName.js +87 -0
- package/mcp/tools/findContactByPhone.js +96 -0
- package/mcp/tools/getCallLog.js +98 -0
- package/mcp/tools/getHelp.js +39 -0
- package/mcp/tools/getPublicConnectors.js +46 -0
- package/mcp/tools/index.js +58 -0
- package/mcp/tools/logout.js +63 -0
- package/mcp/tools/rcGetCallLogs.js +73 -0
- package/mcp/tools/setConnector.js +64 -0
- package/mcp/tools/updateCallLog.js +122 -0
- package/models/accountDataModel.js +34 -0
- package/models/cacheModel.js +3 -0
- package/package.json +6 -4
- package/releaseNotes.json +36 -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 +872 -0
- package/test/lib/callLogComposer.test.js +1231 -0
- package/test/lib/debugTracer.test.js +328 -0
- package/test/lib/logger.test.js +206 -0
- package/test/lib/oauth.test.js +359 -0
- package/test/lib/ringcentral.test.js +473 -0
- package/test/lib/sharedSMSComposer.test.js +1084 -0
- package/test/lib/util.test.js +282 -0
- package/test/mcp/tools/collectAuthInfo.test.js +192 -0
- package/test/mcp/tools/createCallLog.test.js +412 -0
- package/test/mcp/tools/createMessageLog.test.js +580 -0
- package/test/mcp/tools/doAuth.test.js +363 -0
- package/test/mcp/tools/findContactByName.test.js +263 -0
- package/test/mcp/tools/findContactByPhone.test.js +284 -0
- package/test/mcp/tools/getCallLog.test.js +286 -0
- package/test/mcp/tools/getPublicConnectors.test.js +128 -0
- package/test/mcp/tools/logout.test.js +169 -0
- package/test/mcp/tools/setConnector.test.js +177 -0
- package/test/mcp/tools/updateCallLog.test.js +346 -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,580 @@
|
|
|
1
|
+
const createMessageLog = require('../../../mcp/tools/createMessageLog');
|
|
2
|
+
const jwt = require('../../../lib/jwt');
|
|
3
|
+
const connectorRegistry = require('../../../connector/registry');
|
|
4
|
+
const logCore = require('../../../handlers/log');
|
|
5
|
+
|
|
6
|
+
// Mock dependencies
|
|
7
|
+
jest.mock('../../../lib/jwt');
|
|
8
|
+
jest.mock('../../../connector/registry');
|
|
9
|
+
jest.mock('../../../handlers/log');
|
|
10
|
+
|
|
11
|
+
describe('MCP Tool: createMessageLog', () => {
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
jest.clearAllMocks();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe('tool definition', () => {
|
|
17
|
+
test('should have correct tool definition', () => {
|
|
18
|
+
expect(createMessageLog.definition).toBeDefined();
|
|
19
|
+
expect(createMessageLog.definition.name).toBe('createMessageLog');
|
|
20
|
+
expect(createMessageLog.definition.description).toContain('REQUIRES AUTHENTICATION');
|
|
21
|
+
expect(createMessageLog.definition.inputSchema).toBeDefined();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('should require jwtToken and incomingData parameters', () => {
|
|
25
|
+
expect(createMessageLog.definition.inputSchema.required).toContain('jwtToken');
|
|
26
|
+
expect(createMessageLog.definition.inputSchema.required).toContain('incomingData');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('should have detailed inputSchema for incomingData', () => {
|
|
30
|
+
const incomingDataSchema = createMessageLog.definition.inputSchema.properties.incomingData;
|
|
31
|
+
expect(incomingDataSchema.properties).toHaveProperty('conversation');
|
|
32
|
+
expect(incomingDataSchema.properties).toHaveProperty('contactId');
|
|
33
|
+
expect(incomingDataSchema.properties).toHaveProperty('contactName');
|
|
34
|
+
expect(incomingDataSchema.required).toContain('conversation');
|
|
35
|
+
expect(incomingDataSchema.required).toContain('contactId');
|
|
36
|
+
expect(incomingDataSchema.required).toContain('contactName');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('execute', () => {
|
|
41
|
+
test('should create message log successfully', async () => {
|
|
42
|
+
// Arrange
|
|
43
|
+
const mockIncomingData = {
|
|
44
|
+
conversation: {
|
|
45
|
+
conversationId: 'conv-123',
|
|
46
|
+
conversationLogId: 'conv-log-123',
|
|
47
|
+
type: 'SMS',
|
|
48
|
+
messages: [
|
|
49
|
+
{
|
|
50
|
+
id: 'msg-123',
|
|
51
|
+
conversationId: 'conv-123',
|
|
52
|
+
phoneNumber: '+1234567890',
|
|
53
|
+
direction: 'Inbound',
|
|
54
|
+
creationTime: 1704110400000,
|
|
55
|
+
subject: 'Hello',
|
|
56
|
+
from: { phoneNumber: '+1234567890', name: 'John Doe' },
|
|
57
|
+
to: [{ phoneNumber: '+0987654321' }]
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
correspondents: [
|
|
61
|
+
{ phoneNumber: '+1234567890' }
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
contactId: 'contact-123',
|
|
65
|
+
contactName: 'John Doe',
|
|
66
|
+
contactType: 'Contact'
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
jwt.decodeJwt.mockReturnValue({
|
|
70
|
+
id: 'user-123',
|
|
71
|
+
platform: 'testCRM'
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const mockConnector = {
|
|
75
|
+
createMessageLog: jest.fn()
|
|
76
|
+
};
|
|
77
|
+
connectorRegistry.getConnector.mockReturnValue(mockConnector);
|
|
78
|
+
|
|
79
|
+
logCore.createMessageLog.mockResolvedValue({
|
|
80
|
+
successful: true,
|
|
81
|
+
logIds: ['crm-msg-log-123'],
|
|
82
|
+
returnMessage: { message: 'Message logs created successfully' }
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Act
|
|
86
|
+
const result = await createMessageLog.execute({
|
|
87
|
+
jwtToken: 'mock-jwt-token',
|
|
88
|
+
incomingData: mockIncomingData
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Assert
|
|
92
|
+
expect(result).toEqual({
|
|
93
|
+
success: true,
|
|
94
|
+
data: {
|
|
95
|
+
logIds: ['crm-msg-log-123'],
|
|
96
|
+
message: 'Message logs created successfully'
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
expect(jwt.decodeJwt).toHaveBeenCalledWith('mock-jwt-token');
|
|
100
|
+
expect(logCore.createMessageLog).toHaveBeenCalledWith({
|
|
101
|
+
platform: 'testCRM',
|
|
102
|
+
userId: 'user-123',
|
|
103
|
+
incomingData: expect.objectContaining({
|
|
104
|
+
contactId: 'contact-123',
|
|
105
|
+
contactName: 'John Doe',
|
|
106
|
+
logInfo: mockIncomingData.conversation
|
|
107
|
+
})
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('should create message log with multiple messages', async () => {
|
|
112
|
+
// Arrange
|
|
113
|
+
const mockIncomingData = {
|
|
114
|
+
conversation: {
|
|
115
|
+
conversationId: 'conv-456',
|
|
116
|
+
conversationLogId: 'conv-log-456',
|
|
117
|
+
type: 'SMS',
|
|
118
|
+
messages: [
|
|
119
|
+
{
|
|
120
|
+
id: 'msg-456-1',
|
|
121
|
+
conversationId: 'conv-456',
|
|
122
|
+
phoneNumber: '+1234567890',
|
|
123
|
+
direction: 'Outbound',
|
|
124
|
+
from: { phoneNumber: '+0987654321' },
|
|
125
|
+
to: [{ phoneNumber: '+1234567890' }]
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: 'msg-456-2',
|
|
129
|
+
conversationId: 'conv-456',
|
|
130
|
+
phoneNumber: '+1234567890',
|
|
131
|
+
direction: 'Inbound',
|
|
132
|
+
from: { phoneNumber: '+1234567890' },
|
|
133
|
+
to: [{ phoneNumber: '+0987654321' }]
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
correspondents: [
|
|
137
|
+
{ phoneNumber: '+1234567890' }
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
contactId: 'contact-456',
|
|
141
|
+
contactName: 'Jane Smith'
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
jwt.decodeJwt.mockReturnValue({
|
|
145
|
+
id: 'user-123',
|
|
146
|
+
platform: 'testCRM'
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const mockConnector = {
|
|
150
|
+
createMessageLog: jest.fn()
|
|
151
|
+
};
|
|
152
|
+
connectorRegistry.getConnector.mockReturnValue(mockConnector);
|
|
153
|
+
|
|
154
|
+
logCore.createMessageLog.mockResolvedValue({
|
|
155
|
+
successful: true,
|
|
156
|
+
logIds: ['crm-msg-log-456-1', 'crm-msg-log-456-2']
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Act
|
|
160
|
+
const result = await createMessageLog.execute({
|
|
161
|
+
jwtToken: 'mock-jwt-token',
|
|
162
|
+
incomingData: mockIncomingData
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// Assert
|
|
166
|
+
expect(result.success).toBe(true);
|
|
167
|
+
expect(result.data.logIds).toHaveLength(2);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test('should create message log with attachments', async () => {
|
|
171
|
+
// Arrange
|
|
172
|
+
const mockIncomingData = {
|
|
173
|
+
conversation: {
|
|
174
|
+
conversationId: 'conv-789',
|
|
175
|
+
conversationLogId: 'conv-log-789',
|
|
176
|
+
type: 'MMS',
|
|
177
|
+
messages: [
|
|
178
|
+
{
|
|
179
|
+
id: 'msg-789',
|
|
180
|
+
conversationId: 'conv-789',
|
|
181
|
+
phoneNumber: '+1234567890',
|
|
182
|
+
direction: 'Inbound',
|
|
183
|
+
from: { phoneNumber: '+1234567890' },
|
|
184
|
+
to: [{ phoneNumber: '+0987654321' }],
|
|
185
|
+
attachments: [
|
|
186
|
+
{
|
|
187
|
+
type: 'image',
|
|
188
|
+
link: 'https://example.com/image.jpg',
|
|
189
|
+
contentType: 'image/jpeg'
|
|
190
|
+
}
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
],
|
|
194
|
+
correspondents: [
|
|
195
|
+
{ phoneNumber: '+1234567890' }
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
contactId: 'contact-789',
|
|
199
|
+
contactName: 'Bob Johnson'
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
jwt.decodeJwt.mockReturnValue({
|
|
203
|
+
id: 'user-123',
|
|
204
|
+
platform: 'testCRM'
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const mockConnector = {
|
|
208
|
+
createMessageLog: jest.fn()
|
|
209
|
+
};
|
|
210
|
+
connectorRegistry.getConnector.mockReturnValue(mockConnector);
|
|
211
|
+
|
|
212
|
+
logCore.createMessageLog.mockResolvedValue({
|
|
213
|
+
successful: true,
|
|
214
|
+
logIds: ['crm-msg-log-789']
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// Act
|
|
218
|
+
const result = await createMessageLog.execute({
|
|
219
|
+
jwtToken: 'mock-jwt-token',
|
|
220
|
+
incomingData: mockIncomingData
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// Assert
|
|
224
|
+
expect(result.success).toBe(true);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test('should create fax message log', async () => {
|
|
228
|
+
// Arrange
|
|
229
|
+
const mockIncomingData = {
|
|
230
|
+
conversation: {
|
|
231
|
+
conversationId: 'conv-fax',
|
|
232
|
+
conversationLogId: 'conv-log-fax',
|
|
233
|
+
type: 'Fax',
|
|
234
|
+
messages: [
|
|
235
|
+
{
|
|
236
|
+
id: 'msg-fax',
|
|
237
|
+
conversationId: 'conv-fax',
|
|
238
|
+
phoneNumber: '+1234567890',
|
|
239
|
+
direction: 'Inbound',
|
|
240
|
+
messageStatus: 'Received',
|
|
241
|
+
faxPageCount: 5,
|
|
242
|
+
from: { phoneNumber: '+1234567890' },
|
|
243
|
+
to: [{ phoneNumber: '+0987654321' }]
|
|
244
|
+
}
|
|
245
|
+
],
|
|
246
|
+
correspondents: [
|
|
247
|
+
{ phoneNumber: '+1234567890' }
|
|
248
|
+
]
|
|
249
|
+
},
|
|
250
|
+
contactId: 'contact-fax',
|
|
251
|
+
contactName: 'Fax Sender'
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
jwt.decodeJwt.mockReturnValue({
|
|
255
|
+
id: 'user-123',
|
|
256
|
+
platform: 'testCRM'
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
const mockConnector = {
|
|
260
|
+
createMessageLog: jest.fn()
|
|
261
|
+
};
|
|
262
|
+
connectorRegistry.getConnector.mockReturnValue(mockConnector);
|
|
263
|
+
|
|
264
|
+
logCore.createMessageLog.mockResolvedValue({
|
|
265
|
+
successful: true,
|
|
266
|
+
logIds: ['crm-msg-log-fax']
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// Act
|
|
270
|
+
const result = await createMessageLog.execute({
|
|
271
|
+
jwtToken: 'mock-jwt-token',
|
|
272
|
+
incomingData: mockIncomingData
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// Assert
|
|
276
|
+
expect(result.success).toBe(true);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
test('should create message log with additional submission', async () => {
|
|
280
|
+
// Arrange
|
|
281
|
+
const mockIncomingData = {
|
|
282
|
+
conversation: {
|
|
283
|
+
conversationId: 'conv-submit',
|
|
284
|
+
conversationLogId: 'conv-log-submit',
|
|
285
|
+
messages: [
|
|
286
|
+
{
|
|
287
|
+
id: 'msg-submit',
|
|
288
|
+
conversationId: 'conv-submit',
|
|
289
|
+
phoneNumber: '+1234567890',
|
|
290
|
+
direction: 'Inbound',
|
|
291
|
+
from: { phoneNumber: '+1234567890' },
|
|
292
|
+
to: [{ phoneNumber: '+0987654321' }]
|
|
293
|
+
}
|
|
294
|
+
],
|
|
295
|
+
correspondents: [
|
|
296
|
+
{ phoneNumber: '+1234567890' }
|
|
297
|
+
]
|
|
298
|
+
},
|
|
299
|
+
contactId: 'contact-submit',
|
|
300
|
+
contactName: 'Test User',
|
|
301
|
+
additionalSubmission: {
|
|
302
|
+
isAssignedToUser: true
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
jwt.decodeJwt.mockReturnValue({
|
|
307
|
+
id: 'user-123',
|
|
308
|
+
platform: 'testCRM'
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const mockConnector = {
|
|
312
|
+
createMessageLog: jest.fn()
|
|
313
|
+
};
|
|
314
|
+
connectorRegistry.getConnector.mockReturnValue(mockConnector);
|
|
315
|
+
|
|
316
|
+
logCore.createMessageLog.mockResolvedValue({
|
|
317
|
+
successful: true,
|
|
318
|
+
logIds: ['crm-msg-log-submit']
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Act
|
|
322
|
+
const result = await createMessageLog.execute({
|
|
323
|
+
jwtToken: 'mock-jwt-token',
|
|
324
|
+
incomingData: mockIncomingData
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
// Assert
|
|
328
|
+
expect(result.success).toBe(true);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
test('should handle logInfo alias for conversation', async () => {
|
|
332
|
+
// Arrange
|
|
333
|
+
const mockIncomingData = {
|
|
334
|
+
logInfo: {
|
|
335
|
+
conversationId: 'conv-alias',
|
|
336
|
+
conversationLogId: 'conv-log-alias',
|
|
337
|
+
messages: [
|
|
338
|
+
{
|
|
339
|
+
id: 'msg-alias',
|
|
340
|
+
conversationId: 'conv-alias',
|
|
341
|
+
phoneNumber: '+1234567890',
|
|
342
|
+
direction: 'Inbound',
|
|
343
|
+
from: { phoneNumber: '+1234567890' },
|
|
344
|
+
to: [{ phoneNumber: '+0987654321' }]
|
|
345
|
+
}
|
|
346
|
+
],
|
|
347
|
+
correspondents: [
|
|
348
|
+
{ phoneNumber: '+1234567890' }
|
|
349
|
+
]
|
|
350
|
+
},
|
|
351
|
+
contactId: 'contact-alias',
|
|
352
|
+
contactName: 'Alias Test'
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
jwt.decodeJwt.mockReturnValue({
|
|
356
|
+
id: 'user-123',
|
|
357
|
+
platform: 'testCRM'
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
const mockConnector = {
|
|
361
|
+
createMessageLog: jest.fn()
|
|
362
|
+
};
|
|
363
|
+
connectorRegistry.getConnector.mockReturnValue(mockConnector);
|
|
364
|
+
|
|
365
|
+
logCore.createMessageLog.mockResolvedValue({
|
|
366
|
+
successful: true,
|
|
367
|
+
logIds: ['crm-msg-log-alias']
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
// Act
|
|
371
|
+
const result = await createMessageLog.execute({
|
|
372
|
+
jwtToken: 'mock-jwt-token',
|
|
373
|
+
incomingData: mockIncomingData
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
// Assert
|
|
377
|
+
expect(result.success).toBe(true);
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
test('should return error when jwtToken is missing', async () => {
|
|
381
|
+
// Act
|
|
382
|
+
const result = await createMessageLog.execute({
|
|
383
|
+
incomingData: { conversation: {}, contactId: 'test', contactName: 'Test' }
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// Assert
|
|
387
|
+
expect(result.success).toBe(false);
|
|
388
|
+
expect(result.error).toContain('authorize CRM platform');
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test('should return error when incomingData is missing', async () => {
|
|
392
|
+
// Act
|
|
393
|
+
const result = await createMessageLog.execute({
|
|
394
|
+
jwtToken: 'mock-jwt-token'
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
// Assert
|
|
398
|
+
expect(result.success).toBe(false);
|
|
399
|
+
expect(result.error).toContain('Incoming data must be provided');
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
test('should return error when JWT is invalid', async () => {
|
|
403
|
+
// Arrange
|
|
404
|
+
const mockIncomingData = {
|
|
405
|
+
conversation: {
|
|
406
|
+
conversationLogId: 'conv-123',
|
|
407
|
+
messages: [],
|
|
408
|
+
correspondents: []
|
|
409
|
+
},
|
|
410
|
+
contactId: 'contact-123',
|
|
411
|
+
contactName: 'Test'
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
jwt.decodeJwt.mockReturnValue({
|
|
415
|
+
platform: 'testCRM'
|
|
416
|
+
// id is missing
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
// Act
|
|
420
|
+
const result = await createMessageLog.execute({
|
|
421
|
+
jwtToken: 'invalid-token',
|
|
422
|
+
incomingData: mockIncomingData
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// Assert
|
|
426
|
+
expect(result.success).toBe(false);
|
|
427
|
+
expect(result.error).toContain('Invalid JWT token');
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
test('should return error when platform connector not found', async () => {
|
|
431
|
+
// Arrange
|
|
432
|
+
const mockIncomingData = {
|
|
433
|
+
conversation: {
|
|
434
|
+
conversationLogId: 'conv-123',
|
|
435
|
+
messages: [],
|
|
436
|
+
correspondents: []
|
|
437
|
+
},
|
|
438
|
+
contactId: 'contact-123',
|
|
439
|
+
contactName: 'Test'
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
jwt.decodeJwt.mockReturnValue({
|
|
443
|
+
id: 'user-123',
|
|
444
|
+
platform: 'unknownCRM'
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
connectorRegistry.getConnector.mockReturnValue(null);
|
|
448
|
+
|
|
449
|
+
// Act
|
|
450
|
+
const result = await createMessageLog.execute({
|
|
451
|
+
jwtToken: 'mock-jwt-token',
|
|
452
|
+
incomingData: mockIncomingData
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
// Assert
|
|
456
|
+
expect(result.success).toBe(false);
|
|
457
|
+
expect(result.error).toContain('Platform connector not found');
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
test('should return error when createMessageLog is not implemented', async () => {
|
|
461
|
+
// Arrange
|
|
462
|
+
const mockIncomingData = {
|
|
463
|
+
conversation: {
|
|
464
|
+
conversationLogId: 'conv-123',
|
|
465
|
+
messages: [],
|
|
466
|
+
correspondents: []
|
|
467
|
+
},
|
|
468
|
+
contactId: 'contact-123',
|
|
469
|
+
contactName: 'Test'
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
jwt.decodeJwt.mockReturnValue({
|
|
473
|
+
id: 'user-123',
|
|
474
|
+
platform: 'testCRM'
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
const mockConnector = {}; // No createMessageLog method
|
|
478
|
+
connectorRegistry.getConnector.mockReturnValue(mockConnector);
|
|
479
|
+
|
|
480
|
+
// Act
|
|
481
|
+
const result = await createMessageLog.execute({
|
|
482
|
+
jwtToken: 'mock-jwt-token',
|
|
483
|
+
incomingData: mockIncomingData
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
// Assert
|
|
487
|
+
expect(result.success).toBe(false);
|
|
488
|
+
expect(result.error).toContain('not implemented');
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
test('should return error when creation fails', async () => {
|
|
492
|
+
// Arrange
|
|
493
|
+
const mockIncomingData = {
|
|
494
|
+
conversation: {
|
|
495
|
+
conversationId: 'conv-fail',
|
|
496
|
+
conversationLogId: 'conv-log-fail',
|
|
497
|
+
messages: [
|
|
498
|
+
{
|
|
499
|
+
id: 'msg-fail',
|
|
500
|
+
conversationId: 'conv-fail',
|
|
501
|
+
phoneNumber: '+1234567890',
|
|
502
|
+
direction: 'Inbound',
|
|
503
|
+
from: { phoneNumber: '+1234567890' },
|
|
504
|
+
to: [{ phoneNumber: '+0987654321' }]
|
|
505
|
+
}
|
|
506
|
+
],
|
|
507
|
+
correspondents: [
|
|
508
|
+
{ phoneNumber: '+1234567890' }
|
|
509
|
+
]
|
|
510
|
+
},
|
|
511
|
+
contactId: 'contact-fail',
|
|
512
|
+
contactName: 'Fail Test'
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
jwt.decodeJwt.mockReturnValue({
|
|
516
|
+
id: 'user-123',
|
|
517
|
+
platform: 'testCRM'
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
const mockConnector = {
|
|
521
|
+
createMessageLog: jest.fn()
|
|
522
|
+
};
|
|
523
|
+
connectorRegistry.getConnector.mockReturnValue(mockConnector);
|
|
524
|
+
|
|
525
|
+
logCore.createMessageLog.mockResolvedValue({
|
|
526
|
+
successful: false,
|
|
527
|
+
returnMessage: { message: 'Failed to create message logs in CRM' }
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
// Act
|
|
531
|
+
const result = await createMessageLog.execute({
|
|
532
|
+
jwtToken: 'mock-jwt-token',
|
|
533
|
+
incomingData: mockIncomingData
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// Assert
|
|
537
|
+
expect(result.success).toBe(false);
|
|
538
|
+
expect(result.error).toBe('Failed to create message logs in CRM');
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
test('should handle unexpected errors gracefully', async () => {
|
|
542
|
+
// Arrange
|
|
543
|
+
const mockIncomingData = {
|
|
544
|
+
conversation: {
|
|
545
|
+
conversationLogId: 'conv-error',
|
|
546
|
+
messages: [],
|
|
547
|
+
correspondents: []
|
|
548
|
+
},
|
|
549
|
+
contactId: 'contact-error',
|
|
550
|
+
contactName: 'Error Test'
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
jwt.decodeJwt.mockReturnValue({
|
|
554
|
+
id: 'user-123',
|
|
555
|
+
platform: 'testCRM'
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
const mockConnector = {
|
|
559
|
+
createMessageLog: jest.fn()
|
|
560
|
+
};
|
|
561
|
+
connectorRegistry.getConnector.mockReturnValue(mockConnector);
|
|
562
|
+
|
|
563
|
+
logCore.createMessageLog.mockRejectedValue(
|
|
564
|
+
new Error('Network timeout')
|
|
565
|
+
);
|
|
566
|
+
|
|
567
|
+
// Act
|
|
568
|
+
const result = await createMessageLog.execute({
|
|
569
|
+
jwtToken: 'mock-jwt-token',
|
|
570
|
+
incomingData: mockIncomingData
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// Assert
|
|
574
|
+
expect(result.success).toBe(false);
|
|
575
|
+
expect(result.error).toBe('Network timeout');
|
|
576
|
+
expect(result.errorDetails).toBeDefined();
|
|
577
|
+
});
|
|
578
|
+
});
|
|
579
|
+
});
|
|
580
|
+
|