test/botly_test.js
var expect = require('chai').expect;
var mockery = require('mockery');
var sinon = require('sinon');
var http = require('node-mocks-http');
var requireHelper = require('./util/requireHelper');
var Botly;
var request = {
post: sinon.stub(),
get: sinon.stub()
};
const USER_ID = '333';
const PAGE_ID = '111';
describe('Botly Tests', function () {
before(() => {
mockery.enable({
warnOnReplace: false,
warnOnUnregistered: false,
useCleanCache: true
});
// replace the module `request` with a stub object
mockery.registerMock('request', request);
Botly = requireHelper('Botly');
});
afterEach(() => {
request.post = sinon.stub();
request.get = sinon.stub();
});
after(() => {
mockery.disable();
});
it('should exist and allow instance creation with configuration', () => {
expect(Botly).to.be.a.function;
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
expect(botly).to.be.defined;
expect(botly.accessToken).to.equal('myToken');
expect(botly.verifyToken).to.equal('myVerifyToken');
expect(botly.webHookPath).to.equal('/webhook');
expect(botly.notificationType).to.equal(Botly.CONST.NOTIFICATION_TYPE.NO_PUSH);
});
it('should throw an error when no access token provided', () => {
expect(Botly).to.throw(Error, /Must provide accessToken/);
});
it('should provide an express router and handle correct verify_token', () => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var router = botly.router();
expect(router).to.be.defined;
var response = http.createResponse();
var request = http.createRequest({
method: 'GET',
url: '/webhook',
query: {
'hub.mode': 'subscribe',
'hub.verify_token': 'myVerifyToken',
'hub.challenge': '42'
}
});
router.handle(request, response);
expect(response._getData()).to.equal('42');
});
it('should provide an express router and reject correct verify_token if hub.mode is not "subscribe"', () => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var router = botly.router();
expect(router).to.be.defined;
var response = http.createResponse();
var request = http.createRequest({
method: 'GET',
url: '/webhook',
query: {
'hub.mode': 'SubscribE',
'hub.verify_token': 'myVerifyToken',
'hub.challenge': '42'
}
});
router.handle(request, response);
expect(response.statusCode).to.equal(403);
expect(response._getData()).to.equal('Error, wrong validation token');
});
it('should provide an express router and handle bad verify_token', () => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var router = botly.router();
expect(router).to.be.defined;
var response = http.createResponse();
var request = http.createRequest({
method: 'GET',
url: '/webhook',
query: {
'hub.mode': 'subscribe',
'hub.verify_token': '111',
'hub.challenge': '42'
}
});
router.handle(request, response);
expect(response.statusCode).to.equal(403);
expect(response._getData()).to.equal('Error, wrong validation token');
});
it('should handle optin messages', done => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var router = botly.router();
botly.on('optin', (id, message, optin) => {
expect(id).to.equal(USER_ID);
expect(optin).to.equal('PASS_THROUGH_PARAM');
done();
});
var response = http.createResponse();
var request = http.createRequest({
method: 'POST',
url: '/webhook',
body: {
'object': 'page',
'entry': [
{
'id': PAGE_ID,
'time': 12341,
'messaging': [
{
'sender': {
'id': USER_ID
},
'recipient': {
'id': PAGE_ID
},
'timestamp': 1234567890,
'optin': {
'ref': 'PASS_THROUGH_PARAM'
}
}
]
}
]
}
});
router.handle(request, response);
});
it('should handle echo messages', done => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var router = botly.router();
botly.on('echo', (id, message, content) => {
expect(id).to.equal(USER_ID);
expect(content.text).to.equal('some text');
done();
});
var response = http.createResponse();
var request = http.createRequest({
method: 'POST',
url: '/webhook',
body: {
'object': 'page',
'entry': [
{
'id': PAGE_ID,
'time': 12341,
'messaging': [
{
'sender': {
'id': USER_ID
},
'recipient': {
'id': PAGE_ID
},
'timestamp': 1234567890,
'message': {
'mid': 'mid.1457764197618:41d102a3e1ae206a38',
'seq': 73,
'text': 'some text',
'is_echo': true
}
}
]
}
]
}
});
router.handle(request, response);
});
it('should emit error when there is one', done => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var router = botly.router();
botly.on('error', (err) => {
expect(err).to.be.defined;
done();
});
var response = http.createResponse();
var request = http.createRequest({
method: 'POST',
url: '/webhook',
body: {
'object': 'page',
'entry': 'blabla'
}
});
router.handle(request, response);
});
it('should handle delivery messages', done => {
var mids = [
'mid.1458668856218:ed81099e15d3f4f233'
];
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var router = botly.router();
botly.on('delivery', (id, message, delivery) => {
expect(id).to.equal(USER_ID);
expect(delivery[0]).to.equal(mids[0]);
done();
});
var response = http.createResponse();
var request = http.createRequest({
method: 'POST',
url: '/webhook',
body: {
'object': 'page',
'entry': [
{
'id': PAGE_ID,
'time': 1458668856451,
'messaging': [
{
'sender': {
'id': USER_ID
},
'recipient': {
'id': PAGE_ID
},
'delivery': {
'mids': mids,
'watermark': 1458668856253,
'seq': 37
}
}
]
}
]
}
});
router.handle(request, response);
});
it('should handle account linking messages', done => {
var linkContent = {
"status": "linked",
"authorization_code": "PASS_THROUGH_AUTHORIZATION_CODE"
};
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var router = botly.router();
botly.on('account_link', (id, message, link) => {
expect(id).to.equal(USER_ID);
expect(link).to.eql(linkContent);
done();
});
var response = http.createResponse();
var request = http.createRequest({
method: 'POST',
url: '/webhook',
body: {
'object': 'page',
'entry': [
{
'id': PAGE_ID,
'time': 1458668856451,
'messaging': [
{
'sender': {
'id': USER_ID
},
'recipient': {
'id': PAGE_ID
},
'account_linking': linkContent
}
]
}
]
}
});
router.handle(request, response);
});
it('should handle postback messages', done => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var router = botly.router();
botly.on('postback', (id, message, payload) => {
expect(id).to.equal(USER_ID);
expect(payload).to.equal('USER_DEFINED_PAYLOAD');
done();
});
var response = http.createResponse();
var request = http.createRequest({
method: 'POST',
url: '/webhook',
body: {
'object': 'page',
'entry': [
{
'id': PAGE_ID,
'time': 1458692752478,
'messaging': [
{
'sender': {
'id': USER_ID
},
'recipient': {
'id': PAGE_ID
},
'timestamp': 1458692752478,
'postback': {
'payload': 'USER_DEFINED_PAYLOAD'
}
}
]
}
]
}
});
router.handle(request, response);
});
it('should handle text messages', done => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var router = botly.router();
botly.on('message', (id, message, data) => {
expect(id).to.equal(USER_ID);
expect(data.text).to.equal('hello, world!');
done();
});
var response = http.createResponse();
var request = http.createRequest({
method: 'POST',
url: '/webhook',
body: {
'object': 'page',
'entry': [
{
'id': PAGE_ID,
'time': 1457764198246,
'messaging': [
{
'sender': {
'id': USER_ID
},
'recipient': {
'id': PAGE_ID
},
'timestamp': 1457764197627,
'message': {
'mid': 'mid.1457764197618:41d102a3e1ae206a38',
'seq': 73,
'text': 'hello, world!'
}
}
]
}
]
}
});
router.handle(request, response);
});
it('should handle attachment messages', done => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var router = botly.router();
botly.on('message', (id, message, data) => {
expect(id).to.equal(USER_ID);
expect(data.attachments.image[0]).to.equal('IMAGE_URL');
done();
});
var response = http.createResponse();
var request = http.createRequest({
method: 'POST',
url: '/webhook',
body: {
'object': 'page',
'entry': [
{
'id': PAGE_ID,
'time': 1458696618911,
'messaging': [
{
'sender': {
'id': USER_ID
},
'recipient': {
'id': PAGE_ID
},
'timestamp': 1458696618268,
'message': {
'mid': 'mid.1458696618141:b4ef9d19ec21086067',
'seq': 51,
'attachments': [
{
'type': 'image',
'payload': {
'url': 'IMAGE_URL'
}
}
]
}
}
]
}
]
}
});
router.handle(request, response);
});
it('should send text messages', () => {
request.post.yields(null, {});
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.sendText({id: USER_ID, text: 'hi'}, () => {
});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].url).to.equal('https://graph.facebook.com/v2.12/me/messages');
expect(request.post.args[0][0].body).to.eql({
'message': {
'text': 'hi'
},
'messaging_type': 'RESPONSE',
'notification_type': 'NO_PUSH',
'recipient': {
'id': '333'
}
});
});
it('should allow overriding the url', () => {
request.post.yields(null, {});
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
FB_URL: 'https://mydomain.com/',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.sendText({id: USER_ID, text: 'hi'}, () => {
});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].url).to.equal('https://mydomain.com/me/messages');
expect(request.post.args[0][0].body).to.eql({
'message': {
'text': 'hi'
},
'messaging_type': 'RESPONSE',
'notification_type': 'NO_PUSH',
'recipient': {
'id': '333'
}
});
});
it('should send sender action', () => {
request.post.yields(null, {});
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.sendAction({id: USER_ID, action: Botly.CONST.ACTION_TYPES.TYPING_ON}, () => {
});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'sender_action': 'typing_on',
'messaging_type': 'RESPONSE',
'recipient': {
'id': '333'
}
});
});
it('should send text messages with quick replies', () => {
request.post.yields(null, {});
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.sendText({
id: USER_ID,
text: 'hi',
quick_replies: [botly.createQuickReply('option1', 'option_1', 'http://google.com/someimage.png'), botly.createShareLocation()]
}, () => {
});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'message': {
'text': 'hi',
'quick_replies': [
{
'content_type': 'text',
'title': 'option1',
'payload': 'option_1',
'image_url': 'http://google.com/someimage.png'
},
{
'content_type': 'location'
}
]
},
'messaging_type': 'RESPONSE',
'notification_type': 'NO_PUSH',
'recipient': {
'id': '333'
}
});
});
it('should send image messages', () => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.sendImage({id: USER_ID, url: 'http://image.com', is_reusable: true});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'message': {
'attachment': {
'payload': {
'url': 'http://image.com',
'is_reusable': true
},
'type': 'image'
}
},
'messaging_type': 'RESPONSE',
'notification_type': 'NO_PUSH',
'recipient': {
'id': '333'
}
});
});
it('should upload attachment', () => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.upload({type: Botly.CONST.ATTACHMENT_TYPE.IMAGE, payload: {url: 'http://image.com', is_reusable: true}});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'message': {
'attachment': {
'payload': {
'url': 'http://image.com',
'is_reusable': true
},
'type': 'image'
}
}
});
});
it('should send button messages', () => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.sendButtons({
id: USER_ID,
text: 'What do you want to do next?',
buttons: botly.createPostbackButton('Continue', 'continue'),
}, function (err, data) {
});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'message': {
'attachment': {
'payload': {
'buttons': [
{
'payload': 'continue',
'title': 'Continue',
'type': 'postback'
}
],
'template_type': 'button',
'text': 'What do you want to do next?'
},
'type': 'template'
}
},
'messaging_type': 'RESPONSE',
'notification_type': 'NO_PUSH',
'recipient': {
'id': '333'
}
});
});
it('should send generic messages', () => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var element = {
title: 'What do you want to do next?',
item_url: 'https://upload.wikimedia.org/wikipedia/en/9/93/Tanooki_Mario.jpg',
image_url: 'https://upload.wikimedia.org/wikipedia/en/9/93/Tanooki_Mario.jpg',
subtitle: 'Choose now!',
buttons: [botly.createWebURLButton('Go to Askrround', 'http://askrround.com'), botly.createAccountLinkButton('http://askrround.com/login'), botly.createShareButton()]
};
botly.sendGeneric({id: USER_ID, elements: element, aspectRatio: Botly.CONST.IMAGE_ASPECT_RATIO.HORIZONTAL});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'message': {
'attachment': {
'payload': {
'elements': [
{
'buttons': [
{
'title': 'Go to Askrround',
'type': 'web_url',
'url': 'http://askrround.com'
},
{
'type': 'account_link',
'url': 'http://askrround.com/login'
},
{
'type': 'element_share'
}
],
'image_url': 'https://upload.wikimedia.org/wikipedia/en/9/93/Tanooki_Mario.jpg',
'item_url': 'https://upload.wikimedia.org/wikipedia/en/9/93/Tanooki_Mario.jpg',
'subtitle': 'Choose now!',
'title': 'What do you want to do next?'
}
],
'image_aspect_ratio': 'horizontal',
'template_type': 'generic'
},
'type': 'template'
}
},
'messaging_type': 'RESPONSE',
'notification_type': 'NO_PUSH',
'recipient': {
'id': '333'
}
});
});
it('should send list template', () => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var element = botly.createListElement({
title: "Classic T-Shirt Collection",
image_url: "https://peterssendreceiveapp.ngrok.io/img/collection.png",
subtitle: "See all our colors",
buttons: [ //Just to test coverage - you should not send more than one button in a list element
{title: "Go to Askrround", url: "http://askrround.com"},
{title: "DO WORK", payload: "DO_WORK"},
{type: "element_share"}
],
default_action: {
"url": "https://peterssendreceiveapp.ngrok.io/shop_collection",
}
});
botly.sendList({
id: USER_ID,
elements: element,
buttons: botly.createPostbackButton("Continue", "continue"),
top_element_style: Botly.CONST.TOP_ELEMENT_STYLE.LARGE
});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'message': {
'attachment': {
'payload': {
'elements': [
{
'buttons': [
{
'title': 'Go to Askrround',
'type': 'web_url',
'url': 'http://askrround.com'
},
{
'type': 'postback',
'title': 'DO WORK',
'payload': 'DO_WORK'
},
{
'type': 'element_share'
}
],
'default_action': {
'type': 'web_url',
'url': 'https://peterssendreceiveapp.ngrok.io/shop_collection'
},
'image_url': 'https://peterssendreceiveapp.ngrok.io/img/collection.png',
'subtitle': 'See all our colors',
'title': 'Classic T-Shirt Collection'
}
],
'buttons': [
{
'type': 'postback',
'title': 'Continue',
'payload': 'continue'
}
],
"top_element_style": "large",
'template_type': 'list'
},
'type': 'template'
}
},
'messaging_type': 'RESPONSE',
'notification_type': 'NO_PUSH',
'recipient': {
'id': '333'
}
});
});
it('should send webview buttons', () => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var element = {
title: 'What do you want to do next?',
item_url: 'https://upload.wikimedia.org/wikipedia/en/9/93/Tanooki_Mario.jpg',
image_url: 'https://upload.wikimedia.org/wikipedia/en/9/93/Tanooki_Mario.jpg',
subtitle: 'Choose now!',
buttons: [botly.createWebURLButton('Go to Askrround', 'http://askrround.com', Botly.CONST.WEBVIEW_HEIGHT_RATIO.COMPACT, true, 'http://askrround.com')]
};
botly.sendGeneric({id: USER_ID, elements: element});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'message': {
'attachment': {
'payload': {
'elements': [
{
'buttons': [
{
'title': 'Go to Askrround',
'type': 'web_url',
'url': 'http://askrround.com',
'webview_height_ratio': 'compact',
'messenger_extensions': true,
'fallback_url': 'http://askrround.com'
}
],
'image_url': 'https://upload.wikimedia.org/wikipedia/en/9/93/Tanooki_Mario.jpg',
'item_url': 'https://upload.wikimedia.org/wikipedia/en/9/93/Tanooki_Mario.jpg',
'subtitle': 'Choose now!',
'title': 'What do you want to do next?'
}
],
'image_aspect_ratio': 'horizontal',
'template_type': 'generic'
},
'type': 'template'
}
},
'messaging_type': 'RESPONSE',
'notification_type': 'NO_PUSH',
'recipient': {
'id': '333'
}
});
});
it('should send webview buttons when passing object', () => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var element = {
title: 'What do you want to do next?',
item_url: 'https://upload.wikimedia.org/wikipedia/en/9/93/Tanooki_Mario.jpg',
image_url: 'https://upload.wikimedia.org/wikipedia/en/9/93/Tanooki_Mario.jpg',
subtitle: 'Choose now!',
buttons: [botly.createWebURLButton({
title: 'Go to Askrround',
url: 'http://askrround.com',
heightRatio: Botly.CONST.WEBVIEW_HEIGHT_RATIO.COMPACT,
supportExtension: true,
fallbackURL: 'http://askrround.com'
})]
};
botly.sendGeneric({id: USER_ID, elements: element, aspectRatio: Botly.CONST.IMAGE_ASPECT_RATIO.SQUARE});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'message': {
'attachment': {
'payload': {
'elements': [
{
'buttons': [
{
'title': 'Go to Askrround',
'type': 'web_url',
'url': 'http://askrround.com',
'webview_height_ratio': 'compact',
'messenger_extensions': true,
'fallback_url': 'http://askrround.com'
}
],
'image_url': 'https://upload.wikimedia.org/wikipedia/en/9/93/Tanooki_Mario.jpg',
'item_url': 'https://upload.wikimedia.org/wikipedia/en/9/93/Tanooki_Mario.jpg',
'subtitle': 'Choose now!',
'title': 'What do you want to do next?'
}
],
'image_aspect_ratio': 'square',
'template_type': 'generic'
},
'type': 'template'
}
},
'messaging_type': 'RESPONSE',
'notification_type': 'NO_PUSH',
'recipient': {
'id': '333'
}
});
});
it('should send receipt messages', () => {
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
var payload = {
'recipient_name': 'Stephane Crozatier',
'order_number': '12345678902',
'currency': 'USD',
'payment_method': 'Visa 2345',
'order_url': 'http://petersapparel.parseapp.com/order?order_id=123456',
'timestamp': '1428444852',
'elements': [
{
'title': 'Classic White T-Shirt',
'subtitle': '100% Soft and Luxurious Cotton',
'quantity': 2,
'price': 50,
'currency': 'USD',
'image_url': 'http://petersapparel.parseapp.com/img/whiteshirt.png'
},
{
'title': 'Classic Gray T-Shirt',
'subtitle': '100% Soft and Luxurious Cotton',
'quantity': 1,
'price': 25,
'currency': 'USD',
'image_url': 'http://petersapparel.parseapp.com/img/grayshirt.png'
}
],
'address': {
'street_1': '1 Hacker Way',
'street_2': '',
'city': 'Menlo Park',
'postal_code': '94025',
'state': 'CA',
'country': 'US'
},
'summary': {
'subtotal': 75.00,
'shipping_cost': 4.95,
'total_tax': 6.19,
'total_cost': 56.14
},
'adjustments': [
{
'name': 'New Customer Discount',
'amount': 20
},
{
'name': '$10 Off Coupon',
'amount': 10
}
]
};
botly.sendReceipt({id: USER_ID, payload: payload, notificationType: Botly.CONST.NOTIFICATION_TYPE.REGULAR});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'message': {
'attachment': {
'payload': {
'address': {
'city': 'Menlo Park',
'country': 'US',
'postal_code': '94025',
'state': 'CA',
'street_1': '1 Hacker Way',
'street_2': ''
},
'adjustments': [
{
'amount': 20,
'name': 'New Customer Discount'
},
{
'amount': 10,
'name': '$10 Off Coupon'
}
],
'currency': 'USD',
'elements': [
{
'currency': 'USD',
'image_url': 'http://petersapparel.parseapp.com/img/whiteshirt.png',
'price': 50,
'quantity': 2,
'subtitle': '100% Soft and Luxurious Cotton',
'title': 'Classic White T-Shirt'
},
{
'currency': 'USD',
'image_url': 'http://petersapparel.parseapp.com/img/grayshirt.png',
'price': 25,
'quantity': 1,
'subtitle': '100% Soft and Luxurious Cotton',
'title': 'Classic Gray T-Shirt'
}
],
'order_number': '12345678902',
'order_url': 'http://petersapparel.parseapp.com/order?order_id=123456',
'payment_method': 'Visa 2345',
'recipient_name': 'Stephane Crozatier',
'summary': {
'shipping_cost': 4.95,
'subtotal': 75,
'total_cost': 56.14,
'total_tax': 6.19
},
'template_type': 'receipt',
'timestamp': '1428444852'
},
'type': 'template'
}
},
'messaging_type': 'RESPONSE',
'notification_type': 'REGULAR',
'recipient': {
'id': '333'
}
});
});
it('should get user profile with default fields', done => {
request.get.yields(
{
first_name: 'miki'
}
);
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.getUserProfile(USER_ID, (data) => {
expect(request.get.calledOnce).to.be.true;
expect(data).to.eql({
first_name: 'miki'
});
const expectedFields = [
Botly.CONST.USER_PROFILE_FIELD.FIRST_NAME,
Botly.CONST.USER_PROFILE_FIELD.LAST_NAME,
Botly.CONST.USER_PROFILE_FIELD.PROFILE_PIC
].join(',');
const actualFields = request.get.getCall(0).args[0].qs.fields;
expect(expectedFields).to.equal(actualFields);
done();
});
});
it('should get user profile with object and specified fields', done => {
request.get.yields(
{
first_name: 'miki'
}
);
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
const options = {
id: USER_ID,
fields: [
Botly.CONST.USER_PROFILE_FIELD.FIRST_NAME,
Botly.CONST.USER_PROFILE_FIELD.PROFILE_PIC
]
};
botly.getUserProfile(options, (data) => {
expect(request.get.calledOnce).to.be.true;
expect(data).to.eql({
first_name: 'miki'
});
const expectedFields = options.fields.join(',');
const actualFields = request.get.getCall(0).args[0].qs.fields;
expect(actualFields).to.equal(expectedFields);
done();
});
});
it('should get page scoped id', done => {
request.get.yields(
{
"id": "111",
"recipient": "222"
}
);
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.getPSID('333', (data) => {
expect(request.get.calledOnce).to.be.true;
expect(data).to.eql({
"id": "111",
"recipient": "222"
});
done();
});
});
it('should get page scoped id with an object', done => {
request.get.yields(
{
"id": "111",
"recipient": "222"
}
);
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.getPSID({token: '333', accessToken: '7777'}, (data) => {
expect(request.get.calledOnce).to.be.true;
expect(data).to.eql({
"id": "111",
"recipient": "222"
});
done();
});
});
it('should set welcome screen', () => {
request.post.yields(null, {});
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.setGetStarted({pageId: PAGE_ID, payload: 'GET_STARTED_CLICKED'}, () => {
});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'get_started': {
'payload': 'GET_STARTED_CLICKED'
}
});
});
it('should set greeting text', () => {
request.post.yields(null, {});
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.setGreetingText({pageId: PAGE_ID, greeting: [
{
"locale":"default",
"text":"Hello!"
}, {
"locale":"en_US",
"text":"Timeless apparel for the masses."
}
]}, () => {
});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'greeting': [
{
"locale":"default",
"text":"Hello!"
}, {
"locale":"en_US",
"text":"Timeless apparel for the masses."
}
]
});
});
it('should setwhitelist', () => {
request.post.yields(null, {});
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.setWhiteList({whiteList: ["https://askhaley.com"]}, () => {
});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'whitelisted_domains': ["https://askhaley.com"]
});
});
it('should set target audience', () => {
request.post.yields(null, {});
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.setTargetAudience({audience: {
"audience_type":"custom",
"countries":{
"whitelist":["US", "CA"]
}
}}, () => {
});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'target_audience': {
"audience_type":"custom",
"countries":{
"whitelist":["US", "CA"]
}
}
});
});
it('should set persistent menu', () => {
request.post.yields(null, {});
var botly = new Botly({
accessToken: 'myToken',
verifyToken: 'myVerifyToken',
webHookPath: '/webhook',
notificationType: Botly.CONST.NOTIFICATION_TYPE.NO_PUSH
});
botly.setPersistentMenu({
pageId: PAGE_ID, menu: [
{
"locale": "default",
"composer_input_disabled": true,
"call_to_actions": [
{
"title": "My Account",
"type": "nested",
"call_to_actions": [
{
"title": "Pay Bill",
"type": "postback",
"payload": "PAYBILL_PAYLOAD"
},
{
"title": "History",
"type": "postback",
"payload": "HISTORY_PAYLOAD"
},
{
"title": "Contact Info",
"type": "postback",
"payload": "CONTACT_INFO_PAYLOAD"
}
]
},
{
"type": "web_url",
"title": "Latest News",
"url": "http://petershats.parseapp.com/hat-news",
"webview_height_ratio": "full"
}
]
},
{
"locale": "zh_CN",
"composer_input_disabled": false
}
]
}, () => {
});
expect(request.post.calledOnce).to.be.true;
expect(request.post.args[0][0].body).to.eql({
'persistent_menu': [
{
"locale": "default",
"composer_input_disabled": true,
"call_to_actions": [
{
"title": "My Account",
"type": "nested",
"call_to_actions": [
{
"title": "Pay Bill",
"type": "postback",
"payload": "PAYBILL_PAYLOAD"
},
{
"title": "History",
"type": "postback",
"payload": "HISTORY_PAYLOAD"
},
{
"title": "Contact Info",
"type": "postback",
"payload": "CONTACT_INFO_PAYLOAD"
}
]
},
{
"type": "web_url",
"title": "Latest News",
"url": "http://petershats.parseapp.com/hat-news",
"webview_height_ratio": "full"
}
]
},
{
"locale": "zh_CN",
"composer_input_disabled": false
}
]
});
});
});