botium-core 1.12.3 → 1.12.6
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/LICENSES-3RDPARTY.txt +901 -751
- package/dist/botium-cjs.js +138 -71
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +138 -71
- package/dist/botium-es.js.map +1 -1
- package/package.json +21 -21
- package/src/BotDriver.js +24 -19
- package/src/Capabilities.js +1 -0
- package/src/Defaults.js +1 -0
- package/src/containers/plugins/SimpleRestContainer.js +42 -8
- package/src/containers/plugins/index.js +1 -1
- package/src/helpers/Utils.js +1 -1
- package/src/scripting/CompilerXlsx.js +2 -2
- package/src/scripting/Convo.js +7 -7
- package/src/scripting/ScriptingProvider.js +1 -1
- package/src/scripting/helper.js +20 -13
- package/src/scripting/logichook/asserter/BaseCountAsserter.js +1 -1
- package/src/scripting/logichook/asserter/ButtonsAsserter.js +4 -2
- package/src/scripting/logichook/asserter/CardsAsserter.js +4 -2
- package/test/compiler/compilertxt.spec.js +13 -0
- package/test/compiler/convos/txt/convos_args_escape.convo.txt +2 -0
- package/test/connectors/simplerest.spec.js +49 -8
- package/test/convo/convos/continuefailing_timeout.convo.txt +16 -0
- package/test/convo/transcript.spec.js +18 -1
- package/test/logichooks/convos/WAITFORBOT_INFINITE.convo.txt +1 -1
- package/test/logichooks/hookfromsrc.spec.js +1 -1
- package/test/scripting/asserters/buttonsAsserter.spec.js +47 -0
- package/test/scripting/asserters/cardsAsserter.spec.js +39 -0
- package/test/scripting/scriptingProvider.spec.js +1 -1
- package/test/scripting/txt/decompile.spec.js +24 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "botium-core",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.6",
|
|
4
4
|
"description": "The Selenium for Chatbots",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/botium-es.js",
|
|
@@ -32,25 +32,25 @@
|
|
|
32
32
|
},
|
|
33
33
|
"homepage": "https://www.botium.ai",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@babel/runtime": "^7.17.
|
|
35
|
+
"@babel/runtime": "^7.17.9",
|
|
36
36
|
"async": "^3.2.3",
|
|
37
|
-
"body-parser": "^1.
|
|
38
|
-
"boolean": "^3.
|
|
37
|
+
"body-parser": "^1.20.0",
|
|
38
|
+
"boolean": "^3.2.0",
|
|
39
39
|
"bottleneck": "^2.19.5",
|
|
40
40
|
"csv-parse": "^5.0.4",
|
|
41
|
-
"debug": "^4.3.
|
|
41
|
+
"debug": "^4.3.4",
|
|
42
42
|
"esprima": "^4.0.1",
|
|
43
|
-
"express": "^4.17.
|
|
43
|
+
"express": "^4.17.3",
|
|
44
44
|
"globby": "11.0.4",
|
|
45
|
-
"ioredis": "^
|
|
45
|
+
"ioredis": "^5.0.4",
|
|
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
50
|
"markdown-it": "^12.3.2",
|
|
51
|
-
"mime-types": "^2.1.
|
|
51
|
+
"mime-types": "^2.1.35",
|
|
52
52
|
"mkdirp": "^1.0.4",
|
|
53
|
-
"moment": "^2.29.
|
|
53
|
+
"moment": "^2.29.3",
|
|
54
54
|
"mustache": "^4.2.0",
|
|
55
55
|
"promise-retry": "^2.0.1",
|
|
56
56
|
"promise.allsettled": "^1.0.5",
|
|
@@ -62,36 +62,36 @@
|
|
|
62
62
|
"socket.io": "^4.4.1",
|
|
63
63
|
"socket.io-client": "^4.4.1",
|
|
64
64
|
"socketio-auth": "^0.1.1",
|
|
65
|
-
"swagger-jsdoc": "^6.1
|
|
65
|
+
"swagger-jsdoc": "^6.2.1",
|
|
66
66
|
"swagger-ui-express": "^4.3.0",
|
|
67
67
|
"uuid": "^8.3.2",
|
|
68
|
-
"vm2": "^3.9.
|
|
68
|
+
"vm2": "^3.9.9",
|
|
69
69
|
"write-yaml": "^1.0.0",
|
|
70
|
-
"xlsx": "^0.18.
|
|
70
|
+
"xlsx": "^0.18.5",
|
|
71
71
|
"xregexp": "^5.1.0",
|
|
72
|
-
"yaml": "^
|
|
72
|
+
"yaml": "^2.0.1"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
|
-
"@babel/core": "^7.17.
|
|
75
|
+
"@babel/core": "^7.17.9",
|
|
76
76
|
"@babel/node": "^7.16.8",
|
|
77
77
|
"@babel/plugin-transform-runtime": "^7.17.0",
|
|
78
78
|
"@babel/preset-env": "^7.16.11",
|
|
79
79
|
"chai": "^4.3.6",
|
|
80
80
|
"chai-as-promised": "^7.1.1",
|
|
81
81
|
"cross-env": "^7.0.3",
|
|
82
|
-
"eslint": "^8.
|
|
83
|
-
"eslint-config-standard": "^
|
|
84
|
-
"eslint-plugin-import": "^2.
|
|
85
|
-
"eslint-plugin-
|
|
82
|
+
"eslint": "^8.13.0",
|
|
83
|
+
"eslint-config-standard": "^17.0.0",
|
|
84
|
+
"eslint-plugin-import": "^2.26.0",
|
|
85
|
+
"eslint-plugin-n": "^15.1.0",
|
|
86
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.2.
|
|
90
|
+
"mocha": "^9.2.2",
|
|
91
91
|
"nock": "^13.2.4",
|
|
92
|
-
"npm-check-updates": "^12.
|
|
92
|
+
"npm-check-updates": "^12.5.9",
|
|
93
93
|
"nyc": "^15.1.0",
|
|
94
|
-
"rollup": "^2.
|
|
94
|
+
"rollup": "^2.70.2",
|
|
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/BotDriver.js
CHANGED
|
@@ -115,6 +115,7 @@ module.exports = class BotDriver {
|
|
|
115
115
|
this.eventEmitter.emit(Events.CONTAINER_BUILDING)
|
|
116
116
|
|
|
117
117
|
return new Promise((resolve, reject) => {
|
|
118
|
+
let tempDirectory = null
|
|
118
119
|
let repo = null
|
|
119
120
|
let container = null
|
|
120
121
|
|
|
@@ -126,9 +127,19 @@ module.exports = class BotDriver {
|
|
|
126
127
|
.catch(driverValidated)
|
|
127
128
|
},
|
|
128
129
|
|
|
130
|
+
(tempDirectoryCreated) => {
|
|
131
|
+
tempDirectory = path.resolve(process.cwd(), this.caps[Capabilities.TEMPDIR], sanitize(`${this.caps[Capabilities.PROJECTNAME]} ${moment().format('YYYYMMDD HHmmss')} ${randomize('Aa0', 5)}`))
|
|
132
|
+
try {
|
|
133
|
+
mkdirp.sync(tempDirectory)
|
|
134
|
+
tempDirectoryCreated()
|
|
135
|
+
} catch (err) {
|
|
136
|
+
tempDirectoryCreated(new Error(`Unable to create temp directory ${tempDirectory}: ${err.message}`))
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
|
|
129
140
|
(repoValidated) => {
|
|
130
141
|
try {
|
|
131
|
-
repo = this._getRepo()
|
|
142
|
+
repo = this._getRepo(tempDirectory)
|
|
132
143
|
} catch (err) {
|
|
133
144
|
return repoValidated(err)
|
|
134
145
|
}
|
|
@@ -141,7 +152,7 @@ module.exports = class BotDriver {
|
|
|
141
152
|
|
|
142
153
|
(containerValidated) => {
|
|
143
154
|
try {
|
|
144
|
-
container = this._getContainer(repo)
|
|
155
|
+
container = this._getContainer(tempDirectory, repo)
|
|
145
156
|
} catch (err) {
|
|
146
157
|
return containerValidated(err)
|
|
147
158
|
}
|
|
@@ -156,9 +167,9 @@ module.exports = class BotDriver {
|
|
|
156
167
|
if (err) {
|
|
157
168
|
debug(`BotDriver Build error: ${err}`)
|
|
158
169
|
this.eventEmitter.emit(Events.CONTAINER_BUILD_ERROR, err)
|
|
159
|
-
if (
|
|
160
|
-
rimraf(
|
|
161
|
-
if (err) debug(`Cleanup temp dir ${
|
|
170
|
+
if (tempDirectory) {
|
|
171
|
+
rimraf(tempDirectory, (err) => {
|
|
172
|
+
if (err) debug(`Cleanup temp dir ${tempDirectory} failed: ${util.inspect(err)}`)
|
|
162
173
|
})
|
|
163
174
|
}
|
|
164
175
|
return reject(err)
|
|
@@ -311,12 +322,6 @@ module.exports = class BotDriver {
|
|
|
311
322
|
throw new Error(`Capability '${Capabilities.CONTAINERMODE}' or '${Capabilities.BOTIUMGRIDURL}' missing`)
|
|
312
323
|
}
|
|
313
324
|
|
|
314
|
-
this.tempDirectory = path.resolve(process.cwd(), this.caps[Capabilities.TEMPDIR], sanitize(`${this.caps[Capabilities.PROJECTNAME]} ${moment().format('YYYYMMDD HHmmss')} ${randomize('Aa0', 5)}`))
|
|
315
|
-
try {
|
|
316
|
-
mkdirp.sync(this.tempDirectory)
|
|
317
|
-
} catch (err) {
|
|
318
|
-
throw new Error(`Unable to create temp directory ${this.tempDirectory}: ${err}`)
|
|
319
|
-
}
|
|
320
325
|
resolve(this)
|
|
321
326
|
} catch (err) {
|
|
322
327
|
reject(err)
|
|
@@ -324,35 +329,35 @@ module.exports = class BotDriver {
|
|
|
324
329
|
})
|
|
325
330
|
}
|
|
326
331
|
|
|
327
|
-
_getRepo () {
|
|
332
|
+
_getRepo (tempDirectory) {
|
|
328
333
|
if (this.caps[Capabilities.BOTIUMGRIDURL]) {
|
|
329
334
|
const NoRepo = require('./repos/NoRepo')
|
|
330
|
-
return new NoRepo(
|
|
335
|
+
return new NoRepo(tempDirectory, this.sources)
|
|
331
336
|
}
|
|
332
337
|
if (this.sources[Source.GITURL]) {
|
|
333
338
|
const GitRepo = require('./repos/GitRepo')
|
|
334
|
-
return new GitRepo(
|
|
339
|
+
return new GitRepo(tempDirectory, this.sources)
|
|
335
340
|
}
|
|
336
341
|
if (this.sources[Source.LOCALPATH]) {
|
|
337
342
|
const LocalRepo = require('./repos/LocalRepo')
|
|
338
|
-
return new LocalRepo(
|
|
343
|
+
return new LocalRepo(tempDirectory, this.sources)
|
|
339
344
|
}
|
|
340
345
|
throw new Error(`No Repo provider found for Sources ${util.inspect(this.sources)}`)
|
|
341
346
|
}
|
|
342
347
|
|
|
343
|
-
_getContainer (repo) {
|
|
348
|
+
_getContainer (tempDirectory, repo) {
|
|
344
349
|
if (this.caps[Capabilities.BOTIUMGRIDURL]) {
|
|
345
350
|
const GridContainer = require('./containers/GridContainer')
|
|
346
|
-
return new GridContainer(this.eventEmitter,
|
|
351
|
+
return new GridContainer(this.eventEmitter, tempDirectory, repo, this.caps, this.envs)
|
|
347
352
|
}
|
|
348
353
|
if (!this.caps[Capabilities.CONTAINERMODE]) {
|
|
349
354
|
throw new Error(`Capability '${Capabilities.CONTAINERMODE}' missing`)
|
|
350
355
|
}
|
|
351
356
|
if (this.caps[Capabilities.CONTAINERMODE] === 'inprocess') {
|
|
352
357
|
const InProcessContainer = require('./containers/InProcessContainer')
|
|
353
|
-
return new InProcessContainer(this.eventEmitter,
|
|
358
|
+
return new InProcessContainer(this.eventEmitter, tempDirectory, repo, this.caps, this.envs)
|
|
354
359
|
}
|
|
355
360
|
const PluginConnectorContainer = require('./containers/PluginConnectorContainer')
|
|
356
|
-
return new PluginConnectorContainer(this.eventEmitter,
|
|
361
|
+
return new PluginConnectorContainer(this.eventEmitter, tempDirectory, repo, this.caps, this.envs)
|
|
357
362
|
}
|
|
358
363
|
}
|
package/src/Capabilities.js
CHANGED
|
@@ -91,6 +91,7 @@ module.exports = {
|
|
|
91
91
|
SIMPLEREST_REDIS_TOPIC: 'SIMPLEREST_REDIS_TOPIC',
|
|
92
92
|
SIMPLEREST_INBOUND_ORDER_UNSETTLED_EVENTS_JSONPATH: 'SIMPLEREST_INBOUND_ORDER_UNSETTLED_EVENTS_JSONPATH',
|
|
93
93
|
SIMPLEREST_INBOUND_DEBOUNCE_TIMEOUT: 'SIMPLEREST_INBOUND_DEBOUNCE_TIMEOUT',
|
|
94
|
+
SIMPLEREST_COOKIE_REPLICATION: 'SIMPLEREST_COOKIE_REPLICATION',
|
|
94
95
|
// Script Compiler
|
|
95
96
|
SCRIPTING_TXT_EOL: 'SCRIPTING_TXT_EOL',
|
|
96
97
|
// ROW_PER_MESSAGE or QUESTION_ANSWER
|
package/src/Defaults.js
CHANGED
|
@@ -34,6 +34,7 @@ module.exports = {
|
|
|
34
34
|
[Capabilities.SIMPLEREST_STRICT_SSL]: true,
|
|
35
35
|
[Capabilities.SIMPLEREST_INBOUND_UPDATE_CONTEXT]: true,
|
|
36
36
|
[Capabilities.SIMPLEREST_CONTEXT_MERGE_OR_REPLACE]: 'MERGE',
|
|
37
|
+
[Capabilities.SIMPLEREST_COOKIE_REPLICATION]: true,
|
|
37
38
|
[Capabilities.SCRIPTING_TXT_EOL]: '\n',
|
|
38
39
|
[Capabilities.SCRIPTING_XLSX_EOL_WRITE]: '\r\n',
|
|
39
40
|
[Capabilities.SCRIPTING_XLSX_HASHEADERS]: true,
|
|
@@ -28,6 +28,7 @@ module.exports = class SimpleRestContainer {
|
|
|
28
28
|
this.bottleneck = bottleneck || ((fn) => fn())
|
|
29
29
|
this.processInbound = false
|
|
30
30
|
this.redisTopic = this.caps[Capabilities.SIMPLEREST_REDIS_TOPIC] || 'SIMPLEREST_INBOUND_SUBSCRIPTION'
|
|
31
|
+
this.cookies = {}
|
|
31
32
|
|
|
32
33
|
if (this.caps[Capabilities.SIMPLEREST_INBOUND_ORDER_UNSETTLED_EVENTS_JSONPATH]) {
|
|
33
34
|
const debounceTimeout = this.caps[Capabilities.SIMPLEREST_INBOUND_DEBOUNCE_TIMEOUT] || 500
|
|
@@ -451,7 +452,7 @@ module.exports = class SimpleRestContainer {
|
|
|
451
452
|
|
|
452
453
|
if (body) {
|
|
453
454
|
debug(`got response code: ${response.statusCode}, body: ${botiumUtils.shortenJsonString(body)}`)
|
|
454
|
-
|
|
455
|
+
this._storeCookiesFromResponse(response)
|
|
455
456
|
try {
|
|
456
457
|
body = await this._parseResponseBody(body)
|
|
457
458
|
} catch (err) {
|
|
@@ -560,8 +561,8 @@ module.exports = class SimpleRestContainer {
|
|
|
560
561
|
}
|
|
561
562
|
}
|
|
562
563
|
this._addRequestOptions(requestOptions)
|
|
563
|
-
|
|
564
564
|
await executeHook(this.caps, this.requestHook, Object.assign({ requestOptions }, this.view))
|
|
565
|
+
this._addRequestCookies(requestOptions)
|
|
565
566
|
|
|
566
567
|
return requestOptions
|
|
567
568
|
}
|
|
@@ -593,6 +594,7 @@ module.exports = class SimpleRestContainer {
|
|
|
593
594
|
await timeout(pingConfig.timeout)
|
|
594
595
|
} else {
|
|
595
596
|
debug(`_waitForUrlResponse success on url check ${pingConfig.uri}: ${response.statusCode}/${response.statusMessage}`)
|
|
597
|
+
this._storeCookiesFromResponse(response)
|
|
596
598
|
if (debug.enabled && body) {
|
|
597
599
|
debug(botiumUtils.shortenJsonString(body))
|
|
598
600
|
}
|
|
@@ -753,9 +755,9 @@ module.exports = class SimpleRestContainer {
|
|
|
753
755
|
const timeout = this._getCapValue(Capabilities.SIMPLEREST_POLL_TIMEOUT)
|
|
754
756
|
const pollConfig = {
|
|
755
757
|
method: verb,
|
|
756
|
-
uri
|
|
758
|
+
uri,
|
|
757
759
|
followAllRedirects: true,
|
|
758
|
-
timeout
|
|
760
|
+
timeout
|
|
759
761
|
}
|
|
760
762
|
if (this.caps[Capabilities.SIMPLEREST_POLL_HEADERS]) {
|
|
761
763
|
try {
|
|
@@ -783,6 +785,8 @@ module.exports = class SimpleRestContainer {
|
|
|
783
785
|
debug(`_runPolling: exeucting request hook failed - (${err.message})`)
|
|
784
786
|
return
|
|
785
787
|
}
|
|
788
|
+
this._addRequestCookies(pollConfig)
|
|
789
|
+
|
|
786
790
|
request(pollConfig, async (err, response, body) => {
|
|
787
791
|
if (err) {
|
|
788
792
|
debug(`_runPolling: rest request failed: ${err.message}, request: ${JSON.stringify(pollConfig)}`)
|
|
@@ -794,7 +798,7 @@ module.exports = class SimpleRestContainer {
|
|
|
794
798
|
}
|
|
795
799
|
} else if (body) {
|
|
796
800
|
debug(`_runPolling: got response code: ${response.statusCode}, body: ${botiumUtils.shortenJsonString(body)}`)
|
|
797
|
-
|
|
801
|
+
this._storeCookiesFromResponse(response)
|
|
798
802
|
try {
|
|
799
803
|
body = await this._parseResponseBody(body)
|
|
800
804
|
} catch (err) {
|
|
@@ -835,9 +839,9 @@ module.exports = class SimpleRestContainer {
|
|
|
835
839
|
const timeout = this._getCapValue(`${capPrefix}_TIMEOUT`) || this._getCapValue(Capabilities.SIMPLEREST_TIMEOUT)
|
|
836
840
|
const httpConfig = {
|
|
837
841
|
method: verb,
|
|
838
|
-
uri
|
|
842
|
+
uri,
|
|
839
843
|
followAllRedirects: true,
|
|
840
|
-
timeout
|
|
844
|
+
timeout
|
|
841
845
|
}
|
|
842
846
|
if (this.caps[`${capPrefix}_HEADERS`]) {
|
|
843
847
|
try {
|
|
@@ -856,8 +860,8 @@ module.exports = class SimpleRestContainer {
|
|
|
856
860
|
}
|
|
857
861
|
}
|
|
858
862
|
this._addRequestOptions(httpConfig)
|
|
859
|
-
|
|
860
863
|
await executeHook(this.caps, this.requestHooks[capPrefix], Object.assign({ requestOptions: httpConfig }, this.view))
|
|
864
|
+
this._addRequestCookies(httpConfig)
|
|
861
865
|
|
|
862
866
|
const retries = this._getCapValue(`${capPrefix}_RETRIES`)
|
|
863
867
|
debug(`_makeCall(${capPrefix}): rest request: ${JSON.stringify(httpConfig)}`)
|
|
@@ -874,4 +878,34 @@ module.exports = class SimpleRestContainer {
|
|
|
874
878
|
_.merge(httpConfig, this.caps[Capabilities.SIMPLEREST_EXTRA_OPTIONS])
|
|
875
879
|
}
|
|
876
880
|
}
|
|
881
|
+
|
|
882
|
+
_addRequestCookies (requestOptions) {
|
|
883
|
+
if (!this.caps[Capabilities.SIMPLEREST_COOKIE_REPLICATION] || !requestOptions) {
|
|
884
|
+
return
|
|
885
|
+
}
|
|
886
|
+
const url = new URL(requestOptions.uri)
|
|
887
|
+
if (!requestOptions.headers) {
|
|
888
|
+
requestOptions.headers = {}
|
|
889
|
+
}
|
|
890
|
+
requestOptions.headers.Cookie = requestOptions.headers.Cookie ? `${requestOptions.headers.Cookie}; ${this.cookies[url.host]}` : this.cookies[url.host]
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
_storeCookiesFromResponse (response) {
|
|
894
|
+
if (!this.caps[Capabilities.SIMPLEREST_COOKIE_REPLICATION] || !response) {
|
|
895
|
+
return
|
|
896
|
+
}
|
|
897
|
+
const responseCookies = response.headers['set-cookie']
|
|
898
|
+
if (!responseCookies) {
|
|
899
|
+
return
|
|
900
|
+
}
|
|
901
|
+
const host = _.get(response, 'request.uri.host')
|
|
902
|
+
let cookie
|
|
903
|
+
responseCookies.forEach(cookieString => {
|
|
904
|
+
cookie = cookie ? `${cookie}; ${cookieString}` : cookieString
|
|
905
|
+
})
|
|
906
|
+
|
|
907
|
+
if (cookie) {
|
|
908
|
+
this.cookies[host] = cookie
|
|
909
|
+
}
|
|
910
|
+
}
|
|
877
911
|
}
|
package/src/helpers/Utils.js
CHANGED
|
@@ -46,7 +46,7 @@ const toJsonWeak = (stringOrNot) => {
|
|
|
46
46
|
|
|
47
47
|
const optionalJson = (json) => {
|
|
48
48
|
const body = isJson(json)
|
|
49
|
-
return body ? { 'content-type': 'application/json', body
|
|
49
|
+
return body ? { 'content-type': 'application/json', body } : { 'content-type': 'text/plain', body: json }
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
const shortenJsonString = (obj) => {
|
|
@@ -339,7 +339,7 @@ module.exports = class CompilerXlsx extends CompilerBase {
|
|
|
339
339
|
agg[varName] = varValues[varIndex][caseIndex] || null
|
|
340
340
|
return agg
|
|
341
341
|
}, {})
|
|
342
|
-
scriptResults.push({ header: { name: caseName }, values
|
|
342
|
+
scriptResults.push({ header: { name: caseName }, values })
|
|
343
343
|
}
|
|
344
344
|
} else {
|
|
345
345
|
const variableNames = []
|
|
@@ -370,7 +370,7 @@ module.exports = class CompilerXlsx extends CompilerBase {
|
|
|
370
370
|
}
|
|
371
371
|
rowindex += 1
|
|
372
372
|
|
|
373
|
-
scriptResults.push({ header: { name: caseName }, values
|
|
373
|
+
scriptResults.push({ header: { name: caseName }, values })
|
|
374
374
|
} else {
|
|
375
375
|
break
|
|
376
376
|
}
|
package/src/scripting/Convo.js
CHANGED
|
@@ -235,14 +235,14 @@ class Convo {
|
|
|
235
235
|
await this.runConversation(container, scriptingMemory, transcript)
|
|
236
236
|
await this._checkBotRepliesConsumed(container)
|
|
237
237
|
try {
|
|
238
|
-
await this.scriptingEvents.onConvoEnd({ convo: this, convoStep: { stepTag: '#end' }, container, transcript, scriptingMemory
|
|
238
|
+
await this.scriptingEvents.onConvoEnd({ convo: this, convoStep: { stepTag: '#end' }, container, transcript, scriptingMemory })
|
|
239
239
|
} catch (err) {
|
|
240
240
|
throw new TranscriptError(botiumErrorFromErr(`${this.header.name}: ${err.message}`, err), transcript)
|
|
241
241
|
}
|
|
242
242
|
if (transcript.err && container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS]) {
|
|
243
243
|
let assertConvoEndErr = null
|
|
244
244
|
try {
|
|
245
|
-
await this.scriptingEvents.assertConvoEnd({ convo: this, convoStep: { stepTag: '#end' }, container, transcript, scriptingMemory
|
|
245
|
+
await this.scriptingEvents.assertConvoEnd({ convo: this, convoStep: { stepTag: '#end' }, container, transcript, scriptingMemory })
|
|
246
246
|
} catch (err) {
|
|
247
247
|
assertConvoEndErr = botiumErrorFromErr(`${this.header.name}: ${err.message}`, err)
|
|
248
248
|
}
|
|
@@ -257,7 +257,7 @@ class Convo {
|
|
|
257
257
|
throw new TranscriptError(transcript.err, transcript)
|
|
258
258
|
}
|
|
259
259
|
try {
|
|
260
|
-
await this.scriptingEvents.assertConvoEnd({ convo: this, convoStep: { stepTag: '#end' }, container, transcript, scriptingMemory
|
|
260
|
+
await this.scriptingEvents.assertConvoEnd({ convo: this, convoStep: { stepTag: '#end' }, container, transcript, scriptingMemory })
|
|
261
261
|
} catch (err) {
|
|
262
262
|
transcript.err = botiumErrorFromErr(`${this.header.name}: ${err.message}`, err)
|
|
263
263
|
throw new TranscriptError(transcript.err, transcript)
|
|
@@ -307,9 +307,9 @@ class Convo {
|
|
|
307
307
|
transcriptStep.actual = meMsg
|
|
308
308
|
|
|
309
309
|
try {
|
|
310
|
-
await this.scriptingEvents.setUserInput({ convo: this, convoStep, container, scriptingMemory, meMsg, transcript, transcriptStep })
|
|
311
|
-
await this.scriptingEvents.onMeStart({ convo: this, convoStep, container, scriptingMemory, meMsg, transcript, transcriptStep })
|
|
312
|
-
await this.scriptingEvents.onMePrepare({ convo: this, convoStep, container, scriptingMemory, meMsg, transcript, transcriptStep })
|
|
310
|
+
await this.scriptingEvents.setUserInput({ convo: this, convoStep, container, scriptingMemory, meMsg, transcript, transcriptStep, transcriptSteps })
|
|
311
|
+
await this.scriptingEvents.onMeStart({ convo: this, convoStep, container, scriptingMemory, meMsg, transcript, transcriptStep, transcriptSteps })
|
|
312
|
+
await this.scriptingEvents.onMePrepare({ convo: this, convoStep, container, scriptingMemory, meMsg, transcript, transcriptStep, transcriptSteps })
|
|
313
313
|
|
|
314
314
|
await this._checkBotRepliesConsumed(container)
|
|
315
315
|
|
|
@@ -535,7 +535,7 @@ class Convo {
|
|
|
535
535
|
if (container.caps[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]) {
|
|
536
536
|
const transcriptStepErrs = transcript.steps.filter(s => s.err).map(s => s.err)
|
|
537
537
|
if (transcriptStepErrs && transcriptStepErrs.length > 0) {
|
|
538
|
-
transcript.err = botiumErrorFromList([transcriptStepErrs, transcript.err].filter(e => e), {})
|
|
538
|
+
transcript.err = botiumErrorFromList([...transcriptStepErrs.filter(err => err !== transcript.err), transcript.err].filter(e => e), {})
|
|
539
539
|
}
|
|
540
540
|
}
|
|
541
541
|
}
|
|
@@ -1192,7 +1192,7 @@ module.exports = class ScriptingProvider {
|
|
|
1192
1192
|
const node = {
|
|
1193
1193
|
sender: convoNode.sender,
|
|
1194
1194
|
key: randomize('0', 20),
|
|
1195
|
-
hash
|
|
1195
|
+
hash,
|
|
1196
1196
|
convoNodes: convoNodeValues,
|
|
1197
1197
|
convos: [_.cloneDeep(convoNodeHeader)],
|
|
1198
1198
|
childNodes: []
|
package/src/scripting/helper.js
CHANGED
|
@@ -77,6 +77,13 @@ const flatString = (str) => {
|
|
|
77
77
|
return str ? str.split('\n').map(s => s.trim()).join(' ') : ''
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
const _formatAppendArgs = (args) => {
|
|
81
|
+
return args ? ` ${args.map(a => _.isString(a) ? a.replace(/\|/g, '\\|') : `${a}`).join('|')}` : ''
|
|
82
|
+
}
|
|
83
|
+
const _parseArgs = (str) => {
|
|
84
|
+
return (str && str.length > 0 && str.replace(/\\\|/g, '###ESCAPESPLIT###').split('|').map(s => s.replace(/###ESCAPESPLIT###/g, '|').trim())) || []
|
|
85
|
+
}
|
|
86
|
+
|
|
80
87
|
const linesToConvoStep = (lines, sender, context, eol, singleLineMode = false) => {
|
|
81
88
|
if (!validateSender(sender)) throw new Error(`Failed to parse conversation. Section "${sender}" unknown.`)
|
|
82
89
|
|
|
@@ -106,14 +113,14 @@ const linesToConvoStep = (lines, sender, context, eol, singleLineMode = false) =
|
|
|
106
113
|
}
|
|
107
114
|
const name = logicLine.split(' ')[0]
|
|
108
115
|
if (sender !== 'me' && context.IsAsserterValid(name)) {
|
|
109
|
-
const args = (logicLine.length > name.length ? logicLine.substr(name.length + 1)
|
|
116
|
+
const args = (logicLine.length > name.length ? _parseArgs(logicLine.substr(name.length + 1)) : [])
|
|
110
117
|
convoStep.asserters.push({ name, args, not, optional })
|
|
111
118
|
} else if (sender === 'me' && context.IsUserInputValid(name)) {
|
|
112
|
-
const args = (logicLine.length > name.length ? logicLine.substr(name.length + 1)
|
|
119
|
+
const args = (logicLine.length > name.length ? _parseArgs(logicLine.substr(name.length + 1)) : [])
|
|
113
120
|
convoStep.userInputs.push({ name, args })
|
|
114
121
|
textLinesAccepted = false
|
|
115
122
|
} else if (context.IsLogicHookValid(name)) {
|
|
116
|
-
const args = (logicLine.length > name.length ? logicLine.substr(name.length + 1)
|
|
123
|
+
const args = (logicLine.length > name.length ? _parseArgs(logicLine.substr(name.length + 1)) : [])
|
|
117
124
|
convoStep.logicHooks.push({ name, args })
|
|
118
125
|
textLinesAccepted = false
|
|
119
126
|
} else {
|
|
@@ -422,7 +429,7 @@ const convoStepToLines = (step) => {
|
|
|
422
429
|
const lines = []
|
|
423
430
|
if (step.sender === 'me') {
|
|
424
431
|
step.forms && step.forms.filter(form => form.value).forEach((form) => {
|
|
425
|
-
lines.push(`FORM
|
|
432
|
+
lines.push(`FORM${_formatAppendArgs([form.name, form.value])}`)
|
|
426
433
|
})
|
|
427
434
|
if (step.buttons && step.buttons.length > 0) {
|
|
428
435
|
lines.push('BUTTON ' + _decompileButton(step.buttons[0]))
|
|
@@ -432,34 +439,34 @@ const convoStepToLines = (step) => {
|
|
|
432
439
|
lines.push(step.messageText)
|
|
433
440
|
}
|
|
434
441
|
step.userInputs && step.userInputs.forEach((userInput) => {
|
|
435
|
-
lines.push(userInput.name + (userInput.args
|
|
442
|
+
lines.push(userInput.name + _formatAppendArgs(userInput.args))
|
|
436
443
|
})
|
|
437
444
|
step.logicHooks && step.logicHooks.forEach((logicHook) => {
|
|
438
|
-
lines.push(logicHook.name + (logicHook.args
|
|
445
|
+
lines.push(logicHook.name + _formatAppendArgs(logicHook.args))
|
|
439
446
|
})
|
|
440
447
|
} else {
|
|
441
448
|
if (step.messageText) {
|
|
442
449
|
lines.push((step.optional ? '?' : '') + (step.not ? '!' : '') + step.messageText)
|
|
443
450
|
}
|
|
444
|
-
if (step.buttons && step.buttons.length > 0) lines.push('BUTTONS
|
|
445
|
-
if (step.media && step.media.length > 0) lines.push('MEDIA
|
|
451
|
+
if (step.buttons && step.buttons.length > 0) lines.push('BUTTONS' + _formatAppendArgs(step.buttons.filter(b => b.text).map(b => flatString(b.text))))
|
|
452
|
+
if (step.media && step.media.length > 0) lines.push('MEDIA' + _formatAppendArgs(step.media.filter(m => !m.buffer && m.mediaUri).map(m => m.mediaUri)))
|
|
446
453
|
if (step.cards && step.cards.length > 0) {
|
|
447
454
|
step.cards.forEach(c => {
|
|
448
455
|
let cardTexts = []
|
|
449
456
|
if (c.text) cardTexts = cardTexts.concat(_.isArray(c.text) ? c.text : [c.text])
|
|
450
457
|
if (c.subtext) cardTexts = cardTexts.concat(_.isArray(c.subtext) ? c.subtext : [c.subtext])
|
|
451
458
|
if (c.content) cardTexts = cardTexts.concat(_.isArray(c.content) ? c.content : [c.content])
|
|
452
|
-
if (cardTexts.length > 0) lines.push('CARDS
|
|
459
|
+
if (cardTexts.length > 0) lines.push('CARDS' + _formatAppendArgs(cardTexts.map(c => flatString(c))))
|
|
453
460
|
|
|
454
|
-
if (c.buttons && c.buttons.length > 0) lines.push('BUTTONS
|
|
461
|
+
if (c.buttons && c.buttons.length > 0) lines.push('BUTTONS' + _formatAppendArgs(c.buttons.filter(b => b.text).map(b => flatString(b.text))))
|
|
455
462
|
if (c.image && !c.image.buffer && c.image.mediaUri) lines.push('MEDIA ' + c.image.mediaUri)
|
|
456
463
|
})
|
|
457
464
|
}
|
|
458
465
|
step.asserters && step.asserters.forEach((asserter) => {
|
|
459
|
-
lines.push((asserter.optional ? '?' : '') + (asserter.not ? '!' : '') + asserter.name + (asserter.args
|
|
466
|
+
lines.push((asserter.optional ? '?' : '') + (asserter.not ? '!' : '') + asserter.name + _formatAppendArgs(asserter.args))
|
|
460
467
|
})
|
|
461
468
|
step.logicHooks && step.logicHooks.forEach((logicHook) => {
|
|
462
|
-
lines.push(logicHook.name + (logicHook.args
|
|
469
|
+
lines.push(logicHook.name + _formatAppendArgs(logicHook.args))
|
|
463
470
|
})
|
|
464
471
|
}
|
|
465
472
|
return lines.map(l => l.trim())
|
|
@@ -494,7 +501,7 @@ const linesToScriptingMemories = (lines, columnMode = null) => {
|
|
|
494
501
|
agg[varName] = varValues[varIndex][caseIndex] || null
|
|
495
502
|
return agg
|
|
496
503
|
}, {})
|
|
497
|
-
const scriptingMemory = { header: { name: caseName }, values
|
|
504
|
+
const scriptingMemory = { header: { name: caseName }, values }
|
|
498
505
|
scriptingMemories.push(scriptingMemory)
|
|
499
506
|
}
|
|
500
507
|
} else {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
const { SCRIPTING_NORMALIZE_TEXT } = require('../../../Capabilities')
|
|
1
2
|
const { BotiumError } = require('../../BotiumError')
|
|
2
3
|
const { buttonsFromMsg } = require('../helpers')
|
|
4
|
+
const { normalizeText } = require('../../helper')
|
|
3
5
|
|
|
4
6
|
module.exports = class ButtonsAsserter {
|
|
5
7
|
constructor (context, caps = {}) {
|
|
@@ -9,14 +11,14 @@ module.exports = class ButtonsAsserter {
|
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
_evalButtons (args, botMsg) {
|
|
12
|
-
const allButtons = buttonsFromMsg(botMsg, true).map(b => b.text)
|
|
14
|
+
const allButtons = buttonsFromMsg(botMsg, true).map(b => b.text).filter(b => b).map(b => normalizeText(b, !!this.caps[SCRIPTING_NORMALIZE_TEXT]))
|
|
13
15
|
if (!args || args.length === 0) {
|
|
14
16
|
return { allButtons, buttonsNotFound: [], buttonsFound: allButtons }
|
|
15
17
|
}
|
|
16
18
|
const buttonsNotFound = []
|
|
17
19
|
const buttonsFound = []
|
|
18
20
|
for (let i = 0; i < (args || []).length; i++) {
|
|
19
|
-
if (allButtons.findIndex(b => this.context.Match(b, args[i])) < 0) {
|
|
21
|
+
if (allButtons.findIndex(b => this.context.Match(b, normalizeText(args[i], !!this.caps[SCRIPTING_NORMALIZE_TEXT]))) < 0) {
|
|
20
22
|
buttonsNotFound.push(args[i])
|
|
21
23
|
} else {
|
|
22
24
|
buttonsFound.push(args[i])
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
const { SCRIPTING_NORMALIZE_TEXT } = require('../../../Capabilities')
|
|
1
2
|
const { BotiumError } = require('../../BotiumError')
|
|
2
3
|
const { cardsFromMsg } = require('../helpers')
|
|
4
|
+
const { normalizeText } = require('../../helper')
|
|
3
5
|
|
|
4
6
|
module.exports = class CardsAsserter {
|
|
5
7
|
constructor (context, caps = {}) {
|
|
@@ -9,14 +11,14 @@ module.exports = class CardsAsserter {
|
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
_evalCards (args, botMsg) {
|
|
12
|
-
const allCards = cardsFromMsg(botMsg, true).reduce((acc, mc) => acc.concat([mc.text, mc.subtext, mc.content].filter(t => t)), [])
|
|
14
|
+
const allCards = cardsFromMsg(botMsg, true).reduce((acc, mc) => acc.concat([mc.text, mc.subtext, mc.content].filter(t => t).map(t => normalizeText(t, !!this.caps[SCRIPTING_NORMALIZE_TEXT]))), [])
|
|
13
15
|
if (!args || args.length === 0) {
|
|
14
16
|
return { allCards, cardsNotFound: [], cardsFound: allCards }
|
|
15
17
|
}
|
|
16
18
|
const cardsNotFound = []
|
|
17
19
|
const cardsFound = []
|
|
18
20
|
for (let i = 0; i < (args || []).length; i++) {
|
|
19
|
-
if (allCards.findIndex(c => this.context.Match(c, args[i])) < 0) {
|
|
21
|
+
if (allCards.findIndex(c => this.context.Match(c, normalizeText(args[i], !!this.caps[SCRIPTING_NORMALIZE_TEXT]))) < 0) {
|
|
20
22
|
cardsNotFound.push(args[i])
|
|
21
23
|
} else {
|
|
22
24
|
cardsFound.push(args[i])
|
|
@@ -308,5 +308,18 @@ describe('compiler.compilertxt', function () {
|
|
|
308
308
|
assert.equal(convo.conversation[0].asserters.length, 1)
|
|
309
309
|
assert.deepEqual(convo.conversation[0].asserters[0], { name: 'BUTTONS', args: ['Test1', 'Test2'], not: true, optional: false })
|
|
310
310
|
})
|
|
311
|
+
it('should allow escape pipe for args', async function () {
|
|
312
|
+
const scriptBuffer = fs.readFileSync(path.resolve(__dirname, CONVOS_DIR, 'convos_args_escape.convo.txt'))
|
|
313
|
+
const context = buildContextWithPause()
|
|
314
|
+
const caps = {
|
|
315
|
+
}
|
|
316
|
+
const compiler = new Compiler(context, Object.assign({}, DefaultCapabilities, caps))
|
|
317
|
+
|
|
318
|
+
compiler.Compile(scriptBuffer, 'SCRIPTING_TYPE_CONVO')
|
|
319
|
+
const convo = context.convos[0]
|
|
320
|
+
assert.equal(convo.conversation.length, 1)
|
|
321
|
+
assert.equal(convo.conversation[0].asserters.length, 1)
|
|
322
|
+
assert.deepEqual(convo.conversation[0].asserters[0], { name: 'BUTTONS', args: ['Test|1', 'Test|2'], not: false, optional: false })
|
|
323
|
+
})
|
|
311
324
|
})
|
|
312
325
|
})
|