Skip to content

Commit

Permalink
Merge pull request #645 from codeforequity-at/develop
Browse files Browse the repository at this point in the history
Botium Core 1.11.11
  • Loading branch information
Botium authored Aug 15, 2021
2 parents 5a50236 + 0e15762 commit e21dbdd
Show file tree
Hide file tree
Showing 8 changed files with 587 additions and 534 deletions.
990 changes: 494 additions & 496 deletions package-lock.json

Large diffs are not rendered by default.

40 changes: 20 additions & 20 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "botium-core",
"version": "1.11.10",
"version": "1.11.11",
"description": "The Selenium for Chatbots",
"main": "index.js",
"module": "dist/botium-es.js",
Expand Down Expand Up @@ -32,23 +32,23 @@
},
"homepage": "https://www.botium.ai",
"dependencies": {
"@babel/runtime": "^7.14.6",
"async": "^3.2.0",
"@babel/runtime": "^7.15.3",
"async": "^3.2.1",
"body-parser": "^1.19.0",
"boolean": "^3.1.2",
"bottleneck": "^2.19.5",
"csv-parse": "^4.16.0",
"debug": "^4.3.2",
"esprima": "^4.0.1",
"express": "^4.17.1",
"globby": "^11.0.4",
"ioredis": "^4.27.6",
"globby": "11.0.4",
"ioredis": "^4.27.7",
"is-class": "^0.0.9",
"is-json": "^2.0.1",
"jsonpath": "^1.1.1",
"lodash": "^4.17.21",
"markdown-it": "^12.1.0",
"mime-types": "^2.1.31",
"markdown-it": "^12.2.0",
"mime-types": "^2.1.32",
"mkdirp": "^1.0.4",
"moment": "^2.29.1",
"mustache": "^4.2.0",
Expand All @@ -58,39 +58,39 @@
"request": "^2.88.2",
"rimraf": "^3.0.2",
"sanitize-filename": "^1.6.3",
"slugify": "^1.5.3",
"socket.io": "^4.1.2",
"socket.io-client": "^4.1.2",
"slugify": "^1.6.0",
"socket.io": "^4.1.3",
"socket.io-client": "^4.1.3",
"socketio-auth": "^0.1.1",
"swagger-jsdoc": "^6.1.0",
"swagger-ui-express": "^4.1.6",
"uuid": "^8.3.2",
"vm2": "^3.9.3",
"write-yaml": "^1.0.0",
"xlsx": "^0.17.0",
"xregexp": "^5.0.2",
"xregexp": "^5.1.0",
"yaml": "^1.10.2"
},
"devDependencies": {
"@babel/core": "^7.14.6",
"@babel/node": "^7.14.7",
"@babel/plugin-transform-runtime": "^7.14.5",
"@babel/preset-env": "^7.14.7",
"@babel/core": "^7.15.0",
"@babel/node": "^7.14.9",
"@babel/plugin-transform-runtime": "^7.15.0",
"@babel/preset-env": "^7.15.0",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"cross-env": "^7.0.3",
"eslint": "^7.30.0",
"eslint": "^7.32.0",
"eslint-config-standard": "^16.0.3",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-import": "^2.24.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-standard": "^4.1.0",
"license-checker": "^25.0.1",
"mocha": "^9.0.2",
"mocha": "^9.0.3",
"nock": "^13.1.1",
"npm-check-updates": "^11.8.1",
"npm-check-updates": "^11.8.3",
"nyc": "^15.1.0",
"rollup": "^2.52.7",
"rollup": "^2.56.2",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-json": "^4.0.0",
Expand Down
2 changes: 1 addition & 1 deletion src/scripting/MatchFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { toString, quoteRegexpString } = require('./helper')

const _normalize = (botresponse) => {
if (_.isUndefined(botresponse)) return ''
if (_.isObject(botresponse)) {
if (_.isObject(botresponse) && _.has(botresponse, 'messageText')) {
return toString(botresponse.messageText) || ''
}
return toString(botresponse)
Expand Down
24 changes: 16 additions & 8 deletions src/scripting/ScriptingProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const RetryHelper = require('../helpers/RetryHelper')
const { getMatchFunction } = require('./MatchFunctions')
const precompilers = require('./precompilers')

const globPattern = '**/+(*.convo.txt|*.utterances.txt|*.pconvo.txt|*.scriptingmemory.txt|*.xlsx|*.convo.csv|*.pconvo.csv|*.yaml|*.yml|*.json|*.md|*.markdown)'
const globPattern = '**/+(*.convo.txt|*.utterances.txt|*.pconvo.txt|*.scriptingmemory.txt|*.xlsx|*.xlsm|*.convo.csv|*.pconvo.csv|*.yaml|*.yml|*.json|*.md|*.markdown)'
const skipPattern = /^skip[.\-_]/i

const p = (retryHelper, fn) => {
Expand Down Expand Up @@ -486,7 +486,7 @@ module.exports = class ScriptingProvider {
filename = precompResponse.filename || filename
}

if (filename.endsWith('.xlsx')) {
if (filename.endsWith('.xlsx') || filename.endsWith('.xlsm')) {
fileUtterances = this.Compile(scriptBuffer, Constants.SCRIPTING_FORMAT_XSLX, Constants.SCRIPTING_TYPE_UTTERANCES)
filePartialConvos = this.Compile(scriptBuffer, Constants.SCRIPTING_FORMAT_XSLX, Constants.SCRIPTING_TYPE_PCONVO)
fileConvos = this.Compile(scriptBuffer, Constants.SCRIPTING_FORMAT_XSLX, Constants.SCRIPTING_TYPE_CONVO)
Expand Down Expand Up @@ -1093,9 +1093,16 @@ module.exports = class ScriptingProvider {
}
}

GetConversationFlowView ({ getConvoNodeHash = null, detectLoops = false, summarizeMultiSteps = true } = {}) {
GetConversationFlowView ({
getConvoNodeHash = null, detectLoops = false, summarizeMultiSteps = true, includeConvoSteps = false,
extPickMeNodeProps = [], extPickBotNodeProps = [], extPickMeHashProps = [], extPickBotHashProps = []
} = {}) {
const root = []
const botNodesByHash = {}
const pickMeNodeProps = ['index', 'sender', 'messageText', 'utteranceSamples', 'utteranceCount', 'logicHooks', 'userInputs', ...extPickMeNodeProps]
const pickBotNodeProps = ['index', 'sender', 'messageText', 'optional', 'not', 'utteranceSamples', 'utteranceCount', 'logicHooks', 'asserters', ...extPickBotNodeProps]
const pickMeHashProps = ['sender', 'messageText', 'logicHooks', 'userInputs', ...extPickMeHashProps]
const pickBotHashProps = ['sender', 'messageText', 'optional', 'not', 'logicHooks', 'asserters', ...extPickBotHashProps]

this.convos.forEach((convo) => {
const convoNodes = []
Expand Down Expand Up @@ -1127,20 +1134,21 @@ module.exports = class ScriptingProvider {
let currentChildren = root
for (const convoNode of convoNodes) {
const convoNodeValues = convoNode.sender === 'me'
? convoNode.convoSteps.map(convoStep => _.pick(convoStep, ['index', 'sender', 'messageText', 'utteranceSamples', 'utteranceCount', 'logicHooks', 'userInputs']))
: convoNode.convoSteps.map(convoStep => _.pick(convoStep, ['index', 'sender', 'messageText', 'optional', 'not', 'utteranceSamples', 'utteranceCount', 'logicHooks', 'asserters']))
? convoNode.convoSteps.map(convoStep => _.pick(convoStep, pickMeNodeProps))
: convoNode.convoSteps.map(convoStep => _.pick(convoStep, pickBotNodeProps))
const convoNodeHeader = {
header: _.pick(convo.header, ['name', 'description']),
sourceTag: convo.sourceTag,
convoStepIndices: convoNode.convoStepIndices
convoStepIndices: convoNode.convoStepIndices,
conversation: includeConvoSteps ? convo.conversation : undefined
}

let hash = getConvoNodeHash && getConvoNodeHash({ convo, convoNode })
if (!hash) {
if (convoNode.sender === 'bot') {
hash = crypto.createHash('md5').update(JSON.stringify(convoNode.convoSteps.map(convoStep => _.pick(convoStep, ['sender', 'messageText', 'optional', 'not', 'logicHooks', 'asserters'])))).digest('hex')
hash = crypto.createHash('md5').update(JSON.stringify(convoNode.convoSteps.map(convoStep => _.pick(convoStep, pickBotHashProps)))).digest('hex')
} else {
hash = crypto.createHash('md5').update(JSON.stringify(convoNode.convoSteps.map(convoStep => _.pick(convoStep, ['sender', 'messageText', 'logicHooks', 'userInputs'])))).digest('hex')
hash = crypto.createHash('md5').update(JSON.stringify(convoNode.convoSteps.map(convoStep => _.pick(convoStep, pickMeHashProps)))).digest('hex')
}
}

Expand Down
1 change: 1 addition & 0 deletions src/scripting/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const toString = (value) => {
if (_.isUndefined(value)) return undefined
if (_.isString(value)) return value
if (_.isNumber(value)) return value.toString()
if (_.isArray(value)) return value.map(v => toString(v)).join(',')
try {
return JSON.stringify(value)
} catch (err) {
Expand Down
15 changes: 8 additions & 7 deletions src/scripting/logichook/asserter/JsonPathAsserter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { BotiumError } = require('../../BotiumError')
const { getMatchFunction } = require('../../MatchFunctions')
const { toString } = require('../../helper')
const _ = require('lodash')
const jsonPath = require('jsonpath')
const Mustache = require('mustache')
Expand All @@ -23,7 +24,7 @@ module.exports = class JsonPathAsserter {
_getConfig (convoStep, args) {
if (this.globalArgs && this.globalArgs.path) {
if (args && args.length > 1) {
throw new BotiumError(`${convoStep.stepTag}: JsonPathAsserter 0 or 1 arguments expected "${args}"`,
throw new BotiumError(`${convoStep.stepTag}: JsonPathAsserter 0 or 1 arguments expected "${toString(args)}"`,
{
type: 'asserter',
subtype: 'wrong parameters',
Expand All @@ -43,7 +44,7 @@ module.exports = class JsonPathAsserter {
if (_.has(this.globalArgs, 'argCount')) {
const argCount = this.globalArgs.argCount
if (argCount === 0 && args && args.length > 0) {
throw new BotiumError(`${convoStep.stepTag}: JsonPathAsserter ${argCount} arguments expected "${args}"`,
throw new BotiumError(`${convoStep.stepTag}: JsonPathAsserter ${argCount} arguments expected "${toString(args)}"`,
{
type: 'asserter',
subtype: 'wrong parameters',
Expand All @@ -55,7 +56,7 @@ module.exports = class JsonPathAsserter {
}
)
} else if (!args || args.length !== argCount) {
throw new BotiumError(`${convoStep.stepTag}: JsonPathAsserter ${argCount} arguments expected "${args}"`,
throw new BotiumError(`${convoStep.stepTag}: JsonPathAsserter ${argCount} arguments expected "${toString(args)}"`,
{
type: 'asserter',
subtype: 'wrong parameters',
Expand All @@ -74,7 +75,7 @@ module.exports = class JsonPathAsserter {
}
} else {
if (!args || args.length === 0 || args.length > 2) {
throw new BotiumError(`${convoStep.stepTag}: JsonPathAsserter 1 or 2 arguments expected "${args}"`,
throw new BotiumError(`${convoStep.stepTag}: JsonPathAsserter 1 or 2 arguments expected "${toString(args)}"`,
{
type: 'asserter',
subtype: 'wrong parameters',
Expand Down Expand Up @@ -126,7 +127,7 @@ module.exports = class JsonPathAsserter {
}
}
if (assert) {
const actual = jsonPathValues
const actual = (_.isArray(jsonPathValues) && jsonPathValues.length === 1) ? jsonPathValues[0] : jsonPathValues

let matchFn = this.context.Match
if (this.globalArgs && this.globalArgs.matchingMode) {
Expand All @@ -136,7 +137,7 @@ module.exports = class JsonPathAsserter {
const match = jsonPathValues.find(a => matchFn(a, assert))

if (not && match) {
return Promise.reject(new BotiumError(`${convoStep.stepTag}: Not expected: ${actual} in jsonPath ${path}"`,
return Promise.reject(new BotiumError(`${convoStep.stepTag}: Not expected: ${toString(actual)} in jsonPath ${path}"`,
{
type: 'asserter',
source: this.name,
Expand All @@ -157,7 +158,7 @@ module.exports = class JsonPathAsserter {
))
}
if (!not && !match) {
return Promise.reject(new BotiumError(`${convoStep.stepTag}: Expected: ${assert} in jsonPath ${path}: Actual: ${actual}`,
return Promise.reject(new BotiumError(`${convoStep.stepTag}: Expected: ${assert} in jsonPath ${path}: Actual: ${toString(actual)}`,
{
type: 'asserter',
source: this.name,
Expand Down
45 changes: 45 additions & 0 deletions test/scripting/asserters/jsonpathAsserter.spec.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
const assert = require('chai').assert
const JsonPathAsserter = require('../../../src/scripting/logichook/asserter/JsonPathAsserter')
const JsonPathCountAsserter = require('../../../src/scripting/logichook/asserter/JsonPathCountAsserter')
const { getMatchFunction } = require('../../../src/scripting/MatchFunctions')

describe('scripting.asserters.jsonPathAsserter', function () {
beforeEach(async function () {
this.jsonPathAsserter = new JsonPathAsserter({
Match: (botresponse, utterance) => botresponse.toLowerCase().indexOf(utterance.toLowerCase()) >= 0
}, {})
this.jsonPathAsserterWildcard = new JsonPathAsserter({
Match: getMatchFunction('wildcardIgnoreCase')
}, {})
this.jsonPathAsserterGlobalArgs = new JsonPathAsserter({
Match: (botresponse, utterance) => botresponse.toLowerCase().indexOf(utterance.toLowerCase()) >= 0
}, {}, { path: '$.test' })
Expand Down Expand Up @@ -57,6 +61,7 @@ describe('scripting.asserters.jsonPathAsserter', function () {
}
})
} catch (err) {
console.log(err.message)
assert.isTrue(err.message.includes('Expected: message4 in jsonPath $.messages[*].label: Actual: message1,message2,message3'))
}
})
Expand Down Expand Up @@ -97,6 +102,46 @@ describe('scripting.asserters.jsonPathAsserter', function () {
}
})
})
it('should succeed on jsonpath object', async function () {
await this.jsonPathAsserterWildcard.assertConvoStep({
convoStep: { stepTag: 'test' },
args: ['$.messages[0]', '{"label":"message1"}'],
botMsg: {
sourceData: {
messages: [
{ label: 'message1' },
{ label: 'message2' },
{ label: 'message3' }
]
}
}
})
})
it('should fail on invalid jsonpath object', async function () {
try {
await this.jsonPathAsserterWildcard.assertConvoStep({
convoStep: { stepTag: 'test' },
args: ['$.messages[0]', '{"label":"message2"}'],
botMsg: {
sourceData: {
messages: [
{ label: 'message1' },
{ label: 'message2' },
{ label: 'message3' }
]
}
}
})
} catch (err) {
assert.isTrue(err.message.indexOf('Expected: {"label":"message2"} in jsonPath $.messages[0]: Actual: {"label":"message1"}') > 0)
assert.isNotNull(err.context)
assert.isNotNull(err.context.cause)
assert.isNotTrue(err.context.cause.not)
assert.equal(err.context.cause.expected, '{"label":"message2"}')
assert.deepEqual(err.context.cause.actual, { label: 'message1' })
}
})

it('should fail on not matching jsonpath', async function () {
try {
await this.jsonPathAsserter.assertConvoStep({
Expand Down
4 changes: 2 additions & 2 deletions test/scripting/matching/matchingmode.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ describe('matching.matchingmode.general', function () {
assert.isTrue(this.compiler.Match({ messageText: 123 }, '123'))
})

it('should not check other fields as messageText', async function () {
assert.isFalse(this.compiler.Match({ somethingElse: '123' }, '123'))
it('should match JSON response with toString', async function () {
assert.isTrue(this.compiler.Match({ somethingElse: '123' }, '"somethingElse":"123"'))
})
})

Expand Down

0 comments on commit e21dbdd

Please sign in to comment.