Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@microsoft/omnichannel-chat-sdk

Package Overview
Dependencies
Maintainers
5
Versions
336
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@microsoft/omnichannel-chat-sdk - npm Package Compare versions

Comparing version 0.1.1-main.be117dd to 0.1.1-main.fadb071

__tests__/OmnichannelChatSDK.node.spec.ts

599

__tests__/OmnichannelChatSDK.spec.ts
const OmnichannelChatSDK = require('../src/OmnichannelChatSDK').default;
import IFileInfo from "@microsoft/omnichannel-ic3core/lib/interfaces/IFileInfo";
import FileSharingProtocolType from "@microsoft/omnichannel-ic3core/lib/model/FileSharingProtocolType";
import IFileMetadata from "@microsoft/omnichannel-ic3core/lib/model/IFileMetadata";
import IMessage from "@microsoft/omnichannel-ic3core/lib/model/IMessage";
import PersonType from "@microsoft/omnichannel-ic3core/lib/model/PersonType";

@@ -25,3 +30,3 @@ describe('Omnichannel Chat SDK', () => {

});
})
});

@@ -120,3 +125,3 @@ describe('Functionalities', () => {

it('ChatSDK.startchat() with existing liveChatContext should not call OCClient.getChatToken', async() => {
it('ChatSDK.startChat() should fail if OCClient.sessiontInit() fails', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);

@@ -126,2 +131,3 @@ chatSDK.getChatConfig = jest.fn();

await chatSDK.initialize();
jest.spyOn(chatSDK.OCClient, 'getChatToken').mockResolvedValue(Promise.resolve({

@@ -133,4 +139,90 @@ ChatId: '',

jest.spyOn(chatSDK.OCClient, 'sessionInit').mockRejectedValue(Promise.reject());
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve());
jest.spyOn(console, 'error');
try {
await chatSDK.startChat();
} catch (error) {
expect(console.error).toHaveBeenCalled();
}
expect(chatSDK.OCClient.sessionInit).toHaveBeenCalledTimes(1);
expect(chatSDK.IC3Client.initialize).toHaveBeenCalledTimes(0);
expect(chatSDK.IC3Client.joinConversation).toHaveBeenCalledTimes(0);
});
it('ChatSDK.startChat() should fail if IC3Client.initialize() fails', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
await chatSDK.initialize();
jest.spyOn(chatSDK.OCClient, 'getChatToken').mockResolvedValue(Promise.resolve({
ChatId: '',
Token: '',
RegionGtms: '{}'
}));
jest.spyOn(chatSDK.OCClient, 'sessionInit').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'initialize').mockRejectedValue(Promise.reject());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve());
jest.spyOn(console, 'error');
try {
await chatSDK.startChat();
} catch (error) {
expect(console.error).toHaveBeenCalled();
}
expect(chatSDK.OCClient.sessionInit).toHaveBeenCalledTimes(1);
expect(chatSDK.IC3Client.initialize).toHaveBeenCalledTimes(1);
expect(chatSDK.IC3Client.joinConversation).toHaveBeenCalledTimes(0);
});
it('ChatSDK.startChat() should fail if IC3Client.joinConversation() fails', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
await chatSDK.initialize();
jest.spyOn(chatSDK.OCClient, 'getChatToken').mockResolvedValue(Promise.resolve({
ChatId: '',
Token: '',
RegionGtms: '{}'
}));
jest.spyOn(chatSDK.OCClient, 'sessionInit').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockRejectedValue(Promise.reject());
jest.spyOn(console, 'error');
try {
await chatSDK.startChat();
} catch (error) {
expect(console.error).toHaveBeenCalled();
}
expect(chatSDK.OCClient.sessionInit).toHaveBeenCalledTimes(1);
expect(chatSDK.IC3Client.initialize).toHaveBeenCalledTimes(1);
expect(chatSDK.IC3Client.joinConversation).toHaveBeenCalledTimes(1);
});
it('ChatSDK.startchat() with existing liveChatContext should not call OCClient.getChatToken()', async() => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
await chatSDK.initialize();
jest.spyOn(chatSDK.OCClient, 'getChatToken').mockResolvedValue(Promise.resolve({
ChatId: '',
Token: '',
RegionGtms: '{}'
}));
jest.spyOn(chatSDK.OCClient, 'sessionInit').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve());

@@ -159,2 +251,16 @@

it('ChatSDK.getLiveChatConfig() should return the cached value by default', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
chatSDK.liveChatConfig = {
id: 0
}
const liveChatConfig = await chatSDK.getLiveChatConfig();
expect(liveChatConfig.id).toBe(chatSDK.liveChatConfig.id);
expect(chatSDK.getChatConfig).toHaveBeenCalledTimes(0);
});
it('ChatSDK.startChat() with preChatResponse should pass it to OCClient.sessionInit() call\'s optional parameters', async() => {

@@ -221,3 +327,2 @@ const chatSDK = new OmnichannelChatSDK(omnichannelConfig);

jest.spyOn(chatSDK.OCClient, 'getChatToken').mockResolvedValue(Promise.resolve({

@@ -246,2 +351,79 @@ ChatId: '',

it('ChatSDK.getCurrentLiveChatContext() should return chat session data', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
await chatSDK.initialize();
chatSDK.IC3Client = {
initialize: jest.fn(),
joinConversation: jest.fn()
}
jest.spyOn(chatSDK.OCClient, 'getChatToken').mockResolvedValue(Promise.resolve({
ChatId: '',
Token: '',
RegionGtms: '{}'
}));
jest.spyOn(chatSDK.OCClient, 'sessionInit').mockResolvedValue(Promise.resolve());
await chatSDK.startChat();
const chatContext = await chatSDK.getCurrentLiveChatContext();
expect(Object.keys(chatContext).includes('chatToken')).toBe(true);
expect(Object.keys(chatContext).includes('requestId')).toBe(true);
});
it('ChatSDK.getCurrentLiveChatContext() with empty chatToken should return an empty chat session data', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
await chatSDK.initialize();
chatSDK.IC3Client = {
initialize: jest.fn(),
joinConversation: jest.fn()
}
jest.spyOn(chatSDK.OCClient, 'getChatToken').mockResolvedValue(Promise.resolve({
ChatId: '',
Token: '',
RegionGtms: '{}'
}));
jest.spyOn(chatSDK.OCClient, 'sessionInit').mockResolvedValue(Promise.resolve());
const chatContext = await chatSDK.getCurrentLiveChatContext();
expect(Object.keys(chatContext).length).toBe(0);
expect(Object.keys(chatContext).includes('chatToken')).toBe(false);
expect(Object.keys(chatContext).includes('requestId')).toBe(false);
});
it('ChatSDK.getMessages should call conversation.getMessages()', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
chatSDK.getChatToken = jest.fn();
await chatSDK.initialize();
chatSDK.OCClient = {
sessionInit: jest.fn()
}
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve({
getMessages: () => {}
}));
await chatSDK.startChat();
jest.spyOn(chatSDK.conversation, 'getMessages').mockResolvedValue(Promise.resolve());
await chatSDK.getMessages();
expect(chatSDK.conversation.getMessages).toHaveBeenCalledTimes(1);
});
it('ChatSDK.sendMessage() should mask characters if enabled', async () => {

@@ -337,2 +519,338 @@ const chatSDK = new OmnichannelChatSDK(omnichannelConfig);

it('ChatSDK.sendMessage() should send message with custom tags if set', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
chatSDK.getChatToken = jest.fn();
await chatSDK.initialize();
chatSDK.OCClient = {
sessionInit: jest.fn()
}
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve({
sendMessage: (message: any) => {}
}));
await chatSDK.startChat();
jest.spyOn(chatSDK.conversation, 'sendMessage').mockResolvedValue(Promise.resolve());
const messageToSend = {
content: 'sample',
tags: ['system']
}
await chatSDK.sendMessage(messageToSend);
expect(chatSDK.conversation.sendMessage).toHaveBeenCalledTimes(1);
expect((chatSDK.conversation.sendMessage.mock.calls[0][0] as any).tags.length).not.toBe(0);
});
it('ChatSDK.sendMessage() should send message with custom timestamp if set', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
chatSDK.getChatToken = jest.fn();
await chatSDK.initialize();
chatSDK.OCClient = {
sessionInit: jest.fn()
}
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve({
sendMessage: (message: any) => {}
}));
await chatSDK.startChat();
jest.spyOn(chatSDK.conversation, 'sendMessage').mockResolvedValue(Promise.resolve());
const messageToSend = {
content: 'sample',
timestamp: 'timestamp'
}
await chatSDK.sendMessage(messageToSend);
expect(chatSDK.conversation.sendMessage).toHaveBeenCalledTimes(1);
expect((chatSDK.conversation.sendMessage.mock.calls[0][0] as any).timestamp).toEqual(messageToSend.timestamp);
});
it('ChatSDK.sendTypingEvent() should call conversation.sendMessageToBot()', async() => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
chatSDK.getChatToken = jest.fn();
await chatSDK.initialize();
chatSDK.OCClient = {
sessionInit: jest.fn()
}
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve({
indicateTypingStatus: (value: number) => {},
getMembers: () => {},
sendMessageToBot: (botId: string, message: any) => {}
}));
await chatSDK.startChat();
const members = [
{id: 'id', type: PersonType.Bot}
];
jest.spyOn(chatSDK.conversation, 'indicateTypingStatus').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.conversation, 'getMembers').mockResolvedValue(Promise.resolve(members));
jest.spyOn(chatSDK.conversation, 'sendMessageToBot').mockResolvedValue(Promise.resolve());
await chatSDK.sendTypingEvent();
expect(chatSDK.conversation.indicateTypingStatus).toHaveBeenCalledTimes(1);
expect(chatSDK.conversation.getMembers).toHaveBeenCalledTimes(1);
expect(chatSDK.conversation.sendMessageToBot).toHaveBeenCalledTimes(1);
});
it('ChatSDK.sendTypingEvent() should fail if conversation.sendMessageToBot() fails', async() => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
chatSDK.getChatToken = jest.fn();
await chatSDK.initialize();
chatSDK.OCClient = {
sessionInit: jest.fn()
}
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve({
indicateTypingStatus: (value: number) => {},
getMembers: () => {},
sendMessageToBot: (botId: string, message: any) => {}
}));
await chatSDK.startChat();
const members = [
{id: 'id', type: PersonType.Bot}
];
jest.spyOn(chatSDK.conversation, 'indicateTypingStatus').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.conversation, 'getMembers').mockResolvedValue(Promise.resolve(members));
jest.spyOn(chatSDK.conversation, 'sendMessageToBot').mockRejectedValue(Promise.reject());
jest.spyOn(console, 'error');
try {
await chatSDK.sendTypingEvent();
} catch (error) {
expect(console.error).toHaveBeenCalled();
}
expect(chatSDK.conversation.indicateTypingStatus).toHaveBeenCalledTimes(1);
expect(chatSDK.conversation.getMembers).toHaveBeenCalledTimes(1);
expect(chatSDK.conversation.sendMessageToBot).toHaveBeenCalledTimes(1);
});
it('ChatSDK.uploadFileAttachment() should call conversation.sendFileData() & conversation.sendFileMessage()', async() => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
chatSDK.getChatToken = jest.fn();
await chatSDK.initialize();
chatSDK.OCClient = {
sessionInit: jest.fn()
}
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve({
sendFileData: (fileInfo: IFileInfo, fileSharingProtocolType: FileSharingProtocolType) => {},
sendFileMessage: (fileMetaData: IFileMetadata, message: IMessage) => {}
}));
await chatSDK.startChat();
jest.spyOn(chatSDK.conversation, 'sendFileData').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.conversation, 'sendFileMessage').mockResolvedValue(Promise.resolve());
const fileInfo = {};
await chatSDK.uploadFileAttachment(fileInfo);
expect(chatSDK.conversation.sendFileData).toHaveBeenCalledTimes(1);
expect(chatSDK.conversation.sendFileMessage).toHaveBeenCalledTimes(1);
});
it('ChatSDK.downloadFileAttachment() should call conversation.downloadFile()', async() => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
chatSDK.getChatToken = jest.fn();
await chatSDK.initialize();
chatSDK.OCClient = {
sessionInit: jest.fn()
}
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve({
downloadFile: () => {}
}));
await chatSDK.startChat();
jest.spyOn(chatSDK.conversation, 'downloadFile').mockResolvedValue(Promise.resolve());
const fileMetaData = {};
await chatSDK.downloadFileAttachment(fileMetaData);
expect(chatSDK.conversation.downloadFile).toHaveBeenCalledTimes(1);
});
it('ChatSDK.emailLiveChatTranscript() should call OCClient.emailTranscript()', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
chatSDK.getChatToken = jest.fn();
await chatSDK.initialize();
jest.spyOn(chatSDK.OCClient, 'sessionInit').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.OCClient, 'emailTranscript').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve({
sendMessage: (message: any) => {}
}));
await chatSDK.startChat();
const emailBody = {
emailAddress: 'sample@microsoft.com',
attachmentMessage: 'sample',
CustomerLocale: 'sample'
};
await chatSDK.emailLiveChatTranscript(emailBody);
expect(chatSDK.OCClient.emailTranscript).toHaveBeenCalledTimes(1);
});
it('ChatSDK.emailLiveChatTranscript() with authenticatedUserToken should pass it to OCClient.emailTranscript()', async () => {
const chatSDKConfig = {
getAuthToken: async () => {
return 'authenticatedUserToken'
}
};
const chatSDK = new OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
chatSDK.getChatConfig = jest.fn();
await chatSDK.initialize();
chatSDK.IC3Client.initialize = jest.fn();
chatSDK.IC3Client.joinConversation = jest.fn();
const optionaParams = {
authenticatedUserToken: 'authenticatedUserToken'
}
jest.spyOn(chatSDK.OCClient, 'getChatConfig').mockResolvedValue(Promise.resolve({
DataMaskingInfo: { setting: { msdyn_maskforcustomer: false } },
LiveWSAndLiveChatEngJoin: { PreChatSurvey: { msdyn_prechatenabled: false } },
LiveChatConfigAuthSettings: {}
}));
jest.spyOn(chatSDK.OCClient, 'getChatToken').mockResolvedValue(Promise.resolve({
ChatId: '',
Token: '',
RegionGtms: '{}'
}));
jest.spyOn(chatSDK.OCClient, 'sessionInit').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.OCClient, 'emailTranscript').mockResolvedValue(Promise.resolve());
await chatSDK.startChat();
chatSDK.authenticatedUserToken = optionaParams.authenticatedUserToken;
const emailBody = {
emailAddress: 'sample@microsoft.com',
attachmentMessage: 'sample',
CustomerLocale: 'sample'
};
const emailTranscriptOptionalParams = {
authenticatedUserToken: optionaParams.authenticatedUserToken
}
await chatSDK.emailLiveChatTranscript(emailBody);
expect(chatSDK.OCClient.emailTranscript).toHaveBeenCalledTimes(1);
expect(chatSDK.OCClient.emailTranscript.mock.calls[0][3]).toMatchObject(emailTranscriptOptionalParams);
});
it('ChatSDK.getLiveChatTranscript() should call OCClient.getChatTranscripts()', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
chatSDK.getChatToken = jest.fn();
await chatSDK.initialize();
jest.spyOn(chatSDK.OCClient, 'sessionInit').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.OCClient, 'getChatTranscripts').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve({
sendMessage: (message: any) => {}
}));
await chatSDK.startChat();
await chatSDK.getLiveChatTranscript();
expect(chatSDK.OCClient.getChatTranscripts).toHaveBeenCalledTimes(1);
});
it('ChatSDK.getLiveChatTranscript() with authenticatedUserToken should pass it to OCClient.getChatTranscripts()', async () => {
const chatSDKConfig = {
getAuthToken: async () => {
return 'authenticatedUserToken'
}
};
const chatSDK = new OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
chatSDK.getChatConfig = jest.fn();
await chatSDK.initialize();
chatSDK.IC3Client.initialize = jest.fn();
chatSDK.IC3Client.joinConversation = jest.fn();
const optionaParams = {
authenticatedUserToken: 'authenticatedUserToken'
}
jest.spyOn(chatSDK.OCClient, 'getChatConfig').mockResolvedValue(Promise.resolve({
DataMaskingInfo: { setting: { msdyn_maskforcustomer: false } },
LiveWSAndLiveChatEngJoin: { PreChatSurvey: { msdyn_prechatenabled: false } },
LiveChatConfigAuthSettings: {}
}));
jest.spyOn(chatSDK.OCClient, 'getChatToken').mockResolvedValue(Promise.resolve({
ChatId: '',
Token: '',
RegionGtms: '{}'
}));
jest.spyOn(chatSDK.OCClient, 'sessionInit').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.OCClient, 'getChatTranscripts').mockResolvedValue(Promise.resolve());
await chatSDK.startChat();
chatSDK.authenticatedUserToken = optionaParams.authenticatedUserToken;
await chatSDK.startChat();
const getChatTranscriptOptionalParams = {
authenticatedUserToken: optionaParams.authenticatedUserToken
}
await chatSDK.getLiveChatTranscript();
expect(chatSDK.OCClient.getChatTranscripts).toHaveBeenCalledTimes(1);
expect(chatSDK.OCClient.getChatTranscripts.mock.calls[0][3]).toMatchObject(getChatTranscriptOptionalParams);
});
it('ChatSDK.getIC3Client() should return IC3Core if platform is Node', async () => {

@@ -487,3 +1005,78 @@ const IC3SDKProvider = require('@microsoft/omnichannel-ic3core').SDKProvider;

});
it('ChatSDK.endChat() should fail if OCClient.sessionClose() fails', async () => {
const chatSDK = new OmnichannelChatSDK(omnichannelConfig);
chatSDK.getChatConfig = jest.fn();
chatSDK.getChatToken = jest.fn();
await chatSDK.initialize();
await chatSDK.startChat();
jest.spyOn(chatSDK.OCClient, 'sessionInit').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'initialize').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.IC3Client, 'joinConversation').mockResolvedValue(Promise.resolve({
disconnect: () => {}
}));
jest.spyOn(chatSDK.OCClient, 'sessionClose').mockRejectedValue(Promise.reject());
try {
await chatSDK.endChat();
} catch (error) {
expect(console.error).toHaveBeenCalled();
}
expect(chatSDK.OCClient.sessionClose).toHaveBeenCalledTimes(1);
});
it('ChatSDK.endChat() with authenticatedUserToken should pass it to OCClient.sessionClose() call\'s optional parameters', async () => {
const chatSDKConfig = {
getAuthToken: async () => {
return 'authenticatedUserToken'
}
};
const chatSDK = new OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
chatSDK.getChatConfig = jest.fn();
await chatSDK.initialize();
chatSDK.IC3Client.initialize = jest.fn();
chatSDK.IC3Client.joinConversation = jest.fn();
const optionaParams = {
authenticatedUserToken: 'authenticatedUserToken'
}
jest.spyOn(chatSDK.OCClient, 'getChatConfig').mockResolvedValue(Promise.resolve({
DataMaskingInfo: { setting: { msdyn_maskforcustomer: false } },
LiveWSAndLiveChatEngJoin: { PreChatSurvey: { msdyn_prechatenabled: false } },
LiveChatConfigAuthSettings: {}
}));
jest.spyOn(chatSDK.OCClient, 'getChatToken').mockResolvedValue(Promise.resolve({
ChatId: '',
Token: '',
RegionGtms: '{}'
}));
jest.spyOn(chatSDK.OCClient, 'sessionInit').mockResolvedValue(Promise.resolve());
jest.spyOn(chatSDK.OCClient, 'sessionClose').mockResolvedValue(Promise.resolve());
await chatSDK.startChat();
chatSDK.authenticatedUserToken = optionaParams.authenticatedUserToken;
chatSDK.conversation = {
disconnect: jest.fn()
};
const sessionCloseOptionalParams = {
authenticatedUserToken: optionaParams.authenticatedUserToken
}
await chatSDK.endChat();
expect(chatSDK.OCClient.sessionClose).toHaveBeenCalledTimes(1);
expect(chatSDK.OCClient.sessionClose.mock.calls[0][1]).toMatchObject(sessionCloseOptionalParams);
});
});
})

6

lib/core/IChatConfig.d.ts
export default interface IChatConfig {
DataMaskingInfo: any;
LiveChatConfigAuthSettings: any;
LiveWSAndLiveChatEngJoin: any;
DataMaskingInfo: unknown;
LiveChatConfigAuthSettings: unknown;
LiveWSAndLiveChatEngJoin: unknown;
}
"use strict";
/* eslint-disable @typescript-eslint/no-explicit-any */
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=IChatToken.js.map

@@ -8,8 +8,11 @@ import IChatConfig from "./core/IChatConfig";

import IFileMetadata from "@microsoft/omnichannel-ic3core/lib/model/IFileMetadata";
import ILiveChatContext from "./core/ILiveChatContext";
import IMessage from "@microsoft/omnichannel-ic3core/lib/model/IMessage";
import IOmnichannelConfig from "./core/IOmnichannelConfig";
import IRawMessage from "@microsoft/omnichannel-ic3core/lib/model/IRawMessage";
import IRawThread from "@microsoft/omnichannel-ic3core/lib/interfaces/IRawThread";
import IStartChatOptionalParams from "./core/IStartChatOptionalParams";
declare class OmnichannelChatSDK {
OCSDKProvider: any;
IC3SDKProvider: any;
OCSDKProvider: unknown;
IC3SDKProvider: unknown;
OCClient: any;

@@ -30,5 +33,5 @@ IC3Client: any;

initialize(): Promise<IChatConfig>;
startChat(optionalParams?: IStartChatOptionalParams): Promise<any>;
endChat(): Promise<any>;
getCurrentLiveChatContext(): Promise<{}>;
startChat(optionalParams?: IStartChatOptionalParams): Promise<void>;
endChat(): Promise<void>;
getCurrentLiveChatContext(): Promise<ILiveChatContext | {}>;
/**

@@ -39,11 +42,11 @@ * Gets PreChat Survey.

getPreChatSurvey(parse?: boolean): Promise<any>;
getLiveChatConfig(cached?: boolean): Promise<any>;
getLiveChatConfig(cached?: boolean): Promise<IChatConfig>;
getChatToken(cached?: boolean): Promise<IChatToken>;
getMessages(): Promise<import("@microsoft/omnichannel-ic3core/lib/model/IMessage").default[] | undefined>;
getMessages(): Promise<IMessage[] | undefined>;
sendMessage(message: IChatSDKMessage): Promise<void>;
onNewMessage(onNewMessageCallback: CallableFunction): void;
sendTypingEvent(): Promise<any>;
sendTypingEvent(): Promise<void>;
onTypingEvent(onTypingEventCallback: CallableFunction): Promise<void>;
onAgentEndSession(onAgentEndSessionCallback: (message: IRawThread) => void): Promise<void>;
uploadFileAttachment(fileInfo: IFileInfo): Promise<any>;
uploadFileAttachment(fileInfo: IFileInfo): Promise<IRawMessage>;
downloadFileAttachment(fileMetadata: IFileMetadata): Promise<Blob>;

@@ -50,0 +53,0 @@ emailLiveChatTranscript(body: IChatTranscriptBody): Promise<any>;

"use strict";
/* eslint-disable @typescript-eslint/no-non-null-assertion */
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {

@@ -82,3 +83,3 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }

case 1:
_a.OCClient = _c.sent();
_a.OCClient = _c.sent(); // eslint-disable-line @typescript-eslint/no-explicit-any
_b = this;

@@ -291,3 +292,3 @@ return [4 /*yield*/, this.getIC3Client()];

match = void 0;
while (match = regex.exec(content)) {
while (match = regex.exec(content)) { // eslint-disable-line no-cond-assign
replaceStr = match[0].replace(/./g, maskingCharacter);

@@ -338,18 +339,27 @@ content = content.replace(match[0], replaceStr);

return __awaiter(this, void 0, void 0, function () {
var typingPayload;
var _this = this;
var typingPayload, members, botMembers, error_6;
return __generator(this, function (_a) {
typingPayload = "{isTyping: 0}";
try {
this.conversation.indicateTypingStatus(0);
this.conversation.getMembers().then(function (members) {
var botMembers = members.filter(function (member) { return member.type === PersonType_1.default.Bot; });
_this.conversation.sendMessageToBot(botMembers[0].id, { payload: typingPayload });
});
switch (_a.label) {
case 0:
typingPayload = "{isTyping: 0}";
_a.label = 1;
case 1:
_a.trys.push([1, 5, , 6]);
return [4 /*yield*/, this.conversation.indicateTypingStatus(0)];
case 2:
_a.sent();
return [4 /*yield*/, this.conversation.getMembers()];
case 3:
members = _a.sent();
botMembers = members.filter(function (member) { return member.type === PersonType_1.default.Bot; });
return [4 /*yield*/, this.conversation.sendMessageToBot(botMembers[0].id, { payload: typingPayload })];
case 4:
_a.sent();
return [3 /*break*/, 6];
case 5:
error_6 = _a.sent();
console.error("OmnichannelChatSDK/sendTypingEvent/error");
return [2 /*return*/, error_6];
case 6: return [2 /*return*/];
}
catch (error) {
console.error("OmnichannelChatSDK/sendTypingEvent/error");
return [2 /*return*/, error];
}
return [2 /*return*/];
});

@@ -387,3 +397,3 @@ });

return __awaiter(this, void 0, void 0, function () {
var fileMetadata, messageToSend, error_6;
var fileMetadata, messageToSend, error_7;
return __generator(this, function (_a) {

@@ -416,5 +426,5 @@ switch (_a.label) {

case 4:
error_6 = _a.sent();
console.error("OmnichannelChatSDK/uploadFileAttachment/error: " + error_6);
return [2 /*return*/, error_6];
error_7 = _a.sent();
console.error("OmnichannelChatSDK/uploadFileAttachment/error: " + error_7);
return [2 /*return*/, error_7];
case 5: return [2 /*return*/];

@@ -496,2 +506,3 @@ }

};
/* istanbul ignore next */
OmnichannelChatSDK.prototype.setDebug = function (flag) {

@@ -551,3 +562,3 @@ this.debug = flag;

return __awaiter(this, void 0, void 0, function () {
var liveChatConfig, dataMaskingConfig, authSettings, liveWSAndLiveChatEngJoin, setting, preChatSurvey, msdyn_prechatenabled, isPreChatEnabled, token, error_7;
var liveChatConfig, dataMaskingConfig, authSettings, liveWSAndLiveChatEngJoin, setting, preChatSurvey, msdyn_prechatenabled, isPreChatEnabled, token, error_8;
return __generator(this, function (_a) {

@@ -596,5 +607,5 @@ switch (_a.label) {

case 5:
error_7 = _a.sent();
console.error("OmnichannelChatSDK/getChatConfig/error " + error_7);
return [2 /*return*/, error_7];
error_8 = _a.sent();
console.error("OmnichannelChatSDK/getChatConfig/error " + error_8);
return [2 /*return*/, error_8];
case 6: return [2 /*return*/];

@@ -601,0 +612,0 @@ }

@@ -1,2 +0,2 @@

export declare const isSystemMessage: (message: any) => any;
export declare const isCustomerMessage: (message: any) => any;
export declare const isSystemMessage: (message: any) => boolean;
export declare const isCustomerMessage: (message: any) => boolean;
{
"name": "@microsoft/omnichannel-chat-sdk",
"version": "0.1.1-main.be117dd",
"version": "0.1.1-main.fadb071",
"description": "Microsoft Omnichannel Chat SDK",

@@ -9,3 +9,4 @@ "main": "lib/index.js",

"build:tsc": "tsc",
"test": "jest"
"test": "jest",
"lint": "eslint src --ext .ts"
},

@@ -30,2 +31,5 @@ "author": "Microsoft Corporation",

"@types/jest": "^26.0.10",
"@typescript-eslint/eslint-plugin": "^4.9.1",
"@typescript-eslint/parser": "^4.9.1",
"eslint": "^7.15.0",
"jest": "^26.4.2",

@@ -32,0 +36,0 @@ "ts-jest": "^26.3.0",

# Omnichannel Chat SDK
[![npm version](https://badge.fury.io/js/%40microsoft%2Fomnichannel-chat-sdk.svg)](https://badge.fury.io/js/%40microsoft%2Fomnichannel-chat-sdk)
![Release CI](https://github.com/microsoft/omnichannel-chat-sdk/workflows/Release%20CI/badge.svg)
Headless Chat SDK to build your own chat widget against Dynamics 365 Omnichannel Services.

@@ -4,0 +7,0 @@

export default interface IChatConfig {
DataMaskingInfo: any;
LiveChatConfigAuthSettings: any;
LiveWSAndLiveChatEngJoin: any;
DataMaskingInfo: unknown;
LiveChatConfigAuthSettings: unknown;
LiveWSAndLiveChatEngJoin: unknown;
}

@@ -1,3 +0,1 @@

import IOmnichannelConfiguration from "@microsoft/ocsdk/lib/Interfaces/IOmnichannelConfiguration";
export default interface IOmnichannelConfig {

@@ -4,0 +2,0 @@ orgId: string;

@@ -1,2 +0,1 @@

import IChatToken from "../external/IC3Adapter/IChatToken";
import ILiveChatContext from "./ILiveChatContext";

@@ -3,0 +2,0 @@

@@ -0,1 +1,3 @@

/* eslint-disable @typescript-eslint/no-explicit-any */
export default interface IChatToken {

@@ -2,0 +4,0 @@ chatId?: string;

@@ -1,6 +0,3 @@

import HostType from "@microsoft/omnichannel-ic3core/lib/interfaces/HostType";
import IConversation from "@microsoft/omnichannel-ic3core/lib/model/IConversation";
import IChatToken from "./IChatToken";
import INotification from "./INotification";
import ProtocolType from "@microsoft/omnichannel-ic3core/lib/interfaces/ProtocoleType";

@@ -7,0 +4,0 @@ export default interface IIC3AdapterOptions {

@@ -0,1 +1,3 @@

/* eslint-disable @typescript-eslint/no-non-null-assertion */
import {SDKProvider as OCSDKProvider, uuidv4 } from "@microsoft/ocsdk";

@@ -16,6 +18,11 @@ import {SDKProvider as IC3SDKProvider} from '@microsoft/omnichannel-ic3core';

import IFileMetadata from "@microsoft/omnichannel-ic3core/lib/model/IFileMetadata";
import IGetChatTokenOptionalParams from "@microsoft/ocsdk/lib/Interfaces/IGetChatTokenOptionalParams";
import IGetChatTranscriptsOptionalParams from "@microsoft/ocsdk/lib/Interfaces/IGetChatTranscriptsOptionalParams";
import IIC3AdapterOptions from "./external/IC3Adapter/IIC3AdapterOptions";
import ILiveChatContext from "./core/ILiveChatContext";
import IMessage from "@microsoft/omnichannel-ic3core/lib/model/IMessage";
import InitContext from "@microsoft/ocsdk/lib/Model/InitContext";
import IOmnichannelConfig from "./core/IOmnichannelConfig";
import IOmnichannelConfiguration from "@microsoft/ocsdk/lib/Interfaces/IOmnichannelConfiguration";
import IPerson from "@microsoft/omnichannel-ic3core/lib/model/IPerson";
import IRawMessage from "@microsoft/omnichannel-ic3core/lib/model/IRawMessage";

@@ -25,4 +32,2 @@ import IRawThread from "@microsoft/omnichannel-ic3core/lib/interfaces/IRawThread";

import ISessionCloseOptionalParams from "@microsoft/ocsdk/lib/Interfaces/ISessionCloseOptionalParams";
import IGetChatTokenOptionalParams from "@microsoft/ocsdk/lib/Interfaces/IGetChatTokenOptionalParams";
import IGetChatTranscriptsOptionalParams from "@microsoft/ocsdk/lib/Interfaces/IGetChatTranscriptsOptionalParams";
import IEmailTranscriptOptionalParams from "@microsoft/ocsdk/lib/Interfaces/IEmailTranscriptOptionalParams";

@@ -39,8 +44,9 @@ import IStartChatOptionalParams from "./core/IStartChatOptionalParams";

import validateSDKConfig, {defaultChatSDKConfig} from "./validators/SDKConfigValidators";
import ISDKConfiguration from "@microsoft/ocsdk/lib/Interfaces/ISDKConfiguration";
class OmnichannelChatSDK {
public OCSDKProvider: any;
public IC3SDKProvider: any;
public OCClient: any;
public IC3Client: any;
public OCSDKProvider: unknown;
public IC3SDKProvider: unknown;
public OCClient: any; // eslint-disable-line @typescript-eslint/no-explicit-any
public IC3Client: any; // eslint-disable-line @typescript-eslint/no-explicit-any
public omnichannelConfig: IOmnichannelConfig;

@@ -50,7 +56,7 @@ public chatSDKConfig: IChatSDKConfig;

private chatToken: IChatToken;
private liveChatConfig: any;
private dataMaskingRules: any;
private liveChatConfig: any; // eslint-disable-line @typescript-eslint/no-explicit-any
private dataMaskingRules: any; // eslint-disable-line @typescript-eslint/no-explicit-any
private authSettings: IAuthSettings | null = null;
private authenticatedUserToken: string | null = null;
private preChatSurvey: any;
private preChatSurvey: any; // eslint-disable-line @typescript-eslint/no-explicit-any
private conversation: IConversation | null = null;

@@ -74,5 +80,5 @@ private debug: boolean;

public async initialize() {
public async initialize(): Promise<IChatConfig> {
this.OCSDKProvider = OCSDKProvider;
this.OCClient = await OCSDKProvider.getSDK(this.omnichannelConfig as any, {} as any, undefined as any);
this.OCClient = await OCSDKProvider.getSDK(this.omnichannelConfig as IOmnichannelConfiguration, {} as ISDKConfiguration, undefined as any); // eslint-disable-line @typescript-eslint/no-explicit-any
this.IC3Client = await this.getIC3Client();

@@ -82,3 +88,3 @@ return this.getChatConfig();

public async startChat(optionalParams: IStartChatOptionalParams = {}) {
public async startChat(optionalParams: IStartChatOptionalParams = {}): Promise<void> {

@@ -132,3 +138,3 @@ if (optionalParams.liveChatContext) {

public async endChat() {
public async endChat(): Promise<void> {
const sessionCloseOptionalParams: ISessionCloseOptionalParams = {};

@@ -151,3 +157,3 @@ if (this.authenticatedUserToken) {

public async getCurrentLiveChatContext() {
public async getCurrentLiveChatContext(): Promise<ILiveChatContext | {}> {
const chatToken = await this.getChatToken();

@@ -172,7 +178,7 @@ const {requestId} = this;

*/
public async getPreChatSurvey(parse: boolean = true) {
public async getPreChatSurvey(parse = true): Promise<any> { // eslint-disable-line @typescript-eslint/no-explicit-any
return parse ? JSON.parse(this.preChatSurvey) : this.preChatSurvey;
}
public async getLiveChatConfig(cached: boolean = true) {
public async getLiveChatConfig(cached = true): Promise<IChatConfig> {
if (cached) {

@@ -185,3 +191,3 @@ return this.liveChatConfig;

public async getChatToken(cached: boolean = true): Promise<IChatToken> {
public async getChatToken(cached = true): Promise<IChatToken> {
if (!cached) {

@@ -212,7 +218,7 @@ try {

public async getMessages() {
public async getMessages(): Promise<IMessage[] | undefined> {
return this.conversation?.getMessages();
}
public async sendMessage(message: IChatSDKMessage) {
public async sendMessage(message: IChatSDKMessage): Promise<void> {
const {disable, maskingCharacter} = this.chatSDKConfig.dataMasking;

@@ -225,4 +231,4 @@

let match;
while (match = regex.exec(content)) {
let replaceStr = match[0].replace(/./g, maskingCharacter);
while (match = regex.exec(content)) { // eslint-disable-line no-cond-assign
const replaceStr = match[0].replace(/./g, maskingCharacter);
content = content.replace(match[0], replaceStr);

@@ -260,4 +266,4 @@ }

public onNewMessage(onNewMessageCallback: CallableFunction) {
this.conversation?.registerOnNewMessage((message: any) => {
public onNewMessage(onNewMessageCallback: CallableFunction): void {
this.conversation?.registerOnNewMessage((message: IRawMessage) => {
const {messageType} = message;

@@ -276,10 +282,9 @@

public async sendTypingEvent() {
public async sendTypingEvent(): Promise<void> {
const typingPayload = `{isTyping: 0}`;
try {
this.conversation!.indicateTypingStatus(0);
this.conversation!.getMembers().then((members: any) => {
const botMembers = members.filter((member: any) => member.type === PersonType.Bot);
this.conversation!.sendMessageToBot(botMembers[0].id, {payload: typingPayload});
});
await this.conversation!.indicateTypingStatus(0);
const members: IPerson[] = await this.conversation!.getMembers();
const botMembers = members.filter((member: IPerson) => member.type === PersonType.Bot);
await this.conversation!.sendMessageToBot(botMembers[0].id, {payload: typingPayload});
} catch (error) {

@@ -291,4 +296,4 @@ console.error("OmnichannelChatSDK/sendTypingEvent/error");

public async onTypingEvent(onTypingEventCallback: CallableFunction) {
this.conversation?.registerOnNewMessage((message: any) => {
public async onTypingEvent(onTypingEventCallback: CallableFunction): Promise<void> {
this.conversation?.registerOnNewMessage((message: IRawMessage) => {
const {messageType} = message;

@@ -307,7 +312,7 @@

public async onAgentEndSession(onAgentEndSessionCallback: (message: IRawThread) => void) {
public async onAgentEndSession(onAgentEndSessionCallback: (message: IRawThread) => void): Promise<void> {
this.conversation?.registerOnThreadUpdate(onAgentEndSessionCallback);
}
public async uploadFileAttachment(fileInfo: IFileInfo) {
public async uploadFileAttachment(fileInfo: IFileInfo): Promise<IRawMessage> {
const fileMetadata: IFileMetadata = await this.conversation!.sendFileData(fileInfo, FileSharingProtocolType.AmsBasedFileSharing);

@@ -339,7 +344,7 @@

public async downloadFileAttachment(fileMetadata: IFileMetadata) {
public async downloadFileAttachment(fileMetadata: IFileMetadata): Promise<Blob> {
return this.conversation!.downloadFile(fileMetadata);
}
public async emailLiveChatTranscript(body: IChatTranscriptBody) {
public async emailLiveChatTranscript(body: IChatTranscriptBody): Promise<any> { // eslint-disable-line @typescript-eslint/no-explicit-any
const emailTranscriptOptionalParams: IEmailTranscriptOptionalParams = {};

@@ -362,3 +367,3 @@ if (this.authenticatedUserToken) {

public async getLiveChatTranscript() {
public async getLiveChatTranscript(): Promise<any> { // eslint-disable-line @typescript-eslint/no-explicit-any
const getChatTranscriptOptionalParams: IGetChatTranscriptsOptionalParams = {};

@@ -375,3 +380,3 @@ if (this.authenticatedUserToken) {

public async createChatAdapter(protocol: string = ChatAdapterProtocols.IC3) {
public async createChatAdapter(protocol: string = ChatAdapterProtocols.IC3): Promise<unknown> {
if (platform.isNode() || platform.isReactNative()) {

@@ -409,3 +414,4 @@ return Promise.reject('ChatAdapter is only supported on browser');

public setDebug(flag: boolean) {
/* istanbul ignore next */
public setDebug(flag: boolean): void {
this.debug = flag;

@@ -412,0 +418,0 @@ }

import { ic3ClientVersion, webChatIC3AdapterVersion } from "../config/settings";
const getIC3ClientCDNUrl = () => {
const IC3ClientCDNUrl: string = `https://comms.omnichannelengagementhub.com/release/${ic3ClientVersion}/Scripts/SDK/SDK.min.js`;
const getIC3ClientCDNUrl = (): string => {
const IC3ClientCDNUrl = `https://comms.omnichannelengagementhub.com/release/${ic3ClientVersion}/Scripts/SDK/SDK.min.js`;
return IC3ClientCDNUrl;
}
const getIC3AdapterCDNUrl = () => {
const IC3AdapterCDNUrl: string = `https://webchatic3.blob.core.windows.net/webchat-ic3adapter/${webChatIC3AdapterVersion}/botframework-webchat-adapter-ic3.production.min.js`;
const getIC3AdapterCDNUrl = (): string => {
const IC3AdapterCDNUrl = `https://webchatic3.blob.core.windows.net/webchat-ic3adapter/${webChatIC3AdapterVersion}/botframework-webchat-adapter-ic3.production.min.js`;
return IC3AdapterCDNUrl;

@@ -11,0 +11,0 @@ }

@@ -1,4 +0,4 @@

export const isBrowser = () => typeof window !== 'undefined' && typeof window.document !== 'undefined';
export const isNode = () => typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
export const isReactNative = () => typeof navigator != 'undefined' && navigator.product == 'ReactNative';
export const isBrowser = (): boolean => typeof window !== 'undefined' && typeof window.document !== 'undefined';
export const isNode = (): boolean => typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
export const isReactNative = (): boolean => typeof navigator != 'undefined' && navigator.product == 'ReactNative';

@@ -5,0 +5,0 @@ export default {

import MessageType from "@microsoft/omnichannel-ic3core/lib/model/MessageType";
export const isSystemMessage = (message: any) => {
export const isSystemMessage = (message: any): boolean => { // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
const {messageType, properties} = message;

@@ -9,5 +9,5 @@ return (messageType === MessageType.UserMessage)

export const isCustomerMessage = (message: any) => {
export const isCustomerMessage = (message: any): boolean => { // eslint-disable-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
const {sender} = message;
return (sender.id.includes('contacts/8:'));
}

@@ -5,3 +5,3 @@ import IOmnichannelConfig from "../core/IOmnichannelConfig";

const validateOmnichannelConfig = (omnichannelConfig: IOmnichannelConfig) => {
const validateOmnichannelConfig = (omnichannelConfig: IOmnichannelConfig): void => {
if (!omnichannelConfig) {

@@ -8,0 +8,0 @@ throw new Error(`OmnichannelConfiguration not found`);

@@ -24,3 +24,3 @@ import IChatSDKConfig, { IDataMaskingSDKConfig } from "../core/IChatSDKConfig";

const validateSDKConfig = (chatSDKConfig: IChatSDKConfig) => {
const validateSDKConfig = (chatSDKConfig: IChatSDKConfig): void => {
if (chatSDKConfig.dataMasking) {

@@ -27,0 +27,0 @@ validateDataMaskingConfig(chatSDKConfig.dataMasking);

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc