@webex/contact-center 3.12.0-next.41 → 3.12.0-next.43
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 +28 -18
- package/dist/cc.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.map +1 -1
- package/dist/services/core/Utils.js +37 -9
- package/dist/services/core/Utils.js.map +1 -1
- package/dist/types/services/config/types.d.ts +2 -1
- package/dist/types/services/core/Utils.d.ts +10 -3
- package/dist/webex.js +1 -1
- package/package.json +2 -2
- package/src/cc.ts +35 -19
- package/src/services/config/Util.ts +1 -1
- package/src/services/config/types.ts +2 -1
- package/src/services/core/Utils.ts +43 -8
- package/test/unit/spec/cc.ts +21 -15
- package/test/unit/spec/services/config/index.ts +2 -2
- package/test/unit/spec/services/core/Utils.ts +90 -7
- package/umd/contact-center.min.js +2 -2
- package/umd/contact-center.min.js.map +1 -1
package/src/cc.ts
CHANGED
|
@@ -486,7 +486,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
486
486
|
* ```
|
|
487
487
|
*/
|
|
488
488
|
public async register(): Promise<Profile> {
|
|
489
|
-
LoggerProxy.
|
|
489
|
+
LoggerProxy.log('Starting CC SDK registration', {
|
|
490
490
|
module: CC_FILE,
|
|
491
491
|
method: METHODS.REGISTER,
|
|
492
492
|
});
|
|
@@ -731,7 +731,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
731
731
|
* @private
|
|
732
732
|
*/
|
|
733
733
|
private async connectWebsocket() {
|
|
734
|
-
LoggerProxy.
|
|
734
|
+
LoggerProxy.log('Connecting to websocket', {
|
|
735
735
|
module: CC_FILE,
|
|
736
736
|
method: METHODS.CONNECT_WEBSOCKET,
|
|
737
737
|
});
|
|
@@ -758,7 +758,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
758
758
|
this.apiAIAssistant.setAIFeatureFlags(this.agentConfig.aiFeature);
|
|
759
759
|
|
|
760
760
|
if (this.agentConfig.aiFeature?.realtimeTranscripts?.enable) {
|
|
761
|
-
LoggerProxy.
|
|
761
|
+
LoggerProxy.log('Connecting to RTD websocket', {
|
|
762
762
|
module: CC_FILE,
|
|
763
763
|
method: METHODS.CONNECT_WEBSOCKET,
|
|
764
764
|
});
|
|
@@ -803,6 +803,11 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
803
803
|
|
|
804
804
|
if (this.$config && this.$config.allowAutomatedRelogin) {
|
|
805
805
|
await this.silentRelogin();
|
|
806
|
+
} else {
|
|
807
|
+
LoggerProxy.log('Skipping silent relogin: allowAutomatedRelogin is disabled', {
|
|
808
|
+
module: CC_FILE,
|
|
809
|
+
method: METHODS.CONNECT_WEBSOCKET,
|
|
810
|
+
});
|
|
806
811
|
}
|
|
807
812
|
|
|
808
813
|
return this.agentConfig;
|
|
@@ -845,26 +850,37 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
845
850
|
* ```
|
|
846
851
|
*/
|
|
847
852
|
public async stationLogin(data: AgentLogin): Promise<StationLoginResponse> {
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
method: METHODS.STATION_LOGIN,
|
|
851
|
-
});
|
|
853
|
+
const loggerContext = {module: CC_FILE, method: METHODS.STATION_LOGIN};
|
|
854
|
+
|
|
852
855
|
try {
|
|
856
|
+
LoggerProxy.log(
|
|
857
|
+
`Starting agent station login | loginOption: ${data?.loginOption} teamId: ${data?.teamId}`,
|
|
858
|
+
loggerContext
|
|
859
|
+
);
|
|
853
860
|
this.metricsManager.timeEvent([
|
|
854
861
|
METRIC_EVENT_NAMES.STATION_LOGIN_SUCCESS,
|
|
855
862
|
METRIC_EVENT_NAMES.STATION_LOGIN_FAILED,
|
|
856
863
|
]);
|
|
857
864
|
|
|
858
865
|
const dialPlanEntries = this.agentConfig?.dialPlan?.dialPlanEntity ?? [];
|
|
859
|
-
if (
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
+
if (data.loginOption === LoginOption.AGENT_DN) {
|
|
867
|
+
LoggerProxy.log(
|
|
868
|
+
`Validating dial number | dialPlanEnabled: ${!!this.agentConfig
|
|
869
|
+
?.dialPlan} | dialPlanEntryCount: ${dialPlanEntries.length}`,
|
|
870
|
+
loggerContext
|
|
871
|
+
);
|
|
872
|
+
|
|
873
|
+
if (!isValidDialNumber(data.dialNumber, dialPlanEntries)) {
|
|
874
|
+
LoggerProxy.log(
|
|
875
|
+
`Dial number validation failed | dialNumber: ${data.dialNumber} | dialPlanEntryCount: ${dialPlanEntries.length}`,
|
|
876
|
+
loggerContext
|
|
877
|
+
);
|
|
878
|
+
const error = new Error('INVALID_DIAL_NUMBER');
|
|
879
|
+
// @ts-ignore - adding custom key to the error object
|
|
880
|
+
error.details = {data: {reason: 'INVALID_DIAL_NUMBER'}} as Failure;
|
|
866
881
|
|
|
867
|
-
|
|
882
|
+
throw error;
|
|
883
|
+
}
|
|
868
884
|
}
|
|
869
885
|
|
|
870
886
|
const loginResponse = await this.services.agent.stationLogin({
|
|
@@ -1277,13 +1293,13 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1277
1293
|
private async handleConnectionLost(msg: ConnectionLostDetails): Promise<void> {
|
|
1278
1294
|
if (msg.isConnectionLost) {
|
|
1279
1295
|
// TODO: Emit an event saying connection is lost
|
|
1280
|
-
LoggerProxy.
|
|
1296
|
+
LoggerProxy.log('event=handleConnectionLost | Connection lost', {
|
|
1281
1297
|
module: CC_FILE,
|
|
1282
1298
|
method: METHODS.HANDLE_CONNECTION_LOST,
|
|
1283
1299
|
});
|
|
1284
1300
|
} else if (msg.isSocketReconnected) {
|
|
1285
1301
|
// TODO: Emit an event saying connection is re-estabilished
|
|
1286
|
-
LoggerProxy.
|
|
1302
|
+
LoggerProxy.log(
|
|
1287
1303
|
'event=handleConnectionReconnect | Connection reconnected attempting to request silent relogin',
|
|
1288
1304
|
{module: CC_FILE, method: METHODS.HANDLE_CONNECTION_LOST}
|
|
1289
1305
|
);
|
|
@@ -1298,7 +1314,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1298
1314
|
* @private
|
|
1299
1315
|
*/
|
|
1300
1316
|
private async silentRelogin(): Promise<void> {
|
|
1301
|
-
LoggerProxy.
|
|
1317
|
+
LoggerProxy.log('Starting silent relogin process', {
|
|
1302
1318
|
module: CC_FILE,
|
|
1303
1319
|
method: METHODS.SILENT_RELOGIN,
|
|
1304
1320
|
});
|
|
@@ -1320,7 +1336,7 @@ export default class ContactCenter extends WebexPlugin implements IContactCenter
|
|
|
1320
1336
|
await this.handleDeviceType(deviceType as LoginOption, dn);
|
|
1321
1337
|
|
|
1322
1338
|
if (lastStateChangeReason === 'agent-wss-disconnect') {
|
|
1323
|
-
LoggerProxy.
|
|
1339
|
+
LoggerProxy.log(
|
|
1324
1340
|
'event=requestAutoStateChange | Requesting state change to available on socket reconnect',
|
|
1325
1341
|
{module: CC_FILE, method: METHODS.SILENT_RELOGIN}
|
|
1326
1342
|
);
|
|
@@ -189,7 +189,7 @@ function parseAgentConfigs(profileData: {
|
|
|
189
189
|
|
|
190
190
|
const finalData = {
|
|
191
191
|
teams: teamData,
|
|
192
|
-
defaultDn: userData.
|
|
192
|
+
defaultDn: userData.deafultDialledNumber,
|
|
193
193
|
forceDefaultDn: tenantData.forceDefaultDn,
|
|
194
194
|
forceDefaultDnForAgent: getDefaultAgentDN(agentProfileData.agentDNValidation),
|
|
195
195
|
regexUS: tenantData.dnDefaultRegex,
|
|
@@ -279,8 +279,9 @@ export type AgentResponse = {
|
|
|
279
279
|
|
|
280
280
|
/**
|
|
281
281
|
* The default dialed number of the agent.
|
|
282
|
+
* Note: The API returns this field as "deafultDialledNumber" (with typo).
|
|
282
283
|
*/
|
|
283
|
-
|
|
284
|
+
deafultDialledNumber?: string;
|
|
284
285
|
};
|
|
285
286
|
|
|
286
287
|
/**
|
|
@@ -49,34 +49,69 @@ const getAgentActionTypeFromTask = (taskData?: TaskData): 'DIAL_NUMBER' | '' =>
|
|
|
49
49
|
return isDialNumber || isEntryPointVariant ? 'DIAL_NUMBER' : '';
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Strips characters defined in the dial plan entry from the input string.
|
|
54
|
+
*
|
|
55
|
+
* @param input - The dial number to sanitize
|
|
56
|
+
* @param strippedChars - String of characters to remove from the input
|
|
57
|
+
* @returns The sanitized input with specified characters removed
|
|
58
|
+
*/
|
|
59
|
+
export const stripDialPlanChars = (input: string, strippedChars: string): string => {
|
|
60
|
+
if (!strippedChars) {
|
|
61
|
+
return input;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const charsToStrip = new Set(strippedChars.split(''));
|
|
65
|
+
|
|
66
|
+
return input
|
|
67
|
+
.split('')
|
|
68
|
+
.filter((c) => !charsToStrip.has(c))
|
|
69
|
+
.join('');
|
|
70
|
+
};
|
|
54
71
|
|
|
55
72
|
/**
|
|
56
73
|
* Validates a dial number against the provided dial plan regex patterns.
|
|
57
74
|
* A number is valid if it matches at least one regex pattern in the dial plans.
|
|
58
|
-
*
|
|
75
|
+
* Skips validation when no dial plan entries are configured, deferring to the server.
|
|
59
76
|
*
|
|
60
77
|
* @param input - The dial number to validate
|
|
61
78
|
* @param dialPlanEntries - Array of dial plan entries containing regex patterns
|
|
62
|
-
* @returns true if the input matches at least one dial plan regex pattern, false otherwise
|
|
79
|
+
* @returns true if the input matches at least one dial plan regex pattern or no entries are configured, false otherwise
|
|
63
80
|
*/
|
|
64
81
|
export const isValidDialNumber = (
|
|
65
82
|
input: string,
|
|
66
83
|
dialPlanEntries: DialPlan['dialPlanEntity']
|
|
67
84
|
): boolean => {
|
|
85
|
+
if (!input) {
|
|
86
|
+
LoggerProxy.warn('Dial number is empty or undefined.', {
|
|
87
|
+
module: 'Utils',
|
|
88
|
+
method: 'isValidDialNumber',
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
68
94
|
if (!dialPlanEntries || dialPlanEntries.length === 0) {
|
|
69
|
-
LoggerProxy.
|
|
95
|
+
LoggerProxy.log(
|
|
96
|
+
'No dial plan entries found. Skipping client-side validation, deferring to server.',
|
|
97
|
+
{module: 'Utils', method: 'isValidDialNumber'}
|
|
98
|
+
);
|
|
70
99
|
|
|
71
|
-
return
|
|
100
|
+
return true;
|
|
72
101
|
}
|
|
73
102
|
|
|
74
103
|
return dialPlanEntries.some((entry) => {
|
|
75
104
|
try {
|
|
105
|
+
const sanitizedInput = stripDialPlanChars(input, entry.strippedChars);
|
|
76
106
|
const regex = new RegExp(entry.regex);
|
|
77
107
|
|
|
78
|
-
return regex.test(
|
|
79
|
-
} catch {
|
|
108
|
+
return regex.test(sanitizedInput);
|
|
109
|
+
} catch (e) {
|
|
110
|
+
LoggerProxy.warn(`Failed to validate dial number against entry "${entry.name}": ${e}`, {
|
|
111
|
+
module: 'Utils',
|
|
112
|
+
method: 'isValidDialNumber',
|
|
113
|
+
});
|
|
114
|
+
|
|
80
115
|
return false;
|
|
81
116
|
}
|
|
82
117
|
});
|
package/test/unit/spec/cc.ts
CHANGED
|
@@ -302,7 +302,7 @@ describe('webex.cc', () => {
|
|
|
302
302
|
const result = await webex.cc.register();
|
|
303
303
|
|
|
304
304
|
// Verify logging calls
|
|
305
|
-
expect(LoggerProxy.
|
|
305
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Starting CC SDK registration', {
|
|
306
306
|
module: CC_FILE,
|
|
307
307
|
method: 'register',
|
|
308
308
|
});
|
|
@@ -415,7 +415,7 @@ describe('webex.cc', () => {
|
|
|
415
415
|
|
|
416
416
|
await expect(webex.cc.register()).rejects.toThrow('Error while performing register');
|
|
417
417
|
|
|
418
|
-
expect(LoggerProxy.
|
|
418
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Starting CC SDK registration', {
|
|
419
419
|
module: CC_FILE,
|
|
420
420
|
method: 'register',
|
|
421
421
|
});
|
|
@@ -814,10 +814,13 @@ describe('webex.cc', () => {
|
|
|
814
814
|
const result = await webex.cc.stationLogin(options);
|
|
815
815
|
|
|
816
816
|
// Verify logging calls
|
|
817
|
-
expect(LoggerProxy.
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
817
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith(
|
|
818
|
+
`Starting agent station login | loginOption: ${options.loginOption} teamId: ${options.teamId}`,
|
|
819
|
+
{
|
|
820
|
+
module: CC_FILE,
|
|
821
|
+
method: 'stationLogin',
|
|
822
|
+
}
|
|
823
|
+
);
|
|
821
824
|
expect(LoggerProxy.log).toHaveBeenCalledWith(
|
|
822
825
|
`Agent station login completed successfully agentId: ${mockData.data.agentId} loginOption: ${mockData.data.loginOption} teamId: ${mockData.data.teamId}`,
|
|
823
826
|
{
|
|
@@ -868,10 +871,13 @@ describe('webex.cc', () => {
|
|
|
868
871
|
|
|
869
872
|
await expect(webex.cc.stationLogin(options)).rejects.toThrow(error.details.data.reason);
|
|
870
873
|
|
|
871
|
-
expect(LoggerProxy.
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
874
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith(
|
|
875
|
+
`Starting agent station login | loginOption: ${options.loginOption} teamId: ${options.teamId}`,
|
|
876
|
+
{
|
|
877
|
+
module: CC_FILE,
|
|
878
|
+
method: 'stationLogin',
|
|
879
|
+
}
|
|
880
|
+
);
|
|
875
881
|
expect(LoggerProxy.error).toHaveBeenCalledWith(
|
|
876
882
|
`stationLogin failed with reason: ${error.details.data.reason}`,
|
|
877
883
|
{module: CC_FILE, method: 'stationLogin', trackingId: error.details.trackingId}
|
|
@@ -1210,11 +1216,11 @@ describe('webex.cc', () => {
|
|
|
1210
1216
|
const webSocketManagerOnSpy = jest.spyOn(webex.cc.services.webSocketManager, 'on');
|
|
1211
1217
|
await webex.cc['silentRelogin']();
|
|
1212
1218
|
|
|
1213
|
-
expect(LoggerProxy.
|
|
1219
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Starting silent relogin process', {
|
|
1214
1220
|
module: CC_FILE,
|
|
1215
1221
|
method: 'silentRelogin',
|
|
1216
1222
|
});
|
|
1217
|
-
expect(LoggerProxy.
|
|
1223
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith(
|
|
1218
1224
|
'event=requestAutoStateChange | Requesting state change to available on socket reconnect',
|
|
1219
1225
|
{module: CC_FILE, method: 'silentRelogin'}
|
|
1220
1226
|
);
|
|
@@ -1259,7 +1265,7 @@ describe('webex.cc', () => {
|
|
|
1259
1265
|
|
|
1260
1266
|
jest.spyOn(webex.cc.services.agent, 'reload').mockRejectedValue(error);
|
|
1261
1267
|
await webex.cc['silentRelogin']();
|
|
1262
|
-
expect(LoggerProxy.
|
|
1268
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Starting silent relogin process', {
|
|
1263
1269
|
module: CC_FILE,
|
|
1264
1270
|
method: 'silentRelogin',
|
|
1265
1271
|
});
|
|
@@ -1274,7 +1280,7 @@ describe('webex.cc', () => {
|
|
|
1274
1280
|
jest.spyOn(webex.cc.services.agent, 'reload').mockRejectedValue(error);
|
|
1275
1281
|
|
|
1276
1282
|
await expect(webex.cc['silentRelogin']()).rejects.toThrow(error);
|
|
1277
|
-
expect(LoggerProxy.
|
|
1283
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Starting silent relogin process', {
|
|
1278
1284
|
module: CC_FILE,
|
|
1279
1285
|
method: 'silentRelogin',
|
|
1280
1286
|
});
|
|
@@ -1316,7 +1322,7 @@ describe('webex.cc', () => {
|
|
|
1316
1322
|
|
|
1317
1323
|
await webex.cc['silentRelogin']();
|
|
1318
1324
|
|
|
1319
|
-
expect(LoggerProxy.
|
|
1325
|
+
expect(LoggerProxy.log).toHaveBeenCalledWith('Starting silent relogin process', {
|
|
1320
1326
|
module: CC_FILE,
|
|
1321
1327
|
method: 'silentRelogin',
|
|
1322
1328
|
});
|
|
@@ -724,7 +724,7 @@ describe('AgentConfigService', () => {
|
|
|
724
724
|
agentProfileId: 'profile123',
|
|
725
725
|
siteId: 'site789',
|
|
726
726
|
dbId: 'db123',
|
|
727
|
-
|
|
727
|
+
deafultDialledNumber: '1234567890',
|
|
728
728
|
id: 'user001',
|
|
729
729
|
teamIds: ['team1', 'team2'],
|
|
730
730
|
};
|
|
@@ -864,7 +864,7 @@ describe('AgentConfigService', () => {
|
|
|
864
864
|
skillProfileId: 'skillProfile456',
|
|
865
865
|
siteId: 'site789',
|
|
866
866
|
dbId: 'db123',
|
|
867
|
-
|
|
867
|
+
deafultDialledNumber: '1234567890',
|
|
868
868
|
id: 'user001',
|
|
869
869
|
teamIds: ['team1', 'team2'],
|
|
870
870
|
};
|
|
@@ -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
|
}));
|
|
@@ -569,7 +569,7 @@ describe('Utils', () => {
|
|
|
569
569
|
const usOnlyEntry = {
|
|
570
570
|
name: 'US',
|
|
571
571
|
prefix: '1',
|
|
572
|
-
regex:
|
|
572
|
+
regex: '1[0-9]{3}[2-9][0-9]{6}([,]{1,10}[0-9]+){0,1}',
|
|
573
573
|
strippedChars: '( )-',
|
|
574
574
|
};
|
|
575
575
|
|
|
@@ -585,6 +585,11 @@ describe('Utils', () => {
|
|
|
585
585
|
const result = Utils.isValidDialNumber('+442030484377', dialPlanEntries);
|
|
586
586
|
expect(result).toBe(true);
|
|
587
587
|
});
|
|
588
|
+
|
|
589
|
+
it('should return true for a European number', () => {
|
|
590
|
+
const result = Utils.isValidDialNumber('6955577166', dialPlanEntries);
|
|
591
|
+
expect(result).toBe(true);
|
|
592
|
+
});
|
|
588
593
|
});
|
|
589
594
|
|
|
590
595
|
describe('with US-only dial plan entry', () => {
|
|
@@ -606,17 +611,95 @@ describe('Utils', () => {
|
|
|
606
611
|
});
|
|
607
612
|
});
|
|
608
613
|
|
|
609
|
-
describe('with empty dial plan entries (
|
|
610
|
-
it('should return true for
|
|
611
|
-
|
|
614
|
+
describe('with empty dial plan entries (defers to server)', () => {
|
|
615
|
+
it('should return true for any dial number', () => {
|
|
616
|
+
expect(Utils.isValidDialNumber('12223334567', [])).toBe(true);
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
it('should return true for a UK phone number', () => {
|
|
620
|
+
expect(Utils.isValidDialNumber('+442030484377', [])).toBe(true);
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
it('should return true for a European number', () => {
|
|
624
|
+
expect(Utils.isValidDialNumber('6955577166', [])).toBe(true);
|
|
625
|
+
});
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
describe('strippedChars handling', () => {
|
|
629
|
+
it('should strip characters before regex matching', () => {
|
|
630
|
+
const strictEntry = {
|
|
631
|
+
name: 'Digits Only',
|
|
632
|
+
prefix: '',
|
|
633
|
+
regex: '^[0-9]{10,15}$',
|
|
634
|
+
strippedChars: '( )-+',
|
|
635
|
+
};
|
|
636
|
+
const result = Utils.isValidDialNumber('+44 (203) 048-4377', [strictEntry]);
|
|
612
637
|
expect(result).toBe(true);
|
|
613
638
|
});
|
|
614
639
|
|
|
615
|
-
it('should
|
|
616
|
-
const
|
|
640
|
+
it('should handle entries with no strippedChars', () => {
|
|
641
|
+
const noStripEntry = {
|
|
642
|
+
name: 'No Strip',
|
|
643
|
+
prefix: '',
|
|
644
|
+
regex: '^[0-9]+$',
|
|
645
|
+
strippedChars: '',
|
|
646
|
+
};
|
|
647
|
+
expect(Utils.isValidDialNumber('12345', [noStripEntry])).toBe(true);
|
|
648
|
+
expect(Utils.isValidDialNumber('+12345', [noStripEntry])).toBe(false);
|
|
649
|
+
});
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
describe('empty or undefined dial number', () => {
|
|
653
|
+
it('should return false and log warning for undefined dial number', () => {
|
|
654
|
+
const result = Utils.isValidDialNumber(undefined as any, [anyFormatEntry]);
|
|
655
|
+
expect(result).toBe(false);
|
|
656
|
+
expect(LoggerProxy.warn).toHaveBeenCalledWith(
|
|
657
|
+
'Dial number is empty or undefined.',
|
|
658
|
+
expect.objectContaining({module: 'Utils', method: 'isValidDialNumber'})
|
|
659
|
+
);
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
it('should return false and log warning for empty string dial number', () => {
|
|
663
|
+
const result = Utils.isValidDialNumber('', [anyFormatEntry]);
|
|
664
|
+
expect(result).toBe(false);
|
|
665
|
+
expect(LoggerProxy.warn).toHaveBeenCalledWith(
|
|
666
|
+
'Dial number is empty or undefined.',
|
|
667
|
+
expect.objectContaining({module: 'Utils', method: 'isValidDialNumber'})
|
|
668
|
+
);
|
|
669
|
+
});
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
describe('invalid regex handling', () => {
|
|
673
|
+
it('should return false and log warning for invalid regex pattern', () => {
|
|
674
|
+
const badEntry = {
|
|
675
|
+
name: 'Bad Regex',
|
|
676
|
+
prefix: '',
|
|
677
|
+
regex: '[invalid(',
|
|
678
|
+
strippedChars: '',
|
|
679
|
+
};
|
|
680
|
+
const result = Utils.isValidDialNumber('12345', [badEntry]);
|
|
617
681
|
expect(result).toBe(false);
|
|
682
|
+
expect(LoggerProxy.warn).toHaveBeenCalledWith(
|
|
683
|
+
expect.stringContaining('Failed to validate dial number against entry "Bad Regex"'),
|
|
684
|
+
expect.objectContaining({module: 'Utils', method: 'isValidDialNumber'})
|
|
685
|
+
);
|
|
618
686
|
});
|
|
619
687
|
});
|
|
620
688
|
});
|
|
621
689
|
|
|
690
|
+
describe('stripDialPlanChars', () => {
|
|
691
|
+
it('should remove specified characters from input', () => {
|
|
692
|
+
expect(Utils.stripDialPlanChars('+44 (203) 048-4377', '( )-+')).toBe('442030484377');
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
it('should return input unchanged when strippedChars is empty', () => {
|
|
696
|
+
expect(Utils.stripDialPlanChars('+442030484377', '')).toBe('+442030484377');
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
it('should return input unchanged when strippedChars is null/undefined', () => {
|
|
700
|
+
expect(Utils.stripDialPlanChars('12345', null as any)).toBe('12345');
|
|
701
|
+
expect(Utils.stripDialPlanChars('12345', undefined as any)).toBe('12345');
|
|
702
|
+
});
|
|
703
|
+
});
|
|
704
|
+
|
|
622
705
|
});
|