@webex/contact-center 3.8.1 → 3.9.0-multi-llms.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 +196 -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 +13 -1
- 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 +88 -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 +162 -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/websocket/WebSocketManager.js +0 -4
- package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
- package/dist/services/task/TaskManager.js +74 -2
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/constants.js +7 -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 +384 -72
- package/dist/services/task/index.js.map +1 -1
- package/dist/services/task/types.js +14 -0
- package/dist/services/task/types.js.map +1 -1
- package/dist/types/cc.d.ts +115 -35
- package/dist/types/constants.d.ts +1 -0
- package/dist/types/index.d.ts +8 -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 +40 -1
- package/dist/types/services/task/constants.d.ts +6 -0
- package/dist/types/services/task/contact.d.ts +10 -0
- package/dist/types/services/task/index.d.ts +44 -2
- package/dist/types/services/task/types.d.ts +125 -1
- 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 +11 -10
- package/src/cc.ts +221 -52
- package/src/constants.ts +1 -0
- package/src/index.ts +19 -3
- package/src/logger-proxy.ts +24 -1
- package/src/metrics/MetricsManager.ts +1 -1
- package/src/metrics/behavioral-events.ts +92 -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 +199 -1
- package/src/services/core/aqm-reqs.ts +0 -5
- package/src/services/core/websocket/WebSocketManager.ts +0 -4
- package/src/services/task/TaskManager.ts +79 -3
- package/src/services/task/constants.ts +6 -0
- package/src/services/task/contact.ts +80 -0
- package/src/services/task/index.ts +457 -57
- package/src/services/task/types.ts +135 -0
- package/src/types.ts +180 -0
- package/src/utils/PageCache.ts +252 -0
- package/test/unit/spec/cc.ts +77 -84
- package/test/unit/spec/metrics/MetricsManager.ts +0 -1
- package/test/unit/spec/metrics/behavioral-events.ts +56 -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 +50 -0
- 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 +145 -1
- package/test/unit/spec/services/task/contact.ts +31 -1
- package/test/unit/spec/services/task/index.ts +410 -123
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
|
@@ -33,12 +33,13 @@ describe('Task', () => {
|
|
|
33
33
|
let mockMetricsManager;
|
|
34
34
|
let taskDataMock;
|
|
35
35
|
let webCallingService;
|
|
36
|
-
let
|
|
36
|
+
let generateTaskErrorObjectSpy;
|
|
37
37
|
let mockWebexRequest;
|
|
38
38
|
let webex: WebexSDK;
|
|
39
39
|
let loggerInfoSpy;
|
|
40
40
|
let loggerLogSpy;
|
|
41
41
|
let loggerErrorSpy;
|
|
42
|
+
let getDestinationAgentIdSpy;
|
|
42
43
|
|
|
43
44
|
const taskId = '0ae913a4-c857-4705-8d49-76dd3dde75e4';
|
|
44
45
|
const mockTrack = {} as MediaStreamTrack;
|
|
@@ -74,6 +75,9 @@ describe('Task', () => {
|
|
|
74
75
|
wrapup: jest.fn().mockResolvedValue({}),
|
|
75
76
|
pauseRecording: jest.fn().mockResolvedValue({}),
|
|
76
77
|
resumeRecording: jest.fn().mockResolvedValue({}),
|
|
78
|
+
consultConference: jest.fn().mockResolvedValue({}),
|
|
79
|
+
exitConference: jest.fn().mockResolvedValue({}),
|
|
80
|
+
conferenceTransfer: jest.fn().mockResolvedValue({}),
|
|
77
81
|
};
|
|
78
82
|
|
|
79
83
|
mockMetricsManager = {
|
|
@@ -141,6 +145,11 @@ describe('Task', () => {
|
|
|
141
145
|
},
|
|
142
146
|
};
|
|
143
147
|
|
|
148
|
+
// Mock destination agent id resolution from participants
|
|
149
|
+
getDestinationAgentIdSpy = jest
|
|
150
|
+
.spyOn(Utils, 'getDestinationAgentId')
|
|
151
|
+
.mockReturnValue(taskDataMock.destAgentId);
|
|
152
|
+
|
|
144
153
|
// Create an instance of Task
|
|
145
154
|
task = new Task(contactMock, webCallingService, taskDataMock);
|
|
146
155
|
|
|
@@ -158,11 +167,42 @@ describe('Task', () => {
|
|
|
158
167
|
return mockStream;
|
|
159
168
|
});
|
|
160
169
|
|
|
161
|
-
|
|
170
|
+
generateTaskErrorObjectSpy = jest.spyOn(Utils, 'generateTaskErrorObject');
|
|
171
|
+
generateTaskErrorObjectSpy.mockImplementation((error: any, methodName: string) => {
|
|
172
|
+
const trackingId = error?.details?.trackingId;
|
|
173
|
+
const msg = error?.details?.msg;
|
|
174
|
+
const legacyReason = error?.details?.data?.reason;
|
|
175
|
+
const errorMessage = msg?.errorMessage || legacyReason || `Error while performing ${methodName}`;
|
|
176
|
+
const errorType = msg?.errorType || '';
|
|
177
|
+
const errorData = msg?.errorData || '';
|
|
178
|
+
const reasonCode = msg?.reasonCode || 0;
|
|
179
|
+
const reason = legacyReason || (errorType ? `${errorType}: ${errorMessage}` : errorMessage);
|
|
180
|
+
const err: any = new Error(reason);
|
|
181
|
+
err.data = {
|
|
182
|
+
trackingId,
|
|
183
|
+
message: errorMessage,
|
|
184
|
+
errorType,
|
|
185
|
+
errorData,
|
|
186
|
+
reasonCode,
|
|
187
|
+
};
|
|
188
|
+
return err;
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
(global as any).makeFailure = (reason: string, trackingId = '1234', orgId = 'org1') => ({
|
|
192
|
+
type: 'failure_event',
|
|
193
|
+
orgId,
|
|
194
|
+
trackingId,
|
|
195
|
+
data: {
|
|
196
|
+
agentId: 'agent1',
|
|
197
|
+
reason,
|
|
198
|
+
reasonCode: 0,
|
|
199
|
+
},
|
|
200
|
+
});
|
|
162
201
|
});
|
|
163
202
|
|
|
164
203
|
afterEach(() => {
|
|
165
204
|
jest.clearAllMocks();
|
|
205
|
+
jest.restoreAllMocks();
|
|
166
206
|
});
|
|
167
207
|
|
|
168
208
|
it('test the on spy', async () => {
|
|
@@ -413,27 +453,28 @@ describe('Task', () => {
|
|
|
413
453
|
});
|
|
414
454
|
|
|
415
455
|
it('should handle errors in accept method', async () => {
|
|
416
|
-
const error = {
|
|
417
|
-
details: {
|
|
418
|
-
trackingId: '1234',
|
|
419
|
-
data: {
|
|
420
|
-
reason: 'Accept Failed',
|
|
421
|
-
},
|
|
422
|
-
},
|
|
423
|
-
};
|
|
456
|
+
const error = {details: (global as any).makeFailure('Accept Failed')};
|
|
424
457
|
|
|
425
458
|
jest.spyOn(webCallingService, 'answerCall').mockImplementation(() => {
|
|
426
459
|
throw error;
|
|
427
460
|
});
|
|
428
461
|
|
|
429
462
|
await expect(task.accept()).rejects.toThrow(new Error(error.details.data.reason));
|
|
430
|
-
expect(
|
|
463
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'accept', TASK_FILE);
|
|
464
|
+
const expectedTaskErrorFields = {
|
|
465
|
+
trackingId: error.details.trackingId,
|
|
466
|
+
errorMessage: error.details.data.reason,
|
|
467
|
+
errorType: '',
|
|
468
|
+
errorData: '',
|
|
469
|
+
reasonCode: 0,
|
|
470
|
+
};
|
|
431
471
|
expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
|
|
432
472
|
1,
|
|
433
473
|
METRIC_EVENT_NAMES.TASK_ACCEPT_FAILED,
|
|
434
474
|
{
|
|
435
475
|
taskId: taskDataMock.interactionId,
|
|
436
476
|
error: error.toString(),
|
|
477
|
+
...expectedTaskErrorFields,
|
|
437
478
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),
|
|
438
479
|
},
|
|
439
480
|
['operational', 'behavioral', 'business']
|
|
@@ -469,26 +510,27 @@ describe('Task', () => {
|
|
|
469
510
|
});
|
|
470
511
|
|
|
471
512
|
it('should handle errors in decline method', async () => {
|
|
472
|
-
const error = {
|
|
473
|
-
details: {
|
|
474
|
-
trackingId: '1234',
|
|
475
|
-
data: {
|
|
476
|
-
reason: 'Decline Failed',
|
|
477
|
-
},
|
|
478
|
-
},
|
|
479
|
-
};
|
|
513
|
+
const error = {details: (global as any).makeFailure('Decline Failed')};
|
|
480
514
|
|
|
481
515
|
jest.spyOn(webCallingService, 'declineCall').mockImplementation(() => {
|
|
482
516
|
throw error;
|
|
483
517
|
});
|
|
484
518
|
await expect(task.decline()).rejects.toThrow(new Error(error.details.data.reason));
|
|
485
|
-
expect(
|
|
519
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'decline', TASK_FILE);
|
|
520
|
+
const expectedTaskErrorFieldsDecline = {
|
|
521
|
+
trackingId: error.details.trackingId,
|
|
522
|
+
errorMessage: error.details.data.reason,
|
|
523
|
+
errorType: '',
|
|
524
|
+
errorData: '',
|
|
525
|
+
reasonCode: 0,
|
|
526
|
+
};
|
|
486
527
|
expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
|
|
487
528
|
1,
|
|
488
529
|
METRIC_EVENT_NAMES.TASK_DECLINE_FAILED,
|
|
489
530
|
{
|
|
490
531
|
taskId: taskDataMock.interactionId,
|
|
491
532
|
error: error.toString(),
|
|
533
|
+
...expectedTaskErrorFieldsDecline,
|
|
492
534
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),
|
|
493
535
|
},
|
|
494
536
|
['operational', 'behavioral']
|
|
@@ -529,20 +571,20 @@ describe('Task', () => {
|
|
|
529
571
|
});
|
|
530
572
|
|
|
531
573
|
it('should handle errors in hold method', async () => {
|
|
532
|
-
const error = {
|
|
533
|
-
details: {
|
|
534
|
-
trackingId: '1234',
|
|
535
|
-
data: {
|
|
536
|
-
reason: 'Hold Failed',
|
|
537
|
-
},
|
|
538
|
-
},
|
|
539
|
-
};
|
|
574
|
+
const error = {details: (global as any).makeFailure('Hold Failed')};
|
|
540
575
|
contactMock.hold.mockImplementation(() => {
|
|
541
576
|
throw error;
|
|
542
577
|
});
|
|
543
578
|
|
|
544
579
|
await expect(task.hold()).rejects.toThrow(error.details.data.reason);
|
|
545
|
-
expect(
|
|
580
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'hold', TASK_FILE);
|
|
581
|
+
const expectedTaskErrorFieldsHold = {
|
|
582
|
+
trackingId: error.details.trackingId,
|
|
583
|
+
errorMessage: error.details.data.reason,
|
|
584
|
+
errorType: '',
|
|
585
|
+
errorData: '',
|
|
586
|
+
reasonCode: 0,
|
|
587
|
+
};
|
|
546
588
|
expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
|
|
547
589
|
1,
|
|
548
590
|
METRIC_EVENT_NAMES.TASK_HOLD_FAILED,
|
|
@@ -550,6 +592,7 @@ describe('Task', () => {
|
|
|
550
592
|
taskId: taskDataMock.interactionId,
|
|
551
593
|
mediaResourceId: taskDataMock.mediaResourceId,
|
|
552
594
|
error: error.toString(),
|
|
595
|
+
...expectedTaskErrorFieldsHold,
|
|
553
596
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),
|
|
554
597
|
},
|
|
555
598
|
['operational', 'behavioral']
|
|
@@ -581,20 +624,20 @@ describe('Task', () => {
|
|
|
581
624
|
});
|
|
582
625
|
|
|
583
626
|
it('should handle errors in resume method', async () => {
|
|
584
|
-
const error = {
|
|
585
|
-
details: {
|
|
586
|
-
trackingId: '1234',
|
|
587
|
-
data: {
|
|
588
|
-
reason: 'Resume Failed',
|
|
589
|
-
},
|
|
590
|
-
},
|
|
591
|
-
};
|
|
627
|
+
const error = {details: (global as any).makeFailure('Resume Failed')};
|
|
592
628
|
contactMock.unHold.mockImplementation(() => {
|
|
593
629
|
throw error;
|
|
594
630
|
});
|
|
595
631
|
|
|
596
632
|
await expect(task.resume()).rejects.toThrow(error.details.data.reason);
|
|
597
|
-
expect(
|
|
633
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'resume', TASK_FILE);
|
|
634
|
+
const expectedTaskErrorFieldsResume = {
|
|
635
|
+
trackingId: error.details.trackingId,
|
|
636
|
+
errorMessage: error.details.data.reason,
|
|
637
|
+
errorType: '',
|
|
638
|
+
errorData: '',
|
|
639
|
+
reasonCode: 0,
|
|
640
|
+
};
|
|
598
641
|
expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
|
|
599
642
|
1,
|
|
600
643
|
METRIC_EVENT_NAMES.TASK_RESUME_FAILED,
|
|
@@ -604,6 +647,7 @@ describe('Task', () => {
|
|
|
604
647
|
mediaResourceId:
|
|
605
648
|
taskDataMock.interaction.media[taskDataMock.interaction.mainInteractionId]
|
|
606
649
|
.mediaResourceId,
|
|
650
|
+
...expectedTaskErrorFieldsResume,
|
|
607
651
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),
|
|
608
652
|
},
|
|
609
653
|
['operational', 'behavioral']
|
|
@@ -630,8 +674,8 @@ describe('Task', () => {
|
|
|
630
674
|
expect(loggerLogSpy).toHaveBeenCalledWith(`Consult started successfully to ${consultPayload.to}`, {
|
|
631
675
|
module: TASK_FILE,
|
|
632
676
|
method: 'consult',
|
|
633
|
-
trackingId: expectedResponse.trackingId,
|
|
634
677
|
interactionId: task.data.interactionId,
|
|
678
|
+
trackingId: '1234',
|
|
635
679
|
});
|
|
636
680
|
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
|
|
637
681
|
METRIC_EVENT_NAMES.TASK_CONSULT_START_SUCCESS,
|
|
@@ -646,14 +690,7 @@ describe('Task', () => {
|
|
|
646
690
|
});
|
|
647
691
|
|
|
648
692
|
it('should handle errors in consult method', async () => {
|
|
649
|
-
const error = {
|
|
650
|
-
details: {
|
|
651
|
-
trackingId: '1234',
|
|
652
|
-
data: {
|
|
653
|
-
reason: 'Consult Failed',
|
|
654
|
-
},
|
|
655
|
-
},
|
|
656
|
-
};
|
|
693
|
+
const error = {details: (global as any).makeFailure('Consult Failed')};
|
|
657
694
|
contactMock.consult.mockImplementation(() => {
|
|
658
695
|
throw error;
|
|
659
696
|
});
|
|
@@ -664,12 +701,19 @@ describe('Task', () => {
|
|
|
664
701
|
};
|
|
665
702
|
|
|
666
703
|
await expect(task.consult(consultPayload)).rejects.toThrow(error.details.data.reason);
|
|
667
|
-
expect(
|
|
704
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'consult', TASK_FILE);
|
|
668
705
|
expect(loggerInfoSpy).toHaveBeenCalledWith(`Starting consult`, {
|
|
669
706
|
module: TASK_FILE,
|
|
670
707
|
method: 'consult',
|
|
671
708
|
interactionId: task.data.interactionId,
|
|
672
709
|
});
|
|
710
|
+
const expectedTaskErrorFieldsConsult = {
|
|
711
|
+
trackingId: error.details.trackingId,
|
|
712
|
+
errorMessage: error.details.data.reason,
|
|
713
|
+
errorType: '',
|
|
714
|
+
errorData: '',
|
|
715
|
+
reasonCode: 0,
|
|
716
|
+
};
|
|
673
717
|
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
|
|
674
718
|
METRIC_EVENT_NAMES.TASK_CONSULT_START_FAILED,
|
|
675
719
|
{
|
|
@@ -677,6 +721,7 @@ describe('Task', () => {
|
|
|
677
721
|
destination: consultPayload.to,
|
|
678
722
|
destinationType: consultPayload.destinationType,
|
|
679
723
|
error: error.toString(),
|
|
724
|
+
...expectedTaskErrorFieldsConsult,
|
|
680
725
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),
|
|
681
726
|
},
|
|
682
727
|
['operational', 'behavioral', 'business']
|
|
@@ -710,14 +755,7 @@ describe('Task', () => {
|
|
|
710
755
|
});
|
|
711
756
|
|
|
712
757
|
it('should handle errors in endConsult method', async () => {
|
|
713
|
-
const error = {
|
|
714
|
-
details: {
|
|
715
|
-
trackingId: '1234',
|
|
716
|
-
data: {
|
|
717
|
-
reason: 'End Consult Failed',
|
|
718
|
-
},
|
|
719
|
-
},
|
|
720
|
-
};
|
|
758
|
+
const error = {details: (global as any).makeFailure('End Consult Failed')};
|
|
721
759
|
contactMock.consultEnd.mockImplementation(() => {
|
|
722
760
|
throw error;
|
|
723
761
|
});
|
|
@@ -728,13 +766,21 @@ describe('Task', () => {
|
|
|
728
766
|
};
|
|
729
767
|
|
|
730
768
|
await expect(task.endConsult(consultEndPayload)).rejects.toThrow(error.details.data.reason);
|
|
731
|
-
expect(
|
|
769
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'endConsult', TASK_FILE);
|
|
770
|
+
const expectedTaskErrorFieldsEndConsult = {
|
|
771
|
+
trackingId: error.details.trackingId,
|
|
772
|
+
errorMessage: error.details.data.reason,
|
|
773
|
+
errorType: '',
|
|
774
|
+
errorData: '',
|
|
775
|
+
reasonCode: 0,
|
|
776
|
+
};
|
|
732
777
|
expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
|
|
733
778
|
1,
|
|
734
779
|
METRIC_EVENT_NAMES.TASK_CONSULT_END_FAILED,
|
|
735
780
|
{
|
|
736
781
|
taskId: taskDataMock.interactionId,
|
|
737
782
|
error: error.toString(),
|
|
783
|
+
...expectedTaskErrorFieldsEndConsult,
|
|
738
784
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),
|
|
739
785
|
},
|
|
740
786
|
['operational', 'behavioral', 'business']
|
|
@@ -754,29 +800,81 @@ describe('Task', () => {
|
|
|
754
800
|
expect(contactMock.consult).toHaveBeenCalledWith({interactionId: taskId, data: consultPayload});
|
|
755
801
|
expect(response).toEqual(expectedResponse);
|
|
756
802
|
|
|
757
|
-
const
|
|
758
|
-
to: '1234',
|
|
759
|
-
destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
|
|
760
|
-
};
|
|
761
|
-
|
|
762
|
-
const consultTransferResponse = await task.consultTransfer(consultTransferPayload);
|
|
803
|
+
const consultTransferResponse = await task.consultTransfer();
|
|
763
804
|
expect(contactMock.consultTransfer).toHaveBeenCalledWith({
|
|
764
805
|
interactionId: taskId,
|
|
765
|
-
data:
|
|
806
|
+
data: {
|
|
807
|
+
to: taskDataMock.destAgentId,
|
|
808
|
+
destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
|
|
809
|
+
},
|
|
766
810
|
});
|
|
767
811
|
expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
|
|
768
812
|
2,
|
|
769
813
|
METRIC_EVENT_NAMES.TASK_TRANSFER_SUCCESS,
|
|
770
814
|
{
|
|
771
815
|
taskId: taskDataMock.interactionId,
|
|
772
|
-
destination:
|
|
773
|
-
destinationType:
|
|
816
|
+
destination: taskDataMock.destAgentId,
|
|
817
|
+
destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
|
|
774
818
|
isConsultTransfer: true,
|
|
775
819
|
},
|
|
776
820
|
['operational', 'behavioral', 'business']
|
|
777
821
|
);
|
|
778
822
|
});
|
|
779
823
|
|
|
824
|
+
it('should send DIALNUMBER when task destinationType is DN during consultTransfer', async () => {
|
|
825
|
+
const expectedResponse: TaskResponse = {data: {interactionId: taskId}} as AgentContact;
|
|
826
|
+
contactMock.consultTransfer.mockResolvedValue(expectedResponse);
|
|
827
|
+
|
|
828
|
+
// Ensure task data indicates DN scenario
|
|
829
|
+
task.data.destinationType = 'DN' as unknown as string;
|
|
830
|
+
|
|
831
|
+
await task.consultTransfer();
|
|
832
|
+
|
|
833
|
+
expect(contactMock.consultTransfer).toHaveBeenCalledWith({
|
|
834
|
+
interactionId: taskId,
|
|
835
|
+
data: {
|
|
836
|
+
to: taskDataMock.destAgentId,
|
|
837
|
+
destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.DIALNUMBER,
|
|
838
|
+
},
|
|
839
|
+
});
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
it('should send ENTRYPOINT when task destinationType is EPDN during consultTransfer', async () => {
|
|
843
|
+
const expectedResponse: TaskResponse = {data: {interactionId: taskId}} as AgentContact;
|
|
844
|
+
contactMock.consultTransfer.mockResolvedValue(expectedResponse);
|
|
845
|
+
|
|
846
|
+
// Ensure task data indicates EP/EPDN scenario
|
|
847
|
+
task.data.destinationType = 'EPDN' as unknown as string;
|
|
848
|
+
|
|
849
|
+
await task.consultTransfer();
|
|
850
|
+
|
|
851
|
+
expect(contactMock.consultTransfer).toHaveBeenCalledWith({
|
|
852
|
+
interactionId: taskId,
|
|
853
|
+
data: {
|
|
854
|
+
to: taskDataMock.destAgentId,
|
|
855
|
+
destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.ENTRYPOINT,
|
|
856
|
+
},
|
|
857
|
+
});
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
it('should keep AGENT when task destinationType is neither DN nor EPDN/ENTRYPOINT', async () => {
|
|
861
|
+
const expectedResponse: TaskResponse = {data: {interactionId: taskId}} as AgentContact;
|
|
862
|
+
contactMock.consultTransfer.mockResolvedValue(expectedResponse);
|
|
863
|
+
|
|
864
|
+
// Ensure task data indicates non-DN and non-EP/EPDN scenario
|
|
865
|
+
task.data.destinationType = 'SOMETHING_ELSE' as unknown as string;
|
|
866
|
+
|
|
867
|
+
await task.consultTransfer();
|
|
868
|
+
|
|
869
|
+
expect(contactMock.consultTransfer).toHaveBeenCalledWith({
|
|
870
|
+
interactionId: taskId,
|
|
871
|
+
data: {
|
|
872
|
+
to: taskDataMock.destAgentId,
|
|
873
|
+
destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
|
|
874
|
+
},
|
|
875
|
+
});
|
|
876
|
+
});
|
|
877
|
+
|
|
780
878
|
it('should do consult transfer to a queue by using the destAgentId from task data', async () => {
|
|
781
879
|
const expectedResponse: TaskResponse = {data: {interactionId: taskId}} as AgentContact;
|
|
782
880
|
contactMock.consultTransfer.mockResolvedValue(expectedResponse);
|
|
@@ -811,6 +909,9 @@ describe('Task', () => {
|
|
|
811
909
|
destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.QUEUE,
|
|
812
910
|
};
|
|
813
911
|
|
|
912
|
+
// For this negative case, ensure computed destination is empty
|
|
913
|
+
getDestinationAgentIdSpy.mockReturnValueOnce('');
|
|
914
|
+
|
|
814
915
|
await expect(
|
|
815
916
|
taskWithoutDestAgentId.consultTransfer(queueConsultTransferPayload)
|
|
816
917
|
).rejects.toThrow('Error while performing consultTransfer');
|
|
@@ -829,14 +930,7 @@ describe('Task', () => {
|
|
|
829
930
|
expect(contactMock.consult).toHaveBeenCalledWith({interactionId: taskId, data: consultPayload});
|
|
830
931
|
expect(response).toEqual(expectedResponse);
|
|
831
932
|
|
|
832
|
-
const error = {
|
|
833
|
-
details: {
|
|
834
|
-
trackingId: '1234',
|
|
835
|
-
data: {
|
|
836
|
-
reason: 'Consult Transfer Failed',
|
|
837
|
-
},
|
|
838
|
-
},
|
|
839
|
-
};
|
|
933
|
+
const error = {details: (global as any).makeFailure('Consult Transfer Failed')};
|
|
840
934
|
contactMock.consultTransfer.mockImplementation(() => {
|
|
841
935
|
throw error;
|
|
842
936
|
});
|
|
@@ -849,16 +943,24 @@ describe('Task', () => {
|
|
|
849
943
|
await expect(task.consultTransfer(consultTransferPayload)).rejects.toThrow(
|
|
850
944
|
error.details.data.reason
|
|
851
945
|
);
|
|
852
|
-
expect(
|
|
946
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'consultTransfer', TASK_FILE);
|
|
947
|
+
const expectedTaskErrorFieldsConsultTransfer = {
|
|
948
|
+
trackingId: error.details.trackingId,
|
|
949
|
+
errorMessage: error.details.data.reason,
|
|
950
|
+
errorType: '',
|
|
951
|
+
errorData: '',
|
|
952
|
+
reasonCode: 0,
|
|
953
|
+
};
|
|
853
954
|
expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
|
|
854
955
|
2,
|
|
855
956
|
METRIC_EVENT_NAMES.TASK_TRANSFER_FAILED,
|
|
856
957
|
{
|
|
857
958
|
taskId: taskDataMock.interactionId,
|
|
858
|
-
destination:
|
|
859
|
-
destinationType:
|
|
959
|
+
destination: taskDataMock.destAgentId,
|
|
960
|
+
destinationType: CONSULT_TRANSFER_DESTINATION_TYPE.AGENT,
|
|
860
961
|
isConsultTransfer: true,
|
|
861
962
|
error: error.toString(),
|
|
963
|
+
...expectedTaskErrorFieldsConsultTransfer,
|
|
862
964
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),
|
|
863
965
|
},
|
|
864
966
|
['operational', 'behavioral', 'business']
|
|
@@ -926,14 +1028,7 @@ describe('Task', () => {
|
|
|
926
1028
|
});
|
|
927
1029
|
|
|
928
1030
|
it('should handle errors in transfer method', async () => {
|
|
929
|
-
const error = {
|
|
930
|
-
details: {
|
|
931
|
-
trackingId: '1234',
|
|
932
|
-
data: {
|
|
933
|
-
reason: 'Consult Transfer Failed',
|
|
934
|
-
},
|
|
935
|
-
},
|
|
936
|
-
};
|
|
1031
|
+
const error = {details: (global as any).makeFailure('Consult Transfer Failed')};
|
|
937
1032
|
contactMock.blindTransfer.mockImplementation(() => {
|
|
938
1033
|
throw error;
|
|
939
1034
|
});
|
|
@@ -944,7 +1039,14 @@ describe('Task', () => {
|
|
|
944
1039
|
};
|
|
945
1040
|
|
|
946
1041
|
await expect(task.transfer(blindTransferPayload)).rejects.toThrow(error.details.data.reason);
|
|
947
|
-
expect(
|
|
1042
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'transfer', TASK_FILE);
|
|
1043
|
+
const expectedTaskErrorFieldsTransfer = {
|
|
1044
|
+
trackingId: error.details.trackingId,
|
|
1045
|
+
errorMessage: error.details.data.reason,
|
|
1046
|
+
errorType: '',
|
|
1047
|
+
errorData: '',
|
|
1048
|
+
reasonCode: 0,
|
|
1049
|
+
};
|
|
948
1050
|
expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
|
|
949
1051
|
1,
|
|
950
1052
|
METRIC_EVENT_NAMES.TASK_TRANSFER_FAILED,
|
|
@@ -954,6 +1056,7 @@ describe('Task', () => {
|
|
|
954
1056
|
destinationType: blindTransferPayload.destinationType,
|
|
955
1057
|
isConsultTransfer: false,
|
|
956
1058
|
error: error.toString(),
|
|
1059
|
+
...expectedTaskErrorFieldsTransfer,
|
|
957
1060
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),
|
|
958
1061
|
},
|
|
959
1062
|
['operational', 'behavioral', 'business']
|
|
@@ -990,25 +1093,26 @@ describe('Task', () => {
|
|
|
990
1093
|
});
|
|
991
1094
|
|
|
992
1095
|
it('should handle errors in end method', async () => {
|
|
993
|
-
const error = {
|
|
994
|
-
details: {
|
|
995
|
-
trackingId: '1234',
|
|
996
|
-
data: {
|
|
997
|
-
reason: 'End Failed',
|
|
998
|
-
},
|
|
999
|
-
},
|
|
1000
|
-
};
|
|
1096
|
+
const error = {details: (global as any).makeFailure('End Failed')};
|
|
1001
1097
|
contactMock.end.mockImplementation(() => {
|
|
1002
1098
|
throw error;
|
|
1003
1099
|
});
|
|
1004
1100
|
|
|
1005
1101
|
await expect(task.end()).rejects.toThrow(error.details.data.reason);
|
|
1006
|
-
expect(
|
|
1102
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'end', TASK_FILE);
|
|
1103
|
+
const expectedTaskErrorFieldsEnd = {
|
|
1104
|
+
trackingId: error.details.trackingId,
|
|
1105
|
+
errorMessage: error.details.data.reason,
|
|
1106
|
+
errorType: '',
|
|
1107
|
+
errorData: '',
|
|
1108
|
+
reasonCode: 0,
|
|
1109
|
+
};
|
|
1007
1110
|
expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
|
|
1008
1111
|
1,
|
|
1009
1112
|
METRIC_EVENT_NAMES.TASK_END_FAILED,
|
|
1010
1113
|
{
|
|
1011
1114
|
taskId: taskDataMock.interactionId,
|
|
1115
|
+
...expectedTaskErrorFieldsEnd,
|
|
1012
1116
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),
|
|
1013
1117
|
},
|
|
1014
1118
|
['operational', 'behavioral', 'business']
|
|
@@ -1041,14 +1145,7 @@ describe('Task', () => {
|
|
|
1041
1145
|
});
|
|
1042
1146
|
|
|
1043
1147
|
it('should handle errors in wrapup method', async () => {
|
|
1044
|
-
const error = {
|
|
1045
|
-
details: {
|
|
1046
|
-
trackingId: '1234',
|
|
1047
|
-
data: {
|
|
1048
|
-
reason: 'Wrapup Failed',
|
|
1049
|
-
},
|
|
1050
|
-
},
|
|
1051
|
-
};
|
|
1148
|
+
const error = {details: (global as any).makeFailure('Wrapup Failed')};
|
|
1052
1149
|
contactMock.wrapup.mockImplementation(() => {
|
|
1053
1150
|
throw error;
|
|
1054
1151
|
});
|
|
@@ -1059,7 +1156,14 @@ describe('Task', () => {
|
|
|
1059
1156
|
};
|
|
1060
1157
|
|
|
1061
1158
|
await expect(task.wrapup(wrapupPayload)).rejects.toThrow(error.details.data.reason);
|
|
1062
|
-
expect(
|
|
1159
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'wrapup', TASK_FILE);
|
|
1160
|
+
const expectedTaskErrorFieldsWrapup = {
|
|
1161
|
+
trackingId: error.details.trackingId,
|
|
1162
|
+
errorMessage: error.details.data.reason,
|
|
1163
|
+
errorType: '',
|
|
1164
|
+
errorData: '',
|
|
1165
|
+
reasonCode: 0,
|
|
1166
|
+
};
|
|
1063
1167
|
expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
|
|
1064
1168
|
1,
|
|
1065
1169
|
METRIC_EVENT_NAMES.TASK_WRAPUP_FAILED,
|
|
@@ -1067,6 +1171,7 @@ describe('Task', () => {
|
|
|
1067
1171
|
taskId: taskDataMock.interactionId,
|
|
1068
1172
|
wrapUpCode: wrapupPayload.auxCodeId,
|
|
1069
1173
|
wrapUpReason: wrapupPayload.wrapUpReason,
|
|
1174
|
+
...expectedTaskErrorFieldsWrapup,
|
|
1070
1175
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),
|
|
1071
1176
|
},
|
|
1072
1177
|
['operational', 'behavioral', 'business']
|
|
@@ -1124,26 +1229,27 @@ describe('Task', () => {
|
|
|
1124
1229
|
});
|
|
1125
1230
|
|
|
1126
1231
|
it('should handle errors in pauseRecording method', async () => {
|
|
1127
|
-
const error = {
|
|
1128
|
-
details: {
|
|
1129
|
-
trackingId: '1234',
|
|
1130
|
-
data: {
|
|
1131
|
-
reason: 'Pause Recording Failed',
|
|
1132
|
-
},
|
|
1133
|
-
},
|
|
1134
|
-
};
|
|
1232
|
+
const error = {details: (global as any).makeFailure('Pause Recording Failed')};
|
|
1135
1233
|
contactMock.pauseRecording.mockImplementation(() => {
|
|
1136
1234
|
throw error;
|
|
1137
1235
|
});
|
|
1138
1236
|
|
|
1139
1237
|
await expect(task.pauseRecording()).rejects.toThrow(error.details.data.reason);
|
|
1140
|
-
expect(
|
|
1238
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'pauseRecording', TASK_FILE);
|
|
1239
|
+
const expectedTaskErrorFieldsPause = {
|
|
1240
|
+
trackingId: error.details.trackingId,
|
|
1241
|
+
errorMessage: error.details.data.reason,
|
|
1242
|
+
errorType: '',
|
|
1243
|
+
errorData: '',
|
|
1244
|
+
reasonCode: 0,
|
|
1245
|
+
};
|
|
1141
1246
|
expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
|
|
1142
1247
|
1,
|
|
1143
1248
|
METRIC_EVENT_NAMES.TASK_PAUSE_RECORDING_FAILED,
|
|
1144
1249
|
{
|
|
1145
1250
|
taskId: taskDataMock.interactionId,
|
|
1146
1251
|
error: error.toString(),
|
|
1252
|
+
...expectedTaskErrorFieldsPause,
|
|
1147
1253
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),
|
|
1148
1254
|
},
|
|
1149
1255
|
['operational', 'behavioral', 'business']
|
|
@@ -1204,14 +1310,7 @@ describe('Task', () => {
|
|
|
1204
1310
|
});
|
|
1205
1311
|
|
|
1206
1312
|
it('should handle errors in resumeRecording method', async () => {
|
|
1207
|
-
const error = {
|
|
1208
|
-
details: {
|
|
1209
|
-
trackingId: '1234',
|
|
1210
|
-
data: {
|
|
1211
|
-
reason: 'Resume Recording Failed',
|
|
1212
|
-
},
|
|
1213
|
-
},
|
|
1214
|
-
};
|
|
1313
|
+
const error = {details: (global as any).makeFailure('Resume Recording Failed')};
|
|
1215
1314
|
contactMock.resumeRecording.mockImplementation(() => {
|
|
1216
1315
|
throw error;
|
|
1217
1316
|
});
|
|
@@ -1221,13 +1320,21 @@ describe('Task', () => {
|
|
|
1221
1320
|
};
|
|
1222
1321
|
|
|
1223
1322
|
await expect(task.resumeRecording(resumePayload)).rejects.toThrow(error.details.data.reason);
|
|
1224
|
-
expect(
|
|
1323
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'resumeRecording', TASK_FILE);
|
|
1324
|
+
const expectedTaskErrorFieldsResumeRec = {
|
|
1325
|
+
trackingId: error.details.trackingId,
|
|
1326
|
+
errorMessage: error.details.data.reason,
|
|
1327
|
+
errorType: '',
|
|
1328
|
+
errorData: '',
|
|
1329
|
+
reasonCode: 0,
|
|
1330
|
+
};
|
|
1225
1331
|
expect(mockMetricsManager.trackEvent).toHaveBeenNthCalledWith(
|
|
1226
1332
|
1,
|
|
1227
1333
|
METRIC_EVENT_NAMES.TASK_RESUME_RECORDING_FAILED,
|
|
1228
1334
|
{
|
|
1229
1335
|
taskId: taskDataMock.interactionId,
|
|
1230
1336
|
error: error.toString(),
|
|
1337
|
+
...expectedTaskErrorFieldsResumeRec,
|
|
1231
1338
|
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(error.details),
|
|
1232
1339
|
},
|
|
1233
1340
|
['operational', 'behavioral', 'business']
|
|
@@ -1267,7 +1374,7 @@ describe('Task', () => {
|
|
|
1267
1374
|
throw error;
|
|
1268
1375
|
});
|
|
1269
1376
|
await expect(task.toggleMute()).rejects.toThrow(new Error(error.details.data.reason));
|
|
1270
|
-
expect(
|
|
1377
|
+
expect(generateTaskErrorObjectSpy).toHaveBeenCalledWith(error, 'toggleMute', TASK_FILE);
|
|
1271
1378
|
expect(loggerInfoSpy).toHaveBeenCalledWith(`Toggling mute state`, {
|
|
1272
1379
|
module: TASK_FILE,
|
|
1273
1380
|
method: 'toggleMute',
|
|
@@ -1471,4 +1578,184 @@ describe('Task', () => {
|
|
|
1471
1578
|
});
|
|
1472
1579
|
});
|
|
1473
1580
|
});
|
|
1581
|
+
|
|
1582
|
+
describe('Conference methods', () => {
|
|
1583
|
+
beforeEach(() => {
|
|
1584
|
+
contactMock = {
|
|
1585
|
+
consultConference: jest.fn(),
|
|
1586
|
+
exitConference: jest.fn(),
|
|
1587
|
+
conferenceTransfer: jest.fn(),
|
|
1588
|
+
};
|
|
1589
|
+
|
|
1590
|
+
// Re-setup the getDestinationAgentId spy for conference methods
|
|
1591
|
+
getDestinationAgentIdSpy = jest
|
|
1592
|
+
.spyOn(Utils, 'getDestinationAgentId')
|
|
1593
|
+
.mockReturnValue(taskDataMock.destAgentId);
|
|
1594
|
+
|
|
1595
|
+
|
|
1596
|
+
task = new Task(contactMock, webCallingService, taskDataMock, {
|
|
1597
|
+
wrapUpProps: { wrapUpReasonList: [] },
|
|
1598
|
+
autoWrapEnabled: false,
|
|
1599
|
+
autoWrapAfterSeconds: 0
|
|
1600
|
+
}, taskDataMock.agentId);
|
|
1601
|
+
});
|
|
1602
|
+
|
|
1603
|
+
describe('consultConference', () => {
|
|
1604
|
+
|
|
1605
|
+
it('should successfully start conference and emit event', async () => {
|
|
1606
|
+
const mockResponse = {
|
|
1607
|
+
trackingId: 'test-tracking-id',
|
|
1608
|
+
interactionId: taskId,
|
|
1609
|
+
};
|
|
1610
|
+
contactMock.consultConference.mockResolvedValue(mockResponse);
|
|
1611
|
+
|
|
1612
|
+
|
|
1613
|
+
const result = await task.consultConference();
|
|
1614
|
+
|
|
1615
|
+
expect(contactMock.consultConference).toHaveBeenCalledWith({
|
|
1616
|
+
interactionId: taskId,
|
|
1617
|
+
data: {
|
|
1618
|
+
agentId: taskDataMock.agentId, // From task data agent ID
|
|
1619
|
+
to: taskDataMock.destAgentId, // From getDestinationAgentId() using task participants
|
|
1620
|
+
destinationType: 'agent', // From consultation data
|
|
1621
|
+
},
|
|
1622
|
+
});
|
|
1623
|
+
expect(result).toEqual(mockResponse);
|
|
1624
|
+
expect(LoggerProxy.info).toHaveBeenCalledWith(`Initiating consult conference to ${taskDataMock.destAgentId}`, {
|
|
1625
|
+
module: TASK_FILE,
|
|
1626
|
+
method: 'consultConference',
|
|
1627
|
+
interactionId: taskId,
|
|
1628
|
+
});
|
|
1629
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Consult conference started successfully', {
|
|
1630
|
+
module: TASK_FILE,
|
|
1631
|
+
method: 'consultConference',
|
|
1632
|
+
interactionId: taskId,
|
|
1633
|
+
});
|
|
1634
|
+
});
|
|
1635
|
+
|
|
1636
|
+
it('should handle basic validation scenarios', async () => {
|
|
1637
|
+
// Agent Desktop logic validates data structure but not participant availability
|
|
1638
|
+
// This test confirms the method works with the Agent Desktop data flow
|
|
1639
|
+
const mockResponse = {
|
|
1640
|
+
trackingId: 'test-tracking-validation',
|
|
1641
|
+
interactionId: taskId,
|
|
1642
|
+
};
|
|
1643
|
+
contactMock.consultConference.mockResolvedValue(mockResponse);
|
|
1644
|
+
|
|
1645
|
+
const result = await task.consultConference();
|
|
1646
|
+
expect(result).toEqual(mockResponse);
|
|
1647
|
+
});
|
|
1648
|
+
|
|
1649
|
+
it('should handle and rethrow contact method errors', async () => {
|
|
1650
|
+
const mockError = new Error('Conference start failed');
|
|
1651
|
+
contactMock.consultConference.mockRejectedValue(mockError);
|
|
1652
|
+
generateTaskErrorObjectSpy.mockReturnValue(mockError);
|
|
1653
|
+
|
|
1654
|
+
await expect(task.consultConference()).rejects.toThrow('Conference start failed');
|
|
1655
|
+
expect(LoggerProxy.error).toHaveBeenCalledWith('Failed to start consult conference', {
|
|
1656
|
+
module: TASK_FILE,
|
|
1657
|
+
method: 'consultConference',
|
|
1658
|
+
interactionId: taskId,
|
|
1659
|
+
});
|
|
1660
|
+
});
|
|
1661
|
+
});
|
|
1662
|
+
|
|
1663
|
+
describe('exitConference', () => {
|
|
1664
|
+
it('should successfully end conference and emit event', async () => {
|
|
1665
|
+
const mockResponse = {
|
|
1666
|
+
trackingId: 'test-tracking-id-end',
|
|
1667
|
+
interactionId: taskId,
|
|
1668
|
+
};
|
|
1669
|
+
contactMock.exitConference.mockResolvedValue(mockResponse);
|
|
1670
|
+
|
|
1671
|
+
const result = await task.exitConference();
|
|
1672
|
+
|
|
1673
|
+
expect(contactMock.exitConference).toHaveBeenCalledWith({
|
|
1674
|
+
interactionId: taskId,
|
|
1675
|
+
});
|
|
1676
|
+
expect(result).toEqual(mockResponse);
|
|
1677
|
+
expect(LoggerProxy.info).toHaveBeenCalledWith('Exiting consult conference', {
|
|
1678
|
+
module: TASK_FILE,
|
|
1679
|
+
method: 'exitConference',
|
|
1680
|
+
interactionId: taskId,
|
|
1681
|
+
});
|
|
1682
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Consult conference exited successfully', {
|
|
1683
|
+
module: TASK_FILE,
|
|
1684
|
+
method: 'exitConference',
|
|
1685
|
+
interactionId: taskId,
|
|
1686
|
+
});
|
|
1687
|
+
});
|
|
1688
|
+
|
|
1689
|
+
it('should throw error for invalid interaction ID', async () => {
|
|
1690
|
+
task.data.interactionId = '';
|
|
1691
|
+
|
|
1692
|
+
await expect(task.exitConference()).rejects.toThrow('Error while performing exitConference');
|
|
1693
|
+
expect(contactMock.exitConference).not.toHaveBeenCalled();
|
|
1694
|
+
});
|
|
1695
|
+
|
|
1696
|
+
it('should handle and rethrow contact method errors', async () => {
|
|
1697
|
+
const mockError = new Error('Conference end failed');
|
|
1698
|
+
contactMock.exitConference.mockRejectedValue(mockError);
|
|
1699
|
+
generateTaskErrorObjectSpy.mockReturnValue(mockError);
|
|
1700
|
+
|
|
1701
|
+
await expect(task.exitConference()).rejects.toThrow('Conference end failed');
|
|
1702
|
+
expect(LoggerProxy.error).toHaveBeenCalledWith('Failed to exit consult conference', {
|
|
1703
|
+
module: TASK_FILE,
|
|
1704
|
+
method: 'exitConference',
|
|
1705
|
+
interactionId: taskId,
|
|
1706
|
+
});
|
|
1707
|
+
});
|
|
1708
|
+
});
|
|
1709
|
+
|
|
1710
|
+
// TODO: Uncomment this test section in future PR for Multi-Party Conference support (>3 participants)
|
|
1711
|
+
// Conference transfer tests will be uncommented when implementing enhanced multi-party conference functionality
|
|
1712
|
+
/*
|
|
1713
|
+
describe('transferConference', () => {
|
|
1714
|
+
it('should successfully transfer conference', async () => {
|
|
1715
|
+
const mockResponse = {
|
|
1716
|
+
trackingId: 'test-tracking-id-transfer',
|
|
1717
|
+
interactionId: taskId,
|
|
1718
|
+
};
|
|
1719
|
+
contactMock.conferenceTransfer.mockResolvedValue(mockResponse);
|
|
1720
|
+
|
|
1721
|
+
const result = await task.transferConference();
|
|
1722
|
+
|
|
1723
|
+
expect(contactMock.conferenceTransfer).toHaveBeenCalledWith({
|
|
1724
|
+
interactionId: taskId,
|
|
1725
|
+
});
|
|
1726
|
+
expect(result).toEqual(mockResponse);
|
|
1727
|
+
expect(LoggerProxy.info).toHaveBeenCalledWith('Transferring conference', {
|
|
1728
|
+
module: TASK_FILE,
|
|
1729
|
+
method: 'transferConference',
|
|
1730
|
+
interactionId: taskId,
|
|
1731
|
+
});
|
|
1732
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Conference transferred successfully', {
|
|
1733
|
+
module: TASK_FILE,
|
|
1734
|
+
method: 'transferConference',
|
|
1735
|
+
interactionId: taskId,
|
|
1736
|
+
});
|
|
1737
|
+
});
|
|
1738
|
+
|
|
1739
|
+
it('should throw error for invalid interaction ID', async () => {
|
|
1740
|
+
task.data.interactionId = '';
|
|
1741
|
+
|
|
1742
|
+
await expect(task.transferConference()).rejects.toThrow('Error while performing transferConference');
|
|
1743
|
+
expect(contactMock.conferenceTransfer).not.toHaveBeenCalled();
|
|
1744
|
+
});
|
|
1745
|
+
|
|
1746
|
+
it('should handle and rethrow contact method errors', async () => {
|
|
1747
|
+
const mockError = new Error('Conference transfer failed');
|
|
1748
|
+
contactMock.conferenceTransfer.mockRejectedValue(mockError);
|
|
1749
|
+
generateTaskErrorObjectSpy.mockReturnValue(mockError);
|
|
1750
|
+
|
|
1751
|
+
await expect(task.transferConference()).rejects.toThrow('Conference transfer failed');
|
|
1752
|
+
expect(LoggerProxy.error).toHaveBeenCalledWith('Failed to transfer conference', {
|
|
1753
|
+
module: TASK_FILE,
|
|
1754
|
+
method: 'transferConference',
|
|
1755
|
+
interactionId: taskId,
|
|
1756
|
+
});
|
|
1757
|
+
});
|
|
1758
|
+
});
|
|
1759
|
+
*/
|
|
1760
|
+
});
|
|
1474
1761
|
});
|