@webex/contact-center 3.12.0-next.8 → 3.12.0-next.80
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/AGENTS.md +438 -0
- package/ai-docs/README.md +131 -0
- package/ai-docs/RULES.md +455 -0
- package/ai-docs/patterns/event-driven-patterns.md +485 -0
- package/ai-docs/patterns/testing-patterns.md +480 -0
- package/ai-docs/patterns/typescript-patterns.md +365 -0
- package/ai-docs/templates/README.md +102 -0
- package/ai-docs/templates/documentation/create-agents-md.md +240 -0
- package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
- package/ai-docs/templates/existing-service/bug-fix.md +254 -0
- package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
- package/ai-docs/templates/new-method/00-master.md +80 -0
- package/ai-docs/templates/new-method/01-requirements.md +232 -0
- package/ai-docs/templates/new-method/02-implementation.md +295 -0
- package/ai-docs/templates/new-method/03-tests.md +201 -0
- package/ai-docs/templates/new-method/04-validation.md +141 -0
- package/ai-docs/templates/new-service/00-master.md +109 -0
- package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
- package/ai-docs/templates/new-service/02-code-generation.md +346 -0
- package/ai-docs/templates/new-service/03-integration.md +178 -0
- package/ai-docs/templates/new-service/04-test-generation.md +205 -0
- package/ai-docs/templates/new-service/05-validation.md +145 -0
- package/dist/cc.js +265 -29
- package/dist/cc.js.map +1 -1
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +16 -1
- package/dist/constants.js.map +1 -1
- package/dist/index.js +20 -5
- package/dist/index.js.map +1 -1
- package/dist/metrics/behavioral-events.js +101 -0
- package/dist/metrics/behavioral-events.js.map +1 -1
- package/dist/metrics/constants.js +23 -4
- package/dist/metrics/constants.js.map +1 -1
- package/dist/services/ApiAiAssistant.js +74 -3
- package/dist/services/ApiAiAssistant.js.map +1 -1
- package/dist/services/UserPreference.js +427 -0
- package/dist/services/UserPreference.js.map +1 -0
- package/dist/services/config/Util.js +3 -3
- package/dist/services/config/Util.js.map +1 -1
- package/dist/services/config/constants.js +23 -2
- package/dist/services/config/constants.js.map +1 -1
- package/dist/services/config/types.js +49 -9
- package/dist/services/config/types.js.map +1 -1
- package/dist/services/core/Err.js.map +1 -1
- package/dist/services/core/Utils.js +107 -32
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/services/core/websocket/WebSocketManager.js +2 -1
- package/dist/services/core/websocket/WebSocketManager.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/Task.js +688 -0
- package/dist/services/task/Task.js.map +1 -0
- package/dist/services/task/TaskFactory.js +45 -0
- package/dist/services/task/TaskFactory.js.map +1 -0
- package/dist/services/task/TaskManager.js +725 -526
- package/dist/services/task/TaskManager.js.map +1 -1
- package/dist/services/task/TaskUtils.js +162 -26
- package/dist/services/task/TaskUtils.js.map +1 -1
- package/dist/services/task/constants.js +9 -2
- package/dist/services/task/constants.js.map +1 -1
- package/dist/services/task/dialer.js +78 -0
- package/dist/services/task/dialer.js.map +1 -1
- package/dist/services/task/digital/Digital.js +77 -0
- package/dist/services/task/digital/Digital.js.map +1 -0
- package/dist/services/task/state-machine/TaskStateMachine.js +837 -0
- package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
- package/dist/services/task/state-machine/actions.js +543 -0
- package/dist/services/task/state-machine/actions.js.map +1 -0
- package/dist/services/task/state-machine/constants.js +161 -0
- package/dist/services/task/state-machine/constants.js.map +1 -0
- package/dist/services/task/state-machine/guards.js +340 -0
- package/dist/services/task/state-machine/guards.js.map +1 -0
- package/dist/services/task/state-machine/index.js +53 -0
- package/dist/services/task/state-machine/index.js.map +1 -0
- package/dist/services/task/state-machine/types.js +54 -0
- package/dist/services/task/state-machine/types.js.map +1 -0
- package/dist/services/task/state-machine/uiControlsComputer.js +553 -0
- package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
- package/dist/services/task/taskDataNormalizer.js +99 -0
- package/dist/services/task/taskDataNormalizer.js.map +1 -0
- package/dist/services/task/types.js +212 -4
- package/dist/services/task/types.js.map +1 -1
- package/dist/services/task/voice/Voice.js +1042 -0
- package/dist/services/task/voice/Voice.js.map +1 -0
- package/dist/services/task/voice/WebRTC.js +149 -0
- package/dist/services/task/voice/WebRTC.js.map +1 -0
- package/dist/types/cc.d.ts +94 -1
- package/dist/types/config.d.ts +6 -0
- package/dist/types/constants.d.ts +16 -1
- package/dist/types/index.d.ts +21 -6
- package/dist/types/metrics/constants.d.ts +19 -1
- package/dist/types/services/ApiAiAssistant.d.ts +11 -3
- package/dist/types/services/UserPreference.d.ts +118 -0
- package/dist/types/services/config/constants.d.ts +21 -0
- package/dist/types/services/config/types.d.ts +171 -10
- package/dist/types/services/core/Err.d.ts +4 -0
- package/dist/types/services/core/Utils.d.ts +33 -13
- package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -0
- package/dist/types/services/core/websocket/types.d.ts +1 -1
- package/dist/types/services/index.d.ts +1 -1
- package/dist/types/services/task/Task.d.ts +157 -0
- package/dist/types/services/task/TaskFactory.d.ts +12 -0
- package/dist/types/services/task/TaskUtils.d.ts +46 -2
- package/dist/types/services/task/constants.d.ts +7 -0
- package/dist/types/services/task/dialer.d.ts +30 -0
- package/dist/types/services/task/digital/Digital.d.ts +22 -0
- package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +1144 -0
- package/dist/types/services/task/state-machine/actions.d.ts +10 -0
- package/dist/types/services/task/state-machine/constants.d.ts +107 -0
- package/dist/types/services/task/state-machine/guards.d.ts +90 -0
- package/dist/types/services/task/state-machine/index.d.ts +13 -0
- package/dist/types/services/task/state-machine/types.d.ts +267 -0
- package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
- package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
- package/dist/types/services/task/types.d.ts +603 -66
- package/dist/types/services/task/voice/Voice.d.ts +184 -0
- package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
- package/dist/types/types.d.ts +94 -0
- package/dist/types/webex.d.ts +1 -0
- package/dist/types.js +85 -0
- package/dist/types.js.map +1 -1
- package/dist/webex.js +14 -2
- package/dist/webex.js.map +1 -1
- package/package.json +15 -12
- package/src/cc.ts +329 -30
- package/src/config.ts +6 -0
- package/src/constants.ts +16 -1
- package/src/index.ts +23 -5
- package/src/metrics/ai-docs/AGENTS.md +348 -0
- package/src/metrics/ai-docs/ARCHITECTURE.md +336 -0
- package/src/metrics/behavioral-events.ts +106 -0
- package/src/metrics/constants.ts +23 -4
- package/src/services/ApiAiAssistant.ts +104 -3
- package/src/services/UserPreference.ts +509 -0
- package/src/services/agent/ai-docs/AGENTS.md +238 -0
- package/src/services/agent/ai-docs/ARCHITECTURE.md +302 -0
- package/src/services/ai-docs/AGENTS.md +384 -0
- package/src/services/config/Util.ts +3 -3
- package/src/services/config/ai-docs/AGENTS.md +253 -0
- package/src/services/config/ai-docs/ARCHITECTURE.md +424 -0
- package/src/services/config/constants.ts +25 -1
- package/src/services/config/types.ts +174 -11
- package/src/services/core/Err.ts +2 -0
- package/src/services/core/Utils.ts +123 -37
- package/src/services/core/ai-docs/AGENTS.md +379 -0
- package/src/services/core/ai-docs/ARCHITECTURE.md +696 -0
- package/src/services/core/websocket/WebSocketManager.ts +2 -0
- package/src/services/core/websocket/types.ts +1 -1
- package/src/services/index.ts +1 -1
- package/src/services/task/Task.ts +837 -0
- package/src/services/task/TaskFactory.ts +55 -0
- package/src/services/task/TaskManager.ts +738 -613
- package/src/services/task/TaskUtils.ts +205 -25
- package/src/services/task/ai-docs/AGENTS.md +455 -0
- package/src/services/task/ai-docs/ARCHITECTURE.md +585 -0
- package/src/services/task/constants.ts +7 -0
- package/src/services/task/dialer.ts +80 -0
- package/src/services/task/digital/Digital.ts +95 -0
- package/src/services/task/state-machine/TaskStateMachine.ts +1077 -0
- package/src/services/task/state-machine/actions.ts +685 -0
- package/src/services/task/state-machine/ai-docs/AGENTS.md +495 -0
- package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1135 -0
- package/src/services/task/state-machine/constants.ts +172 -0
- package/src/services/task/state-machine/guards.ts +406 -0
- package/src/services/task/state-machine/index.ts +28 -0
- package/src/services/task/state-machine/types.ts +241 -0
- package/src/services/task/state-machine/uiControlsComputer.ts +867 -0
- package/src/services/task/taskDataNormalizer.ts +137 -0
- package/src/services/task/types.ts +710 -71
- package/src/services/task/voice/Voice.ts +1267 -0
- package/src/services/task/voice/WebRTC.ts +187 -0
- package/src/types.ts +122 -2
- package/src/utils/AGENTS.md +276 -0
- package/src/webex.js +2 -0
- package/test/unit/spec/cc.ts +343 -23
- package/test/unit/spec/logger-proxy.ts +70 -0
- package/test/unit/spec/services/ApiAiAssistant.ts +122 -17
- package/test/unit/spec/services/UserPreference.ts +401 -0
- package/test/unit/spec/services/WebCallingService.ts +7 -1
- package/test/unit/spec/services/config/index.ts +30 -30
- package/test/unit/spec/services/core/Utils.ts +425 -8
- package/test/unit/spec/services/core/websocket/WebSocketManager.ts +66 -40
- package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
- package/test/unit/spec/services/task/Task.ts +477 -0
- package/test/unit/spec/services/task/TaskFactory.ts +62 -0
- package/test/unit/spec/services/task/TaskManager.ts +832 -1702
- package/test/unit/spec/services/task/TaskUtils.ts +206 -0
- package/test/unit/spec/services/task/dialer.ts +190 -0
- package/test/unit/spec/services/task/digital/Digital.ts +105 -0
- package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +1825 -0
- package/test/unit/spec/services/task/state-machine/guards.ts +479 -0
- package/test/unit/spec/services/task/state-machine/types.ts +18 -0
- package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +2020 -0
- package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
- package/test/unit/spec/services/task/voice/Voice.ts +631 -0
- package/test/unit/spec/services/task/voice/WebRTC.ts +235 -0
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
- package/dist/services/task/index.js +0 -1525
- package/dist/services/task/index.js.map +0 -1
- package/dist/types/services/task/index.d.ts +0 -650
- package/src/services/task/index.ts +0 -1801
- package/test/unit/spec/services/task/index.ts +0 -2184
|
@@ -66,7 +66,6 @@ describe('AgentConfigService', () => {
|
|
|
66
66
|
method: 'GET',
|
|
67
67
|
});
|
|
68
68
|
expect(result).toEqual(mockResponse.body);
|
|
69
|
-
|
|
70
69
|
expect(LoggerProxy.info).toHaveBeenCalledWith('Fetching user data using CI', {
|
|
71
70
|
module: CONFIG_FILE_NAME,
|
|
72
71
|
method: 'getUserUsingCI',
|
|
@@ -124,7 +123,6 @@ describe('AgentConfigService', () => {
|
|
|
124
123
|
method: 'GET',
|
|
125
124
|
});
|
|
126
125
|
expect(result).toEqual(mockResponse.body);
|
|
127
|
-
|
|
128
126
|
expect(LoggerProxy.info).toHaveBeenCalledWith('Fetching desktop profile', {
|
|
129
127
|
module: CONFIG_FILE_NAME,
|
|
130
128
|
method: 'getDesktopProfileById',
|
|
@@ -183,7 +181,6 @@ describe('AgentConfigService', () => {
|
|
|
183
181
|
method: 'GET',
|
|
184
182
|
});
|
|
185
183
|
expect(result).toEqual(mockResponse.body);
|
|
186
|
-
|
|
187
184
|
expect(LoggerProxy.info).toHaveBeenCalledWith('Fetching list of teams', {
|
|
188
185
|
module: CONFIG_FILE_NAME,
|
|
189
186
|
method: 'getListOfTeams',
|
|
@@ -263,11 +260,10 @@ describe('AgentConfigService', () => {
|
|
|
263
260
|
|
|
264
261
|
expect(mockWebexRequest.request).toHaveBeenCalledWith({
|
|
265
262
|
service: mockWccAPIURL,
|
|
266
|
-
resource: `organization/${mockOrgId}/v2/auxiliary-code?page=${page}&pageSize=${pageSize}&filter=id=in=(${filter})&attributes=${attributes}`,
|
|
263
|
+
resource: `organization/${mockOrgId}/v2/auxiliary-code?page=${page}&pageSize=${pageSize}&filter=id=in=(${filter})&attributes=${attributes}&desktopProfileFilter=true`,
|
|
267
264
|
method: 'GET',
|
|
268
265
|
});
|
|
269
266
|
expect(result).toEqual(mockResponse.body);
|
|
270
|
-
|
|
271
267
|
expect(LoggerProxy.info).toHaveBeenCalledWith('Fetching list of aux codes', {
|
|
272
268
|
module: CONFIG_FILE_NAME,
|
|
273
269
|
method: 'getListOfAuxCodes',
|
|
@@ -495,7 +491,7 @@ describe('AgentConfigService', () => {
|
|
|
495
491
|
const mockResponse = {
|
|
496
492
|
statusCode: 200,
|
|
497
493
|
body: {
|
|
498
|
-
realtimeTranscripts: {enable: true},
|
|
494
|
+
data: [{realtimeTranscripts: {enable: true}}],
|
|
499
495
|
},
|
|
500
496
|
};
|
|
501
497
|
mockWebexRequest.request.mockResolvedValue(mockResponse);
|
|
@@ -710,6 +706,32 @@ describe('AgentConfigService', () => {
|
|
|
710
706
|
});
|
|
711
707
|
|
|
712
708
|
describe('getAgentConfig', () => {
|
|
709
|
+
const mockTeamData = [
|
|
710
|
+
{id: 'team1', name: 'Support Team'},
|
|
711
|
+
{id: 'team2', name: 'Sales Team'},
|
|
712
|
+
];
|
|
713
|
+
|
|
714
|
+
const mockOrgInfo = {
|
|
715
|
+
tenantId: 'tenant123',
|
|
716
|
+
timezone: 'GMT',
|
|
717
|
+
environment: 'produs1',
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
const mockSiteInfo = {
|
|
721
|
+
id: 'c6a5451f-5ba7-49a1-aee8-fbef70c19ece',
|
|
722
|
+
name: 'Site-1',
|
|
723
|
+
multimediaProfileId: 'c5888e6f-5661-4871-9936-cbcec7658d41',
|
|
724
|
+
};
|
|
725
|
+
|
|
726
|
+
const mockURLMapping = [
|
|
727
|
+
{key: 'ACQUEON_API_URL', url: 'https://api.example.com'},
|
|
728
|
+
{key: 'ACQUEON_CONSOLE_URL', url: 'https://console.example.com'},
|
|
729
|
+
];
|
|
730
|
+
|
|
731
|
+
const mockAIFeatureFlags = {
|
|
732
|
+
data: [{realtimeTranscripts: {enable: true}}],
|
|
733
|
+
};
|
|
734
|
+
|
|
713
735
|
beforeEach(() => {
|
|
714
736
|
jest.clearAllMocks();
|
|
715
737
|
});
|
|
@@ -724,7 +746,7 @@ describe('AgentConfigService', () => {
|
|
|
724
746
|
agentProfileId: 'profile123',
|
|
725
747
|
siteId: 'site789',
|
|
726
748
|
dbId: 'db123',
|
|
727
|
-
|
|
749
|
+
deafultDialledNumber: '1234567890',
|
|
728
750
|
id: 'user001',
|
|
729
751
|
teamIds: ['team1', 'team2'],
|
|
730
752
|
};
|
|
@@ -770,12 +792,6 @@ describe('AgentConfigService', () => {
|
|
|
770
792
|
maskSensitiveData: false,
|
|
771
793
|
};
|
|
772
794
|
|
|
773
|
-
const mockSiteInfo = {
|
|
774
|
-
id: 'c6a5451f-5ba7-49a1-aee8-fbef70c19ece',
|
|
775
|
-
name: 'Site-1',
|
|
776
|
-
multimediaProfileId: 'c5888e6f-5661-4871-9936-cbcec7658d41',
|
|
777
|
-
};
|
|
778
|
-
|
|
779
795
|
const mockTenantData = {
|
|
780
796
|
timeoutDesktopInactivityEnabled: false,
|
|
781
797
|
timeoutDesktopInactivityMins: 15,
|
|
@@ -789,11 +805,6 @@ describe('AgentConfigService', () => {
|
|
|
789
805
|
callVariablesSuppressed: false,
|
|
790
806
|
};
|
|
791
807
|
|
|
792
|
-
const mockURLMapping = [
|
|
793
|
-
{key: 'ACQUEON_API_URL', url: 'https://api.example.com'},
|
|
794
|
-
{key: 'ACQUEON_CONSOLE_URL', url: 'https://console.example.com'},
|
|
795
|
-
];
|
|
796
|
-
|
|
797
808
|
const mockAuxCodes = [
|
|
798
809
|
{id: 'aux1', type: 'WRAP_UP_CODE', name: 'Wrap Up Code 1', isDefault: true},
|
|
799
810
|
{id: 'aux2', type: 'IDLE_CODE', name: 'Idle Code 1', isDefault: true},
|
|
@@ -864,7 +875,7 @@ describe('AgentConfigService', () => {
|
|
|
864
875
|
skillProfileId: 'skillProfile456',
|
|
865
876
|
siteId: 'site789',
|
|
866
877
|
dbId: 'db123',
|
|
867
|
-
|
|
878
|
+
deafultDialledNumber: '1234567890',
|
|
868
879
|
id: 'user001',
|
|
869
880
|
teamIds: ['team1', 'team2'],
|
|
870
881
|
};
|
|
@@ -915,12 +926,6 @@ describe('AgentConfigService', () => {
|
|
|
915
926
|
maskSensitiveData: true,
|
|
916
927
|
};
|
|
917
928
|
|
|
918
|
-
const mockSiteInfo = {
|
|
919
|
-
id: 'c6a5451f-5ba7-49a1-aee8-fbef70c19ece',
|
|
920
|
-
name: 'Site-1',
|
|
921
|
-
multimediaProfileId: 'c5888e6f-5661-4871-9936-cbcec7658d41',
|
|
922
|
-
};
|
|
923
|
-
|
|
924
929
|
const mockTenantData = {
|
|
925
930
|
timeoutDesktopInactivityEnabled: true,
|
|
926
931
|
timeoutDesktopInactivityMins: 15,
|
|
@@ -935,11 +940,6 @@ describe('AgentConfigService', () => {
|
|
|
935
940
|
lostConnectionRecoveryTimeout: 30,
|
|
936
941
|
};
|
|
937
942
|
|
|
938
|
-
const mockURLMapping = [
|
|
939
|
-
{key: 'ACQUEON_API_URL', url: 'https://api.example.com'},
|
|
940
|
-
{key: 'ACQUEON_CONSOLE_URL', url: 'https://console.example.com'},
|
|
941
|
-
];
|
|
942
|
-
|
|
943
943
|
const mockAuxCodes = [
|
|
944
944
|
{id: 'aux1', type: 'WRAP_UP_CODE', name: 'Wrap Up Code 1'},
|
|
945
945
|
{id: 'aux2', type: 'IDLE_CODE', name: 'Idle Code 1'},
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as Utils from '../../../../../src/services/core/Utils';
|
|
2
|
-
import {FALLBACK_DIAL_NUMBER_REGEX} from '../../../../../src/services/core/Utils';
|
|
3
2
|
import LoggerProxy from '../../../../../src/logger-proxy';
|
|
4
3
|
import WebexRequest from '../../../../../src/services/core/WebexRequest';
|
|
5
4
|
import {LoginOption, WebexRequestPayload} from '../../../../../src/types';
|
|
@@ -12,6 +11,7 @@ jest.mock('../../../../../src/logger-proxy', () => ({
|
|
|
12
11
|
log: jest.fn(),
|
|
13
12
|
error: jest.fn(),
|
|
14
13
|
info: jest.fn(),
|
|
14
|
+
warn: jest.fn(),
|
|
15
15
|
initialize: jest.fn(),
|
|
16
16
|
},
|
|
17
17
|
}));
|
|
@@ -531,7 +531,341 @@ describe('Utils', () => {
|
|
|
531
531
|
};
|
|
532
532
|
|
|
533
533
|
const result = Utils.calculateDestAgentId(interaction, currentAgentId);
|
|
534
|
-
expect(result).
|
|
534
|
+
expect(result).toBe('');
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
it('should handle CBT scenario when phone number is not a direct participant key', () => {
|
|
538
|
+
const interaction: any = {
|
|
539
|
+
media: {
|
|
540
|
+
consult: {
|
|
541
|
+
mType: 'consult',
|
|
542
|
+
participants: [currentAgentId, '5551234567'], // Phone number in media
|
|
543
|
+
},
|
|
544
|
+
},
|
|
545
|
+
participants: {
|
|
546
|
+
// Note: '5551234567' is NOT a key - this is CBT
|
|
547
|
+
'agent-uuid-cbt': {
|
|
548
|
+
type: 'Agent',
|
|
549
|
+
pType: 'dn',
|
|
550
|
+
dn: '5551234567', // Found by matching DN
|
|
551
|
+
id: 'agent-uuid-cbt',
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
const result = Utils.calculateDestAgentId(interaction, currentAgentId);
|
|
557
|
+
expect(result).toBe('agent-uuid-cbt'); // Returns the CBT agent
|
|
558
|
+
});
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
describe('calculateDestType', () => {
|
|
562
|
+
const currentAgentId = 'current-agent-123';
|
|
563
|
+
|
|
564
|
+
it('should return DIALNUMBER when pType is DN', () => {
|
|
565
|
+
const interaction: any = {
|
|
566
|
+
media: {
|
|
567
|
+
consult: {
|
|
568
|
+
mType: 'consult',
|
|
569
|
+
participants: [currentAgentId, 'dest-agent-456'],
|
|
570
|
+
},
|
|
571
|
+
},
|
|
572
|
+
participants: {
|
|
573
|
+
[currentAgentId]: {type: 'Agent', pType: 'Agent'},
|
|
574
|
+
'dest-agent-456': {type: 'Agent', pType: 'DN', id: 'dest-agent-456'},
|
|
575
|
+
},
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
const result = Utils.calculateDestType(interaction, currentAgentId);
|
|
579
|
+
expect(result).toBe('dialNumber');
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
it('should return ENTRYPOINT when pType is EP-DN', () => {
|
|
583
|
+
const interaction: any = {
|
|
584
|
+
media: {
|
|
585
|
+
consult: {
|
|
586
|
+
mType: 'consult',
|
|
587
|
+
participants: [currentAgentId, 'dest-agent-456'],
|
|
588
|
+
},
|
|
589
|
+
},
|
|
590
|
+
participants: {
|
|
591
|
+
[currentAgentId]: {type: 'Agent', pType: 'Agent'},
|
|
592
|
+
'dest-agent-456': {type: 'Agent', pType: 'EP-DN', id: 'dest-agent-456'},
|
|
593
|
+
},
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
const result = Utils.calculateDestType(interaction, currentAgentId);
|
|
597
|
+
expect(result).toBe('entryPoint');
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
it('should return lowercase pType for other types', () => {
|
|
601
|
+
const interaction: any = {
|
|
602
|
+
media: {
|
|
603
|
+
consult: {
|
|
604
|
+
mType: 'consult',
|
|
605
|
+
participants: [currentAgentId, 'dest-agent-456'],
|
|
606
|
+
},
|
|
607
|
+
},
|
|
608
|
+
participants: {
|
|
609
|
+
[currentAgentId]: {type: 'Agent', pType: 'Agent'},
|
|
610
|
+
'dest-agent-456': {type: 'Agent', pType: 'Agent', id: 'dest-agent-456'},
|
|
611
|
+
},
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
const result = Utils.calculateDestType(interaction, currentAgentId);
|
|
615
|
+
expect(result).toBe('agent');
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
it('should return agent when no destination agent found', () => {
|
|
619
|
+
const interaction: any = {
|
|
620
|
+
media: {},
|
|
621
|
+
participants: {
|
|
622
|
+
[currentAgentId]: {type: 'Agent', pType: 'Agent'},
|
|
623
|
+
},
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
const result = Utils.calculateDestType(interaction, currentAgentId);
|
|
627
|
+
expect(result).toBe('agent');
|
|
628
|
+
});
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
describe('buildConsultConferenceParamData', () => {
|
|
632
|
+
it('maps entryPoint destinationType correctly', () => {
|
|
633
|
+
const result = Utils.buildConsultConferenceParamData(
|
|
634
|
+
{
|
|
635
|
+
agentId: 'agent1',
|
|
636
|
+
destinationType: 'entryPoint',
|
|
637
|
+
destAgentId: 'ep123',
|
|
638
|
+
},
|
|
639
|
+
'interaction123'
|
|
640
|
+
);
|
|
641
|
+
|
|
642
|
+
expect(result).toEqual({
|
|
643
|
+
interactionId: 'interaction123',
|
|
644
|
+
data: {
|
|
645
|
+
agentId: 'agent1',
|
|
646
|
+
to: 'ep123',
|
|
647
|
+
destinationType: 'entryPoint',
|
|
648
|
+
},
|
|
649
|
+
});
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
it('maps EP-DN/EP_DN destinationType variants to entryPoint', () => {
|
|
653
|
+
const hyphenResult = Utils.buildConsultConferenceParamData(
|
|
654
|
+
{
|
|
655
|
+
agentId: 'agent1',
|
|
656
|
+
destinationType: 'EP-DN',
|
|
657
|
+
destAgentId: 'ep123',
|
|
658
|
+
},
|
|
659
|
+
'interaction123'
|
|
660
|
+
);
|
|
661
|
+
const underscoreResult = Utils.buildConsultConferenceParamData(
|
|
662
|
+
{
|
|
663
|
+
agentId: 'agent1',
|
|
664
|
+
destinationType: 'EP_DN',
|
|
665
|
+
destAgentId: 'ep123',
|
|
666
|
+
},
|
|
667
|
+
'interaction123'
|
|
668
|
+
);
|
|
669
|
+
|
|
670
|
+
expect(hyphenResult.data.destinationType).toBe('entryPoint');
|
|
671
|
+
expect(underscoreResult.data.destinationType).toBe('entryPoint');
|
|
672
|
+
});
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
describe('getDestAgentIdForCBT', () => {
|
|
676
|
+
it('should return destination agent ID for CBT scenario', () => {
|
|
677
|
+
const interaction: any = {
|
|
678
|
+
participants: {
|
|
679
|
+
'agent-uuid-123': {
|
|
680
|
+
type: 'Agent',
|
|
681
|
+
pType: 'dn',
|
|
682
|
+
dn: '5551234567',
|
|
683
|
+
id: 'agent-uuid-123',
|
|
684
|
+
},
|
|
685
|
+
'customer-1': {
|
|
686
|
+
type: 'Customer',
|
|
687
|
+
pType: 'Customer',
|
|
688
|
+
id: 'customer-1',
|
|
689
|
+
},
|
|
690
|
+
},
|
|
691
|
+
};
|
|
692
|
+
const consultingAgent = '5551234567'; // Phone number, not in participants as key
|
|
693
|
+
|
|
694
|
+
const result = Utils.getDestAgentIdForCBT(interaction, consultingAgent);
|
|
695
|
+
expect(result).toBe('agent-uuid-123');
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
it('should return empty string when consultingAgent is in participants (non-CBT)', () => {
|
|
699
|
+
const interaction: any = {
|
|
700
|
+
participants: {
|
|
701
|
+
'agent-123': {
|
|
702
|
+
type: 'Agent',
|
|
703
|
+
pType: 'Agent',
|
|
704
|
+
id: 'agent-123',
|
|
705
|
+
},
|
|
706
|
+
},
|
|
707
|
+
};
|
|
708
|
+
const consultingAgent = 'agent-123'; // Exists as key in participants
|
|
709
|
+
|
|
710
|
+
const result = Utils.getDestAgentIdForCBT(interaction, consultingAgent);
|
|
711
|
+
expect(result).toBe('');
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
it('should return empty string when no matching dial number found', () => {
|
|
715
|
+
const interaction: any = {
|
|
716
|
+
participants: {
|
|
717
|
+
'agent-uuid-123': {
|
|
718
|
+
type: 'Agent',
|
|
719
|
+
pType: 'dn',
|
|
720
|
+
dn: '5559999999',
|
|
721
|
+
id: 'agent-uuid-123',
|
|
722
|
+
},
|
|
723
|
+
},
|
|
724
|
+
};
|
|
725
|
+
const consultingAgent = '5551234567'; // Different number
|
|
726
|
+
|
|
727
|
+
const result = Utils.getDestAgentIdForCBT(interaction, consultingAgent);
|
|
728
|
+
expect(result).toBe('');
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
it('should return empty string when consultingAgent is empty', () => {
|
|
732
|
+
const interaction: any = {
|
|
733
|
+
participants: {
|
|
734
|
+
'agent-uuid-123': {
|
|
735
|
+
type: 'Agent',
|
|
736
|
+
pType: 'dn',
|
|
737
|
+
dn: '5551234567',
|
|
738
|
+
},
|
|
739
|
+
},
|
|
740
|
+
};
|
|
741
|
+
|
|
742
|
+
const result = Utils.getDestAgentIdForCBT(interaction, '');
|
|
743
|
+
expect(result).toBe('');
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
it('should match only when participant type is dial number and type is Agent', () => {
|
|
747
|
+
const interaction: any = {
|
|
748
|
+
participants: {
|
|
749
|
+
'participant-1': {
|
|
750
|
+
type: 'Customer',
|
|
751
|
+
pType: 'dn',
|
|
752
|
+
dn: '5551234567',
|
|
753
|
+
},
|
|
754
|
+
'participant-2': {
|
|
755
|
+
type: 'Agent',
|
|
756
|
+
pType: 'Agent',
|
|
757
|
+
dn: '5551234567',
|
|
758
|
+
},
|
|
759
|
+
'participant-3': {
|
|
760
|
+
type: 'Agent',
|
|
761
|
+
pType: 'dn',
|
|
762
|
+
dn: '5551234567',
|
|
763
|
+
id: 'correct-agent',
|
|
764
|
+
},
|
|
765
|
+
},
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
const result = Utils.getDestAgentIdForCBT(interaction, '5551234567');
|
|
769
|
+
expect(result).toBe('participant-3');
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
it('should handle case-insensitive participant type comparison', () => {
|
|
773
|
+
const interaction: any = {
|
|
774
|
+
participants: {
|
|
775
|
+
'agent-uuid': {
|
|
776
|
+
type: 'Agent',
|
|
777
|
+
pType: 'DN', // Uppercase (dial number)
|
|
778
|
+
dn: '5551234567',
|
|
779
|
+
},
|
|
780
|
+
},
|
|
781
|
+
};
|
|
782
|
+
|
|
783
|
+
const result = Utils.getDestAgentIdForCBT(interaction, '5551234567');
|
|
784
|
+
expect(result).toBe('agent-uuid');
|
|
785
|
+
});
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
describe('calculateDestAgentId', () => {
|
|
789
|
+
const currentAgentId = 'agent-123';
|
|
790
|
+
|
|
791
|
+
it('should return destAgentIdCBT when found', () => {
|
|
792
|
+
const interaction: any = {
|
|
793
|
+
media: {
|
|
794
|
+
consult: {
|
|
795
|
+
mType: 'consult',
|
|
796
|
+
participants: [currentAgentId, '5551234567'],
|
|
797
|
+
},
|
|
798
|
+
},
|
|
799
|
+
participants: {
|
|
800
|
+
'agent-uuid-456': {
|
|
801
|
+
type: 'Agent',
|
|
802
|
+
pType: 'dn',
|
|
803
|
+
dn: '5551234567',
|
|
804
|
+
id: 'agent-uuid-456',
|
|
805
|
+
},
|
|
806
|
+
},
|
|
807
|
+
};
|
|
808
|
+
|
|
809
|
+
const result = Utils.calculateDestAgentId(interaction, currentAgentId);
|
|
810
|
+
expect(result).toBe('agent-uuid-456');
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
it('should return participant id for regular agent when not CBT', () => {
|
|
814
|
+
const consultedAgentId = 'agent-456';
|
|
815
|
+
const interaction: any = {
|
|
816
|
+
media: {
|
|
817
|
+
consult: {
|
|
818
|
+
mType: 'consult',
|
|
819
|
+
participants: [currentAgentId, consultedAgentId],
|
|
820
|
+
},
|
|
821
|
+
},
|
|
822
|
+
participants: {
|
|
823
|
+
[consultedAgentId]: {
|
|
824
|
+
type: 'Agent',
|
|
825
|
+
id: consultedAgentId,
|
|
826
|
+
},
|
|
827
|
+
},
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
const result = Utils.calculateDestAgentId(interaction, currentAgentId);
|
|
831
|
+
expect(result).toBe(consultedAgentId);
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
it('should return epId for EpDn type participants', () => {
|
|
835
|
+
const consultedAgentId = 'epdn-456';
|
|
836
|
+
const interaction: any = {
|
|
837
|
+
media: {
|
|
838
|
+
consult: {
|
|
839
|
+
mType: 'consult',
|
|
840
|
+
participants: [currentAgentId, consultedAgentId],
|
|
841
|
+
},
|
|
842
|
+
},
|
|
843
|
+
participants: {
|
|
844
|
+
[consultedAgentId]: {
|
|
845
|
+
type: 'EpDn',
|
|
846
|
+
id: consultedAgentId,
|
|
847
|
+
epId: 'entry-point-id-789',
|
|
848
|
+
},
|
|
849
|
+
},
|
|
850
|
+
};
|
|
851
|
+
|
|
852
|
+
const result = Utils.calculateDestAgentId(interaction, currentAgentId);
|
|
853
|
+
expect(result).toBe('entry-point-id-789');
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
it('should return undefined when no consulting agent found', () => {
|
|
857
|
+
const interaction: any = {
|
|
858
|
+
media: {
|
|
859
|
+
mainCall: {
|
|
860
|
+
mType: 'mainCall',
|
|
861
|
+
participants: [currentAgentId],
|
|
862
|
+
},
|
|
863
|
+
},
|
|
864
|
+
participants: {},
|
|
865
|
+
};
|
|
866
|
+
|
|
867
|
+
const result = Utils.calculateDestAgentId(interaction, currentAgentId);
|
|
868
|
+
expect(result).toBe('');
|
|
535
869
|
});
|
|
536
870
|
|
|
537
871
|
it('should handle CBT scenario when phone number is not a direct participant key', () => {
|
|
@@ -569,7 +903,7 @@ describe('Utils', () => {
|
|
|
569
903
|
const usOnlyEntry = {
|
|
570
904
|
name: 'US',
|
|
571
905
|
prefix: '1',
|
|
572
|
-
regex:
|
|
906
|
+
regex: '1[0-9]{3}[2-9][0-9]{6}([,]{1,10}[0-9]+){0,1}',
|
|
573
907
|
strippedChars: '( )-',
|
|
574
908
|
};
|
|
575
909
|
|
|
@@ -585,6 +919,11 @@ describe('Utils', () => {
|
|
|
585
919
|
const result = Utils.isValidDialNumber('+442030484377', dialPlanEntries);
|
|
586
920
|
expect(result).toBe(true);
|
|
587
921
|
});
|
|
922
|
+
|
|
923
|
+
it('should return true for a European number', () => {
|
|
924
|
+
const result = Utils.isValidDialNumber('6955577166', dialPlanEntries);
|
|
925
|
+
expect(result).toBe(true);
|
|
926
|
+
});
|
|
588
927
|
});
|
|
589
928
|
|
|
590
929
|
describe('with US-only dial plan entry', () => {
|
|
@@ -606,16 +945,94 @@ describe('Utils', () => {
|
|
|
606
945
|
});
|
|
607
946
|
});
|
|
608
947
|
|
|
609
|
-
describe('with empty dial plan entries (
|
|
610
|
-
it('should return true for
|
|
611
|
-
|
|
948
|
+
describe('with empty dial plan entries (defers to server)', () => {
|
|
949
|
+
it('should return true for any dial number', () => {
|
|
950
|
+
expect(Utils.isValidDialNumber('12223334567', [])).toBe(true);
|
|
951
|
+
});
|
|
952
|
+
|
|
953
|
+
it('should return true for a UK phone number', () => {
|
|
954
|
+
expect(Utils.isValidDialNumber('+442030484377', [])).toBe(true);
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
it('should return true for a European number', () => {
|
|
958
|
+
expect(Utils.isValidDialNumber('6955577166', [])).toBe(true);
|
|
959
|
+
});
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
describe('strippedChars handling', () => {
|
|
963
|
+
it('should strip characters before regex matching', () => {
|
|
964
|
+
const strictEntry = {
|
|
965
|
+
name: 'Digits Only',
|
|
966
|
+
prefix: '',
|
|
967
|
+
regex: '^[0-9]{10,15}$',
|
|
968
|
+
strippedChars: '( )-+',
|
|
969
|
+
};
|
|
970
|
+
const result = Utils.isValidDialNumber('+44 (203) 048-4377', [strictEntry]);
|
|
612
971
|
expect(result).toBe(true);
|
|
613
972
|
});
|
|
614
973
|
|
|
615
|
-
it('should
|
|
616
|
-
const
|
|
974
|
+
it('should handle entries with no strippedChars', () => {
|
|
975
|
+
const noStripEntry = {
|
|
976
|
+
name: 'No Strip',
|
|
977
|
+
prefix: '',
|
|
978
|
+
regex: '^[0-9]+$',
|
|
979
|
+
strippedChars: '',
|
|
980
|
+
};
|
|
981
|
+
expect(Utils.isValidDialNumber('12345', [noStripEntry])).toBe(true);
|
|
982
|
+
expect(Utils.isValidDialNumber('+12345', [noStripEntry])).toBe(false);
|
|
983
|
+
});
|
|
984
|
+
});
|
|
985
|
+
|
|
986
|
+
describe('empty or undefined dial number', () => {
|
|
987
|
+
it('should return false and log warning for undefined dial number', () => {
|
|
988
|
+
const result = Utils.isValidDialNumber(undefined as any, [anyFormatEntry]);
|
|
617
989
|
expect(result).toBe(false);
|
|
990
|
+
expect(LoggerProxy.warn).toHaveBeenCalledWith(
|
|
991
|
+
'Dial number is empty or undefined.',
|
|
992
|
+
expect.objectContaining({module: 'Utils', method: 'isValidDialNumber'})
|
|
993
|
+
);
|
|
618
994
|
});
|
|
995
|
+
|
|
996
|
+
it('should return false and log warning for empty string dial number', () => {
|
|
997
|
+
const result = Utils.isValidDialNumber('', [anyFormatEntry]);
|
|
998
|
+
expect(result).toBe(false);
|
|
999
|
+
expect(LoggerProxy.warn).toHaveBeenCalledWith(
|
|
1000
|
+
'Dial number is empty or undefined.',
|
|
1001
|
+
expect.objectContaining({module: 'Utils', method: 'isValidDialNumber'})
|
|
1002
|
+
);
|
|
1003
|
+
});
|
|
1004
|
+
});
|
|
1005
|
+
|
|
1006
|
+
describe('invalid regex handling', () => {
|
|
1007
|
+
it('should return false and log warning for invalid regex pattern', () => {
|
|
1008
|
+
const badEntry = {
|
|
1009
|
+
name: 'Bad Regex',
|
|
1010
|
+
prefix: '',
|
|
1011
|
+
regex: '[invalid(',
|
|
1012
|
+
strippedChars: '',
|
|
1013
|
+
};
|
|
1014
|
+
const result = Utils.isValidDialNumber('12345', [badEntry]);
|
|
1015
|
+
expect(result).toBe(false);
|
|
1016
|
+
expect(LoggerProxy.warn).toHaveBeenCalledWith(
|
|
1017
|
+
expect.stringContaining('Failed to validate dial number against entry "Bad Regex"'),
|
|
1018
|
+
expect.objectContaining({module: 'Utils', method: 'isValidDialNumber'})
|
|
1019
|
+
);
|
|
1020
|
+
});
|
|
1021
|
+
});
|
|
1022
|
+
});
|
|
1023
|
+
|
|
1024
|
+
describe('stripDialPlanChars', () => {
|
|
1025
|
+
it('should remove specified characters from input', () => {
|
|
1026
|
+
expect(Utils.stripDialPlanChars('+44 (203) 048-4377', '( )-+')).toBe('442030484377');
|
|
1027
|
+
});
|
|
1028
|
+
|
|
1029
|
+
it('should return input unchanged when strippedChars is empty', () => {
|
|
1030
|
+
expect(Utils.stripDialPlanChars('+442030484377', '')).toBe('+442030484377');
|
|
1031
|
+
});
|
|
1032
|
+
|
|
1033
|
+
it('should return input unchanged when strippedChars is null/undefined', () => {
|
|
1034
|
+
expect(Utils.stripDialPlanChars('12345', null as any)).toBe('12345');
|
|
1035
|
+
expect(Utils.stripDialPlanChars('12345', undefined as any)).toBe('12345');
|
|
619
1036
|
});
|
|
620
1037
|
});
|
|
621
1038
|
|