botium-core 1.13.18 → 1.13.19
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 +29 -6
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +29 -6
- package/dist/botium-es.js.map +1 -1
- package/package.json +2 -1
- package/src/scripting/Convo.js +17 -5
- package/src/scripting/logichook/LogicHookConsts.js +5 -1
- package/src/scripting/logichook/asserter/ButtonsAsserter.js +5 -5
- package/src/scripting/logichook/logichooks/ConditionalBusinessHoursLogicHook.js +56 -0
- package/src/scripting/logichook/logichooks/ConditionalCapabilityValueBasedLogicHook.js +37 -0
- package/src/scripting/logichook/logichooks/ConditionalJsonPathBasedLogicHook.js +31 -0
- package/src/scripting/logichook/logichooks/ConditionalTimeBasedLogicHook.js +46 -0
- package/test/scripting/logichooks/CustomConditionalLogicHook.js +21 -0
- package/test/scripting/logichooks/conditionalStepBusinessHoursLogicHook.spec.js +130 -0
- package/test/scripting/logichooks/conditionalStepCapabilityValueBasedLogicHook.spec.js +35 -0
- package/test/scripting/logichooks/conditionalStepJsonPathBasedLogicHook.spec.js +35 -0
- package/test/scripting/logichooks/conditionalStepTimeBasedLogicHook.spec.js +91 -0
- package/test/scripting/logichooks/convos/conditional_steps.convo.txt +12 -0
- package/test/scripting/logichooks/convos/conditional_steps_business_hours.convo.txt +16 -0
- package/test/scripting/logichooks/convos/conditional_steps_cap_value_based.convo.txt +12 -0
- package/test/scripting/logichooks/convos/conditional_steps_followed_by_bot_msg.convo.txt +15 -0
- package/test/scripting/logichooks/convos/conditional_steps_followed_by_me.convo.txt +18 -0
- package/test/scripting/logichooks/convos/conditional_steps_json_path_based.convo.txt.convo.txt +12 -0
- package/test/scripting/logichooks/convos/conditional_steps_multiple_condition_groups.convo.txt +20 -0
- package/test/scripting/logichooks/convos/conditional_steps_multiple_condition_groups_no_assertion.convo.txt +20 -0
- package/test/scripting/logichooks/convos/conditional_steps_time_based.convo.txt +12 -0
- package/test/scripting/logichooks/customConditionalStepLogicHook.spec.js +105 -0
- package/test/scripting/scriptingProvider.spec.js +1 -1
- package/test/scripting/logichooks/convos/custom_embedded_skip.convo.txt +0 -11
- package/test/scripting/logichooks/convos/custom_embedded_skip_followed_by_me.convo.txt +0 -11
- package/test/scripting/logichooks/convos/custom_embedded_skip_followed_by_nothing.convo.txt +0 -8
- package/test/scripting/logichooks/customEmbeddedSkip.json +0 -14
- package/test/scripting/logichooks/customEmbeddedSkip.spec.js +0 -58
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "botium-core",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.19",
|
|
4
4
|
"description": "The Selenium for Chatbots",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/botium-es.js",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"mime-types": "^2.1.35",
|
|
52
52
|
"mkdirp": "^3.0.1",
|
|
53
53
|
"moment": "^2.29.4",
|
|
54
|
+
"moment-timezone": "^0.5.43",
|
|
54
55
|
"mustache": "^4.2.0",
|
|
55
56
|
"promise-retry": "^2.0.1",
|
|
56
57
|
"promise.allsettled": "^1.0.6",
|
package/src/scripting/Convo.js
CHANGED
|
@@ -356,6 +356,7 @@ class Convo {
|
|
|
356
356
|
throw failErr
|
|
357
357
|
}
|
|
358
358
|
} else if (convoStep.sender === 'bot') {
|
|
359
|
+
const previousWaitForBotSays = waitForBotSays
|
|
359
360
|
if (waitForBotSays) {
|
|
360
361
|
botMsg = null
|
|
361
362
|
} else {
|
|
@@ -404,13 +405,24 @@ class Convo {
|
|
|
404
405
|
throw failErr
|
|
405
406
|
}
|
|
406
407
|
|
|
407
|
-
if (convoStep.
|
|
408
|
-
skipTranscriptStep = true
|
|
408
|
+
if (convoStep.conditional) {
|
|
409
409
|
const nextConvoStep = this.conversation[i + 1]
|
|
410
|
-
|
|
411
|
-
|
|
410
|
+
|
|
411
|
+
if (!previousWaitForBotSays) {
|
|
412
|
+
skipTranscriptStep = true
|
|
413
|
+
}
|
|
414
|
+
waitForBotSays = false
|
|
415
|
+
if (!nextConvoStep || nextConvoStep.sender !== 'bot' || !nextConvoStep.logicHooks || !nextConvoStep.logicHooks.some(lh => lh.name.toUpperCase().startsWith('CONDITIONAL_STEP'))) {
|
|
416
|
+
waitForBotSays = true
|
|
417
|
+
} else {
|
|
418
|
+
const conditionalLogicHook = convoStep.logicHooks.find(lh => lh.name.startsWith('CONDITIONAL_STEP'))
|
|
419
|
+
const nextConditionalLogicHook = nextConvoStep.logicHooks.find(lh => lh.name.startsWith('CONDITIONAL_STEP'))
|
|
420
|
+
waitForBotSays = conditionalLogicHook.args[1] !== nextConditionalLogicHook.args[1]
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (convoStep.conditional.skip) {
|
|
424
|
+
continue
|
|
412
425
|
}
|
|
413
|
-
continue
|
|
414
426
|
}
|
|
415
427
|
|
|
416
428
|
if (!botMsg || (!botMsg.messageText && !botMsg.media && !botMsg.buttons && !botMsg.cards && !botMsg.sourceData && !botMsg.nlp)) {
|
|
@@ -57,7 +57,11 @@ module.exports = {
|
|
|
57
57
|
{ name: 'ASSIGN_SCRIPTING_MEMORY', className: 'AssignScriptingMemoryLogicHook' },
|
|
58
58
|
{ name: 'UPDATE_CUSTOM', className: 'UpdateCustomLogicHook' },
|
|
59
59
|
{ name: 'SKIP_BOT_UNCONSUMED', className: 'ClearQueueLogicHook' },
|
|
60
|
-
{ name: LOGIC_HOOK_INCLUDE, className: 'IncludeLogicHook' }
|
|
60
|
+
{ name: LOGIC_HOOK_INCLUDE, className: 'IncludeLogicHook' },
|
|
61
|
+
{ name: 'CONDITIONAL_STEP_TIME_BASED', className: 'ConditionalTimeBasedLogicHook' },
|
|
62
|
+
{ name: 'CONDITIONAL_STEP_BUSINESS_HOURS', className: 'ConditionalBusinessHoursLogicHook' },
|
|
63
|
+
{ name: 'CONDITIONAL_STEP_CAPABILITY_VALUE_BASED', className: 'ConditionalCapabilityValueBasedLogicHook' },
|
|
64
|
+
{ name: 'CONDITIONAL_STEP_JSON_PATH_BASED', className: 'ConditionalJsonPathBasedLogicHook.js' }
|
|
61
65
|
],
|
|
62
66
|
DEFAULT_USER_INPUTS: [
|
|
63
67
|
{ name: 'BUTTON', className: 'ButtonInput' },
|
|
@@ -18,19 +18,19 @@ module.exports = class ButtonsAsserter {
|
|
|
18
18
|
}
|
|
19
19
|
const buttonsNotFound = []
|
|
20
20
|
const buttonsFound = []
|
|
21
|
-
const
|
|
21
|
+
const stringifyPayload = (payload) => {
|
|
22
22
|
if (_.isNil(payload)) {
|
|
23
|
-
return
|
|
23
|
+
return ''
|
|
24
24
|
}
|
|
25
25
|
try {
|
|
26
|
-
return JSON.parse(payload)
|
|
26
|
+
return JSON.stringify(JSON.parse(payload))
|
|
27
27
|
} catch (e) {
|
|
28
|
-
return payload
|
|
28
|
+
return JSON.stringify(payload)
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
for (let i = 0; i < (args || []).length; i++) {
|
|
32
32
|
const matchByText = allButtons.some(b => this.context.Match(b.text, normalizeText(args[i], !!this.caps[SCRIPTING_NORMALIZE_TEXT])))
|
|
33
|
-
const matchByPayload = allButtons.some(b =>
|
|
33
|
+
const matchByPayload = allButtons.some(b => this.context.Match(stringifyPayload(b.payload), normalizeText(args[i], !!this.caps[SCRIPTING_NORMALIZE_TEXT])))
|
|
34
34
|
if (matchByText || matchByPayload) {
|
|
35
35
|
buttonsFound.push(args[i])
|
|
36
36
|
} else {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const util = require('util')
|
|
2
|
+
const moment = require('moment-timezone')
|
|
3
|
+
const debug = require('debug')('botium-core-ConditionalTimeBasedLogicHook')
|
|
4
|
+
|
|
5
|
+
module.exports = class ConditionalBusinessHoursLogicHook {
|
|
6
|
+
constructor (context, caps, globalArgs) {
|
|
7
|
+
this.context = context
|
|
8
|
+
this.caps = caps
|
|
9
|
+
this.globalArgs = globalArgs
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
_isBetween ({ now, start, end, days, timeZone }) {
|
|
13
|
+
if ((!start || !end) && (!days || days.length === 0)) {
|
|
14
|
+
throw new Error('ConditionalBusinessHoursLogicHook: Either start and end time or days array needs to be specified in params')
|
|
15
|
+
}
|
|
16
|
+
now.tz(timeZone)
|
|
17
|
+
if (days && days.length > 0 && !days.includes(now.format('dddd'))) {
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!start && !end && days && days.length > 0 && days.includes(now.format('dddd'))) {
|
|
22
|
+
return true
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const momentStartTime = moment(start, 'HH:mm')
|
|
26
|
+
const startTime = now.clone().set({ hour: momentStartTime.hour(), minute: momentStartTime.minute() })
|
|
27
|
+
startTime.tz(timeZone)
|
|
28
|
+
const momentEndTime = moment(end, 'HH:mm')
|
|
29
|
+
const endTime = now.clone().set({ hour: momentEndTime.hour(), minute: momentEndTime.minute() })
|
|
30
|
+
endTime.tz(timeZone)
|
|
31
|
+
if (startTime.isSameOrAfter(endTime)) {
|
|
32
|
+
if (now.isSameOrAfter(startTime)) {
|
|
33
|
+
endTime.add(1, 'days')
|
|
34
|
+
} else {
|
|
35
|
+
startTime.add(-1, 'days')
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return now.isBetween(startTime, endTime, 'minutes', '[]')
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
onBotPrepare ({ convo, convoStep, args }) {
|
|
42
|
+
const conditionGroupId = args[1]
|
|
43
|
+
let params
|
|
44
|
+
try {
|
|
45
|
+
params = JSON.parse(args[0])
|
|
46
|
+
} catch (e) {
|
|
47
|
+
throw new Error(`ConditionalBusinessHoursLogicHook: No parsable JSON object found in params: ${e}`)
|
|
48
|
+
}
|
|
49
|
+
convoStep.conditional = {
|
|
50
|
+
conditionGroupId
|
|
51
|
+
}
|
|
52
|
+
params.now = moment()
|
|
53
|
+
convoStep.conditional.skip = !this._isBetween(params)
|
|
54
|
+
debug(`ConditionalBusinessHoursLogicHook onBotPrepare ${convo.header.name}/${convoStep.stepTag}, args: ${util.inspect(args)}, convoStep.conditional: ${convoStep.conditional}`)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const util = require('util')
|
|
2
|
+
const jp = require('jsonpath')
|
|
3
|
+
const _ = require('lodash')
|
|
4
|
+
const debug = require('debug')('botium-core-ConditionalCapabilityValueBasedLogicHook')
|
|
5
|
+
|
|
6
|
+
module.exports = class ConditionalCapabilityValueBasedLogicHook {
|
|
7
|
+
constructor (context, caps, globalArgs) {
|
|
8
|
+
this.context = context
|
|
9
|
+
this.caps = caps
|
|
10
|
+
this.globalArgs = globalArgs
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
_isCapabilityValueEqual ({ capabilityName, jsonPath, value }) {
|
|
14
|
+
if (jsonPath) {
|
|
15
|
+
const capabilityObject = _.isObject(this.caps[capabilityName]) ? this.caps[capabilityName] : JSON.parse(this.caps[capabilityName])
|
|
16
|
+
const values = jp.query(capabilityObject, jsonPath)
|
|
17
|
+
return !!(values && values.length > 0 && values.includes(value))
|
|
18
|
+
} else {
|
|
19
|
+
return this.caps[capabilityName] === value
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
onBotPrepare ({ convo, convoStep, args }) {
|
|
24
|
+
const conditionGroupId = args[1]
|
|
25
|
+
let params
|
|
26
|
+
try {
|
|
27
|
+
params = JSON.parse(args[0])
|
|
28
|
+
} catch (e) {
|
|
29
|
+
throw new Error(`ConditionalCapabilityValueBasedLogicHook: No parsable JSON object found in params: ${e}`)
|
|
30
|
+
}
|
|
31
|
+
convoStep.conditional = {
|
|
32
|
+
conditionGroupId
|
|
33
|
+
}
|
|
34
|
+
convoStep.conditional.skip = !this._isCapabilityValueEqual(params)
|
|
35
|
+
debug(`ConditionalCapabilityValueBasedLogicHook onBotPrepare ${convo.header.name}/${convoStep.stepTag}, args: ${util.inspect(args)}, convoStep.conditional: ${convoStep.conditional}`)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const util = require('util')
|
|
2
|
+
const jp = require('jsonpath')
|
|
3
|
+
const debug = require('debug')('botium-core-ConditionalJsonPathBasedLogicHook')
|
|
4
|
+
|
|
5
|
+
module.exports = class ConditionalJsonPathBasedLogicHook {
|
|
6
|
+
constructor (context, caps, globalArgs) {
|
|
7
|
+
this.context = context
|
|
8
|
+
this.caps = caps
|
|
9
|
+
this.globalArgs = globalArgs
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
onBotPrepare ({ convo, convoStep, args, botMsg }) {
|
|
13
|
+
const conditionGroupId = args[1]
|
|
14
|
+
let params
|
|
15
|
+
try {
|
|
16
|
+
params = JSON.parse(args[0])
|
|
17
|
+
} catch (e) {
|
|
18
|
+
throw new Error(`ConditionalJsonPathBasedLogicHook: No parsable JSON object found in params: ${e}`)
|
|
19
|
+
}
|
|
20
|
+
convoStep.conditional = {
|
|
21
|
+
conditionGroupId
|
|
22
|
+
}
|
|
23
|
+
let skip = true
|
|
24
|
+
if (params.jsonPath) {
|
|
25
|
+
const values = jp.query(botMsg, params.jsonPath)
|
|
26
|
+
skip = !(values && values.length > 0 && values.includes(params.value))
|
|
27
|
+
}
|
|
28
|
+
convoStep.conditional.skip = skip
|
|
29
|
+
debug(`ConditionalJsonPathBasedLogicHook onBotPrepare ${convo.header.name}/${convoStep.stepTag}, args: ${util.inspect(args)}, convoStep.conditional: ${convoStep.conditional}`)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const util = require('util')
|
|
2
|
+
const moment = require('moment-timezone')
|
|
3
|
+
const debug = require('debug')('botium-core-ConditionalTimeBasedLogicHook')
|
|
4
|
+
|
|
5
|
+
module.exports = class ConditionalTimeBasedLogicHook {
|
|
6
|
+
constructor (context, caps, globalArgs) {
|
|
7
|
+
this.context = context
|
|
8
|
+
this.caps = caps
|
|
9
|
+
this.globalArgs = globalArgs
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
_isBetween ({ now, start, end, timeZone }) {
|
|
13
|
+
now.tz(timeZone)
|
|
14
|
+
const momentStartTime = moment(start, 'HH:mm')
|
|
15
|
+
const startTime = now.clone().set({ hour: momentStartTime.hour(), minute: momentStartTime.minute() })
|
|
16
|
+
startTime.tz(timeZone)
|
|
17
|
+
const momentEndTime = moment(end, 'HH:mm')
|
|
18
|
+
const endTime = now.clone().set({ hour: momentEndTime.hour(), minute: momentEndTime.minute() })
|
|
19
|
+
endTime.tz(timeZone)
|
|
20
|
+
|
|
21
|
+
if (startTime.isSameOrAfter(endTime)) {
|
|
22
|
+
if (now.isSameOrAfter(startTime)) {
|
|
23
|
+
endTime.add(1, 'days')
|
|
24
|
+
} else {
|
|
25
|
+
startTime.add(-1, 'days')
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return now.isBetween(startTime, endTime, 'minutes', '[]')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
onBotPrepare ({ convo, convoStep, args }) {
|
|
32
|
+
const conditionGroupId = args[1]
|
|
33
|
+
let params
|
|
34
|
+
try {
|
|
35
|
+
params = JSON.parse(args[0])
|
|
36
|
+
} catch (e) {
|
|
37
|
+
throw new Error(`ConditionalTimeBasedLogicHook: No parsable JSON object found in params: ${e}`)
|
|
38
|
+
}
|
|
39
|
+
convoStep.conditional = {
|
|
40
|
+
conditionGroupId
|
|
41
|
+
}
|
|
42
|
+
params.now = moment()
|
|
43
|
+
convoStep.conditional.skip = !this._isBetween(params)
|
|
44
|
+
debug(`ConditionalTimeBasedLogicHook onBotPrepare ${convo.header.name}/${convoStep.stepTag}, args: ${util.inspect(args)}, convoStep.conditional: ${convoStep.conditional}`)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module.exports = class ConditionalLogicHook {
|
|
2
|
+
constructor (context, caps, globalArgs) {
|
|
3
|
+
this.context = context
|
|
4
|
+
this.caps = caps
|
|
5
|
+
this.globalArgs = globalArgs
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
onBotPrepare ({ convo, convoStep, args }) {
|
|
9
|
+
const conditionGroupId = args[1]
|
|
10
|
+
let params
|
|
11
|
+
try {
|
|
12
|
+
params = JSON.parse(args[0])
|
|
13
|
+
} catch (e) {
|
|
14
|
+
throw new Error(`ConditionalCapabilityValueLogicHook: No parsable JSON object found in params: ${e}`)
|
|
15
|
+
}
|
|
16
|
+
convoStep.conditional = {
|
|
17
|
+
conditionGroupId
|
|
18
|
+
}
|
|
19
|
+
convoStep.conditional.skip = params.skip
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const moment = require('moment/moment')
|
|
3
|
+
const assert = require('chai').assert
|
|
4
|
+
const BotDriver = require('../../../index').BotDriver
|
|
5
|
+
const Capabilities = require('../../../index').Capabilities
|
|
6
|
+
const ConditionalBusinessHoursLogicHook = require('../../../src/scripting/logichook/logichooks/ConditionalBusinessHoursLogicHook')
|
|
7
|
+
|
|
8
|
+
const echoConnector = ({ queueBotSays }) => {
|
|
9
|
+
return {
|
|
10
|
+
UserSays (msg) {
|
|
11
|
+
const now = moment()
|
|
12
|
+
const start = moment('8:00', [moment.ISO_8601, 'HH:mm'])
|
|
13
|
+
const end = moment('16:30', [moment.ISO_8601, 'HH:mm'])
|
|
14
|
+
if (start.isSameOrAfter(end)) {
|
|
15
|
+
if (now.isSameOrAfter(start)) {
|
|
16
|
+
end.add(1, 'days')
|
|
17
|
+
} else {
|
|
18
|
+
start.add(-1, 'days')
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const businessHoursText = ['Saturday', 'Sunday'].includes(now.format('dddd'))
|
|
22
|
+
? 'it\'s non-business hours'
|
|
23
|
+
: now.isBetween(start, end, 'minutes', '[]')
|
|
24
|
+
? 'it\'s business hours'
|
|
25
|
+
: 'it\'s non-business hours'
|
|
26
|
+
const botMsg = { sender: 'bot', sourceData: msg.sourceData, messageText: `Hello, ${businessHoursText}` }
|
|
27
|
+
queueBotSays(botMsg)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe('convo with business hours conditional logichook', function () {
|
|
33
|
+
beforeEach(async function () {
|
|
34
|
+
const myCaps = {
|
|
35
|
+
[Capabilities.PROJECTNAME]: 'scripting.logichooks',
|
|
36
|
+
[Capabilities.CONTAINERMODE]: echoConnector,
|
|
37
|
+
[Capabilities.SCRIPTING_ENABLE_MEMORY]: true
|
|
38
|
+
}
|
|
39
|
+
const driver = new BotDriver(myCaps)
|
|
40
|
+
this.compiler = driver.BuildCompiler()
|
|
41
|
+
this.container = await driver.Build()
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
afterEach(async function () {
|
|
45
|
+
this.container && await this.container.Clean()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('should success', async function () {
|
|
49
|
+
this.compiler.ReadScript(path.resolve(__dirname, 'convos'), 'conditional_steps_business_hours.convo.txt')
|
|
50
|
+
await this.compiler.convos[0].Run(this.container)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('is between Monday-Friday 8:00-16:00', async function () {
|
|
54
|
+
const clh = new ConditionalBusinessHoursLogicHook()
|
|
55
|
+
const params = {
|
|
56
|
+
days: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
|
|
57
|
+
start: '8:00',
|
|
58
|
+
end: '16:00'
|
|
59
|
+
}
|
|
60
|
+
// Monday 10:00
|
|
61
|
+
params.now = moment('2023-08-21T10:00:00')
|
|
62
|
+
assert.isTrue(clh._isBetween(params))
|
|
63
|
+
// Monday 08:00
|
|
64
|
+
params.now = moment('2023-08-21T08:00:00')
|
|
65
|
+
assert.isTrue(clh._isBetween(params))
|
|
66
|
+
// Monday 16:00
|
|
67
|
+
params.now = moment('2023-08-21T16:00:00')
|
|
68
|
+
assert.isTrue(clh._isBetween(params))
|
|
69
|
+
// Monday 16:01
|
|
70
|
+
params.now = moment('2023-08-21T16:01:00')
|
|
71
|
+
assert.isFalse(clh._isBetween(params))
|
|
72
|
+
// Sunday 10:00
|
|
73
|
+
params.now = moment('2023-08-20T10:00:00')
|
|
74
|
+
assert.isFalse(clh._isBetween(params))
|
|
75
|
+
// Friday 16:01
|
|
76
|
+
params.now = moment('2023-08-25T16:01:00')
|
|
77
|
+
assert.isFalse(clh._isBetween(params))
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('is between Monday-Friday 16:01-7:59', async function () {
|
|
81
|
+
const clh = new ConditionalBusinessHoursLogicHook()
|
|
82
|
+
const params = {
|
|
83
|
+
days: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
|
|
84
|
+
start: '16:01',
|
|
85
|
+
end: '7:59'
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Monday 17:00
|
|
89
|
+
params.now = moment('2023-08-21T17:00:00')
|
|
90
|
+
assert.isTrue(clh._isBetween(params))
|
|
91
|
+
// Monday 05:00
|
|
92
|
+
params.now = moment('2023-08-21T05:00:00')
|
|
93
|
+
assert.isTrue(clh._isBetween(params))
|
|
94
|
+
// Monday 16:01
|
|
95
|
+
params.now = moment('2023-08-21T16:01:00')
|
|
96
|
+
assert.isTrue(clh._isBetween(params))
|
|
97
|
+
// Monday 07:59
|
|
98
|
+
params.now = moment('2023-08-21T07:59:00')
|
|
99
|
+
assert.isTrue(clh._isBetween(params))
|
|
100
|
+
// Friday 23:00
|
|
101
|
+
params.now = moment('2023-08-25T23:00:00')
|
|
102
|
+
assert.isTrue(clh._isBetween(params))
|
|
103
|
+
// Monday 16:00
|
|
104
|
+
params.now = moment('2023-08-21T16:00:00')
|
|
105
|
+
assert.isFalse(clh._isBetween(params))
|
|
106
|
+
// Sunday 23:00
|
|
107
|
+
params.now = moment('2023-08-20T23:00:00')
|
|
108
|
+
assert.isFalse(clh._isBetween(params))
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
it('is on Saturday or Sunday', async function () {
|
|
112
|
+
const clh = new ConditionalBusinessHoursLogicHook()
|
|
113
|
+
const params = {
|
|
114
|
+
days: ['Saturday', 'Sunday']
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Sunday 17:00
|
|
118
|
+
params.now = moment('2023-08-20T17:00:00')
|
|
119
|
+
assert.isTrue(clh._isBetween(params))
|
|
120
|
+
// Saturday 05:00
|
|
121
|
+
params.now = moment('2023-08-19T05:00:00')
|
|
122
|
+
assert.isTrue(clh._isBetween(params))
|
|
123
|
+
// Monday 16:01
|
|
124
|
+
params.now = moment('2023-08-21T16:01:00')
|
|
125
|
+
assert.isFalse(clh._isBetween(params))
|
|
126
|
+
// Friday 23:00
|
|
127
|
+
params.now = moment('2023-08-25T23:00:00')
|
|
128
|
+
assert.isFalse(clh._isBetween(params))
|
|
129
|
+
})
|
|
130
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const BotDriver = require('../../../index').BotDriver
|
|
3
|
+
const Capabilities = require('../../../index').Capabilities
|
|
4
|
+
|
|
5
|
+
const echoConnector = ({ queueBotSays }) => {
|
|
6
|
+
return {
|
|
7
|
+
UserSays (msg) {
|
|
8
|
+
const botMsg = { sender: 'bot', sourceData: msg.sourceData, messageText: msg.messageText }
|
|
9
|
+
queueBotSays(botMsg)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe('convo with capablility value based conditional logichook', function () {
|
|
15
|
+
beforeEach(async function () {
|
|
16
|
+
const myCaps = {
|
|
17
|
+
[Capabilities.PROJECTNAME]: 'scripting.logichooks',
|
|
18
|
+
[Capabilities.CONTAINERMODE]: echoConnector,
|
|
19
|
+
[Capabilities.SCRIPTING_ENABLE_MEMORY]: true,
|
|
20
|
+
SIMPLE_TEXT: 'echo1'
|
|
21
|
+
}
|
|
22
|
+
const driver = new BotDriver(myCaps)
|
|
23
|
+
this.compiler = driver.BuildCompiler()
|
|
24
|
+
this.container = await driver.Build()
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
afterEach(async function () {
|
|
28
|
+
this.container && await this.container.Clean()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('should success', async function () {
|
|
32
|
+
this.compiler.ReadScript(path.resolve(__dirname, 'convos'), 'conditional_steps_cap_value_based.convo.txt')
|
|
33
|
+
await this.compiler.convos[0].Run(this.container)
|
|
34
|
+
})
|
|
35
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const BotDriver = require('../../../index').BotDriver
|
|
3
|
+
const Capabilities = require('../../../index').Capabilities
|
|
4
|
+
|
|
5
|
+
const echoConnector = ({ queueBotSays }) => {
|
|
6
|
+
return {
|
|
7
|
+
UserSays (msg) {
|
|
8
|
+
const botMsg = { sender: 'bot', sourceData: msg.sourceData, messageText: msg.messageText }
|
|
9
|
+
queueBotSays(botMsg)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe('convo with capablility value based conditional logichook', function () {
|
|
15
|
+
beforeEach(async function () {
|
|
16
|
+
const myCaps = {
|
|
17
|
+
[Capabilities.PROJECTNAME]: 'scripting.logichooks',
|
|
18
|
+
[Capabilities.CONTAINERMODE]: echoConnector,
|
|
19
|
+
[Capabilities.SCRIPTING_ENABLE_MEMORY]: true,
|
|
20
|
+
SIMPLE_TEXT: 'echo1'
|
|
21
|
+
}
|
|
22
|
+
const driver = new BotDriver(myCaps)
|
|
23
|
+
this.compiler = driver.BuildCompiler()
|
|
24
|
+
this.container = await driver.Build()
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
afterEach(async function () {
|
|
28
|
+
this.container && await this.container.Clean()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('should success', async function () {
|
|
32
|
+
this.compiler.ReadScript(path.resolve(__dirname, 'convos'), 'conditional_steps_json_path_based.convo.txt.convo.txt')
|
|
33
|
+
await this.compiler.convos[0].Run(this.container)
|
|
34
|
+
})
|
|
35
|
+
})
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const moment = require('moment/moment')
|
|
3
|
+
const assert = require('chai').assert
|
|
4
|
+
const BotDriver = require('../../../index').BotDriver
|
|
5
|
+
const Capabilities = require('../../../index').Capabilities
|
|
6
|
+
const ConditionalTimeBasedLogicHook = require('../../../src/scripting/logichook/logichooks/ConditionalTimeBasedLogicHook')
|
|
7
|
+
|
|
8
|
+
const echoConnector = ({ queueBotSays }) => {
|
|
9
|
+
return {
|
|
10
|
+
UserSays (msg) {
|
|
11
|
+
const now = moment()
|
|
12
|
+
const start = moment('8:00', [moment.ISO_8601, 'HH:mm'])
|
|
13
|
+
const end = moment('16:30', [moment.ISO_8601, 'HH:mm'])
|
|
14
|
+
if (start.isSameOrAfter(end)) {
|
|
15
|
+
if (now.isSameOrAfter(start)) {
|
|
16
|
+
end.add(1, 'days')
|
|
17
|
+
} else {
|
|
18
|
+
start.add(-1, 'days')
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const businessHoursText = now.isBetween(start, end, 'minutes', '[]') ? 'we are open' : 'we are closed'
|
|
22
|
+
const botMsg = { sender: 'bot', sourceData: msg.sourceData, messageText: `Hello, ${businessHoursText}` }
|
|
23
|
+
queueBotSays(botMsg)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe('convo with time based conditional logichook', function () {
|
|
29
|
+
beforeEach(async function () {
|
|
30
|
+
const myCaps = {
|
|
31
|
+
[Capabilities.PROJECTNAME]: 'scripting.logichooks',
|
|
32
|
+
[Capabilities.CONTAINERMODE]: echoConnector,
|
|
33
|
+
[Capabilities.SCRIPTING_ENABLE_MEMORY]: true
|
|
34
|
+
}
|
|
35
|
+
const driver = new BotDriver(myCaps)
|
|
36
|
+
this.compiler = driver.BuildCompiler()
|
|
37
|
+
this.container = await driver.Build()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
afterEach(async function () {
|
|
41
|
+
this.container && await this.container.Clean()
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('should success', async function () {
|
|
45
|
+
this.compiler.ReadScript(path.resolve(__dirname, 'convos'), 'conditional_steps_time_based.convo.txt')
|
|
46
|
+
await this.compiler.convos[0].Run(this.container)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('is between 8:00-16:00', async function () {
|
|
50
|
+
const clh = new ConditionalTimeBasedLogicHook()
|
|
51
|
+
const params = {
|
|
52
|
+
start: '8:00',
|
|
53
|
+
end: '16:00'
|
|
54
|
+
}
|
|
55
|
+
// Monday 10:00
|
|
56
|
+
params.now = moment('2023-08-21T10:00:00')
|
|
57
|
+
assert.isTrue(clh._isBetween(params))
|
|
58
|
+
// Monday 08:00
|
|
59
|
+
params.now = moment('2023-08-21T08:00:00')
|
|
60
|
+
assert.isTrue(clh._isBetween(params))
|
|
61
|
+
// Monday 16:00
|
|
62
|
+
params.now = moment('2023-08-21T16:00:00')
|
|
63
|
+
assert.isTrue(clh._isBetween(params))
|
|
64
|
+
// Monday 16:01
|
|
65
|
+
params.now = moment('2023-08-21T16:01:00')
|
|
66
|
+
assert.isFalse(clh._isBetween(params))
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('is between 16:01-7:59', async function () {
|
|
70
|
+
const clh = new ConditionalTimeBasedLogicHook()
|
|
71
|
+
const params = {
|
|
72
|
+
start: '16:01',
|
|
73
|
+
end: '7:59'
|
|
74
|
+
}
|
|
75
|
+
// Monday 17:00
|
|
76
|
+
params.now = moment('2023-08-21T17:00:00')
|
|
77
|
+
assert.isTrue(clh._isBetween(params))
|
|
78
|
+
// Monday 05:00
|
|
79
|
+
params.now = moment('2023-08-21T05:00:00')
|
|
80
|
+
assert.isTrue(clh._isBetween(params))
|
|
81
|
+
// Monday 16:01
|
|
82
|
+
params.now = moment('2023-08-21T16:01:00')
|
|
83
|
+
assert.isTrue(clh._isBetween(params))
|
|
84
|
+
// Monday 07:59
|
|
85
|
+
params.now = moment('2023-08-21T07:59:00')
|
|
86
|
+
assert.isTrue(clh._isBetween(params))
|
|
87
|
+
// Monday 16:00
|
|
88
|
+
params.now = moment('2023-08-21T16:00:00')
|
|
89
|
+
assert.isFalse(clh._isBetween(params))
|
|
90
|
+
})
|
|
91
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
conditional_steps_time_based
|
|
2
|
+
|
|
3
|
+
#me
|
|
4
|
+
hello
|
|
5
|
+
|
|
6
|
+
#bot
|
|
7
|
+
hello, it's business hours
|
|
8
|
+
CONDITIONAL_STEP_BUSINESS_HOURS { "days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], "start":"8:00", "end": "16:30" }
|
|
9
|
+
|
|
10
|
+
#bot
|
|
11
|
+
hello, it's non-business hours
|
|
12
|
+
CONDITIONAL_STEP_BUSINESS_HOURS { "days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], "start":"16:31", "end": "7:59" }
|
|
13
|
+
|
|
14
|
+
#bot
|
|
15
|
+
hello, it's non-business hours
|
|
16
|
+
CONDITIONAL_STEP_BUSINESS_HOURS { "days": ["Saturday", "Sunday"] }
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
conditional_steps_time_based
|
|
2
|
+
|
|
3
|
+
#me
|
|
4
|
+
hello
|
|
5
|
+
|
|
6
|
+
#bot
|
|
7
|
+
hello
|
|
8
|
+
CONDITIONAL_STEP_CAPABILITY_VALUE_BASED { "capabilityName":"SIMPLE_TEXT", "value": "echo1" }
|
|
9
|
+
|
|
10
|
+
#bot
|
|
11
|
+
fail
|
|
12
|
+
CONDITIONAL_STEP_CAPABILITY_VALUE_BASED { "capabilityName":"SIMPLE_TEXT", "value": "echo2" }
|