botium-core 1.12.0 → 1.12.1
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 +290 -115
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +281 -107
- package/dist/botium-es.js.map +1 -1
- package/index.js +1 -0
- package/package.json +21 -21
- package/src/Capabilities.js +3 -0
- package/src/Defaults.js +1 -0
- package/src/Enums.js +6 -0
- package/src/scripting/BotiumError.js +21 -0
- 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/logichooks/ClearQueueLogicHook.js +1 -1
- package/src/scripting/logichook/userinput/MediaInput.js +14 -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,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "botium-core",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.1",
|
|
4
4
|
"description": "The Selenium for Chatbots",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/botium-es.js",
|
|
@@ -32,22 +32,22 @@
|
|
|
32
32
|
},
|
|
33
33
|
"homepage": "https://www.botium.ai",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@babel/runtime": "^7.16.
|
|
36
|
-
"async": "^3.2.
|
|
35
|
+
"@babel/runtime": "^7.16.7",
|
|
36
|
+
"async": "^3.2.3",
|
|
37
37
|
"body-parser": "^1.19.1",
|
|
38
38
|
"boolean": "^3.1.4",
|
|
39
39
|
"bottleneck": "^2.19.5",
|
|
40
|
-
"csv-parse": "^5.0.
|
|
40
|
+
"csv-parse": "^5.0.4",
|
|
41
41
|
"debug": "^4.3.3",
|
|
42
42
|
"esprima": "^4.0.1",
|
|
43
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.3.
|
|
50
|
+
"markdown-it": "^12.3.2",
|
|
51
51
|
"mime-types": "^2.1.34",
|
|
52
52
|
"mkdirp": "^1.0.4",
|
|
53
53
|
"moment": "^2.29.1",
|
|
@@ -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.4.
|
|
63
|
-
"socket.io-client": "^4.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
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.2.
|
|
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",
|
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',
|
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
|
@@ -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
|
|
|
@@ -761,6 +761,7 @@ module.exports = class ScriptingProvider {
|
|
|
761
761
|
|
|
762
762
|
debug(`ExpandScriptingMemoryToConvos - ${convosExpandedAll.length} convo expanded, added to convos (${this.convos.length}). Result ${convosExpandedAll.length + this.convos.length} convo`)
|
|
763
763
|
this.convos = this.convos.concat(convosExpandedAll)
|
|
764
|
+
this._sortConvos()
|
|
764
765
|
}
|
|
765
766
|
|
|
766
767
|
ExpandUtterancesToConvos ({ useNameAsIntent, incomprehensionUtt } = {}) {
|
|
@@ -796,6 +797,11 @@ module.exports = class ScriptingProvider {
|
|
|
796
797
|
conversation: [
|
|
797
798
|
{
|
|
798
799
|
sender: 'me',
|
|
800
|
+
logicHooks: [
|
|
801
|
+
{
|
|
802
|
+
name: 'SKIP_BOT_UNCONSUMED'
|
|
803
|
+
}
|
|
804
|
+
],
|
|
799
805
|
messageText: utt.name,
|
|
800
806
|
stepTag: 'Step 1 - tell utterance'
|
|
801
807
|
},
|
package/src/scripting/helper.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const _ = require('lodash')
|
|
2
2
|
const isJSON = require('is-json')
|
|
3
3
|
|
|
4
|
+
const { E_SCRIPTING_MEMORY_COLUMN_MODE } = require('../Enums')
|
|
5
|
+
|
|
4
6
|
const normalizeText = (str, doCleanup) => {
|
|
5
7
|
if (str && _.isArray(str)) {
|
|
6
8
|
str = str.join(' ')
|
|
@@ -463,6 +465,56 @@ const convoStepToLines = (step) => {
|
|
|
463
465
|
return lines.map(l => l.trim())
|
|
464
466
|
}
|
|
465
467
|
|
|
468
|
+
const linesToScriptingMemories = (lines, columnMode = null) => {
|
|
469
|
+
const guessScriptingMemoryColumnMode = (lines) => {
|
|
470
|
+
if (lines && lines.length > 1) {
|
|
471
|
+
if (lines[1].trim().startsWith('$')) return E_SCRIPTING_MEMORY_COLUMN_MODE.TESTCASENAMES
|
|
472
|
+
}
|
|
473
|
+
return E_SCRIPTING_MEMORY_COLUMN_MODE.VARNAMES
|
|
474
|
+
}
|
|
475
|
+
columnMode = columnMode || guessScriptingMemoryColumnMode(lines)
|
|
476
|
+
|
|
477
|
+
const scriptingMemories = []
|
|
478
|
+
|
|
479
|
+
if (columnMode === E_SCRIPTING_MEMORY_COLUMN_MODE.TESTCASENAMES) {
|
|
480
|
+
const caseNames = lines[0].split('|').map((name) => name.trim()).slice(1)
|
|
481
|
+
|
|
482
|
+
const varNames = []
|
|
483
|
+
const varValues = []
|
|
484
|
+
for (let row = 1; row < lines.length; row++) {
|
|
485
|
+
if (!lines[row] || lines[row].length === 0) continue
|
|
486
|
+
const rawRow = lines[row].split('|').map((name) => name.trim())
|
|
487
|
+
varNames.push(rawRow[0])
|
|
488
|
+
varValues.push(rawRow.slice(1))
|
|
489
|
+
}
|
|
490
|
+
for (let caseIndex = 0; caseIndex < caseNames.length; caseIndex++) {
|
|
491
|
+
const caseName = caseNames[caseIndex]
|
|
492
|
+
|
|
493
|
+
const values = varNames.reduce((agg, varName, varIndex) => {
|
|
494
|
+
agg[varName] = varValues[varIndex][caseIndex] || null
|
|
495
|
+
return agg
|
|
496
|
+
}, {})
|
|
497
|
+
const scriptingMemory = { header: { name: caseName }, values: values }
|
|
498
|
+
scriptingMemories.push(scriptingMemory)
|
|
499
|
+
}
|
|
500
|
+
} else {
|
|
501
|
+
const varNames = lines[0].split('|').map((name) => name.trim()).slice(1)
|
|
502
|
+
for (let row = 1; row < lines.length; row++) {
|
|
503
|
+
if (!lines[row] || lines[row].length === 0) continue
|
|
504
|
+
const rawRow = lines[row].split('|').map((name) => name.trim())
|
|
505
|
+
const caseName = rawRow[0]
|
|
506
|
+
const values = rawRow.slice(1)
|
|
507
|
+
const varValues = {}
|
|
508
|
+
for (let varIndex = 0; varIndex < varNames.length; varIndex++) {
|
|
509
|
+
varValues[varNames[varIndex]] = values[varIndex]
|
|
510
|
+
}
|
|
511
|
+
const scriptingMemory = { header: { name: caseName }, values: varValues }
|
|
512
|
+
scriptingMemories.push(scriptingMemory)
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return scriptingMemories
|
|
516
|
+
}
|
|
517
|
+
|
|
466
518
|
module.exports = {
|
|
467
519
|
normalizeText,
|
|
468
520
|
splitStringInNonEmptyLines,
|
|
@@ -475,5 +527,6 @@ module.exports = {
|
|
|
475
527
|
convoStepToObject,
|
|
476
528
|
validSenders,
|
|
477
529
|
validateSender,
|
|
478
|
-
validateConvo
|
|
530
|
+
validateConvo,
|
|
531
|
+
linesToScriptingMemories
|
|
479
532
|
}
|
|
@@ -20,6 +20,9 @@ module.exports = class MediaInput {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
_getResolvedUri (uri, convo) {
|
|
23
|
+
if (uri.startsWith('data:')) {
|
|
24
|
+
return new url.URL(uri)
|
|
25
|
+
}
|
|
23
26
|
if (this.globalArgs && this.globalArgs.baseUris) {
|
|
24
27
|
const baseUrisSelector = _.get(convo, this.globalArgs.baseSelector || DEFAULT_BASE_SELECTOR)
|
|
25
28
|
if (baseUrisSelector && this.globalArgs.baseUris[baseUrisSelector]) {
|
|
@@ -134,6 +137,8 @@ module.exports = class MediaInput {
|
|
|
134
137
|
}
|
|
135
138
|
})
|
|
136
139
|
})
|
|
140
|
+
} else if (uri.protocol === 'data:') {
|
|
141
|
+
return Buffer.from(uri.href.split(',')[1], 'base64')
|
|
137
142
|
}
|
|
138
143
|
}
|
|
139
144
|
}
|
|
@@ -142,6 +147,13 @@ module.exports = class MediaInput {
|
|
|
142
147
|
return arg.indexOf('*') >= 0
|
|
143
148
|
}
|
|
144
149
|
|
|
150
|
+
_mime (arg) {
|
|
151
|
+
if (arg.startsWith('data:')) {
|
|
152
|
+
return arg.substring(arg.indexOf(':') + 1, arg.indexOf(';'))
|
|
153
|
+
}
|
|
154
|
+
return mime.lookup(arg)
|
|
155
|
+
}
|
|
156
|
+
|
|
145
157
|
expandConvo ({ convo, convoStep, args }) {
|
|
146
158
|
const hasWildcard = args.findIndex(a => this._isWildcard(a)) >= 0
|
|
147
159
|
|
|
@@ -187,14 +199,14 @@ module.exports = class MediaInput {
|
|
|
187
199
|
meMsg.media.push(new BotiumMockMedia({
|
|
188
200
|
mediaUri: args[0],
|
|
189
201
|
downloadUri: uri.toString(),
|
|
190
|
-
mimeType:
|
|
202
|
+
mimeType: this._mime(args[0]),
|
|
191
203
|
buffer
|
|
192
204
|
}))
|
|
193
205
|
}
|
|
194
206
|
} else if (args.length === 2) {
|
|
195
207
|
meMsg.media.push(new BotiumMockMedia({
|
|
196
208
|
mediaUri: args[0],
|
|
197
|
-
mimeType:
|
|
209
|
+
mimeType: this._mime(args[0]),
|
|
198
210
|
buffer: args[1]
|
|
199
211
|
}))
|
|
200
212
|
}
|
|
@@ -42,12 +42,25 @@ describe('convo.transcript', function () {
|
|
|
42
42
|
this.compilerMultipleAssertErrors = this.driverMultipleAssertErrors.BuildCompiler()
|
|
43
43
|
this.containerMultipleAssertErrors = await this.driverMultipleAssertErrors.Build()
|
|
44
44
|
await this.containerMultipleAssertErrors.Start()
|
|
45
|
+
|
|
46
|
+
const myCapsSkipAssertErrors = {
|
|
47
|
+
[Capabilities.PROJECTNAME]: 'convo.transcript',
|
|
48
|
+
[Capabilities.CONTAINERMODE]: echoConnector,
|
|
49
|
+
[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS]: true,
|
|
50
|
+
[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]: true
|
|
51
|
+
}
|
|
52
|
+
this.driverSkipAssertErrors = new BotDriver(myCapsSkipAssertErrors)
|
|
53
|
+
this.compilerSkipAssertErrors = this.driverSkipAssertErrors.BuildCompiler()
|
|
54
|
+
this.containerSkipAssertErrors = await this.driverSkipAssertErrors.Build()
|
|
55
|
+
await this.containerSkipAssertErrors.Start()
|
|
45
56
|
})
|
|
46
57
|
afterEach(async function () {
|
|
47
58
|
await this.container.Stop()
|
|
48
59
|
await this.container.Clean()
|
|
49
60
|
await this.containerMultipleAssertErrors.Stop()
|
|
50
61
|
await this.containerMultipleAssertErrors.Clean()
|
|
62
|
+
await this.containerSkipAssertErrors.Stop()
|
|
63
|
+
await this.containerSkipAssertErrors.Clean()
|
|
51
64
|
})
|
|
52
65
|
it('should provide transcript steps on success', async function () {
|
|
53
66
|
this.compiler.ReadScript(path.resolve(__dirname, 'convos'), '2steps.convo.txt')
|
|
@@ -347,4 +360,25 @@ describe('convo.transcript', function () {
|
|
|
347
360
|
assert.equal(this.compilerMultipleAssertErrors.convos.length, 1)
|
|
348
361
|
await this.compilerMultipleAssertErrors.convos[0].Run(this.containerMultipleAssertErrors)
|
|
349
362
|
})
|
|
363
|
+
it('should continue on failing assertion', async function () {
|
|
364
|
+
this.compilerSkipAssertErrors.ReadScript(path.resolve(__dirname, 'convos'), 'continuefailing.convo.txt')
|
|
365
|
+
assert.equal(this.compilerSkipAssertErrors.convos.length, 1)
|
|
366
|
+
|
|
367
|
+
try {
|
|
368
|
+
await this.compilerSkipAssertErrors.convos[0].Run(this.containerSkipAssertErrors)
|
|
369
|
+
assert.fail('expected error')
|
|
370
|
+
} catch (err) {
|
|
371
|
+
assert.isDefined(err.transcript)
|
|
372
|
+
assert.equal(err.transcript.steps.length, 6)
|
|
373
|
+
assert.equal(err.transcript.steps[0].actual.messageText, this.compilerSkipAssertErrors.convos[0].conversation[0].messageText)
|
|
374
|
+
assert.equal(err.transcript.steps[1].actual.messageText, this.compilerSkipAssertErrors.convos[0].conversation[1].messageText)
|
|
375
|
+
assert.equal(err.transcript.steps[2].actual.messageText, this.compilerSkipAssertErrors.convos[0].conversation[2].messageText)
|
|
376
|
+
assert.equal(err.transcript.steps[3].expected.messageText, this.compilerSkipAssertErrors.convos[0].conversation[3].messageText)
|
|
377
|
+
assert.notEqual(err.transcript.steps[3].actual.messageText, this.compilerSkipAssertErrors.convos[0].conversation[3].messageText)
|
|
378
|
+
assert.isDefined(err.transcript.steps[3].err)
|
|
379
|
+
assert.equal(err.transcript.steps[4].expected.messageText, this.compilerSkipAssertErrors.convos[0].conversation[4].messageText)
|
|
380
|
+
assert.equal(err.transcript.steps[5].expected.messageText, this.compilerSkipAssertErrors.convos[0].conversation[5].messageText)
|
|
381
|
+
assert.isNull(err.transcript.steps[5].err)
|
|
382
|
+
}
|
|
383
|
+
})
|
|
350
384
|
})
|