bot-handoff
Version:
Bot hand off module for the Microsoft Bot Framework. It allows you to transfer a customer from talking to a bot to talking to a human.
136 lines (111 loc) • 6.19 kB
text/typescript
import * as Promise from 'bluebird';
import { BotTester } from 'bot-tester';
import { ConsoleConnector, IAddress, Message, Session, UniversalBot } from 'botbuilder';
import * as chai from 'chai';
import * as sinon from 'sinon';
import * as sinonChai from 'sinon-chai';
import { QueueEventMessage } from '../src/eventMessages/QueueEventMessage';
import { IConversation } from '../src/IConversation';
import { MessageReceivedWhileWaitingHandler } from '../src/options/MessageReceivedWhileWaitingHandler';
import { InMemoryProvider } from '../src/provider/prebuilt/InMemoryProvider';
import { applyHandoffMiddleware } from './../src/applyHandoffMiddleware';
import { ConnectEventMessage } from './../src/eventMessages/ConnectEventMessage';
import { IProvider } from './../src/provider/IProvider';
chai.use(sinonChai);
const expect = chai.expect;
const connector = new ConsoleConnector();
const CUSTOMER_ADDRESS: IAddress = { channelId: 'console',
user: { id: 'userId1', name: 'user1' },
bot: { id: 'bot', name: 'Bot' },
conversation: { id: 'user1Conversation' }
};
const AGENT_ADDRESS: IAddress = { channelId: 'console',
user: { id: 'agentId', name: 'agent' },
bot: { id: 'bot', name: 'Bot' },
conversation: { id: 'agent_convo' }
};
const isAgent = (session: Session): Promise<boolean> => {
return Promise.resolve(session.message.address.user.name === 'agent');
};
describe('agent handoff', () => {
let bot: UniversalBot;
let provider: IProvider;
const customerIntroMessage = new Message()
.text('hello')
.address(CUSTOMER_ADDRESS)
.toMessage();
const agentMessage = new Message()
.address(AGENT_ADDRESS)
.text('hello there')
.toMessage();
beforeEach(() => {
provider = new InMemoryProvider();
bot = new UniversalBot(connector);
bot.dialog('/', (session: Session) => {
session.send('intro!');
});
});
it('can handover to agents', () => {
applyHandoffMiddleware(bot, isAgent, provider);
const userReceptionOfAgentMessage = Object.assign({}, agentMessage, { address: CUSTOMER_ADDRESS, text: 'hello there'});
const userResponseToAgent = Object.assign({}, customerIntroMessage, {text: 'I\'m responding'});
const agentReceptionOfResponse = Object.assign({}, userResponseToAgent, { address: AGENT_ADDRESS });
return new BotTester(bot, CUSTOMER_ADDRESS)
.sendMessageToBot(customerIntroMessage, 'intro!')
.sendMessageToBot(new ConnectEventMessage(CUSTOMER_ADDRESS, AGENT_ADDRESS), 'you\'re now connected to an agent')
.sendMessageToBot(agentMessage, userReceptionOfAgentMessage)
.sendMessageToBot(userResponseToAgent, agentReceptionOfResponse)
.runTest()
.then(() => provider.getAllConversations())
.then((convos: IConversation[]) => {
convos.forEach((convo: IConversation) => {
expect(convo.transcript).not.to.be.empty;
});
});
});
describe('Handoff Options', () => {
it('will not transcribe if shouldTranscribeMessages option is set to false', () => {
applyHandoffMiddleware(bot, isAgent, provider, {shouldTranscribeMessages: false});
const userReceptionOfAgentMessage = Object.assign({}, agentMessage, { address: CUSTOMER_ADDRESS, text: 'hello there'});
return new BotTester(bot, CUSTOMER_ADDRESS)
.sendMessageToBot(customerIntroMessage, 'intro!')
.sendMessageToBot(new ConnectEventMessage(CUSTOMER_ADDRESS, AGENT_ADDRESS), 'you\'re now connected to an agent')
.sendMessageToBot(agentMessage, userReceptionOfAgentMessage)
.runTest()
.then(() => provider.getAllConversations())
.then((convos: IConversation[]) => {
convos.forEach((convo: IConversation) => {
expect(convo.transcript).to.be.empty;
});
});
});
it('calls the MessageReceivedWhileWaitingHandler when in a waiting state', () => {
// limitations of the BotTester famework require next to be called for the test to pass
const messageReceivedHandler: MessageReceivedWhileWaitingHandler = (_0: UniversalBot, _1: Session, next: Function) => {
next();
};
const spy = sinon.spy(messageReceivedHandler);
const resetSpy = () => spy.reset();
const messageReceivedWhileWaitingHandlerSpy = spy as MessageReceivedWhileWaitingHandler;
const expectMessageReceivedWhileWaitingNotToHaveBeenCalled =
() => expect(messageReceivedWhileWaitingHandlerSpy).not.to.have.been.called;
const expectMessageReceivedWhileWaitingToHaveBeenCalledOnce =
() => expect(messageReceivedWhileWaitingHandlerSpy).to.have.been.calledOnce;
applyHandoffMiddleware(bot, isAgent, provider, { messageReceivedWhileWaitingHandler: messageReceivedWhileWaitingHandlerSpy });
const userReceptionOfAgentMessage = Object.assign({}, agentMessage, { address: CUSTOMER_ADDRESS, text: 'hello there'});
return new BotTester(bot, CUSTOMER_ADDRESS)
.sendMessageToBot(customerIntroMessage, 'intro!')
.then(expectMessageReceivedWhileWaitingNotToHaveBeenCalled)
.sendMessageToBot(new QueueEventMessage(CUSTOMER_ADDRESS))
.then(expectMessageReceivedWhileWaitingNotToHaveBeenCalled)
.sendMessageToBot(customerIntroMessage)
.then(expectMessageReceivedWhileWaitingToHaveBeenCalledOnce)
.then(resetSpy)
.sendMessageToBot(new ConnectEventMessage(CUSTOMER_ADDRESS, AGENT_ADDRESS), 'you\'re now connected to an agent')
.then(expectMessageReceivedWhileWaitingNotToHaveBeenCalled)
.sendMessageToBot(agentMessage, userReceptionOfAgentMessage)
.then(expectMessageReceivedWhileWaitingNotToHaveBeenCalled)
.runTest();
});
});
});