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.
Files changed (33) hide show
  1. package/dist/botium-cjs.js +29 -6
  2. package/dist/botium-cjs.js.map +1 -1
  3. package/dist/botium-es.js +29 -6
  4. package/dist/botium-es.js.map +1 -1
  5. package/package.json +2 -1
  6. package/src/scripting/Convo.js +17 -5
  7. package/src/scripting/logichook/LogicHookConsts.js +5 -1
  8. package/src/scripting/logichook/asserter/ButtonsAsserter.js +5 -5
  9. package/src/scripting/logichook/logichooks/ConditionalBusinessHoursLogicHook.js +56 -0
  10. package/src/scripting/logichook/logichooks/ConditionalCapabilityValueBasedLogicHook.js +37 -0
  11. package/src/scripting/logichook/logichooks/ConditionalJsonPathBasedLogicHook.js +31 -0
  12. package/src/scripting/logichook/logichooks/ConditionalTimeBasedLogicHook.js +46 -0
  13. package/test/scripting/logichooks/CustomConditionalLogicHook.js +21 -0
  14. package/test/scripting/logichooks/conditionalStepBusinessHoursLogicHook.spec.js +130 -0
  15. package/test/scripting/logichooks/conditionalStepCapabilityValueBasedLogicHook.spec.js +35 -0
  16. package/test/scripting/logichooks/conditionalStepJsonPathBasedLogicHook.spec.js +35 -0
  17. package/test/scripting/logichooks/conditionalStepTimeBasedLogicHook.spec.js +91 -0
  18. package/test/scripting/logichooks/convos/conditional_steps.convo.txt +12 -0
  19. package/test/scripting/logichooks/convos/conditional_steps_business_hours.convo.txt +16 -0
  20. package/test/scripting/logichooks/convos/conditional_steps_cap_value_based.convo.txt +12 -0
  21. package/test/scripting/logichooks/convos/conditional_steps_followed_by_bot_msg.convo.txt +15 -0
  22. package/test/scripting/logichooks/convos/conditional_steps_followed_by_me.convo.txt +18 -0
  23. package/test/scripting/logichooks/convos/conditional_steps_json_path_based.convo.txt.convo.txt +12 -0
  24. package/test/scripting/logichooks/convos/conditional_steps_multiple_condition_groups.convo.txt +20 -0
  25. package/test/scripting/logichooks/convos/conditional_steps_multiple_condition_groups_no_assertion.convo.txt +20 -0
  26. package/test/scripting/logichooks/convos/conditional_steps_time_based.convo.txt +12 -0
  27. package/test/scripting/logichooks/customConditionalStepLogicHook.spec.js +105 -0
  28. package/test/scripting/scriptingProvider.spec.js +1 -1
  29. package/test/scripting/logichooks/convos/custom_embedded_skip.convo.txt +0 -11
  30. package/test/scripting/logichooks/convos/custom_embedded_skip_followed_by_me.convo.txt +0 -11
  31. package/test/scripting/logichooks/convos/custom_embedded_skip_followed_by_nothing.convo.txt +0 -8
  32. package/test/scripting/logichooks/customEmbeddedSkip.json +0 -14
  33. 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.18",
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",
@@ -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.skip === true) {
408
- skipTranscriptStep = true
408
+ if (convoStep.conditional) {
409
409
  const nextConvoStep = this.conversation[i + 1]
410
- if (nextConvoStep && nextConvoStep.sender === 'bot') {
411
- waitForBotSays = false
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 parsePayload = (payload) => {
21
+ const stringifyPayload = (payload) => {
22
22
  if (_.isNil(payload)) {
23
- return undefined
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 => _.isEqual(parsePayload(b.payload), parsePayload(args[i])))
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,12 @@
1
+ custom embedded
2
+
3
+ #me
4
+ hello
5
+
6
+ #bot
7
+ hello should not assert
8
+ CONDITIONAL_STEP_LOGIC_HOOK { "skip":true }|G1
9
+
10
+ #bot
11
+ hello
12
+ CONDITIONAL_STEP_LOGIC_HOOK { "skip":false }|G1
@@ -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" }
@@ -0,0 +1,15 @@
1
+ custom embedded
2
+
3
+ #me
4
+ hello
5
+
6
+ #bot
7
+ hello should not assert
8
+ CONDITIONAL_STEP_LOGIC_HOOK { "skip":true }|G1
9
+
10
+ #bot
11
+ hello
12
+ CONDITIONAL_STEP_LOGIC_HOOK { "skip":false }|G1
13
+
14
+ #bot
15
+ hello Duplicate
@@ -0,0 +1,18 @@
1
+ custom embedded
2
+
3
+ #me
4
+ hello
5
+
6
+ #bot
7
+ hello should not assert
8
+ CONDITIONAL_STEP_LOGIC_HOOK { "skip":true }|G1
9
+
10
+ #bot
11
+ hello
12
+ CONDITIONAL_STEP_LOGIC_HOOK { "skip":false }|G1
13
+
14
+ #me
15
+ hello
16
+
17
+ #bot
18
+ hello