@webex/contact-center 3.12.0-task-refactor.10 → 3.12.0-task-refactor.12
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 +345 -82
- package/dist/cc.js.map +1 -1
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +3 -0
- package/dist/constants.js.map +1 -1
- package/dist/metrics/behavioral-events.js +39 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +8 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/ApiAiAssistant.js +3 -0
- package/dist/services/ApiAiAssistant.js.map +1 -1
- package/dist/services/config/Util.js +1 -1
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/types.js +10 -0
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/constants.js +1 -0
- package/dist/services/constants.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/Utils.js +57 -6
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/core/aqm-reqs.js +92 -17
- package/dist/services/core/aqm-reqs.js.map +1 -1
- package/dist/services/core/websocket/WebSocketManager.js +24 -3
- package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
- package/dist/services/index.js +1 -0
- package/dist/services/index.js.map +1 -1
- package/dist/services/task/Task.js +16 -4
- package/dist/services/task/Task.js.map +1 -1
- package/dist/services/task/TaskManager.js +158 -6
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +39 -11
- package/dist/services/task/TaskUtils.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/dialer.js +129 -0
- package/dist/services/task/dialer.js.map +1 -1
- package/dist/services/task/state-machine/TaskStateMachine.js +30 -3
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -1
- package/dist/services/task/state-machine/actions.js +4 -0
- package/dist/services/task/state-machine/actions.js.map +1 -1
- package/dist/services/task/state-machine/constants.js +3 -0
- package/dist/services/task/state-machine/constants.js.map +1 -1
- package/dist/services/task/state-machine/guards.js +23 -0
- package/dist/services/task/state-machine/guards.js.map +1 -1
- package/dist/services/task/state-machine/types.js.map +1 -1
- package/dist/services/task/state-machine/uiControlsComputer.js +1 -1
- package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -1
- package/dist/services/task/types.js +69 -0
- package/dist/services/task/types.js.map +1 -1
- package/dist/types/cc.d.ts +93 -2
- package/dist/types/config.d.ts +6 -0
- package/dist/types/constants.d.ts +3 -0
- package/dist/types/metrics/constants.d.ts +6 -0
- package/dist/types/services/config/types.d.ts +22 -1
- package/dist/types/services/core/Err.d.ts +6 -0
- package/dist/types/services/core/Utils.d.ts +20 -2
- package/dist/types/services/core/aqm-reqs.d.ts +49 -0
- package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -0
- package/dist/types/services/core/websocket/connection-service.d.ts +1 -0
- package/dist/types/services/task/Task.d.ts +1 -0
- package/dist/types/services/task/TaskUtils.d.ts +13 -0
- package/dist/types/services/task/constants.d.ts +6 -0
- package/dist/types/services/task/dialer.d.ts +45 -0
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +36 -8
- package/dist/types/services/task/state-machine/constants.d.ts +3 -0
- package/dist/types/services/task/state-machine/guards.d.ts +2 -0
- package/dist/types/services/task/state-machine/types.d.ts +11 -0
- package/dist/types/services/task/types.d.ts +85 -1
- package/dist/types/types.d.ts +2 -0
- package/dist/types.js.map +1 -1
- package/dist/webex.js +1 -1
- package/package.json +2 -2
- package/src/cc.ts +452 -102
- package/src/config.ts +6 -0
- package/src/constants.ts +3 -0
- package/src/metrics/behavioral-events.ts +42 -0
- package/src/metrics/constants.ts +9 -1
- package/src/services/ApiAiAssistant.ts +3 -0
- package/src/services/config/Util.ts +1 -1
- package/src/services/config/types.ts +12 -1
- package/src/services/constants.ts +1 -0
- package/src/services/core/Err.ts +3 -0
- package/src/services/core/Utils.ts +68 -5
- package/src/services/core/aqm-reqs.ts +100 -22
- package/src/services/core/websocket/WebSocketManager.ts +23 -2
- package/src/services/index.ts +1 -0
- package/src/services/task/Task.ts +22 -4
- package/src/services/task/TaskManager.ts +175 -7
- package/src/services/task/TaskUtils.ts +33 -1
- package/src/services/task/constants.ts +6 -0
- package/src/services/task/dialer.ts +136 -1
- package/src/services/task/state-machine/TaskStateMachine.ts +37 -5
- package/src/services/task/state-machine/actions.ts +4 -0
- package/src/services/task/state-machine/constants.ts +3 -0
- package/src/services/task/state-machine/guards.ts +30 -0
- package/src/services/task/state-machine/types.ts +14 -1
- package/src/services/task/state-machine/uiControlsComputer.ts +1 -1
- package/src/services/task/types.ts +91 -0
- package/src/types.ts +6 -1
- package/test/unit/spec/cc.ts +432 -26
- package/test/unit/spec/services/config/index.ts +30 -2
- package/test/unit/spec/services/core/Utils.ts +367 -1
- package/test/unit/spec/services/core/websocket/WebSocketManager.ts +90 -1
- package/test/unit/spec/services/core/websocket/connection-service.ts +4 -5
- package/test/unit/spec/services/task/TaskManager.ts +2334 -145
- package/test/unit/spec/services/task/dialer.ts +372 -96
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +47 -0
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
package/test/unit/spec/cc.ts
CHANGED
|
@@ -15,7 +15,7 @@ import type {ContactServiceQueuesResponse} from '../../../src/types';
|
|
|
15
15
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
16
16
|
import {StationLoginSuccess, AGENT_EVENTS} from '../../../src/services/agent/types';
|
|
17
17
|
import {SetStateResponse} from '../../../src/types';
|
|
18
|
-
import {AGENT, WEB_RTC_PREFIX} from '../../../src/services/constants';
|
|
18
|
+
import {AGENT, SUBSCRIBE_API, WEB_RTC_PREFIX} from '../../../src/services/constants';
|
|
19
19
|
import Services from '../../../src/services';
|
|
20
20
|
import config from '../../../src/config';
|
|
21
21
|
import {CC_EVENTS} from '../../../src/services/config/types';
|
|
@@ -89,6 +89,8 @@ describe('webex.cc', () => {
|
|
|
89
89
|
initWebSocket: jest.fn(),
|
|
90
90
|
on: jest.fn(),
|
|
91
91
|
off: jest.fn(),
|
|
92
|
+
close: jest.fn(),
|
|
93
|
+
isSocketClosed: false,
|
|
92
94
|
};
|
|
93
95
|
|
|
94
96
|
mockContact = {
|
|
@@ -130,6 +132,13 @@ describe('webex.cc', () => {
|
|
|
130
132
|
getOutdialAniEntries: jest.fn(),
|
|
131
133
|
},
|
|
132
134
|
webSocketManager: mockWebSocketManager,
|
|
135
|
+
rtdWebSocketManager: {
|
|
136
|
+
initWebSocket: jest.fn().mockResolvedValue({}),
|
|
137
|
+
on: jest.fn(),
|
|
138
|
+
off: jest.fn(),
|
|
139
|
+
close: jest.fn(),
|
|
140
|
+
isSocketClosed: false,
|
|
141
|
+
},
|
|
133
142
|
connectionService: {
|
|
134
143
|
on: jest.fn(),
|
|
135
144
|
off: jest.fn(),
|
|
@@ -138,6 +147,13 @@ describe('webex.cc', () => {
|
|
|
138
147
|
|
|
139
148
|
dialer: {
|
|
140
149
|
startOutdial: jest.fn(),
|
|
150
|
+
acceptPreviewContact: jest.fn(),
|
|
151
|
+
skipPreviewContact: jest.fn(),
|
|
152
|
+
removePreviewContact: jest.fn(),
|
|
153
|
+
},
|
|
154
|
+
apiAIAssistant: {
|
|
155
|
+
sendEvent: jest.fn(),
|
|
156
|
+
fetchHistoricTranscripts: jest.fn(),
|
|
141
157
|
},
|
|
142
158
|
};
|
|
143
159
|
|
|
@@ -195,6 +211,35 @@ describe('webex.cc', () => {
|
|
|
195
211
|
webex.emit('ready');
|
|
196
212
|
});
|
|
197
213
|
|
|
214
|
+
it('should throw when WebRTC registration is disabled without multi-login', () => {
|
|
215
|
+
const invalidWebex = MockWebex({
|
|
216
|
+
children: {
|
|
217
|
+
mercury: Mercury,
|
|
218
|
+
},
|
|
219
|
+
logger: {
|
|
220
|
+
log: jest.fn(),
|
|
221
|
+
error: jest.fn(),
|
|
222
|
+
info: jest.fn(),
|
|
223
|
+
},
|
|
224
|
+
credentials: {
|
|
225
|
+
getOrgId: jest.fn(() => 'mockOrgId'),
|
|
226
|
+
},
|
|
227
|
+
config: {
|
|
228
|
+
...config,
|
|
229
|
+
cc: {
|
|
230
|
+
...config.cc,
|
|
231
|
+
allowMultiLogin: false,
|
|
232
|
+
disableWebRTCRegistration: true,
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
once: jest.fn((event, callback) => callback()),
|
|
236
|
+
}) as unknown as WebexSDK;
|
|
237
|
+
|
|
238
|
+
expect(() => new ContactCenter({parent: invalidWebex})).toThrow(
|
|
239
|
+
'Invalid Contact Center configuration: disableWebRTCRegistration cannot be true when allowMultiLogin is false. Enable allowMultiLogin or allow WebRTC registration so an SDK instance can receive Mobius/WebRTC task events.'
|
|
240
|
+
);
|
|
241
|
+
});
|
|
242
|
+
|
|
198
243
|
describe('cc.getDeviceId', () => {
|
|
199
244
|
it('should return dialNumber when loginOption is EXTENSION', () => {
|
|
200
245
|
const loginOption = LoginOption.EXTENSION;
|
|
@@ -273,6 +318,7 @@ describe('webex.cc', () => {
|
|
|
273
318
|
};
|
|
274
319
|
|
|
275
320
|
it('should register successfully and return agent profile', async () => {
|
|
321
|
+
mockAgentProfile.aiFeature = {realtimeTranscripts: {enable: true}} as any;
|
|
276
322
|
const mercuryConnect = jest.spyOn(webex.internal.mercury, 'connect').mockResolvedValue(true);
|
|
277
323
|
const connectWebsocketSpy = jest.spyOn(webex.cc, 'connectWebsocket');
|
|
278
324
|
const setupEventListenersSpy = jest.spyOn(webex.cc, 'setupEventListeners');
|
|
@@ -294,7 +340,7 @@ describe('webex.cc', () => {
|
|
|
294
340
|
const result = await webex.cc.register();
|
|
295
341
|
|
|
296
342
|
// Verify logging calls
|
|
297
|
-
expect(LoggerProxy.
|
|
343
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Starting CC SDK registration', {
|
|
298
344
|
module: CC_FILE,
|
|
299
345
|
method: 'register',
|
|
300
346
|
});
|
|
@@ -316,7 +362,7 @@ describe('webex.cc', () => {
|
|
|
316
362
|
clientType: 'WebexCCSDK',
|
|
317
363
|
allowMultiLogin: false,
|
|
318
364
|
},
|
|
319
|
-
resource:
|
|
365
|
+
resource: SUBSCRIBE_API,
|
|
320
366
|
});
|
|
321
367
|
|
|
322
368
|
// TODO: https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-626777 Implement the de-register method and close the listener there
|
|
@@ -328,7 +374,24 @@ describe('webex.cc', () => {
|
|
|
328
374
|
TASK_EVENTS.TASK_HYDRATE,
|
|
329
375
|
expect.any(Function)
|
|
330
376
|
);
|
|
377
|
+
expect(mockTaskManager.on).toHaveBeenCalledWith(
|
|
378
|
+
TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE,
|
|
379
|
+
expect.any(Function)
|
|
380
|
+
);
|
|
331
381
|
expect(mockWebSocketManager.on).toHaveBeenCalledWith('message', expect.any(Function));
|
|
382
|
+
expect(webex.cc.services.rtdWebSocketManager.initWebSocket).toHaveBeenCalledWith({
|
|
383
|
+
body: {
|
|
384
|
+
force: true,
|
|
385
|
+
isKeepAliveEnabled: false,
|
|
386
|
+
clientType: 'WebexCCSDK',
|
|
387
|
+
allowMultiLogin: false,
|
|
388
|
+
},
|
|
389
|
+
resource: 'v1/realtime/subscribe',
|
|
390
|
+
});
|
|
391
|
+
expect(webex.cc.services.rtdWebSocketManager.on).toHaveBeenCalledWith(
|
|
392
|
+
'message',
|
|
393
|
+
expect.any(Function)
|
|
394
|
+
);
|
|
332
395
|
|
|
333
396
|
expect(configSpy).toHaveBeenCalled();
|
|
334
397
|
expect(LoggerProxy.log).toHaveBeenCalledWith('Agent config is fetched successfully', {
|
|
@@ -384,7 +447,7 @@ describe('webex.cc', () => {
|
|
|
384
447
|
clientType: 'WebexCCSDK',
|
|
385
448
|
allowMultiLogin: true,
|
|
386
449
|
},
|
|
387
|
-
resource:
|
|
450
|
+
resource: SUBSCRIBE_API,
|
|
388
451
|
});
|
|
389
452
|
expect(configSpy).toHaveBeenCalled();
|
|
390
453
|
expect(LoggerProxy.log).toHaveBeenCalledWith('Agent config is fetched successfully', {
|
|
@@ -406,7 +469,7 @@ describe('webex.cc', () => {
|
|
|
406
469
|
|
|
407
470
|
await expect(webex.cc.register()).rejects.toThrow('Error while performing register');
|
|
408
471
|
|
|
409
|
-
expect(LoggerProxy.
|
|
472
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Starting CC SDK registration', {
|
|
410
473
|
module: CC_FILE,
|
|
411
474
|
method: 'register',
|
|
412
475
|
});
|
|
@@ -464,7 +527,7 @@ describe('webex.cc', () => {
|
|
|
464
527
|
clientType: 'WebexCCSDK',
|
|
465
528
|
allowMultiLogin: false,
|
|
466
529
|
},
|
|
467
|
-
resource:
|
|
530
|
+
resource: SUBSCRIBE_API,
|
|
468
531
|
});
|
|
469
532
|
|
|
470
533
|
expect(mockTaskManager.on).toHaveBeenCalledWith(
|
|
@@ -475,6 +538,10 @@ describe('webex.cc', () => {
|
|
|
475
538
|
TASK_EVENTS.TASK_HYDRATE,
|
|
476
539
|
expect.any(Function)
|
|
477
540
|
);
|
|
541
|
+
expect(mockTaskManager.on).toHaveBeenCalledWith(
|
|
542
|
+
TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE,
|
|
543
|
+
expect.any(Function)
|
|
544
|
+
);
|
|
478
545
|
expect(mockWebSocketManager.on).toHaveBeenCalledWith('message', expect.any(Function));
|
|
479
546
|
|
|
480
547
|
expect(configSpy).toHaveBeenCalled();
|
|
@@ -486,8 +553,39 @@ describe('webex.cc', () => {
|
|
|
486
553
|
expect(result).toEqual(mockAgentProfile);
|
|
487
554
|
});
|
|
488
555
|
|
|
556
|
+
it('should skip mercury connection when disableWebRTCRegistration is enabled', async () => {
|
|
557
|
+
webex.cc.$config = {
|
|
558
|
+
...webex.cc.$config,
|
|
559
|
+
allowAutomatedRelogin: false,
|
|
560
|
+
disableWebRTCRegistration: true,
|
|
561
|
+
};
|
|
562
|
+
mockAgentProfile.webRtcEnabled = true;
|
|
563
|
+
const mercurySpy = jest.spyOn(webex.internal.mercury, 'connect');
|
|
564
|
+
const connectWebsocketSpy = jest.spyOn(webex.cc, 'connectWebsocket');
|
|
565
|
+
const setupEventListenersSpy = jest.spyOn(webex.cc, 'setupEventListeners');
|
|
566
|
+
jest.spyOn(webex.cc.services.config, 'getAgentConfig').mockResolvedValue(mockAgentProfile);
|
|
567
|
+
mockWebSocketManager.initWebSocket.mockResolvedValue({
|
|
568
|
+
agentId: 'agent123',
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
const result = await webex.cc.register();
|
|
572
|
+
|
|
573
|
+
expect(connectWebsocketSpy).toHaveBeenCalled();
|
|
574
|
+
expect(setupEventListenersSpy).toHaveBeenCalled();
|
|
575
|
+
expect(mercurySpy).not.toHaveBeenCalled();
|
|
576
|
+
expect(LoggerProxy.info).toHaveBeenCalledWith(
|
|
577
|
+
'Skipping Mobius registration because disableWebRTCRegistration is enabled',
|
|
578
|
+
{
|
|
579
|
+
module: CC_FILE,
|
|
580
|
+
method: 'connectWebsocket',
|
|
581
|
+
}
|
|
582
|
+
);
|
|
583
|
+
expect(result).toEqual(mockAgentProfile);
|
|
584
|
+
});
|
|
585
|
+
|
|
489
586
|
it('should not attempt for mercury connection when webrtc is disabled', async () => {
|
|
490
587
|
mockAgentProfile.webRtcEnabled = false;
|
|
588
|
+
mockAgentProfile.aiFeature = {realtimeTranscripts: {enable: false}} as any;
|
|
491
589
|
const mercurySpy = jest.spyOn(webex.internal.mercury, 'connect');
|
|
492
590
|
const connectWebsocketSpy = jest.spyOn(webex.cc, 'connectWebsocket');
|
|
493
591
|
const setupEventListenersSpy = jest.spyOn(webex.cc, 'setupEventListeners');
|
|
@@ -517,13 +615,39 @@ describe('webex.cc', () => {
|
|
|
517
615
|
clientType: 'WebexCCSDK',
|
|
518
616
|
allowMultiLogin: false,
|
|
519
617
|
},
|
|
520
|
-
resource:
|
|
618
|
+
resource: SUBSCRIBE_API,
|
|
521
619
|
});
|
|
522
620
|
|
|
523
621
|
expect(configSpy).toHaveBeenCalled();
|
|
524
622
|
expect(mercurySpy).not.toHaveBeenCalled();
|
|
623
|
+
expect(webex.cc.services.rtdWebSocketManager.initWebSocket).not.toHaveBeenCalled();
|
|
525
624
|
expect(result).toEqual(mockAgentProfile);
|
|
526
625
|
});
|
|
626
|
+
|
|
627
|
+
it('should not connect RTD websocket when realtime transcripts feature is disabled', async () => {
|
|
628
|
+
mockAgentProfile.aiFeature = {realtimeTranscripts: {enable: false}} as any;
|
|
629
|
+
jest.spyOn(webex.internal.mercury, 'connect').mockResolvedValue(true);
|
|
630
|
+
jest.spyOn(webex.cc.services.agent, 'reload').mockResolvedValue({
|
|
631
|
+
data: {
|
|
632
|
+
auxCodeId: 'auxCodeId',
|
|
633
|
+
agentId: 'agentId',
|
|
634
|
+
deviceType: LoginOption.EXTENSION,
|
|
635
|
+
dn: '12345',
|
|
636
|
+
},
|
|
637
|
+
});
|
|
638
|
+
jest.spyOn(webex.cc.services.config, 'getAgentConfig').mockResolvedValue(mockAgentProfile);
|
|
639
|
+
mockWebSocketManager.initWebSocket.mockResolvedValue({
|
|
640
|
+
agentId: 'agent123',
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
await webex.cc.register();
|
|
644
|
+
|
|
645
|
+
expect(webex.cc.services.rtdWebSocketManager.initWebSocket).not.toHaveBeenCalled();
|
|
646
|
+
expect(webex.cc.services.rtdWebSocketManager.on).not.toHaveBeenCalledWith(
|
|
647
|
+
'message',
|
|
648
|
+
expect.any(Function)
|
|
649
|
+
);
|
|
650
|
+
});
|
|
527
651
|
});
|
|
528
652
|
|
|
529
653
|
describe('stationLogin', () => {
|
|
@@ -627,10 +751,8 @@ describe('webex.cc', () => {
|
|
|
627
751
|
|
|
628
752
|
expect(emitSpy).toHaveBeenCalledTimes(1);
|
|
629
753
|
expect(emitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_INCOMING, mockTask);
|
|
630
|
-
// Verify message
|
|
631
|
-
const messageCallback =
|
|
632
|
-
(call) => call[0] === 'message'
|
|
633
|
-
)[1];
|
|
754
|
+
// Verify websocket message handling
|
|
755
|
+
const messageCallback = webex.cc['handleWebsocketMessage'];
|
|
634
756
|
const agentStateChangeEventData = {
|
|
635
757
|
type: CC_EVENTS.AGENT_STATE_CHANGE,
|
|
636
758
|
data: {some: 'data'},
|
|
@@ -658,6 +780,59 @@ describe('webex.cc', () => {
|
|
|
658
780
|
);
|
|
659
781
|
});
|
|
660
782
|
|
|
783
|
+
it('should skip web calling line registration when disableWebRTCRegistration is enabled', async () => {
|
|
784
|
+
const options = {
|
|
785
|
+
teamId: 'teamId',
|
|
786
|
+
loginOption: LoginOption.BROWSER,
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
webex.cc.$config = {
|
|
790
|
+
...webex.cc.$config,
|
|
791
|
+
disableWebRTCRegistration: true,
|
|
792
|
+
};
|
|
793
|
+
webex.cc.agentConfig = {
|
|
794
|
+
agentId: 'agentId',
|
|
795
|
+
webRtcEnabled: true,
|
|
796
|
+
loginVoiceOptions: ['BROWSER', 'EXTENSION', 'AGENT_DN'],
|
|
797
|
+
};
|
|
798
|
+
|
|
799
|
+
const registerWebCallingLineSpy = jest.spyOn(
|
|
800
|
+
webex.cc.webCallingService,
|
|
801
|
+
'registerWebCallingLine'
|
|
802
|
+
);
|
|
803
|
+
|
|
804
|
+
jest.spyOn(webex.cc.services.agent, 'stationLogin').mockResolvedValue({
|
|
805
|
+
data: {
|
|
806
|
+
loginOption: LoginOption.BROWSER,
|
|
807
|
+
agentId: 'agentId',
|
|
808
|
+
teamId: 'teamId',
|
|
809
|
+
siteId: 'siteId',
|
|
810
|
+
roles: [AGENT],
|
|
811
|
+
channelsMap: {
|
|
812
|
+
chat: [],
|
|
813
|
+
email: [],
|
|
814
|
+
social: [],
|
|
815
|
+
telephony: [],
|
|
816
|
+
},
|
|
817
|
+
},
|
|
818
|
+
trackingId: 'notifs_52628',
|
|
819
|
+
orgId: 'orgId',
|
|
820
|
+
type: 'StationLoginSuccess',
|
|
821
|
+
eventType: 'STATION_LOGIN',
|
|
822
|
+
} as unknown as StationLoginSuccess);
|
|
823
|
+
|
|
824
|
+
await webex.cc.stationLogin(options);
|
|
825
|
+
|
|
826
|
+
expect(registerWebCallingLineSpy).not.toHaveBeenCalled();
|
|
827
|
+
expect(LoggerProxy.info).toHaveBeenCalledWith(
|
|
828
|
+
'Skipping web calling line registration because disableWebRTCRegistration is enabled',
|
|
829
|
+
{
|
|
830
|
+
module: CC_FILE,
|
|
831
|
+
method: 'stationLogin',
|
|
832
|
+
}
|
|
833
|
+
);
|
|
834
|
+
});
|
|
835
|
+
|
|
661
836
|
it('should not attempt mobius registration for LoginOption.BROWSER if webrtc is disabled', async () => {
|
|
662
837
|
const options = {
|
|
663
838
|
teamId: 'teamId',
|
|
@@ -780,10 +955,13 @@ describe('webex.cc', () => {
|
|
|
780
955
|
const result = await webex.cc.stationLogin(options);
|
|
781
956
|
|
|
782
957
|
// Verify logging calls
|
|
783
|
-
expect(LoggerProxy.
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
958
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith(
|
|
959
|
+
`Starting agent station login | loginOption: ${options.loginOption} teamId: ${options.teamId}`,
|
|
960
|
+
{
|
|
961
|
+
module: CC_FILE,
|
|
962
|
+
method: 'stationLogin',
|
|
963
|
+
}
|
|
964
|
+
);
|
|
787
965
|
expect(LoggerProxy.log).toHaveBeenCalledWith(
|
|
788
966
|
`Agent station login completed successfully agentId: ${mockData.data.agentId} loginOption: ${mockData.data.loginOption} teamId: ${mockData.data.teamId}`,
|
|
789
967
|
{
|
|
@@ -834,10 +1012,13 @@ describe('webex.cc', () => {
|
|
|
834
1012
|
|
|
835
1013
|
await expect(webex.cc.stationLogin(options)).rejects.toThrow(error.details.data.reason);
|
|
836
1014
|
|
|
837
|
-
expect(LoggerProxy.
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
1015
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith(
|
|
1016
|
+
`Starting agent station login | loginOption: ${options.loginOption} teamId: ${options.teamId}`,
|
|
1017
|
+
{
|
|
1018
|
+
module: CC_FILE,
|
|
1019
|
+
method: 'stationLogin',
|
|
1020
|
+
}
|
|
1021
|
+
);
|
|
841
1022
|
expect(LoggerProxy.error).toHaveBeenCalledWith(
|
|
842
1023
|
`stationLogin failed with reason: ${error.details.data.reason}`,
|
|
843
1024
|
{module: CC_FILE, method: 'stationLogin', trackingId: error.details.trackingId}
|
|
@@ -1176,11 +1357,11 @@ describe('webex.cc', () => {
|
|
|
1176
1357
|
const webSocketManagerOnSpy = jest.spyOn(webex.cc.services.webSocketManager, 'on');
|
|
1177
1358
|
await webex.cc['silentRelogin']();
|
|
1178
1359
|
|
|
1179
|
-
expect(LoggerProxy.
|
|
1360
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Starting silent relogin process', {
|
|
1180
1361
|
module: CC_FILE,
|
|
1181
1362
|
method: 'silentRelogin',
|
|
1182
1363
|
});
|
|
1183
|
-
expect(LoggerProxy.
|
|
1364
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith(
|
|
1184
1365
|
'event=requestAutoStateChange | Requesting state change to available on socket reconnect',
|
|
1185
1366
|
{module: CC_FILE, method: 'silentRelogin'}
|
|
1186
1367
|
);
|
|
@@ -1225,7 +1406,7 @@ describe('webex.cc', () => {
|
|
|
1225
1406
|
|
|
1226
1407
|
jest.spyOn(webex.cc.services.agent, 'reload').mockRejectedValue(error);
|
|
1227
1408
|
await webex.cc['silentRelogin']();
|
|
1228
|
-
expect(LoggerProxy.
|
|
1409
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Starting silent relogin process', {
|
|
1229
1410
|
module: CC_FILE,
|
|
1230
1411
|
method: 'silentRelogin',
|
|
1231
1412
|
});
|
|
@@ -1240,7 +1421,7 @@ describe('webex.cc', () => {
|
|
|
1240
1421
|
jest.spyOn(webex.cc.services.agent, 'reload').mockRejectedValue(error);
|
|
1241
1422
|
|
|
1242
1423
|
await expect(webex.cc['silentRelogin']()).rejects.toThrow(error);
|
|
1243
|
-
expect(LoggerProxy.
|
|
1424
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Starting silent relogin process', {
|
|
1244
1425
|
module: CC_FILE,
|
|
1245
1426
|
method: 'silentRelogin',
|
|
1246
1427
|
});
|
|
@@ -1282,7 +1463,7 @@ describe('webex.cc', () => {
|
|
|
1282
1463
|
|
|
1283
1464
|
await webex.cc['silentRelogin']();
|
|
1284
1465
|
|
|
1285
|
-
expect(LoggerProxy.
|
|
1466
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Starting silent relogin process', {
|
|
1286
1467
|
module: CC_FILE,
|
|
1287
1468
|
method: 'silentRelogin',
|
|
1288
1469
|
});
|
|
@@ -1558,6 +1739,13 @@ describe('webex.cc', () => {
|
|
|
1558
1739
|
});
|
|
1559
1740
|
|
|
1560
1741
|
it('should unregister successfully and clean up all resources when webrtc is enabled', async () => {
|
|
1742
|
+
webex.cc.services.rtdWebSocketManager = {
|
|
1743
|
+
isSocketClosed: false,
|
|
1744
|
+
close: jest.fn(),
|
|
1745
|
+
off: jest.fn(),
|
|
1746
|
+
on: jest.fn(),
|
|
1747
|
+
} as any;
|
|
1748
|
+
|
|
1561
1749
|
await webex.cc.deregister();
|
|
1562
1750
|
|
|
1563
1751
|
expect(mockTaskManager.off).toHaveBeenCalledWith(
|
|
@@ -1568,14 +1756,25 @@ describe('webex.cc', () => {
|
|
|
1568
1756
|
TASK_EVENTS.TASK_HYDRATE,
|
|
1569
1757
|
expect.any(Function)
|
|
1570
1758
|
);
|
|
1759
|
+
expect(mockTaskManager.off).toHaveBeenCalledWith(
|
|
1760
|
+
TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE,
|
|
1761
|
+
expect.any(Function)
|
|
1762
|
+
);
|
|
1571
1763
|
expect(mockWebSocketManager.off).toHaveBeenCalledWith('message', expect.any(Function));
|
|
1764
|
+
expect(webex.cc.services.rtdWebSocketManager.off).toHaveBeenCalledWith(
|
|
1765
|
+
'message',
|
|
1766
|
+
expect.any(Function)
|
|
1767
|
+
);
|
|
1572
1768
|
expect(webex.cc.services.connectionService.off).toHaveBeenCalledWith(
|
|
1573
1769
|
'connectionLost',
|
|
1574
1770
|
expect.any(Function)
|
|
1575
1771
|
);
|
|
1576
1772
|
|
|
1577
1773
|
expect(mockWebSocketManager.close).toHaveBeenCalledWith(false, 'Unregistering the SDK');
|
|
1578
|
-
expect(
|
|
1774
|
+
expect(webex.cc.services.rtdWebSocketManager.close).toHaveBeenCalledWith(
|
|
1775
|
+
false,
|
|
1776
|
+
'Unregistering the RTD websocket'
|
|
1777
|
+
);
|
|
1579
1778
|
expect(webex.cc.agentConfig).toBeNull();
|
|
1580
1779
|
|
|
1581
1780
|
expect(webex.internal.mercury.off).toHaveBeenCalledWith('online');
|
|
@@ -1617,6 +1816,13 @@ describe('webex.cc', () => {
|
|
|
1617
1816
|
const [, hydrateCallback] = hydrateCalls[0];
|
|
1618
1817
|
expect(hydrateCallback).toBe(webex.cc['handleTaskHydrate']);
|
|
1619
1818
|
|
|
1819
|
+
const multiLoginHydrateCalls = mockTaskManager.off.mock.calls.filter(
|
|
1820
|
+
([evt]) => evt === TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE
|
|
1821
|
+
);
|
|
1822
|
+
expect(multiLoginHydrateCalls).toHaveLength(1);
|
|
1823
|
+
const [, multiLoginHydrateCallback] = multiLoginHydrateCalls[0];
|
|
1824
|
+
expect(multiLoginHydrateCallback).toBe(webex.cc['handleTaskMultiLoginHydrate']);
|
|
1825
|
+
|
|
1620
1826
|
const messageCalls = mockWebSocketManager.off.mock.calls.filter(([evt]) => evt === 'message');
|
|
1621
1827
|
expect(messageCalls).toHaveLength(1);
|
|
1622
1828
|
const [, messageCallback] = messageCalls[0];
|
|
@@ -1642,6 +1848,10 @@ describe('webex.cc', () => {
|
|
|
1642
1848
|
TASK_EVENTS.TASK_HYDRATE,
|
|
1643
1849
|
expect.any(Function)
|
|
1644
1850
|
);
|
|
1851
|
+
expect(mockTaskManager.off).toHaveBeenCalledWith(
|
|
1852
|
+
TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE,
|
|
1853
|
+
expect.any(Function)
|
|
1854
|
+
);
|
|
1645
1855
|
expect(mockWebSocketManager.off).toHaveBeenCalledWith('message', expect.any(Function));
|
|
1646
1856
|
expect(webex.cc.services.connectionService.off).toHaveBeenCalledWith(
|
|
1647
1857
|
'connectionLost',
|
|
@@ -1687,6 +1897,10 @@ describe('webex.cc', () => {
|
|
|
1687
1897
|
TASK_EVENTS.TASK_HYDRATE,
|
|
1688
1898
|
expect.any(Function)
|
|
1689
1899
|
);
|
|
1900
|
+
expect(mockTaskManager.off).toHaveBeenCalledWith(
|
|
1901
|
+
TASK_EVENTS.TASK_MULTI_LOGIN_HYDRATE,
|
|
1902
|
+
expect.any(Function)
|
|
1903
|
+
);
|
|
1690
1904
|
|
|
1691
1905
|
expect(LoggerProxy.error).toHaveBeenCalledWith(`Error during deregister: ${mockError}`, {
|
|
1692
1906
|
module: CC_FILE,
|
|
@@ -1709,7 +1923,7 @@ describe('webex.cc', () => {
|
|
|
1709
1923
|
|
|
1710
1924
|
beforeEach(() => {
|
|
1711
1925
|
emitSpy = jest.spyOn(webex.cc, 'emit');
|
|
1712
|
-
messageCallback =
|
|
1926
|
+
messageCallback = webex.cc['handleWebsocketMessage'];
|
|
1713
1927
|
});
|
|
1714
1928
|
|
|
1715
1929
|
it('should emit AGENT_STATION_LOGIN_SUCCESS on CC_EVENTS.AGENT_STATION_LOGIN_SUCCESS with mapped payload', () => {
|
|
@@ -2239,4 +2453,196 @@ describe('webex.cc', () => {
|
|
|
2239
2453
|
);
|
|
2240
2454
|
});
|
|
2241
2455
|
});
|
|
2456
|
+
|
|
2457
|
+
describe('acceptPreviewContact', () => {
|
|
2458
|
+
const previewPayload = {
|
|
2459
|
+
interactionId: 'interaction-123',
|
|
2460
|
+
campaignId: 'campaign-456',
|
|
2461
|
+
};
|
|
2462
|
+
|
|
2463
|
+
it('should accept preview contact successfully', async () => {
|
|
2464
|
+
const mockResponse = {trackingId: 'track-123'} as AgentContact;
|
|
2465
|
+
|
|
2466
|
+
const acceptPreviewContactMock = jest
|
|
2467
|
+
.spyOn(webex.cc.services.dialer, 'acceptPreviewContact')
|
|
2468
|
+
.mockResolvedValue(mockResponse);
|
|
2469
|
+
|
|
2470
|
+
const result = await webex.cc.acceptPreviewContact(previewPayload);
|
|
2471
|
+
|
|
2472
|
+
expect(LoggerProxy.info).toHaveBeenCalledWith('Accepting campaign preview contact', {
|
|
2473
|
+
module: CC_FILE,
|
|
2474
|
+
method: 'acceptPreviewContact',
|
|
2475
|
+
});
|
|
2476
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith(
|
|
2477
|
+
'Campaign preview contact accepted successfully',
|
|
2478
|
+
{
|
|
2479
|
+
module: CC_FILE,
|
|
2480
|
+
method: 'acceptPreviewContact',
|
|
2481
|
+
trackingId: 'track-123',
|
|
2482
|
+
interactionId: previewPayload.interactionId,
|
|
2483
|
+
}
|
|
2484
|
+
);
|
|
2485
|
+
|
|
2486
|
+
expect(acceptPreviewContactMock).toHaveBeenCalledWith({data: previewPayload});
|
|
2487
|
+
expect(result).toEqual(mockResponse);
|
|
2488
|
+
});
|
|
2489
|
+
|
|
2490
|
+
it('should handle error during acceptPreviewContact', async () => {
|
|
2491
|
+
getErrorDetailsSpy.mockRestore();
|
|
2492
|
+
getErrorDetailsSpy = jest.spyOn(Utils, 'getErrorDetails');
|
|
2493
|
+
|
|
2494
|
+
const error = {
|
|
2495
|
+
details: {
|
|
2496
|
+
trackingId: '1234',
|
|
2497
|
+
data: {
|
|
2498
|
+
reason: 'Error while performing acceptPreviewContact',
|
|
2499
|
+
},
|
|
2500
|
+
},
|
|
2501
|
+
};
|
|
2502
|
+
|
|
2503
|
+
jest.spyOn(webex.cc.services.dialer, 'acceptPreviewContact').mockRejectedValue(error);
|
|
2504
|
+
|
|
2505
|
+
await expect(webex.cc.acceptPreviewContact(previewPayload)).rejects.toThrow(
|
|
2506
|
+
error.details.data.reason
|
|
2507
|
+
);
|
|
2508
|
+
|
|
2509
|
+
expect(LoggerProxy.info).toHaveBeenCalledWith('Accepting campaign preview contact', {
|
|
2510
|
+
module: CC_FILE,
|
|
2511
|
+
method: 'acceptPreviewContact',
|
|
2512
|
+
});
|
|
2513
|
+
expect(LoggerProxy.error).toHaveBeenCalledWith(
|
|
2514
|
+
`acceptPreviewContact failed with reason: ${error.details.data.reason}`,
|
|
2515
|
+
{module: CC_FILE, method: 'acceptPreviewContact', trackingId: error.details.trackingId}
|
|
2516
|
+
);
|
|
2517
|
+
expect(getErrorDetailsSpy).toHaveBeenCalledWith(error, 'acceptPreviewContact', CC_FILE);
|
|
2518
|
+
});
|
|
2519
|
+
});
|
|
2520
|
+
|
|
2521
|
+
describe('skipPreviewContact', () => {
|
|
2522
|
+
const previewPayload = {
|
|
2523
|
+
interactionId: 'interaction-123',
|
|
2524
|
+
campaignId: 'campaign-456',
|
|
2525
|
+
};
|
|
2526
|
+
|
|
2527
|
+
it('should skip preview contact successfully', async () => {
|
|
2528
|
+
const mockResponse = {trackingId: 'track-123'} as AgentContact;
|
|
2529
|
+
|
|
2530
|
+
const skipPreviewContactMock = jest
|
|
2531
|
+
.spyOn(webex.cc.services.dialer, 'skipPreviewContact')
|
|
2532
|
+
.mockResolvedValue(mockResponse);
|
|
2533
|
+
|
|
2534
|
+
const result = await webex.cc.skipPreviewContact(previewPayload);
|
|
2535
|
+
|
|
2536
|
+
expect(LoggerProxy.info).toHaveBeenCalledWith('Skipping campaign preview contact', {
|
|
2537
|
+
module: CC_FILE,
|
|
2538
|
+
method: 'skipPreviewContact',
|
|
2539
|
+
});
|
|
2540
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith(
|
|
2541
|
+
'Campaign preview contact skipped successfully',
|
|
2542
|
+
{
|
|
2543
|
+
module: CC_FILE,
|
|
2544
|
+
method: 'skipPreviewContact',
|
|
2545
|
+
trackingId: 'track-123',
|
|
2546
|
+
interactionId: previewPayload.interactionId,
|
|
2547
|
+
}
|
|
2548
|
+
);
|
|
2549
|
+
|
|
2550
|
+
expect(skipPreviewContactMock).toHaveBeenCalledWith({data: previewPayload});
|
|
2551
|
+
expect(result).toEqual(mockResponse);
|
|
2552
|
+
});
|
|
2553
|
+
|
|
2554
|
+
it('should handle error during skipPreviewContact', async () => {
|
|
2555
|
+
getErrorDetailsSpy.mockRestore();
|
|
2556
|
+
getErrorDetailsSpy = jest.spyOn(Utils, 'getErrorDetails');
|
|
2557
|
+
|
|
2558
|
+
const error = {
|
|
2559
|
+
details: {
|
|
2560
|
+
trackingId: '1234',
|
|
2561
|
+
data: {
|
|
2562
|
+
reason: 'Error while performing skipPreviewContact',
|
|
2563
|
+
},
|
|
2564
|
+
},
|
|
2565
|
+
};
|
|
2566
|
+
|
|
2567
|
+
jest.spyOn(webex.cc.services.dialer, 'skipPreviewContact').mockRejectedValue(error);
|
|
2568
|
+
|
|
2569
|
+
await expect(webex.cc.skipPreviewContact(previewPayload)).rejects.toThrow(
|
|
2570
|
+
error.details.data.reason
|
|
2571
|
+
);
|
|
2572
|
+
|
|
2573
|
+
expect(LoggerProxy.info).toHaveBeenCalledWith('Skipping campaign preview contact', {
|
|
2574
|
+
module: CC_FILE,
|
|
2575
|
+
method: 'skipPreviewContact',
|
|
2576
|
+
});
|
|
2577
|
+
expect(LoggerProxy.error).toHaveBeenCalledWith(
|
|
2578
|
+
`skipPreviewContact failed with reason: ${error.details.data.reason}`,
|
|
2579
|
+
{module: CC_FILE, method: 'skipPreviewContact', trackingId: error.details.trackingId}
|
|
2580
|
+
);
|
|
2581
|
+
expect(getErrorDetailsSpy).toHaveBeenCalledWith(error, 'skipPreviewContact', CC_FILE);
|
|
2582
|
+
});
|
|
2583
|
+
});
|
|
2584
|
+
|
|
2585
|
+
describe('removePreviewContact', () => {
|
|
2586
|
+
const previewPayload = {
|
|
2587
|
+
interactionId: 'interaction-123',
|
|
2588
|
+
campaignId: 'campaign-456',
|
|
2589
|
+
};
|
|
2590
|
+
|
|
2591
|
+
it('should remove preview contact successfully', async () => {
|
|
2592
|
+
const mockResponse = {trackingId: 'track-123'} as AgentContact;
|
|
2593
|
+
|
|
2594
|
+
const removePreviewContactMock = jest
|
|
2595
|
+
.spyOn(webex.cc.services.dialer, 'removePreviewContact')
|
|
2596
|
+
.mockResolvedValue(mockResponse);
|
|
2597
|
+
|
|
2598
|
+
const result = await webex.cc.removePreviewContact(previewPayload);
|
|
2599
|
+
|
|
2600
|
+
expect(LoggerProxy.info).toHaveBeenCalledWith('Removing campaign preview contact', {
|
|
2601
|
+
module: CC_FILE,
|
|
2602
|
+
method: 'removePreviewContact',
|
|
2603
|
+
});
|
|
2604
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith(
|
|
2605
|
+
'Campaign preview contact removed successfully',
|
|
2606
|
+
{
|
|
2607
|
+
module: CC_FILE,
|
|
2608
|
+
method: 'removePreviewContact',
|
|
2609
|
+
trackingId: 'track-123',
|
|
2610
|
+
interactionId: previewPayload.interactionId,
|
|
2611
|
+
}
|
|
2612
|
+
);
|
|
2613
|
+
|
|
2614
|
+
expect(removePreviewContactMock).toHaveBeenCalledWith({data: previewPayload});
|
|
2615
|
+
expect(result).toEqual(mockResponse);
|
|
2616
|
+
});
|
|
2617
|
+
|
|
2618
|
+
it('should handle error during removePreviewContact', async () => {
|
|
2619
|
+
getErrorDetailsSpy.mockRestore();
|
|
2620
|
+
getErrorDetailsSpy = jest.spyOn(Utils, 'getErrorDetails');
|
|
2621
|
+
|
|
2622
|
+
const error = {
|
|
2623
|
+
details: {
|
|
2624
|
+
trackingId: '1234',
|
|
2625
|
+
data: {
|
|
2626
|
+
reason: 'Error while performing removePreviewContact',
|
|
2627
|
+
},
|
|
2628
|
+
},
|
|
2629
|
+
};
|
|
2630
|
+
|
|
2631
|
+
jest.spyOn(webex.cc.services.dialer, 'removePreviewContact').mockRejectedValue(error);
|
|
2632
|
+
|
|
2633
|
+
await expect(webex.cc.removePreviewContact(previewPayload)).rejects.toThrow(
|
|
2634
|
+
error.details.data.reason
|
|
2635
|
+
);
|
|
2636
|
+
|
|
2637
|
+
expect(LoggerProxy.info).toHaveBeenCalledWith('Removing campaign preview contact', {
|
|
2638
|
+
module: CC_FILE,
|
|
2639
|
+
method: 'removePreviewContact',
|
|
2640
|
+
});
|
|
2641
|
+
expect(LoggerProxy.error).toHaveBeenCalledWith(
|
|
2642
|
+
`removePreviewContact failed with reason: ${error.details.data.reason}`,
|
|
2643
|
+
{module: CC_FILE, method: 'removePreviewContact', trackingId: error.details.trackingId}
|
|
2644
|
+
);
|
|
2645
|
+
expect(getErrorDetailsSpy).toHaveBeenCalledWith(error, 'removePreviewContact', CC_FILE);
|
|
2646
|
+
});
|
|
2647
|
+
});
|
|
2242
2648
|
});
|