botium-core 1.13.1 → 1.13.4

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 (56) hide show
  1. package/.eslintrc.js +6 -3
  2. package/dist/botium-cjs.js +291 -86
  3. package/dist/botium-cjs.js.map +1 -1
  4. package/dist/botium-es.js +290 -86
  5. package/dist/botium-es.js.map +1 -1
  6. package/package.json +3 -1
  7. package/src/Capabilities.js +4 -1
  8. package/src/Defaults.js +4 -0
  9. package/src/containers/plugins/SimpleRestContainer.js +23 -16
  10. package/src/grid/inbound/proxy.js +2 -1
  11. package/src/mocks/BotiumMockScripting.js +1 -0
  12. package/src/scripting/Convo.js +16 -10
  13. package/src/scripting/MatchFunctions.js +10 -0
  14. package/src/scripting/ScriptingProvider.js +162 -69
  15. package/src/scripting/logichook/LogicHookConsts.js +1 -1
  16. package/src/scripting/logichook/asserter/WerAsserter.js +59 -0
  17. package/src/scripting/logichook/logichooks/UpdateCustomLogicHook.js +3 -2
  18. package/test/compiler/compilercsv.spec.js +104 -3
  19. package/test/compiler/compilerjson.spec.js +0 -2
  20. package/test/compiler/compilerxlsx.spec.js +1 -1
  21. package/test/compiler/convos/csv/utterances_liveperson2.csv +12 -0
  22. package/test/connectors/simplerest.spec.js +1012 -969
  23. package/test/convo/fillAndApplyScriptingMemory.spec.js +804 -785
  24. package/test/convo/partialconvo.spec.js +345 -339
  25. package/test/driver/capabilities.spec.js +156 -151
  26. package/test/logichooks/hookfromsrc.spec.js +79 -73
  27. package/test/plugins/plugins.spec.js +44 -42
  28. package/test/scripting/asserters/buttonsAsserter.spec.js +257 -240
  29. package/test/scripting/asserters/cardsAsserter.spec.js +214 -212
  30. package/test/scripting/asserters/convos/wer_threshold_nok.yml +7 -0
  31. package/test/scripting/asserters/convos/wer_threshold_ok.yml +7 -0
  32. package/test/scripting/asserters/intentConfidenceAsserter.spec.js +34 -35
  33. package/test/scripting/asserters/jsonpathAsserter.spec.js +307 -308
  34. package/test/scripting/asserters/mediaAsserter.spec.js +236 -234
  35. package/test/scripting/asserters/werAsserter.spec.js +51 -0
  36. package/test/scripting/logichooks/setClearScriptingMemory.spec.js +202 -192
  37. package/test/scripting/matching/matchingmode.spec.js +306 -258
  38. package/test/scripting/scriptingProvider.spec.js +720 -630
  39. package/test/scripting/scriptingmemory/fillScriptingMemoryFromFile.spec.js +299 -281
  40. package/test/scripting/scriptingmemory/useScriptingMemoryForAssertion.spec.js +94 -80
  41. package/test/scripting/userinputs/defaultUserInputs.spec.js +233 -127
  42. package/test/scripting/userinputs/mediaInputConvos.spec.js +409 -403
  43. package/test/scripting/utteranceexpansion/associateByIndex.spec.js +259 -0
  44. package/test/scripting/utteranceexpansion/convos/associate_utterances_by_index.json +33 -0
  45. package/test/scripting/utteranceexpansion/convos/media.convo.txt +19 -0
  46. package/test/scripting/utteranceexpansion/files/step0voice0.wav +0 -0
  47. package/test/scripting/utteranceexpansion/files/step0voice1.wav +0 -0
  48. package/test/scripting/utteranceexpansion/files/step0voice2.wav +0 -0
  49. package/test/scripting/utteranceexpansion/files/step1voice0.wav +0 -0
  50. package/test/scripting/utteranceexpansion/files/step2voice0.wav +0 -0
  51. package/test/scripting/utteranceexpansion/files/step2voice1.wav +0 -0
  52. package/test/scripting/utteranceexpansion/files/step2voice2.wav +0 -0
  53. package/test/scripting/utteranceexpansion/files/step2voice4.wav +0 -0
  54. package/test/scripting/utteranceexpansion/files/step2voice5.wav +0 -0
  55. package/test/security/allowUnsafe.spec.js +274 -268
  56. package/test/utils.spec.js +40 -38
@@ -0,0 +1,59 @@
1
+ // const _ = require('lodash')
2
+ const speechScorer = require('word-error-rate')
3
+ const { BotiumError } = require('../../BotiumError')
4
+
5
+ module.exports = class WerAsserter {
6
+ constructor (context, caps = {}) {
7
+ this.context = context
8
+ this.caps = caps
9
+ this.name = 'WerAsserter'
10
+ }
11
+
12
+ assertConvoStep ({ convo, convoStep, args, botMsg }) {
13
+ if (!args || args.length < 1) {
14
+ return Promise.reject(new BotiumError(`${convoStep.stepTag}: WerAsserter Missing argument`,
15
+ {
16
+ type: 'asserter',
17
+ subtype: 'wrong parameters',
18
+ source: this.name,
19
+ cause: { args }
20
+ }
21
+ ))
22
+ }
23
+ if (args.length > 2) {
24
+ return Promise.reject(new BotiumError(`${convoStep.stepTag}: WerAsserter Too much argument "${args}"`,
25
+ {
26
+ type: 'asserter',
27
+ subtype: 'wrong parameters',
28
+ source: this.name,
29
+ cause: { args }
30
+ }
31
+ ))
32
+ }
33
+
34
+ const utterance = args[0]
35
+ const threshold = args[1]
36
+
37
+ const wer = speechScorer.wordErrorRate(botMsg.messageText, utterance)
38
+ if (wer > threshold) {
39
+ return Promise.reject(new BotiumError(
40
+ `${convoStep.stepTag}: Word error rate ${wer} > ${threshold} for ${utterance}`,
41
+ {
42
+ type: 'asserter',
43
+ source: this.name,
44
+ context: {
45
+ params: {
46
+ args
47
+ }
48
+ },
49
+ cause: {
50
+ expected: `Word error rate <= ${threshold}`,
51
+ actual: `Word error rate = ${wer}`
52
+ }
53
+ }
54
+ ))
55
+ }
56
+
57
+ return Promise.resolve()
58
+ }
59
+ }
@@ -1,5 +1,6 @@
1
1
  const util = require('util')
2
2
  const _ = require('lodash')
3
+ const { ConvoStepLogicHook } = require('../../Convo')
3
4
 
4
5
  module.exports = class UpdateCustomLogicHook {
5
6
  constructor (context, caps = {}, globalArgs = {}) {
@@ -14,10 +15,10 @@ module.exports = class UpdateCustomLogicHook {
14
15
  const validConvoSteps = convo.conversation.filter(s => s.sender === 'me')
15
16
  for (const convoStep of validConvoSteps) {
16
17
  convoStep.logicHooks = (convoStep.logicHooks || [])
17
- convoStep.logicHooks.push({
18
+ convoStep.logicHooks.push(new ConvoStepLogicHook({
18
19
  name: 'UPDATE_CUSTOM',
19
20
  args
20
- })
21
+ }))
21
22
  }
22
23
  }
23
24
 
@@ -24,6 +24,41 @@ const buildContext = () => {
24
24
  return result
25
25
  }
26
26
 
27
+ const assertLivepersonV2 = (context) => {
28
+ assert.lengthOf(context.utterances, 4)
29
+ assert.lengthOf(context.convos, 0)
30
+ assert.deepEqual(context.utterances[0], {
31
+ name: 'Cancel Pre-Authorized Payment',
32
+ utterances: [
33
+ 'Can I call back to re-start the payment',
34
+ 'Can I stop a direct debit',
35
+ 'Can you cancel a preauthorized payment for me',
36
+ 'Can you help me cancel my pre authorized payment'
37
+ ]
38
+ })
39
+ assert.deepEqual(context.utterances[1], {
40
+ name: 'Payee - Correct/Modify',
41
+ utterances: [
42
+ 'Can I modify my existing payee?',
43
+ 'Can you change the name of the payee?'
44
+ ]
45
+ })
46
+ assert.deepEqual(context.utterances[2], {
47
+ name: 'Pre-Authorized Payment - Correct/Modify',
48
+ utterances: [
49
+ 'Can I delay my payment to (company)?'
50
+ ]
51
+ })
52
+ assert.deepEqual(context.utterances[3], {
53
+ name: 'E-Transfer Recipient – Delete',
54
+ utterances: [
55
+ 'Can you delete my friend as an e-transfer recipient?',
56
+ 'Can you delete this e-transfer recipient',
57
+ 'Can you delete this recipient'
58
+ ]
59
+ })
60
+ }
61
+
27
62
  describe('compiler.compilercsv', function () {
28
63
  describe('ROW_PER_MESSAGE mode, full', function () {
29
64
  it('should read basic case', async function () {
@@ -357,7 +392,7 @@ describe('compiler.compilercsv', function () {
357
392
  assert.equal(err.message, 'Failed to parse conversation. Section "goodbye" unknown.')
358
393
  }
359
394
  })
360
- it('should not parse multi column uttrances as convos ???', async function () {
395
+ it('should not parse multi column uttrances as convos ??? 2', async function () {
361
396
  const scriptBuffer = fs.readFileSync(path.resolve(__dirname, CONVOS_DIR, 'utterances_multicolumn5col.csv'))
362
397
  const context = buildContext()
363
398
 
@@ -459,7 +494,6 @@ describe('compiler.compilercsv', function () {
459
494
  ]
460
495
  })
461
496
  })
462
- // maybe we could read it
463
497
  it('should read liveperson format with SCRIPTING_CSV_STARTROW', async function () {
464
498
  const scriptBuffer = fs.readFileSync(path.resolve(__dirname, CONVOS_DIR, 'utterances_liveperson.csv'))
465
499
  const context = buildContext()
@@ -482,6 +516,20 @@ describe('compiler.compilercsv', function () {
482
516
  ]
483
517
  })
484
518
  })
519
+ it('should read liveperson format 2 with SCRIPTING_CSV_STARTROW', async function () {
520
+ const scriptBuffer = fs.readFileSync(path.resolve(__dirname, CONVOS_DIR, 'utterances_liveperson2.csv'))
521
+ const context = buildContext()
522
+
523
+ const caps = {
524
+ [Capabilities.SCRIPTING_CSV_UTTERANCE_STARTROW]: 9,
525
+ [Capabilities.SCRIPTING_CSV_UTTERANCE_STOP_ON_EMPTY]: true,
526
+ [Capabilities.SCRIPTING_CSV_LEGACY_MODE_OFF]: true
527
+ }
528
+ const compiler = new Compiler(context, Object.assign({}, DefaultCapabilities, caps))
529
+
530
+ compiler.Compile(scriptBuffer, 'SCRIPTING_TYPE_UTTERANCES')
531
+ assertLivepersonV2(context)
532
+ })
485
533
  it('should read liveperson format with SCRIPTING_CSV_STARTROW without stop', async function () {
486
534
  const scriptBuffer = fs.readFileSync(path.resolve(__dirname, CONVOS_DIR, 'utterances_liveperson.csv'))
487
535
  const context = buildContext()
@@ -501,7 +549,45 @@ describe('compiler.compilercsv', function () {
501
549
  const context = buildContext()
502
550
 
503
551
  const caps = {
504
- [Capabilities.SCRIPTING_CSV_UTTERANCE_STARTROW]: 12,
552
+ [Capabilities.SCRIPTING_CSV_UTTERANCE_STARTROW_HEADER]: 'SampleSentences',
553
+ [Capabilities.SCRIPTING_CSV_UTTERANCE_STOP_ON_EMPTY]: true,
554
+ [Capabilities.SCRIPTING_CSV_LEGACY_MODE_OFF]: true
555
+ }
556
+
557
+ const compiler = new Compiler(context, Object.assign({}, DefaultCapabilities, caps))
558
+
559
+ compiler.Compile(scriptBuffer, 'SCRIPTING_TYPE_UTTERANCES')
560
+ assert.lengthOf(context.utterances, 18)
561
+ assert.lengthOf(context.convos, 0)
562
+ assert.deepEqual(context.utterances[0], {
563
+ name: 'ask about installation',
564
+ utterances: [
565
+ 'about my appointment',
566
+ 'book service installation appointment'
567
+ ]
568
+ })
569
+ })
570
+ it('should read liveperson format 2 with SCRIPTING_CSV_STARTROWHEADER', async function () {
571
+ const scriptBuffer = fs.readFileSync(path.resolve(__dirname, CONVOS_DIR, 'utterances_liveperson2.csv'))
572
+ const context = buildContext()
573
+
574
+ const caps = {
575
+ [Capabilities.SCRIPTING_CSV_UTTERANCE_STARTROW_HEADER]: 'SampleSentences',
576
+ [Capabilities.SCRIPTING_CSV_UTTERANCE_STOP_ON_EMPTY]: true,
577
+ [Capabilities.SCRIPTING_CSV_LEGACY_MODE_OFF]: true
578
+ }
579
+
580
+ const compiler = new Compiler(context, Object.assign({}, DefaultCapabilities, caps))
581
+
582
+ compiler.Compile(scriptBuffer, 'SCRIPTING_TYPE_UTTERANCES')
583
+ assertLivepersonV2(context)
584
+ })
585
+ it('should read liveperson format with SCRIPTING_CSV_STARTROWHEADER 2', async function () {
586
+ const scriptBuffer = fs.readFileSync(path.resolve(__dirname, CONVOS_DIR, 'utterances_liveperson.csv'))
587
+ const context = buildContext()
588
+
589
+ const caps = {
590
+ [Capabilities.SCRIPTING_CSV_UTTERANCE_STARTROW_HEADER]: 'SampleSentences',
505
591
  [Capabilities.SCRIPTING_CSV_UTTERANCE_STOP_ON_EMPTY]: true,
506
592
  [Capabilities.SCRIPTING_CSV_LEGACY_MODE_OFF]: true
507
593
  }
@@ -519,6 +605,21 @@ describe('compiler.compilercsv', function () {
519
605
  ]
520
606
  })
521
607
  })
608
+ it('should read liveperson format 2 with SCRIPTING_CSV_STARTROWHEADER 2', async function () {
609
+ const scriptBuffer = fs.readFileSync(path.resolve(__dirname, CONVOS_DIR, 'utterances_liveperson2.csv'))
610
+ const context = buildContext()
611
+
612
+ const caps = {
613
+ [Capabilities.SCRIPTING_CSV_UTTERANCE_STARTROW_HEADER]: 'SampleSentences',
614
+ [Capabilities.SCRIPTING_CSV_UTTERANCE_STOP_ON_EMPTY]: true,
615
+ [Capabilities.SCRIPTING_CSV_LEGACY_MODE_OFF]: true
616
+ }
617
+
618
+ const compiler = new Compiler(context, Object.assign({}, DefaultCapabilities, caps))
619
+
620
+ compiler.Compile(scriptBuffer, 'SCRIPTING_TYPE_UTTERANCES')
621
+ assertLivepersonV2(context)
622
+ })
522
623
  it('should work with variable length csv', async function () {
523
624
  const scriptBuffer = fs.readFileSync(path.resolve(__dirname, CONVOS_DIR, 'utterances_variable_row_len.csv'))
524
625
  const context = buildContext()
@@ -109,9 +109,7 @@ describe('compiler.compilerjson', function () {
109
109
  assert.equal(context.scriptingMemories[0].header.name, 'scenario1')
110
110
  assert.equal(context.scriptingMemories[0].values.$var1, 'var1_1')
111
111
  })
112
- })
113
112
 
114
- describe('compiler.decompilerjson', function () {
115
113
  it('should decompile convos', async function () {
116
114
  const scriptBuffer = fs.readFileSync(path.resolve(__dirname, CONVOS_DIR, 'convos_and_utterances.json'))
117
115
  const context = buildContext()
@@ -473,7 +473,7 @@ describe('compiler.compilerxlsx', function () {
473
473
 
474
474
  assert.lengthOf(context.utterances, 0)
475
475
  })
476
- it('should read 3 convos without name (forced)', async function () {
476
+ it('should read 3 convos without name (forced) 2', async function () {
477
477
  const scriptBuffer = fs.readFileSync(path.resolve(__dirname, CONVOS_DIR, 'convos_2convos_without_names_noheader.xlsx'))
478
478
  const context = buildContext()
479
479
 
@@ -0,0 +1,12 @@
1
+ Cancel Pre-Authorized Payment,Payee - Correct/Modify,Pre-Authorized Payment - Correct/Modify,E-Transfer Recipient – Delete
2
+ DisplayName,DisplayName,DisplayName,DisplayName
3
+ Cancel Pre-Authorized Payment,Payee - Correct/Modify,Pre-Authorized Payment - Correct/Modify,E-Transfer Recipient – Delete
4
+ KeyPhrases,KeyPhrases,KeyPhrases,KeyPhrases
5
+ ,,,
6
+ MetaIntent,MetaIntent,MetaIntent,MetaIntent
7
+ ,,,
8
+ SampleSentences,SampleSentences,SampleSentences,SampleSentences
9
+ Can I call back to re-start the payment,Can I modify my existing payee?,Can I delay my payment to (company)?,Can you delete my friend as an e-transfer recipient?
10
+ Can I stop a direct debit,Can you change the name of the payee?,,Can you delete this e-transfer recipient
11
+ Can you cancel a preauthorized payment for me,,,Can you delete this recipient
12
+ Can you help me cancel my pre authorized payment,,,