@webex/contact-center 3.10.0-next.2 → 3.10.0-next.21
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 +13 -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 +2 -2
- 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 +92 -74
- 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 +17 -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 +177 -56
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +122 -5
- 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 +46 -40
- package/dist/services/task/index.js.map +1 -1
- package/dist/services/task/types.js +377 -4
- package/dist/services/task/types.js.map +1 -1
- package/dist/types/cc.d.ts +6 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/metrics/constants.d.ts +4 -0
- package/dist/types/services/config/types.d.ts +4 -4
- package/dist/types/services/core/Utils.d.ts +32 -17
- package/dist/types/services/core/constants.d.ts +14 -0
- package/dist/types/services/task/TaskUtils.d.ts +59 -3
- package/dist/types/services/task/constants.d.ts +2 -0
- package/dist/types/services/task/types.d.ts +57 -13
- 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 +8 -8
- package/src/cc.ts +12 -0
- package/src/index.ts +1 -0
- package/src/metrics/behavioral-events.ts +12 -0
- package/src/metrics/constants.ts +4 -0
- package/src/services/config/types.ts +2 -2
- package/src/services/core/Utils.ts +101 -85
- package/src/services/core/constants.ts +16 -0
- package/src/services/task/TaskManager.ts +204 -36
- package/src/services/task/TaskUtils.ts +145 -5
- package/src/services/task/constants.ts +2 -0
- package/src/services/task/index.ts +50 -63
- package/src/services/task/types.ts +60 -13
- package/test/unit/spec/cc.ts +1 -0
- package/test/unit/spec/metrics/behavioral-events.ts +14 -0
- package/test/unit/spec/services/core/Utils.ts +262 -31
- package/test/unit/spec/services/task/TaskManager.ts +748 -5
- package/test/unit/spec/services/task/TaskUtils.ts +311 -9
- package/test/unit/spec/services/task/index.ts +323 -68
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -39,7 +39,8 @@ describe('Task', () => {
|
|
|
39
39
|
let loggerInfoSpy;
|
|
40
40
|
let loggerLogSpy;
|
|
41
41
|
let loggerErrorSpy;
|
|
42
|
-
let
|
|
42
|
+
let calculateDestAgentIdSpy;
|
|
43
|
+
let calculateDestTypeSpy;
|
|
43
44
|
|
|
44
45
|
const taskId = '0ae913a4-c857-4705-8d49-76dd3dde75e4';
|
|
45
46
|
const mockTrack = {} as MediaStreamTrack;
|
|
@@ -119,6 +120,32 @@ describe('Task', () => {
|
|
|
119
120
|
interaction: {
|
|
120
121
|
mediaType: 'telephony',
|
|
121
122
|
mainInteractionId: taskId,
|
|
123
|
+
participants: {
|
|
124
|
+
'723a8ffb-a26e-496d-b14a-ff44fb83b64f': {
|
|
125
|
+
pType: 'Agent',
|
|
126
|
+
type: 'AGENT',
|
|
127
|
+
id: '723a8ffb-a26e-496d-b14a-ff44fb83b64f',
|
|
128
|
+
hasLeft: false,
|
|
129
|
+
hasJoined: true,
|
|
130
|
+
isWrapUp: false,
|
|
131
|
+
},
|
|
132
|
+
'f520d6b5-28ad-4f2f-b83e-781bb64af617': {
|
|
133
|
+
pType: 'Agent',
|
|
134
|
+
type: 'AGENT',
|
|
135
|
+
id: 'f520d6b5-28ad-4f2f-b83e-781bb64af617',
|
|
136
|
+
hasLeft: false,
|
|
137
|
+
hasJoined: true,
|
|
138
|
+
isWrapUp: false,
|
|
139
|
+
},
|
|
140
|
+
'ebeb893b-ba67-4f36-8418-95c7492b28c2': {
|
|
141
|
+
pType: 'Agent',
|
|
142
|
+
type: 'AGENT',
|
|
143
|
+
id: 'ebeb893b-ba67-4f36-8418-95c7492b28c2',
|
|
144
|
+
hasLeft: false,
|
|
145
|
+
hasJoined: true,
|
|
146
|
+
isWrapUp: false,
|
|
147
|
+
},
|
|
148
|
+
},
|
|
122
149
|
media: {
|
|
123
150
|
'58a45567-4e61-4f4b-a580-5bc86357bef0': {
|
|
124
151
|
holdTimestamp: null,
|
|
@@ -145,13 +172,18 @@ describe('Task', () => {
|
|
|
145
172
|
},
|
|
146
173
|
};
|
|
147
174
|
|
|
148
|
-
// Mock
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
175
|
+
// Mock calculateDestAgentId to return the expected destination agent
|
|
176
|
+
calculateDestAgentIdSpy = jest.spyOn(Utils, 'calculateDestAgentId').mockReturnValue(taskDataMock.destAgentId);
|
|
177
|
+
|
|
178
|
+
// Mock calculateDestType to return 'agent' by default
|
|
179
|
+
calculateDestTypeSpy = jest.spyOn(Utils, 'calculateDestType').mockReturnValue('agent');
|
|
152
180
|
|
|
153
|
-
// Create an instance of Task
|
|
154
|
-
task = new Task(contactMock, webCallingService, taskDataMock
|
|
181
|
+
// Create an instance of Task with wrapupData and agentId
|
|
182
|
+
task = new Task(contactMock, webCallingService, taskDataMock, {
|
|
183
|
+
wrapUpProps: { wrapUpReasonList: [] },
|
|
184
|
+
autoWrapEnabled: false,
|
|
185
|
+
autoWrapAfterSeconds: 0
|
|
186
|
+
}, taskDataMock.agentId);
|
|
155
187
|
|
|
156
188
|
// Mock navigator.mediaDevices
|
|
157
189
|
global.navigator.mediaDevices = {
|
|
@@ -993,15 +1025,16 @@ describe('Task', () => {
|
|
|
993
1025
|
);
|
|
994
1026
|
});
|
|
995
1027
|
|
|
996
|
-
it('should send DIALNUMBER when
|
|
1028
|
+
it('should send DIALNUMBER when calculateDestType returns dialNumber during consultTransfer', async () => {
|
|
997
1029
|
const expectedResponse: TaskResponse = {data: {interactionId: taskId}} as AgentContact;
|
|
998
1030
|
contactMock.consultTransfer.mockResolvedValue(expectedResponse);
|
|
999
1031
|
|
|
1000
|
-
//
|
|
1001
|
-
|
|
1032
|
+
// Mock calculateDestType to return dialNumber
|
|
1033
|
+
calculateDestTypeSpy.mockReturnValue(CONSULT_TRANSFER_DESTINATION_TYPE.DIALNUMBER);
|
|
1002
1034
|
|
|
1003
1035
|
await task.consultTransfer();
|
|
1004
1036
|
|
|
1037
|
+
expect(calculateDestTypeSpy).toHaveBeenCalledWith(taskDataMock.interaction, taskDataMock.agentId);
|
|
1005
1038
|
expect(contactMock.consultTransfer).toHaveBeenCalledWith({
|
|
1006
1039
|
interactionId: taskId,
|
|
1007
1040
|
data: {
|
|
@@ -1011,15 +1044,16 @@ describe('Task', () => {
|
|
|
1011
1044
|
});
|
|
1012
1045
|
});
|
|
1013
1046
|
|
|
1014
|
-
it('should send ENTRYPOINT when
|
|
1047
|
+
it('should send ENTRYPOINT when calculateDestType returns entryPoint during consultTransfer', async () => {
|
|
1015
1048
|
const expectedResponse: TaskResponse = {data: {interactionId: taskId}} as AgentContact;
|
|
1016
1049
|
contactMock.consultTransfer.mockResolvedValue(expectedResponse);
|
|
1017
1050
|
|
|
1018
|
-
//
|
|
1019
|
-
|
|
1051
|
+
// Mock calculateDestType to return entryPoint
|
|
1052
|
+
calculateDestTypeSpy.mockReturnValue(CONSULT_TRANSFER_DESTINATION_TYPE.ENTRYPOINT);
|
|
1020
1053
|
|
|
1021
1054
|
await task.consultTransfer();
|
|
1022
1055
|
|
|
1056
|
+
expect(calculateDestTypeSpy).toHaveBeenCalledWith(taskDataMock.interaction, taskDataMock.agentId);
|
|
1023
1057
|
expect(contactMock.consultTransfer).toHaveBeenCalledWith({
|
|
1024
1058
|
interactionId: taskId,
|
|
1025
1059
|
data: {
|
|
@@ -1029,15 +1063,16 @@ describe('Task', () => {
|
|
|
1029
1063
|
});
|
|
1030
1064
|
});
|
|
1031
1065
|
|
|
1032
|
-
it('should
|
|
1066
|
+
it('should use AGENT when calculateDestType returns agent during consultTransfer', async () => {
|
|
1033
1067
|
const expectedResponse: TaskResponse = {data: {interactionId: taskId}} as AgentContact;
|
|
1034
1068
|
contactMock.consultTransfer.mockResolvedValue(expectedResponse);
|
|
1035
1069
|
|
|
1036
|
-
//
|
|
1037
|
-
|
|
1070
|
+
// Mock calculateDestType to return agent (default behavior)
|
|
1071
|
+
calculateDestTypeSpy.mockReturnValue(CONSULT_TRANSFER_DESTINATION_TYPE.AGENT);
|
|
1038
1072
|
|
|
1039
1073
|
await task.consultTransfer();
|
|
1040
1074
|
|
|
1075
|
+
expect(calculateDestTypeSpy).toHaveBeenCalledWith(taskDataMock.interaction, taskDataMock.agentId);
|
|
1041
1076
|
expect(contactMock.consultTransfer).toHaveBeenCalledWith({
|
|
1042
1077
|
interactionId: taskId,
|
|
1043
1078
|
data: {
|
|
@@ -1074,7 +1109,11 @@ describe('Task', () => {
|
|
|
1074
1109
|
const taskWithoutDestAgentId = new Task(contactMock, webCallingService, {
|
|
1075
1110
|
...taskDataMock,
|
|
1076
1111
|
destAgentId: undefined,
|
|
1077
|
-
}
|
|
1112
|
+
}, {
|
|
1113
|
+
wrapUpProps: { wrapUpReasonList: [] },
|
|
1114
|
+
autoWrapEnabled: false,
|
|
1115
|
+
autoWrapAfterSeconds: 0
|
|
1116
|
+
}, taskDataMock.agentId);
|
|
1078
1117
|
|
|
1079
1118
|
const queueConsultTransferPayload: ConsultTransferPayLoad = {
|
|
1080
1119
|
to: 'some-queue-id',
|
|
@@ -1082,61 +1121,123 @@ describe('Task', () => {
|
|
|
1082
1121
|
};
|
|
1083
1122
|
|
|
1084
1123
|
// For this negative case, ensure computed destination is empty
|
|
1085
|
-
|
|
1124
|
+
calculateDestAgentIdSpy.mockReturnValueOnce('');
|
|
1086
1125
|
|
|
1087
1126
|
await expect(
|
|
1088
1127
|
taskWithoutDestAgentId.consultTransfer(queueConsultTransferPayload)
|
|
1089
|
-
).rejects.toThrow('
|
|
1128
|
+
).rejects.toThrow('No agent has accepted this queue consult yet');
|
|
1090
1129
|
});
|
|
1091
1130
|
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1131
|
+
describe('consultTransfer', () => {
|
|
1132
|
+
it('should successfully perform consult transfer with agent destination', async () => {
|
|
1133
|
+
const expectedResponse: TaskResponse = {
|
|
1134
|
+
data: {interactionId: taskId},
|
|
1135
|
+
trackingId: 'test-tracking-id'
|
|
1136
|
+
} as AgentContact;
|
|
1137
|
+
contactMock.consultTransfer.mockResolvedValue(expectedResponse);
|
|
1138
|
+
|
|
1139
|
+
calculateDestTypeSpy.mockReturnValue(CONSULT_TRANSFER_DESTINATION_TYPE.AGENT);
|
|
1099
1140
|
|
|
1100
|
-
|
|
1141
|
+
const result = await task.consultTransfer();
|
|
1101
1142
|
|
|
1102
|
-
|
|
1103
|
-
|
|
1143
|
+
expect(calculateDestAgentIdSpy).toHaveBeenCalledWith(taskDataMock.interaction, taskDataMock.agentId);
|
|
1144
|
+
expect(calculateDestTypeSpy).toHaveBeenCalledWith(taskDataMock.interaction, taskDataMock.agentId);
|
|
1145
|
+
expect(contactMock.consultTransfer).toHaveBeenCalledWith({
|
|
1146
|
+
interactionId: taskId,
|
|
1147
|
+
data: {
|
|
1148
|
+
to: taskDataMock.destAgentId,
|
|
1149
|
+
destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
|
|
1150
|
+
},
|
|
1151
|
+
});
|
|
1152
|
+
expect(result).toEqual(expectedResponse);
|
|
1153
|
+
expect(loggerInfoSpy).toHaveBeenCalledWith(
|
|
1154
|
+
`Initiating consult transfer to ${taskDataMock.destAgentId}`,
|
|
1155
|
+
{
|
|
1156
|
+
module: TASK_FILE,
|
|
1157
|
+
method: 'consultTransfer',
|
|
1158
|
+
interactionId: taskId,
|
|
1159
|
+
}
|
|
1160
|
+
);
|
|
1161
|
+
expect(loggerLogSpy).toHaveBeenCalledWith(
|
|
1162
|
+
`Consult transfer completed successfully to ${taskDataMock.destAgentId}`,
|
|
1163
|
+
{
|
|
1164
|
+
module: TASK_FILE,
|
|
1165
|
+
method: 'consultTransfer',
|
|
1166
|
+
trackingId: expectedResponse.trackingId,
|
|
1167
|
+
interactionId: taskId,
|
|
1168
|
+
}
|
|
1169
|
+
);
|
|
1170
|
+
});
|
|
1171
|
+
|
|
1172
|
+
it('should track metrics on successful consult transfer', async () => {
|
|
1173
|
+
const expectedResponse: TaskResponse = {
|
|
1174
|
+
data: {interactionId: taskId},
|
|
1175
|
+
trackingId: 'test-tracking-id'
|
|
1176
|
+
} as AgentContact;
|
|
1177
|
+
contactMock.consultTransfer.mockResolvedValue(expectedResponse);
|
|
1178
|
+
|
|
1179
|
+
await task.consultTransfer();
|
|
1180
|
+
|
|
1181
|
+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
|
|
1182
|
+
METRIC_EVENT_NAMES.TASK_TRANSFER_SUCCESS,
|
|
1183
|
+
{
|
|
1184
|
+
taskId: taskDataMock.interactionId,
|
|
1185
|
+
destination: taskDataMock.destAgentId,
|
|
1186
|
+
destinationType: 'agent',
|
|
1187
|
+
isConsultTransfer: true,
|
|
1188
|
+
...MetricsManager.getCommonTrackingFieldForAQMResponse(expectedResponse),
|
|
1189
|
+
},
|
|
1190
|
+
['operational', 'behavioral', 'business']
|
|
1191
|
+
);
|
|
1192
|
+
});
|
|
1104
1193
|
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1194
|
+
it('should throw error when no destination agent is found', async () => {
|
|
1195
|
+
calculateDestAgentIdSpy.mockReturnValue('');
|
|
1196
|
+
|
|
1197
|
+
await expect(task.consultTransfer()).rejects.toThrow('No agent has accepted this queue consult yet');
|
|
1198
|
+
|
|
1199
|
+
expect(contactMock.consultTransfer).not.toHaveBeenCalled();
|
|
1108
1200
|
});
|
|
1109
1201
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1202
|
+
it('should handle and rethrow contact method errors', async () => {
|
|
1203
|
+
const mockError = new Error('Consult Transfer Failed');
|
|
1204
|
+
contactMock.consultTransfer.mockRejectedValue(mockError);
|
|
1205
|
+
generateTaskErrorObjectSpy.mockReturnValue(mockError);
|
|
1114
1206
|
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1207
|
+
await expect(task.consultTransfer()).rejects.toThrow('Consult Transfer Failed');
|
|
1208
|
+
|
|
1209
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(mockError, 'consultTransfer', TASK_FILE);
|
|
1210
|
+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
|
|
1211
|
+
METRIC_EVENT_NAMES.TASK_TRANSFER_FAILED,
|
|
1212
|
+
expect.objectContaining({
|
|
1213
|
+
taskId: taskDataMock.interactionId,
|
|
1214
|
+
destination: taskDataMock.destAgentId,
|
|
1215
|
+
destinationType: 'agent',
|
|
1216
|
+
isConsultTransfer: true,
|
|
1217
|
+
error: mockError.toString(),
|
|
1218
|
+
}),
|
|
1219
|
+
['operational', 'behavioral', 'business']
|
|
1220
|
+
);
|
|
1221
|
+
});
|
|
1222
|
+
|
|
1223
|
+
it('should dynamically calculate destAgentId when not available', async () => {
|
|
1224
|
+
const consultedAgentId = 'dynamic-agent-123';
|
|
1225
|
+
calculateDestAgentIdSpy.mockReturnValue(consultedAgentId);
|
|
1226
|
+
|
|
1227
|
+
const expectedResponse: TaskResponse = {data: {interactionId: taskId}} as AgentContact;
|
|
1228
|
+
contactMock.consultTransfer.mockResolvedValue(expectedResponse);
|
|
1229
|
+
|
|
1230
|
+
await task.consultTransfer();
|
|
1231
|
+
|
|
1232
|
+
expect(calculateDestAgentIdSpy).toHaveBeenCalledWith(taskDataMock.interaction, taskDataMock.agentId);
|
|
1233
|
+
expect(contactMock.consultTransfer).toHaveBeenCalledWith({
|
|
1234
|
+
interactionId: taskId,
|
|
1235
|
+
data: {
|
|
1236
|
+
to: consultedAgentId,
|
|
1237
|
+
destinationType: 'agent',
|
|
1238
|
+
},
|
|
1239
|
+
});
|
|
1240
|
+
});
|
|
1140
1241
|
});
|
|
1141
1242
|
|
|
1142
1243
|
it('should do vteamTransfer if destinationType is queue and return the expected response', async () => {
|
|
@@ -1759,12 +1860,6 @@ describe('Task', () => {
|
|
|
1759
1860
|
conferenceTransfer: jest.fn(),
|
|
1760
1861
|
};
|
|
1761
1862
|
|
|
1762
|
-
// Re-setup the getDestinationAgentId spy for conference methods
|
|
1763
|
-
getDestinationAgentIdSpy = jest
|
|
1764
|
-
.spyOn(Utils, 'getDestinationAgentId')
|
|
1765
|
-
.mockReturnValue(taskDataMock.destAgentId);
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
1863
|
task = new Task(contactMock, webCallingService, taskDataMock, {
|
|
1769
1864
|
wrapUpProps: { wrapUpReasonList: [] },
|
|
1770
1865
|
autoWrapEnabled: false,
|
|
@@ -1788,7 +1883,7 @@ describe('Task', () => {
|
|
|
1788
1883
|
interactionId: taskId,
|
|
1789
1884
|
data: {
|
|
1790
1885
|
agentId: taskDataMock.agentId, // From task data agent ID
|
|
1791
|
-
to: taskDataMock.destAgentId, // From
|
|
1886
|
+
to: taskDataMock.destAgentId, // From calculateDestAgentId() using task participants
|
|
1792
1887
|
destinationType: 'agent', // From consultation data
|
|
1793
1888
|
},
|
|
1794
1889
|
});
|
|
@@ -1830,6 +1925,166 @@ describe('Task', () => {
|
|
|
1830
1925
|
interactionId: taskId,
|
|
1831
1926
|
});
|
|
1832
1927
|
});
|
|
1928
|
+
|
|
1929
|
+
it('should dynamically calculate destAgentId from participants when this.data.destAgentId is null', async () => {
|
|
1930
|
+
// Simulate scenario where destAgentId is not preserved (e.g., after hold/unhold)
|
|
1931
|
+
task.data.destAgentId = null;
|
|
1932
|
+
|
|
1933
|
+
const consultedAgentId = 'consulted-agent-123';
|
|
1934
|
+
calculateDestAgentIdSpy.mockReturnValue(consultedAgentId);
|
|
1935
|
+
|
|
1936
|
+
const mockResponse = {
|
|
1937
|
+
trackingId: 'test-tracking-dynamic',
|
|
1938
|
+
interactionId: taskId,
|
|
1939
|
+
};
|
|
1940
|
+
contactMock.consultConference.mockResolvedValue(mockResponse);
|
|
1941
|
+
|
|
1942
|
+
const result = await task.consultConference();
|
|
1943
|
+
|
|
1944
|
+
// Verify calculateDestAgentId was called to dynamically calculate the destination
|
|
1945
|
+
expect(calculateDestAgentIdSpy).toHaveBeenCalledWith(
|
|
1946
|
+
taskDataMock.interaction,
|
|
1947
|
+
taskDataMock.agentId
|
|
1948
|
+
);
|
|
1949
|
+
|
|
1950
|
+
// Verify the conference was called with the dynamically calculated destAgentId
|
|
1951
|
+
expect(contactMock.consultConference).toHaveBeenCalledWith({
|
|
1952
|
+
interactionId: taskId,
|
|
1953
|
+
data: {
|
|
1954
|
+
agentId: taskDataMock.agentId,
|
|
1955
|
+
to: consultedAgentId, // Dynamically calculated value
|
|
1956
|
+
destinationType: 'agent',
|
|
1957
|
+
},
|
|
1958
|
+
});
|
|
1959
|
+
expect(result).toEqual(mockResponse);
|
|
1960
|
+
});
|
|
1961
|
+
|
|
1962
|
+
it('should throw error when no destination agent is found (queue consult not accepted)', async () => {
|
|
1963
|
+
// Simulate queue consult scenario where no agent has accepted yet
|
|
1964
|
+
calculateDestAgentIdSpy.mockReturnValue(''); // No agent found
|
|
1965
|
+
|
|
1966
|
+
await expect(task.consultConference()).rejects.toThrow('No agent has accepted this queue consult yet');
|
|
1967
|
+
|
|
1968
|
+
// Verify the conference was NOT called
|
|
1969
|
+
expect(contactMock.consultConference).not.toHaveBeenCalled();
|
|
1970
|
+
});
|
|
1971
|
+
|
|
1972
|
+
it('should calculate destination type from participant type for regular agents', async () => {
|
|
1973
|
+
const destAgentId = 'consulted-agent-456';
|
|
1974
|
+
|
|
1975
|
+
calculateDestAgentIdSpy = jest.spyOn(Utils, 'calculateDestAgentId').mockReturnValue(destAgentId);
|
|
1976
|
+
calculateDestTypeSpy = jest.spyOn(Utils, 'calculateDestType').mockReturnValue('agent');
|
|
1977
|
+
|
|
1978
|
+
const mockResponse = {trackingId: 'test-tracking-id', interactionId: taskId};
|
|
1979
|
+
contactMock.consultConference.mockResolvedValue(mockResponse);
|
|
1980
|
+
|
|
1981
|
+
await task.consultConference();
|
|
1982
|
+
|
|
1983
|
+
expect(calculateDestTypeSpy).toHaveBeenCalledWith(
|
|
1984
|
+
task.data.interaction,
|
|
1985
|
+
taskDataMock.agentId
|
|
1986
|
+
);
|
|
1987
|
+
|
|
1988
|
+
expect(contactMock.consultConference).toHaveBeenCalledWith({
|
|
1989
|
+
interactionId: taskId,
|
|
1990
|
+
data: {
|
|
1991
|
+
agentId: taskDataMock.agentId,
|
|
1992
|
+
to: destAgentId,
|
|
1993
|
+
destinationType: 'agent',
|
|
1994
|
+
},
|
|
1995
|
+
});
|
|
1996
|
+
});
|
|
1997
|
+
|
|
1998
|
+
it('should use DN destination type for dial number participants', async () => {
|
|
1999
|
+
const destAgentId = 'dn-uuid-123';
|
|
2000
|
+
|
|
2001
|
+
calculateDestAgentIdSpy = jest.spyOn(Utils, 'calculateDestAgentId').mockReturnValue(destAgentId);
|
|
2002
|
+
calculateDestTypeSpy = jest.spyOn(Utils, 'calculateDestType').mockReturnValue('dialNumber');
|
|
2003
|
+
|
|
2004
|
+
const mockResponse = {trackingId: 'test-tracking-id-dn', interactionId: taskId};
|
|
2005
|
+
contactMock.consultConference.mockResolvedValue(mockResponse);
|
|
2006
|
+
|
|
2007
|
+
await task.consultConference();
|
|
2008
|
+
|
|
2009
|
+
expect(contactMock.consultConference).toHaveBeenCalledWith({
|
|
2010
|
+
interactionId: taskId,
|
|
2011
|
+
data: {
|
|
2012
|
+
agentId: taskDataMock.agentId,
|
|
2013
|
+
to: destAgentId,
|
|
2014
|
+
destinationType: 'dialNumber',
|
|
2015
|
+
},
|
|
2016
|
+
});
|
|
2017
|
+
});
|
|
2018
|
+
|
|
2019
|
+
it('should use EpDn destination type for entry point dial number participants', async () => {
|
|
2020
|
+
const destAgentId = 'epdn-uuid-456';
|
|
2021
|
+
|
|
2022
|
+
calculateDestAgentIdSpy = jest.spyOn(Utils, 'calculateDestAgentId').mockReturnValue(destAgentId);
|
|
2023
|
+
calculateDestTypeSpy = jest.spyOn(Utils, 'calculateDestType').mockReturnValue('entryPoint');
|
|
2024
|
+
|
|
2025
|
+
const mockResponse = {trackingId: 'test-tracking-id-epdn', interactionId: taskId};
|
|
2026
|
+
contactMock.consultConference.mockResolvedValue(mockResponse);
|
|
2027
|
+
|
|
2028
|
+
await task.consultConference();
|
|
2029
|
+
|
|
2030
|
+
expect(contactMock.consultConference).toHaveBeenCalledWith({
|
|
2031
|
+
interactionId: taskId,
|
|
2032
|
+
data: {
|
|
2033
|
+
agentId: taskDataMock.agentId,
|
|
2034
|
+
to: destAgentId,
|
|
2035
|
+
destinationType: 'entryPoint',
|
|
2036
|
+
},
|
|
2037
|
+
});
|
|
2038
|
+
});
|
|
2039
|
+
|
|
2040
|
+
it('should fall back to task.data.destinationType when calculateDestType returns empty', async () => {
|
|
2041
|
+
const destAgentId = 'consulted-agent-789';
|
|
2042
|
+
|
|
2043
|
+
calculateDestAgentIdSpy = jest.spyOn(Utils, 'calculateDestAgentId').mockReturnValue(destAgentId);
|
|
2044
|
+
calculateDestTypeSpy = jest.spyOn(Utils, 'calculateDestType').mockReturnValue(''); // No type found
|
|
2045
|
+
|
|
2046
|
+
task.data.destinationType = 'EPDN';
|
|
2047
|
+
|
|
2048
|
+
const mockResponse = {trackingId: 'test-tracking-id-fallback', interactionId: taskId};
|
|
2049
|
+
contactMock.consultConference.mockResolvedValue(mockResponse);
|
|
2050
|
+
|
|
2051
|
+
await task.consultConference();
|
|
2052
|
+
|
|
2053
|
+
expect(contactMock.consultConference).toHaveBeenCalledWith({
|
|
2054
|
+
interactionId: taskId,
|
|
2055
|
+
data: {
|
|
2056
|
+
agentId: taskDataMock.agentId,
|
|
2057
|
+
to: destAgentId,
|
|
2058
|
+
destinationType: 'EPDN', // Falls back to task.data.destinationType
|
|
2059
|
+
},
|
|
2060
|
+
});
|
|
2061
|
+
});
|
|
2062
|
+
|
|
2063
|
+
it('should handle CBT scenarios with correct destination type', async () => {
|
|
2064
|
+
const destAgentId = 'agent-cbt-uuid';
|
|
2065
|
+
|
|
2066
|
+
calculateDestAgentIdSpy = jest.spyOn(Utils, 'calculateDestAgentId').mockReturnValue(destAgentId);
|
|
2067
|
+
calculateDestTypeSpy = jest.spyOn(Utils, 'calculateDestType').mockReturnValue('dialNumber');
|
|
2068
|
+
|
|
2069
|
+
const mockResponse = {trackingId: 'test-tracking-id-cbt', interactionId: taskId};
|
|
2070
|
+
contactMock.consultConference.mockResolvedValue(mockResponse);
|
|
2071
|
+
|
|
2072
|
+
await task.consultConference();
|
|
2073
|
+
|
|
2074
|
+
expect(calculateDestTypeSpy).toHaveBeenCalledWith(
|
|
2075
|
+
task.data.interaction,
|
|
2076
|
+
taskDataMock.agentId
|
|
2077
|
+
);
|
|
2078
|
+
|
|
2079
|
+
expect(contactMock.consultConference).toHaveBeenCalledWith({
|
|
2080
|
+
interactionId: taskId,
|
|
2081
|
+
data: {
|
|
2082
|
+
agentId: taskDataMock.agentId,
|
|
2083
|
+
to: destAgentId,
|
|
2084
|
+
destinationType: 'dialNumber', // dialNumber for CBT scenarios
|
|
2085
|
+
},
|
|
2086
|
+
});
|
|
2087
|
+
});
|
|
1833
2088
|
});
|
|
1834
2089
|
|
|
1835
2090
|
describe('exitConference', () => {
|