scv-connector-base
Version:
Salesforce Service Cloud Connector Base
840 lines (785 loc) • 232 kB
JavaScript
/*
* Copyright (c) 2021, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import {
initializeConnector,
Constants,
publishEvent,
publishError,
publishLog,
AgentStatusInfo,
AgentVendorStatusInfo,
StateChangeResult,
CustomError
} from '../main/index';
import { ActiveCallsResult, InitResult, CallResult, HoldToggleResult, GenericResult, ContactsResult, PhoneContactsResult, MuteToggleResult,
ParticipantResult, RecordingToggleResult, Contact, PhoneCall, CallInfo, VendorConnector, TelephonyConnector, SharedCapabilitiesResult, VoiceCapabilitiesResult,
AgentConfigResult, Phone, HangupResult, SignedRecordingUrlResult, LogoutResult, AudioStats, StatsInfo, AudioStatsElement,
SuperviseCallResult, SupervisorHangupResult, SupervisedCallInfo, ShowStorageAccessResult, AudioDevicesResult, ACWInfo, SetAgentConfigResult, SetAgentStateResult } from '../main/index';
import baseConstants from '../main/constants';
import { log } from '../main/logger';
jest.mock('../main/logger');
const constants = {
...baseConstants,
SHARED_MESSAGE_TYPE: {
...baseConstants.SHARED_MESSAGE_TYPE,
DONT_SETUP_CONNECTOR: 'DONT_SETUP_CONNECTOR',
CALLS_IN_PROGRESS: 'CALLS_IN_PROGRESS',
INVALID_CALL: 'INVALID_CALL'
},
GENERIC_ERROR_KEY: 'GENERIC_ERROR',
AGENT_ERROR_KEY: 'AGENT_ERROR',
OPTIONAL_ERROR: 'OPTIONAL_ERROR',
CONNECTOR_CONFIG: 'CONNECTOR_CONFIG',
CONTAINER: 'CONTAINER'
}
global.console.error = jest.fn(); //do not print console.error from dispatchError
const loginFrameHeight = 300;
const invalidResult = {};
const dummyPhoneNumber = '123456789';
const dummyCallId = 'callId'
const dummyConsultCallId = 'consultCallId';
const dummyContact = new Contact({ phoneNumber: dummyPhoneNumber });
const dummyCallInfo = new CallInfo({ isOnHold: false });
const dummyPhoneCall = new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.INBOUND, callSubtype: constants.CALL_SUBTYPE.PSTN, state: 'state', callAttributes: {}, phoneNumber: '100'});
const dummyNonReplayablePhoneCall = new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.INBOUND, callSubtype: constants.CALL_SUBTYPE.PSTN, state: 'state', callAttributes: {}, phoneNumber: '100', callInfo: new CallInfo({ isReplayable: false })});
const dummyBargeAbleCall = new PhoneCall({ callId: dummyCallId, callInfo: new CallInfo({ isBargeable: true })});
const dummyBargeAbleDeskPhoneCall = new PhoneCall({ callId: dummyCallId, callInfo: new CallInfo({ isBargeable: true, isSoftphoneCall : false })});
const dummyCallback = new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.CALLBACK, callSubtype: constants.CALL_SUBTYPE.PSTN, state: 'state', callAttributes: {}, phoneNumber: '100'});
const dummyDialedCallback = new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.DIALED_CALLBACK, callSubtype: constants.CALL_SUBTYPE.PSTN, state: 'state', callAttributes: {}, phoneNumber: '100'});
const dummyRingingPhoneCall = new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.INBOUND, callSubtype: constants.CALL_SUBTYPE.PSTN, contact: dummyContact, state: constants.CALL_STATE.RINGING, callAttributes: { initialCallHasEnded: false }, phoneNumber: '100'});
const dummyConnectedPhoneCall = new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.INBOUND, callSubtype: constants.CALL_SUBTYPE.PSTN, contact: dummyContact, state: constants.CALL_STATE.CONNECTED, callAttributes: { initialCallHasEnded: false }, phoneNumber: '100'});
const dummySupervisorRingingPhoneCall = new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.INBOUND, callSubtype: constants.CALL_SUBTYPE.PSTN, contact: dummyContact, state: constants.CALL_STATE.RINGING, callAttributes: { initialCallHasEnded: false, participantType: constants.PARTICIPANT_TYPE.SUPERVISOR, hasSupervisorBargedIn: false }, phoneNumber: '100'});
const dummySupervisorConnectedPhoneCall = new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.INBOUND, callSubtype: constants.CALL_SUBTYPE.PSTN, contact: dummyContact, state: constants.CALL_STATE.CONNECTED, callAttributes: { initialCallHasEnded: false, participantType: constants.PARTICIPANT_TYPE.SUPERVISOR, hasSupervisorBargedIn: false }, phoneNumber: '100'});
const dummySupervisorBargedInPhoneCall = new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.INBOUND, callSubtype: constants.CALL_SUBTYPE.PSTN, contact: dummyContact, state: constants.CALL_STATE.CONNECTED, callAttributes: { initialCallHasEnded: false, participantType: constants.PARTICIPANT_TYPE.SUPERVISOR, hasSupervisorBargedIn: true }, phoneNumber: '100'});
const thirdPartyRemovedResult = new CallResult({ call: new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.ADD_PARTICIPANT, callSubtype: constants.CALL_SUBTYPE.PSTN, reason: dummyReason, state: 'state', callAttributes: { participantType: constants.PARTICIPANT_TYPE.THIRD_PARTY }, phoneNumber: '100'}) });
const initialCallerRemovedResult = new CallResult({ call: new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.ADD_PARTICIPANT, callSubtype: constants.CALL_SUBTYPE.PSTN, reason: dummyReason, state: 'state', callAttributes: { participantType: constants.PARTICIPANT_TYPE.INITIAL_CALLER }, phoneNumber: '100'}) });
const dummyTransferringCall = new PhoneCall({ callId: 'callId', callType: constants.CALL_TYPE.ADD_PARTICIPANT, callSubtype: constants.CALL_SUBTYPE.PSTN, contact: dummyContact, state: constants.CALL_STATE.TRANSFERRING, callAttributes: { initialCallHasEnded: false }, phoneNumber: '100'});
const dummyTransferredCall = new PhoneCall({ callId: 'dummyCallId', callType: constants.CALL_TYPE.ADD_PARTICIPANT, callSubtype: constants.CALL_SUBTYPE.PSTN, contact: dummyContact, state: constants.CALL_STATE.TRANSFERRED, callAttributes: { initialCallHasEnded: false }, phoneNumber: '100'});
const dummyConsultCall = new PhoneCall({ callId: dummyConsultCallId, callType: constants.CALL_TYPE.CONSULT, callSubtype: constants.CALL_SUBTYPE.PSTN, contact: dummyContact, state: constants.CALL_STATE.TRANSFERRED, callAttributes: { initialCallHasEnded: false }, phoneNumber: '101'});
const dummyActiveTransferringCallResult = new ActiveCallsResult({ activeCalls: [dummyTransferringCall] });
const dummyTransferringPhoneCall = new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.INBOUND, callSubtype: constants.CALL_SUBTYPE.PSTN, contact: dummyContact, state: constants.CALL_STATE.TRANSFERRING, callAttributes: { initialCallHasEnded: false }, phoneNumber: '100'});
const dummyTransferredPhoneCall = new PhoneCall({ callId: dummyCallId, callType: constants.CALL_TYPE.INBOUND, callSubtype: constants.CALL_SUBTYPE.PSTN, contact: dummyContact, state: constants.CALL_STATE.TRANSFERRED, callAttributes: { initialCallHasEnded: false, isAutoMergeOn: true }, phoneNumber: '100'});
const dummyReason = 'dummyReason';
const dummyCloseCallOnError = true;
const dummyIsOmniSoftphone = true;
const dummyCallType = constants.CALL_TYPE.OUTBOUND;
const dummyCallSubtype = constants.CALL_SUBTYPE.PSTN;
const dummyAgentStatus = 'dummyAgentStatus';
const dummyLabelName = 'dummyLabelName';
const dummyNamespace = 'dummyNamespace';
const dummyMessage = 'dummyMessage';
const dummyCustomErrorPayload = {
customError: {
labelName: dummyLabelName,
namespace: dummyNamespace,
message: dummyMessage
}
};
const initResult_showLogin = new InitResult({ showLogin: true, loginFrameHeight });
const initResult_connectorReady = new InitResult({ showLogin: false, loginFrameHeight });
const initResult_isSilentLogin = new InitResult({ isSilentLogin: true });
const initResult_showStorageAccessTrue = new InitResult({ showStorageAccess: true });
const initResult_showStorageAccessFalse = new InitResult({ showStorageAccess: false });
const emptyActiveCallsResult = new ActiveCallsResult({ activeCalls: [] });
const activeCallsResult = new ActiveCallsResult({ activeCalls: [ dummyPhoneCall ] });
const activeCallsResult1 = new ActiveCallsResult({ activeCalls: [ dummyPhoneCall, dummyRingingPhoneCall, dummyConnectedPhoneCall, dummyTransferringPhoneCall, dummyTransferredPhoneCall, dummySupervisorRingingPhoneCall, dummySupervisorConnectedPhoneCall, dummySupervisorBargedInPhoneCall ] });
const activeCallsResult2 = new ActiveCallsResult({ activeCalls: [ dummyNonReplayablePhoneCall ] });
const dummyConsultCallResult = new CallResult({ call: new PhoneCall({ callId: dummyConsultCallId, callType: constants.CALL_TYPE.CONSULT, callSubtype: constants.CALL_SUBTYPE.PSTN, reason: dummyReason, state: 'state', callAttributes: { participantType: constants.PARTICIPANT_TYPE.INITIAL_CALLER }, phoneNumber: '101'}) });
const callResult = new CallResult({ call: dummyPhoneCall });
const callbackResult = new CallResult({ call: dummyCallback });
const dialedCallbackResult = new CallResult( { call: dummyDialedCallback});
const callHangUpResult = new HangupResult({ calls: [new PhoneCall({ reason: dummyReason, callId: dummyCallId, closeCallOnError: dummyCloseCallOnError, callType: dummyCallType, callSubtype: dummyCallSubtype, agentStatus: dummyAgentStatus, isOmniSoftphone: dummyIsOmniSoftphone })]});
const muteToggleResult = new MuteToggleResult({ isMuted: true });
const unmuteToggleResult = new MuteToggleResult({ isMuted: false });
const signedRecordingUrlResult = new SignedRecordingUrlResult({ success: true, url: 'recordingUrl', duration: 10, callId: 'callId' });
const audioDevicesResult = new AudioDevicesResult({ deviceIdsPromise: Promise.resolve() });
const calls = [dummyPhoneCall];
const isThirdPartyOnHold = false;
const isCustomerOnHold = true;
const holdToggleResult = new HoldToggleResult({ isThirdPartyOnHold, isCustomerOnHold, calls });
const success = true;
const genericResult = new GenericResult({ success });
const setAgentConfigResult = new SetAgentConfigResult({ success, isSystemEvent: false });
const setAgentStateResult = new SetAgentStateResult({ success, isStatusSyncNeeded: true });
const logoutResult = new LogoutResult({ success, loginFrameHeight });
const customErrorResult = new CustomError({ labelName: dummyLabelName, namespace: dummyNamespace, message: dummyMessage });
const contacts = [ new Contact({}) ];
const contactTypes = [ Constants.CONTACT_TYPE.AGENT, Constants.CONTACT_TYPE.QUEUE ]
const phoneContactsResult = new PhoneContactsResult({ contacts, contactTypes });
const contactsResult = new ContactsResult({ contacts, contactTypes });
const participantResult = new ParticipantResult({ initialCallHasEnded: true, callInfo: dummyCallInfo, phoneNumber: dummyPhoneNumber, callId: dummyCallId });
const isRecordingPaused = true;
const contactId = 'contactId';
const initialContactId = 'initialContactId';
const instanceId = 'instanceId';
const region = 'region';
const recordingToggleResult = new RecordingToggleResult({ isRecordingPaused, contactId, initialContactId, instanceId, region });
const superviseCallResult = new SuperviseCallResult({call:dummyBargeAbleCall});
const superviseDeskphoneCallResult = new SuperviseCallResult({call:dummyBargeAbleDeskPhoneCall});
const supervisorHangupResult = new SupervisorHangupResult({calls:dummyBargeAbleDeskPhoneCall});
const supervisorHangupMultipleCallsResult = new SupervisorHangupResult({calls: [dummyBargeAbleDeskPhoneCall]});
const showStorageAccessResultSuccess = new ShowStorageAccessResult({success:true});
const showStorageAccessResultShowLogin = new ShowStorageAccessResult({success:true, showLogin: true, loginFrameHeight});
const showStorageAccessResultShowLoginFail = new ShowStorageAccessResult({success:false, showLogin: true, loginFrameHeight});
const hasMute = false;
const hasRecord = false;
const hasMerge = true;
const hasSwap = true;
const hasSignedRecordingUrl = true;
const phones = ["DESK_PHONE", "SOFT_PHONE"];
const selectedPhone = new Phone({type: "DESK_PHONE", number: "555 888 3345"});
const softphone = new Phone({type: "SOFT_PHONE"});
const supportsMos = true;
const agentConfigResult = new AgentConfigResult({ phones, selectedPhone });
const agentConfigResultWithSoftphone = new AgentConfigResult({ phones, selectedPhone : softphone});
const agentConfigPayload = {
[constants.AGENT_CONFIG_TYPE.PHONES] : agentConfigResult.phones,
[constants.AGENT_CONFIG_TYPE.SELECTED_PHONE] : agentConfigResult.selectedPhone
};
const sharedCapabilitiesResult = new SharedCapabilitiesResult({});
const voiceCapabilitiesResult = new VoiceCapabilitiesResult({ hasMute, hasRecord, hasMerge, hasSwap, hasSignedRecordingUrl });
const capabilitiesPayload = {
[constants.SHARED_CAPABILITIES_TYPE.DEBUG_ENABLED] : sharedCapabilitiesResult.debugEnabled,
[constants.SHARED_CAPABILITIES_TYPE.CONTACT_SEARCH] : sharedCapabilitiesResult.hasContactSearch,
[constants.SHARED_CAPABILITIES_TYPE.VENDOR_PROVIDED_AVAILABILITY] : sharedCapabilitiesResult.hasAgentAvailability,
[constants.SHARED_CAPABILITIES_TYPE.VENDOR_PROVIDED_QUEUE_WAIT_TIME] : sharedCapabilitiesResult.hasQueueWaitTime,
[constants.SHARED_CAPABILITIES_TYPE.TRANSFER_TO_OMNI_FLOW] : sharedCapabilitiesResult.hasTransferToOmniFlow,
[constants.SHARED_CAPABILITIES_TYPE.PENDING_STATUS_CHANGE] : sharedCapabilitiesResult.hasPendingStatusChange,
[constants.SHARED_CAPABILITIES_TYPE.SFDC_PENDING_STATE]: sharedCapabilitiesResult.hasSFDCPendingState,
[constants.SHARED_CAPABILITIES_TYPE.AUTO_ACCEPT_ENABLED]: sharedCapabilitiesResult.hasAutoAcceptEnabled,
[constants.VOICE_CAPABILITIES_TYPE.MUTE] : voiceCapabilitiesResult.hasMute,
[constants.VOICE_CAPABILITIES_TYPE.RECORD] : voiceCapabilitiesResult.hasRecord,
[constants.VOICE_CAPABILITIES_TYPE.MERGE] : voiceCapabilitiesResult.hasMerge,
[constants.VOICE_CAPABILITIES_TYPE.SWAP] : voiceCapabilitiesResult.hasSwap,
[constants.VOICE_CAPABILITIES_TYPE.BLIND_TRANSFER] : voiceCapabilitiesResult.hasBlindTransfer,
[constants.VOICE_CAPABILITIES_TYPE.SIGNED_RECORDING_URL] : voiceCapabilitiesResult.hasSignedRecordingUrl,
[constants.VOICE_CAPABILITIES_TYPE.SUPERVISOR_LISTEN_IN] : voiceCapabilitiesResult.hasSupervisorListenIn,
[constants.VOICE_CAPABILITIES_TYPE.SUPERVISOR_BARGE_IN] : voiceCapabilitiesResult.hasSupervisorBargeIn,
[constants.VOICE_CAPABILITIES_TYPE.MOS] : voiceCapabilitiesResult.supportsMos,
[constants.VOICE_CAPABILITIES_TYPE.PHONEBOOK] : voiceCapabilitiesResult.hasPhoneBook,
[constants.VOICE_CAPABILITIES_TYPE.HAS_GET_EXTERNAL_SPEAKER] : voiceCapabilitiesResult.hasGetExternalSpeakerDeviceSetting,
[constants.VOICE_CAPABILITIES_TYPE.HAS_SET_EXTERNAL_SPEAKER] : voiceCapabilitiesResult.hasSetExternalSpeakerDeviceSetting,
[constants.VOICE_CAPABILITIES_TYPE.HAS_GET_EXTERNAL_MICROPHONE] : voiceCapabilitiesResult.hasGetExternalMicrophoneDeviceSetting,
[constants.VOICE_CAPABILITIES_TYPE.HAS_SET_EXTERNAL_MICROPHONE] : voiceCapabilitiesResult.hasSetExternalMicrophoneDeviceSetting,
[constants.VOICE_CAPABILITIES_TYPE.CAN_CONSULT]: voiceCapabilitiesResult.canConsult,
[constants.VOICE_CAPABILITIES_TYPE.DIAL_PAD]: voiceCapabilitiesResult.isDialPadDisabled,
[constants.VOICE_CAPABILITIES_TYPE.HAS_HID_SUPPORT]: voiceCapabilitiesResult.isHidSupported,
[constants.VOICE_CAPABILITIES_TYPE.PHONEBOOK_DISABLE]: voiceCapabilitiesResult.isPhoneBookDisabled
};
const capabilitiesResultWithMos = new VoiceCapabilitiesResult({ hasMute, hasRecord, hasMerge, hasSwap, hasSignedRecordingUrl, supportsMos });
const capabilitiesPayloadWithMos = { ...capabilitiesPayload, [constants.VOICE_CAPABILITIES_TYPE.MOS] : capabilitiesResultWithMos.supportsMos };
const dummyActiveTransferredallResult = new ActiveCallsResult({ activeCalls: [dummyTransferredCall] });
const dummyConsultCallEndResult = new ActiveCallsResult({ activeCalls: [dummyTransferredCall, dummyConsultCall] });
const config = { config: { selectedPhone } };
const dummyStatusInfo = {statusId: 'dummyStatusId', statusApiName: 'dummyStatusApiName', statusName: 'dummyStatusName'};
const error = 'error';
const sanitizePayload = (payload) => {
if (payload && typeof(payload) === 'object') {
const isArray = Array.isArray(payload);
const sanitizedPayload = isArray ? [] : {};
if (isArray) {
payload.forEach(element => {
sanitizedPayload.push(sanitizePayload(element));
});
} else {
for (const property in payload) {
// expect.Anything() doesn't serialize well so not sanitizing that
if (property === 'error') {
sanitizedPayload[property] = payload[property];
} else if (property !== 'phoneNumber' && property !== 'number' && property !== 'name' && property !== 'callAttributes' && property !== '/reqHvcc/reqTelephonyIntegrationCertificate') {
sanitizedPayload[property] = sanitizePayload(payload[property]);
}
}
}
return sanitizedPayload;
}
return payload;
}
const dummyAudioStatsElement = new AudioStatsElement({
inputChannelStats: new StatsInfo({packetsCount: 10, packetsLost: 2, jitterBufferMillis: 10, roundTripTimeMillis: 30}),
outputChannelStats: new StatsInfo({packetsCount: 20, packetsLost: 1, jitterBufferMillis: 20, roundTripTimeMillis: 40})
});
const dummyAudioStatsElementWithAudioOutput = new AudioStatsElement({
outputChannelStats: new StatsInfo({packetsCount: 20, packetsLost: 1, jitterBufferMillis: 20, roundTripTimeMillis: 40})
});
const dummyAudioStatsElementWithAudioInput = new AudioStatsElement({
inputChannelStats: new StatsInfo({packetsCount: 10, packetsLost: 2, jitterBufferMillis: 10, roundTripTimeMillis: 30})
});
class ErrorResult {
constructor({ type, message }) {
this.type = type;
this.message = message;
}
}
const supervisedCallInfo = new SupervisedCallInfo({
callId: "callId",
voiceCallId: "voiceCallId",
callType: constants.CALL_TYPE.INBOUND,
from: "from",
to: "to",
supervisorName: "supervisorName",
isBargedIn: true
});
describe('SCVConnectorBase tests', () => {
class DemoAdapter extends VendorConnector {}
class DemoTelephonyAdapter extends TelephonyConnector {}
const adapter = new DemoAdapter();
const telephonyAdapter = new DemoTelephonyAdapter();
// VendorConnector overrides
DemoAdapter.prototype.init = jest.fn().mockResolvedValue(initResult_connectorReady);
DemoAdapter.prototype.getTelephonyConnector = jest.fn().mockResolvedValue(telephonyAdapter);
DemoAdapter.prototype.setAgentStatus = jest.fn().mockResolvedValue(setAgentStateResult);
DemoAdapter.prototype.logout = jest.fn().mockResolvedValue(logoutResult);
DemoAdapter.prototype.handleMessage = jest.fn(),
DemoAdapter.prototype.downloadLogs = jest.fn();
DemoAdapter.prototype.logMessageToVendor = jest.fn();
DemoAdapter.prototype.onAgentWorkEvent = jest.fn();
DemoAdapter.prototype.getContacts = jest.fn().mockResolvedValue(contactsResult);
DemoAdapter.prototype.getAudioDevices = jest.fn().mockResolvedValue(audioDevicesResult);
DemoAdapter.prototype.getSharedCapabilities = jest.fn().mockResolvedValue(sharedCapabilitiesResult);
// TelephonyConnector overrides
DemoTelephonyAdapter.prototype.acceptCall = jest.fn().mockResolvedValue(callResult);
DemoTelephonyAdapter.prototype.declineCall = jest.fn().mockResolvedValue(callResult);
DemoTelephonyAdapter.prototype.endCall = jest.fn().mockResolvedValue();
DemoTelephonyAdapter.prototype.mute = jest.fn().mockResolvedValue(muteToggleResult);
DemoTelephonyAdapter.prototype.unmute = jest.fn().mockResolvedValue(unmuteToggleResult);
DemoTelephonyAdapter.prototype.hold = jest.fn().mockResolvedValue(holdToggleResult);
DemoTelephonyAdapter.prototype.resume = jest.fn().mockResolvedValue(holdToggleResult);
DemoTelephonyAdapter.prototype.dial = jest.fn().mockResolvedValue(callResult);
DemoTelephonyAdapter.prototype.sendDigits = jest.fn().mockResolvedValue({});
DemoTelephonyAdapter.prototype.getPhoneContacts = jest.fn().mockResolvedValue(phoneContactsResult);
DemoTelephonyAdapter.prototype.swap = jest.fn().mockResolvedValue(holdToggleResult);
DemoTelephonyAdapter.prototype.conference = jest.fn().mockResolvedValue(holdToggleResult);
DemoTelephonyAdapter.prototype.addParticipant = jest.fn().mockResolvedValue(participantResult);
DemoTelephonyAdapter.prototype.getActiveCalls = jest.fn().mockResolvedValue(activeCallsResult);
DemoTelephonyAdapter.prototype.pauseRecording = jest.fn().mockResolvedValue(recordingToggleResult);
DemoTelephonyAdapter.prototype.resumeRecording = jest.fn().mockResolvedValue(recordingToggleResult);
DemoTelephonyAdapter.prototype.getVoiceCapabilities = jest.fn().mockResolvedValue(voiceCapabilitiesResult);
DemoTelephonyAdapter.prototype.getSignedRecordingUrl = jest.fn().mockResolvedValue(signedRecordingUrlResult);
DemoTelephonyAdapter.prototype.wrapUpCall = jest.fn();
DemoTelephonyAdapter.prototype.getAgentConfig = jest.fn().mockResolvedValue(agentConfigResult);
DemoTelephonyAdapter.prototype.setAgentConfig = jest.fn().mockResolvedValue(setAgentConfigResult);
DemoTelephonyAdapter.prototype.setAgentConfigGenericResult = jest.fn().mockResolvedValue(genericResult);
const eventMap = {};
const channelPort = {
postMessage: jest.fn()
};
const fireMessage = (type, args) => {
channelPort.onmessage(args ? {
data: {
type,
...args
}
} : {data: {type}});
};
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
connectorConfig: constants.CONNECTOR_CONFIG
},
ports: [channelPort],
origin: 'https://validOrgDomain.lightning.force.com'
};
const assertChannelPortPayload = ({ eventType, payload }) => {
expect(channelPort.postMessage).toHaveBeenCalledWith({
type: constants.SHARED_MESSAGE_TYPE.TELEPHONY_EVENT_DISPATCHED,
payload: {
telephonyEventType: eventType,
telephonyEventPayload: payload
}
});
}
const assertChannelPortPayloadEventLog = ({ eventType, payload, isError }) => {
expect(channelPort.postMessage).toHaveBeenCalledWith({
type: constants.SHARED_MESSAGE_TYPE.LOG,
payload: {
eventType,
payload: sanitizePayload(payload),
isError
}
});
}
beforeAll(() => {
window.addEventListener = (event, cb) => {
eventMap[event] = cb;
};
});
beforeEach(() => {
initializeConnector(adapter);
});
describe('SCVConnectorBase initialization tests', () => {
it('Should NOT dispatch init to the vendor after wrong initialization', () => {
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.DONT_SETUP_CONNECTOR,
connectorConfig: constants.CONNECTOR_CONFIG
},
ports: [channelPort]
};
eventMap['message'](message);
expect(adapter.init).not.toHaveBeenCalled();
});
it('Should NOT dispatch init to the vendor for a message from non Salesforce domain', () => {
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
connectorConfig: constants.CONNECTOR_CONFIG
},
ports: [channelPort],
origin: 'https://nonSfDomain.domain.com'
};
eventMap['message'](message);
expect(adapter.init).not.toHaveBeenCalled();
});
it('Should dispatch init to the vendor for a message from a Salesforce domain with port', () => {
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
connectorConfig: constants.CONNECTOR_CONFIG
},
ports: [channelPort],
origin: 'https://validOrgDomain.lightning.force.com:8080'
};
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
eventMap['message'](message);
expect(adapter.init).toHaveBeenCalledWith(constants.CONNECTOR_CONFIG);
});
it('Should dispatch init to the vendor for a message from a Salesforce soma domain', () => {
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
connectorConfig: constants.CONNECTOR_CONFIG
},
ports: [channelPort],
origin: 'https://ise240.lightning.mist78.soma.force.com'
};
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
eventMap['message'](message);
expect(adapter.init).toHaveBeenCalledWith(constants.CONNECTOR_CONFIG);
});
it('Should dispatch init to the vendor for a message from a Salesforce workspace domain', () => {
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
connectorConfig: constants.CONNECTOR_CONFIG
},
ports: [channelPort],
origin: 'https://orgfarm-d506aff378.lightning.force-com.cj6x25uar7dm14thqzvy0.wc.crm.dev'
};
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
eventMap['message'](message);
expect(adapter.init).toHaveBeenCalledWith(constants.CONNECTOR_CONFIG);
});
it('Should dispatch init to the vendor for a message from a Salesforce military domain (crmforce.mil)', () => {
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
connectorConfig: constants.CONNECTOR_CONFIG
},
ports: [channelPort],
origin: 'https://military-org.pc-rnd.crmforce.mil'
};
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
eventMap['message'](message);
expect(adapter.init).toHaveBeenCalledWith(constants.CONNECTOR_CONFIG);
});
it('Should dispatch init to the vendor for a message from a Salesforce military domain (salesforce.mil)', () => {
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
connectorConfig: constants.CONNECTOR_CONFIG
},
ports: [channelPort],
origin: 'https://dod-enterprise.pc-rnd.salesforce.mil'
};
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
eventMap['message'](message);
expect(adapter.init).toHaveBeenCalledWith(constants.CONNECTOR_CONFIG);
});
it('Should NOT dispatch init to the vendor for a message from invalid military domain', () => {
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
connectorConfig: constants.CONNECTOR_CONFIG
},
ports: [channelPort],
origin: 'https://invalid.army.mil'
};
eventMap['message'](message);
expect(adapter.init).not.toHaveBeenCalled();
});
it('Should dispatch init to the vendor for a message from a Lightning production military domain', () => {
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
connectorConfig: constants.CONNECTOR_CONFIG
},
ports: [channelPort],
origin: 'https://usa9402scrt2voicegov.lightning.crmforce.mil'
};
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
eventMap['message'](message);
expect(adapter.init).toHaveBeenCalledWith(constants.CONNECTOR_CONFIG);
});
it('Should dispatch init to the vendor for a message from a sandbox Lightning military domain', () => {
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
connectorConfig: constants.CONNECTOR_CONFIG
},
ports: [channelPort],
origin: 'https://scrtusa9402mil--scrt.sandbox.lightning.crmforce.mil'
};
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
eventMap['message'](message);
expect(adapter.init).toHaveBeenCalledWith(constants.CONNECTOR_CONFIG);
});
it('Should log the right fields when init is called', () => {
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
connectorConfig: {
"/reqGeneralInfo/reqAdapterUrl": "abc",
"invalidKey": "unknown",
"/reqHvcc/1": "1",
"/reqHvcc/2": "2",
"/reqHvcc/reqTelephonyIntegrationCertificate" : "abc"
}
},
ports: [channelPort],
origin: 'https://validOrgDomain.lightning.force.com:8080'
};
log.mockClear();
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
eventMap['message'](message);
expect(log).toBeCalledTimes(1);
expect(log.mock.calls[0][0]).toEqual({
eventType: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
payload: {
"/reqGeneralInfo/reqAdapterUrl": "abc",
"/reqHvcc/1": "1",
"/reqHvcc/2": "2"
}
});
});
it('Should log the right fields when init is called with an empty payload', () => {
const message = {
data: {
type: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
connectorConfig: undefined
},
ports: [channelPort],
origin: 'https://validOrgDomain.lightning.force.com:8080'
};
log.mockClear();
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
eventMap['message'](message);
expect(log).toBeCalledTimes(1);
expect(log.mock.calls[0][0]).toEqual({
eventType: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
payload: {}
});
});
it('Should dispatch default error after invalid initialization result', async () => {
adapter.init = jest.fn().mockResolvedValue(invalidResult);
eventMap['message'](message);
await expect(adapter.init()).resolves.toBe(invalidResult);
assertChannelPortPayload({ eventType: constants.SHARED_EVENT_TYPE.ERROR, payload: {
message: constants.SHARED_ERROR_TYPE.CAN_NOT_LOG_IN
}});
assertChannelPortPayloadEventLog({
eventType: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
payload: {
errorType: constants.SHARED_ERROR_TYPE.CAN_NOT_LOG_IN,
error: expect.anything()
},
isError: true
});
});
it('Should dispatch typed error after invalid param result', async () => {
const errorResult = new ErrorResult({ type: Constants.VOICE_ERROR_TYPE.INVALID_PARAMS });
adapter.init = jest.fn().mockRejectedValue(errorResult);
eventMap['message'](message);
await expect(adapter.init()).rejects.toBe(errorResult);
assertChannelPortPayload({ eventType: constants.SHARED_EVENT_TYPE.ERROR, payload: {
message: constants.VOICE_ERROR_TYPE.INVALID_PARAMS
}});
assertChannelPortPayloadEventLog({
eventType: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
payload: {
errorType: constants.VOICE_ERROR_TYPE.INVALID_PARAMS,
error: expect.anything()
},
isError: true
});
});
it('Should dispatch custom error after failing to setup connector', async () => {
adapter.init = jest.fn().mockRejectedValue(customErrorResult);
eventMap['message'](message);
await expect(adapter.init()).rejects.toBe(customErrorResult);
assertChannelPortPayload({ eventType: constants.SHARED_EVENT_TYPE.ERROR, payload: dummyCustomErrorPayload });
assertChannelPortPayloadEventLog({
eventType: constants.SHARED_MESSAGE_TYPE.SETUP_CONNECTOR,
payload: {
errorType: constants.SHARED_ERROR_TYPE.CUSTOM_ERROR,
error: expect.anything()
},
isError: true
});
});
it('Should dispatch SHOW_LOGIN after initialization', async () => {
adapter.init = jest.fn().mockResolvedValue(initResult_showStorageAccessTrue);
eventMap['message'](message);
await expect(adapter.init()).resolves.toBe(initResult_showStorageAccessTrue);
assertChannelPortPayload({ eventType: constants.SHARED_EVENT_TYPE.SHOW_STORAGE_ACCESS, payload: {
success: true
}});
assertChannelPortPayloadEventLog({
eventType: constants.SHARED_EVENT_TYPE.SHOW_STORAGE_ACCESS,
payload: {
success: true
},
isError: false
});
});
it('Should dispatch SHOW_LOGIN (isSilentLogin) after initialization', async () => {
adapter.init = jest.fn().mockResolvedValue(initResult_isSilentLogin);
eventMap['message'](message);
await expect(adapter.init()).resolves.toBe(initResult_isSilentLogin);
});
it('Should dispatch SHOW_LOGIN (initResult_showStorageAccess as True) after initialization', async () => {
adapter.init = jest.fn().mockResolvedValue(initResult_showStorageAccessTrue);
eventMap['message'](message);
await expect(adapter.init()).resolves.toBe(initResult_showStorageAccessTrue);
});
it('Should dispatch SHOW_LOGIN (initResult_showStorageAccess as False) after initialization', async () => {
adapter.init = jest.fn().mockResolvedValue(initResult_showStorageAccessFalse);
eventMap['message'](message);
await expect(adapter.init()).resolves.toBe(initResult_showStorageAccessFalse);
});
it('Should dispatch SHOW_STORAGE_ACCESS after initialization', async () => {
adapter.init = jest.fn().mockResolvedValue(initResult_showLogin);
eventMap['message'](message);
await expect(adapter.init()).resolves.toBe(initResult_showLogin);
assertChannelPortPayload({ eventType: constants.SHARED_EVENT_TYPE.SHOW_LOGIN, payload: {
loginFrameHeight
}});
assertChannelPortPayloadEventLog({
eventType: constants.SHARED_EVENT_TYPE.SHOW_LOGIN,
payload: {
loginFrameHeight
},
isError: false
});
});
it('Should dispatch CONNECTOR_READY after initialization', async () => {
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
eventMap['message'](message);
expect(adapter.init).toHaveBeenCalledWith(constants.CONNECTOR_CONFIG);
await expect(adapter.init()).resolves.toBe(initResult_connectorReady);
await expect(adapter.getSharedCapabilities()).resolves.toBe(sharedCapabilitiesResult);
await expect(adapter.getTelephonyConnector()).resolves.toBe(telephonyAdapter);
await expect(telephonyAdapter.getAgentConfig()).resolves.toBe(agentConfigResult);
await expect(telephonyAdapter.getVoiceCapabilities()).resolves.toBe(voiceCapabilitiesResult);
await expect(telephonyAdapter.getActiveCalls()).resolves.toBe(activeCallsResult);
expect(channelPort.postMessage).toHaveBeenCalledWith({
type: constants.SHARED_MESSAGE_TYPE.CONNECTOR_READY,
payload: {
agentConfig: agentConfigPayload,
capabilities: capabilitiesPayload,
callInProgress: dummyPhoneCall
}
});
assertChannelPortPayloadEventLog({
eventType: constants.SHARED_MESSAGE_TYPE.CONNECTOR_READY,
payload: {
agentConfig: agentConfigPayload,
capabilities: capabilitiesPayload,
callInProgress: dummyPhoneCall
},
isError: false
});
});
it('Should dispatch CONNECTOR_READY after initialization without any active calls', async () => {
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
eventMap['message'](message);
expect(adapter.init).toHaveBeenCalledWith(constants.CONNECTOR_CONFIG);
telephonyAdapter.getActiveCalls = jest.fn().mockResolvedValue(emptyActiveCallsResult);
await expect(adapter.init()).resolves.toBe(initResult_connectorReady);
await expect(adapter.getTelephonyConnector()).resolves.toBe(telephonyAdapter);
await expect(adapter.getSharedCapabilities()).resolves.toBe(sharedCapabilitiesResult);
await expect(telephonyAdapter.getAgentConfig()).resolves.toBe(agentConfigResult);
await expect(telephonyAdapter.getVoiceCapabilities()).resolves.toBe(voiceCapabilitiesResult);
await expect(telephonyAdapter.getActiveCalls()).resolves.toBe(emptyActiveCallsResult);
//expect(channelPort.postMessage).toHaveBeenCalledTimes(3);
expect(channelPort.postMessage).toHaveBeenNthCalledWith(1, {
type: constants.SHARED_MESSAGE_TYPE.LOG,
payload: {
eventType: "SETUP_CONNECTOR",
isError: false,
payload: {}
}
});
expect(channelPort.postMessage).toHaveBeenNthCalledWith(2, {
type: constants.SHARED_MESSAGE_TYPE.CONNECTOR_READY,
payload: {
agentConfig: agentConfigPayload,
capabilities: capabilitiesPayload,
callInProgress: null
}
});
assertChannelPortPayloadEventLog({
eventType: constants.SHARED_MESSAGE_TYPE.CONNECTOR_READY,
payload: {
agentConfig: agentConfigPayload,
capabilities: capabilitiesPayload,
callInProgress: null
},
isError: false
});
});
it('Should dispatch CONNECTOR_READY on a failed getAgentConfig invocation', async () => {
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
telephonyAdapter.getAgentConfig = jest.fn().mockResolvedValue(invalidResult);
telephonyAdapter.getActiveCalls = jest.fn().mockResolvedValue(activeCallsResult);
telephonyAdapter.getVoiceCapabilities = jest.fn().mockResolvedValue(voiceCapabilitiesResult);
eventMap['message'](message);
expect(adapter.init).toHaveBeenCalledWith(constants.CONNECTOR_CONFIG);
await expect(adapter.init()).resolves.toBe(initResult_connectorReady);
await expect(adapter.getSharedCapabilities()).resolves.toBe(sharedCapabilitiesResult);
await expect(adapter.getTelephonyConnector()).resolves.toBe(telephonyAdapter);
await expect(telephonyAdapter.getAgentConfig()).resolves.toBe(invalidResult);
await expect(telephonyAdapter.getVoiceCapabilities()).resolves.toBe(voiceCapabilitiesResult);
await expect(telephonyAdapter.getActiveCalls()).resolves.toBe(activeCallsResult);
expect(channelPort.postMessage).toHaveBeenCalledWith({
type: constants.SHARED_MESSAGE_TYPE.CONNECTOR_READY,
payload: {}
});
assertChannelPortPayloadEventLog({
eventType: constants.SHARED_MESSAGE_TYPE.CONNECTOR_READY,
payload: {},
isError: false
});
});
it('Should NOT dispatch invalid call to the vendor', () => {
expect(() => fireMessage(constants.SHARED_MESSAGE_TYPE.INVALID_CALL)).not.toThrowError();
expect(channelPort.postMessage).not.toHaveBeenCalledWith();
});
afterAll(() => {
telephonyAdapter.getActiveCalls = jest.fn().mockResolvedValue(activeCallsResult);
telephonyAdapter.getAgentConfig = jest.fn().mockResolvedValue(agentConfigResult);
telephonyAdapter.getVoiceCapabilities = jest.fn().mockResolvedValue(voiceCapabilitiesResult);
});
});
describe('Agent available', () => {
it('Should replay active calls on agent available', async () => {
telephonyAdapter.getActiveCalls = jest.fn().mockResolvedValue(activeCallsResult1);
fireMessage(constants.VOICE_MESSAGE_TYPE.AGENT_AVAILABLE, { isAvailable: true });
await expect(adapter.getTelephonyConnector()).resolves.toBe(telephonyAdapter);
await expect(telephonyAdapter.getActiveCalls()).resolves.toBe(activeCallsResult1);
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.PARTICIPANT_CONNECTED, payload: {
phoneNumber: dummyTransferredPhoneCall.contact.phoneNumber,
contact:dummyTransferredPhoneCall.contact,
callInfo: dummyTransferredPhoneCall.callInfo,
callAttributes: dummyTransferredPhoneCall.callAttributes,
initialCallHasEnded: dummyTransferredPhoneCall.callAttributes.initialCallHasEnded,
callId: dummyTransferredPhoneCall.callId,
connectionId: dummyTransferredPhoneCall.connectionId
}});
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.PARTICIPANT_ADDED, payload: {
phoneNumber: dummyTransferringPhoneCall.contact.phoneNumber,
contact:dummyTransferredPhoneCall.contact,
callInfo: dummyTransferringPhoneCall.callInfo,
callAttributes: dummyTransferringPhoneCall.callAttributes,
initialCallHasEnded: dummyTransferringPhoneCall.callAttributes.initialCallHasEnded,
callId: dummyTransferringPhoneCall.callId,
connectionId: dummyTransferredPhoneCall.connectionId
} });
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.CALL_STARTED, payload: dummyRingingPhoneCall });
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.CALL_CONNECTED, payload: dummyConnectedPhoneCall });
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.SUPERVISOR_CALL_STARTED, payload: dummySupervisorRingingPhoneCall });
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.SUPERVISOR_CALL_CONNECTED, payload: dummySupervisorConnectedPhoneCall });
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.SUPERVISOR_BARGED_IN, payload: dummySupervisorBargedInPhoneCall });
});
it('Should replay active calls on agent available with barge in', async () => {
await expect(adapter.getTelephonyConnector()).resolves.toBe(telephonyAdapter);
telephonyAdapter.getActiveCalls = jest.fn().mockResolvedValue(activeCallsResult1);
fireMessage(constants.VOICE_MESSAGE_TYPE.AGENT_AVAILABLE, { isAvailable: true });
await expect(adapter.getTelephonyConnector()).resolves.toBe(telephonyAdapter);
await expect(telephonyAdapter.getActiveCalls()).resolves.toBe(activeCallsResult1);
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.PARTICIPANT_CONNECTED, payload: {
phoneNumber: dummyTransferredPhoneCall.contact.phoneNumber,
contact: dummyTransferredPhoneCall.contact,
callInfo: dummyTransferredPhoneCall.callInfo,
callAttributes: dummyTransferredPhoneCall.callAttributes,
initialCallHasEnded: dummyTransferredPhoneCall.callAttributes.initialCallHasEnded,
callId: dummyTransferredPhoneCall.callId,
connectionId: dummyTransferredPhoneCall.connectionId
}});
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.PARTICIPANT_ADDED, payload: {
phoneNumber: dummyTransferringPhoneCall.contact.phoneNumber,
contact: dummyTransferredPhoneCall.contact,
callInfo: dummyTransferringPhoneCall.callInfo,
callAttributes: dummyTransferringPhoneCall.callAttributes,
initialCallHasEnded: dummyTransferringPhoneCall.callAttributes.initialCallHasEnded,
callId: dummyTransferringPhoneCall.callId,
connectionId: dummyTransferredPhoneCall.connectionId
} });
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.CALL_STARTED, payload: dummyRingingPhoneCall });
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.CALL_CONNECTED, payload: dummyConnectedPhoneCall });
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.SUPERVISOR_CALL_STARTED, payload: dummySupervisorRingingPhoneCall });
assertChannelPortPayload({ eventType: constants.VOICE_EVENT_TYPE.SUPERVISOR_CALL_CONNECTED, payload: dummySupervisorConnectedPhoneCall });
});
it ('Should NOT replay active calls on when is not replayable', async () => {
await expect(adapter.getTelephonyConnector()).resolves.toBe(telephonyAdapter);
telephonyAdapter.getActiveCalls = jest.fn().mockResolvedValue(activeCallsResult2);
fireMessage(constants.VOICE_MESSAGE_TYPE.AGENT_AVAILABLE, { isAvailable: true });
await expect(telephonyAdapter.getActiveCalls()).resolves.toBe(activeCallsResult2);
expect(channelPort.postMessage).toBeCalledTimes(1);
});
it ('Should NOT replay active calls on agent un-available', async () => {
await expect(adapter.getTelephonyConnector()).resolves.toBe(telephonyAdapter);
telephonyAdapter.getActiveCalls = jest.fn().mockResolvedValue(activeCallsResult1);
fireMessage(constants.VOICE_MESSAGE_TYPE.AGENT_AVAILABLE, { isAvailable: false });
expect(telephonyAdapter.getActiveCalls).not.toHaveBeenCalled();
});
});
describe('SCVConnectorBase event tests', () => {
beforeEach(async () => {
adapter.init = jest.fn().mockResolvedValue(initResult_connectorReady);
telephonyAdapter.getActiveCalls = jest.fn().mockResolvedValue(activeCallsResult);
eventMap['message'](message);
expect(adapter.init).toHaveBeenCalledWith(constants.CONNECTOR_CONFIG);
await expect(adapter.init()).resolves.toBe(initResult_connectorReady);
await expect(adapter.getTelephonyConnector()).resolves.toBe(telephonyAdapter);
await expect(telephonyAdapter.getAgentConfig()).resolves.toBe(agentConfigResult);
await expect(telephonyAdapter.getVoiceCapabilities()).resolves.toBe(voiceCapabilitiesResult);
await expect(telephonyAdapter.getActiveCalls()).resolves.toBe(activeCallsResult);
await new Promise((r) => setTimeout(r, 10)); // wait a hundredth of a second for the event to have been fired
expect(channelPort.postMessage).toHaveBeenCalledWith({
type: constants.SHARED_MESSAGE_TYPE.CONNECTOR_READY,
payload: {
agentConfig: agentConfigPayload,
capabilities: capabilitiesPayload,
callInProgress: dummyPhoneCall
}
});
assertChannelPortPayloadEventLog({
eventType: constants.SHARED_MESSAGE_TYPE.CONNECTOR_READY,
payload: {
agentConfig: agentConfigPayload,
capabilities: capabilitiesPayload,
callInProgress: dummyPhoneCall
},
isError: false
});
});
describe('acceptCall()', () => {
it('Should dispatch CAN_NOT_ACCEPT_THE_CALL on a failed acceptCall() invocation', async () => {
telephonyAdapter.acceptCall = jest.fn().mockResolvedValue(invalidResult);
fireMessage(constants.VOICE_MESSAGE_TYPE.ACCEPT_CALL);
await expect(adapter.getTelephonyConnector