@webex/contact-center 3.10.0-next.9 → 3.10.0-set-bitrate.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/dist/cc.js +2 -1
- package/dist/cc.js.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/logger-proxy.js.map +1 -1
- package/dist/metrics/MetricsManager.js +2 -1
- package/dist/metrics/MetricsManager.js.map +1 -1
- package/dist/metrics/behavioral-events.js +12 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +4 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/AddressBook.js +2 -3
- package/dist/services/AddressBook.js.map +1 -1
- package/dist/services/EntryPoint.js +2 -3
- package/dist/services/EntryPoint.js.map +1 -1
- package/dist/services/Queue.js +2 -3
- package/dist/services/Queue.js.map +1 -1
- package/dist/services/WebCallingService.js +1 -1
- package/dist/services/WebCallingService.js.map +1 -1
- package/dist/services/agent/index.js +1 -2
- package/dist/services/agent/index.js.map +1 -1
- package/dist/services/agent/types.js +10 -0
- package/dist/services/agent/types.js.map +1 -1
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/index.js +1 -1
- package/dist/services/config/index.js.map +1 -1
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/constants.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/GlobalTypes.js.map +1 -1
- package/dist/services/core/Utils.js +2 -3
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/core/WebexRequest.js +1 -2
- package/dist/services/core/WebexRequest.js.map +1 -1
- package/dist/services/core/aqm-reqs.js +2 -3
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/constants.js.map +1 -1
- package/dist/services/core/types.js.map +1 -1
- package/dist/services/core/websocket/WebSocketManager.js +1 -2
- package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
- package/dist/services/core/websocket/connection-service.js +1 -1
- package/dist/services/core/websocket/connection-service.js.map +1 -1
- package/dist/services/core/websocket/keepalive.worker.js.map +1 -1
- package/dist/services/core/websocket/types.js.map +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/index.js.map +1 -1
- package/dist/services/task/AutoWrapup.js +1 -1
- package/dist/services/task/AutoWrapup.js.map +1 -1
- package/dist/services/task/TaskManager.js +121 -33
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +90 -1
- package/dist/services/task/TaskUtils.js.map +1 -1
- package/dist/services/task/constants.js +3 -1
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/contact.js +0 -2
- package/dist/services/task/contact.js.map +1 -1
- package/dist/services/task/dialer.js.map +1 -1
- package/dist/services/task/index.js +1 -1
- package/dist/services/task/index.js.map +1 -1
- package/dist/services/task/types.js +375 -0
- package/dist/services/task/types.js.map +1 -1
- package/dist/types/metrics/constants.d.ts +4 -0
- package/dist/types/services/task/TaskUtils.d.ts +42 -0
- package/dist/types/services/task/constants.d.ts +2 -0
- package/dist/types/services/task/types.d.ts +32 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/PageCache.js +1 -1
- package/dist/utils/PageCache.js.map +1 -1
- package/dist/webex-config.js.map +1 -1
- package/dist/webex.js +2 -2
- package/dist/webex.js.map +1 -1
- package/package.json +9 -9
- package/src/cc.ts +1 -0
- package/src/metrics/behavioral-events.ts +12 -0
- package/src/metrics/constants.ts +4 -0
- package/src/services/task/TaskManager.ts +135 -22
- package/src/services/task/TaskUtils.ts +109 -1
- package/src/services/task/constants.ts +2 -0
- package/src/services/task/types.ts +34 -0
- package/test/unit/spec/cc.ts +1 -0
- package/test/unit/spec/metrics/behavioral-events.ts +14 -0
- package/test/unit/spec/services/task/TaskManager.ts +378 -4
- package/test/unit/spec/services/task/TaskUtils.ts +305 -3
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -673,14 +673,181 @@ describe('TaskManager', () => {
|
|
|
673
673
|
expect(taskUpdateTaskDataSpy).toHaveBeenCalledWith(payload.data);
|
|
674
674
|
});
|
|
675
675
|
|
|
676
|
-
|
|
676
|
+
describe('Auto-Answer Functionality', () => {
|
|
677
|
+
it('should emit both TASK_OFFER_CONTACT and TASK_AUTO_ANSWERED events when auto-answer succeeds', async () => {
|
|
678
|
+
// Step 1: Create the task first with initial payload
|
|
679
|
+
webSocketManagerMock.emit('message', JSON.stringify(initalPayload));
|
|
680
|
+
|
|
681
|
+
const task = taskManager.getTask(taskId);
|
|
682
|
+
const taskEmitSpy = jest.spyOn(task, 'emit');
|
|
683
|
+
const taskManagerEmitSpy = jest.spyOn(taskManager, 'emit');
|
|
684
|
+
const taskAcceptSpy = jest.spyOn(task, 'accept').mockResolvedValue(undefined);
|
|
685
|
+
|
|
686
|
+
// Step 2: Trigger AGENT_OFFER_CONTACT with auto-answer
|
|
687
|
+
const autoAnswerPayload = {
|
|
688
|
+
data: {
|
|
689
|
+
...initalPayload.data,
|
|
690
|
+
type: CC_EVENTS.AGENT_OFFER_CONTACT,
|
|
691
|
+
isAutoAnswering: true,
|
|
692
|
+
interaction: {
|
|
693
|
+
...initalPayload.data.interaction,
|
|
694
|
+
mediaType: 'telephony',
|
|
695
|
+
state: 'new',
|
|
696
|
+
},
|
|
697
|
+
},
|
|
698
|
+
};
|
|
699
|
+
|
|
700
|
+
webSocketManagerMock.emit('message', JSON.stringify(autoAnswerPayload));
|
|
701
|
+
|
|
702
|
+
// Wait for async auto-answer to complete
|
|
703
|
+
await new Promise(process.nextTick);
|
|
704
|
+
|
|
705
|
+
// Verify accept was called
|
|
706
|
+
expect(taskAcceptSpy).toHaveBeenCalledTimes(1);
|
|
707
|
+
|
|
708
|
+
// Verify BOTH events were emitted
|
|
709
|
+
expect(taskManagerEmitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_OFFER_CONTACT, task);
|
|
710
|
+
expect(taskEmitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_AUTO_ANSWERED, task);
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
it('should NOT emit TASK_AUTO_ANSWERED event when auto-answer fails', async () => {
|
|
714
|
+
// Step 1: Create the task first with initial payload
|
|
715
|
+
webSocketManagerMock.emit('message', JSON.stringify(initalPayload));
|
|
716
|
+
|
|
717
|
+
const task = taskManager.getTask(taskId);
|
|
718
|
+
const taskEmitSpy = jest.spyOn(task, 'emit');
|
|
719
|
+
const taskAcceptSpy = jest.spyOn(task, 'accept').mockRejectedValue(new Error('Accept failed'));
|
|
720
|
+
|
|
721
|
+
// Step 2: Trigger AGENT_OFFER_CONTACT with auto-answer (will fail)
|
|
722
|
+
const autoAnswerPayload = {
|
|
723
|
+
data: {
|
|
724
|
+
...initalPayload.data,
|
|
725
|
+
type: CC_EVENTS.AGENT_OFFER_CONTACT,
|
|
726
|
+
isAutoAnswering: true,
|
|
727
|
+
interaction: {
|
|
728
|
+
...initalPayload.data.interaction,
|
|
729
|
+
mediaType: 'telephony',
|
|
730
|
+
state: 'new',
|
|
731
|
+
},
|
|
732
|
+
},
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
webSocketManagerMock.emit('message', JSON.stringify(autoAnswerPayload));
|
|
736
|
+
|
|
737
|
+
// Wait for async auto-answer to complete
|
|
738
|
+
await new Promise(process.nextTick);
|
|
739
|
+
|
|
740
|
+
// Verify accept was called
|
|
741
|
+
expect(taskAcceptSpy).toHaveBeenCalledTimes(1);
|
|
742
|
+
|
|
743
|
+
// Verify TASK_AUTO_ANSWERED event was NOT emitted on failure
|
|
744
|
+
expect(taskEmitSpy).not.toHaveBeenCalledWith(TASK_EVENTS.TASK_AUTO_ANSWERED, task);
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
it('should emit both TASK_OFFER_CONSULT and TASK_AUTO_ANSWERED events for consult with auto-answer', async () => {
|
|
748
|
+
// Step 1: Create the task first with initial payload
|
|
749
|
+
webSocketManagerMock.emit('message', JSON.stringify(initalPayload));
|
|
750
|
+
|
|
751
|
+
const task = taskManager.getTask(taskId);
|
|
752
|
+
const taskEmitSpy = jest.spyOn(task, 'emit');
|
|
753
|
+
const taskAcceptSpy = jest.spyOn(task, 'accept').mockResolvedValue(undefined);
|
|
754
|
+
|
|
755
|
+
// Step 2: Trigger AGENT_OFFER_CONSULT with auto-answer
|
|
756
|
+
const consultAutoAnswerPayload = {
|
|
757
|
+
data: {
|
|
758
|
+
...initalPayload.data,
|
|
759
|
+
type: CC_EVENTS.AGENT_OFFER_CONSULT,
|
|
760
|
+
isAutoAnswering: true,
|
|
761
|
+
isConsulted: true,
|
|
762
|
+
interaction: {
|
|
763
|
+
...initalPayload.data.interaction,
|
|
764
|
+
mediaType: 'telephony',
|
|
765
|
+
state: 'consult',
|
|
766
|
+
},
|
|
767
|
+
},
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
webSocketManagerMock.emit('message', JSON.stringify(consultAutoAnswerPayload));
|
|
771
|
+
|
|
772
|
+
// Wait for async auto-answer to complete
|
|
773
|
+
await new Promise(process.nextTick);
|
|
774
|
+
|
|
775
|
+
// Verify accept was called
|
|
776
|
+
expect(taskAcceptSpy).toHaveBeenCalledTimes(1);
|
|
777
|
+
|
|
778
|
+
// Verify BOTH events were emitted
|
|
779
|
+
expect(taskEmitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_OFFER_CONSULT, task);
|
|
780
|
+
expect(taskEmitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_AUTO_ANSWERED, task);
|
|
781
|
+
|
|
782
|
+
// Verify isConsulted flag is set correctly
|
|
783
|
+
expect(task.data.isConsulted).toBe(true);
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
it('should NOT emit TASK_AUTO_ANSWERED when isAutoAnswering is false', async () => {
|
|
787
|
+
// Step 1: Create the task first with initial payload
|
|
788
|
+
webSocketManagerMock.emit('message', JSON.stringify(initalPayload));
|
|
789
|
+
|
|
790
|
+
const task = taskManager.getTask(taskId);
|
|
791
|
+
const taskEmitSpy = jest.spyOn(task, 'emit');
|
|
792
|
+
const taskAcceptSpy = jest.spyOn(task, 'accept').mockResolvedValue(undefined);
|
|
793
|
+
|
|
794
|
+
// Step 2: Trigger AGENT_OFFER_CONTACT without auto-answer
|
|
795
|
+
const normalPayload = {
|
|
796
|
+
data: {
|
|
797
|
+
...initalPayload.data,
|
|
798
|
+
type: CC_EVENTS.AGENT_OFFER_CONTACT,
|
|
799
|
+
isAutoAnswering: false,
|
|
800
|
+
interaction: {
|
|
801
|
+
...initalPayload.data.interaction,
|
|
802
|
+
mediaType: 'telephony',
|
|
803
|
+
state: 'new',
|
|
804
|
+
},
|
|
805
|
+
},
|
|
806
|
+
};
|
|
807
|
+
|
|
808
|
+
webSocketManagerMock.emit('message', JSON.stringify(normalPayload));
|
|
809
|
+
|
|
810
|
+
// Wait for any async operations
|
|
811
|
+
await new Promise(process.nextTick);
|
|
812
|
+
|
|
813
|
+
// Verify accept was NOT called
|
|
814
|
+
expect(taskAcceptSpy).not.toHaveBeenCalled();
|
|
815
|
+
|
|
816
|
+
// Verify TASK_AUTO_ANSWERED event was NOT emitted
|
|
817
|
+
expect(taskEmitSpy).not.toHaveBeenCalledWith(TASK_EVENTS.TASK_AUTO_ANSWERED, expect.anything());
|
|
818
|
+
});
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
it('should NOT remove OUTDIAL task from taskCollection on AGENT_OUTBOUND_FAILED when terminated (wrap-up flow)', () => {
|
|
822
|
+
const task = taskManager.getTask(taskId);
|
|
823
|
+
task.updateTaskData = jest.fn().mockImplementation((newData) => {
|
|
824
|
+
task.data = {
|
|
825
|
+
...task.data,
|
|
826
|
+
...newData,
|
|
827
|
+
interaction: {
|
|
828
|
+
...task.data.interaction,
|
|
829
|
+
...newData.interaction,
|
|
830
|
+
outboundType: 'OUTDIAL',
|
|
831
|
+
state: 'new',
|
|
832
|
+
isTerminated: true,
|
|
833
|
+
},
|
|
834
|
+
};
|
|
835
|
+
return task;
|
|
836
|
+
});
|
|
837
|
+
task.unregisterWebCallListeners = jest.fn();
|
|
838
|
+
const removeTaskSpy = jest.spyOn(taskManager, 'removeTaskFromCollection');
|
|
839
|
+
|
|
677
840
|
const payload = {
|
|
678
841
|
data: {
|
|
679
842
|
type: CC_EVENTS.AGENT_OUTBOUND_FAILED,
|
|
680
843
|
agentId: '723a8ffb-a26e-496d-b14a-ff44fb83b64f',
|
|
681
844
|
eventTime: 1733211616959,
|
|
682
845
|
eventType: 'RoutingMessage',
|
|
683
|
-
interaction: {
|
|
846
|
+
interaction: {
|
|
847
|
+
outboundType: 'OUTDIAL',
|
|
848
|
+
state: 'new',
|
|
849
|
+
isTerminated: true,
|
|
850
|
+
},
|
|
684
851
|
interactionId: taskId,
|
|
685
852
|
orgId: '6ecef209-9a34-4ed1-a07a-7ddd1dbe925a',
|
|
686
853
|
trackingId: '575c0ec2-618c-42af-a61c-53aeb0a221ee',
|
|
@@ -688,14 +855,220 @@ describe('TaskManager', () => {
|
|
|
688
855
|
destAgentId: 'ebeb893b-ba67-4f36-8418-95c7492b28c2',
|
|
689
856
|
owner: '723a8ffb-a26e-496d-b14a-ff44fb83b64f',
|
|
690
857
|
queueMgr: 'aqm',
|
|
858
|
+
reason: 'CUSTOMER_BUSY',
|
|
859
|
+
reasonCode: 1022,
|
|
691
860
|
},
|
|
692
861
|
};
|
|
693
862
|
|
|
694
|
-
|
|
863
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
864
|
+
|
|
865
|
+
expect(taskManager.getTask(taskId)).toBeDefined();
|
|
866
|
+
expect(removeTaskSpy).not.toHaveBeenCalled();
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
it('should emit TASK_OUTDIAL_FAILED event on AGENT_OUTBOUND_FAILED', () => {
|
|
870
|
+
const task = taskManager.getTask(taskId);
|
|
871
|
+
task.updateTaskData = jest.fn().mockReturnValue(task);
|
|
872
|
+
const taskEmitSpy = jest.spyOn(task, 'emit');
|
|
873
|
+
const payload = {
|
|
874
|
+
data: {
|
|
875
|
+
type: CC_EVENTS.AGENT_OUTBOUND_FAILED,
|
|
876
|
+
interactionId: taskId,
|
|
877
|
+
reason: 'CUSTOMER_BUSY',
|
|
878
|
+
},
|
|
879
|
+
};
|
|
880
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
881
|
+
expect(taskEmitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_OUTDIAL_FAILED, 'CUSTOMER_BUSY');
|
|
882
|
+
});
|
|
883
|
+
|
|
884
|
+
it('should handle AGENT_OUTBOUND_FAILED gracefully when task is undefined', () => {
|
|
885
|
+
const payload = {
|
|
886
|
+
data: {
|
|
887
|
+
type: CC_EVENTS.AGENT_OUTBOUND_FAILED,
|
|
888
|
+
interactionId: 'non-existent-task-id',
|
|
889
|
+
reason: 'CUSTOMER_BUSY',
|
|
890
|
+
},
|
|
891
|
+
};
|
|
892
|
+
// Should not throw error when task doesn't exist
|
|
893
|
+
expect(() => {
|
|
894
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
895
|
+
}).not.toThrow();
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
it('should NOT remove OUTDIAL task on CONTACT_ENDED when agentsPendingWrapUp exists', () => {
|
|
899
|
+
const task = taskManager.getTask(taskId);
|
|
900
|
+
task.updateTaskData = jest.fn().mockImplementation((newData) => {
|
|
901
|
+
task.data = {
|
|
902
|
+
...task.data,
|
|
903
|
+
...newData,
|
|
904
|
+
interaction: {
|
|
905
|
+
...task.data.interaction,
|
|
906
|
+
outboundType: 'OUTDIAL',
|
|
907
|
+
state: 'new',
|
|
908
|
+
mediaType: 'telephony',
|
|
909
|
+
},
|
|
910
|
+
agentsPendingWrapUp: ['agent-123'],
|
|
911
|
+
};
|
|
912
|
+
return task;
|
|
913
|
+
});
|
|
914
|
+
task.unregisterWebCallListeners = jest.fn();
|
|
915
|
+
const removeTaskSpy = jest.spyOn(taskManager, 'removeTaskFromCollection');
|
|
916
|
+
|
|
917
|
+
const payload = {
|
|
918
|
+
data: {
|
|
919
|
+
type: CC_EVENTS.CONTACT_ENDED,
|
|
920
|
+
interactionId: taskId,
|
|
921
|
+
interaction: {
|
|
922
|
+
outboundType: 'OUTDIAL',
|
|
923
|
+
state: 'new',
|
|
924
|
+
mediaType: 'telephony',
|
|
925
|
+
},
|
|
926
|
+
agentsPendingWrapUp: ['agent-123'],
|
|
927
|
+
},
|
|
928
|
+
};
|
|
929
|
+
|
|
930
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
931
|
+
|
|
932
|
+
expect(removeTaskSpy).not.toHaveBeenCalled();
|
|
933
|
+
expect(taskManager.getTask(taskId)).toBeDefined();
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
it('should remove OUTDIAL task on CONTACT_ENDED when agentsPendingWrapUp is empty', () => {
|
|
937
|
+
const task = taskManager.getTask(taskId);
|
|
938
|
+
task.updateTaskData = jest.fn().mockImplementation((newData) => {
|
|
939
|
+
task.data = {
|
|
940
|
+
...task.data,
|
|
941
|
+
...newData,
|
|
942
|
+
interaction: {
|
|
943
|
+
...task.data.interaction,
|
|
944
|
+
outboundType: 'OUTDIAL',
|
|
945
|
+
state: 'new',
|
|
946
|
+
mediaType: 'telephony',
|
|
947
|
+
},
|
|
948
|
+
agentsPendingWrapUp: [],
|
|
949
|
+
};
|
|
950
|
+
return task;
|
|
951
|
+
});
|
|
952
|
+
task.unregisterWebCallListeners = jest.fn();
|
|
953
|
+
const removeTaskSpy = jest.spyOn(taskManager, 'removeTaskFromCollection');
|
|
954
|
+
|
|
955
|
+
const payload = {
|
|
956
|
+
data: {
|
|
957
|
+
type: CC_EVENTS.CONTACT_ENDED,
|
|
958
|
+
interactionId: taskId,
|
|
959
|
+
interaction: {
|
|
960
|
+
outboundType: 'OUTDIAL',
|
|
961
|
+
state: 'new',
|
|
962
|
+
mediaType: 'telephony',
|
|
963
|
+
},
|
|
964
|
+
agentsPendingWrapUp: [],
|
|
965
|
+
},
|
|
966
|
+
};
|
|
967
|
+
|
|
968
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
969
|
+
|
|
970
|
+
expect(removeTaskSpy).toHaveBeenCalled();
|
|
971
|
+
});
|
|
972
|
+
|
|
973
|
+
it('should remove OUTDIAL task on CONTACT_ENDED when agentsPendingWrapUp is undefined', () => {
|
|
974
|
+
const task = taskManager.getTask(taskId);
|
|
975
|
+
task.updateTaskData = jest.fn().mockImplementation((newData) => {
|
|
976
|
+
task.data = {
|
|
977
|
+
...task.data,
|
|
978
|
+
...newData,
|
|
979
|
+
interaction: {
|
|
980
|
+
...task.data.interaction,
|
|
981
|
+
outboundType: 'OUTDIAL',
|
|
982
|
+
state: 'new',
|
|
983
|
+
mediaType: 'telephony',
|
|
984
|
+
},
|
|
985
|
+
// agentsPendingWrapUp is undefined
|
|
986
|
+
};
|
|
987
|
+
return task;
|
|
988
|
+
});
|
|
989
|
+
task.unregisterWebCallListeners = jest.fn();
|
|
990
|
+
const removeTaskSpy = jest.spyOn(taskManager, 'removeTaskFromCollection');
|
|
991
|
+
|
|
992
|
+
const payload = {
|
|
993
|
+
data: {
|
|
994
|
+
type: CC_EVENTS.CONTACT_ENDED,
|
|
995
|
+
interactionId: taskId,
|
|
996
|
+
interaction: {
|
|
997
|
+
outboundType: 'OUTDIAL',
|
|
998
|
+
state: 'new',
|
|
999
|
+
mediaType: 'telephony',
|
|
1000
|
+
},
|
|
1001
|
+
// agentsPendingWrapUp not included
|
|
1002
|
+
},
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1006
|
+
|
|
1007
|
+
expect(removeTaskSpy).toHaveBeenCalled();
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
it('should handle CONTACT_ENDED gracefully when task is undefined', () => {
|
|
1011
|
+
const payload = {
|
|
1012
|
+
data: {
|
|
1013
|
+
type: CC_EVENTS.CONTACT_ENDED,
|
|
1014
|
+
interactionId: 'non-existent-task-id',
|
|
1015
|
+
interaction: {
|
|
1016
|
+
state: 'new',
|
|
1017
|
+
},
|
|
1018
|
+
},
|
|
1019
|
+
};
|
|
1020
|
+
// Should not throw error when task doesn't exist
|
|
1021
|
+
expect(() => {
|
|
1022
|
+
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
1023
|
+
}).not.toThrow();
|
|
1024
|
+
});
|
|
1025
|
+
|
|
1026
|
+
it('should remove OUTDIAL task from taskCollection on AGENT_CONTACT_ASSIGN_FAILED when NOT terminated (user-declined)', () => {
|
|
1027
|
+
const task = taskManager.getTask(taskId);
|
|
1028
|
+
task.updateTaskData = jest.fn().mockImplementation((newData) => {
|
|
1029
|
+
task.data = {
|
|
1030
|
+
...task.data,
|
|
1031
|
+
...newData,
|
|
1032
|
+
interaction: {
|
|
1033
|
+
...task.data.interaction,
|
|
1034
|
+
...newData.interaction,
|
|
1035
|
+
outboundType: 'OUTDIAL',
|
|
1036
|
+
state: 'new',
|
|
1037
|
+
isTerminated: false,
|
|
1038
|
+
},
|
|
1039
|
+
};
|
|
1040
|
+
return task;
|
|
1041
|
+
});
|
|
1042
|
+
task.unregisterWebCallListeners = jest.fn();
|
|
1043
|
+
const removeTaskSpy = jest.spyOn(taskManager, 'removeTaskFromCollection');
|
|
1044
|
+
|
|
1045
|
+
const payload = {
|
|
1046
|
+
data: {
|
|
1047
|
+
type: CC_EVENTS.AGENT_CONTACT_ASSIGN_FAILED,
|
|
1048
|
+
agentId: '723a8ffb-a26e-496d-b14a-ff44fb83b64f',
|
|
1049
|
+
eventTime: 1733211616959,
|
|
1050
|
+
eventType: 'RoutingMessage',
|
|
1051
|
+
interaction: {
|
|
1052
|
+
outboundType: 'OUTDIAL',
|
|
1053
|
+
state: 'new',
|
|
1054
|
+
isTerminated: false,
|
|
1055
|
+
},
|
|
1056
|
+
interactionId: taskId,
|
|
1057
|
+
orgId: '6ecef209-9a34-4ed1-a07a-7ddd1dbe925a',
|
|
1058
|
+
trackingId: '575c0ec2-618c-42af-a61c-53aeb0a221ee',
|
|
1059
|
+
mediaResourceId: '0ae913a4-c857-4705-8d49-76dd3dde75e4',
|
|
1060
|
+
destAgentId: 'ebeb893b-ba67-4f36-8418-95c7492b28c2',
|
|
1061
|
+
owner: '723a8ffb-a26e-496d-b14a-ff44fb83b64f',
|
|
1062
|
+
queueMgr: 'aqm',
|
|
1063
|
+
reason: 'USER_DECLINED',
|
|
1064
|
+
reasonCode: 156,
|
|
1065
|
+
},
|
|
1066
|
+
};
|
|
695
1067
|
|
|
696
1068
|
webSocketManagerMock.emit('message', JSON.stringify(payload));
|
|
697
1069
|
|
|
698
1070
|
expect(taskManager.getTask(taskId)).toBeUndefined();
|
|
1071
|
+
expect(removeTaskSpy).toHaveBeenCalled();
|
|
699
1072
|
});
|
|
700
1073
|
|
|
701
1074
|
it('handle AGENT_OFFER_CONSULT event', () => {
|
|
@@ -1420,7 +1793,7 @@ describe('TaskManager', () => {
|
|
|
1420
1793
|
expect(spy).toHaveBeenCalledWith(taskEvent, task);
|
|
1421
1794
|
});
|
|
1422
1795
|
});
|
|
1423
|
-
});
|
|
1796
|
+
});
|
|
1424
1797
|
|
|
1425
1798
|
describe('Conference event handling', () => {
|
|
1426
1799
|
let task;
|
|
@@ -2105,5 +2478,6 @@ describe('TaskManager', () => {
|
|
|
2105
2478
|
);
|
|
2106
2479
|
});
|
|
2107
2480
|
});
|
|
2481
|
+
|
|
2108
2482
|
});
|
|
2109
2483
|
|