Skip to content

Commit

Permalink
fix(plugin-cc): event emission fix for different disconnect flows (#4036
Browse files Browse the repository at this point in the history
)

Co-authored-by: Sreekanth Narayanan <131740035+sreenara@users.noreply.github.com>
  • Loading branch information
Kesari3008 and sreenara authored Dec 20, 2024
1 parent 9880b88 commit 510a290
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 35 deletions.
8 changes: 7 additions & 1 deletion docs/samples/contact-center/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,13 @@ function registerTaskListeners(task) {
task.on('task:media', (track) => {
document.getElementById('remote-audio').srcObject = new MediaStream([track]);
});
task.on('task:end', (task) => {
task.on('task:end', (wrapupData) => {
if (!wrapupData.wrapupRequired) {
answerElm.disabled = true;
declineElm.disabled = true;
console.log('Call ended without call being answered');
}
incomingDetailsElm.innerText = '';
if (!endElm.disabled) {
console.info('Call ended successfully by the external user');
updateButtonsPostEndCall();
Expand Down
1 change: 1 addition & 0 deletions packages/@webex/plugin-cc/src/services/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const CC_EVENTS = {
AGENT_OFFER_CONTACT: 'AgentOfferContact',
AGENT_CONTACT_ASSIGNED: 'AgentContactAssigned',
AGENT_CONTACT_ASSIGN_FAILED: 'AgentContactAssignFailed',
AGENT_CONTACT_OFFER_RONA: 'AgentOfferContactRona',
AGENT_CONTACT_HELD: 'AgentContactHeld',
AGENT_CONTACT_HOLD_FAILED: 'AgentContactHoldFailed',
AGENT_CONTACT_UNHELD: 'AgentContactUnheld',
Expand Down
14 changes: 9 additions & 5 deletions packages/@webex/plugin-cc/src/services/task/TaskManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,20 @@ export default class TaskManager extends EventEmitter {
this.currentTask = this.currentTask.updateTaskData(payload.data);
this.currentTask.emit(TASK_EVENTS.TASK_ASSIGNED, this.currentTask);
break;
case CC_EVENTS.AGENT_CONTACT_OFFER_RONA:
case CC_EVENTS.CONTACT_ENDED:
this.emit(TASK_EVENTS.TASK_UNASSIGNED, this.currentTask);
if (this.webCallingService.loginOption === LoginOption.BROWSER) {
this.currentTask.unregisterWebCallListeners();
this.webCallingService.unregisterCallListeners();
if (this.currentTask.data.interaction.state === 'new') {
this.currentTask.emit(TASK_EVENTS.TASK_END, {wrapupRequired: false});
if (this.webCallingService.loginOption === LoginOption.BROWSER) {
this.currentTask.unregisterWebCallListeners();
this.webCallingService.unregisterCallListeners();
}
this.removeCurrentTaskFromCollection();
}
break;
case CC_EVENTS.AGENT_WRAPUP:
this.currentTask = this.currentTask.updateTaskData(payload.data);
this.currentTask.emit(TASK_EVENTS.TASK_END, this.currentTask);
this.currentTask.emit(TASK_EVENTS.TASK_END, {wrapupRequired: true});
break;
case CC_EVENTS.AGENT_WRAPPEDUP:
this.removeCurrentTaskFromCollection();
Expand Down
2 changes: 1 addition & 1 deletion packages/@webex/plugin-cc/src/services/task/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const CONSULT_END = '/consult/end';
export const TRANSFER = '/transfer';
export const CONSULT_TRANSFER = '/consult/transfer';
export const PAUSE = '/record/pause';
export const RESUME = 'record/resume';
export const RESUME = '/record/resume';
export const WRAPUP = '/wrapup';
export const END = '/end';
export const TASK_MANAGER_FILE = 'taskManager';
Expand Down
3 changes: 2 additions & 1 deletion packages/@webex/plugin-cc/src/services/task/contact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
END,
HOLD,
PAUSE,
RESUME,
TASK_API,
TASK_MESSAGE_TYPE,
TRANSFER,
Expand Down Expand Up @@ -121,7 +122,7 @@ export default function routingContact(aqm: AqmReqs) {
*/
resumeRecording: aqm.req(
(p: {interactionId: string; data: Contact.ResumeRecordingPayload}) => ({
url: `${TASK_API}${p.interactionId}/record/resume`,
url: `${TASK_API}${p.interactionId}${RESUME}`,
data: p.data,
host: WCC_API_GATEWAY,
err,
Expand Down
3 changes: 1 addition & 2 deletions packages/@webex/plugin-cc/src/services/task/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,10 +362,9 @@ export interface ITask extends EventEmitter {
* task.decline();
* ```
*/
decline(taskId: TaskId): Promise<TaskResponse>;
decline(): Promise<TaskResponse>;
/**
* This is used to hold the task.
* @param taskId
* @returns Promise<TaskResponse>
* @example
* ```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,6 @@ import { TASK_EVENTS } from '../../../../../src/services/task/types';
import WebCallingService from '../../../../../src/services/WebCallingService';
import config from '../../../../../src/config';

jest.mock('./../../../../../src/services/task', () => {
return jest.fn().mockImplementation(() => {
return {
updateTaskData: jest.fn().mockReturnThis(),
emit: jest.fn()
};
});
});

describe('TaskManager', () => {
let mockCall;
let webSocketManagerMock;
Expand Down Expand Up @@ -76,13 +67,6 @@ describe('TaskManager', () => {
onSpy = jest.spyOn(webCallingService, 'on');

taskManager = new TaskManager(contactMock, webCallingService, webSocketManagerMock);
taskManager.currentTask = {
accept: jest.fn(),
decline: jest.fn(),
updateTaskData: jest.fn(),
unregisterWebCallListeners: jest.fn(),
data: taskDataMock
}
taskManager.call = mockCall;
});

Expand All @@ -91,6 +75,7 @@ describe('TaskManager', () => {
});

it('should initialize TaskManager and register listeners', () => {
webSocketManagerMock.emit('message', JSON.stringify({data: taskDataMock}));
const incomingCallCb = onSpy.mock.calls[0][1];
const taskEmitSpy = jest.spyOn(taskManager, 'emit');

Expand Down Expand Up @@ -126,7 +111,6 @@ describe('TaskManager', () => {

webSocketManagerMock.emit('message', JSON.stringify(payload));

expect(Task).toHaveBeenCalledWith(contactMock, webCallingService , payload.data);
expect(taskIncomingSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_INCOMING, taskManager.currentTask);
expect(taskManager.getTask(payload.data.interactionId)).toBe(taskManager.currentTask);
expect(taskManager.getAllTasks()).toHaveProperty(payload.data.interactionId);
Expand Down Expand Up @@ -178,7 +162,6 @@ describe('TaskManager', () => {

webSocketManagerMock.emit('message', JSON.stringify(payload));

expect(Task).toHaveBeenCalledWith(contactMock, webCallingService , payload.data);
expect(taskIncomingSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_INCOMING, taskManager.currentTask);
expect(taskManager.getTask(payload.data.interactionId)).toBe(taskManager.currentTask);
expect(taskManager.getAllTasks()).toHaveProperty(payload.data.interactionId);
Expand Down Expand Up @@ -264,7 +247,10 @@ describe('TaskManager', () => {
});

it('test call listeners being switched off on call end', () => {
const taskEmitSpy = jest.spyOn(taskManager, 'emit');
webSocketManagerMock.emit('message', JSON.stringify({data: taskDataMock}));

const taskEmitSpy = jest.spyOn(taskManager.currentTask, 'emit');
const webCallListenerSpy = jest.spyOn(taskManager.currentTask, 'unregisterWebCallListeners');
const webCallingServiceOffSpy = jest.spyOn(webCallingService, 'off');
const callOffSpy = jest.spyOn(mockCall, 'off');
const payload = {
Expand All @@ -273,7 +259,7 @@ describe('TaskManager', () => {
agentId: "723a8ffb-a26e-496d-b14a-ff44fb83b64f",
eventTime: 1733211616959,
eventType: "RoutingMessage",
interaction: {},
interaction: {"state": "new"},
interactionId: taskId,
orgId: "6ecef209-9a34-4ed1-a07a-7ddd1dbe925a",
trackingId: "575c0ec2-618c-42af-a61c-53aeb0a221ee",
Expand All @@ -284,14 +270,15 @@ describe('TaskManager', () => {
},
};

taskManager.currentTask.data = payload.data;
webSocketManagerMock.emit('message', JSON.stringify(payload));

expect(taskEmitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_UNASSIGNED, taskManager.currentTask);
expect(taskManager.currentTask.unregisterWebCallListeners).toHaveBeenCalledWith();
expect(taskEmitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_END, {wrapupRequired: false});
expect(webCallListenerSpy).toHaveBeenCalledWith();
expect(callOffSpy).toHaveBeenCalledWith(CALL_EVENT_KEYS.REMOTE_MEDIA, callOffSpy.mock.calls[0][1]);

taskManager.unregisterIncomingCallEvent();
expect(webCallingServiceOffSpy).toHaveBeenCalledWith(LINE_EVENTS.INCOMING_CALL, webCallingServiceOffSpy.mock.calls[0][1]);
expect(webCallingServiceOffSpy).toHaveBeenCalledWith(LINE_EVENTS.INCOMING_CALL, webCallingServiceOffSpy.mock.calls[1][1]);
});

it('should emit TASK_END event on AGENT_WRAPUP event', () => {
Expand Down Expand Up @@ -332,11 +319,12 @@ describe('TaskManager', () => {
};

const taskEmitSpy = jest.spyOn(taskManager.currentTask, 'emit');
const updateTaskDataSpy = jest.spyOn(taskManager.currentTask, 'updateTaskData');

webSocketManagerMock.emit('message', JSON.stringify(wrapupPayload));

expect(taskManager.currentTask.updateTaskData).toHaveBeenCalledWith(wrapupPayload.data);
expect(taskEmitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_END, taskManager.currentTask);
expect(updateTaskDataSpy).toHaveBeenCalledWith(wrapupPayload.data);
expect(taskEmitSpy).toHaveBeenCalledWith(TASK_EVENTS.TASK_END, {wrapupRequired: true});
});

it('should remove currentTask from taskCollection on AGENT_WRAPPEDUP event', () => {
Expand Down

0 comments on commit 510a290

Please sign in to comment.