botium-core 1.13.18 → 1.14.0

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 (60) hide show
  1. package/dist/botium-cjs.js +326 -387
  2. package/dist/botium-cjs.js.map +1 -1
  3. package/dist/botium-es.js +326 -385
  4. package/dist/botium-es.js.map +1 -1
  5. package/package.json +21 -25
  6. package/samples/extensions/asserterHooks/botium.json +1 -0
  7. package/samples/extensions/logichooks/botium.json +1 -0
  8. package/samples/extensions/logichooks/custom/MyAsserter.js +3 -3
  9. package/src/Capabilities.js +2 -1
  10. package/src/containers/PluginConnectorContainer.js +8 -0
  11. package/src/containers/plugins/SimpleRestContainer.js +17 -9
  12. package/src/containers/plugins/index.js +29 -41
  13. package/src/helpers/HookUtils.js +32 -68
  14. package/src/scripting/Convo.js +17 -5
  15. package/src/scripting/ScriptingMemory.js +0 -24
  16. package/src/scripting/logichook/LogicHookConsts.js +5 -1
  17. package/src/scripting/logichook/LogicHookUtils.js +27 -47
  18. package/src/scripting/logichook/asserter/ButtonsAsserter.js +5 -5
  19. package/src/scripting/logichook/logichooks/ConditionalBusinessHoursLogicHook.js +56 -0
  20. package/src/scripting/logichook/logichooks/ConditionalCapabilityValueBasedLogicHook.js +37 -0
  21. package/src/scripting/logichook/logichooks/ConditionalJsonPathBasedLogicHook.js +31 -0
  22. package/src/scripting/logichook/logichooks/ConditionalTimeBasedLogicHook.js +46 -0
  23. package/test/compiler/precompilerscript.spec.js +24 -26
  24. package/test/connectors/pluginconnectorcontainer.spec.js +60 -0
  25. package/test/connectors/simplerest.spec.js +24 -27
  26. package/test/convo/fillAndApplyScriptingMemory.spec.js +1 -47
  27. package/test/hooks/customhooks.spec.js +3 -25
  28. package/test/logichooks/hookfromsrc.spec.js +13 -3
  29. package/test/plugins/plugins.spec.js +29 -2
  30. package/test/scripting/logichooks/CustomConditionalLogicHook.js +21 -0
  31. package/test/scripting/logichooks/conditionalStepBusinessHoursLogicHook.spec.js +130 -0
  32. package/test/scripting/logichooks/conditionalStepCapabilityValueBasedLogicHook.spec.js +35 -0
  33. package/test/scripting/logichooks/conditionalStepJsonPathBasedLogicHook.spec.js +35 -0
  34. package/test/scripting/logichooks/conditionalStepTimeBasedLogicHook.spec.js +91 -0
  35. package/test/scripting/logichooks/convos/conditional_steps.convo.txt +12 -0
  36. package/test/scripting/logichooks/convos/conditional_steps_business_hours.convo.txt +16 -0
  37. package/test/scripting/logichooks/convos/conditional_steps_cap_value_based.convo.txt +12 -0
  38. package/test/scripting/logichooks/convos/conditional_steps_followed_by_bot_msg.convo.txt +15 -0
  39. package/test/scripting/logichooks/convos/conditional_steps_followed_by_me.convo.txt +18 -0
  40. package/test/scripting/logichooks/convos/conditional_steps_json_path_based.convo.txt.convo.txt +12 -0
  41. package/test/scripting/logichooks/convos/conditional_steps_multiple_condition_groups.convo.txt +20 -0
  42. package/test/scripting/logichooks/convos/conditional_steps_multiple_condition_groups_no_assertion.convo.txt +20 -0
  43. package/test/scripting/logichooks/convos/conditional_steps_time_based.convo.txt +12 -0
  44. package/test/scripting/logichooks/customConditionalStepLogicHook.spec.js +105 -0
  45. package/test/scripting/scriptingProvider.spec.js +1 -1
  46. package/test/security/allowUnsafe.spec.js +20 -129
  47. package/LICENSES-3RDPARTY.txt +0 -6450
  48. package/test/scripting/asserters/convos/customembeddedasserterwithhugo.convo.txt +0 -7
  49. package/test/scripting/asserters/convos/customembeddedasserterwithouthugo.convo.txt +0 -7
  50. package/test/scripting/asserters/customEmbeddedAsserter.json +0 -14
  51. package/test/scripting/asserters/customEmbeddedAsserter.spec.js +0 -55
  52. package/test/scripting/logichooks/convos/custom_embedded.convo.txt +0 -8
  53. package/test/scripting/logichooks/convos/custom_embedded_skip.convo.txt +0 -11
  54. package/test/scripting/logichooks/convos/custom_embedded_skip_followed_by_me.convo.txt +0 -11
  55. package/test/scripting/logichooks/convos/custom_embedded_skip_followed_by_nothing.convo.txt +0 -8
  56. package/test/scripting/logichooks/customEmbedded.json +0 -14
  57. package/test/scripting/logichooks/customEmbedded.spec.js +0 -44
  58. package/test/scripting/logichooks/customEmbeddedSkip.json +0 -14
  59. package/test/scripting/logichooks/customEmbeddedSkip.spec.js +0 -58
  60. package/test/security/convos/withscriptingmemoryfunction.convo.txt +0 -5
@@ -50,7 +50,6 @@ const myCapsScriptingMemory = {
50
50
  FUNCTION_WITHOUT_PARAM: '{{fnc.year}}',
51
51
  FUNCTION_WITH_PARAM: '{{#fnc.random}}5{{/fnc.random}}',
52
52
  FUNCTION_WITH_PARAM_FROM_SCRIPTING_MEMORY: '{{#fnc.random}}{{msg.scriptingMemory.functionArgument}}{{/fnc.random}}',
53
- USING_CODE: '{{#fnc.func}}1 + 2{{/fnc.func}}',
54
53
  SAMPLE_ENV: '{{#fnc.env}}SAMPLE_ENV{{/fnc.env}}',
55
54
  VARIABLE: '{{msg.scriptingMemory.variable}}',
56
55
  PROJECTNAME: '{{fnc.projectname}}',
@@ -91,11 +90,11 @@ const myCapsHookBase = {
91
90
  [Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: ['$']
92
91
  }
93
92
  const myCapsRequestHookFromString = Object.assign({
94
- [Capabilities.SIMPLEREST_REQUEST_HOOK]: `
93
+ [Capabilities.SIMPLEREST_REQUEST_HOOK]: ({ requestOptions, context }) => {
95
94
  let counter = 1
96
- requestOptions.body = {bodyFieldRequestHook: counter++}
95
+ requestOptions.body = { bodyFieldRequestHook: counter++ }
97
96
  context.contextFieldRequestHook = counter
98
- `
97
+ }
99
98
  }, myCapsHookBase)
100
99
  const myCapsRequestHookFromStringInvalid = Object.assign({
101
100
  [Capabilities.SIMPLEREST_REQUEST_HOOK]: '!'
@@ -108,12 +107,13 @@ const myCapsRequestHookFromFunction = Object.assign({
108
107
  }
109
108
  }, myCapsHookBase)
110
109
  const myCapsRequestHookFromModule = Object.assign({
111
- [Capabilities.SIMPLEREST_REQUEST_HOOK]: 'test/connectors/logicHook.js'
110
+ [Capabilities.SAFEDIR]: './test/connectors/',
111
+ [Capabilities.SIMPLEREST_REQUEST_HOOK]: 'logicHook.js'
112
112
  }, myCapsHookBase)
113
113
  const myCapsResponseHook = Object.assign({
114
- [Capabilities.SIMPLEREST_RESPONSE_HOOK]: `
115
- botMsg.messageText = 'message text from hook'
116
- `
114
+ [Capabilities.SIMPLEREST_RESPONSE_HOOK]: ({ botMsg }) => {
115
+ botMsg.messageText = 'message text from hook'
116
+ }
117
117
  }, myCapsHookBase)
118
118
 
119
119
  const msg = {
@@ -460,9 +460,6 @@ describe('connectors.simplerest', function () {
460
460
  assert.exists(request.body.SAMPLE_ENV)
461
461
  assert.equal(request.body.SAMPLE_ENV, 'SAMPLE_ENV')
462
462
 
463
- assert.exists(request.body.USING_CODE)
464
- assert.equal(request.body.USING_CODE, 3)
465
-
466
463
  assert.exists(request.body.VARIABLE)
467
464
  assert.equal(request.body.VARIABLE, 'varvalue')
468
465
 
@@ -519,13 +516,13 @@ describe('connectors.simplerest', function () {
519
516
  it('should use request hook, from module', async function () {
520
517
  await _assertHook(Object.assign({}, myCapsRequestHookFromModule))
521
518
  })
522
- it('should use request hook, from invalid string', async function () {
519
+ it('should reject request hook, from invalid string', async function () {
523
520
  const driver = new BotDriver(myCapsRequestHookFromStringInvalid)
524
521
  try {
525
522
  await driver.Build()
526
523
  assert.fail('it should have failed')
527
524
  } catch (err) {
528
- assert.isTrue(err.message.includes('Cant load hook, syntax is not valid'))
525
+ assert.isTrue(err.message.includes('Hook specification "\'!\'" invalid'))
529
526
  }
530
527
  })
531
528
  it('should add query params from UPDATE_CUSTOM (without "?")', async function () {
@@ -741,9 +738,9 @@ describe('connectors.simplerest', function () {
741
738
  const myCaps = Object.assign({}, myCapsGet, {
742
739
  [Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$.text',
743
740
  [Capabilities.SIMPLEREST_MEDIA_JSONPATH]: '$.media',
744
- [Capabilities.SIMPLEREST_RESPONSE_HOOK]: `
745
- botMsg.nlp = { intent: { name: 'hugo' } }
746
- `,
741
+ [Capabilities.SIMPLEREST_RESPONSE_HOOK]: ({ botMsg }) => {
742
+ botMsg.nlp = { intent: { name: 'hugo' } }
743
+ },
747
744
  [Capabilities.SIMPLEREST_IGNORE_EMPTY]: true
748
745
  })
749
746
  const driver = new BotDriver(myCaps)
@@ -764,9 +761,9 @@ describe('connectors.simplerest', function () {
764
761
  const myCaps = Object.assign({}, myCapsGet, {
765
762
  [Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$.text',
766
763
  [Capabilities.SIMPLEREST_MEDIA_JSONPATH]: '$.media',
767
- [Capabilities.SIMPLEREST_RESPONSE_HOOK]: `
768
- botMsg.someextradata = 'message text from hook'
769
- `,
764
+ [Capabilities.SIMPLEREST_RESPONSE_HOOK]: ({ botMsg }) => {
765
+ botMsg.someextradata = 'message text from hook'
766
+ },
770
767
  [Capabilities.SIMPLEREST_IGNORE_EMPTY]: true
771
768
  })
772
769
  const driver = new BotDriver(myCaps)
@@ -787,9 +784,9 @@ describe('connectors.simplerest', function () {
787
784
  const myCaps = Object.assign({}, myCapsGet, {
788
785
  [Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$.text',
789
786
  [Capabilities.SIMPLEREST_MEDIA_JSONPATH]: '$.media',
790
- [Capabilities.SIMPLEREST_RESPONSE_HOOK]: `
791
- botMsg.messageText = 'message text from hook'
792
- `,
787
+ [Capabilities.SIMPLEREST_RESPONSE_HOOK]: ({ botMsg }) => {
788
+ botMsg.messageText = 'message text from hook'
789
+ },
793
790
  [Capabilities.SIMPLEREST_IGNORE_EMPTY]: true
794
791
  })
795
792
  const driver = new BotDriver(myCaps)
@@ -1061,7 +1058,7 @@ describe('connectors.simplerest', function () {
1061
1058
  await this.init({
1062
1059
  [Capabilities.SIMPLEREST_PING_URL]: 'https://mock.com/pingencoded',
1063
1060
  [Capabilities.SIMPLEREST_PING_PROCESS_RESPONSE]: true,
1064
- [Capabilities.SIMPLEREST_PARSER_HOOK]: 'body.text = JSON.parse(body.text).prop'
1061
+ [Capabilities.SIMPLEREST_PARSER_HOOK]: ({ body }) => { body.text = JSON.parse(body.text).prop }
1065
1062
  })
1066
1063
 
1067
1064
  this.compiler.ReadScript(path.resolve(__dirname, 'convos'), 'responsefromping.convo.txt')
@@ -1074,7 +1071,7 @@ describe('connectors.simplerest', function () {
1074
1071
  await this.init({
1075
1072
  [Capabilities.SIMPLEREST_PING_URL]: 'https://mock.com/pingstring',
1076
1073
  [Capabilities.SIMPLEREST_PING_PROCESS_RESPONSE]: true,
1077
- [Capabilities.SIMPLEREST_PARSER_HOOK]: 'changeBody({ text: body })'
1074
+ [Capabilities.SIMPLEREST_PARSER_HOOK]: ({ changeBody, body }) => changeBody({ text: body })
1078
1075
  })
1079
1076
 
1080
1077
  this.compiler.ReadScript(path.resolve(__dirname, 'convos'), 'responsefromping.convo.txt')
@@ -1114,7 +1111,7 @@ describe('connectors.simplerest', function () {
1114
1111
  await this.init({
1115
1112
  [Capabilities.SIMPLEREST_START_URL]: 'https://mock.com/startencoded',
1116
1113
  [Capabilities.SIMPLEREST_START_PROCESS_RESPONSE]: true,
1117
- [Capabilities.SIMPLEREST_PARSER_HOOK]: 'body.text = JSON.parse(body.text).prop'
1114
+ [Capabilities.SIMPLEREST_PARSER_HOOK]: ({ body }) => { body.text = JSON.parse(body.text).prop }
1118
1115
  })
1119
1116
 
1120
1117
  this.compiler.ReadScript(path.resolve(__dirname, 'convos'), 'responsefromstart.convo.txt')
@@ -1127,7 +1124,7 @@ describe('connectors.simplerest', function () {
1127
1124
  await this.init({
1128
1125
  [Capabilities.SIMPLEREST_START_URL]: 'https://mock.com/startstring',
1129
1126
  [Capabilities.SIMPLEREST_START_PROCESS_RESPONSE]: true,
1130
- [Capabilities.SIMPLEREST_PARSER_HOOK]: 'changeBody({ text: body })'
1127
+ [Capabilities.SIMPLEREST_PARSER_HOOK]: ({ changeBody, body }) => changeBody({ text: body })
1131
1128
  })
1132
1129
 
1133
1130
  this.compiler.ReadScript(path.resolve(__dirname, 'convos'), 'responsefromstart.convo.txt')
@@ -1283,7 +1280,7 @@ describe('connectors.simplerest', function () {
1283
1280
  [Capabilities.SIMPLEREST_URL]: () => 'https://mock.com/endpoint',
1284
1281
  [Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: () => ['$.text'],
1285
1282
  [Capabilities.SIMPLEREST_POLL_URL]: () => 'https://mock.com/poll',
1286
- [Capabilities.SIMPLEREST_POLL_REQUEST_HOOK]: 'requestOptions.uri = "https://mock.com/_from_hook"'
1283
+ [Capabilities.SIMPLEREST_POLL_REQUEST_HOOK]: ({ requestOptions }) => { requestOptions.uri = 'https://mock.com/_from_hook' }
1287
1284
  }
1288
1285
  const scope = nock('https://mock.com')
1289
1286
  .get('/endpoint')
@@ -168,7 +168,7 @@ describe('convo.fillAndApplyScriptingMemory', function () {
168
168
  [Capabilities.PROJECTNAME]: 'convo.scriptingmemory',
169
169
  [Capabilities.CONTAINERMODE]: echoConnector,
170
170
  [Capabilities.SCRIPTING_ENABLE_MEMORY]: true,
171
- [Capabilities.CUSTOMHOOK_ONBUILD]: 'module.exports = ({ container }) => { console.log("customhooks called"); container.caps.MYTOKEN = "test1234" }'
171
+ [Capabilities.CUSTOMHOOK_ONBUILD]: ({ container }) => { console.log('customhooks called'); container.caps.MYTOKEN = 'test1234' }
172
172
  }
173
173
  const driver = new BotDriver(myCaps)
174
174
  const compiler = driver.BuildCompiler()
@@ -847,52 +847,6 @@ describe('convo.fillAndApplyScriptingMemory', function () {
847
847
  assert(result.length === 36, '$uniqid invalid')
848
848
  })
849
849
 
850
- it('func', async function () {
851
- const result = ScriptingMemory.apply(
852
- { caps: CAPS_ENABLE_SCRIPTING_MEMORY },
853
- {},
854
- '$func(3*5)'
855
- )
856
-
857
- assert(result === '15', 'func invalid')
858
- })
859
- it('func with caps', async function () {
860
- const result = ScriptingMemory.apply(
861
- { caps: Object.assign({}, CAPS_ENABLE_SCRIPTING_MEMORY, { mycap: 'botium' }) },
862
- {},
863
- '$func(caps.mycap)'
864
- )
865
- assert.equal(result, 'botium')
866
- })
867
- it('func invalid code', async function () {
868
- try {
869
- ScriptingMemory.apply(
870
- { caps: CAPS_ENABLE_SCRIPTING_MEMORY },
871
- {},
872
- '$func(hugo123)'
873
- )
874
- assert.fail('should have failed')
875
- } catch (err) {
876
- assert.isTrue(err.message.indexOf('func function execution failed') >= 0)
877
- }
878
- })
879
- it('func environment variable', async function () {
880
- process.env.MY_VAR_VALUE = 'botium'
881
- const result = ScriptingMemory.apply(
882
- { caps: CAPS_ENABLE_SCRIPTING_MEMORY },
883
- {},
884
- '$func(process.env.MY_VAR_VALUE)'
885
- )
886
- assert.equal(result, 'botium')
887
- })
888
- it('func with moment', async function () {
889
- const result = ScriptingMemory.apply(
890
- { caps: CAPS_ENABLE_SCRIPTING_MEMORY },
891
- {},
892
- '$func(moment(\\).subtract(1, "month"\\).startOf("month"\\).format("DD.MM.YYYY"\\))'
893
- )
894
- assert.equal(result, moment().subtract(1, 'month').startOf('month').format('DD.MM.YYYY'))
895
- })
896
850
  it('environment variable', async function () {
897
851
  process.env.MY_VAR_VALUE = 'botium'
898
852
  const result = ScriptingMemory.apply(
@@ -65,28 +65,6 @@ describe('customhooks.hookfromsrc', function () {
65
65
  assert.isTrue(onStopCalled)
66
66
  assert.isTrue(onCleanCalled)
67
67
  })
68
- it('should call hooks from string function', async function () {
69
- const { container } = await buildDriver({
70
- [Capabilities.CUSTOMHOOK_ONBUILD]: 'module.exports = ({ container }) => { container.onBuildCalled = true }',
71
- [Capabilities.CUSTOMHOOK_ONSTART]: 'module.exports = ({ container }) => { container.onStartCalled = true }',
72
- [Capabilities.CUSTOMHOOK_ONUSERSAYS]: 'module.exports = ({ container }) => { container.onUserSaysCalled = true }',
73
- [Capabilities.CUSTOMHOOK_ONBOTRESPONSE]: 'module.exports = ({ container }) => { container.onBotResponseCalled = true }',
74
- [Capabilities.CUSTOMHOOK_ONSTOP]: 'module.exports = ({ container }) => { container.onStopCalled = true }',
75
- [Capabilities.CUSTOMHOOK_ONCLEAN]: 'module.exports = ({ container }) => { container.onCleanCalled = true }'
76
- })
77
- await container.Start()
78
- await container.UserSaysText('hallo')
79
- await container.WaitBotSays()
80
- await container.Stop()
81
- await container.Clean()
82
-
83
- assert.isTrue(container.onBuildCalled)
84
- assert.isTrue(container.onStartCalled)
85
- assert.isTrue(container.onUserSaysCalled)
86
- assert.isTrue(container.onBotResponseCalled)
87
- assert.isTrue(container.onStopCalled)
88
- assert.isTrue(container.onCleanCalled)
89
- })
90
68
  it('should change meMsg from hook', async function () {
91
69
  const { container } = await buildDriver({
92
70
  [Capabilities.CUSTOMHOOK_ONUSERSAYS]: ({ meMsg }) => {
@@ -115,7 +93,7 @@ describe('customhooks.hookfromsrc', function () {
115
93
 
116
94
  assert.equal(botMsg.fromHook, 1)
117
95
  })
118
- it('should call http api from string function', async function () {
96
+ it('should call http api from function', async function () {
119
97
  const scope = nock('https://gettoken.com')
120
98
  .get('/get')
121
99
  .reply(200, {
@@ -124,7 +102,7 @@ describe('customhooks.hookfromsrc', function () {
124
102
  .persist()
125
103
 
126
104
  const { container } = await buildDriver({
127
- [Capabilities.CUSTOMHOOK_ONSTART]: `module.exports = async ({ container, request }) => {
105
+ [Capabilities.CUSTOMHOOK_ONSTART]: async ({ container, request }) => {
128
106
  return new Promise((resolve, reject) => {
129
107
  request({ method: 'get', uri: 'https://gettoken.com/get', json: true }, (err, response, body) => {
130
108
  if (err) return reject(err)
@@ -132,7 +110,7 @@ describe('customhooks.hookfromsrc', function () {
132
110
  resolve()
133
111
  })
134
112
  })
135
- }`
113
+ }
136
114
  })
137
115
  await container.Start()
138
116
  assert.equal(container.caps.MYTOKEN, 'thisisausertoken')
@@ -36,7 +36,13 @@ describe('logichooks.hookfromsrc', function () {
36
36
  [Capabilities.ASSERTERS]: [{
37
37
  ref: 'CUSTOMASSERTER',
38
38
  src: {
39
- assertConvoStep: 'if (botMsg.messageText === "Hello") result=Promise.resolve(); else result=Promise.reject(new Error("expected Hello"))'
39
+ assertConvoStep: ({ botMsg }) => {
40
+ if (botMsg.messageText === 'Hello') {
41
+ return Promise.resolve()
42
+ } else {
43
+ return Promise.reject(new Error('expected Hello'))
44
+ }
45
+ }
40
46
  }
41
47
  }]
42
48
  })
@@ -48,7 +54,10 @@ describe('logichooks.hookfromsrc', function () {
48
54
  [Capabilities.ASSERTERS]: [{
49
55
  ref: 'CUSTOMASSERTER',
50
56
  src: {
51
- assertConvoStep: 'if (botMsg.messageText === "Hello1") module.exports=Promise.resolve(); else module.exports=Promise.reject(new Error("expected Hello1"))'
57
+ assertConvoStep: ({ botMsg }) => {
58
+ if (botMsg.messageText === 'Hello1') return Promise.resolve()
59
+ else return Promise.reject(new Error('expected Hello1'))
60
+ }
52
61
  }
53
62
  }]
54
63
  })
@@ -74,7 +83,8 @@ describe('logichooks.hookfromsrc', function () {
74
83
  await compiler.convos[0].Run(container)
75
84
  assert.fail('it should have failed')
76
85
  } catch (err) {
77
- assert.isTrue(err.message.includes('Line 6: assertion error - Script assertConvoStep is not valid'))
86
+ console.log(err.message)
87
+ assert.isTrue(err.message.includes('Line 6: assertion error - Script assertConvoStep is not valid - only functions accepted'))
78
88
  }
79
89
  })
80
90
  })
@@ -27,7 +27,7 @@ describe('plugins.plugins', function () {
27
27
  })
28
28
 
29
29
  describe('load', function () {
30
- it('should map simple function to class', async function () {
30
+ it('should map simple function from module to class', async function () {
31
31
  const myCaps = {
32
32
  [Capabilities.PROJECTNAME]: 'plugins.load',
33
33
  [Capabilities.CONTAINERMODE]: 'fromfile1'
@@ -39,7 +39,20 @@ describe('plugins.plugins', function () {
39
39
  const response = await container.WaitBotSays()
40
40
  assert.equal(response.messageText, 'TEST')
41
41
  })
42
- it('should use UserSays function as class', async function () {
42
+ it('should map simple function from file to class', async function () {
43
+ const myCaps = {
44
+ [Capabilities.PROJECTNAME]: 'plugins.load',
45
+ [Capabilities.SAFEDIR]: './test/plugins/plugindir',
46
+ [Capabilities.CONTAINERMODE]: 'fromfile/botium-connector-fromfile1.js'
47
+ }
48
+ const driver = new BotDriver(myCaps)
49
+ const container = await driver.Build()
50
+
51
+ await container.UserSays({ messageText: 'TEST' })
52
+ const response = await container.WaitBotSays()
53
+ assert.equal(response.messageText, 'TEST')
54
+ })
55
+ it('should use UserSays function from module as class', async function () {
43
56
  const myCaps = {
44
57
  [Capabilities.PROJECTNAME]: 'plugins.load',
45
58
  [Capabilities.CONTAINERMODE]: 'fromfile2',
@@ -48,6 +61,20 @@ describe('plugins.plugins', function () {
48
61
  const driver = new BotDriver(myCaps)
49
62
  const container = await driver.Build()
50
63
 
64
+ await container.UserSays({ messageText: 'TEST' })
65
+ const response = await container.WaitBotSays()
66
+ assert.equal(response.messageText, 'MYPREFIX:TEST')
67
+ })
68
+ it('should use UserSays function from file as class', async function () {
69
+ const myCaps = {
70
+ [Capabilities.PROJECTNAME]: 'plugins.load',
71
+ [Capabilities.SAFEDIR]: './test/plugins/plugindir',
72
+ [Capabilities.CONTAINERMODE]: 'fromfile/botium-connector-fromfile2.js',
73
+ cap1: 'MYPREFIX'
74
+ }
75
+ const driver = new BotDriver(myCaps)
76
+ const container = await driver.Build()
77
+
51
78
  await container.UserSays({ messageText: 'TEST' })
52
79
  const response = await container.WaitBotSays()
53
80
  assert.equal(response.messageText, 'MYPREFIX:TEST')
@@ -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
+ })