Skip to content

Commit

Permalink
Merge b85b9d3 into 56409dd
Browse files Browse the repository at this point in the history
  • Loading branch information
omenocal committed Sep 26, 2018
2 parents 56409dd + b85b9d3 commit 816c043
Show file tree
Hide file tree
Showing 5 changed files with 645 additions and 127 deletions.
20 changes: 12 additions & 8 deletions lib/Voxa-Chatbase.js
Expand Up @@ -4,15 +4,17 @@ const _ = require('lodash');
const Chatbase = require('@google/chatbase');
const lambdaLog = require('lambda-log');

let defaultConfig = {
const pluginConfig = {
ignoreUsers: [],
platform: 'Alexa',
};

let defaultConfig;

module.exports = register;

function register(skill, config) {
defaultConfig = _.merge({}, defaultConfig, config);
defaultConfig = _.merge({}, pluginConfig, config);

skill.onBeforeReplySent(track);

Expand Down Expand Up @@ -51,15 +53,15 @@ async function track(request, reply, transition, isSessionEndedRequest) {
}

function createUserMessage(messageSet, request) {
const unhandledIntents = ['AMAZON.FallbackIntent', 'Unhandled', 'DefaultFallbackIntent'];
const unhandledIntents = ['FallbackIntent', 'Unhandled', 'DefaultFallbackIntent'];
const intentName = request.intent.name || request.request.type;
const slots = {};
const params = {};

_.each(request.intent.slots, (x) => {
slots[x.name] = x.value;
_.each(request.intent.params, (x) => {
params[x.name] = x.value;
});

const userMessage = request.intent.slots ? JSON.stringify(slots) : '';
const userMessage = request.intent.params ? JSON.stringify(params) : '';

const newMessage = createMessage(messageSet, request);

Expand All @@ -74,7 +76,9 @@ function createUserMessage(messageSet, request) {
}

function createBotMessage(messageSet, request, reply) {
const appMessage = reply.msg.statements.join(' ');
let appMessage = _.get(reply, 'response.outputSpeech.ssml', '');
appMessage = appMessage || _.get(reply, 'response.outputSpeech.text', '');
appMessage = appMessage.replace('<speak>', '').replace('</speak>', '');

const newMessage = createMessage(messageSet, request);

Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -45,7 +45,7 @@
"mocha-jenkins-reporter": "^0.4.0",
"nock": "^10.0.0",
"simple-mock": "^0.8.0",
"voxa": "^2.5.0"
"voxa": "3.0.0-alpha30"
},
"bugs": {
"url": "https://github.com/mediarain/voxa-chatbase/issues"
Expand Down
26 changes: 15 additions & 11 deletions tests/views.js
Expand Up @@ -9,17 +9,21 @@

const views = (function views() {
return {
LaunchIntent: {
OpenResponse: { tell: 'Hello! How are you?' },
},
Question: {
Ask: { ask: 'What time is it?' },
},
ExitIntent: {
GeneralExit: { tell: 'Ok. Goodbye.' },
},
BadInput: {
RepeatLastAskReprompt: { say: 'I\'m sorry. I didn\'t understand.' },
en: {
translation: {
LaunchIntent: {
OpenResponse: 'Hello! How are you?',
},
Question: {
Ask: { ask: 'What time is it?' },
},
ExitIntent: {
GeneralExit: 'Ok. Goodbye.',
},
BadInput: {
RepeatLastAskReprompt: { say: 'I\'m sorry. I didn\'t understand.' },
},
},
},
};
}());
Expand Down
174 changes: 88 additions & 86 deletions tests/voxa-chatbase.spec.js
Expand Up @@ -3,7 +3,7 @@
const _ = require('lodash');
const simple = require('simple-mock');
const nock = require('nock');
const Voxa = require('voxa');
const voxa = require('voxa');
const { expect } = require('chai');

const voxaChatbase = require('../lib/Voxa-Chatbase');
Expand All @@ -14,11 +14,13 @@ const chatbaseConfig = {
apiKey: 'some_api_key',
};

let voxaStateMachine;
let app;
let alexaSkill;

describe('Voxa-Chatbase plugin', () => {
beforeEach(() => {
voxaStateMachine = new Voxa({ views });
app = new voxa.VoxaApp({ views });
alexaSkill = new voxa.AlexaPlatform(app);

const response = {
all_succeeded: true,
Expand All @@ -35,9 +37,9 @@ describe('Voxa-Chatbase plugin', () => {
nock.cleanAll();
});

it('should register ChatbaseAnalytics on LaunchRequest', () => {
const spy = simple.spy(() => ({ reply: 'LaunchIntent.OpenResponse', to: 'entry' }));
voxaStateMachine.onIntent('LaunchIntent', spy);
it('should register ChatbaseAnalytics on LaunchRequest', async () => {
const spy = simple.spy(() => ({ ask: 'LaunchIntent.OpenResponse', to: 'entry' }));
alexaSkill.onIntent('LaunchIntent', spy);

const event = {
request: {
Expand All @@ -55,20 +57,19 @@ describe('Voxa-Chatbase plugin', () => {
},
};

voxaChatbase(voxaStateMachine, chatbaseConfig);
return voxaStateMachine.execute(event)
.then((reply) => {
expect(spy.called).to.be.true;
expect(reply.session.new).to.equal(true);
expect(reply.session.attributes.state).to.equal('entry');
expect(reply.msg.statements).to.have.lengthOf(1);
expect(reply.msg.statements[0]).to.equal('Hello! How are you?');
});
voxaChatbase(app, chatbaseConfig);

const reply = await alexaSkill.execute(event);

expect(spy.called).to.be.true;
expect(reply.response.outputSpeech.ssml).to.contains('Hello! How are you?');
expect(reply.response.shouldEndSession).to.equal(false);
expect(reply.sessionAttributes.state).to.equal('entry');
});

it('should register ChatbaseAnalytics on IntentRequest', () => {
const spy = simple.spy(() => ({ reply: 'Question.Ask', to: 'entry' }));
voxaStateMachine.onIntent('SomeIntent', spy);
it('should register ChatbaseAnalytics on IntentRequest', async () => {
const spy = simple.spy(() => ({ ask: 'Question.Ask', to: 'entry' }));
alexaSkill.onIntent('SomeIntent', spy);

const event = {
request: {
Expand All @@ -94,20 +95,19 @@ describe('Voxa-Chatbase plugin', () => {
},
};

voxaChatbase(voxaStateMachine, chatbaseConfig);
return voxaStateMachine.execute(event)
.then((reply) => {
expect(spy.called).to.be.true;
expect(reply.session.new).to.equal(false);
expect(reply.session.attributes.state).to.equal('entry');
expect(reply.msg.statements).to.have.lengthOf(1);
expect(reply.msg.statements[0]).to.equal('What time is it?');
});
voxaChatbase(app, chatbaseConfig);

const reply = await alexaSkill.execute(event);

expect(spy.called).to.be.true;
expect(reply.response.outputSpeech.ssml).to.contains('What time is it?');
expect(reply.response.shouldEndSession).to.equal(false);
expect(reply.sessionAttributes.state).to.equal('entry');
});

it('should register ChatbaseAnalytics on AMAZON.FallbackIntent and end the session', () => {
const spy = simple.spy(() => ({ reply: 'ExitIntent.GeneralExit' }));
voxaStateMachine.onIntent('AMAZON.FallbackIntent', spy);
it('should register ChatbaseAnalytics on AMAZON.FallbackIntent and end the session', async () => {
const spy = simple.spy(() => ({ tell: 'ExitIntent.GeneralExit' }));
alexaSkill.onIntent('FallbackIntent', spy);

const event = {
request: {
Expand All @@ -127,20 +127,19 @@ describe('Voxa-Chatbase plugin', () => {
},
};

voxaChatbase(voxaStateMachine, chatbaseConfig);
return voxaStateMachine.execute(event)
.then((reply) => {
expect(spy.called).to.be.true;
expect(reply.session.new).to.equal(false);
expect(reply.session.attributes.state).to.equal('die');
expect(reply.msg.statements).to.have.lengthOf(1);
expect(reply.msg.statements[0]).to.equal('Ok. Goodbye.');
});
voxaChatbase(app, chatbaseConfig);

const reply = await alexaSkill.execute(event);

expect(spy.called).to.be.true;
expect(reply.response.outputSpeech.ssml).to.contains('Ok. Goodbye.');
expect(reply.response.shouldEndSession).to.equal(true);
expect(reply.sessionAttributes.state).to.equal('die');
});

it('should register ChatbaseAnalytics on SessionEndedRequest', () => {
const spy = simple.spy(() => ({ reply: 'ExitIntent.GeneralExit' }));
voxaStateMachine.onSessionEnded(spy);
it('should register ChatbaseAnalytics on SessionEndedRequest', async () => {
const spy = simple.spy(() => ({ tell: 'ExitIntent.GeneralExit' }));
app.onSessionEnded(spy);

const event = {
request: {
Expand All @@ -157,22 +156,22 @@ describe('Voxa-Chatbase plugin', () => {
},
};

voxaChatbase(voxaStateMachine, chatbaseConfig);
return voxaStateMachine.execute(event)
.then((reply) => {
expect(spy.called).to.be.true;
expect(reply.version).to.equal('1.0');
});
voxaChatbase(app, chatbaseConfig);

const reply = await alexaSkill.execute(event);

expect(spy.called).to.be.true;
expect(reply.version).to.equal('1.0');
});

it('should register ChatbaseAnalytics on unexpected error', () => {
it('should register ChatbaseAnalytics on unexpected error', async () => {
const intentSpy = simple.spy(() => {
throw new Error('random error');
});
voxaStateMachine.onIntent('ErrorIntent', intentSpy);
alexaSkill.onIntent('ErrorIntent', intentSpy);

const spy = simple.spy(() => ({ reply: 'BadInput.RepeatLastAskReprompt', to: 'invalid-state' }));
voxaStateMachine.onError(spy);
const spy = simple.spy(() => ({ say: 'BadInput.RepeatLastAskReprompt.say', to: 'invalid-state' }));
app.onError(spy);

const event = {
request: {
Expand All @@ -192,19 +191,18 @@ describe('Voxa-Chatbase plugin', () => {
},
};

voxaChatbase(voxaStateMachine, chatbaseConfig);
return voxaStateMachine.execute(event)
.then((reply) => {
expect(spy.called).to.be.true;
expect(reply.reply).to.equal('BadInput.RepeatLastAskReprompt');
expect(reply.to).to.equal('invalid-state');
expect(reply.error.toString()).to.equal('Error: random error');
});
voxaChatbase(app, chatbaseConfig);

const reply = await alexaSkill.execute(event);

expect(spy.called).to.be.true;
expect(reply.say).to.equal('BadInput.RepeatLastAskReprompt.say');
expect(reply.to).to.equal('invalid-state');
});

it('should not record analytics if the user is ignored', () => {
const spy = simple.spy(() => ({ reply: 'ExitIntent.GeneralExit' }));
voxaStateMachine.onSessionEnded(spy);
it('should not record analytics if the user is ignored', async () => {
const spy = simple.spy(() => ({ tell: 'ExitIntent.GeneralExit' }));
app.onSessionEnded(spy);

const event = {
request: {
Expand All @@ -224,20 +222,23 @@ describe('Voxa-Chatbase plugin', () => {
const ignoreUsersConfig = _.cloneDeep(chatbaseConfig);
ignoreUsersConfig.ignoreUsers = ['user-id'];

voxaChatbase(voxaStateMachine, ignoreUsersConfig);
return voxaStateMachine.execute(event)
.then((reply) => {
expect(reply.version).to.equal('1.0');
});
voxaChatbase(app, ignoreUsersConfig);

const reply = await alexaSkill.execute(event);

expect(reply.version).to.equal('1.0');
});

it('should not record analytics if suppressSending === true', () => {
const spy = simple.spy(() => ({ reply: 'ExitIntent.GeneralExit' }));
voxaStateMachine.onSessionEnded(spy);
it('should not record analytics if suppressSending === true', async () => {
const spy = simple.spy(() => ({ tell: 'ExitIntent.GeneralExit' }));
alexaSkill.onIntent('ErrorIntent', spy);

const event = {
request: {
type: 'SessionEndedRequest',
type: 'IntentRequest',
intent: {
name: 'ErrorIntent',
},
},
session: {
new: false,
Expand All @@ -253,17 +254,18 @@ describe('Voxa-Chatbase plugin', () => {
const suppressSendingConfig = _.cloneDeep(chatbaseConfig);
suppressSendingConfig.suppressSending = true;

voxaChatbase(voxaStateMachine, suppressSendingConfig);
return voxaStateMachine.execute(event)
.then((reply) => {
expect(reply.version).to.equal('1.0');
});
voxaChatbase(app, suppressSendingConfig);

const reply = await alexaSkill.execute(event);

expect(reply.version).to.equal('1.0');
});
});

describe('Voxa-Chatbase plugin error: all_succeeded flag is not present', () => {
beforeEach(() => {
voxaStateMachine = new Voxa({ views });
app = new voxa.VoxaApp({ views });
alexaSkill = new voxa.AlexaPlatform(app);

const response = {
status: 200,
Expand All @@ -279,9 +281,9 @@ describe('Voxa-Chatbase plugin error: all_succeeded flag is not present', () =>
nock.cleanAll();
});

it('should not record analytics due to Chatbase Error', () => {
const spy = simple.spy(() => ({ reply: 'ExitIntent.GeneralExit' }));
voxaStateMachine.onSessionEnded(spy);
it('should not record analytics due to Chatbase Error', async () => {
const spy = simple.spy(() => ({ tell: 'ExitIntent.GeneralExit' }));
app.onSessionEnded(spy);

const event = {
request: {
Expand All @@ -298,10 +300,10 @@ describe('Voxa-Chatbase plugin error: all_succeeded flag is not present', () =>
},
};

voxaChatbase(voxaStateMachine, chatbaseConfig);
return voxaStateMachine.execute(event)
.then((reply) => {
expect(reply.version).to.equal('1.0');
});
voxaChatbase(app, chatbaseConfig);

const reply = await alexaSkill.execute(event);

expect(reply.version).to.equal('1.0');
});
});

0 comments on commit 816c043

Please sign in to comment.