botium-core 1.13.17 → 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 (38) hide show
  1. package/README.md +0 -1
  2. package/dist/botium-cjs.js +118 -15
  3. package/dist/botium-cjs.js.map +1 -1
  4. package/dist/botium-es.js +118 -15
  5. package/dist/botium-es.js.map +1 -1
  6. package/package.json +2 -1
  7. package/src/BotDriver.js +2 -2
  8. package/src/Capabilities.js +6 -0
  9. package/src/containers/BaseContainer.js +7 -4
  10. package/src/containers/plugins/SimpleRestContainer.js +49 -0
  11. package/src/scripting/Convo.js +21 -0
  12. package/src/scripting/ScriptingProvider.js +19 -2
  13. package/src/scripting/logichook/LogicHookConsts.js +5 -1
  14. package/src/scripting/logichook/asserter/ButtonsAsserter.js +21 -8
  15. package/src/scripting/logichook/logichooks/ClearQueueLogicHook.js +0 -1
  16. package/src/scripting/logichook/logichooks/ConditionalBusinessHoursLogicHook.js +56 -0
  17. package/src/scripting/logichook/logichooks/ConditionalCapabilityValueBasedLogicHook.js +37 -0
  18. package/src/scripting/logichook/logichooks/ConditionalJsonPathBasedLogicHook.js +31 -0
  19. package/src/scripting/logichook/logichooks/ConditionalTimeBasedLogicHook.js +46 -0
  20. package/test/connectors/logicHook.js +0 -1
  21. package/test/connectors/simplerest.spec.js +79 -4
  22. package/test/scripting/asserters/buttonsAsserter.spec.js +84 -50
  23. package/test/scripting/logichooks/CustomConditionalLogicHook.js +21 -0
  24. package/test/scripting/logichooks/conditionalStepBusinessHoursLogicHook.spec.js +130 -0
  25. package/test/scripting/logichooks/conditionalStepCapabilityValueBasedLogicHook.spec.js +35 -0
  26. package/test/scripting/logichooks/conditionalStepJsonPathBasedLogicHook.spec.js +35 -0
  27. package/test/scripting/logichooks/conditionalStepTimeBasedLogicHook.spec.js +91 -0
  28. package/test/scripting/logichooks/convos/conditional_steps.convo.txt +12 -0
  29. package/test/scripting/logichooks/convos/conditional_steps_business_hours.convo.txt +16 -0
  30. package/test/scripting/logichooks/convos/conditional_steps_cap_value_based.convo.txt +12 -0
  31. package/test/scripting/logichooks/convos/conditional_steps_followed_by_bot_msg.convo.txt +15 -0
  32. package/test/scripting/logichooks/convos/conditional_steps_followed_by_me.convo.txt +18 -0
  33. package/test/scripting/logichooks/convos/conditional_steps_json_path_based.convo.txt.convo.txt +12 -0
  34. package/test/scripting/logichooks/convos/conditional_steps_multiple_condition_groups.convo.txt +20 -0
  35. package/test/scripting/logichooks/convos/conditional_steps_multiple_condition_groups_no_assertion.convo.txt +20 -0
  36. package/test/scripting/logichooks/convos/conditional_steps_time_based.convo.txt +12 -0
  37. package/test/scripting/logichooks/customConditionalStepLogicHook.spec.js +105 -0
  38. package/test/scripting/scriptingProvider.spec.js +1 -1
package/README.md CHANGED
@@ -4,7 +4,6 @@
4
4
 
5
5
  [![NPM](https://nodei.co/npm/botium-core.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/botium-core/)
6
6
 
7
- [ ![Codeship Status for codeforequity-at/botium-core](https://app.codeship.com/projects/0389ad40-cecc-0135-2ddc-161d5c3cc5fd/status?branch=master)](https://app.codeship.com/projects/262204)
8
7
  [![npm version](https://badge.fury.io/js/botium-core.svg)](https://badge.fury.io/js/botium-core)
9
8
  [![license](https://img.shields.io/github/license/mashape/apistatus.svg)]()
10
9
  [![Discourse users](https://img.shields.io/discourse/users?server=https%3A%2F%2Fforum.botium.ai%2F)](https://forum.botium.ai)
@@ -6,7 +6,7 @@ var util = require('util');
6
6
  var fs = require('fs');
7
7
  var path = require('path');
8
8
  var async = require('async');
9
- var rimraf$2 = require('rimraf');
9
+ var rimraf$1 = require('rimraf');
10
10
  var mkdirp = require('mkdirp');
11
11
  var sanitizeFilename = require('sanitize-filename');
12
12
  var moment = require('moment');
@@ -46,7 +46,7 @@ var util__default = /*#__PURE__*/_interopDefaultLegacy(util);
46
46
  var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
47
47
  var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
48
48
  var async__default = /*#__PURE__*/_interopDefaultLegacy(async);
49
- var rimraf__default = /*#__PURE__*/_interopDefaultLegacy(rimraf$2);
49
+ var rimraf__default = /*#__PURE__*/_interopDefaultLegacy(rimraf$1);
50
50
  var mkdirp__default = /*#__PURE__*/_interopDefaultLegacy(mkdirp);
51
51
  var sanitizeFilename__default = /*#__PURE__*/_interopDefaultLegacy(sanitizeFilename);
52
52
  var moment__default = /*#__PURE__*/_interopDefaultLegacy(moment);
@@ -81,7 +81,7 @@ var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
81
81
  var bodyParser__default = /*#__PURE__*/_interopDefaultLegacy(bodyParser);
82
82
 
83
83
  var name = "botium-core";
84
- var version$1 = "1.13.17";
84
+ var version$1 = "1.13.19";
85
85
  var description = "The Selenium for Chatbots";
86
86
  var main = "index.js";
87
87
  var module$1 = "dist/botium-es.js";
@@ -132,6 +132,7 @@ var dependencies = {
132
132
  "mime-types": "^2.1.35",
133
133
  mkdirp: "^3.0.1",
134
134
  moment: "^2.29.4",
135
+ "moment-timezone": "^0.5.43",
135
136
  mustache: "^4.2.0",
136
137
  "promise-retry": "^2.0.1",
137
138
  "promise.allsettled": "^1.0.6",
@@ -286,6 +287,12 @@ var Capabilities = {
286
287
  SIMPLEREST_POLL_INTERVAL: 'SIMPLEREST_POLL_INTERVAL',
287
288
  SIMPLEREST_POLL_TIMEOUT: 'SIMPLEREST_PING_TIMEOUT',
288
289
  SIMPLEREST_POLL_UPDATE_CONTEXT: 'SIMPLEREST_POLL_UPDATE_CONTEXT',
290
+ SIMPLEREST_CONTEXT_IGNORE_JSONPATH: 'SIMPLEREST_CONTEXT_IGNORE_JSONPATH',
291
+ SIMPLEREST_CONTEXT_IGNORE_MATCH: 'SIMPLEREST_CONTEXT_IGNORE_MATCH',
292
+ SIMPLEREST_CONTEXT_SKIP_JSONPATH: 'SIMPLEREST_CONTEXT_SKIP_JSONPATH',
293
+ SIMPLEREST_CONTEXT_SKIP_MATCH: 'SIMPLEREST_CONTEXT_SKIP_MATCH',
294
+ SIMPLEREST_CONTEXT_CONTINUE_JSONPATH: 'SIMPLEREST_CONTEXT_CONTINUE_JSONPATH',
295
+ SIMPLEREST_CONTEXT_CONTINUE_MATCH: 'SIMPLEREST_CONTEXT_CONTINUE_MATCH',
289
296
  SIMPLEREST_BODY_JSONPATH: 'SIMPLEREST_BODY_JSONPATH',
290
297
  SIMPLEREST_RESPONSE_JSONPATH: 'SIMPLEREST_RESPONSE_JSONPATH',
291
298
  SIMPLEREST_RESPONSE_HOOK: 'SIMPLEREST_RESPONSE_HOOK',
@@ -452,6 +459,12 @@ Capabilities.SIMPLEREST_POLL_REQUEST_HOOK;
452
459
  Capabilities.SIMPLEREST_POLL_INTERVAL;
453
460
  Capabilities.SIMPLEREST_POLL_TIMEOUT;
454
461
  Capabilities.SIMPLEREST_POLL_UPDATE_CONTEXT;
462
+ Capabilities.SIMPLEREST_CONTEXT_IGNORE_JSONPATH;
463
+ Capabilities.SIMPLEREST_CONTEXT_IGNORE_MATCH;
464
+ Capabilities.SIMPLEREST_CONTEXT_SKIP_JSONPATH;
465
+ Capabilities.SIMPLEREST_CONTEXT_SKIP_MATCH;
466
+ Capabilities.SIMPLEREST_CONTEXT_CONTINUE_JSONPATH;
467
+ Capabilities.SIMPLEREST_CONTEXT_CONTINUE_MATCH;
455
468
  Capabilities.SIMPLEREST_BODY_JSONPATH;
456
469
  Capabilities.SIMPLEREST_RESPONSE_JSONPATH;
457
470
  Capabilities.SIMPLEREST_RESPONSE_HOOK;
@@ -1192,6 +1205,18 @@ var LogicHookConsts = {
1192
1205
  }, {
1193
1206
  name: LOGIC_HOOK_INCLUDE$1,
1194
1207
  className: 'IncludeLogicHook'
1208
+ }, {
1209
+ name: 'CONDITIONAL_STEP_TIME_BASED',
1210
+ className: 'ConditionalTimeBasedLogicHook'
1211
+ }, {
1212
+ name: 'CONDITIONAL_STEP_BUSINESS_HOURS',
1213
+ className: 'ConditionalBusinessHoursLogicHook'
1214
+ }, {
1215
+ name: 'CONDITIONAL_STEP_CAPABILITY_VALUE_BASED',
1216
+ className: 'ConditionalCapabilityValueBasedLogicHook'
1217
+ }, {
1218
+ name: 'CONDITIONAL_STEP_JSON_PATH_BASED',
1219
+ className: 'ConditionalJsonPathBasedLogicHook.js'
1195
1220
  }],
1196
1221
  DEFAULT_USER_INPUTS: [{
1197
1222
  name: 'BUTTON',
@@ -3066,6 +3091,7 @@ class Convo$6 {
3066
3091
  throw failErr;
3067
3092
  }
3068
3093
  } else if (convoStep.sender === 'bot') {
3094
+ const previousWaitForBotSays = waitForBotSays;
3069
3095
  if (waitForBotSays) {
3070
3096
  botMsg = null;
3071
3097
  } else {
@@ -3121,6 +3147,23 @@ class Convo$6 {
3121
3147
  } catch (failErr) {}
3122
3148
  throw failErr;
3123
3149
  }
3150
+ if (convoStep.conditional) {
3151
+ const nextConvoStep = this.conversation[i + 1];
3152
+ if (!previousWaitForBotSays) {
3153
+ skipTranscriptStep = true;
3154
+ }
3155
+ waitForBotSays = false;
3156
+ if (!nextConvoStep || nextConvoStep.sender !== 'bot' || !nextConvoStep.logicHooks || !nextConvoStep.logicHooks.some(lh => lh.name.toUpperCase().startsWith('CONDITIONAL_STEP'))) {
3157
+ waitForBotSays = true;
3158
+ } else {
3159
+ const conditionalLogicHook = convoStep.logicHooks.find(lh => lh.name.startsWith('CONDITIONAL_STEP'));
3160
+ const nextConditionalLogicHook = nextConvoStep.logicHooks.find(lh => lh.name.startsWith('CONDITIONAL_STEP'));
3161
+ waitForBotSays = conditionalLogicHook.args[1] !== nextConditionalLogicHook.args[1];
3162
+ }
3163
+ if (convoStep.conditional.skip) {
3164
+ continue;
3165
+ }
3166
+ }
3124
3167
  if (!botMsg || !botMsg.messageText && !botMsg.media && !botMsg.buttons && !botMsg.cards && !botMsg.sourceData && !botMsg.nlp) {
3125
3168
  const failErr = new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot says nothing`);
3126
3169
  debug$j(failErr);
@@ -6415,10 +6458,16 @@ var ScriptingProvider_1 = class ScriptingProvider {
6415
6458
  convoFilter: null
6416
6459
  }, options);
6417
6460
  const expandedConvos = [];
6461
+ // The globalContext is going to keep the data even if the Object.assign which happening to create the myContext in _expandConvo function
6462
+ const context = {
6463
+ globalContext: {
6464
+ totalConvoCount: 0
6465
+ }
6466
+ };
6418
6467
  debug$9(`ExpandConvos - Using utterances expansion mode: ${this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE]}`);
6419
6468
  this.convos.forEach(convo => {
6420
6469
  convo.expandPartialConvos();
6421
- for (const expanded of this._expandConvo(convo, options, {})) {
6470
+ for (const expanded of this._expandConvo(convo, options, context)) {
6422
6471
  expanded.header.assertionCount = this.GetAssertionCount(expanded);
6423
6472
  if (options.justHeader) {
6424
6473
  const ConvoWithOnlyHeader = {
@@ -6434,6 +6483,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
6434
6483
  }
6435
6484
  });
6436
6485
  this.convos = expandedConvos;
6486
+ this.totalConvoCount = context.globalContext.totalConvoCount;
6437
6487
  if (!options.justHeader) {
6438
6488
  this._sortConvos();
6439
6489
  } else {
@@ -6445,16 +6495,23 @@ var ScriptingProvider_1 = class ScriptingProvider {
6445
6495
  // drop unwanted convos
6446
6496
  convoFilter: null
6447
6497
  }, options);
6498
+ // The globalContext is going to keep the data even if the Object.assign which happening to create the myContext in _expandConvo function
6499
+ const context = {
6500
+ globalContext: {
6501
+ totalConvoCount: 0
6502
+ }
6503
+ };
6448
6504
  debug$9(`ExpandConvos - Using utterances expansion mode: ${this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE]}`);
6449
6505
  // creating a nested generator, calling the other.
6450
6506
  // We hope this.convos does not changes while this iterator is used
6451
6507
  const _convosIterable = function* (options) {
6452
6508
  for (const convo of this.convos) {
6453
6509
  convo.expandPartialConvos();
6454
- yield* this._expandConvo(convo, options, {});
6510
+ yield* this._expandConvo(convo, options, context);
6455
6511
  }
6456
6512
  }.bind(this);
6457
6513
  this.convosIterable = _convosIterable(options);
6514
+ this.totalConvoCount = context.globalContext.totalConvoCount;
6458
6515
  }
6459
6516
 
6460
6517
  /**
@@ -6672,6 +6729,9 @@ var ScriptingProvider_1 = class ScriptingProvider {
6672
6729
  const expanded = Object.assign(lodash__default["default"].cloneDeep(currentConvo), {
6673
6730
  conversation: lodash__default["default"].cloneDeep(convoStepsStack)
6674
6731
  });
6732
+ if (!lodash__default["default"].isNil(lodash__default["default"].get(context, 'globalContext.totalConvoCount'))) {
6733
+ context.globalContext.totalConvoCount++;
6734
+ }
6675
6735
  if (!options.convoFilter || options.convoFilter(expanded)) {
6676
6736
  yield expanded;
6677
6737
  }
@@ -7190,9 +7250,6 @@ var Queue_1 = class Queue {
7190
7250
  }
7191
7251
  };
7192
7252
 
7193
- const {
7194
- rimraf: rimraf$1
7195
- } = rimraf__default["default"];
7196
7253
  const debug$7 = debug__default["default"]('botium-connector-BaseContainer');
7197
7254
  const {
7198
7255
  executeHook: executeHook$1,
@@ -7325,7 +7382,12 @@ var BaseContainer_1 = class BaseContainer {
7325
7382
  }, rimraffed => {
7326
7383
  if (this.caps[Capabilities.CLEANUPTEMPDIR]) {
7327
7384
  debug$7(`Cleanup rimrafing temp dir ${this.tempDirectory}`);
7328
- rimraf$1(this.tempDirectory).catch(err => debug$7(`Cleanup temp dir ${this.tempDirectory} failed: ${util__default["default"].inspect(err)}`)).finally(() => rimraffed());
7385
+ try {
7386
+ rimraf__default["default"].sync(this.tempDirectory);
7387
+ rimraffed();
7388
+ } catch (err) {
7389
+ rimraffed(new Error(`Cleanup temp directory ${this.tempDirectory} failed: ${util__default["default"].inspect(err)}`));
7390
+ }
7329
7391
  } else {
7330
7392
  rimraffed();
7331
7393
  }
@@ -7944,6 +8006,43 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
7944
8006
  }
7945
8007
  debug$4(`current session context: ${util__default["default"].inspect(this.view.context)}`);
7946
8008
  }
8009
+ const _isAnyContextJsonPathMatch = (capName, capNameMatch) => {
8010
+ const jsonPaths = getAllCapValues(capName, this.caps);
8011
+ if (jsonPaths.length > 0) {
8012
+ const jsonPathsMatch = getAllCapValues(capNameMatch, this.caps);
8013
+ for (const [index, jsonPath] of jsonPaths.entries()) {
8014
+ const contextNodes = jsonpath__default["default"].query(this.view.context, jsonPath);
8015
+ if (lodash__default["default"].isArray(contextNodes) && contextNodes.length > 0) {
8016
+ if (jsonPathsMatch[index]) {
8017
+ if (contextNodes[0] === jsonPathsMatch[index]) {
8018
+ return {
8019
+ jsonPath,
8020
+ match: contextNodes[0]
8021
+ };
8022
+ }
8023
+ } else {
8024
+ return {
8025
+ jsonPath
8026
+ };
8027
+ }
8028
+ }
8029
+ }
8030
+ }
8031
+ return null;
8032
+ };
8033
+ const ignoreMatch = _isAnyContextJsonPathMatch(Capabilities.SIMPLEREST_CONTEXT_IGNORE_JSONPATH, Capabilities.SIMPLEREST_CONTEXT_IGNORE_MATCH);
8034
+ if (ignoreMatch) {
8035
+ if (ignoreMatch.match) debug$4(`ignoring response for context match: ${ignoreMatch.jsonPath} = ${ignoreMatch.match}`);else debug$4(`ignoring response for context: ${ignoreMatch.jsonPath}`);
8036
+ return;
8037
+ }
8038
+ const skipMatch = _isAnyContextJsonPathMatch(Capabilities.SIMPLEREST_CONTEXT_SKIP_JSONPATH, Capabilities.SIMPLEREST_CONTEXT_SKIP_MATCH);
8039
+ if (skipMatch) {
8040
+ if (skipMatch.match) debug$4(`skipping response for context match: ${skipMatch.jsonPath} = ${skipMatch.match}`);else debug$4(`skipping response for context: ${skipMatch.jsonPath}`);
8041
+ setTimeout(() => this._doRequest({
8042
+ messageText: ''
8043
+ }, true, true), 0);
8044
+ return;
8045
+ }
7947
8046
  const result = [];
7948
8047
  if (isFromUser) {
7949
8048
  const _extractFrom = (root, jsonPaths) => {
@@ -8092,6 +8191,13 @@ var SimpleRestContainer_1 = class SimpleRestContainer {
8092
8191
  }
8093
8192
  }
8094
8193
  }
8194
+ const continueMatch = _isAnyContextJsonPathMatch(Capabilities.SIMPLEREST_CONTEXT_CONTINUE_JSONPATH, Capabilities.SIMPLEREST_CONTEXT_CONTINUE_MATCH);
8195
+ if (continueMatch) {
8196
+ if (continueMatch.match) debug$4(`continue with next response for context match: ${continueMatch.jsonPath} = ${continueMatch.match}`);else debug$4(`continue with next response for context: ${continueMatch.jsonPath}`);
8197
+ setTimeout(() => this._doRequest({
8198
+ messageText: ''
8199
+ }, true, true), 0);
8200
+ }
8095
8201
  return result;
8096
8202
  }
8097
8203
  _doRequest(msg, isFromUser, updateContext) {
@@ -8849,21 +8955,18 @@ var PluginConnectorContainer_1 = class PluginConnectorContainer extends BaseCont
8849
8955
  }
8850
8956
  };
8851
8957
 
8852
- var require$$4 = getCjsExportFromNamespace(_package$1);
8958
+ var require$$3 = getCjsExportFromNamespace(_package$1);
8853
8959
 
8854
8960
  const {
8855
8961
  rimraf
8856
8962
  } = rimraf__default["default"];
8857
- const {
8858
- mkdirpSync
8859
- } = mkdirp__default["default"];
8860
8963
  const {
8861
8964
  boolean
8862
8965
  } = boolean__default["default"];
8863
8966
  const debug$1 = debug__default["default"]('botium-core-BotDriver');
8864
8967
  const {
8865
8968
  version
8866
- } = require$$4;
8969
+ } = require$$3;
8867
8970
  var BotDriver_1 = class BotDriver {
8868
8971
  constructor(caps = {}, sources = {}, envs = {}) {
8869
8972
  this.eventEmitter = new events__default["default"]();
@@ -8953,7 +9056,7 @@ var BotDriver_1 = class BotDriver {
8953
9056
  }, tempDirectoryCreated => {
8954
9057
  tempDirectory = path__default["default"].resolve(process.cwd(), this.caps[Capabilities.TEMPDIR], sanitizeFilename__default["default"](`${this.caps[Capabilities.PROJECTNAME]} ${moment__default["default"]().format('YYYYMMDD HHmmss')} ${randomatic__default["default"]('Aa0', 5)}`));
8955
9058
  try {
8956
- mkdirpSync(tempDirectory);
9059
+ mkdirp__default["default"].sync(tempDirectory);
8957
9060
  tempDirectoryCreated();
8958
9061
  } catch (err) {
8959
9062
  tempDirectoryCreated(new Error(`Unable to create temp directory ${tempDirectory}: ${err.message}`));