Skip to content

Commit

Permalink
feat(calling): move apis, listeners from calling client to line
Browse files Browse the repository at this point in the history
  • Loading branch information
ShreyasSharma28 committed Sep 21, 2023
1 parent 0b42a95 commit 6a52910
Show file tree
Hide file tree
Showing 13 changed files with 430 additions and 225 deletions.
40 changes: 20 additions & 20 deletions docs/samples/calling/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,13 +295,13 @@ function toggleDisplay(elementId, status) {
}
}

const callNotifyEvent = new CustomEvent('callingClient:incoming_call', {
const callNotifyEvent = new CustomEvent('line:incoming_call', {
detail: {
callObject: call,
},
});

callListener.addEventListener('callingClient:incoming_call', (myEvent) => {
callListener.addEventListener('line:incoming_call', (myEvent) => {
console.log('Received incoming call');
answerElm.disabled = false;
const callerDisplay = myEvent.detail.callObject.getCallerInfo();
Expand Down Expand Up @@ -331,9 +331,9 @@ function createDevice() {
});

// Start listening for incoming calls
callingClient.on('callingClient:incoming_call', (callObj) => {
line.on('line:incoming_call', (callObj) => {
call = callObj;
call.on('call:caller_id', (CallerIdEmitter) => {
call.on('caller_id', (CallerIdEmitter) => {
callDetailsElm.innerText = `Name: ${CallerIdEmitter.callerId.name}, Number: ${CallerIdEmitter.callerId.num}, Avatar: ${CallerIdEmitter.callerId.avatarSrc}, UserId: ${CallerIdEmitter.callerId.id}`;
console.log(
`callerId : Name: ${CallerIdEmitter.callerId.name}, Number: ${CallerIdEmitter.callerId.name}, Avatar: ${CallerIdEmitter.callerId.avatarSrc}, UserId: ${CallerIdEmitter.callerId.id}`
Expand Down Expand Up @@ -381,14 +381,14 @@ function muteUnmute() {
function holdResume() {
const elem = document.getElementById('hold_button');

call.on('call:held', (correlationId) => {
call.on('held', (correlationId) => {
if (elem.value === 'Hold') {
callDetailsElm.innerText = 'Call is held';
elem.value = 'Resume';
}
});

call.on('call:resumed', (correlationId) => {
call.on('resumed', (correlationId) => {
if (elem.value === 'Resume') {
callDetailsElm.innerText = 'Call is Resumed';
elem.value = 'Hold';
Expand Down Expand Up @@ -452,12 +452,12 @@ function createCall(e) {
console.log(destination.value);

console.log(destination.value);
call = callingClient.makeCall({
call = line.makeCall({
type: 'uri',
address: destination.value,
});

call.on('call:caller_id', (CallerIdEmitter) => {
call.on('caller_id', (CallerIdEmitter) => {
callDetailsElm.innerText = `Name: ${CallerIdEmitter.callerId.name}, Number: ${CallerIdEmitter.callerId.num}, Avatar: ${CallerIdEmitter.callerId.avatarSrc} , UserId: ${CallerIdEmitter.callerId.id}`;
console.log(
`callerId : Name: ${CallerIdEmitter.callerId.name}, Number: ${CallerIdEmitter.callerId.num}, Avatar: ${CallerIdEmitter.callerId.avatarSrc}, UserId: ${CallerIdEmitter.callerId.id}`
Expand All @@ -468,17 +468,17 @@ function createCall(e) {
}
});

call.on('call:progress', (correlationId) => {
call.on('progress', (correlationId) => {
callDetailsElm.innerText = `${correlationId}: Call Progress`;
});
call.on('call:connect', (correlationId) => {
call.on('connect', (correlationId) => {
callDetailsElm.innerText = `${correlationId}: Call Connect`;
});
call.on('call:established', (correlationId) => {
call.on('established', (correlationId) => {
callDetailsElm.innerText = `${correlationId}: Call Established`;
transferElm.disabled = false;
});
call.on('call:disconnect', (correlationId) => {
call.on('disconnect', (correlationId) => {
callDetailsElm.innerText = `${correlationId}: Call Disconnected`;

if (transferInitiated) {
Expand All @@ -488,7 +488,7 @@ function createCall(e) {
}
});

call.on('call:remote_media', (track) => {
call.on('remote_media', (track) => {
document.getElementById('remote-audio').srcObject = new MediaStream([track]);
});

Expand Down Expand Up @@ -530,20 +530,20 @@ function commitTransfer() {
address: digit,
});

callTranferObj.on('call:remote_media', (track) => {
callTranferObj.on('remote_media', (track) => {
document.getElementById('remote-audio').srcObject = new MediaStream([track]);

transferDetailsElm.innerText = `Got remote audio`;
});

callTranferObj.on('call:established', (correlationId) => {
callTranferObj.on('established', (correlationId) => {
transferDetailsElm.innerText = `${correlationId}: Transfer target connected`;
endSecondElm.disabled = false;
transferElm.innerHTML = 'Commit';
transferElm.disabled = false;
});

callTranferObj.on('call:disconnect', (correlationId) => {
callTranferObj.on('disconnect', (correlationId) => {
endSecondElm.disabled = true;
callTranferObj = null;
});
Expand All @@ -564,7 +564,7 @@ function initiateTransfer() {
if (!call.isHeld()) {
call.doHoldResume();

call.on('call:held', (correlationId) => {
call.on('held', (correlationId) => {
transferDetailsElm.innerText = `Placed call: ${call.getCorrelationId()} on hold`;
commitTransfer();
});
Expand Down Expand Up @@ -646,16 +646,16 @@ function answer() {
answerElm.disabled = true;

if (call) {
call.on('call:established', (correlationId) => {
call.on('established', (correlationId) => {
callDetailsElm.innerText = `${correlationId}: Call Established`;
console.log(` Call is Established: ${correlationId}`);
endElm.disabled = false;
});
call.on('call:disconnect', () => {
call.on('disconnect', () => {
console.log(` Call is Disconnected: ${correlationId}`);
});

call.on('call:remote_media', (track) => {
call.on('remote_media', (track) => {
document.getElementById('remote-audio').srcObject = new MediaStream([track]);
});

Expand Down
146 changes: 65 additions & 81 deletions packages/calling/src/CallingClient/CallingClient.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {Mutex} from 'async-mutex';
import {LOGGER} from '../Logger/types';
import {getTestUtilsWebex, getMockRequestTemplate, getMockDeviceInfo} from '../common/testUtil';
import {
CallDirection,
CallType,
MobiusStatus,
ServiceIndicator,
WebexRequestPayload,
} from '../common/types';
getTestUtilsWebex,
getMockRequestTemplate,
getMockDeviceInfo,
getMobiusDiscoveryResponse,
} from '../common/testUtil';
import {CallType, MobiusStatus, ServiceIndicator, WebexRequestPayload} from '../common/types';
/* eslint-disable dot-notation */
import {CallSessionEvent, EVENT_KEYS, MOBIUS_EVENT_KEYS} from '../Events/types';
import log from '../Logger';
Expand All @@ -23,7 +23,7 @@ import {
SPARK_USER_AGENT,
} from './constants';
import {MOCK_MULTIPLE_SESSIONS_EVENT, MOCK_SESSION_EVENT} from './callRecordFixtures';
import {ILine} from './line/types';
import {ILine, LineStatus} from './line/types';
import {
ipPayload,
regionBody,
Expand All @@ -34,6 +34,10 @@ import {
uri,
myIP,
} from './callingClientFixtures';
import Line from './line';
import {filterMobiusUris} from '../common/Utils';
import {URL} from './registration/registerFixtures';
import {ICall} from './calling/types';

describe('CallingClient Tests', () => {
// Common initializers
Expand Down Expand Up @@ -571,10 +575,31 @@ describe('CallingClient Tests', () => {

// Calling related test cases
describe('Calling tests', () => {
let callingClient: ICallingClient;
const mutex = new Mutex();
const userId = webex.internal.device.userId;
const clientDeviceUri = webex.internal.device.url;
const mobiusUris = filterMobiusUris(getMobiusDiscoveryResponse(), URL);
const primaryMobiusUris = jest.fn(() => mobiusUris.primary);
const backupMobiusUris = jest.fn(() => mobiusUris.backup);

let callingClient;
let line: Line;

beforeAll(async () => {
callingClient = await createClient(webex, {logger: {level: LOGGER.INFO}});
callingClient = await createClient(webex);
line = new Line(
userId,
clientDeviceUri,
LineStatus.ACTIVE,
mutex,
primaryMobiusUris(),
backupMobiusUris(),
LOGGER.INFO
);
const calls = Object.values(callManager.getActiveCalls());
calls.forEach((call) => {
call.end();
});
});

afterAll(() => {
Expand All @@ -588,85 +613,44 @@ describe('CallingClient Tests', () => {
);
});

it('Return a successful call object while making call', () => {
const call = callingClient.makeCall({address: '5003', type: CallType.URI});

expect(call).toBeTruthy();
expect(callingClient.getCall(call ? call.getCorrelationId() : '')).toBe(call);
expect(call ? call['direction'] : undefined).toStrictEqual(CallDirection.OUTBOUND);
call?.end();
it('returns undefined when there is no connected call', () => {
line.register();
line.makeCall({address: '123456', type: CallType.URI});
expect(callingClient.getConnectedCall()).toEqual(undefined);
});

it('Return a successful call object while making call to FAC codes', () => {
const call = callingClient.makeCall({address: '*25', type: CallType.URI});

expect(call).toBeTruthy();
expect(call ? call['direction'] : undefined).toStrictEqual(CallDirection.OUTBOUND);
call?.end();
});

it('Remove spaces from dialled number while making call', () => {
const call = callingClient.makeCall({address: '+91 123 456 7890', type: CallType.URI});

expect(call).toBeTruthy();
expect(call ? call['direction'] : undefined).toStrictEqual(CallDirection.OUTBOUND);
expect(call ? call['destination']['address'] : undefined).toStrictEqual('tel:+911234567890');
call?.end();
});

it('Remove hyphen from dialled number while making call', () => {
const call = callingClient.makeCall({address: '123-456-7890', type: CallType.URI});

expect(call).toBeTruthy();
expect(call ? call['direction'] : undefined).toStrictEqual(CallDirection.OUTBOUND);
expect(call ? call['destination']['address'] : undefined).toStrictEqual('tel:1234567890');
call?.end();
it('returns the connected call', () => {
line.register();
const call1 = line.makeCall({address: '5893', type: CallType.URI});
line.makeCall({address: '1234', type: CallType.URI});
if (call1) jest.spyOn(call1, 'isConnected').mockReturnValue(true);
expect(callingClient.getConnectedCall()).toEqual(call1);
});
it('returns all active calls', () => {
callingClient.lineDict = {
mockDeviceId: {lineId: 'mockLineId'} as ILine,
mockDeviceId2: {lineId: 'mockLineId2'} as ILine,
};

it('attempt to create call with incorrect number format 1', (done) => {
// There may be other listeners , which may create race
callingClient.removeAllListeners(EVENT_KEYS.ERROR);
const createCallSpy = jest.spyOn(callManager, 'createCall');

callingClient.on(EVENT_KEYS.ERROR, (error) => {
expect(error.message).toBe(
'An invalid phone number was detected. Check the number and try again.'
);
done();
});
try {
const call = callingClient.makeCall({address: 'select#$@^^', type: CallType.URI});
const mockCall = line.makeCall({address: '1234', type: CallType.URI});
const mockCall2 = line.makeCall({address: '5678', type: CallType.URI});
const mockCall3 = line.makeCall({address: '9101', type: CallType.URI});

expect(call).toBeUndefined();
expect(createCallSpy).toBeCalledTimes(0);
} catch (error) {
done(error);
}
expect.assertions(3);
});
mockCall.lineId = 'mockLineId';
mockCall2.lineId = 'mockLineId2';
mockCall3.lineId = 'mockLineId2';

it('attempt to create call with incorrect number format 2', (done) => {
expect.assertions(3);
// There may be other listeners , which may create race
callingClient.removeAllListeners(EVENT_KEYS.ERROR);
const createCallSpy = jest.spyOn(callManager, 'createCall');
const mockActiveCalls: Record<string, ICall> = {
mockCorrelationId: mockCall as ICall,
mockCorrelationId2: mockCall2 as ICall,
mockCorrelationId3: mockCall3 as ICall,
};

callingClient.on(EVENT_KEYS.ERROR, (error) => {
expect(error.message).toBe(
'An invalid phone number was detected. Check the number and try again.'
);
done();
jest.spyOn(callManager, 'getActiveCalls').mockReturnValue(mockActiveCalls);
expect(callingClient.getActiveCalls()).toEqual({
mockLineId: [mockCall],
mockLineId2: [mockCall2, mockCall3],
});

try {
const call = callingClient.makeCall({address: '+1@8883332505', type: CallType.URI});

expect(call).toBeUndefined();
expect(createCallSpy).toBeCalledTimes(0);
} catch (error) {
done(error);
}
expect.assertions(3);
});
});

Expand Down
Loading

0 comments on commit 6a52910

Please sign in to comment.