Skip to content

Commit 68b9b88

Browse files
authored
Merge branch 'next' into log-UTs-extended-error-CAI-7234
2 parents a36ad7a + c2d00ee commit 68b9b88

File tree

40 files changed

+1395
-153
lines changed

40 files changed

+1395
-153
lines changed

docs/samples/calling/app.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,10 @@ function createDevice() {
415415
unregisterElm.disabled = false;
416416
});
417417

418+
line.on('error', (error) => {
419+
console.log('Error: ', error);
420+
});
421+
418422
// Start listening for incoming calls
419423
line.on('line:incoming_call', (callObj) => {
420424
call = callObj;
@@ -429,6 +433,7 @@ function createDevice() {
429433
}
430434
});
431435

436+
432437
call.on('disconnect', () => {
433438
callDetailsElm.innerText = `${correlationId}: Call Disconnected`;
434439
makeCallBtn.disabled = false;

packages/@webex/contact-center/src/metrics/behavioral-events.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,20 @@ const eventTaxonomyMap: Record<string, BehavioralEventTaxonomy> = {
409409
target: 'queue_fetch',
410410
verb: 'fail',
411411
},
412+
413+
// Outdial ANI API Events
414+
[METRIC_EVENT_NAMES.OUTDIAL_ANI_EP_FETCH_SUCCESS]: {
415+
product,
416+
agent: 'user',
417+
target: 'outdial_ani_ep_fetch',
418+
verb: 'complete',
419+
},
420+
[METRIC_EVENT_NAMES.OUTDIAL_ANI_EP_FETCH_FAILED]: {
421+
product,
422+
agent: 'user',
423+
target: 'outdial_ani_ep_fetch',
424+
verb: 'fail',
425+
},
412426
};
413427

414428
/**

packages/@webex/contact-center/test/unit/spec/cc.ts

Lines changed: 205 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ describe('webex.cc', () => {
118118
},
119119
config: {
120120
getAgentConfig: jest.fn(),
121+
getOutdialAniEntries: jest.fn(),
121122
},
122123
webSocketManager: mockWebSocketManager,
123124
connectionService: {
@@ -161,7 +162,7 @@ describe('webex.cc', () => {
161162
};
162163

163164
jest.spyOn(MetricsManager, 'getInstance').mockReturnValue(mockMetricsManager);
164-
jest.spyOn(Services, 'getInstance').mockReturnValue(mockServicesInstance);
165+
jest.spyOn(Services, 'getInstance').mockReturnValue(mockServicesInstance as any);
165166
jest.spyOn(TaskManager, 'getTaskManager').mockReturnValue(mockTaskManager);
166167
jest.spyOn(WebexRequest, 'getInstance').mockReturnValue(mockWebexRequest);
167168
// Instantiate ContactCenter to ensure it's fully initialized
@@ -1975,4 +1976,207 @@ describe('webex.cc', () => {
19751976
});
19761977
});
19771978
});
1979+
1980+
describe('getOutdialAniEntries', () => {
1981+
const mockOutdialANI = 'ani-123-456';
1982+
const mockParams = {
1983+
outdialANI: mockOutdialANI,
1984+
page: 0,
1985+
pageSize: 10,
1986+
search: 'test',
1987+
filter: 'active=true',
1988+
attributes: 'id,name,number',
1989+
};
1990+
1991+
beforeEach(() => {
1992+
jest.clearAllMocks();
1993+
// Reset orgId mock to return valid value
1994+
webex.credentials.getOrgId.mockReturnValue('mockOrgId');
1995+
});
1996+
1997+
it('should successfully fetch outdial ANI entries and track success metrics', async () => {
1998+
const mockResult = [
1999+
{
2000+
id: '142fba3c-8502-4446-bf6e-584fd657553a',
2001+
name: 'Test Entry',
2002+
number: '+19403016307',
2003+
},
2004+
{
2005+
id: '6f53000b-e04a-4418-9de9-ba511d2367cb',
2006+
name: 'Another Entry',
2007+
number: '+19403016308',
2008+
},
2009+
];
2010+
2011+
// Mock the service call to return successful result
2012+
webex.cc.services.config.getOutdialAniEntries.mockResolvedValue(mockResult);
2013+
2014+
const result = await webex.cc.getOutdialAniEntries(mockParams);
2015+
2016+
// Verify the service was called with correct parameters
2017+
expect(webex.cc.services.config.getOutdialAniEntries).toHaveBeenCalledWith('mockOrgId', {
2018+
outdialANI: mockOutdialANI,
2019+
page: 0,
2020+
pageSize: 10,
2021+
search: 'test',
2022+
filter: 'active=true',
2023+
attributes: 'id,name,number',
2024+
});
2025+
2026+
// Verify the result is returned correctly
2027+
expect(result).toEqual(mockResult);
2028+
2029+
// Verify success metrics are tracked
2030+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
2031+
METRIC_EVENT_NAMES.OUTDIAL_ANI_EP_FETCH_SUCCESS,
2032+
{
2033+
outdialANI: mockOutdialANI,
2034+
resultCount: 2,
2035+
},
2036+
['behavioral', 'business', 'operational']
2037+
);
2038+
2039+
// Verify success logging
2040+
expect(LoggerProxy.log).toHaveBeenCalledWith(
2041+
`Successfully retrieved outdial ANI entries for ANI ID ${mockOutdialANI}`,
2042+
{
2043+
module: CC_FILE,
2044+
method: 'getOutdialAniEntries',
2045+
}
2046+
);
2047+
});
2048+
2049+
it('should handle empty results and track success metrics with zero count', async () => {
2050+
const mockResult = [];
2051+
2052+
// Mock the service call to return empty result
2053+
webex.cc.services.config.getOutdialAniEntries.mockResolvedValue(mockResult);
2054+
2055+
const result = await webex.cc.getOutdialAniEntries({outdialANI: mockOutdialANI});
2056+
2057+
// Verify the result is returned correctly
2058+
expect(result).toEqual(mockResult);
2059+
2060+
// Verify success metrics are tracked with zero count
2061+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
2062+
METRIC_EVENT_NAMES.OUTDIAL_ANI_EP_FETCH_SUCCESS,
2063+
{
2064+
outdialANI: mockOutdialANI,
2065+
resultCount: 0,
2066+
},
2067+
['behavioral', 'business', 'operational']
2068+
);
2069+
});
2070+
2071+
it('should handle undefined results and track success metrics with zero count', async () => {
2072+
// Mock the service call to return undefined
2073+
webex.cc.services.config.getOutdialAniEntries.mockResolvedValue(undefined);
2074+
2075+
const result = await webex.cc.getOutdialAniEntries({outdialANI: mockOutdialANI});
2076+
2077+
// Verify the result is returned correctly
2078+
expect(result).toBeUndefined();
2079+
2080+
// Verify success metrics are tracked with zero count
2081+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
2082+
METRIC_EVENT_NAMES.OUTDIAL_ANI_EP_FETCH_SUCCESS,
2083+
{
2084+
outdialANI: mockOutdialANI,
2085+
resultCount: 0,
2086+
},
2087+
['behavioral', 'business', 'operational']
2088+
);
2089+
});
2090+
2091+
it('should handle service failure and track failure metrics', async () => {
2092+
const mockError = new Error('Service unavailable') as any;
2093+
mockError.details = {
2094+
trackingId: 'test-tracking-id',
2095+
orgId: 'mockOrgId',
2096+
error: 'Service error',
2097+
};
2098+
2099+
// Mock the service call to throw an error
2100+
webex.cc.services.config.getOutdialAniEntries.mockRejectedValue(mockError);
2101+
2102+
// Mock getErrorDetails to return a detailed error
2103+
const detailedError = new Error('Detailed service error');
2104+
getErrorDetailsSpy.mockReturnValue({error: detailedError});
2105+
2106+
await expect(webex.cc.getOutdialAniEntries(mockParams)).rejects.toThrow('Detailed service error');
2107+
2108+
// Verify failure metrics are tracked
2109+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
2110+
METRIC_EVENT_NAMES.OUTDIAL_ANI_EP_FETCH_FAILED,
2111+
{
2112+
...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(mockError.details),
2113+
outdialANI: mockOutdialANI,
2114+
error: mockError,
2115+
},
2116+
['behavioral', 'business', 'operational']
2117+
);
2118+
2119+
// Verify error logging
2120+
expect(LoggerProxy.error).toHaveBeenCalledWith(
2121+
`Failed to fetch outdial ANI entries for ANI ID ${mockOutdialANI} due to: ${mockError}`,
2122+
{
2123+
module: CC_FILE,
2124+
method: 'getOutdialAniEntries',
2125+
trackingId: 'test-tracking-id',
2126+
}
2127+
);
2128+
2129+
// Verify getErrorDetails was called
2130+
expect(getErrorDetailsSpy).toHaveBeenCalledWith(
2131+
mockError,
2132+
'getOutdialAniEntries',
2133+
CC_FILE
2134+
);
2135+
});
2136+
2137+
it('should throw error when orgId is not found', async () => {
2138+
// Mock getOrgId to return null
2139+
webex.credentials.getOrgId.mockReturnValue(null);
2140+
2141+
await expect(webex.cc.getOutdialAniEntries(mockParams)).rejects.toThrow('Org ID not found.');
2142+
2143+
// Verify error logging
2144+
expect(LoggerProxy.error).toHaveBeenCalledWith('Org ID not found.', {
2145+
module: CC_FILE,
2146+
method: 'getOutdialAniEntries',
2147+
});
2148+
2149+
// Verify service was not called
2150+
expect(webex.cc.services.config.getOutdialAniEntries).not.toHaveBeenCalled();
2151+
2152+
// Verify no metrics were tracked
2153+
expect(mockMetricsManager.trackEvent).not.toHaveBeenCalled();
2154+
});
2155+
2156+
it('should handle minimal parameters correctly', async () => {
2157+
const minimalParams = {outdialANI: mockOutdialANI};
2158+
const mockResult = [{id: 'test', name: 'Test', number: '+1234567890'}];
2159+
2160+
webex.cc.services.config.getOutdialAniEntries.mockResolvedValue(mockResult);
2161+
2162+
const result = await webex.cc.getOutdialAniEntries(minimalParams);
2163+
2164+
// Verify the service was called with minimal parameters
2165+
expect(webex.cc.services.config.getOutdialAniEntries).toHaveBeenCalledWith('mockOrgId', {
2166+
outdialANI: mockOutdialANI,
2167+
});
2168+
2169+
expect(result).toEqual(mockResult);
2170+
2171+
// Verify success metrics are tracked
2172+
expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
2173+
METRIC_EVENT_NAMES.OUTDIAL_ANI_EP_FETCH_SUCCESS,
2174+
{
2175+
outdialANI: mockOutdialANI,
2176+
resultCount: 1,
2177+
},
2178+
['behavioral', 'business', 'operational']
2179+
);
2180+
});
2181+
});
19782182
});

0 commit comments

Comments
 (0)