wingbot 3.67.28 → 3.67.30
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wingbot",
|
|
3
|
-
"version": "3.67.
|
|
3
|
+
"version": "3.67.30",
|
|
4
4
|
"description": "Enterprise Messaging Bot Conversation Engine",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"doc": "npm run doc:gql && node ./bin/makeApiDoc.js && cpy ./CHANGELOG.md ./doc && gitbook install ./doc && gitbook build ./doc && rimraf -rf ./docs && rimraf --rf ./doc/CHANGELOG.md && move-cli ./doc/_book ./docs",
|
|
11
11
|
"test": "npm run test:lint && npm run test:coverage && npm run test:coverage:threshold",
|
|
12
12
|
"test:coverage": "nyc --reporter=html mocha ./test && nyc report",
|
|
13
|
-
"test:coverage:threshold": "nyc check-coverage --lines 89 --functions
|
|
13
|
+
"test:coverage:threshold": "nyc check-coverage --lines 89 --functions 88 --branches 80",
|
|
14
14
|
"test:backend": "mocha ./test",
|
|
15
15
|
"test:lint": "eslint --ext .js src test *.js plugins"
|
|
16
16
|
},
|
|
@@ -134,6 +134,7 @@ class ConversationTester {
|
|
|
134
134
|
};
|
|
135
135
|
this._output = '';
|
|
136
136
|
this._cachedBot = null;
|
|
137
|
+
this._cachedBotSnapshot = null;
|
|
137
138
|
this._log = options.log || console;
|
|
138
139
|
}
|
|
139
140
|
|
|
@@ -165,9 +166,10 @@ class ConversationTester {
|
|
|
165
166
|
* @param {object} validationRequestBody
|
|
166
167
|
* @param {number} [step]
|
|
167
168
|
* @param {string} [lang]
|
|
169
|
+
* @param {string} [snapshot]
|
|
168
170
|
* @returns {Promise<TestsOutput>}
|
|
169
171
|
*/
|
|
170
|
-
async test (validationRequestBody = null, step = null, lang = null) {
|
|
172
|
+
async test (validationRequestBody = null, step = null, lang = null, snapshot = null) {
|
|
171
173
|
if (step <= 1) {
|
|
172
174
|
this._cachedBot = null;
|
|
173
175
|
}
|
|
@@ -191,10 +193,20 @@ class ConversationTester {
|
|
|
191
193
|
for (const testsGroup of testsGroups) {
|
|
192
194
|
let stepResult;
|
|
193
195
|
if (testsGroup.type === 'texts') {
|
|
194
|
-
stepResult = await this._runTextCaseTests(
|
|
196
|
+
stepResult = await this._runTextCaseTests(
|
|
197
|
+
testsGroup,
|
|
198
|
+
botconfig,
|
|
199
|
+
lang,
|
|
200
|
+
snapshot
|
|
201
|
+
);
|
|
195
202
|
}
|
|
196
203
|
if (testsGroup.type === 'steps') {
|
|
197
|
-
stepResult = await this._runStepCaseTests(
|
|
204
|
+
stepResult = await this._runStepCaseTests(
|
|
205
|
+
testsGroup,
|
|
206
|
+
botconfig,
|
|
207
|
+
lang,
|
|
208
|
+
snapshot
|
|
209
|
+
);
|
|
198
210
|
}
|
|
199
211
|
results.push(stepResult);
|
|
200
212
|
}
|
|
@@ -403,11 +415,13 @@ class ConversationTester {
|
|
|
403
415
|
* @param {TestsGroup} testsGroup
|
|
404
416
|
* @param {object} [botconfig]
|
|
405
417
|
* @param {string} [lang]
|
|
418
|
+
* @param {string} [snapshot]
|
|
406
419
|
* @returns {Promise<Tester>}
|
|
407
420
|
*/
|
|
408
|
-
async _createTester (testsGroup, botconfig = null, lang = null) {
|
|
409
|
-
if (!this._cachedBot) {
|
|
410
|
-
this.
|
|
421
|
+
async _createTester (testsGroup, botconfig = null, lang = null, snapshot = null) {
|
|
422
|
+
if (!this._cachedBot || this._cachedBotSnapshot !== snapshot) {
|
|
423
|
+
this._cachedBotSnapshot = snapshot;
|
|
424
|
+
this._cachedBot = Promise.resolve(this._botFactory(true, snapshot))
|
|
411
425
|
.then((cb) => {
|
|
412
426
|
if (botconfig) {
|
|
413
427
|
cb.buildWithSnapshot(botconfig.blocks, Number.MAX_SAFE_INTEGER);
|
|
@@ -440,9 +454,10 @@ class ConversationTester {
|
|
|
440
454
|
* @param {TestsGroup} testsGroup
|
|
441
455
|
* @param {object} botconfig
|
|
442
456
|
* @param {string} [lang]
|
|
457
|
+
* @param {string} [snapshot]
|
|
443
458
|
*/
|
|
444
|
-
async _runTextCaseTests (testsGroup, botconfig = null, lang = null) {
|
|
445
|
-
const t = await this._createTester(testsGroup, botconfig, lang);
|
|
459
|
+
async _runTextCaseTests (testsGroup, botconfig = null, lang = null, snapshot = null) {
|
|
460
|
+
const t = await this._createTester(testsGroup, botconfig, lang, snapshot);
|
|
446
461
|
let out = '';
|
|
447
462
|
let passing = 0;
|
|
448
463
|
let longestText = 0;
|
|
@@ -457,7 +472,7 @@ class ConversationTester {
|
|
|
457
472
|
|
|
458
473
|
const { textCaseParallel } = this._options;
|
|
459
474
|
const runTestCase = (textCase) => this
|
|
460
|
-
.executeTextCase(testsGroup, t, textCase, botconfig, longestText, lang);
|
|
475
|
+
.executeTextCase(testsGroup, t, textCase, botconfig, longestText, lang, snapshot);
|
|
461
476
|
|
|
462
477
|
while (iterate.length > 0) {
|
|
463
478
|
const cases = iterate.splice(0, textCaseParallel);
|
|
@@ -500,12 +515,13 @@ class ConversationTester {
|
|
|
500
515
|
* @param {TestsGroup} testsGroup
|
|
501
516
|
* @param {object} botconfig
|
|
502
517
|
* @param {string} [lang]
|
|
518
|
+
* @param {string} [snapshot]
|
|
503
519
|
*/
|
|
504
|
-
async _runStepCaseTests (testsGroup, botconfig = null, lang = null) {
|
|
520
|
+
async _runStepCaseTests (testsGroup, botconfig = null, lang = null, snapshot = null) {
|
|
505
521
|
const out = [];
|
|
506
522
|
|
|
507
523
|
for (const testCase of testsGroup.testCases) {
|
|
508
|
-
const t = await this._createTester(testsGroup, botconfig, lang);
|
|
524
|
+
const t = await this._createTester(testsGroup, botconfig, lang, snapshot);
|
|
509
525
|
let o = '';
|
|
510
526
|
let fail = null;
|
|
511
527
|
// @ts-ignore
|
|
@@ -538,10 +554,19 @@ class ConversationTester {
|
|
|
538
554
|
* @param {*} botconfig
|
|
539
555
|
* @param {number} longestText
|
|
540
556
|
* @param {string} [lang]
|
|
557
|
+
* @param {string} [snapshot]
|
|
541
558
|
*/
|
|
542
|
-
async executeTextCase (
|
|
559
|
+
async executeTextCase (
|
|
560
|
+
testsGroup,
|
|
561
|
+
t,
|
|
562
|
+
textCase,
|
|
563
|
+
botconfig,
|
|
564
|
+
longestText,
|
|
565
|
+
lang = null,
|
|
566
|
+
snapshot = null
|
|
567
|
+
) {
|
|
543
568
|
if (this._options.useConversationForTextTestCases) {
|
|
544
|
-
const tester = await this._createTester(testsGroup, botconfig, lang);
|
|
569
|
+
const tester = await this._createTester(testsGroup, botconfig, lang, snapshot);
|
|
545
570
|
|
|
546
571
|
try {
|
|
547
572
|
await tester.text(textCase.text);
|
package/src/graphApi/GraphApi.js
CHANGED
|
@@ -19,6 +19,11 @@ const DEFAULT_CACHE = 86400000; // 24 hours
|
|
|
19
19
|
* @param {object[]} [errors]
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {object} RequestParams
|
|
24
|
+
* @param {string} [snapshot]
|
|
25
|
+
*/
|
|
26
|
+
|
|
22
27
|
/** @typedef {import('../CallbackAuditLog')} AuditLog */
|
|
23
28
|
/** @typedef {import('graphql')} GqlLib */
|
|
24
29
|
|
|
@@ -110,9 +115,10 @@ class GraphApi {
|
|
|
110
115
|
* @param {string} [headers.Referer]
|
|
111
116
|
* @param {string} [headers.referer]
|
|
112
117
|
* @param {string} [wingbotToken]
|
|
118
|
+
* @param {RequestParams} [params]
|
|
113
119
|
* @returns {Promise<GraphQlResponse>}
|
|
114
120
|
*/
|
|
115
|
-
async request (body, headers, wingbotToken = undefined) {
|
|
121
|
+
async request (body, headers, wingbotToken = undefined, params = {}) {
|
|
116
122
|
assert.ok(body && typeof body === 'object', 'GraphQL request should be an object with a request property');
|
|
117
123
|
assert.equal(typeof body.query, 'string', 'GraphQL request should contain a query property');
|
|
118
124
|
|
|
@@ -149,7 +155,8 @@ class GraphApi {
|
|
|
149
155
|
const ctx = {
|
|
150
156
|
token,
|
|
151
157
|
groups: this._defaultGroups,
|
|
152
|
-
audit
|
|
158
|
+
audit,
|
|
159
|
+
params
|
|
153
160
|
};
|
|
154
161
|
|
|
155
162
|
const response = await this._gql.graphql({
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
'use strict';
|
|
5
5
|
|
|
6
6
|
const apiAuthorizer = require('./apiAuthorizer');
|
|
7
|
-
const { apiTextOutputFilter } = require('../utils/deepMapTools');
|
|
7
|
+
const { apiTextOutputFilter, mapObject, defaultMapperFactory } = require('../utils/deepMapTools');
|
|
8
|
+
|
|
9
|
+
/** @typedef {import('../utils/deepMapTools').Mapper} Mapper */
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* @typedef {object} ConversationsAPI
|
|
@@ -47,6 +49,7 @@ const { apiTextOutputFilter } = require('../utils/deepMapTools');
|
|
|
47
49
|
* @param {string[]|Function} [acl] - limit api to array of groups or use auth function
|
|
48
50
|
* @param {object} options
|
|
49
51
|
* @param {textFilter} [options.stateTextFilter] - optional funcion for filtering data in states
|
|
52
|
+
* @param {Mapper} [options.mapper] - mapper for state values
|
|
50
53
|
* @returns {ConversationsAPI}
|
|
51
54
|
* @example
|
|
52
55
|
* const { GraphApi, conversationsApi } = require('wingbot');
|
|
@@ -106,6 +109,13 @@ function conversationsApi (
|
|
|
106
109
|
history,
|
|
107
110
|
subscribtions
|
|
108
111
|
});
|
|
112
|
+
} else if (options.mapper) {
|
|
113
|
+
mapState = (d) => mapObject({
|
|
114
|
+
...d,
|
|
115
|
+
lastInteraction: d.lastInteraction || (new Date(0)),
|
|
116
|
+
history,
|
|
117
|
+
subscribtions
|
|
118
|
+
}, defaultMapperFactory(options.mapper));
|
|
109
119
|
} else {
|
|
110
120
|
mapState = (d) => ({
|
|
111
121
|
...d,
|
|
@@ -102,7 +102,7 @@ function validateBotApi (botFactory, postBackTest = null, textTest = null, acl =
|
|
|
102
102
|
validationRequestBody = decompress(validationRequestBody);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
const bot = await Promise.resolve(botFactory());
|
|
105
|
+
const bot = await Promise.resolve(botFactory(true, ctx.snapshot));
|
|
106
106
|
|
|
107
107
|
await ctx.audit('validateBot');
|
|
108
108
|
return validate(bot, validationRequestBody, postBackTest, textTest);
|
|
@@ -23,6 +23,58 @@ function deepEqual (left, right) {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @callback Mapper
|
|
28
|
+
* @param {string} key
|
|
29
|
+
* @param {any} val
|
|
30
|
+
* @param {object} lastObj
|
|
31
|
+
* @param {string|null} lastKey
|
|
32
|
+
* @returns {any}
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
*
|
|
37
|
+
* @param {Mapper} [otherMapper]
|
|
38
|
+
* @returns {Mapper}
|
|
39
|
+
*/
|
|
40
|
+
function defaultMapperFactory (otherMapper = null) {
|
|
41
|
+
return (k, v, o, lk) => {
|
|
42
|
+
const useV = otherMapper
|
|
43
|
+
? otherMapper(k, v, o, lk)
|
|
44
|
+
: v;
|
|
45
|
+
|
|
46
|
+
if (useV instanceof Date) {
|
|
47
|
+
return v.toISOString();
|
|
48
|
+
}
|
|
49
|
+
return useV;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
* @template T
|
|
56
|
+
* @param {T} obj
|
|
57
|
+
* @param {Mapper} mapFn
|
|
58
|
+
* @returns {T}
|
|
59
|
+
*/
|
|
60
|
+
function mapObject (obj, mapFn) {
|
|
61
|
+
let lastKey = null;
|
|
62
|
+
let lastObj = obj;
|
|
63
|
+
|
|
64
|
+
const str = JSON.stringify(obj, (key, val) => {
|
|
65
|
+
const ret = mapFn(key, val, lastObj, lastKey);
|
|
66
|
+
|
|
67
|
+
if (val && typeof val === 'object') {
|
|
68
|
+
lastObj = val;
|
|
69
|
+
lastKey = key || null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return ret;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return JSON.parse(str);
|
|
76
|
+
}
|
|
77
|
+
|
|
26
78
|
function apiTextOutputFilter (obj, callback, prevKey = '') {
|
|
27
79
|
let useKey;
|
|
28
80
|
if (Array.isArray(obj)) {
|
|
@@ -59,4 +111,6 @@ function apiTextOutputFilter (obj, callback, prevKey = '') {
|
|
|
59
111
|
return obj;
|
|
60
112
|
}
|
|
61
113
|
|
|
62
|
-
module.exports = {
|
|
114
|
+
module.exports = {
|
|
115
|
+
apiTextOutputFilter, deepEqual, mapObject, defaultMapperFactory
|
|
116
|
+
};
|