node-nlp
Version:
Library for NLU (Natural Language Understanding) done in Node.js
352 lines (319 loc) • 13.3 kB
JavaScript
const assert = require('assert');
const { TestAdapter, ActivityTypes } = require('../');
const receivedMessage = { text: 'received', type: 'message' };
const updatedActivity = { text: 'update', type: 'message' };
const deletedActivityId = '1234';
describe(`TestAdapter`, function () {
this.timeout(5000);
it(`should call bot logic when receiveActivity() is called.`, function (done) {
const adapter = new TestAdapter((context) => {
assert(context, `context not passed to bot logic.`);
assert(context.activity, `activity not passed through.`);
assert(context.activity.type === ActivityTypes.Message, `wrong type.`);
assert(context.activity.text === 'test', `wrong text.`);
assert(context.activity.id, `missing id.`);
assert(context.activity.from, `missing from.`);
assert(context.activity.recipient, `missing recipient.`);
assert(context.activity.conversation, `missing conversation.`);
assert(context.activity.channelId, `missing channelId.`);
assert(context.activity.serviceUrl, `missing serviceUrl.`);
done();
});
adapter.receiveActivity('test');
});
it(`should support receiveActivity() called with an Activity.`, function (done) {
const adapter = new TestAdapter((context) => {
assert(context.activity.type === ActivityTypes.Message, `wrong type.`);
assert(context.activity.text === 'test', `wrong text.`);
done();
});
adapter.receiveActivity({ text: 'test', type: ActivityTypes.Message });
});
it(`should automatically set the type when receiveActivity() is called with an Activity.`, function (done) {
const adapter = new TestAdapter((context) => {
assert(context.activity.type === ActivityTypes.Message, `wrong type.`);
assert(context.activity.text === 'test', `wrong text.`);
done();
});
adapter.receiveActivity({ text: 'test' });
});
it(`should support passing your own Activity.Id to receiveActivity().`, function (done) {
const adapter = new TestAdapter((context) => {
assert(context.activity.id === 'myId', `custom ID not passed through.`);
assert(context.activity.type === ActivityTypes.Message, `wrong type.`);
assert(context.activity.text === 'test', `wrong text.`);
done();
});
adapter.receiveActivity({ text: 'test', type: ActivityTypes.Message, id: 'myId' });
});
it(`should call bot logic when send() is called.`, function (done) {
const adapter = new TestAdapter((context) => {
done();
}).send('test');
});
it(`should return a message to assertReply().`, function (done) {
const adapter = new TestAdapter((context) => {
return context.sendActivity(receivedMessage);
});
adapter.send('test')
.assertReply('received')
.then(() => done());
});
it(`async startTest().`, async function () {
const adapter = new TestAdapter((context) => {
return context.sendActivity(receivedMessage);
});
await adapter.send('test')
.assertReply('received')
.startTest();
});
it(`should send and receive when test() is called.`, function (done) {
const adapter = new TestAdapter((context) => {
return context.sendActivity(receivedMessage);
});
adapter.test('test', 'received')
.then(() => done());
});
it(`should support multiple calls to test().`, function (done) {
let count = 0;
const adapter = new TestAdapter((context) => {
count++;
return context.sendActivity(receivedMessage);
});
adapter.test('test', 'received')
.test('test', 'received')
.test('test', 'received')
.test('test', 'received')
.test('test', 'received')
.then(() => {
assert(count == 5, `incorrect count of "${count}".`);
done();
});
});
it(`should support context.updateActivity() calls.`, function (done) {
const adapter = new TestAdapter((context) => {
return context.updateActivity(updatedActivity)
.then(() => context.sendActivity(receivedMessage));
});
adapter.test('test', 'received')
.then(() => {
assert(adapter.updatedActivities.length === 1, `no activities updated.`);
assert(adapter.updatedActivities[0].text === updatedActivity.text, `invalid update activity.`);
done();
});
});
it(`should support context.deleteActivity() calls.`, function (done) {
const adapter = new TestAdapter((context) => {
return context.deleteActivity({ activityId: deletedActivityId })
.then(() => context.sendActivity(receivedMessage));
});
adapter.test('test', 'received')
.then(() => {
assert(adapter.deletedActivities.length === 1, `no activities deleted.`);
assert(adapter.deletedActivities[0].activityId === deletedActivityId, `invalid deleted activity id.`);
done();
});
});
it(`should delay() before running another test.`, function (done) {
const start = new Date().getTime();
const adapter = new TestAdapter((context) => {
return context.sendActivity(receivedMessage);
});
adapter
.test('test', 'received')
.delay(600)
.test('test', 'received')
.then(() => {
const end = new Date().getTime();
assert((end - start) >= 500, `didn't delay before moving on.`);
done();
});
});
it(`should support calling assertReply() with an expected Activity.`, function (done) {
const start = new Date().getTime();
const adapter = new TestAdapter((context) => {
return context.sendActivity(receivedMessage);
});
adapter
.send('test')
.assertReply({ text: 'received' })
.then(() => done());
});
it(`should support calling assertReply() with a custom inspector.`, function (done) {
let called = false;
const start = new Date().getTime();
const adapter = new TestAdapter((context) => {
return context.sendActivity(receivedMessage);
});
adapter
.send('test')
.assertReply((reply, description) => {
assert(reply, `reply not passed`);
called = true;
})
.then(() => {
assert(called, `inspector not called.`);
done();
});
});
it(`should timeout waiting for assertReply() when a string is expected.`, function (done) {
const start = new Date().getTime();
const adapter = new TestAdapter((context) => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), 600);
});
});
adapter
.send('test')
.assertReply('received', 'received failed', 500)
.catch((err) => done());
});
it(`should timeout waiting for assertReply() when an Activity is expected.`, function (done) {
const start = new Date().getTime();
const adapter = new TestAdapter((context) => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), 600);
});
});
adapter
.send('test')
.assertReply({ text: 'received' }, 'received failed', 500)
.catch((err) => done());
});
it(`should timeout waiting for assertReply() when a custom inspector is expected.`, function (done) {
const start = new Date().getTime();
const adapter = new TestAdapter((context) => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), 600);
});
});
adapter
.send('test')
.assertReply(() => assert(false, `inspector shouldn't be called.`), 'received failed', 500)
.catch((err) => done());
});
it(`should support calling assertReplyOneOf().`, function (done) {
const start = new Date().getTime();
const adapter = new TestAdapter((context) => {
return context.sendActivity(receivedMessage);
});
adapter
.send('test')
.assertReplyOneOf(['foo', 'bar', 'received'])
.then(() => done());
});
it(`should fail assertReplyOneOf() call for invalid response.`, function (done) {
const start = new Date().getTime();
const adapter = new TestAdapter((context) => {
return context.sendActivity(receivedMessage);
});
adapter
.send('test')
.assertReplyOneOf(['foo', 'bar'])
.then(() => {
assert(false, `shouldn't pass test.`);
})
.catch(() => done());
});
it(`should return an error from continueConversation().`, function (done) {
const adapter = new TestAdapter((context) => {
assert(false, `shouldn't run bot logic.`);
});
adapter.continueConversation().catch((err) => {
assert(err, `Error not returned.`);
done();
});
});
it(`should apply the user-defined Activity template.`, function (done) {
const template = {
channelId: 'foo',
from: { id: 'foo', name: 'Foo' },
};
new TestAdapter((context) => {
assert(context.activity.channelId === template.channelId, `activity channelId does not match template.`);
assert(context.activity.from.id === template.from.id, `activity from.id does not match template.`);
assert(context.activity.from.name === template.from.name, `activity from.name does not match template.`);
assert(context.activity.serviceUrl, `missing serviceUrl.`);
done();
}, template).send('test');
});
it(`should test activities that have a from.role normalized value of 'bot' via testActivities().`, function (done) {
// Counter to keep track of how many times the bot logic is run.
let counter = 0;
const adapter = new TestAdapter((context) => {
counter++;
return context.sendActivity('Greetings User!');
});
// We create two activities, one which is a message from the user to the bot.
// The other is the bot's response.
// The bot's logic should only run once, when it receives the 'Hello' from the user.
const activities = [
{
from: {
role: 'User',
name: 'User',
id: 'user'
},
type: 'message',
text: 'Hello'
},
{
from: {
role: 'Bot',
name: 'Bot',
id: 'bot'
},
type: 'message',
text: 'Greetings User!'
}
];
adapter.testActivities(activities).then(() => {
assert(counter === 1, `should have only run bot logic once.`);
done();
});
});
it(`should run the bot's logic to activities without a from property via testActivities().`, function (done) {
let counter = 0;
const adapter = new TestAdapter((context) => {
counter++;
});
// These conversationUpdate activities should trigger the bot's logic to run.
const activities = [
{
type: 'conversationUpdate',
membersAdded: [
{ name: 'Bot', id: 'bot' }
]
},
{
type: 'conversationUpdate',
membersAdded: [
{ name: 'User', id: 'user' }
]
},
{
type: 'conversationUpdate',
membersRemoved: [
{ name: 'Bot', id: 'bot' },
{ name: 'User', id: 'user' }
]
}
];
adapter.testActivities(activities).then(() => {
assert(counter === 3, `should have run bot logic for activities without the from property.`);
done();
});
});
it(`should throw error if activities is not passed to testActivities().`, function (done) {
const adapter = new TestAdapter((context) => {
return context.sendActivity(context.activity.text);
});
try {
adapter.testActivities()
} catch (e) {
assert(e.message === 'Missing array of activities', `wrong error thrown.`);
done();
}
throw new Error(`TestAdapter.testActivities() should not have succeeded without activities argument.`);
});
});