对于我的高级项目,我正在AWS Lex上实现一个聊天机器人。我已经使用这个确切的代码在AWS控制台中测试了机器人,并且没有任何错误或问题。但是,当我在Node.js中的机器上(而不是在AWS控制台上)编写代码时,我正在尝试通过单元测试运行npm run test
或npm test
,但我收到以下错误:
FulfillmentCodeHook with no slots
✕ Customer asks, 'how can I setup' (12ms)
● FulfillmentCodeHook with no slots › Customer asks, 'how can I setup'
TypeError: callback is not a function
62 | var fulfillmentResult = fulfillSetup(processType);
63 |
> 64 | callback(lexResponses.close(
65 | intentRequest.sessionAttributes,
66 | fulfillmentResult.fulfillmentState,
67 | fulfillmentResult.message
at Object.<anonymous>.module.exports (Chatbot_Processor/SetupProcess_Intent/manageFulfillment.js:64:5)
at Object.<anonymous>.module.exports (Chatbot_Processor/SetupProcess_Intent/setupProcess.js:29:16)
at Object.<anonymous> (Tests/setupProcess.spec.js:32:22)
&#13;
以下是相关的代码段,从handler.js
开始,因为这是运行bot时首先调用的文件。
P.S。 constant-vars.js
是一个包含所有常量变量列表的文件。我没有把它包括在内。
handler.js
'use strict';
const constants = require('./constant-vars');
const dispatch = require('./dispatch');
const assert = require('assert');
exports.handler = (event, context, callback) => {
try {
dispatch(event, (response) => {callback(null, response)});
} catch (err) {
callback(err);
}
};
&#13;
dispatch.js
'use strict';
const constants = require('./constant-vars');
const setupProcess = require('./SetupProcess_Intent/setupProcess');
module.exports = function(intentRequest, callback) {
const intentName = intentRequest.currentIntent.name;
// SetupProcess intent
if(intentName === constants.SETUP_PROCESS_INTENT) {
console.log(`${constants.INTENT_TAG} ${intentName}`);
return setupProcess(intentRequest, callback);
}
}
&#13;
setupProcess.js
'use strict';
const constants = require('../constant-vars');
const handleDialogCodeHook = require('./manageDialogs');
const handleFulfillmentCodeHook = require('./manageFulfillment');
const lexResponses = require('../lexResponses');
module.exports = function(intentRequest, callback) {
// source of lambda invokation
const source = intentRequest.invocationSource;
// source of lambda invokation is Dialog Code Hook
if(source === constants.DIALOG_CODE_HOOK) {
return handleDialogCodeHook(intentRequest, callback);
}
// source of lambda invokation of Fulfillment Code Hook
if(source === constants.FULFILL_CODE_HOOK) {
return handleFulfillmentCodeHook(intentRequest, false, callback);
}
}
&#13;
manageFulfillment.js
'use strict';
const constants = require('../constant-vars');
const lexResponses = require('../lexResponses');
/**
* builds object for fulfilling SetupProcess intent
*/
function buildFulfillmentResult(fulfillmentState, messageContent) {
return {
fulfillmentState,
message: {
contentType: 'PlainText',
content: messageContent
}
};
}
/**
* fulfills SetupProcess intent
*/
function fulfillSetup(processType) {
if(processType === `${constants.AUTO_PAY_SLOT} or ${constants.PAPERLESS_SLOT}`) {
return buildFulfillmentResult(
constants.FULFILLED_STATUS,
constants.SETUP_BOT_RESPONSE.replace('{0}', constants.PROCESSES_LIKE).replace('{1}', processType).replace('{2}', constants.COMPANY_MONTEREY_NUM)
);
}
return buildFulfillmentResult(
constants.FULFILLED_STATUS,
constants.SETUP_BOT_RESPONSE.replace('{0}', "").replace('{1}', processType).replace('{2}', constants.COMPANY_MONTEREY_NUM)
);
}
/**
* handleFulfillmentCodeHook(intentRequest)
*/
module.exports = function(intentRequest, redirectedFromDialogs = false, callback) {
// this call to handleFulfillmentCodeHook did not come from the handler for dialog code hook
if(!redirectedFromDialogs) {
var processType = intentRequest.currentIntent.slots.processType;
console.log(`${constants.PROCESS_TYPE_VAL} ${processType}`);
var fulfillmentResult = fulfillSetup(processType);
callback(lexResponses.close(
intentRequest.sessionAttributes,
fulfillmentResult.fulfillmentState,
fulfillmentResult.message
)
);
}
// this call to handleFulfillmentCodeHook came from the handler for dialog code hook,
// meaning the user did not specify a slot type
else {
var processType = `${constants.AUTO_PAY_SLOT} or ${constants.PAPERLESS_SLOT}`;
var message = constants.SETUP_BOT_RESPONSE.replace('{0}', constants.PROCESSES_LIKE).replace('{1}', processType).replace('{2}', constants.COMPANY_MONTEREY_NUM);
var fulfillmentResult = buildFulfillmentResult(constants.FULFILLED_STATUS, message);
callback(lexResponses.close(
intentRequest.sessionAttributes,
fulfillmentResult.fulfillmentState,
fulfillmentResult.message
)
);
}
}
&#13;
lexResponses.js
'use strict';
const constants = require('./constant-vars.js');
/**
* Delegate
* Directs Amazon Lex to choose the next course of action based on the bot configuration.
*/
module.exports.delegate = function(sessionAttributes, slots) {
return {
sessionAttributes,
dialogAction: {
type: 'Delegate',
slots,
},
};
}
/**
* ElicitSlot
* Informs Amazon Lex that the user is expected to provide a slot value in the response.
*/
module.exports.elicitSlot = function(sessionAttributes, intentName, slots, slotToElicit, message) {
return {
sessionAttributes,
dialogAction: {
type: 'ElicitSlot',
intentName,
slots,
slotToElicit,
message
}
};
};
/**
* Close
* Close dialog with the customer, reporting fulfillmentState of Failed or Fulfilled
*/
module.exports.close = function(sessionAttributes, fulfillmentState, message) {
return {
sessionAttributes,
dialogAction: {
type: 'Close',
fulfillmentState,
message,
},
};
}
&#13;