Skip to content

Commit

Permalink
fix: CRM integration mismatch on callback type (#31880)
Browse files Browse the repository at this point in the history
  • Loading branch information
KevLehman authored Mar 12, 2024
1 parent d9291b6 commit 871efa5
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/slow-jobs-think.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

fix: CRM integration mismatch on callback type vs code validation. Previously, callback was attempting to register a `LivechatStarted` event, however, our internal code was expecting a `LivechatStart` event, causing the hook to receive incomplete data
22 changes: 16 additions & 6 deletions apps/meteor/app/livechat/server/hooks/sendToCRM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,28 @@ type OmnichannelRoomWithExtraFields = IOmnichannelRoom & {
oldDepartmentId?: IOmnichannelRoom['departmentId'];
};

type CRMActions =
| 'LivechatSessionStart'
| 'LivechatSessionQueued'
| 'LivechatSession'
| 'LivechatSessionTaken'
| 'LivechatSessionForwarded'
| 'LivechatEdit'
| 'Message'
| 'LeadCapture';

const msgNavType = 'livechat_navigation_history';
const msgClosingType = 'livechat-close';

const isOmnichannelNavigationMessage = (message: IMessage): message is IOmnichannelSystemMessage => {
export const isOmnichannelNavigationMessage = (message: IMessage): message is IOmnichannelSystemMessage => {
return message.t === msgNavType;
};

const isOmnichannelClosingMessage = (message: IMessage): message is IOmnichannelSystemMessage => {
export const isOmnichannelClosingMessage = (message: IMessage): message is IOmnichannelSystemMessage => {
return message.t === msgClosingType;
};

const sendMessageType = (msgType: string): boolean => {
export const sendMessageType = (msgType: string): boolean => {
switch (msgType) {
case msgClosingType:
return true;
Expand All @@ -60,10 +70,10 @@ const sendMessageType = (msgType: string): boolean => {
}
};

const getAdditionalFieldsByType = (type: string, room: OmnichannelRoomWithExtraFields): AdditionalFields => {
export const getAdditionalFieldsByType = (type: CRMActions, room: OmnichannelRoomWithExtraFields): AdditionalFields => {
const { departmentId, servedBy, closedAt, closedBy, closer, oldServedBy, oldDepartmentId } = room;
switch (type) {
case 'LivechatSessionStarted':
case 'LivechatSessionStart':
case 'LivechatSessionQueued':
return { departmentId };
case 'LivechatSession':
Expand All @@ -78,7 +88,7 @@ const getAdditionalFieldsByType = (type: string, room: OmnichannelRoomWithExtraF
};

async function sendToCRM(
type: string,
type: CRMActions,
room: OmnichannelRoomWithExtraFields,
includeMessages: boolean | IOmnichannelSystemMessage[] = true,
): Promise<OmnichannelRoomWithExtraFields> {
Expand Down
123 changes: 123 additions & 0 deletions apps/meteor/tests/unit/app/livechat/server/hooks/sendToCRM.tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { expect } from 'chai';
import p from 'proxyquire';

const resultObj = {
result: true,
};

const { sendMessageType, isOmnichannelNavigationMessage, isOmnichannelClosingMessage, getAdditionalFieldsByType } = p
.noCallThru()
.load('../../../../../../app/livechat/server/hooks/sendToCRM', {
'../../../settings/server': {
settings: {
get() {
return resultObj.result;
},
},
},
'../../../utils/server/functions/normalizeMessageFileUpload': {
normalizeMessageFileUpload: (data: any) => data,
},
'../lib/LivechatTyped': {
Livechat: {},
},
});

describe('[OC] Send TO CRM', () => {
describe('isOmnichannelNavigationMessage', () => {
it('should return true if the message is a navigation message', () => {
const message = { t: 'livechat_navigation_history' } as any;
expect(isOmnichannelNavigationMessage(message)).to.be.true;
});

it('should return false if the message is not a navigation message', () => {
const message = { t: 'livechat-close' } as any;
expect(isOmnichannelNavigationMessage(message)).to.be.false;
});
});

describe('isOmnichannelClosingMessage', () => {
it('should return true if the message is a closing message', () => {
const message = { t: 'livechat-close' } as any;
expect(isOmnichannelClosingMessage(message)).to.be.true;
});

it('should return false if the message is not a closing message', () => {
const message = { t: 'livechat_navigation_history' } as any;
expect(isOmnichannelClosingMessage(message)).to.be.false;
});
});

describe('sendMessageType', () => {
it('should return true if the message type is a closing message', () => {
expect(sendMessageType('livechat-close')).to.be.true;
});

it('should return true if the message type is a navigation message and the settings are enabled', () => {
expect(sendMessageType('livechat_navigation_history')).to.be.true;
});

it('should return false if the message type is a navigation message and the settings are disabled', () => {
resultObj.result = false;
expect(sendMessageType('livechat_navigation_history')).to.be.false;
});

it('should return false if the message type is not a closing or navigation message', () => {
expect(sendMessageType('message')).to.be.false;
});
});

describe('getAdditionalFieldsByType', () => {
it('should return the correct fields for the LivechatSessionStart type', () => {
const room = { departmentId: 'departmentId' } as any;
expect(getAdditionalFieldsByType('LivechatSessionStart', room)).to.deep.equal({ departmentId: 'departmentId' });
});

it('should return the correct fields for the LivechatSessionQueued type', () => {
const room = { departmentId: 'departmentId' } as any;
expect(getAdditionalFieldsByType('LivechatSessionQueued', room)).to.deep.equal({ departmentId: 'departmentId' });
});

it('should return the correct fields for the LivechatSession type', () => {
const room = {
departmentId: 'departmentId',
servedBy: 'servedBy',
closedAt: 'closedAt',
closedBy: 'closedBy',
closer: 'closer',
} as any;
expect(getAdditionalFieldsByType('LivechatSession', room)).to.deep.equal({
departmentId: 'departmentId',
servedBy: 'servedBy',
closedAt: 'closedAt',
closedBy: 'closedBy',
closer: 'closer',
});
});

it('should return the correct fields for the LivechatSessionTaken type', () => {
const room = { departmentId: 'departmentId', servedBy: 'servedBy' } as any;
expect(getAdditionalFieldsByType('LivechatSessionTaken', room)).to.deep.equal({ departmentId: 'departmentId', servedBy: 'servedBy' });
});

it('should return the correct fields for the LivechatSessionForwarded type', () => {
const room = {
departmentId: 'departmentId',
servedBy: 'servedBy',
oldDepartmentId: 'oldDepartmentId',
oldServedBy: 'oldServedBy',
} as any;
expect(getAdditionalFieldsByType('LivechatSessionForwarded', room)).to.deep.equal({
departmentId: 'departmentId',
servedBy: 'servedBy',
oldDepartmentId: 'oldDepartmentId',
oldServedBy: 'oldServedBy',
});
});

it('should return an empty object for an unknown type', () => {
const room = {} as any;
expect(getAdditionalFieldsByType('unknownType' as any, room)).to.deep.equal({});
});
});
});

0 comments on commit 871efa5

Please sign in to comment.