@webex/contact-center 3.9.0 → 3.10.0-multi-llms.1
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/dist/cc.js +207 -47
- package/dist/cc.js.map +1 -1
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/logger-proxy.js +24 -1
- package/dist/logger-proxy.js.map +1 -1
- package/dist/metrics/MetricsManager.js +1 -1
- package/dist/metrics/MetricsManager.js.map +1 -1
- package/dist/metrics/behavioral-events.js +89 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +32 -2
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/AddressBook.js +271 -0
- package/dist/services/AddressBook.js.map +1 -0
- package/dist/services/EntryPoint.js +227 -0
- package/dist/services/EntryPoint.js.map +1 -0
- package/dist/services/Queue.js +261 -0
- package/dist/services/Queue.js.map +1 -0
- package/dist/services/config/constants.js +36 -2
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/index.js +29 -21
- package/dist/services/config/index.js.map +1 -1
- package/dist/services/config/types.js +33 -1
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/core/GlobalTypes.js.map +1 -1
- package/dist/services/core/Utils.js +181 -2
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/core/aqm-reqs.js +0 -4
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/constants.js +17 -1
- package/dist/services/core/constants.js.map +1 -1
- package/dist/services/core/websocket/WebSocketManager.js +0 -4
- package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
- package/dist/services/task/TaskManager.js +151 -7
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +104 -0
- package/dist/services/task/TaskUtils.js.map +1 -0
- package/dist/services/task/constants.js +26 -1
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/contact.js +86 -0
- package/dist/services/task/contact.js.map +1 -1
- package/dist/services/task/index.js +428 -91
- package/dist/services/task/index.js.map +1 -1
- package/dist/services/task/types.js +12 -0
- package/dist/services/task/types.js.map +1 -1
- package/dist/types/cc.d.ts +121 -35
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/index.d.ts +4 -3
- package/dist/types/metrics/constants.d.ts +25 -1
- package/dist/types/services/AddressBook.d.ts +74 -0
- package/dist/types/services/EntryPoint.d.ts +67 -0
- package/dist/types/services/Queue.d.ts +76 -0
- package/dist/types/services/config/constants.d.ts +35 -1
- package/dist/types/services/config/index.d.ts +6 -9
- package/dist/types/services/config/types.d.ts +79 -58
- package/dist/types/services/core/GlobalTypes.d.ts +25 -0
- package/dist/types/services/core/Utils.d.ts +55 -1
- package/dist/types/services/core/constants.d.ts +14 -0
- package/dist/types/services/task/TaskUtils.d.ts +42 -0
- package/dist/types/services/task/constants.d.ts +23 -0
- package/dist/types/services/task/contact.d.ts +10 -0
- package/dist/types/services/task/index.d.ts +85 -4
- package/dist/types/services/task/types.d.ts +245 -21
- package/dist/types/types.d.ts +162 -0
- package/dist/types/utils/PageCache.d.ts +173 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/PageCache.js +192 -0
- package/dist/utils/PageCache.js.map +1 -0
- package/dist/webex.js +1 -1
- package/package.json +10 -9
- package/src/cc.ts +232 -52
- package/src/constants.ts +1 -0
- package/src/index.ts +17 -2
- package/src/logger-proxy.ts +24 -1
- package/src/metrics/MetricsManager.ts +1 -1
- package/src/metrics/behavioral-events.ts +94 -0
- package/src/metrics/constants.ts +37 -1
- package/src/services/AddressBook.ts +291 -0
- package/src/services/EntryPoint.ts +241 -0
- package/src/services/Queue.ts +277 -0
- package/src/services/config/constants.ts +42 -2
- package/src/services/config/index.ts +30 -30
- package/src/services/config/types.ts +59 -58
- package/src/services/core/GlobalTypes.ts +27 -0
- package/src/services/core/Utils.ts +215 -1
- package/src/services/core/aqm-reqs.ts +0 -5
- package/src/services/core/constants.ts +16 -0
- package/src/services/core/websocket/WebSocketManager.ts +0 -4
- package/src/services/task/TaskManager.ts +182 -9
- package/src/services/task/TaskUtils.ts +113 -0
- package/src/services/task/constants.ts +25 -0
- package/src/services/task/contact.ts +80 -0
- package/src/services/task/index.ts +497 -71
- package/src/services/task/types.ts +264 -20
- package/src/types.ts +180 -0
- package/src/utils/PageCache.ts +252 -0
- package/test/unit/spec/cc.ts +282 -85
- package/test/unit/spec/metrics/MetricsManager.ts +0 -1
- package/test/unit/spec/metrics/behavioral-events.ts +42 -0
- package/test/unit/spec/services/AddressBook.ts +332 -0
- package/test/unit/spec/services/EntryPoint.ts +259 -0
- package/test/unit/spec/services/Queue.ts +323 -0
- package/test/unit/spec/services/config/index.ts +279 -65
- package/test/unit/spec/services/core/Utils.ts +282 -1
- package/test/unit/spec/services/core/aqm-reqs.ts +1 -3
- package/test/unit/spec/services/core/websocket/WebSocketManager.ts +0 -4
- package/test/unit/spec/services/task/TaskManager.ts +760 -2
- package/test/unit/spec/services/task/TaskUtils.ts +131 -0
- package/test/unit/spec/services/task/contact.ts +31 -1
- package/test/unit/spec/services/task/index.ts +873 -163
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -479,6 +479,73 @@ describe('TaskManager', () => {
|
|
|
479
479
|
);
|
|
480
480
|
});
|
|
481
481
|
|
|
482
|
+
it('should set isConferenceInProgress correctly when creating task via AGENT_CONTACT with conference in progress', () => {
|
|
483
|
+
const testAgentId = '723a8ffb-a26e-496d-b14a-ff44fb83b64f';
|
|
484
|
+
taskManager.setAgentId(testAgentId);
|
|
485
|
+
taskManager.taskCollection = [];
|
|
486
|
+
|
|
487
|
+
const payload = {
|
|
488
|
+
data: {
|
|
489
|
+
...initalPayload.data,
|
|
490
|
+
type: CC_EVENTS.AGENT_CONTACT,
|
|
491
|
+
interaction: {
|
|
492
|
+
mediaType: 'telephony',
|
|
493
|
+
state: 'conference',
|
|
494
|
+
participants: {
|
|
495
|
+
[testAgentId]: { pType: 'Agent', hasLeft: false },
|
|
496
|
+
'agent-2': { pType: 'Agent', hasLeft: false },
|
|
497
|
+
'customer-1': { pType: 'Customer', hasLeft: false },
|
|
498
|
+
},
|
|
499
|
+
media: {
|
|
500
|
+
[taskId]: {
|
|
501
|
+
mType: 'mainCall',
|
|
502
|
+
participants: [testAgentId, 'agent-2', 'customer-1'],
|
|
503
|
+
},
|
|
504
|
+
},
|
|
505
|
+
},
|
|
506
|
+
},
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
510
|
+
|
|
511
|
+
const createdTask = taskManager.getTask(taskId);
|
|
512
|
+
expect(createdTask).toBeDefined();
|
|
513
|
+
expect(createdTask.data.isConferenceInProgress).toBe(true);
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
it('should set isConferenceInProgress to false when creating task via AGENT_CONTACT with only one agent', () => {
|
|
517
|
+
const testAgentId = '723a8ffb-a26e-496d-b14a-ff44fb83b64f';
|
|
518
|
+
taskManager.setAgentId(testAgentId);
|
|
519
|
+
taskManager.taskCollection = [];
|
|
520
|
+
|
|
521
|
+
const payload = {
|
|
522
|
+
data: {
|
|
523
|
+
...initalPayload.data,
|
|
524
|
+
type: CC_EVENTS.AGENT_CONTACT,
|
|
525
|
+
interaction: {
|
|
526
|
+
mediaType: 'telephony',
|
|
527
|
+
state: 'connected',
|
|
528
|
+
participants: {
|
|
529
|
+
[testAgentId]: { pType: 'Agent', hasLeft: false },
|
|
530
|
+
'customer-1': { pType: 'Customer', hasLeft: false },
|
|
531
|
+
},
|
|
532
|
+
media: {
|
|
533
|
+
[taskId]: {
|
|
534
|
+
mType: 'mainCall',
|
|
535
|
+
participants: [testAgentId, 'customer-1'],
|
|
536
|
+
},
|
|
537
|
+
},
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
543
|
+
|
|
544
|
+
const createdTask = taskManager.getTask(taskId);
|
|
545
|
+
expect(createdTask).toBeDefined();
|
|
546
|
+
expect(createdTask.data.isConferenceInProgress).toBe(false);
|
|
547
|
+
});
|
|
548
|
+
|
|
482
549
|
it('should emit TASK_END event on AGENT_WRAPUP event', () => {
|
|
483
550
|
webSocketManagerMock.emit('message', JSON.stringify(initalPayload));
|
|
484
551
|
|
|
@@ -658,6 +725,13 @@ describe('TaskManager', () => {
|
|
|
658
725
|
});
|
|
659
726
|
|
|
660
727
|
it('should emit TASK_CONSULT_ACCEPTED event on AGENT_CONSULTING event', () => {
|
|
728
|
+
const initialConsultingPayload = {
|
|
729
|
+
data: {
|
|
730
|
+
...initalPayload.data,
|
|
731
|
+
type: CC_EVENTS.AGENT_OFFER_CONSULT,
|
|
732
|
+
},
|
|
733
|
+
};
|
|
734
|
+
|
|
661
735
|
const consultingPayload = {
|
|
662
736
|
data: {
|
|
663
737
|
...initalPayload.data,
|
|
@@ -672,8 +746,8 @@ describe('TaskManager', () => {
|
|
|
672
746
|
});
|
|
673
747
|
|
|
674
748
|
const taskEmitSpy = jest.spyOn(taskManager.getTask(taskId), 'emit');
|
|
749
|
+
webSocketManagerMock.emit('message', JSON.stringify(initialConsultingPayload));
|
|
675
750
|
webSocketManagerMock.emit('message', JSON.stringify(consultingPayload));
|
|
676
|
-
expect(taskManager.getTask(taskId).updateTaskData).toHaveBeenCalledWith(consultingPayload.data);
|
|
677
751
|
expect(taskManager.getTask(taskId).data.isConsulted).toBe(true);
|
|
678
752
|
expect(taskEmitSpy).toHaveBeenCalledWith(
|
|
679
753
|
TASK_EVENTS.TASK_CONSULT_ACCEPTED,
|
|
@@ -1346,6 +1420,690 @@ describe('TaskManager', () => {
|
|
|
1346
1420
|
expect(spy).toHaveBeenCalledWith(taskEvent, task);
|
|
1347
1421
|
});
|
|
1348
1422
|
});
|
|
1349
|
-
});
|
|
1423
|
+
});
|
|
1424
|
+
|
|
1425
|
+
describe('Conference event handling', () => {
|
|
1426
|
+
let task;
|
|
1427
|
+
const agentId = '723a8ffb-a26e-496d-b14a-ff44fb83b64f';
|
|
1428
|
+
|
|
1429
|
+
beforeEach(() => {
|
|
1430
|
+
// Set the agentId on taskManager before tests run
|
|
1431
|
+
taskManager.setAgentId(agentId);
|
|
1432
|
+
|
|
1433
|
+
task = {
|
|
1434
|
+
data: { interactionId: taskId },
|
|
1435
|
+
emit: jest.fn(),
|
|
1436
|
+
updateTaskData: jest.fn().mockImplementation((updatedData) => {
|
|
1437
|
+
// Mock the updateTaskData method to actually update task.data
|
|
1438
|
+
task.data = { ...task.data, ...updatedData };
|
|
1439
|
+
return task;
|
|
1440
|
+
}),
|
|
1441
|
+
};
|
|
1442
|
+
taskManager.taskCollection[taskId] = task;
|
|
1443
|
+
});
|
|
1444
|
+
|
|
1445
|
+
it('should handle AGENT_CONSULT_CONFERENCED event', () => {
|
|
1446
|
+
const payload = {
|
|
1447
|
+
data: {
|
|
1448
|
+
type: CC_EVENTS.AGENT_CONSULT_CONFERENCED,
|
|
1449
|
+
interactionId: taskId,
|
|
1450
|
+
isConferencing: true,
|
|
1451
|
+
},
|
|
1452
|
+
};
|
|
1453
|
+
|
|
1454
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1455
|
+
|
|
1456
|
+
expect(task.data.isConferencing).toBe(true);
|
|
1457
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_CONFERENCE_STARTED, task);
|
|
1458
|
+
});
|
|
1459
|
+
|
|
1460
|
+
it('should handle AGENT_CONSULT_CONFERENCING event', () => {
|
|
1461
|
+
const payload = {
|
|
1462
|
+
data: {
|
|
1463
|
+
type: CC_EVENTS.AGENT_CONSULT_CONFERENCING,
|
|
1464
|
+
interactionId: taskId,
|
|
1465
|
+
isConferencing: true,
|
|
1466
|
+
},
|
|
1467
|
+
};
|
|
1468
|
+
|
|
1469
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1470
|
+
|
|
1471
|
+
expect(task.data.isConferencing).toBe(true);
|
|
1472
|
+
// No task event emission for conferencing - only for conferenced (completed)
|
|
1473
|
+
expect(task.emit).not.toHaveBeenCalledWith(TASK_EVENTS.TASK_CONFERENCE_STARTED, task);
|
|
1474
|
+
});
|
|
1475
|
+
|
|
1476
|
+
it('should handle AGENT_CONSULT_CONFERENCE_FAILED event', () => {
|
|
1477
|
+
const payload = {
|
|
1478
|
+
data: {
|
|
1479
|
+
type: CC_EVENTS.AGENT_CONSULT_CONFERENCE_FAILED,
|
|
1480
|
+
interactionId: taskId,
|
|
1481
|
+
reason: 'Network error',
|
|
1482
|
+
},
|
|
1483
|
+
};
|
|
1484
|
+
|
|
1485
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1486
|
+
|
|
1487
|
+
expect(task.data.reason).toBe('Network error');
|
|
1488
|
+
// No event emission expected for failure - handled by contact method promise rejection
|
|
1489
|
+
});
|
|
1490
|
+
|
|
1491
|
+
it('should handle PARTICIPANT_JOINED_CONFERENCE event', () => {
|
|
1492
|
+
const payload = {
|
|
1493
|
+
data: {
|
|
1494
|
+
type: CC_EVENTS.PARTICIPANT_JOINED_CONFERENCE,
|
|
1495
|
+
interactionId: taskId,
|
|
1496
|
+
participantId: 'new-participant-123',
|
|
1497
|
+
participantType: 'agent',
|
|
1498
|
+
interaction: {
|
|
1499
|
+
participants: {
|
|
1500
|
+
[agentId]: { pType: 'Agent', hasLeft: false },
|
|
1501
|
+
'new-participant-123': { pType: 'Agent', hasLeft: false },
|
|
1502
|
+
},
|
|
1503
|
+
media: {
|
|
1504
|
+
[taskId]: {
|
|
1505
|
+
mType: 'mainCall',
|
|
1506
|
+
participants: [agentId, 'new-participant-123'],
|
|
1507
|
+
},
|
|
1508
|
+
},
|
|
1509
|
+
},
|
|
1510
|
+
},
|
|
1511
|
+
};
|
|
1512
|
+
|
|
1513
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1514
|
+
|
|
1515
|
+
expect(task.data.participantId).toBe('new-participant-123');
|
|
1516
|
+
expect(task.data.participantType).toBe('agent');
|
|
1517
|
+
// No specific task event emission for participant joined - just data update
|
|
1518
|
+
});
|
|
1519
|
+
|
|
1520
|
+
it('should call updateTaskData only once for PARTICIPANT_JOINED_CONFERENCE with pre-calculated isConferenceInProgress', () => {
|
|
1521
|
+
const payload = {
|
|
1522
|
+
data: {
|
|
1523
|
+
type: CC_EVENTS.PARTICIPANT_JOINED_CONFERENCE,
|
|
1524
|
+
interactionId: taskId,
|
|
1525
|
+
participantId: 'new-agent-789',
|
|
1526
|
+
interaction: {
|
|
1527
|
+
participants: {
|
|
1528
|
+
[agentId]: { pType: 'Agent', hasLeft: false },
|
|
1529
|
+
'agent-2': { pType: 'Agent', hasLeft: false },
|
|
1530
|
+
'new-agent-789': { pType: 'Agent', hasLeft: false },
|
|
1531
|
+
'customer-1': { pType: 'Customer', hasLeft: false },
|
|
1532
|
+
},
|
|
1533
|
+
media: {
|
|
1534
|
+
[taskId]: {
|
|
1535
|
+
mType: 'mainCall',
|
|
1536
|
+
participants: [agentId, 'agent-2', 'new-agent-789', 'customer-1'],
|
|
1537
|
+
},
|
|
1538
|
+
},
|
|
1539
|
+
},
|
|
1540
|
+
},
|
|
1541
|
+
};
|
|
1542
|
+
|
|
1543
|
+
const updateTaskDataSpy = jest.spyOn(task, 'updateTaskData');
|
|
1544
|
+
|
|
1545
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1546
|
+
|
|
1547
|
+
// Verify updateTaskData was called exactly once
|
|
1548
|
+
expect(updateTaskDataSpy).toHaveBeenCalledTimes(1);
|
|
1549
|
+
|
|
1550
|
+
// Verify it was called with isConferenceInProgress already calculated
|
|
1551
|
+
expect(updateTaskDataSpy).toHaveBeenCalledWith(
|
|
1552
|
+
expect.objectContaining({
|
|
1553
|
+
participantId: 'new-agent-789',
|
|
1554
|
+
isConferenceInProgress: true, // 3 active agents
|
|
1555
|
+
})
|
|
1556
|
+
);
|
|
1557
|
+
|
|
1558
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_PARTICIPANT_JOINED, task);
|
|
1559
|
+
});
|
|
1560
|
+
|
|
1561
|
+
describe('PARTICIPANT_LEFT_CONFERENCE event handling', () => {
|
|
1562
|
+
it('should call updateTaskData only once for PARTICIPANT_LEFT_CONFERENCE with pre-calculated isConferenceInProgress', () => {
|
|
1563
|
+
const payload = {
|
|
1564
|
+
data: {
|
|
1565
|
+
type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE,
|
|
1566
|
+
interactionId: taskId,
|
|
1567
|
+
interaction: {
|
|
1568
|
+
participants: {
|
|
1569
|
+
[agentId]: { pType: 'Agent', hasLeft: false },
|
|
1570
|
+
'agent-2': { pType: 'Agent', hasLeft: true }, // This agent left
|
|
1571
|
+
'customer-1': { pType: 'Customer', hasLeft: false },
|
|
1572
|
+
},
|
|
1573
|
+
media: {
|
|
1574
|
+
[taskId]: {
|
|
1575
|
+
mType: 'mainCall',
|
|
1576
|
+
participants: [agentId, 'customer-1'], // agent-2 removed from participants
|
|
1577
|
+
},
|
|
1578
|
+
},
|
|
1579
|
+
},
|
|
1580
|
+
},
|
|
1581
|
+
};
|
|
1582
|
+
|
|
1583
|
+
const updateTaskDataSpy = jest.spyOn(task, 'updateTaskData');
|
|
1584
|
+
|
|
1585
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1586
|
+
|
|
1587
|
+
// Verify updateTaskData was called exactly once
|
|
1588
|
+
expect(updateTaskDataSpy).toHaveBeenCalledTimes(1);
|
|
1589
|
+
|
|
1590
|
+
// Verify it was called with isConferenceInProgress already calculated
|
|
1591
|
+
expect(updateTaskDataSpy).toHaveBeenCalledWith(
|
|
1592
|
+
expect.objectContaining({
|
|
1593
|
+
isConferenceInProgress: false, // Only 1 active agent remains
|
|
1594
|
+
})
|
|
1595
|
+
);
|
|
1596
|
+
|
|
1597
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_PARTICIPANT_LEFT, task);
|
|
1598
|
+
});
|
|
1599
|
+
|
|
1600
|
+
it('should emit TASK_PARTICIPANT_LEFT event when participant leaves conference', () => {
|
|
1601
|
+
const payload = {
|
|
1602
|
+
data: {
|
|
1603
|
+
type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE,
|
|
1604
|
+
interactionId: taskId,
|
|
1605
|
+
interaction: {
|
|
1606
|
+
participants: {
|
|
1607
|
+
[agentId]: {
|
|
1608
|
+
hasLeft: false,
|
|
1609
|
+
},
|
|
1610
|
+
},
|
|
1611
|
+
},
|
|
1612
|
+
},
|
|
1613
|
+
};
|
|
1614
|
+
|
|
1615
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1616
|
+
|
|
1617
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_PARTICIPANT_LEFT, task);
|
|
1618
|
+
});
|
|
1619
|
+
|
|
1620
|
+
it('should NOT remove task when agent is still in interaction', () => {
|
|
1621
|
+
const payload = {
|
|
1622
|
+
data: {
|
|
1623
|
+
type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE,
|
|
1624
|
+
interactionId: taskId,
|
|
1625
|
+
interaction: {
|
|
1626
|
+
participants: {
|
|
1627
|
+
[agentId]: {
|
|
1628
|
+
hasLeft: false,
|
|
1629
|
+
},
|
|
1630
|
+
},
|
|
1631
|
+
},
|
|
1632
|
+
},
|
|
1633
|
+
};
|
|
1634
|
+
|
|
1635
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1636
|
+
|
|
1637
|
+
// Task should still exist in collection
|
|
1638
|
+
expect(taskManager.getTask(taskId)).toBeDefined();
|
|
1639
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_PARTICIPANT_LEFT, task);
|
|
1640
|
+
});
|
|
1641
|
+
|
|
1642
|
+
it('should NOT remove task when agent left but is in main interaction', () => {
|
|
1643
|
+
const payload = {
|
|
1644
|
+
data: {
|
|
1645
|
+
type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE,
|
|
1646
|
+
interactionId: taskId,
|
|
1647
|
+
interaction: {
|
|
1648
|
+
participants: {
|
|
1649
|
+
[agentId]: {
|
|
1650
|
+
hasLeft: true,
|
|
1651
|
+
},
|
|
1652
|
+
},
|
|
1653
|
+
media: {
|
|
1654
|
+
[taskId]: {
|
|
1655
|
+
mType: 'mainCall',
|
|
1656
|
+
participants: [agentId],
|
|
1657
|
+
},
|
|
1658
|
+
},
|
|
1659
|
+
},
|
|
1660
|
+
},
|
|
1661
|
+
};
|
|
1662
|
+
|
|
1663
|
+
const removeTaskSpy = jest.spyOn(taskManager, 'removeTaskFromCollection');
|
|
1664
|
+
|
|
1665
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1666
|
+
|
|
1667
|
+
// Task should still exist - not removed
|
|
1668
|
+
expect(removeTaskSpy).not.toHaveBeenCalled();
|
|
1669
|
+
expect(taskManager.getTask(taskId)).toBeDefined();
|
|
1670
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_PARTICIPANT_LEFT, task);
|
|
1671
|
+
});
|
|
1672
|
+
|
|
1673
|
+
it('should NOT remove task when agent left but is primary (owner)', () => {
|
|
1674
|
+
const payload = {
|
|
1675
|
+
data: {
|
|
1676
|
+
type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE,
|
|
1677
|
+
interactionId: taskId,
|
|
1678
|
+
interaction: {
|
|
1679
|
+
participants: {
|
|
1680
|
+
[agentId]: {
|
|
1681
|
+
hasLeft: true,
|
|
1682
|
+
},
|
|
1683
|
+
},
|
|
1684
|
+
owner: agentId,
|
|
1685
|
+
media: {
|
|
1686
|
+
[taskId]: {
|
|
1687
|
+
mType: 'consultCall',
|
|
1688
|
+
participants: ['other-agent'],
|
|
1689
|
+
},
|
|
1690
|
+
},
|
|
1691
|
+
},
|
|
1692
|
+
},
|
|
1693
|
+
};
|
|
1694
|
+
|
|
1695
|
+
const removeTaskSpy = jest.spyOn(taskManager, 'removeTaskFromCollection');
|
|
1696
|
+
|
|
1697
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1698
|
+
|
|
1699
|
+
// Task should still exist - not removed because agent is primary
|
|
1700
|
+
expect(removeTaskSpy).not.toHaveBeenCalled();
|
|
1701
|
+
expect(taskManager.getTask(taskId)).toBeDefined();
|
|
1702
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_PARTICIPANT_LEFT, task);
|
|
1703
|
+
});
|
|
1704
|
+
|
|
1705
|
+
it('should remove task when agent left and is NOT in main interaction and is NOT primary', () => {
|
|
1706
|
+
const payload = {
|
|
1707
|
+
data: {
|
|
1708
|
+
type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE,
|
|
1709
|
+
interactionId: taskId,
|
|
1710
|
+
interaction: {
|
|
1711
|
+
participants: {
|
|
1712
|
+
[agentId]: {
|
|
1713
|
+
hasLeft: true,
|
|
1714
|
+
},
|
|
1715
|
+
},
|
|
1716
|
+
owner: 'another-agent-id',
|
|
1717
|
+
media: {
|
|
1718
|
+
[taskId]: {
|
|
1719
|
+
mType: 'mainCall',
|
|
1720
|
+
participants: ['another-agent-id'],
|
|
1721
|
+
},
|
|
1722
|
+
},
|
|
1723
|
+
},
|
|
1724
|
+
},
|
|
1725
|
+
};
|
|
1726
|
+
|
|
1727
|
+
const removeTaskSpy = jest.spyOn(taskManager, 'removeTaskFromCollection');
|
|
1728
|
+
|
|
1729
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1730
|
+
|
|
1731
|
+
// Task should be removed
|
|
1732
|
+
expect(removeTaskSpy).toHaveBeenCalled();
|
|
1733
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_PARTICIPANT_LEFT, task);
|
|
1734
|
+
});
|
|
1735
|
+
|
|
1736
|
+
it('should remove task when agent is not in participants list', () => {
|
|
1737
|
+
const payload = {
|
|
1738
|
+
data: {
|
|
1739
|
+
type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE,
|
|
1740
|
+
interactionId: taskId,
|
|
1741
|
+
interaction: {
|
|
1742
|
+
participants: {
|
|
1743
|
+
'other-agent-id': {
|
|
1744
|
+
hasLeft: false,
|
|
1745
|
+
},
|
|
1746
|
+
},
|
|
1747
|
+
owner: 'another-agent-id',
|
|
1748
|
+
},
|
|
1749
|
+
},
|
|
1750
|
+
};
|
|
1751
|
+
|
|
1752
|
+
const removeTaskSpy = jest.spyOn(taskManager, 'removeTaskFromCollection');
|
|
1753
|
+
|
|
1754
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1755
|
+
|
|
1756
|
+
// Task should be removed because agent is not in participants
|
|
1757
|
+
expect(removeTaskSpy).toHaveBeenCalled();
|
|
1758
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_PARTICIPANT_LEFT, task);
|
|
1759
|
+
});
|
|
1760
|
+
|
|
1761
|
+
it('should update isConferenceInProgress based on remaining active agents', () => {
|
|
1762
|
+
const payload = {
|
|
1763
|
+
data: {
|
|
1764
|
+
type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE,
|
|
1765
|
+
interactionId: taskId,
|
|
1766
|
+
interaction: {
|
|
1767
|
+
participants: {
|
|
1768
|
+
[agentId]: {
|
|
1769
|
+
hasLeft: false,
|
|
1770
|
+
pType: 'Agent',
|
|
1771
|
+
},
|
|
1772
|
+
'agent-2': {
|
|
1773
|
+
hasLeft: false,
|
|
1774
|
+
pType: 'Agent',
|
|
1775
|
+
},
|
|
1776
|
+
'customer-1': {
|
|
1777
|
+
hasLeft: false,
|
|
1778
|
+
pType: 'Customer',
|
|
1779
|
+
},
|
|
1780
|
+
},
|
|
1781
|
+
media: {
|
|
1782
|
+
[taskId]: {
|
|
1783
|
+
mType: 'mainCall',
|
|
1784
|
+
participants: [agentId, 'agent-2', 'customer-1'],
|
|
1785
|
+
},
|
|
1786
|
+
},
|
|
1787
|
+
},
|
|
1788
|
+
},
|
|
1789
|
+
};
|
|
1790
|
+
|
|
1791
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1792
|
+
|
|
1793
|
+
// isConferenceInProgress should be true (2 active agents)
|
|
1794
|
+
expect(task.data.isConferenceInProgress).toBe(true);
|
|
1795
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_PARTICIPANT_LEFT, task);
|
|
1796
|
+
});
|
|
1797
|
+
|
|
1798
|
+
it('should set isConferenceInProgress to false when only one agent remains', () => {
|
|
1799
|
+
const payload = {
|
|
1800
|
+
data: {
|
|
1801
|
+
type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE,
|
|
1802
|
+
interactionId: taskId,
|
|
1803
|
+
interaction: {
|
|
1804
|
+
participants: {
|
|
1805
|
+
[agentId]: {
|
|
1806
|
+
hasLeft: false,
|
|
1807
|
+
pType: 'Agent',
|
|
1808
|
+
},
|
|
1809
|
+
'agent-2': {
|
|
1810
|
+
hasLeft: true,
|
|
1811
|
+
pType: 'Agent',
|
|
1812
|
+
},
|
|
1813
|
+
'customer-1': {
|
|
1814
|
+
hasLeft: false,
|
|
1815
|
+
pType: 'Customer',
|
|
1816
|
+
},
|
|
1817
|
+
},
|
|
1818
|
+
media: {
|
|
1819
|
+
[taskId]: {
|
|
1820
|
+
mType: 'mainCall',
|
|
1821
|
+
participants: [agentId, 'customer-1'],
|
|
1822
|
+
},
|
|
1823
|
+
},
|
|
1824
|
+
},
|
|
1825
|
+
},
|
|
1826
|
+
};
|
|
1827
|
+
|
|
1828
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1829
|
+
|
|
1830
|
+
// isConferenceInProgress should be false (only 1 active agent)
|
|
1831
|
+
expect(task.data.isConferenceInProgress).toBe(false);
|
|
1832
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_PARTICIPANT_LEFT, task);
|
|
1833
|
+
});
|
|
1834
|
+
|
|
1835
|
+
it('should handle participant left when no participants data exists', () => {
|
|
1836
|
+
const payload = {
|
|
1837
|
+
data: {
|
|
1838
|
+
type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE,
|
|
1839
|
+
interactionId: taskId,
|
|
1840
|
+
interaction: {},
|
|
1841
|
+
},
|
|
1842
|
+
};
|
|
1843
|
+
|
|
1844
|
+
const removeTaskSpy = jest.spyOn(taskManager, 'removeTaskFromCollection');
|
|
1845
|
+
|
|
1846
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1847
|
+
|
|
1848
|
+
// When no participants data exists, checkParticipantNotInInteraction returns true
|
|
1849
|
+
// Since agent won't be in main interaction either, task should be removed
|
|
1850
|
+
expect(removeTaskSpy).toHaveBeenCalled();
|
|
1851
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_PARTICIPANT_LEFT, task);
|
|
1852
|
+
});
|
|
1853
|
+
});
|
|
1854
|
+
|
|
1855
|
+
it('should handle PARTICIPANT_LEFT_CONFERENCE_FAILED event', () => {
|
|
1856
|
+
const payload = {
|
|
1857
|
+
data: {
|
|
1858
|
+
type: CC_EVENTS.PARTICIPANT_LEFT_CONFERENCE_FAILED,
|
|
1859
|
+
interactionId: taskId,
|
|
1860
|
+
reason: 'Exit failed',
|
|
1861
|
+
},
|
|
1862
|
+
};
|
|
1863
|
+
|
|
1864
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1865
|
+
|
|
1866
|
+
expect(task.data.reason).toBe('Exit failed');
|
|
1867
|
+
// No event emission expected for failure - handled by contact method promise rejection
|
|
1868
|
+
});
|
|
1869
|
+
|
|
1870
|
+
it('should only update task for matching interactionId', () => {
|
|
1871
|
+
const otherTaskId = 'other-task-id';
|
|
1872
|
+
const otherTask = {
|
|
1873
|
+
data: { interactionId: otherTaskId },
|
|
1874
|
+
emit: jest.fn(),
|
|
1875
|
+
};
|
|
1876
|
+
taskManager.taskCollection[otherTaskId] = otherTask;
|
|
1877
|
+
|
|
1878
|
+
const payload = {
|
|
1879
|
+
data: {
|
|
1880
|
+
type: CC_EVENTS.AGENT_CONSULT_CONFERENCED,
|
|
1881
|
+
interactionId: taskId,
|
|
1882
|
+
isConferencing: true,
|
|
1883
|
+
},
|
|
1884
|
+
};
|
|
1885
|
+
|
|
1886
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1887
|
+
|
|
1888
|
+
// Only the matching task should be updated
|
|
1889
|
+
expect(task.data.isConferencing).toBe(true);
|
|
1890
|
+
expect(task.emit).toHaveBeenCalledWith(TASK_EVENTS.TASK_CONFERENCE_STARTED, task);
|
|
1891
|
+
|
|
1892
|
+
// Other task should not be affected
|
|
1893
|
+
expect(otherTask.data.isConferencing).toBeUndefined();
|
|
1894
|
+
expect(otherTask.emit).not.toHaveBeenCalled();
|
|
1895
|
+
});
|
|
1896
|
+
});
|
|
1897
|
+
|
|
1898
|
+
describe('CONTACT_MERGED event handling', () => {
|
|
1899
|
+
let task;
|
|
1900
|
+
let taskEmitSpy;
|
|
1901
|
+
let managerEmitSpy;
|
|
1902
|
+
|
|
1903
|
+
beforeEach(() => {
|
|
1904
|
+
// Create initial task
|
|
1905
|
+
webSocketManagerMock.emit('message', JSON.stringify(initalPayload));
|
|
1906
|
+
task = taskManager.getTask(taskId);
|
|
1907
|
+
taskEmitSpy = jest.spyOn(task, 'emit');
|
|
1908
|
+
managerEmitSpy = jest.spyOn(taskManager, 'emit');
|
|
1909
|
+
});
|
|
1910
|
+
|
|
1911
|
+
it('should update existing task data and emit TASK_MERGED event when CONTACT_MERGED is received', () => {
|
|
1912
|
+
const mergedPayload = {
|
|
1913
|
+
data: {
|
|
1914
|
+
type: CC_EVENTS.CONTACT_MERGED,
|
|
1915
|
+
interactionId: taskId,
|
|
1916
|
+
agentId: taskDataMock.agentId,
|
|
1917
|
+
interaction: {
|
|
1918
|
+
...taskDataMock.interaction,
|
|
1919
|
+
state: 'merged',
|
|
1920
|
+
customField: 'updated-value',
|
|
1921
|
+
},
|
|
1922
|
+
},
|
|
1923
|
+
};
|
|
1924
|
+
|
|
1925
|
+
webSocketManagerMock.emit('message', JSON.stringify(mergedPayload));
|
|
1926
|
+
|
|
1927
|
+
const updatedTask = taskManager.getTask(taskId);
|
|
1928
|
+
expect(updatedTask).toBeDefined();
|
|
1929
|
+
expect(updatedTask.data.interaction.customField).toBe('updated-value');
|
|
1930
|
+
expect(updatedTask.data.interaction.state).toBe('merged');
|
|
1931
|
+
expect(managerEmitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_MERGED, updatedTask);
|
|
1932
|
+
});
|
|
1933
|
+
|
|
1934
|
+
it('should create new task when CONTACT_MERGED is received for non-existing task', () => {
|
|
1935
|
+
const newMergedTaskId = 'new-merged-task-id';
|
|
1936
|
+
const mergedPayload = {
|
|
1937
|
+
data: {
|
|
1938
|
+
type: CC_EVENTS.CONTACT_MERGED,
|
|
1939
|
+
interactionId: newMergedTaskId,
|
|
1940
|
+
agentId: taskDataMock.agentId,
|
|
1941
|
+
interaction: {
|
|
1942
|
+
mediaType: 'telephony',
|
|
1943
|
+
state: 'merged',
|
|
1944
|
+
participants: {
|
|
1945
|
+
[taskDataMock.agentId]: {
|
|
1946
|
+
isWrapUp: false,
|
|
1947
|
+
hasJoined: true,
|
|
1948
|
+
},
|
|
1949
|
+
},
|
|
1950
|
+
},
|
|
1951
|
+
},
|
|
1952
|
+
};
|
|
1953
|
+
|
|
1954
|
+
// Verify task doesn't exist before
|
|
1955
|
+
expect(taskManager.getTask(newMergedTaskId)).toBeUndefined();
|
|
1956
|
+
|
|
1957
|
+
webSocketManagerMock.emit('message', JSON.stringify(mergedPayload));
|
|
1958
|
+
|
|
1959
|
+
// Verify task was created
|
|
1960
|
+
const newTask = taskManager.getTask(newMergedTaskId);
|
|
1961
|
+
expect(newTask).toBeDefined();
|
|
1962
|
+
expect(newTask.data.interactionId).toBe(newMergedTaskId);
|
|
1963
|
+
expect(managerEmitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_MERGED, newTask);
|
|
1964
|
+
});
|
|
1965
|
+
|
|
1966
|
+
it('should remove child task when childInteractionId is present in CONTACT_MERGED', () => {
|
|
1967
|
+
const childTaskId = 'child-task-id';
|
|
1968
|
+
const parentTaskId = 'parent-task-id';
|
|
1969
|
+
|
|
1970
|
+
// Create child task
|
|
1971
|
+
const childPayload = {
|
|
1972
|
+
data: {
|
|
1973
|
+
type: CC_EVENTS.AGENT_CONTACT_RESERVED,
|
|
1974
|
+
interactionId: childTaskId,
|
|
1975
|
+
agentId: taskDataMock.agentId,
|
|
1976
|
+
interaction: {mediaType: 'telephony'},
|
|
1977
|
+
},
|
|
1978
|
+
};
|
|
1979
|
+
webSocketManagerMock.emit('message', JSON.stringify(childPayload));
|
|
1980
|
+
|
|
1981
|
+
// Verify child task exists
|
|
1982
|
+
expect(taskManager.getTask(childTaskId)).toBeDefined();
|
|
1983
|
+
|
|
1984
|
+
// Create parent task
|
|
1985
|
+
const parentPayload = {
|
|
1986
|
+
data: {
|
|
1987
|
+
type: CC_EVENTS.AGENT_CONTACT_RESERVED,
|
|
1988
|
+
interactionId: parentTaskId,
|
|
1989
|
+
agentId: taskDataMock.agentId,
|
|
1990
|
+
interaction: {mediaType: 'telephony'},
|
|
1991
|
+
},
|
|
1992
|
+
};
|
|
1993
|
+
webSocketManagerMock.emit('message', JSON.stringify(parentPayload));
|
|
1994
|
+
|
|
1995
|
+
// Send CONTACT_MERGED with childInteractionId
|
|
1996
|
+
const mergedPayload = {
|
|
1997
|
+
data: {
|
|
1998
|
+
type: CC_EVENTS.CONTACT_MERGED,
|
|
1999
|
+
interactionId: parentTaskId,
|
|
2000
|
+
childInteractionId: childTaskId,
|
|
2001
|
+
agentId: taskDataMock.agentId,
|
|
2002
|
+
interaction: {
|
|
2003
|
+
mediaType: 'telephony',
|
|
2004
|
+
state: 'merged',
|
|
2005
|
+
},
|
|
2006
|
+
},
|
|
2007
|
+
};
|
|
2008
|
+
|
|
2009
|
+
webSocketManagerMock.emit('message', JSON.stringify(mergedPayload));
|
|
2010
|
+
|
|
2011
|
+
// Verify child task was removed
|
|
2012
|
+
expect(taskManager.getTask(childTaskId)).toBeUndefined();
|
|
2013
|
+
|
|
2014
|
+
// Verify parent task still exists
|
|
2015
|
+
expect(taskManager.getTask(parentTaskId)).toBeDefined();
|
|
2016
|
+
|
|
2017
|
+
// Verify TASK_MERGED event was emitted
|
|
2018
|
+
expect(managerEmitSpy).toHaveBeenCalledWith(
|
|
2019
|
+
TASK_EVENTS.TASK_MERGED,
|
|
2020
|
+
expect.objectContaining({
|
|
2021
|
+
data: expect.objectContaining({
|
|
2022
|
+
interactionId: parentTaskId,
|
|
2023
|
+
}),
|
|
2024
|
+
})
|
|
2025
|
+
);
|
|
2026
|
+
});
|
|
2027
|
+
|
|
2028
|
+
it('should handle CONTACT_MERGED with EP-DN participant correctly', () => {
|
|
2029
|
+
const epdnTaskId = 'epdn-merged-task';
|
|
2030
|
+
const mergedPayload = {
|
|
2031
|
+
data: {
|
|
2032
|
+
type: CC_EVENTS.CONTACT_MERGED,
|
|
2033
|
+
interactionId: epdnTaskId,
|
|
2034
|
+
agentId: taskDataMock.agentId,
|
|
2035
|
+
interaction: {
|
|
2036
|
+
mediaType: 'telephony',
|
|
2037
|
+
state: 'merged',
|
|
2038
|
+
participants: {
|
|
2039
|
+
[taskDataMock.agentId]: {
|
|
2040
|
+
type: 'Agent',
|
|
2041
|
+
isWrapUp: false,
|
|
2042
|
+
hasJoined: true,
|
|
2043
|
+
},
|
|
2044
|
+
'epdn-participant': {
|
|
2045
|
+
type: 'EpDn',
|
|
2046
|
+
epId: 'entry-point-123',
|
|
2047
|
+
isWrapUp: false,
|
|
2048
|
+
},
|
|
2049
|
+
},
|
|
2050
|
+
},
|
|
2051
|
+
},
|
|
2052
|
+
};
|
|
2053
|
+
|
|
2054
|
+
webSocketManagerMock.emit('message', JSON.stringify(mergedPayload));
|
|
2055
|
+
|
|
2056
|
+
const mergedTask = taskManager.getTask(epdnTaskId);
|
|
2057
|
+
expect(mergedTask).toBeDefined();
|
|
2058
|
+
expect(mergedTask.data.interaction.participants['epdn-participant']).toBeDefined();
|
|
2059
|
+
expect(mergedTask.data.interaction.participants['epdn-participant'].type).toBe('EpDn');
|
|
2060
|
+
expect(managerEmitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_MERGED, mergedTask);
|
|
2061
|
+
});
|
|
2062
|
+
|
|
2063
|
+
it('should not affect other tasks when CONTACT_MERGED is received', () => {
|
|
2064
|
+
const otherTaskId = 'other-unrelated-task';
|
|
2065
|
+
const otherPayload = {
|
|
2066
|
+
data: {
|
|
2067
|
+
type: CC_EVENTS.AGENT_CONTACT_RESERVED,
|
|
2068
|
+
interactionId: otherTaskId,
|
|
2069
|
+
agentId: taskDataMock.agentId,
|
|
2070
|
+
interaction: {mediaType: 'chat'},
|
|
2071
|
+
},
|
|
2072
|
+
};
|
|
2073
|
+
webSocketManagerMock.emit('message', JSON.stringify(otherPayload));
|
|
2074
|
+
|
|
2075
|
+
const otherTask = taskManager.getTask(otherTaskId);
|
|
2076
|
+
const otherTaskEmitSpy = jest.spyOn(otherTask, 'emit');
|
|
2077
|
+
|
|
2078
|
+
// Send CONTACT_MERGED for the original task
|
|
2079
|
+
const mergedPayload = {
|
|
2080
|
+
data: {
|
|
2081
|
+
type: CC_EVENTS.CONTACT_MERGED,
|
|
2082
|
+
interactionId: taskId,
|
|
2083
|
+
agentId: taskDataMock.agentId,
|
|
2084
|
+
interaction: {
|
|
2085
|
+
mediaType: 'telephony',
|
|
2086
|
+
state: 'merged',
|
|
2087
|
+
},
|
|
2088
|
+
},
|
|
2089
|
+
};
|
|
2090
|
+
|
|
2091
|
+
webSocketManagerMock.emit('message', JSON.stringify(mergedPayload));
|
|
2092
|
+
|
|
2093
|
+
// Verify other task was not affected
|
|
2094
|
+
expect(otherTaskEmitSpy).not.toHaveBeenCalled();
|
|
2095
|
+
expect(otherTask.data.interaction.mediaType).toBe('chat');
|
|
2096
|
+
|
|
2097
|
+
// Verify original task was updated
|
|
2098
|
+
expect(managerEmitSpy).toHaveBeenCalledWith(
|
|
2099
|
+
TASK_EVENTS.TASK_MERGED,
|
|
2100
|
+
expect.objectContaining({
|
|
2101
|
+
data: expect.objectContaining({
|
|
2102
|
+
interactionId: taskId,
|
|
2103
|
+
}),
|
|
2104
|
+
})
|
|
2105
|
+
);
|
|
2106
|
+
});
|
|
2107
|
+
});
|
|
1350
2108
|
});
|
|
1351
2109
|
|