botium-core 1.11.15 → 1.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/botium-cjs.js +420 -172
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +411 -164
- package/dist/botium-es.js.map +1 -1
- package/index.js +1 -0
- package/package.json +27 -27
- package/samples/connectors/custom/botium-connector-myapi.js +3 -3
- package/samples/extensions/asserterHooks/DummyAsserter.js +3 -3
- package/src/Capabilities.js +4 -0
- package/src/Defaults.js +1 -0
- package/src/Enums.js +6 -0
- package/src/containers/BaseContainer.js +20 -10
- package/src/containers/PluginConnectorContainer.js +1 -0
- package/src/containers/plugins/SimpleRestContainer.js +36 -4
- package/src/scripting/BotiumError.js +21 -0
- package/src/scripting/CompilerCsv.js +1 -1
- package/src/scripting/CompilerObjectBase.js +4 -14
- package/src/scripting/CompilerTxt.js +4 -15
- package/src/scripting/CompilerXlsx.js +81 -25
- package/src/scripting/Convo.js +16 -4
- package/src/scripting/ScriptingProvider.js +6 -0
- package/src/scripting/helper.js +54 -1
- package/src/scripting/logichook/LogicHookUtils.js +2 -0
- package/src/scripting/logichook/asserter/JsonPathAsserter.js +1 -1
- package/src/scripting/logichook/logichooks/ClearQueueLogicHook.js +1 -1
- package/src/scripting/logichook/userinput/MediaInput.js +14 -2
- package/test/connectors/convos/hello.convo.txt +6 -0
- package/test/connectors/simplerest.spec.js +42 -2
- package/test/convo/convos/continuefailing.convo.txt +19 -0
- package/test/convo/transcript.spec.js +34 -0
- package/test/scripting/scriptingProvider.spec.js +4 -4
- package/test/scripting/scriptingmemory/convosMultiMemorySameCols/buy.convo.txt +6 -0
- package/test/scripting/scriptingmemory/convosMultiMemorySameCols/products1.scriptingmemory.txt +2 -0
- package/test/scripting/scriptingmemory/convosMultiMemorySameCols/products2.scriptingmemory.txt +2 -0
- package/test/scripting/scriptingmemory/convosSimpleCols/buy.convo.txt +8 -0
- package/test/scripting/scriptingmemory/convosSimpleCols/product.scriptingmemory.txt +3 -0
- package/test/scripting/scriptingmemory/convosTwoTablesCols/buy.convo.txt +6 -0
- package/test/scripting/scriptingmemory/convosTwoTablesCols/customer.xlsx +0 -0
- package/test/scripting/scriptingmemory/convosTwoTablesCols/product.xlsx +0 -0
- package/test/scripting/scriptingmemory/fillScriptingMemoryFromFile.spec.js +45 -0
- package/test/scripting/userinputs/mediaInputConvos.spec.js +53 -2
package/index.js
CHANGED
|
@@ -4,6 +4,7 @@ module.exports = {
|
|
|
4
4
|
ScriptingConstants: require('./src/scripting/Constants'),
|
|
5
5
|
Capabilities: require('./src/Capabilities'),
|
|
6
6
|
Defaults: require('./src/Defaults'),
|
|
7
|
+
Enums: require('./src/Enums'),
|
|
7
8
|
Source: require('./src/Source'),
|
|
8
9
|
Events: require('./src/Events'),
|
|
9
10
|
Plugins: require('./src/Plugins'),
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "botium-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.2",
|
|
4
4
|
"description": "The Selenium for Chatbots",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/botium-es.js",
|
|
7
7
|
"engines": {
|
|
8
|
-
"node": ">=
|
|
8
|
+
"node": ">=14.0.0"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"postinstall": "node ./report.js",
|
|
@@ -32,23 +32,23 @@
|
|
|
32
32
|
},
|
|
33
33
|
"homepage": "https://www.botium.ai",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@babel/runtime": "^7.16.
|
|
36
|
-
"async": "^3.2.
|
|
37
|
-
"body-parser": "^1.19.
|
|
35
|
+
"@babel/runtime": "^7.16.7",
|
|
36
|
+
"async": "^3.2.3",
|
|
37
|
+
"body-parser": "^1.19.1",
|
|
38
38
|
"boolean": "^3.1.4",
|
|
39
39
|
"bottleneck": "^2.19.5",
|
|
40
|
-
"csv-parse": "^
|
|
41
|
-
"debug": "^4.3.
|
|
40
|
+
"csv-parse": "^5.0.4",
|
|
41
|
+
"debug": "^4.3.3",
|
|
42
42
|
"esprima": "^4.0.1",
|
|
43
|
-
"express": "^4.17.
|
|
43
|
+
"express": "^4.17.2",
|
|
44
44
|
"globby": "11.0.4",
|
|
45
|
-
"ioredis": "^4.28.
|
|
45
|
+
"ioredis": "^4.28.3",
|
|
46
46
|
"is-class": "^0.0.9",
|
|
47
47
|
"is-json": "^2.0.1",
|
|
48
48
|
"jsonpath": "^1.1.1",
|
|
49
49
|
"lodash": "^4.17.21",
|
|
50
|
-
"markdown-it": "^12.2
|
|
51
|
-
"mime-types": "^2.1.
|
|
50
|
+
"markdown-it": "^12.3.2",
|
|
51
|
+
"mime-types": "^2.1.34",
|
|
52
52
|
"mkdirp": "^1.0.4",
|
|
53
53
|
"moment": "^2.29.1",
|
|
54
54
|
"mustache": "^4.2.0",
|
|
@@ -58,40 +58,40 @@
|
|
|
58
58
|
"request": "^2.88.2",
|
|
59
59
|
"rimraf": "^3.0.2",
|
|
60
60
|
"sanitize-filename": "^1.6.3",
|
|
61
|
-
"slugify": "^1.6.
|
|
62
|
-
"socket.io": "^4.
|
|
63
|
-
"socket.io-client": "^4.
|
|
61
|
+
"slugify": "^1.6.5",
|
|
62
|
+
"socket.io": "^4.4.1",
|
|
63
|
+
"socket.io-client": "^4.4.1",
|
|
64
64
|
"socketio-auth": "^0.1.1",
|
|
65
65
|
"swagger-jsdoc": "^6.1.0",
|
|
66
|
-
"swagger-ui-express": "^4.
|
|
66
|
+
"swagger-ui-express": "^4.3.0",
|
|
67
67
|
"uuid": "^8.3.2",
|
|
68
68
|
"vm2": "^3.9.5",
|
|
69
69
|
"write-yaml": "^1.0.0",
|
|
70
|
-
"xlsx": "^0.17.
|
|
70
|
+
"xlsx": "^0.17.5",
|
|
71
71
|
"xregexp": "^5.1.0",
|
|
72
72
|
"yaml": "^1.10.2"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
|
-
"@babel/core": "^7.16.
|
|
76
|
-
"@babel/node": "^7.16.
|
|
77
|
-
"@babel/plugin-transform-runtime": "^7.16.
|
|
78
|
-
"@babel/preset-env": "^7.16.
|
|
75
|
+
"@babel/core": "^7.16.12",
|
|
76
|
+
"@babel/node": "^7.16.8",
|
|
77
|
+
"@babel/plugin-transform-runtime": "^7.16.10",
|
|
78
|
+
"@babel/preset-env": "^7.16.11",
|
|
79
79
|
"chai": "^4.3.4",
|
|
80
80
|
"chai-as-promised": "^7.1.1",
|
|
81
81
|
"cross-env": "^7.0.3",
|
|
82
|
-
"eslint": "^8.
|
|
82
|
+
"eslint": "^8.7.0",
|
|
83
83
|
"eslint-config-standard": "^16.0.3",
|
|
84
|
-
"eslint-plugin-import": "^2.25.
|
|
84
|
+
"eslint-plugin-import": "^2.25.4",
|
|
85
85
|
"eslint-plugin-node": "^11.1.0",
|
|
86
|
-
"eslint-plugin-promise": "^
|
|
86
|
+
"eslint-plugin-promise": "^6.0.0",
|
|
87
87
|
"eslint-plugin-standard": "^4.1.0",
|
|
88
88
|
"license-checker": "^25.0.1",
|
|
89
89
|
"license-compatibility-checker": "^0.3.5",
|
|
90
|
-
"mocha": "^9.
|
|
91
|
-
"nock": "^13.
|
|
92
|
-
"npm-check-updates": "^12.
|
|
90
|
+
"mocha": "^9.2.0",
|
|
91
|
+
"nock": "^13.2.2",
|
|
92
|
+
"npm-check-updates": "^12.2.1",
|
|
93
93
|
"nyc": "^15.1.0",
|
|
94
|
-
"rollup": "^2.
|
|
94
|
+
"rollup": "^2.66.0",
|
|
95
95
|
"rollup-plugin-babel": "^4.4.0",
|
|
96
96
|
"rollup-plugin-commonjs": "^10.1.0",
|
|
97
97
|
"rollup-plugin-json": "^4.0.0",
|
|
@@ -23,13 +23,13 @@ class BotiumConnectorMyApi {
|
|
|
23
23
|
[CoreCapabilities.SIMPLEREST_URL]: this.caps[Capabilities.MYAPI_URL],
|
|
24
24
|
[CoreCapabilities.SIMPLEREST_METHOD]: 'POST',
|
|
25
25
|
[CoreCapabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$.reply',
|
|
26
|
-
[CoreCapabilities.SIMPLEREST_BODY_TEMPLATE]: JSON.stringify({
|
|
26
|
+
[CoreCapabilities.SIMPLEREST_BODY_TEMPLATE]: JSON.stringify({
|
|
27
27
|
username: 'botium',
|
|
28
28
|
message: '{{msg.messageText}}',
|
|
29
29
|
session: '{{botium.conversationId}}',
|
|
30
30
|
startsession: false,
|
|
31
31
|
quickreply: null
|
|
32
|
-
|
|
32
|
+
})
|
|
33
33
|
}
|
|
34
34
|
if (this.caps[Capabilities.MYAPI_TOKEN]) {
|
|
35
35
|
this.delegateCaps[CoreCapabilities.SIMPLEREST_HEADERS_TEMPLATE] = `{ "Authorization": "Token ${this.caps[Capabilities.MYAPI_TOKEN]}"}`
|
|
@@ -104,4 +104,4 @@ module.exports = {
|
|
|
104
104
|
}
|
|
105
105
|
]
|
|
106
106
|
}
|
|
107
|
-
}
|
|
107
|
+
}
|
|
@@ -6,17 +6,17 @@ module.exports = class DummyAsserter {
|
|
|
6
6
|
this.caps = caps
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
assertConvoBegin ({convo, container, args}) {
|
|
9
|
+
assertConvoBegin ({ convo, container, args }) {
|
|
10
10
|
console.log(`Dummy asserter Begin started with those args: ${utils.inspect(args)}`)
|
|
11
11
|
return Promise.resolve()
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
assertConvoStep ({convo, convoStep, args, botMsg}) {
|
|
14
|
+
assertConvoStep ({ convo, convoStep, args, botMsg }) {
|
|
15
15
|
console.log(`ConvoStep dummy assertion with those args: ${utils.inspect(args)}, botMessage: ${utils.inspect(botMsg)} ...`)
|
|
16
16
|
return Promise.resolve()
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
assertConvoEnd ({convo, container, transcript, args}) {
|
|
19
|
+
assertConvoEnd ({ convo, container, transcript, args }) {
|
|
20
20
|
console.log(`ConvoEnd dummy assertion with those args: ${utils.inspect(args)}, transcript: ${utils.inspect(transcript)} ...`)
|
|
21
21
|
return Promise.resolve()
|
|
22
22
|
}
|
package/src/Capabilities.js
CHANGED
|
@@ -111,6 +111,7 @@ module.exports = {
|
|
|
111
111
|
SCRIPTING_NORMALIZE_TEXT: 'SCRIPTING_NORMALIZE_TEXT',
|
|
112
112
|
SCRIPTING_ENABLE_MEMORY: 'SCRIPTING_ENABLE_MEMORY',
|
|
113
113
|
SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS: 'SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS',
|
|
114
|
+
SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS: 'SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS',
|
|
114
115
|
SCRIPTING_FORCE_BOT_CONSUMED: 'SCRIPTING_FORCE_BOT_CONSUMED',
|
|
115
116
|
// regexp, regexpIgnoreCase, wildcard, wildcardIgnoreCase, wildcardExact, wildcardExactIgnoreCase, include, includeIgnoreCase, equals, equalsIgnoreCase
|
|
116
117
|
SCRIPTING_MATCHING_MODE: 'SCRIPTING_MATCHING_MODE',
|
|
@@ -126,6 +127,8 @@ module.exports = {
|
|
|
126
127
|
SCRIPTING_MEMORYEXPANSION_KEEP_ORIG: 'SCRIPTING_MEMORYEXPANSION_KEEP_ORIG',
|
|
127
128
|
// word, non_whitespace, joker
|
|
128
129
|
SCRIPTING_MEMORY_MATCHING_MODE: 'SCRIPTING_MEMORY_MATCHING_MODE',
|
|
130
|
+
// varnames, testcasenames
|
|
131
|
+
SCRIPTING_MEMORY_COLUMN_MODE: 'SCRIPTING_MEMORY_COLUMN_MODE',
|
|
129
132
|
// Botium Lifecycle Hooks
|
|
130
133
|
CUSTOMHOOK_ONBUILD: 'CUSTOMHOOK_ONBUILD',
|
|
131
134
|
CUSTOMHOOK_ONSTART: 'CUSTOMHOOK_ONSTART',
|
|
@@ -140,6 +143,7 @@ module.exports = {
|
|
|
140
143
|
// API Calls Rate Limiting
|
|
141
144
|
RATELIMIT_USERSAYS_MAXCONCURRENT: 'RATELIMIT_USERSAYS_MAXCONCURRENT',
|
|
142
145
|
RATELIMIT_USERSAYS_MINTIME: 'RATELIMIT_USERSAYS_MINTIME',
|
|
146
|
+
RATELIMIT_BOTTLENECK_FN: 'RATELIMIT_BOTTLENECK_FN',
|
|
143
147
|
SECURITY_ALLOW_UNSAFE: 'SECURITY_ALLOW_UNSAFE',
|
|
144
148
|
PRECOMPILERS: 'PRECOMPILERS'
|
|
145
149
|
}
|
package/src/Defaults.js
CHANGED
|
@@ -50,6 +50,7 @@ module.exports = {
|
|
|
50
50
|
[Capabilities.SCRIPTING_UTTEXPANSION_NAMING_MODE]: 'justLineTag',
|
|
51
51
|
[Capabilities.SCRIPTING_UTTEXPANSION_NAMING_UTTERANCE_MAX]: '16',
|
|
52
52
|
[Capabilities.SCRIPTING_MEMORYEXPANSION_KEEP_ORIG]: false,
|
|
53
|
+
[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]: false,
|
|
53
54
|
[Capabilities.SCRIPTING_FORCE_BOT_CONSUMED]: false,
|
|
54
55
|
[Capabilities.ASSERTERS]: [],
|
|
55
56
|
[Capabilities.LOGIC_HOOKS]: [],
|
package/src/Enums.js
ADDED
|
@@ -21,7 +21,7 @@ module.exports = class BaseContainer {
|
|
|
21
21
|
this.tempDirectory = tempDirectory
|
|
22
22
|
this.cleanupTasks = []
|
|
23
23
|
this.queues = {}
|
|
24
|
-
this.
|
|
24
|
+
this.bottleneck = null
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
Validate () {
|
|
@@ -32,18 +32,28 @@ module.exports = class BaseContainer {
|
|
|
32
32
|
this.onStopHook = getHook(this.caps, this.caps[Capabilities.CUSTOMHOOK_ONSTOP])
|
|
33
33
|
this.onCleanHook = getHook(this.caps, this.caps[Capabilities.CUSTOMHOOK_ONCLEAN])
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
if (this.caps[Capabilities.RATELIMIT_BOTTLENECK_FN]) {
|
|
36
|
+
if (_.isFunction(this.caps[Capabilities.RATELIMIT_BOTTLENECK_FN])) {
|
|
37
|
+
this.bottleneck = this.caps[Capabilities.RATELIMIT_BOTTLENECK_FN]
|
|
38
|
+
debug('Validate: Applying userSays rate limits from capability')
|
|
39
|
+
} else {
|
|
40
|
+
const limiter = new Bottleneck(this.caps[Capabilities.RATELIMIT_BOTTLENECK_FN])
|
|
41
|
+
this.bottleneck = (fn) => limiter.schedule(fn)
|
|
42
|
+
debug(`Validate: Applying userSays rate limits ${util.inspect(this.caps[Capabilities.RATELIMIT_BOTTLENECK_FN])}`)
|
|
43
|
+
}
|
|
44
|
+
} else if (this.caps[Capabilities.RATELIMIT_USERSAYS_MAXCONCURRENT] || this.caps[Capabilities.RATELIMIT_USERSAYS_MINTIME]) {
|
|
40
45
|
const opts = {}
|
|
41
46
|
if (this.caps[Capabilities.RATELIMIT_USERSAYS_MAXCONCURRENT]) opts.maxConcurrent = this.caps[Capabilities.RATELIMIT_USERSAYS_MAXCONCURRENT]
|
|
42
47
|
if (this.caps[Capabilities.RATELIMIT_USERSAYS_MINTIME]) opts.minTime = this.caps[Capabilities.RATELIMIT_USERSAYS_MINTIME]
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
const limiter = new Bottleneck(opts)
|
|
49
|
+
this.bottleneck = (fn) => limiter.schedule(fn)
|
|
50
|
+
debug(`Validate: Applying userSays rate limits ${util.inspect(opts)}`)
|
|
45
51
|
}
|
|
46
52
|
|
|
53
|
+
return Promise.resolve()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
Build () {
|
|
47
57
|
return new Promise((resolve, reject) => {
|
|
48
58
|
this._RunCustomHook('onBuild', this.onBuildHook)
|
|
49
59
|
.then(() => resolve(this))
|
|
@@ -69,8 +79,8 @@ module.exports = class BaseContainer {
|
|
|
69
79
|
const run = () => this._RunCustomHook('onUserSays', this.onUserSaysHook, { meMsg })
|
|
70
80
|
.then(() => this.UserSaysImpl(meMsg))
|
|
71
81
|
|
|
72
|
-
if (this.
|
|
73
|
-
return this.
|
|
82
|
+
if (this.bottleneck) {
|
|
83
|
+
return this.bottleneck(run)
|
|
74
84
|
} else {
|
|
75
85
|
return run()
|
|
76
86
|
}
|
|
@@ -17,13 +17,15 @@ const Defaults = require('../../Defaults').Capabilities
|
|
|
17
17
|
const { SCRIPTING_FUNCTIONS } = require('../../scripting/ScriptingMemory')
|
|
18
18
|
const { getHook, executeHook } = require('../../helpers/HookUtils')
|
|
19
19
|
const { escapeJSONString } = require('../../helpers/Utils')
|
|
20
|
+
const { BotiumError } = require('../../scripting/BotiumError')
|
|
20
21
|
|
|
21
22
|
Mustache.escape = s => s
|
|
22
23
|
|
|
23
24
|
module.exports = class SimpleRestContainer {
|
|
24
|
-
constructor ({ queueBotSays, caps }) {
|
|
25
|
+
constructor ({ queueBotSays, caps, bottleneck }) {
|
|
25
26
|
this.queueBotSays = queueBotSays
|
|
26
27
|
this.caps = Object.assign({}, Defaults, caps)
|
|
28
|
+
this.bottleneck = bottleneck || ((fn) => fn())
|
|
27
29
|
this.processInbound = false
|
|
28
30
|
this.redisTopic = this.caps[Capabilities.SIMPLEREST_REDIS_TOPIC] || 'SIMPLEREST_INBOUND_SUBSCRIPTION'
|
|
29
31
|
|
|
@@ -384,6 +386,18 @@ module.exports = class SimpleRestContainer {
|
|
|
384
386
|
} else {
|
|
385
387
|
if (response.statusCode >= 400) {
|
|
386
388
|
debug(`got error response: ${response.statusCode}/${response.statusMessage}`)
|
|
389
|
+
if (debug.enabled && body) {
|
|
390
|
+
debug(botiumUtils.shortenJsonString(body))
|
|
391
|
+
}
|
|
392
|
+
if (body) {
|
|
393
|
+
const jsonBody = botiumUtils.toJsonWeak(body)
|
|
394
|
+
const errKey = Object.keys(jsonBody).find(k => k.startsWith('err') || k.startsWith('fail'))
|
|
395
|
+
if (errKey) {
|
|
396
|
+
return reject(new BotiumError(`got error response: ${response.statusCode}/${response.statusMessage} - ${jsonBody[errKey]}`, {
|
|
397
|
+
message: botiumUtils.shortenJsonString(body)
|
|
398
|
+
}))
|
|
399
|
+
}
|
|
400
|
+
}
|
|
387
401
|
return reject(new Error(`got error response: ${response.statusCode}/${response.statusMessage}`))
|
|
388
402
|
}
|
|
389
403
|
|
|
@@ -475,6 +489,15 @@ module.exports = class SimpleRestContainer {
|
|
|
475
489
|
requestOptions.uri = `${requestOptions.uri}?${appendToUri}`
|
|
476
490
|
}
|
|
477
491
|
}
|
|
492
|
+
if (msg.ADD_FORM_PARAM && Object.keys(msg.ADD_FORM_PARAM).length > 0) {
|
|
493
|
+
requestOptions.form = {}
|
|
494
|
+
for (const formKey of Object.keys(msg.ADD_FORM_PARAM)) {
|
|
495
|
+
const formValue = this._getMustachedVal(
|
|
496
|
+
_.isString(msg.ADD_FORM_PARAM[formKey]) ? msg.ADD_FORM_PARAM[formKey] : JSON.stringify(msg.ADD_FORM_PARAM[formKey]),
|
|
497
|
+
false)
|
|
498
|
+
requestOptions.form[formKey] = formValue
|
|
499
|
+
}
|
|
500
|
+
}
|
|
478
501
|
if (msg.ADD_HEADER && Object.keys(msg.ADD_HEADER).length > 0) {
|
|
479
502
|
requestOptions.headers = requestOptions.headers || {}
|
|
480
503
|
|
|
@@ -506,19 +529,25 @@ module.exports = class SimpleRestContainer {
|
|
|
506
529
|
throw new Error(`Failed to ping bot after ${retries} retries`)
|
|
507
530
|
}
|
|
508
531
|
tries++
|
|
509
|
-
const { err, response, body } = await new Promise((resolve) => {
|
|
532
|
+
const { err, response, body } = await this.bottleneck(() => new Promise((resolve) => {
|
|
510
533
|
request(pingConfig, (err, response, body) => {
|
|
511
534
|
resolve({ err, response, body })
|
|
512
535
|
})
|
|
513
|
-
})
|
|
536
|
+
}))
|
|
514
537
|
if (err) {
|
|
515
538
|
debug(`_waitForUrlResponse error on url check ${pingConfig.uri}: ${err}`)
|
|
516
539
|
await timeout(pingConfig.timeout)
|
|
517
540
|
} else if (response.statusCode >= 400) {
|
|
518
541
|
debug(`_waitForUrlResponse on url check ${pingConfig.uri} got error response: ${response.statusCode}/${response.statusMessage}`)
|
|
542
|
+
if (debug.enabled && body) {
|
|
543
|
+
debug(botiumUtils.shortenJsonString(body))
|
|
544
|
+
}
|
|
519
545
|
await timeout(pingConfig.timeout)
|
|
520
546
|
} else {
|
|
521
|
-
debug(`_waitForUrlResponse success on url check ${pingConfig.uri}`)
|
|
547
|
+
debug(`_waitForUrlResponse success on url check ${pingConfig.uri}: ${response.statusCode}/${response.statusMessage}`)
|
|
548
|
+
if (debug.enabled && body) {
|
|
549
|
+
debug(botiumUtils.shortenJsonString(body))
|
|
550
|
+
}
|
|
522
551
|
return body
|
|
523
552
|
}
|
|
524
553
|
}
|
|
@@ -712,6 +741,9 @@ module.exports = class SimpleRestContainer {
|
|
|
712
741
|
} else {
|
|
713
742
|
if (response.statusCode >= 400) {
|
|
714
743
|
debug(`_runPolling: got error response: ${response.statusCode}/${response.statusMessage}, request: ${JSON.stringify(pollConfig)}`)
|
|
744
|
+
if (debug.enabled && body) {
|
|
745
|
+
debug(botiumUtils.shortenJsonString(body))
|
|
746
|
+
}
|
|
715
747
|
} else if (body) {
|
|
716
748
|
debug(`_runPolling: got response code: ${response.statusCode}, body: ${botiumUtils.shortenJsonString(body)}`)
|
|
717
749
|
|
|
@@ -26,6 +26,27 @@ const BotiumError = class BotiumError extends Error {
|
|
|
26
26
|
this.context.message = message.message || message
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
isAsserterError () {
|
|
30
|
+
if (this.context) {
|
|
31
|
+
const errArr = _.isArray(this.context) ? this.context : [this.context]
|
|
32
|
+
const hasNotAsserterError = errArr.findIndex(errDetail => {
|
|
33
|
+
if (errDetail.type === 'list') {
|
|
34
|
+
if (errDetail.errors) {
|
|
35
|
+
return errDetail.errors.findIndex(e => e.type !== 'asserter') >= 0
|
|
36
|
+
} else {
|
|
37
|
+
return true
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
return errDetail.type !== 'asserter'
|
|
41
|
+
}
|
|
42
|
+
}) >= 0
|
|
43
|
+
if (hasNotAsserterError) return false
|
|
44
|
+
return true
|
|
45
|
+
} else {
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
29
50
|
prettify (includeJson) {
|
|
30
51
|
const lines = []
|
|
31
52
|
if (this.context) {
|
|
@@ -6,7 +6,7 @@ const CompilerBase = require('./CompilerBase')
|
|
|
6
6
|
const Constants = require('./Constants')
|
|
7
7
|
const Utterance = require('./Utterance')
|
|
8
8
|
const { Convo } = require('./Convo')
|
|
9
|
-
const { linesToConvoStep, validSenders } = require('./helper')
|
|
9
|
+
const { linesToConvoStep, validSenders, linesToScriptingMemories } = require('./helper')
|
|
10
10
|
|
|
11
11
|
module.exports = class CompilerObjectBase extends CompilerBase {
|
|
12
12
|
constructor (context, caps = {}) {
|
|
@@ -109,20 +109,10 @@ module.exports = class CompilerObjectBase extends CompilerBase {
|
|
|
109
109
|
if (lines && lines.length > 0) {
|
|
110
110
|
if (_.isString(lines[0])) {
|
|
111
111
|
if (lines.length > 1) {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const rawRow = lines[row].split('|').map((name) => name.trim())
|
|
116
|
-
const caseName = rawRow[0]
|
|
117
|
-
const values = rawRow.slice(1)
|
|
118
|
-
const json = {}
|
|
119
|
-
for (let col = 0; col < names.length; col++) {
|
|
120
|
-
json[names[col]] = values[col]
|
|
121
|
-
}
|
|
122
|
-
const scriptingMemory = { header: { name: caseName }, values: json }
|
|
123
|
-
scriptingMemories.push(scriptingMemory)
|
|
112
|
+
const scriptingMemories = linesToScriptingMemories(lines, this.caps[Capabilities.SCRIPTING_MEMORY_COLUMN_MODE])
|
|
113
|
+
if (scriptingMemories && scriptingMemories.length > 0) {
|
|
114
|
+
this.context.AddScriptingMemories(scriptingMemories)
|
|
124
115
|
}
|
|
125
|
-
this.context.AddScriptingMemories(scriptingMemories)
|
|
126
116
|
return scriptingMemories
|
|
127
117
|
}
|
|
128
118
|
} else {
|
|
@@ -5,7 +5,7 @@ const Constants = require('./Constants')
|
|
|
5
5
|
const CompilerBase = require('./CompilerBase')
|
|
6
6
|
const Utterance = require('./Utterance')
|
|
7
7
|
const { ConvoHeader, Convo } = require('./Convo')
|
|
8
|
-
const { linesToConvoStep, convoStepToLines, validateConvo, validSenders } = require('./helper')
|
|
8
|
+
const { linesToConvoStep, convoStepToLines, validateConvo, validSenders, linesToScriptingMemories } = require('./helper')
|
|
9
9
|
|
|
10
10
|
module.exports = class CompilerTxt extends CompilerBase {
|
|
11
11
|
constructor (context, caps = {}) {
|
|
@@ -131,21 +131,10 @@ module.exports = class CompilerTxt extends CompilerBase {
|
|
|
131
131
|
|
|
132
132
|
_compileScriptingMemory (lines) {
|
|
133
133
|
if (lines && lines.length > 1) {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if (!lines[row] || lines[row].length === 0) continue
|
|
138
|
-
const rawRow = lines[row].split('|').map((name) => name.trim())
|
|
139
|
-
const caseName = rawRow[0]
|
|
140
|
-
const values = rawRow.slice(1)
|
|
141
|
-
const json = {}
|
|
142
|
-
for (let col = 0; col < names.length; col++) {
|
|
143
|
-
json[names[col]] = values[col]
|
|
144
|
-
}
|
|
145
|
-
const scriptingMemory = { header: { name: caseName }, values: json }
|
|
146
|
-
scriptingMemories.push(scriptingMemory)
|
|
134
|
+
const scriptingMemories = linesToScriptingMemories(lines, this.caps[Capabilities.SCRIPTING_MEMORY_COLUMN_MODE])
|
|
135
|
+
if (scriptingMemories && scriptingMemories.length > 0) {
|
|
136
|
+
this.context.AddScriptingMemories(scriptingMemories)
|
|
147
137
|
}
|
|
148
|
-
this.context.AddScriptingMemories(scriptingMemories)
|
|
149
138
|
return scriptingMemories
|
|
150
139
|
}
|
|
151
140
|
}
|
|
@@ -4,6 +4,7 @@ const _ = require('lodash')
|
|
|
4
4
|
const debug = require('debug')('botium-core-CompilerXlsx')
|
|
5
5
|
|
|
6
6
|
const Capabilities = require('../Capabilities')
|
|
7
|
+
const { E_SCRIPTING_MEMORY_COLUMN_MODE } = require('../Enums')
|
|
7
8
|
const CompilerBase = require('./CompilerBase')
|
|
8
9
|
const Constants = require('./Constants')
|
|
9
10
|
const Utterance = require('./Utterance')
|
|
@@ -286,38 +287,93 @@ module.exports = class CompilerXlsx extends CompilerBase {
|
|
|
286
287
|
}
|
|
287
288
|
|
|
288
289
|
if (scriptType === Constants.SCRIPTING_TYPE_SCRIPTING_MEMORY) {
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
if (sheet[variableNameCell] && sheet[variableNameCell].v) {
|
|
294
|
-
variableNames.push(sheet[variableNameCell].v)
|
|
295
|
-
} else {
|
|
296
|
-
break
|
|
290
|
+
const guessScriptingMemoryColumnMode = () => {
|
|
291
|
+
const line1Cell = this.colnames[colindex] + (rowindex + 1)
|
|
292
|
+
if (sheet[line1Cell] && sheet[line1Cell].v) {
|
|
293
|
+
if (sheet[line1Cell].v.startsWith('$')) return E_SCRIPTING_MEMORY_COLUMN_MODE.TESTCASENAMES
|
|
297
294
|
}
|
|
298
|
-
|
|
299
|
-
colindexTemp++
|
|
295
|
+
return E_SCRIPTING_MEMORY_COLUMN_MODE.VARNAMES
|
|
300
296
|
}
|
|
297
|
+
const columnMode = this.caps[Capabilities.SCRIPTING_MEMORY_COLUMN_MODE] || guessScriptingMemoryColumnMode()
|
|
298
|
+
|
|
299
|
+
if (columnMode === E_SCRIPTING_MEMORY_COLUMN_MODE.TESTCASENAMES) {
|
|
300
|
+
const caseNames = []
|
|
301
|
+
let colindexTemp = colindex + 1
|
|
302
|
+
while (true) {
|
|
303
|
+
const caseNameCell = this.colnames[colindexTemp] + rowindex
|
|
304
|
+
if (sheet[caseNameCell] && sheet[caseNameCell].v) {
|
|
305
|
+
caseNames.push(sheet[caseNameCell].v)
|
|
306
|
+
} else {
|
|
307
|
+
break
|
|
308
|
+
}
|
|
309
|
+
colindexTemp++
|
|
310
|
+
}
|
|
301
311
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
312
|
+
const varNames = []
|
|
313
|
+
const varValues = []
|
|
314
|
+
|
|
315
|
+
rowindex += 1
|
|
316
|
+
while (true) {
|
|
317
|
+
const varNameCell = this.colnames[colindex] + rowindex
|
|
318
|
+
if (sheet[varNameCell] && sheet[varNameCell].v) {
|
|
319
|
+
varNames.push(sheet[varNameCell].v)
|
|
320
|
+
const values = []
|
|
321
|
+
for (let i = 0; i < caseNames.length; i++) {
|
|
322
|
+
const variableValueCell = this.colnames[colindex + 1 + i] + rowindex
|
|
323
|
+
if (sheet[variableValueCell] && sheet[variableValueCell].v) {
|
|
324
|
+
values.push(sheet[variableValueCell].v.toString())
|
|
325
|
+
} else {
|
|
326
|
+
values.push(null)
|
|
327
|
+
}
|
|
314
328
|
}
|
|
329
|
+
varValues.push(values)
|
|
330
|
+
rowindex += 1
|
|
331
|
+
} else {
|
|
332
|
+
break
|
|
315
333
|
}
|
|
316
|
-
|
|
334
|
+
}
|
|
335
|
+
for (let caseIndex = 0; caseIndex < caseNames.length; caseIndex++) {
|
|
336
|
+
const caseName = caseNames[caseIndex]
|
|
317
337
|
|
|
338
|
+
const values = varNames.reduce((agg, varName, varIndex) => {
|
|
339
|
+
agg[varName] = varValues[varIndex][caseIndex] || null
|
|
340
|
+
return agg
|
|
341
|
+
}, {})
|
|
318
342
|
scriptResults.push({ header: { name: caseName }, values: values })
|
|
319
|
-
}
|
|
320
|
-
|
|
343
|
+
}
|
|
344
|
+
} else {
|
|
345
|
+
const variableNames = []
|
|
346
|
+
let colindexTemp = colindex + 1
|
|
347
|
+
while (true) {
|
|
348
|
+
const variableNameCell = this.colnames[colindexTemp] + rowindex
|
|
349
|
+
if (sheet[variableNameCell] && sheet[variableNameCell].v) {
|
|
350
|
+
variableNames.push(sheet[variableNameCell].v)
|
|
351
|
+
} else {
|
|
352
|
+
break
|
|
353
|
+
}
|
|
354
|
+
colindexTemp++
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
rowindex += 1
|
|
358
|
+
while (true) {
|
|
359
|
+
const caseNameCell = this.colnames[colindex] + rowindex
|
|
360
|
+
if (sheet[caseNameCell] && sheet[caseNameCell].v) {
|
|
361
|
+
const caseName = sheet[caseNameCell].v
|
|
362
|
+
const values = {}
|
|
363
|
+
for (let i = 0; i < variableNames.length; i++) {
|
|
364
|
+
const variableValueCell = this.colnames[colindex + 1 + i] + rowindex
|
|
365
|
+
if (sheet[variableValueCell] && sheet[variableValueCell].v) {
|
|
366
|
+
values[variableNames[i]] = sheet[variableValueCell].v.toString()
|
|
367
|
+
} else {
|
|
368
|
+
values[variableNames[i]] = null
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
rowindex += 1
|
|
372
|
+
|
|
373
|
+
scriptResults.push({ header: { name: caseName }, values: values })
|
|
374
|
+
} else {
|
|
375
|
+
break
|
|
376
|
+
}
|
|
321
377
|
}
|
|
322
378
|
}
|
|
323
379
|
}
|
package/src/scripting/Convo.js
CHANGED
|
@@ -36,7 +36,7 @@ class ConvoStepAssert {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
toString () {
|
|
39
|
-
return (this.optional ? '?' : '') + (this.not ? '!' : '') + this.name + '(' + (this.args ? this.args.join(',') : 'no args') + ')'
|
|
39
|
+
return (this.optional ? '?' : '') + (this.not ? '!' : '') + this.name + '(' + (this.args ? this.args.map(a => _.truncate(a, { length: 200 })).join(',') : 'no args') + ')'
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -47,7 +47,7 @@ class ConvoStepLogicHook {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
toString () {
|
|
50
|
-
return this.name + '(' + (this.args ? this.args.join(',') : 'no args') + ')'
|
|
50
|
+
return this.name + '(' + (this.args ? this.args.map(a => _.truncate(a, { length: 200 })).join(',') : 'no args') + ')'
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -58,7 +58,7 @@ class ConvoStepUserInput {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
toString () {
|
|
61
|
-
return this.name + '(' + (this.args ? this.args.join(',') : 'no args') + ')'
|
|
61
|
+
return this.name + '(' + (this.args ? this.args.map(a => _.truncate(a, { length: 200 })).join(',') : 'no args') + ')'
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -511,7 +511,13 @@ class Convo {
|
|
|
511
511
|
}
|
|
512
512
|
}
|
|
513
513
|
transcriptStep.err = err
|
|
514
|
-
|
|
514
|
+
if (err instanceof BotiumError && container.caps[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]) {
|
|
515
|
+
if (!err.isAsserterError()) {
|
|
516
|
+
throw err
|
|
517
|
+
}
|
|
518
|
+
} else {
|
|
519
|
+
throw err
|
|
520
|
+
}
|
|
515
521
|
} finally {
|
|
516
522
|
if (convoStep.sender !== 'begin' && convoStep.sender !== 'end' && !skipTranscriptStep) {
|
|
517
523
|
transcriptStep.scriptingMemory = Object.assign({}, scriptingMemory)
|
|
@@ -526,6 +532,12 @@ class Convo {
|
|
|
526
532
|
transcript.steps = transcriptSteps.filter(s => s)
|
|
527
533
|
transcript.scriptingMemory = scriptingMemory
|
|
528
534
|
transcript.convoEnd = new Date()
|
|
535
|
+
if (container.caps[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]) {
|
|
536
|
+
const transcriptStepErrs = transcript.steps.filter(s => s.err).map(s => s.err)
|
|
537
|
+
if (transcriptStepErrs && transcriptStepErrs.length > 0) {
|
|
538
|
+
transcript.err = botiumErrorFromList([transcriptStepErrs, transcript.err].filter(e => e), {})
|
|
539
|
+
}
|
|
540
|
+
}
|
|
529
541
|
}
|
|
530
542
|
}
|
|
531
543
|
|