botium-core 1.14.9 → 1.14.10

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-es.js CHANGED
@@ -35,7 +35,7 @@ import express from 'express';
35
35
  import bodyParser from 'body-parser';
36
36
 
37
37
  var name = "botium-core";
38
- var version$1 = "1.14.9";
38
+ var version$1 = "1.14.10";
39
39
  var description = "The Selenium for Chatbots";
40
40
  var main = "index.js";
41
41
  var module = "dist/botium-es.js";
@@ -98,6 +98,7 @@ var dependencies = {
98
98
  "socketio-auth": "^0.1.1",
99
99
  "swagger-jsdoc": "^6.2.8",
100
100
  "swagger-ui-express": "^5.0.0",
101
+ tinyglobby: "^0.2.10",
101
102
  uuid: "^9.0.1",
102
103
  "word-error-rate": "0.0.7",
103
104
  "write-yaml": "^1.0.0",
@@ -1082,9 +1083,9 @@ var LogicHookUtils_1 = class LogicHookUtils {
1082
1083
  caps
1083
1084
  }) {
1084
1085
  this.asserters = {};
1085
- this.globalAsserters = [];
1086
+ this.globalAsserterNames = [];
1086
1087
  this.logicHooks = {};
1087
- this.globalLogicHooks = [];
1088
+ this.globalLogicHookNames = [];
1088
1089
  this.userInputs = {};
1089
1090
  this.buildScriptContext = buildScriptContext;
1090
1091
  this.caps = caps;
@@ -1117,7 +1118,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1117
1118
  }
1118
1119
  this.asserters[asserter.ref] = this._loadClass(asserter, 'asserter');
1119
1120
  if (asserter.global) {
1120
- this.globalAsserters.push(asserter.ref);
1121
+ this.globalAsserterNames.push(asserter.ref);
1121
1122
  }
1122
1123
  });
1123
1124
  }
@@ -1128,7 +1129,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1128
1129
  }
1129
1130
  this.logicHooks[logicHook.ref] = this._loadClass(logicHook, 'logichook');
1130
1131
  if (logicHook.global) {
1131
- this.globalLogicHooks.push(logicHook.ref);
1132
+ this.globalLogicHookNames.push(logicHook.ref);
1132
1133
  }
1133
1134
  });
1134
1135
  }
@@ -1140,11 +1141,17 @@ var LogicHookUtils_1 = class LogicHookUtils {
1140
1141
  this.userInputs[userInput.ref] = this._loadClass(userInput, 'userinput');
1141
1142
  });
1142
1143
  }
1143
- getGlobalAsserter() {
1144
- return this.globalAsserters.map(name => this.asserters[name]);
1144
+ getGlobalAsserters() {
1145
+ return this.globalAsserterNames.reduce((agg, name) => ({
1146
+ ...agg,
1147
+ [name]: this.asserters[name]
1148
+ }), {});
1145
1149
  }
1146
- getGlobalLogicHook() {
1147
- return this.globalLogicHooks.map(name => this.logicHooks[name]);
1150
+ getGlobalLogicHooks() {
1151
+ return this.globalLogicHookNames.reduce((agg, name) => ({
1152
+ ...agg,
1153
+ [name]: this.logicHooks[name]
1154
+ }), {});
1148
1155
  }
1149
1156
  _loadClass({
1150
1157
  src,
@@ -2934,6 +2941,10 @@ class Convo$6 {
2934
2941
  let skipTranscriptStep = false;
2935
2942
  let conditionalGroupId = null;
2936
2943
  let conditionMetInGroup = false;
2944
+ let skipOptionalStep = false;
2945
+ // If there are optional step(s) in the conversation, and the message from the bot fails on each optional bot step(s) and/or mandatory bot step, then we have an unexpected message.
2946
+ // So in this case an unexpected error should be shown instead of the latest assertion error.
2947
+ let optionalStepAssertionError = false;
2937
2948
  let globalConvoStepParameters = container.caps[Capabilities.SCRIPTING_CONVO_STEP_PARAMETERS] || {};
2938
2949
  let retryBotMessageTimeoutEnd = null;
2939
2950
  let retryBotMessageConvoId = null;
@@ -2941,6 +2952,13 @@ class Convo$6 {
2941
2952
  for (let i = 0; i < this.conversation.length; i = retryBotMessageDropBotResponse ? i : i + 1) {
2942
2953
  retryBotMessageDropBotResponse = false;
2943
2954
  const convoStep = this.conversation[i];
2955
+ if (!convoStep.optional) {
2956
+ skipOptionalStep = false;
2957
+ }
2958
+ if (convoStep.optional && skipOptionalStep) {
2959
+ // If there are multiple optional steps, and the previous optional step was timeout, then the next optional step should be skipped to prevent too long convo run with multiple timeout.
2960
+ continue;
2961
+ }
2944
2962
  const rawConvoStepParameters = convoStep.logicHooks.find(lh => lh.name === 'CONVO_STEP_PARAMETERS')?.args;
2945
2963
  let convoStepParameters = {};
2946
2964
  if (rawConvoStepParameters && rawConvoStepParameters.length) {
@@ -3125,7 +3143,8 @@ class Convo$6 {
3125
3143
  debug$k(`${this.header.name}: bot says (cleaned by binary and base64 data and sourceData) ${JSON.stringify(coreMsg, null, 2)}`);
3126
3144
  } catch (err) {
3127
3145
  transcriptStep.botEnd = new Date();
3128
- if (convoStep.optional) {
3146
+ if (!(err.message.indexOf('Bot did not respond within') < 0) && convoStep.optional) {
3147
+ skipOptionalStep = true;
3129
3148
  continue;
3130
3149
  }
3131
3150
  const failErr = botiumErrorFromErr$1(`${this.header.name}/${convoStep.stepTag}: error waiting for bot - ${err.message}`, err);
@@ -3209,6 +3228,7 @@ class Convo$6 {
3209
3228
  }
3210
3229
  waitForBotSays = false;
3211
3230
  skipTranscriptStep = true;
3231
+ optionalStepAssertionError = true;
3212
3232
  return true;
3213
3233
  } else if (retryOn) {
3214
3234
  if (!retryBotMessageTimeoutEnd || retryBotMessageConvoId !== convoStep.stepTag) {
@@ -3226,9 +3246,18 @@ class Convo$6 {
3226
3246
  }
3227
3247
  }
3228
3248
  if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS]) {
3229
- assertErrors.push(err);
3249
+ if (optionalStepAssertionError) {
3250
+ optionalStepAssertionError = false;
3251
+ assertErrors.push(new BotiumError$2(`${this.header.name}: Unexpected message.`));
3252
+ } else {
3253
+ assertErrors.push(err);
3254
+ }
3230
3255
  return false;
3231
3256
  } else {
3257
+ if (optionalStepAssertionError) {
3258
+ optionalStepAssertionError = false;
3259
+ throw new BotiumError$2(`${this.header.name}: Unexpected message.`);
3260
+ }
3232
3261
  throw err;
3233
3262
  }
3234
3263
  };
@@ -3242,6 +3271,7 @@ class Convo$6 {
3242
3271
  if (convoStep.not) {
3243
3272
  try {
3244
3273
  this.scriptingEvents.assertBotNotResponse(response, tomatch, `${this.header.name}/${convoStep.stepTag}`, lastMeConvoStep, convoStepParameters);
3274
+ optionalStepAssertionError = false;
3245
3275
  } catch (err) {
3246
3276
  if (isErrorHandledWithOptionConvoStep(err)) {
3247
3277
  continue;
@@ -3250,6 +3280,7 @@ class Convo$6 {
3250
3280
  } else {
3251
3281
  try {
3252
3282
  this.scriptingEvents.assertBotResponse(response, tomatch, `${this.header.name}/${convoStep.stepTag}`, lastMeConvoStep, convoStepParameters);
3283
+ optionalStepAssertionError = false;
3253
3284
  } catch (err) {
3254
3285
  if (isErrorHandledWithOptionConvoStep(err)) {
3255
3286
  continue;
@@ -3259,6 +3290,7 @@ class Convo$6 {
3259
3290
  } else if (convoStep.sourceData) {
3260
3291
  try {
3261
3292
  this._compareObject(container, scriptingMemory, convoStep, botMsg.sourceData, convoStep.sourceData, botMsg, convoStepParameters);
3293
+ optionalStepAssertionError = false;
3262
3294
  } catch (err) {
3263
3295
  if (isErrorHandledWithOptionConvoStep(err)) {
3264
3296
  continue;
@@ -3285,11 +3317,13 @@ class Convo$6 {
3285
3317
  transcript,
3286
3318
  transcriptStep
3287
3319
  });
3320
+ optionalStepAssertionError = false;
3288
3321
  } catch (err) {
3289
3322
  const nextConvoStep = this.conversation[i + 1];
3290
3323
  if (convoStep.optional && nextConvoStep && nextConvoStep.sender === 'bot') {
3291
3324
  waitForBotSays = false;
3292
3325
  skipTranscriptStep = true;
3326
+ optionalStepAssertionError = true;
3293
3327
  continue;
3294
3328
  }
3295
3329
  const errors = err.toArray ? err.toArray() : [];
@@ -3318,8 +3352,17 @@ class Convo$6 {
3318
3352
  this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
3319
3353
  } catch (failErr) {}
3320
3354
  if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS] && err instanceof BotiumError$2) {
3321
- assertErrors.push(err);
3355
+ if (optionalStepAssertionError) {
3356
+ optionalStepAssertionError = false;
3357
+ assertErrors.push(new BotiumError$2(`${this.header.name}: Unexpected message.`));
3358
+ } else {
3359
+ assertErrors.push(err);
3360
+ }
3322
3361
  } else {
3362
+ if (optionalStepAssertionError) {
3363
+ optionalStepAssertionError = false;
3364
+ throw new BotiumError$2(`${this.header.name}: Unexpected message.`);
3365
+ }
3323
3366
  throw failErr;
3324
3367
  }
3325
3368
  }
@@ -5520,9 +5563,9 @@ var ScriptingProvider_1 = class ScriptingProvider {
5520
5563
  this.utterances = {};
5521
5564
  this.matchFn = null;
5522
5565
  this.asserters = {};
5523
- this.globalAsserter = {};
5566
+ this.globalAsserters = {};
5524
5567
  this.logicHooks = {};
5525
- this.globalLogicHook = {};
5568
+ this.globalLogicHooks = {};
5526
5569
  this.userInputs = {};
5527
5570
  this.partialConvos = {};
5528
5571
  this.scriptingMemories = [];
@@ -5891,7 +5934,8 @@ var ScriptingProvider_1 = class ScriptingProvider {
5891
5934
  return p(this.retryHelperAsserter, () => asserter[asserterType](params));
5892
5935
  }
5893
5936
  };
5894
- const convoAsserter = asserters.filter(a => this.asserters[a.name][asserterType]).map(a => ({
5937
+ const localAsserters = (asserters || []).filter(a => this.asserters[a.name][asserterType]);
5938
+ const convoStepPromises = localAsserters.map(a => ({
5895
5939
  asserter: a,
5896
5940
  promise: callAsserter(a, this.asserters[a.name], {
5897
5941
  convo,
@@ -5906,7 +5950,8 @@ var ScriptingProvider_1 = class ScriptingProvider {
5906
5950
  promise,
5907
5951
  asserter
5908
5952
  }) => updateExceptionContext(promise, asserter));
5909
- const globalAsserter = Object.values(this.globalAsserter).filter(a => a[asserterType]).map(a => ({
5953
+ const globalAsserters = Object.keys(this.globalAsserters).filter(name => localAsserters.map(a => a.name).indexOf(name) < 0).reduce((agg, name) => [...agg, this.globalAsserters[name]], []).filter(a => a[asserterType]);
5954
+ const globalPromises = globalAsserters.map(a => ({
5910
5955
  asserter: a,
5911
5956
  promise: p(this.retryHelperAsserter, () => a[asserterType]({
5912
5957
  convo,
@@ -5921,7 +5966,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5921
5966
  promise,
5922
5967
  asserter
5923
5968
  }) => updateExceptionContext(promise, asserter));
5924
- const allPromises = [...convoAsserter, ...globalAsserter];
5969
+ const allPromises = [...convoStepPromises, ...globalPromises];
5925
5970
  if (this.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS]) {
5926
5971
  return Promise.allSettled(allPromises).then(results => {
5927
5972
  const rejected = results.filter(result => result.status === 'rejected').map(result => result.reason);
@@ -5956,7 +6001,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5956
6001
  isGlobal: false,
5957
6002
  ...rest
5958
6003
  })));
5959
- const globalHooks = Object.values(this.globalLogicHook).filter(l => l[hookType]);
6004
+ const globalHooks = Object.keys(this.globalLogicHooks).filter(name => localHooks.map(l => l.name).indexOf(name) < 0).reduce((agg, name) => [...agg, this.globalLogicHooks[name]], []).filter(l => l[hookType]);
5960
6005
  const globalPromises = globalHooks.map(l => p(this.retryHelperLogicHook, () => l[hookType]({
5961
6006
  convo,
5962
6007
  convoStep,
@@ -6076,9 +6121,9 @@ var ScriptingProvider_1 = class ScriptingProvider {
6076
6121
  caps: this.caps
6077
6122
  });
6078
6123
  this.asserters = logicHookUtils.asserters;
6079
- this.globalAsserter = logicHookUtils.getGlobalAsserter();
6124
+ this.globalAsserters = logicHookUtils.getGlobalAsserters();
6080
6125
  this.logicHooks = logicHookUtils.logicHooks;
6081
- this.globalLogicHook = logicHookUtils.getGlobalLogicHook();
6126
+ this.globalLogicHooks = logicHookUtils.getGlobalLogicHooks();
6082
6127
  this.userInputs = logicHookUtils.userInputs;
6083
6128
  }
6084
6129
  IsAsserterValid(name) {