From ec9451249c059963a25a9de5cc5e6eac3a090e95 Mon Sep 17 00:00:00 2001 From: Antonio Pintus Date: Thu, 31 Jan 2019 12:10:02 +0100 Subject: [PATCH] feat(util): add methods to create default actions and text quick replies Add new methods in BotMessage utility class to create default actions and quick replies also from arrays of strings --- examples/dummy-bot.js | 18 +--------- examples/dummy-bot.ts | 18 +--------- src/message.ts | 45 ++++++++++++++++++------- test/ts/agent-general.test.ts | 37 +++++++++++++++++++++ test/ts/dummy-bot.ts | 9 ++--- test/ts/message.test.ts | 62 ++++++++++++++++++++++++++++++++++- 6 files changed, 139 insertions(+), 50 deletions(-) diff --git a/examples/dummy-bot.js b/examples/dummy-bot.js index ebf1191..bc611d2 100644 --- a/examples/dummy-bot.js +++ b/examples/dummy-bot.js @@ -42,23 +42,7 @@ manager.registerAgent('custom', async (msg) => { } response.messages = [ index_1.BotMessage.createSimpleTextMessage('Hello! I am a DummyBot from Bot SDK 3.3.0 😎'), - { - code: 'message', - type: 'text', - body: 'To start, choose one of the following options to see what I can do for you ', - quick_replies: [ - { - title: 'fullhelp', - payload: 'fullhelp', - content_type: 'text' - }, - { - title: 'help', - payload: 'help', - content_type: 'text' - } - ] - } + index_1.BotMessage.createTextMessageWithQuickReplies('To start, choose one of the following options to see what I can do for you', ['fullhelp', 'help']) ]; response.data = {}; } diff --git a/examples/dummy-bot.ts b/examples/dummy-bot.ts index 11aed1f..8880a0d 100644 --- a/examples/dummy-bot.ts +++ b/examples/dummy-bot.ts @@ -49,23 +49,7 @@ manager.registerAgent( } response.messages = [ BotMessage.createSimpleTextMessage('Hello! I am a DummyBot from Bot SDK 3.3.0 😎'), - { - code: 'message', - type: 'text', - body: 'To start, choose one of the following options to see what I can do for you ', - quick_replies: [ - { - title: 'fullhelp', - payload: 'fullhelp', - content_type: 'text' - }, - { - title: 'help', - payload: 'help', - content_type: 'text' - } - ] - } as TextMessage + BotMessage.createTextMessageWithQuickReplies('To start, choose one of the following options to see what I can do for you', ['fullhelp', 'help']) ]; response.data = {}; } else if ((msg.message as any).type === 'action') { diff --git a/src/message.ts b/src/message.ts index 2e571f9..3a57b4e 100644 --- a/src/message.ts +++ b/src/message.ts @@ -15,6 +15,10 @@ export interface PostbackButton { title: string; payload: string; } +export interface DefaultAction { + type: 'web_url'; + url: string; +} /** * Utility class exposing static methods to compose common used Vivocha Bot Messages. @@ -34,7 +38,7 @@ export class BotMessage { } as TextMessage; } } - public static createTextMessageWithQuickReplies(body: string, quickReplies: QuickReply[]): TextMessage { + public static createTextMessageWithQuickReplies(body: string, quickReplies: QuickReply[] | string[]): TextMessage { const txtMsg = BotMessage.createSimpleTextMessage(body); txtMsg.quick_replies = BotMessage.createQuickReplies(quickReplies); return txtMsg; @@ -57,23 +61,32 @@ export class BotMessage { } as ActionMessage; } } - public static createQuickReplies(quickReplies: QuickReply[]): MessageQuickReply[] { + public static createQuickReplies(quickReplies: QuickReply[] | string[]): MessageQuickReply[] { if (!quickReplies) { throw new Error('quickReplies param must be valid'); } else { - return quickReplies.map(qr => { - if (!qr.title) { - throw new Error('a quick reply must have at least a title'); - } else { + return (quickReplies as any[]).map(qr => { + if (typeof qr === 'string') { const quickReply: MessageQuickReply = { content_type: 'text', - title: qr.title, - payload: qr.payload || qr.title + title: qr, + payload: qr }; - if (qr.image_url) { - quickReply.image_url = qr.image_url; - } return quickReply; + } else { + if (!qr.title) { + throw new Error('a quick reply must have at least a title'); + } else { + const quickReply: MessageQuickReply = { + content_type: 'text', + title: qr.title, + payload: qr.payload || qr.title + }; + if (qr.image_url) { + quickReply.image_url = qr.image_url; + } + return quickReply; + } } }); } @@ -100,4 +113,14 @@ export class BotMessage { }; } } + public static createDefaultAction(url: string): DefaultAction { + if (!url) { + throw new Error('In a DefaultAction url is required'); + } else { + return { + type: 'web_url', + url + }; + } + } } diff --git a/test/ts/agent-general.test.ts b/test/ts/agent-general.test.ts index c0720d5..be98ffb 100644 --- a/test/ts/agent-general.test.ts +++ b/test/ts/agent-general.test.ts @@ -224,6 +224,39 @@ describe('Testing a generic Bot Agent (Dummy Bot) ', function() { ]); return; }); + it('sending quick3, it should reply with three quick_replies', async function() { + const request1: BotRequest = { + language: 'en', + event: 'continue', + settings: getSettings(), + message: getTextMessage('quick3') + }; + //console.dir(request1, { colors: true, depth: 20 }); + const result1 = await http(getHTTPOptions(request1)); + //console.dir(result1, { colors: true, depth: 20 }); + result1.event.should.equal('continue'); + result1.messages.should.have.lengthOf(1); + result1.messages[0].body.should.contain('Just an example of quick replies... choose a color?'); + result1.messages[0].quick_replies.should.have.lengthOf(3); + result1.messages[0].quick_replies.should.deep.equal([ + { + content_type: 'text', + title: 'red', + payload: 'red' + }, + { + content_type: 'text', + title: 'blue', + payload: 'blue' + }, + { + content_type: 'text', + title: 'white', + payload: 'white' + } + ]); + return; + }); it('sending cat, it should reply with a template', async function() { const request1: BotRequest = { language: 'en', @@ -268,6 +301,10 @@ describe('Testing a generic Bot Agent (Dummy Bot) ', function() { template.elements[0].should.have.property('image_url'); template.elements[0].should.have.property('subtitle'); template.elements[0].should.have.property('default_action'); + template.elements[0].default_action.should.deep.equal({ + type: 'web_url', + url: 'https://en.wikipedia.org/wiki/Cat' + }); template.elements[0].should.have.property('buttons'); const buttons = template.elements[0].buttons; buttons[0].should.deep.equal({ diff --git a/test/ts/dummy-bot.ts b/test/ts/dummy-bot.ts index 8945207..260cfaa 100644 --- a/test/ts/dummy-bot.ts +++ b/test/ts/dummy-bot.ts @@ -172,6 +172,10 @@ dummyBot.registerAgent( ]; response.event = 'continue'; break; + case 'quick3': + response.messages = [BotMessage.createTextMessageWithQuickReplies('Just an example of quick replies... choose a color?', ['red', 'blue', 'white'])]; + response.event = 'continue'; + break; case 'help': response.messages = [ { @@ -340,10 +344,7 @@ dummyBot.registerAgent( 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c0/Tajeschidolls_Beren_of_LoveLorien_Ragdoll_Seal_Mink_Lynx_Bicolor.jpg/1024px-Tajeschidolls_Beren_of_LoveLorien_Ragdoll_Seal_Mink_Lynx_Bicolor.jpg', subtitle: 'We have the right cat for everyone.', - default_action: { - type: 'web_url', - url: 'https://en.wikipedia.org/wiki/Cat' - }, + default_action: BotMessage.createDefaultAction('https://en.wikipedia.org/wiki/Cat'), buttons: [ BotMessage.createWebUrlButton('View Website', 'https://en.wikipedia.org/wiki/Cat'), diff --git a/test/ts/message.test.ts b/test/ts/message.test.ts index f97708d..4f88df0 100644 --- a/test/ts/message.test.ts +++ b/test/ts/message.test.ts @@ -99,7 +99,7 @@ describe('Testing BotMessage creation factory', function() { }.should.throw(Error, /action_code string is required for an ActionMessage/)); }); }); - describe('Calling createQuickReplies()', function() { + describe('Calling createQuickReplies() from an array of QuickReply definitions', function() { it('with an array of two good text-based quick replies and no payload, should return a correct quick reply message array with titles and payloads from titles', function() { const msg = BotMessage.createQuickReplies([ { @@ -235,6 +235,52 @@ describe('Testing BotMessage creation factory', function() { }.should.throw(Error, /a quick reply must have at least a title/)); }); }); + describe('Calling createQuickReplies() from an array of strings', function() { + it('with an array of two good text-based quick replies should return a correct quick reply message array with titles and payloads from titles', function() { + const msg = BotMessage.createQuickReplies(['red', 'blue']); + msg.should.deep.equal([ + { + content_type: 'text', + title: 'red', + payload: 'red' + }, + { + content_type: 'text', + title: 'blue', + payload: 'blue' + } + ]); + }); + it('with an array of three good text-based quick replies should return a correct quick reply message array with titles and payloads', function() { + const msg = BotMessage.createQuickReplies(['red', 'blue', 'white']); + msg.should.deep.equal([ + { + content_type: 'text', + title: 'red', + payload: 'red' + }, + { + content_type: 'text', + title: 'blue', + payload: 'blue' + }, + { + content_type: 'text', + title: 'white', + payload: 'white' + } + ]); + }); + it('with an empty array, it should return an empty array', function() { + const msg = BotMessage.createQuickReplies([]); + msg.should.have.lengthOf(0); + }); + it('with an undefined param, it should throw an error', function() { + (function() { + BotMessage.createQuickReplies(undefined); + }.should.throw(Error, /quickReplies param must be valid/)); + }); + }); describe('Calling createIsWritingMessage', function() { it('it should return a correct TextMessage', function() { const msg = BotMessage.createIsWritingMessage(); @@ -294,4 +340,18 @@ describe('Testing BotMessage creation factory', function() { }.should.throw(Error, /In a PostbackButton, title and payload are required/)); }); }); + describe('Calling createDefaultAction()', function() { + it('with valid url should return a DefaultAction', function() { + const btn = BotMessage.createDefaultAction('https://www.vivocha.com'); + btn.should.deep.equal({ + type: 'web_url', + url: 'https://www.vivocha.com' + }); + }); + it('with missing params, it should throw an error', function() { + (function() { + BotMessage.createDefaultAction(undefined); + }.should.throw(Error, /In a DefaultAction url is required/)); + }); + }); });