@webex/contact-center 3.9.0-next.1 → 3.9.0-next.3

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.
@@ -1,7 +1,7 @@
1
1
  import EventEmitter from 'events';
2
2
  import {CALL_EVENT_KEYS, LocalMicrophoneStream} from '@webex/calling';
3
3
  import {CallId} from '@webex/calling/dist/types/common/types';
4
- import {getErrorDetails} from '../core/Utils';
4
+ import {getErrorDetails, deriveConsultTransferDestinationType} from '../core/Utils';
5
5
  import {LoginOption} from '../../types';
6
6
  import {TASK_FILE} from '../../constants';
7
7
  import {METHODS} from './constants';
@@ -19,7 +19,6 @@ import {
19
19
  ConsultEndPayload,
20
20
  TransferPayLoad,
21
21
  DESTINATION_TYPE,
22
- CONSULT_TRANSFER_DESTINATION_TYPE,
23
22
  ConsultTransferPayLoad,
24
23
  MEDIA_CHANNEL,
25
24
  } from './types';
@@ -1308,61 +1307,70 @@ export default class Task extends EventEmitter implements ITask {
1308
1307
  * ```
1309
1308
  */
1310
1309
  public async consultTransfer(
1311
- consultTransferPayload: ConsultTransferPayLoad
1310
+ consultTransferPayload?: ConsultTransferPayLoad
1312
1311
  ): Promise<TaskResponse> {
1313
1312
  try {
1314
- LoggerProxy.info(`Initiating consult transfer to ${consultTransferPayload.to}`, {
1315
- module: TASK_FILE,
1316
- method: METHODS.CONSULT_TRANSFER,
1317
- interactionId: this.data.interactionId,
1318
- });
1313
+ // Resolve the target id (queue consult transfers go to the accepted agent)
1314
+ if (!this.data.destAgentId) {
1315
+ throw new Error('No agent has accepted this queue consult yet');
1316
+ }
1319
1317
 
1320
- // For queue destinations, use the destAgentId from task data
1321
- if (consultTransferPayload.destinationType === CONSULT_TRANSFER_DESTINATION_TYPE.QUEUE) {
1322
- if (!this.data.destAgentId) {
1323
- throw new Error('No agent has accepted this queue consult yet');
1318
+ LoggerProxy.info(
1319
+ `Initiating consult transfer to ${consultTransferPayload?.to || this.data.destAgentId}`,
1320
+ {
1321
+ module: TASK_FILE,
1322
+ method: METHODS.CONSULT_TRANSFER,
1323
+ interactionId: this.data.interactionId,
1324
1324
  }
1325
+ );
1326
+ // Obtain payload based on desktop logic using TaskData
1327
+ const finalDestinationType = deriveConsultTransferDestinationType(this.data);
1325
1328
 
1326
- // Override the destination with the agent who accepted the queue consult
1327
- consultTransferPayload = {
1328
- to: this.data.destAgentId,
1329
- destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
1330
- };
1331
- }
1329
+ // By default we always use `destAgentId` as the target id
1330
+ const consultTransferRequest: ConsultTransferPayLoad = {
1331
+ to: this.data.destAgentId,
1332
+ destinationType: finalDestinationType,
1333
+ };
1332
1334
 
1333
1335
  const result = await this.contact.consultTransfer({
1334
1336
  interactionId: this.data.interactionId,
1335
- data: consultTransferPayload,
1337
+ data: consultTransferRequest,
1336
1338
  });
1337
1339
 
1338
1340
  this.metricsManager.trackEvent(
1339
1341
  METRIC_EVENT_NAMES.TASK_TRANSFER_SUCCESS,
1340
1342
  {
1341
1343
  taskId: this.data.interactionId,
1342
- destination: consultTransferPayload.to,
1343
- destinationType: consultTransferPayload.destinationType,
1344
+ destination: consultTransferRequest.to,
1345
+ destinationType: consultTransferRequest.destinationType,
1344
1346
  isConsultTransfer: true,
1345
1347
  ...MetricsManager.getCommonTrackingFieldForAQMResponse(result),
1346
1348
  },
1347
1349
  ['operational', 'behavioral', 'business']
1348
1350
  );
1349
1351
 
1350
- LoggerProxy.log(`Consult transfer completed successfully to ${consultTransferPayload.to}`, {
1351
- module: TASK_FILE,
1352
- method: METHODS.CONSULT_TRANSFER,
1353
- trackingId: result.trackingId,
1354
- interactionId: this.data.interactionId,
1355
- });
1352
+ LoggerProxy.log(
1353
+ `Consult transfer completed successfully to ${
1354
+ consultTransferPayload?.to || this.data.destAgentId
1355
+ }`,
1356
+ {
1357
+ module: TASK_FILE,
1358
+ method: METHODS.CONSULT_TRANSFER,
1359
+ trackingId: result.trackingId,
1360
+ interactionId: this.data.interactionId,
1361
+ }
1362
+ );
1356
1363
 
1357
1364
  return result;
1358
1365
  } catch (error) {
1359
1366
  const {error: detailedError} = getErrorDetails(error, METHODS.CONSULT_TRANSFER, TASK_FILE);
1367
+ const failedDestinationType = deriveConsultTransferDestinationType(this.data);
1360
1368
  this.metricsManager.trackEvent(
1361
1369
  METRIC_EVENT_NAMES.TASK_TRANSFER_FAILED,
1362
1370
  {
1363
1371
  taskId: this.data.interactionId,
1364
- destination: consultTransferPayload.to,
1365
- destinationType: consultTransferPayload.destinationType,
1372
+ destination: this.data.destAgentId || '',
1373
+ destinationType: failedDestinationType,
1366
1374
  isConsultTransfer: true,
1367
1375
  error: error.toString(),
1368
1376
  ...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details || {}),
@@ -658,6 +658,13 @@ describe('TaskManager', () => {
658
658
  });
659
659
 
660
660
  it('should emit TASK_CONSULT_ACCEPTED event on AGENT_CONSULTING event', () => {
661
+ const initialConsultingPayload = {
662
+ data: {
663
+ ...initalPayload.data,
664
+ type: CC_EVENTS.AGENT_OFFER_CONSULT,
665
+ },
666
+ };
667
+
661
668
  const consultingPayload = {
662
669
  data: {
663
670
  ...initalPayload.data,
@@ -672,8 +679,8 @@ describe('TaskManager', () => {
672
679
  });
673
680
 
674
681
  const taskEmitSpy = jest.spyOn(taskManager.getTask(taskId), 'emit');
682
+ webSocketManagerMock.emit('message', JSON.stringify(initialConsultingPayload));
675
683
  webSocketManagerMock.emit('message', JSON.stringify(consultingPayload));
676
- expect(taskManager.getTask(taskId).updateTaskData).toHaveBeenCalledWith(consultingPayload.data);
677
684
  expect(taskManager.getTask(taskId).data.isConsulted).toBe(true);
678
685
  expect(taskEmitSpy).toHaveBeenCalledWith(
679
686
  TASK_EVENTS.TASK_CONSULT_ACCEPTED,
@@ -754,29 +754,81 @@ describe('Task', () => {
754
754
  expect(contactMock.consult).toHaveBeenCalledWith({interactionId: taskId, data: consultPayload});
755
755
  expect(response).toEqual(expectedResponse);
756
756
 
757
- const consultTransferPayload: ConsultTransferPayLoad = {
758
- to: '1234',
759
- destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
760
- };
761
-
762
- const consultTransferResponse = await task.consultTransfer(consultTransferPayload);
757
+ const consultTransferResponse = await task.consultTransfer();
763
758
  expect(contactMock.consultTransfer).toHaveBeenCalledWith({
764
759
  interactionId: taskId,
765
- data: consultTransferPayload,
760
+ data: {
761
+ to: taskDataMock.destAgentId,
762
+ destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
763
+ },
766
764
  });
767
765
  expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
768
766
  2,
769
767
  METRIC_EVENT_NAMES.TASK_TRANSFER_SUCCESS,
770
768
  {
771
769
  taskId: taskDataMock.interactionId,
772
- destination: consultTransferPayload.to,
773
- destinationType: consultTransferPayload.destinationType,
770
+ destination: taskDataMock.destAgentId,
771
+ destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
774
772
  isConsultTransfer: true,
775
773
  },
776
774
  ['operational', 'behavioral', 'business']
777
775
  );
778
776
  });
779
777
 
778
+ it('should send DIALNUMBER when task destinationType is DN during consultTransfer', async () => {
779
+ const expectedResponse: TaskResponse = {data: {interactionId: taskId}} as AgentContact;
780
+ contactMock.consultTransfer.mockResolvedValue(expectedResponse);
781
+
782
+ // Ensure task data indicates DN scenario
783
+ task.data.destinationType = 'DN' as unknown as string;
784
+
785
+ await task.consultTransfer();
786
+
787
+ expect(contactMock.consultTransfer).toHaveBeenCalledWith({
788
+ interactionId: taskId,
789
+ data: {
790
+ to: taskDataMock.destAgentId,
791
+ destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.DIALNUMBER,
792
+ },
793
+ });
794
+ });
795
+
796
+ it('should send ENTRYPOINT when task destinationType is EPDN during consultTransfer', async () => {
797
+ const expectedResponse: TaskResponse = {data: {interactionId: taskId}} as AgentContact;
798
+ contactMock.consultTransfer.mockResolvedValue(expectedResponse);
799
+
800
+ // Ensure task data indicates EP/EPDN scenario
801
+ task.data.destinationType = 'EPDN' as unknown as string;
802
+
803
+ await task.consultTransfer();
804
+
805
+ expect(contactMock.consultTransfer).toHaveBeenCalledWith({
806
+ interactionId: taskId,
807
+ data: {
808
+ to: taskDataMock.destAgentId,
809
+ destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.ENTRYPOINT,
810
+ },
811
+ });
812
+ });
813
+
814
+ it('should keep AGENT when task destinationType is neither DN nor EPDN/ENTRYPOINT', async () => {
815
+ const expectedResponse: TaskResponse = {data: {interactionId: taskId}} as AgentContact;
816
+ contactMock.consultTransfer.mockResolvedValue(expectedResponse);
817
+
818
+ // Ensure task data indicates non-DN and non-EP/EPDN scenario
819
+ task.data.destinationType = 'SOMETHING_ELSE' as unknown as string;
820
+
821
+ await task.consultTransfer();
822
+
823
+ expect(contactMock.consultTransfer).toHaveBeenCalledWith({
824
+ interactionId: taskId,
825
+ data: {
826
+ to: taskDataMock.destAgentId,
827
+ destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
828
+ },
829
+ });
830
+ });
831
+
780
832
  it('should do consult transfer to a queue by using the destAgentId from task data', async () => {
781
833
  const expectedResponse: TaskResponse = {data: {interactionId: taskId}} as AgentContact;
782
834
  contactMock.consultTransfer.mockResolvedValue(expectedResponse);
@@ -855,8 +907,8 @@ describe('Task', () => {
855
907
  METRIC_EVENT_NAMES.TASK_TRANSFER_FAILED,
856
908
  {
857
909
  taskId: taskDataMock.interactionId,
858
- destination: consultTransferPayload.to,
859
- destinationType: consultTransferPayload.destinationType,
910
+ destination: taskDataMock.destAgentId,
911
+ destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
860
912
  isConsultTransfer: true,
861
913
  error: error.toString(),
862
914
  ...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),