Skip to content

Developing Custom Logic Hooks

With some Javascript development know-how, you can extend Botium with your own logic hooks.

Logic Hooks

There are currently nine types of logic hook events where you can add your custom logic:

  • onConvoBegin: before a convo begins
  • Conversation step, me section:
    • onMeBegin: before a me message is sent.
    • onMeEnd: after a me message is sent
    • onMe: same as onMeBegin/onMeEnd, but the position (executed before, or after) depends on the order in the script. Use this instead of onMeBegin/onMeEnd if it has sense to execute a logichook before, and after sending the me message, like Pause Logic Hook
  • Conversation step, bot section:
    • onBotBegin: before a bot message received
    • onBotPrepare: after a bot message received but before assertions are done
    • onBotEnd: after a bot message received
    • onBot: same as onBegin/onMeEnd, but the position (executed before, or after) depends on the order in the script. Use this instead of onMeBegin/onMeEnd if it has sense to execute a logichook before, and after asserting the bot response, like Pause Logic Hook
  • onConvoEnd: after convo ends

The logic hooks are implemented as Javascript functions. Implementation of the hooks is optional, you just have to implement the hooks required by your logic.

Note

When adding a global logic hook to Botium Box (Register as global scripting component), the logic hooks will be called on every convo and every convo step.

Note

Please keep in mind, that the logic hooks are blocking the test.

Some tips for better performance:

  • Put your time consuming initialization into constructor, or into the onConvoBegin function.

  • Execute write processes (which have no influence on the test process) parallel.

Using Botium CLI to generate Skeleton Project

You can use the Botium CLI to generate a skeleton project with a sample custom logic hook in the current directory:

> botium-cli init-dev logichook
> botium-cli run

Code Sample - Logic Hook Class Skeleton

Best practice is to place your custom logic hook code in a Javascript file and export a Javascript class definition. As an example, place this in a file called MyCustomLogicHook.js:

module.exports = class MyCustomLogicHook {
  constructor (context, caps, globalArgs) {
    this.context = context
    this.caps = caps
    this.globalArgs = globalArgs
    console.log(`MyCustomLogicHook constructor, globalArgs: ${utils.inspect(globalArgs)}`)
  }

  onConvoBegin ({ convo, args }) {
    console.log(`MyCustomLogicHook onConvoBegin: ${convo.header.name}`)
  }

  onConvoEnd ({ convo, transcript, args }) {
    console.log(`MyCustomLogicHook onConvoEnd ${convo.header.name}, conversation length: ${transcript.steps.length} steps`)
  }

  onMeStart ({ convo, convoStep, args }) {
    console.log(`MyCustomLogicHook onMeStart ${convo.header.name}/${convoStep.stepTag}, args: ${utils.inspect(args)}, meMessage: ${convoStep.messageText}`)
  }

  onMeEnd ({ convo, convoStep, args }) {
    console.log(`MyCustomLogicHook onMeEnd ${convo.header.name}/${convoStep.stepTag}, args: ${utils.inspect(args)}, meMessage: ${convoStep.messageText}`)
  }

  onMe ({ convo, convoStep, args }) {
    console.log(`MyCustomLogicHook onMe ${convo.header.name}/${convoStep.stepTag}, args: ${utils.inspect(args)}, meMessage: ${convoStep.messageText}`)
  }

  onBotStart ({ convo, convoStep, args }) {
    console.log(`MyCustomLogicHook onBotStart ${convo.header.name}/${convoStep.stepTag}, args: ${utils.inspect(args)}, expected: ${convoStep.messageText}`)
  }

  onBotPrepare ({ convo, convoStep, args }) {
    console.log(`MyCustomLogicHook onBotPrepare ${convo.header.name}/${convoStep.stepTag}, args: ${utils.inspect(args)}, expected: ${convoStep.messageText}`)
  }

  onBotEnd ({ convo, convoStep, botMsg, args }) {
    console.log(`MyCustomLogicHook onBotEnd ${convo.header.name}/${convoStep.stepTag}, args: ${utils.inspect(args)}, expected: ${convoStep.messageText}, meMessage: ${botMsg.messageText}`)
  }

  onBot ({ convo, convoStep, botMsg, args }) {
    console.log(`MyCustomLogicHook onBot ${convo.header.name}/${convoStep.stepTag}, args: ${utils.inspect(args)}, expected: ${convoStep.messageText}, meMessage: ${botMsg ? botMsg.messageText : null}`)
  }
}

Code Sample - Logic Hook File Code

For short logic hook it is possible to place the Javascript code directly in the component configuration:

{
  "botium": {
    "Capabilities": {
      ...
      "LOGIC_HOOKS": [
        {
          "ref": "MY-LOGICHOOK-NAME",
          "src": {
            "onMeStart": "meMsg.messageText += ' from logichook'"
          },
          "global": false,
          "args": {
            "my-arg-1": "something"
          }
        }
      ]
    }
  }
}

Logic Hook API

Class Constructor Arguments (only for class definitions)

  • context - Scripting Context with several Botium internal functions

  • caps - Botium capabilities

  • globalArgs - the component configuration (from the Component Configuration field in Botium Box, or from the args field in botium.json) as JSON structure

onConvoBegin Arguments

  • convo - current convo

  • args - the logic hook args from the convo file (as JSON array - split by “|”)

  • scriptingMemory - scripting memory variables (a JSON object)

  • isGlobal - wether the logic hook has been registered globally or not

  • container - Botium Connector container (provides access to internal connector data)

onMeStart/onMeEnd/onMe

  • convo - see above

  • convoStep - the logic hook args from the convo file (as JSON array - split by “|”)

  • args - see above

  • scriptingMemory - see above

  • isGlobal - see above

  • container - see above

  • meMsg - request from the user

onBotStart Arguments

  • convo - see above

  • convoStep - the logic hook args from the convo file (as JSON array - split by “|”)

  • args - see above

  • scriptingMemory - see above

  • isGlobal - see above

  • container - see above

onBotPrepare Arguments

  • convo - see above

  • convoStep -see above

  • args - see above

  • scriptingMemory - see above

  • isGlobal - see above

  • container - see above

  • botMsg - the message from the bot

onBotEnd Arguments

  • convo - see above

  • convoStep -see above

  • args - see above

  • scriptingMemory - see above

  • isGlobal - see above

  • container - see above

  • botMsg - the message from the bot

onBot Arguments

  • convo - see above

  • convoStep -see above

  • args - see above

  • scriptingMemory - see above

  • isGlobal - see above

  • container - see above

  • botMsg - the message from the bot. CAN BE NULL DEPENDING ON ORDER IN SCRIPT.

onConvoEnd Arguments

  • convo - see above

  • args - see above

  • scriptingMemory - see above

  • isGlobal - see above

  • container - see above

  • transcript - the full conversation transcript

Deployment to Botium Box

There are 2 ways to deploy your custom logic hook to Botium Box.

Option 1: NPM package

Build an NPM package, exporting a Javascript class holding your logic. You have to add the NPM package to your Botium Box server - unpack the NPM package to the resources directory - the package.json of your NPM package is in the resources/your-logichook-name directory - and run “npm install” there.

Note

An NPM package is nothing more than a ZIP-File. For Botium logic hooks hosted on Github, you can download the package as ZIP-file from Github (Clone or Download => Download as ZIP) and unpack them - make sure to rename the resulting directory to match the logic hook package name (Github adds the -master suffix to the downloaded files)

Now you can use the Registered Components view to register your custom logic hook, using your-logichook-name as Component Source. (Registering works like for asserters)

Option 2: Shared Javascript file

You can just tell Botium Box to load the logic hook code from a Javascript file. The Javascript file has to be available on all Botium Box servers and agents, obviously, by placing it in the resources directory.

Now you can use the Registered Components view to register your custom logic hook, using your-logichook-filename.js as Component Source (the relative path in the resources directory). (Registering works like for asserters)

Note

In booth cases you can use botium-logichook- prefix to automatically register your logic hook.

Note

I booth cases logic hook is loaded if plugins are enabled.

Deployment to botium.json

When using botium-cli or botium-bindings, you have to register your logic hook in the botium.json file:

{
  "botium": {
    "Capabilities": {
      ...
      "LOGIC_HOOKS": [
        {
          "ref": "MY-LOGICHOOK-NAME",
          "src": "path-to-my-javascript-file-or-npm-package-name",
          "global": false,
          "args": {
            "my-arg-1": "something"
          }
        }
      ]
    }
  }
}

Using the Logic Hook

You trigger the logic hook call by using the defined Component Ref Code of the logic hook (in our example below: DUMMY_LOG_TESTCASE and DUMMY_INSERT_TO_SCRIPTING_MEMORY). Everything after Component Ref Code are args separated by |

  • begin: Before the conversation starts (use onConvoBegin hook)

  • me: before and after me request (use onMeStart/onMeEnd, or booth hooks)

  • bot: before and after bot response (use onBotStart/onBotEnd, or booth hooks)

  • end: After the conversation finished

restaurant
#begin
DUMMY_LOG_TESTCASE dbUrl | dbPassword

#me
hi

#bot
Hi. It looks like a nice drive today. What would you like me to do?

#me
where is the next restaurant

#bot
I understand you want me to find a location. I can find restaurants, gas stations and restrooms nearby.

#me
find my a restaurant

#bot
Of course. Do you have a specific cuisine in mind?

#me
DUMMY_INSERT_TO_SCRIPTING_MEMORY CUISINE1
$cuisine

#bot
Super! I've found 5 locations for you. Which one would you like to drive to?

#me
DUMMY_INSERT_TO_SCRIPTING_MEMORY CUISINE1 | CHOICE1
$choice

#bot
Sure! That restaurant gets great reviews.

#end
DUMMY_LOG_TESTCASE dbUrl | dbPassword