Skip to content

Commit

Permalink
feat: postback fexible
Browse files Browse the repository at this point in the history
### BREAKING CHANGES

dialog and entities became dialogData in postback-message and postback 
the dialogData structure is : dialogData : { name: dialog, data: { messageEntities: entities}}
  • Loading branch information
Benjamin Heinen committed Jul 23, 2018
1 parent 7e14821 commit 16293b2
Show file tree
Hide file tree
Showing 13 changed files with 56 additions and 93 deletions.
4 changes: 2 additions & 2 deletions packages/botfuel-dialog/src/bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,9 @@ class Bot {
async respondWhenPostback(userMessage: PostbackMessage): Promise<BotMessageJson[]> {
logger.debug('respondWhenPostback', userMessage);
const dialog = {
name: userMessage.payload.value.dialog,
name: userMessage.payload.value.name,
data: {
messageEntities: userMessage.payload.value.entities,
messageEntities: userMessage.payload.value.data.messageEntities,
},
};
const botMessages = await this.dm.executeDialog(userMessage, dialog);
Expand Down
2 changes: 1 addition & 1 deletion packages/botfuel-dialog/src/dialog-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,8 @@ class DialogManager extends Resolver<Dialog> {
});
} else {
const dialogInstance: Dialog = this.resolve(dialog.name);

// See https://github.com/facebook/flow/issues/5294

const executeResult: ExecuteResult = await dialogInstance.execute(
userMessage,
dialog.data,
Expand Down
15 changes: 9 additions & 6 deletions packages/botfuel-dialog/src/messages/postback-message.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
* limitations under the License.
*/

// @flow

import type { DialogData } from './../types';

const Message = require('./message');

/**
Expand All @@ -23,20 +27,19 @@ const Message = require('./message');
class PostbackMessage extends Message {
/**
* @constructor
* @param {String} dialog - the postback dialog name
* @param {Object[]} entities - the dialog entities
* @param {DialogData} dialogData - the postback dialog information
* @param {Object} [options] - the message options
*/
constructor(dialog, entities, options) {
super('postback', 'user', { dialog, entities }, options);
constructor(dialogData: DialogData, options?: Object) {
super('postback', 'user', dialogData, options);
this.validate();
}

/** @inheritDoc */
validate() {
super.validate();
this.validateString(this.type, this.value.dialog);
this.validateArray(this.type, this.value.entities);
this.validateString(this.type, this.value.name);
this.validateArray(this.type, this.value.data.messageEntities);
}
}

Expand Down
15 changes: 9 additions & 6 deletions packages/botfuel-dialog/src/messages/postback.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
* limitations under the License.
*/

// @flow

import type { DialogData } from './../types';

const Action = require('./action');

/**
Expand All @@ -24,18 +28,17 @@ class Postback extends Action {
/**
* @constructor
* @param {String} text - the postback text
* @param {String} dialog - the postback dialog name
* @param {Object[]} entities - the dialog entities
* @param {DialogData} dialogData - the postback dialog information, like name or entities
*/
constructor(text, dialog, entities) {
super('postback', text, { dialog, entities });
constructor(text: string, dialogData: DialogData) {
super('postback', text, dialogData);
}

/** @inheritDoc */
validate() {
super.validate();
this.validateString(this.type, this.value.dialog);
this.validateArray(this.type, this.value.entities);
this.validateString(this.type, this.value.name);
this.validateArray(this.type, this.value.data.messageEntities);
}
}

Expand Down
5 changes: 1 addition & 4 deletions packages/botfuel-dialog/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@ export type PostbackMessage = {
type: 'postback',
user: string,
payload: {
value: {
dialog: string,
entities: MessageEntities,
},
value: DialogData,
},
id?: string,
timestamp?: number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ class ClassificationDisambiguationView extends View {
/** @inheritDoc */
render(userMessage, { classificationResults, messageEntities }) {
logger.debug('render', userMessage, { classificationResults, messageEntities });

const postbacks = classificationResults.map((cr) => {
const resolvePrompt = cr.resolvePrompt || `[${cr.label.toUpperCase()}]`;

if (cr.isQnA()) {
return new Postback(resolvePrompt, cr.name, cr.answers);
const postback = new Postback(resolvePrompt,
{ name: cr.name, data: { messageEntities: cr.answers } });
return postback;
}
return new Postback(resolvePrompt, cr.name, messageEntities);
return new Postback(resolvePrompt,
{ name: cr.name, data: { messageEntities } });
});

const options = {
Expand Down
13 changes: 9 additions & 4 deletions packages/botfuel-dialog/tests/messages/cards-message.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ describe('CardsMessage', () => {
const message = new CardsMessage([
new Card('Card 1', 'https://image1.jpg', [
new Link('Details', 'https://image1'),
new Postback('Buy', 'products', [{ dim: 'product', value: '1' }]),
new Postback('Buy', { name: 'products', data: { messageEntities: [{ dim: 'product', value: '1' }] } }),
]),
new Card('Card 2', 'https://image2.jpg', [
new Link('Details', 'https://image2'),
new Postback('Buy', 'products', [{ dim: 'product', value: '2' }]),
new Postback('Buy', { name: 'products', data: { messageEntities: [{ dim: 'product', value: '2' }] } }),
]),
]);
expect(message.toJson('USER')).toEqual({
Expand All @@ -57,7 +57,12 @@ describe('CardsMessage', () => {
{
text: 'Buy',
type: 'postback',
value: { dialog: 'products', entities: [{ dim: 'product', value: '1' }] },
value: {
name: 'products',
data: {
messageEntities: [{ dim: 'product', value: '1' }],
},
},
},
],
image_url: 'https://image1.jpg',
Expand All @@ -73,7 +78,7 @@ describe('CardsMessage', () => {
{
text: 'Buy',
type: 'postback',
value: { dialog: 'products', entities: [{ dim: 'product', value: '2' }] },
value: { name: 'products', data: { messageEntities: [{ dim: 'product', value: '2' }] } },
},
],
image_url: 'https://image2.jpg',
Expand Down
13 changes: 8 additions & 5 deletions packages/botfuel-dialog/tests/messages/postback-message.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,26 @@ const MessageError = require('../../src/errors/message-error');

describe('PostbackMessage', () => {
test('should throw an exception dialog name is not a string', async () => {
expect(() => new PostbackMessage(123, [])).toThrow(MessageError);
expect(() => new PostbackMessage({ name: 123, data: { messageEntities: [] } }))
.toThrow(MessageError);
});

test('should throw an exception when entities are not an array', async () => {
expect(() => new PostbackMessage('greetings', 'hello')).toThrow(MessageError);
expect(() => new PostbackMessage({ name: 'greetings', data: { messageEntities: 'hello' } })).toThrow(MessageError);
});

test('should generate the proper json', async () => {
const message = new PostbackMessage('greetings', []);
const message = new PostbackMessage({ name: 'greetings', data: { messageEntities: [] } });
expect(message.toJson('USER')).toEqual({
type: 'postback',
sender: 'user',
user: 'USER',
payload: {
value: {
dialog: 'greetings',
entities: [],
name: 'greetings',
data: {
messageEntities: [],
},
},
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ describe('ClassificationDisambiguationView', () => {
view.render({ user: 'TEST_USER' }, { classificationResults, messageEntities: [] }),
).toEqual([
new ActionsMessage([
new Postback('You want trip information?', 'trip', []),
new Postback('You want delivery information?', 'qnas', [
[{ value: 'Here is your delivery information' }],
]),
new Postback('You want trip information?', { name: 'trip', data: { messageEntities: [] } }),
new Postback('You want delivery information?', { name: 'qnas',
data: { messageEntities: [
[{ value: 'Here is your delivery information' }]] } }),
], option),
]);
});
Expand Down
4 changes: 2 additions & 2 deletions packages/botfuel-dialog/tests/views/qnas-view.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ describe('QnasView', () => {
},
],
];
await bot.play([new PostbackMessage('qnas', answers)]);
await bot.play([new PostbackMessage({ name: 'qnas', data: { messageEntities: answers } })]);

expect(bot.adapter.log).toEqual(
[new PostbackMessage('qnas', answers), new BotTextMessage('answer')].map(msg =>
[new PostbackMessage({ name: 'qnas', data: { messageEntities: answers } }), new BotTextMessage('answer')].map(msg =>
msg.toJson('USER_TEST')),
);
});
Expand Down
2 changes: 1 addition & 1 deletion packages/test-ecommerce/src/views/products-view.en.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const PRODUCTS = require('../../PRODUCTS.json');
const productToCard = (key, product) =>
new Card(product.title, WebAdapter.getStaticUrl(product.imageUrl), [
new Link('Details', product.link),
new Postback('Buy', 'products', [{ dim: 'product', values: [key] }]),
new Postback('Buy', { name: 'products', data: { messageEntities: [{ dim: 'product', values: [key] }] } }),
]);

class ProductsView extends PromptView {
Expand Down
10 changes: 5 additions & 5 deletions packages/test-ecommerce/tests/products.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('Products', () => {
const { userId } = adapter;
await bot.play([
new UserTextMessage('Show me the products.'),
new PostbackMessage('products', [{ dim: 'product', values: ['top hat'] }]),
new PostbackMessage({ name: 'products', data: { messageEntities: [{ dim: 'product', values: ['top hat'] }] } }),
]);
expect(bot.adapter.log[0]).toEqual(new UserTextMessage('Show me the products.').toJson(userId));
expect(bot.adapter.log[1]).toEqual(
Expand All @@ -46,26 +46,26 @@ describe('Products', () => {
new CardsMessage([
new Card('Top hat', WebAdapter.getStaticUrl('images/tophat.jpg'), [
new Link('Details', 'https://www.amazon.com/Beistle-Satin-Sleek-Top-Hat/dp/B0051BH6IM'),
new Postback('Buy', 'products', [{ dim: 'product', values: ['top hat'] }]),
new Postback('Buy', { name: 'products', data: { messageEntities: [{ dim: 'product', values: ['top hat'] }] } }),
]),
new Card('Cowboy hat', WebAdapter.getStaticUrl('images/cowboyhat.jpg'), [
new Link(
'Details',
'https://www.amazon.co.uk/Leather-Australian-Cowboy-Aussie-brown/dp/B0094J2H0O',
),
new Postback('Buy', 'products', [{ dim: 'product', values: ['cowboy hat'] }]),
new Postback('Buy', { name: 'products', data: { messageEntities: [{ dim: 'product', values: ['cowboy hat'] }] } }),
]),
new Card('Detective hat', WebAdapter.getStaticUrl('images/detectivehat.jpg'), [
new Link(
'Details',
'https://www.amazon.com/Unisex-Sherlock-Holmes-Detective-Deerstalker/dp/B016A3J3N0',
),
new Postback('Buy', 'products', [{ dim: 'product', values: ['detective hat'] }]),
new Postback('Buy', { name: 'products', data: { messageEntities: [{ dim: 'product', values: ['detective hat'] }] } }),
]),
]).toJson(userId),
);
expect(bot.adapter.log[3]).toEqual(
new PostbackMessage('products', [{ dim: 'product', values: ['top hat'] }]).toJson(userId),
new PostbackMessage({ name: 'products', data: { messageEntities: [{ dim: 'product', values: ['top hat'] }] } }).toJson(userId),
);
expect(bot.adapter.log[4]).toEqual(
new BotImageMessage(
Expand Down
49 changes: 0 additions & 49 deletions packages/test-qna/tests/qna.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@

const {
Bot,
// ActionsMessage,
BotTextMessage,
// Postback,
UserTextMessage,
} = require('botfuel-dialog');
const config = require('../test-config');
Expand Down Expand Up @@ -47,53 +45,6 @@ describe('Qna', () => {
expect(dialogs.previous[0].name).toBe('default');
});

/**
test('should respond with many qnas when question not fully understood', async () => {
const bot = new Bot(config);
const userId = bot.adapter.userId;
await bot.play([new UserTextMessage('get an')]);
expect(bot.adapter.log).toEqual(
[
new UserTextMessage('get an invoice'),
new BotTextMessage('What do you mean?'),
new ActionsMessage([
new Postback('Will I get an invoice?', 'qnas', [
{
dim: 'qnas',
value: [
{
answer:
'The invoice for your purchase will be sent along with your goods.
You can also download an electronic version from your account.',
},
],
},
]),
new Postback('Can I get an invoice ?', 'qnas', [
{
dim: 'qnas',
value: [
{
answer:
'Of curse! The invoice for your purchase will be sent along with your goods.
You can also download an electronic version from your account.',
},
],
},
]),
]),
].map(msg => msg.toJson(userId)),
);
const user = await bot.brain.getUser(userId);
const dialogs = await bot.brain.getDialogs(userId);
expect(user.userId).toBe(userId);
expect(user.conversations.length).toBe(1);
expect(dialogs.stack.length).toBe(1);
expect(dialogs.stack[0].name).toBe('qnas');
expect(dialogs.previous).toHaveLength(0);
});
*/

test('should respond to help request', async () => {
const bot = new Bot(config);
const { adapter } = bot;
Expand Down

0 comments on commit 16293b2

Please sign in to comment.