Skip to content

Repository files navigation

Bot Tester for Bot Builder Framework CircleCInpm versionCoverage Status

Simple framework that allows for easy testing of a botbuiler chatbot using mocha and chai.

install

npm install --save bot-tester

Class definitions, see the BotTester Framework reference docs

config

config can be set one of 2 ways:

  1. creating a bot-tester.json file in the root directory of your project.
  2. passing in a config object into the options param, which is the last, when creating a BotTester instance

Passing in the config overrides any default values or values set by bot-tester.json. At the moment, the options are:

{defaultAddress: botbuilder.IAddress,timeout: number// in milliseconds}

if timeout is defined, then a particular runTest() call will fail if it does not receive each expected message within the timeout period of time set in the options.

For a more in depth view, check out the Bot Tester Framework Config doc

Example Usage

import{IAddress,IMessage,Message,Prompts,Session,UniversalBot}from'botbuilder';import{expect}from'chai';import{BotTester,TestConnector}from'bot-tester';constconnector=newTestConnector();describe('BotTester',()=>{letbot;beforeEach(()=>{bot=newUniversalBot(connector);});// ... tests live here!

Test for single response

it('can handle a single response',()=>{bot.dialog('/',(session)=>{session.send('hello!');});constbotTester=newBotTester(bot).sendMessageToBot('Hola!','hello!');returnbotTester.runTest();});

Test for multiple responses

it('can handle multiple responses',()=>{bot.dialog('/',(session)=>{session.send('hello!');session.send('how are you doing?');});newBotTester(bot).sendMessageToBot('Hola!','hello!','how are you doing?').runTest();});

Test for random response arrays

// re-run the test multiple times to guarantee that multiple colors are returnedletrandomResponseRunCounter=5;constrandomColors=['red','green','blue','grey','gray','purple','magenta','cheese','orange','hazelnut'];while(randomResponseRunCounter--){it('Can handle random responses',()=>{bot.dialog('/',(session)=>{session.send(randomColors);});returnnewBotTester(bot).sendMessageToBot('tell me a color!',randomColors).runTest();});}

Test with prompts

it('can test prompts',()=>{bot.dialog('/',[(session)=>{newPrompts.text(session,'Hi there! Tell me something you like');},(session,results)=>{session.send(`${results.response} is pretty cool.`);newPrompts.text(session,'Why do you like it?');},(session)=>session.send('Interesting. Well, that\'s all I have for now')]);returnnewBotTester(bot).sendMessageToBot('Hola!','Hi there! Tell me something you like').sendMessageToBot('The sky','The sky is pretty cool.','Why do you like it?').sendMessageToBot('It\'s blue','Interesting. Well, that\'s all I have for now').runTest();});

Inspect session

it('can inspect session state',()=>{bot.dialog('/',[(session)=>{newPrompts.text(session,'What would you like to set data to?');},(session,results)=>{session.userData={data: results.response};session.save();}]);returnnewBotTester(bot).sendMessageToBot('Start this thing!','What would you like to set data to?').sendMessageToBotAndExpectSaveWithNoResponse('This is data!').checkSession((session)=>{expect(session.userData).not.to.be.null;expect(session.userData.data).to.be.equal('This is data!');}).runTest();});

Test custom messages

it('can handle custom messages in response',()=>{constcustomMessage: {someField?: {}}&IMessage=newMessage().text('this is text').toMessage();customMessage.someField={a: 1};customMessage.type='newType';constmatchingCustomMessage: {someField?: {}}&IMessage=newMessage().toMessage();matchingCustomMessage.text='this is text';matchingCustomMessage.type='newType';bot.dialog('/',(session: Session)=>{session.send(customMessage);});returnnewBotTester(bot).sendMessageToBot('anything',customMessage).sendMessageToBot('anything',matchingCustomMessage).runTest();});

Address/multiuser cases

describe('Address/multi user',()=>{constdefaultAddress={channelId: 'console',user: {id: 'user1',name: 'A'},bot: {id: 'bot',name: 'Bot'},conversation: {id: 'user1Conversation'}};constuser2Address={channelId: 'console',user: {id: 'user2',name: 'B'},bot: {id: 'bot',name: 'Bot'},conversation: {id: 'user2Conversation'}};beforeEach(()=>{bot.dialog('/',(session)=>session.send(session.message.address.user.name));});

Can check addressess, including partial addresses

it('can ensure proper address being used for routing. Includes partial address',()=>{constaskForUser1Name=newMessage().text('What is my name?').address(defaultAddress).toMessage();constexpectedAddressInMessage=newMessage().address(defaultAddress).toMessage();constaddr={user: {id: 'user1'}}asIAddress;// partial addresses work as well (i.e. if you only want to check one field such as userId)constexpectedPartialAddress=newMessage().address(addr).toMessage();returnnewBotTester(bot).sendMessageToBot(askForUser1Name,expectedAddressInMessage).sendMessageToBot(askForUser1Name,expectedPartialAddress).runTest();});

Can have a default address assigned to the bot

// the bot can have a default address that messages are sent to. If needed, the default address can be ignored by sending an IMessageit('Can have a default address assigned to it and communicate to multiple users',()=>{constaskForUser1Name=newMessage().text('What is my name?').address(defaultAddress).toMessage();constaskForUser2Name=newMessage().text('What is my name?').address(user2Address).toMessage();constuser1ExpectedResponse=newMessage().text('A').address(defaultAddress).toMessage();constuser2ExpectedResponse=newMessage().text('B').address(user2Address).toMessage();// when testing for an address that is not the default for the bot, the address must be passed inreturnnewBotTester(bot,{ defaultAddress })// because user 1 is the default address, the expected responses can be a string.sendMessageToBot(askForUser1Name,'A').sendMessageToBot(askForUser1Name,user1ExpectedResponse).sendMessageToBot(askForUser2Name,user2ExpectedResponse).runTest();});});

Can test batch responses

it('can handle batch responses',()=>{constCUSTOMER_ADDRESS: IAddress={channelId: 'console',user: {id: 'userId1',name: 'user1'},bot: {id: 'bot',name: 'Bot'},conversation: {id: 'user1Conversation'}};constmsg1=newMessage().address(CUSTOMER_ADDRESS).text('hello').toMessage();constmsg2=newMessage().address(CUSTOMER_ADDRESS).text('there').toMessage();bot.dialog('/',(session: Session)=>{bot.send([msg1,msg2]);});returnnewBotTester(bot,{defaultAddress: CUSTOMER_ADDRESS}).sendMessageToBot('anything','hello','there').runTest();});

Can test using regex

it('accepts RegExp',()=>{constnumberRegex=/^\d+/;bot.dialog('/',(session)=>{// send only numbers for this test case ....session.send(session.message.text);});returnnewBotTester(bot).sendMessageToBot('1',numberRegex).sendMessageToBot('3156',numberRegex).sendMessageToBot('8675309',numberRegex).runTest();});

variable # args can have mixed type

it('rest params can have mixed type',()=>{constnumberRegex=/^\d+/;bot.dialog('/',(session)=>{session.send(session.message.text);session.send(session.message.text);});returnnewBotTester(bot).sendMessageToBot('123',numberRegex,'123').runTest();});

Can perform arbitrary work between test steps

it('can do arbitrary work between test steps',()=>{letresponseString='goodbye';bot.dialog('/',(session)=>{// send only numbers for this test case ....session.send(responseString);});returnnewBotTester(bot).sendMessageToBot('you say','goodbye').then(()=>responseString='hello').sendMessageToBot('and i say','hello').runTest();});

Can wait between test steps

it('can wait between test steps',()=>{constdelay=1000;letbeforeDelayTime;letafterDelayTime;bot.dialog('/',(session)=>{// send only numbers for this test case ....if(afterDelayTime-beforeDelayTime>=delay){session.send('i waited some time');}});returnnewBotTester(bot).then(()=>beforeDelayTime=Date.now()).wait(delay).then(()=>afterDelayTime=Date.now()).sendMessageToBot('have you waited ?','i waited some time').runTest();});

can check messages while ignoring order

it('can accept messages without expectations for order',()=>{bot.dialog('/',(session)=>{session.send('hi');session.send('there');session.send('how are you?');});returnnewBotTester(bot).sendMessageToBotIgnoringResponseOrder('anything','how are you?','hi','there').runTest();});

About

A simple bot testing framework for the bot builder framework. Easily send messages to a bot and check for expected responses and inspect session inside a dialog

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages