Skip to content

Commit

Permalink
[ARO] Add unit test + interpretation of string return
Browse files Browse the repository at this point in the history
  • Loading branch information
erbizard committed Jul 25, 2018
1 parent f2c97dc commit fb63b7f
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 29 deletions.
13 changes: 9 additions & 4 deletions src/ExpectedMessage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {IEvent, IMessage} from 'botbuilder';
import {assert} from 'chai';
import {BotTesterExpectation} from './assertionLibraries/BotTesterExpectation';
import {IConfig} from './config';

Expand Down Expand Up @@ -116,7 +115,7 @@ export class ExpectedMessage {
const regexCollection: RegExp[] = this.expectedResponseCollection as RegExp[];

this.internalExpectation.expect(regexCollection.some((regex: RegExp) => regex.test(text)),
`'${text}' did not match any regex in ${regexCollection}`).toBeTrue();
`'${text}' did not match any regex in ${regexCollection}`).toBeTrue();
}

/**
Expand Down Expand Up @@ -152,19 +151,25 @@ export class ExpectedMessage {
private deepMatchCheckWithFunction(outgoingMessage: IMessage): void {
const functionCollection: Function[] = this.expectedResponseCollection as Function[];
let errorString = '';
const exceptedResponsesStrings = [];
let success = false;
functionCollection.forEach((func: Function) => {
const result = func(outgoingMessage);
if (result instanceof Error) {
errorString += `\n -----------------ERROR-----------------\n\n\n'${result.message}' `;
} else if (typeof result === 'string') {
exceptedResponsesStrings.push(result);
} else {
success = true;
}
});
// ErrorString here, can hold multiples error, if the bot send multiples message in one batching
const error = `Bot should have relied response that matches with function but respond '${outgoingMessage}'` +
` that create the following error(s) '${errorString}'`;
this.internalExpectation.expect(success, error).toBeTrue();

if (exceptedResponsesStrings.length > 0) {
this.checkMessageTextForExactStringMatch(outgoingMessage, exceptedResponsesStrings);
} else {
this.internalExpectation.expect(success, error).toBeTrue();
}
}
}
89 changes: 65 additions & 24 deletions test/mocha/chai/BotTester.mocha.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//```javascript
import { IAddress, IMessage, Message, Prompts, Session, UniversalBot } from 'botbuilder';
import {IAddress, IMessage, Message, Prompts, Session, UniversalBot} from 'botbuilder';
import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised';
import { BotTester } from './../../../src/BotTester';
import { TestConnector } from './../../../src/TestConnector';
import { getAdaptiveCard, getAdaptiveCardAttachment, getAdaptiveCardMessage } from './../../adaptiveCardProvider';
import {BotTester} from './../../../src/BotTester';
import {TestConnector} from './../../../src/TestConnector';
import {getAdaptiveCard, getAdaptiveCardAttachment, getAdaptiveCardMessage} from './../../adaptiveCardProvider';

chai.use(chaiAsPromised);
const expect = chai.expect;
Expand Down Expand Up @@ -105,12 +105,12 @@ describe('BotTester', () => {
bot.dialog('/', [(session) => {
new Prompts.text(session, 'What would you like to set data to?');
}, (session, results) => {
session.userData = { data: results.response };
session.userData = {data: results.response};
session.save();
}]);

return new BotTester(bot)
.sendMessageToBot('Start this thing!', 'What would you like to set data to?')
.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;
Expand Down Expand Up @@ -152,16 +152,18 @@ describe('BotTester', () => {
//# Address/multiuser cases
//```javascript
describe('Address/multi user', () => {
const defaultAddress = { channelId: 'console',
user: { id: 'customUser1', name: 'A' },
bot: { id: 'customBot1', name: 'Bot1' },
conversation: { id: 'customUser1Conversation' }
const defaultAddress = {
channelId: 'console',
user: {id: 'customUser1', name: 'A'},
bot: {id: 'customBot1', name: 'Bot1'},
conversation: {id: 'customUser1Conversation'}
};

const user2Address = { channelId: 'console',
user: { id: 'user2', name: 'B' },
bot: { id: 'bot', name: 'Bot' },
conversation: { id: 'user2Conversation' }
const user2Address = {
channelId: 'console',
user: {id: 'user2', name: 'B'},
bot: {id: 'bot', name: 'Bot'},
conversation: {id: 'user2Conversation'}
};

beforeEach(() => {
Expand Down Expand Up @@ -201,7 +203,7 @@ describe('BotTester', () => {

//## Can have a default address assigned to the bot
//```javascript
// the bot can have a default address that messages are sent to. If needed, the default address can be ignored by sending an IMessage
// the bot can have a default address that messages are sent to. If needed, the default address can be ignored by sending an IMessage
it('Can have a default address assigned to it and communicate to multiple users', () => {
const askForUser1Name = new Message()
.text('What is my name?')
Expand All @@ -224,8 +226,8 @@ describe('BotTester', () => {
.toMessage();

// when testing for an address that is not the default for the bot, the address must be passed in
return new BotTester(bot, { defaultAddress })
// because user 1 is the default address, the expected responses can be a string
return new BotTester(bot, {defaultAddress})
// because user 1 is the default address, the expected responses can be a string
.sendMessageToBot(askForUser1Name, 'A')
.sendMessageToBot('What is my name?', user1ExpectedResponse)
.sendMessageToBot(askForUser1Name, user1ExpectedResponse)
Expand All @@ -238,10 +240,11 @@ describe('BotTester', () => {
//# Can test batch responses
//```javascript
it('can handle batch responses', () => {
const CUSTOMER_ADDRESS: IAddress = { channelId: 'console',
user: { id: 'userId1', name: 'user1' },
bot: { id: 'bot', name: 'Bot' },
conversation: { id: 'user1Conversation' }
const CUSTOMER_ADDRESS: IAddress = {
channelId: 'console',
user: {id: 'userId1', name: 'user1'},
bot: {id: 'bot', name: 'Bot'},
conversation: {id: 'user1Conversation'}
};

const msg1 = new Message()
Expand All @@ -258,7 +261,7 @@ describe('BotTester', () => {
bot.send([msg1, msg2]);
});

return new BotTester(bot, { defaultAddress: CUSTOMER_ADDRESS })
return new BotTester(bot, {defaultAddress: CUSTOMER_ADDRESS})
.sendMessageToBot('anything', 'hello', 'there')
.runTest();
});
Expand All @@ -282,6 +285,44 @@ describe('BotTester', () => {
});
//```

//# Can test using Function
//```javascript
it('accepts Function', () => {
bot.dialog('/', (session: Session) => {
session.send('hello!');
session.send('12');
});

const botTester = new BotTester(bot)
.sendMessageToBot('Hi', (message: IMessage) => {
if (message.text === 'hello!') {
return true;
}
}, (message: IMessage) => {
if (parseInt(message.text, 0) % 2 === 0) {
return true;
}
});

return botTester.runTest();
});
//```

//```javascript
it('accepts Function that return string', () => {
bot.dialog('/', (session: Session) => {
session.send('hello!');
});

const botTester = new BotTester(bot)
.sendMessageToBot('Hi', (message: IMessage) => {
return message.text;
});

return botTester.runTest();
});
//```

//# variable # args can have mixed type
//```javascript
it('rest params can have mixed type', () => {
Expand Down Expand Up @@ -367,7 +408,7 @@ describe('BotTester', () => {
const ignoreHowMessage = (message) => !message.text.includes('how');
const ignoreAreMessage = (message) => !message.text.includes('are');

return new BotTester(bot, { messageFilters: [ignoreHowMessage, ignoreAreMessage]})
return new BotTester(bot, {messageFilters: [ignoreHowMessage, ignoreAreMessage]})
.sendMessageToBot('intro', 'hello', 'you?')
.runTest();
});
Expand All @@ -393,7 +434,7 @@ describe('BotTester', () => {
it('change timeout time', (done) => {
const timeout = 750;
bot.dialog('/', (session) => {
setTimeout(() => session.send('hi there'), timeout * 2 );
setTimeout(() => session.send('hi there'), timeout * 2);
});

expect(new BotTester(bot)
Expand Down
35 changes: 34 additions & 1 deletion test/mocha/chai/BotTesterFailure.mocha.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ describe('BotTester', () => {
});

// ignore this for now. It's more of a debate as to whether or not the user should know not to do this
xit('it will fail if an empty collection is given', () => {
it('it will fail if an empty collection is given', () => {
bot.dialog('/', (session: Session) => {
session.send('hello!');
});
Expand Down Expand Up @@ -193,6 +193,39 @@ describe('BotTester', () => {
).to.eventually.be.rejectedWith('\'abcd\' did not match any regex in /^\\d+/').notify(done);
});

it('will fail if function return an error', (done: Function) => {
bot.dialog('/', (session: Session) => {
session.send('hello!');
session.send('13');
});

const botTester = new BotTester(bot)
.sendMessageToBot('Hi', (message: IMessage) => {
if (message.text === 'hello!') {
return true;
}
}, (message: IMessage) => {
if (parseInt(message.text, 0) % 2 !== 0) {
return new Error(`Message is not an even number : '${message.text}'`);
}
});

expect(botTester.runTest()).to.be.rejected.notify(done);
});

it('will fail if function return a bad string', (done: Function) => {
bot.dialog('/', (session: Session) => {
session.send('hello!');
});

const botTester = new BotTester(bot)
.sendMessageToBot('Hi', (message: IMessage) => {
return 'foo';
});

expect(botTester.runTest()).to.be.rejected.notify(done);
});

it('can timeout', (done: Function) => {
const timeout = 1000;
bot.dialog('/', (session: Session) => {
Expand Down

0 comments on commit fb63b7f

Please sign in to comment.