@webex/internal-plugin-dss 3.0.0-beta.136 → 3.0.0-beta.137
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/config.js +31 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.js +11 -1
- package/dist/constants.js.map +1 -1
- package/dist/dss-batcher.js +139 -0
- package/dist/dss-batcher.js.map +1 -0
- package/dist/dss.js +138 -28
- package/dist/dss.js.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +7 -7
- package/src/config.ts +25 -0
- package/src/constants.ts +5 -0
- package/src/dss-batcher.ts +129 -0
- package/src/dss.ts +136 -27
- package/src/index.ts +2 -1
- package/src/types.ts +3 -2
- package/test/unit/spec/dss-batcher.ts +146 -0
- package/test/unit/spec/dss.ts +626 -61
package/src/config.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2022 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
dss: {
|
|
7
|
+
/**
|
|
8
|
+
* Debounce wait (ms) before sending a dss request (gap between lookups that will trigger a request)
|
|
9
|
+
* @type {Number}
|
|
10
|
+
*/
|
|
11
|
+
batcherWait: 50,
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Maximum queue size before sending a dss request
|
|
15
|
+
* @type {Number}
|
|
16
|
+
*/
|
|
17
|
+
batcherMaxCalls: 50,
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Debounce max wait (ms) before sending a dss request (time from first lookup that will trigger a request)
|
|
21
|
+
* @type {Number}
|
|
22
|
+
*/
|
|
23
|
+
batcherMaxWait: 150,
|
|
24
|
+
},
|
|
25
|
+
};
|
package/src/constants.ts
CHANGED
|
@@ -12,3 +12,8 @@ export const SEARCH_TYPES = {
|
|
|
12
12
|
ROOM: 'ROOM',
|
|
13
13
|
ROBOT: 'ROBOT',
|
|
14
14
|
};
|
|
15
|
+
export const LOOKUP_DATA_PATH = 'lookupResult.entities';
|
|
16
|
+
export const LOOKUP_FOUND_PATH = 'lookupResult.entitiesFound';
|
|
17
|
+
export const LOOKUP_NOT_FOUND_PATH = 'lookupResult.entitiesNotFound';
|
|
18
|
+
export const LOOKUP_REQUEST_KEY = 'lookupValues';
|
|
19
|
+
export const SEARCH_DATA_PATH = 'directoryEntities';
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2022 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
/* eslint-disable no-underscore-dangle */
|
|
5
|
+
|
|
6
|
+
import {Batcher} from '@webex/webex-core';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @class
|
|
10
|
+
*/
|
|
11
|
+
const DssBatcher = Batcher.extend({
|
|
12
|
+
namespace: 'DSS',
|
|
13
|
+
|
|
14
|
+
props: {
|
|
15
|
+
resource: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
required: true,
|
|
18
|
+
setOnce: true,
|
|
19
|
+
allowNull: false,
|
|
20
|
+
},
|
|
21
|
+
dataPath: {
|
|
22
|
+
type: 'string',
|
|
23
|
+
required: true,
|
|
24
|
+
setOnce: true,
|
|
25
|
+
allowNull: false,
|
|
26
|
+
},
|
|
27
|
+
entitiesFoundPath: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
required: true,
|
|
30
|
+
setOnce: true,
|
|
31
|
+
allowNull: false,
|
|
32
|
+
},
|
|
33
|
+
entitiesNotFoundPath: {
|
|
34
|
+
type: 'string',
|
|
35
|
+
required: true,
|
|
36
|
+
setOnce: true,
|
|
37
|
+
allowNull: false,
|
|
38
|
+
},
|
|
39
|
+
requestKey: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
required: true,
|
|
42
|
+
setOnce: true,
|
|
43
|
+
allowNull: false,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Submits the DSS request
|
|
49
|
+
* @param {Object} payload
|
|
50
|
+
* @returns {Promise<Array>}
|
|
51
|
+
*/
|
|
52
|
+
submitHttpRequest(payload) {
|
|
53
|
+
return this.parent._request({
|
|
54
|
+
dataPath: this.dataPath,
|
|
55
|
+
foundPath: this.entitiesFoundPath,
|
|
56
|
+
notFoundPath: this.entitiesNotFoundPath,
|
|
57
|
+
resource: this.resource,
|
|
58
|
+
params: {
|
|
59
|
+
lookupValues: payload,
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Actions taken when the http request returns a success
|
|
66
|
+
* @param {Promise<Array>} res
|
|
67
|
+
* @returns {Promise<undefined>}
|
|
68
|
+
*/
|
|
69
|
+
handleHttpSuccess(res) {
|
|
70
|
+
const successItems = res.foundArray.map((requestValue, index) => ({
|
|
71
|
+
requestValue,
|
|
72
|
+
entity: res.resultArray[index],
|
|
73
|
+
}));
|
|
74
|
+
const failureItems = res.notFoundArray.map((requestValue) => ({requestValue, entity: null}));
|
|
75
|
+
|
|
76
|
+
return Promise.all(successItems.concat(failureItems).map((item) => this.acceptItem(item)));
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Checks if the item was found
|
|
81
|
+
* @param {Object} item
|
|
82
|
+
* @returns {Promise<Boolean>}
|
|
83
|
+
*/
|
|
84
|
+
didItemFail(item) {
|
|
85
|
+
return Promise.resolve(item.entity === null);
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Finds the Defer for the specified item and resolves its promise with null
|
|
90
|
+
* @param {Object} item
|
|
91
|
+
* @returns {Promise<undefined>}
|
|
92
|
+
*/
|
|
93
|
+
handleItemFailure(item) {
|
|
94
|
+
return this.getDeferredForResponse(item).then((defer) => {
|
|
95
|
+
defer.resolve(null);
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Finds the Defer for the specified item and resolves its promise
|
|
101
|
+
* @param {Object} item
|
|
102
|
+
* @returns {Promise<undefined>}
|
|
103
|
+
*/
|
|
104
|
+
handleItemSuccess(item) {
|
|
105
|
+
return this.getDeferredForResponse(item).then((defer) => {
|
|
106
|
+
defer.resolve(item.entity);
|
|
107
|
+
});
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Returns a promise with the unique key for the item
|
|
112
|
+
* @param {Object} item
|
|
113
|
+
* @returns {Promise}
|
|
114
|
+
*/
|
|
115
|
+
fingerprintRequest(item) {
|
|
116
|
+
return Promise.resolve(item);
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Returns a promise with the unique key for the item
|
|
121
|
+
* @param {Object} item
|
|
122
|
+
* @returns {Promise}
|
|
123
|
+
*/
|
|
124
|
+
fingerprintResponse(item) {
|
|
125
|
+
return Promise.resolve(item.requestValue);
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
export default DssBatcher;
|
package/src/dss.ts
CHANGED
|
@@ -22,7 +22,13 @@ import {
|
|
|
22
22
|
DSS_SERVICE_NAME,
|
|
23
23
|
DSS_SEARCH_MERCURY_EVENT,
|
|
24
24
|
DSS_RESULT,
|
|
25
|
+
LOOKUP_DATA_PATH,
|
|
26
|
+
LOOKUP_FOUND_PATH,
|
|
27
|
+
LOOKUP_NOT_FOUND_PATH,
|
|
28
|
+
LOOKUP_REQUEST_KEY,
|
|
29
|
+
SEARCH_DATA_PATH,
|
|
25
30
|
} from './constants';
|
|
31
|
+
import DssBatcher from './dss-batcher';
|
|
26
32
|
|
|
27
33
|
const DSS = WebexPlugin.extend({
|
|
28
34
|
namespace: 'DSS',
|
|
@@ -35,6 +41,18 @@ const DSS = WebexPlugin.extend({
|
|
|
35
41
|
*/
|
|
36
42
|
registered: false,
|
|
37
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Initializer
|
|
46
|
+
* @private
|
|
47
|
+
* @param {Object} attrs
|
|
48
|
+
* @param {Object} options
|
|
49
|
+
* @returns {undefined}
|
|
50
|
+
*/
|
|
51
|
+
initialize(...args) {
|
|
52
|
+
Reflect.apply(WebexPlugin.prototype.initialize, this, args);
|
|
53
|
+
this.batchers = {};
|
|
54
|
+
},
|
|
55
|
+
|
|
38
56
|
/**
|
|
39
57
|
* Explicitly sets up the DSS plugin by connecting to mercury, and listening for DSS events.
|
|
40
58
|
* @returns {Promise}
|
|
@@ -114,6 +132,7 @@ const DSS = WebexPlugin.extend({
|
|
|
114
132
|
},
|
|
115
133
|
|
|
116
134
|
/**
|
|
135
|
+
* constructs the event name based on request id
|
|
117
136
|
* @param {UUID} requestId the id of the request
|
|
118
137
|
* @returns {string}
|
|
119
138
|
*/
|
|
@@ -122,6 +141,7 @@ const DSS = WebexPlugin.extend({
|
|
|
122
141
|
},
|
|
123
142
|
|
|
124
143
|
/**
|
|
144
|
+
* Takes incoming data and triggers correct events
|
|
125
145
|
* @param {Object} data the event data
|
|
126
146
|
* @returns {undefined}
|
|
127
147
|
*/
|
|
@@ -135,39 +155,67 @@ const DSS = WebexPlugin.extend({
|
|
|
135
155
|
* @param {Object} options
|
|
136
156
|
* @param {string} options.resource the URL to query
|
|
137
157
|
* @param {string} options.params additional params for the body of the request
|
|
138
|
-
* @param {string} options.dataPath
|
|
139
|
-
* @
|
|
158
|
+
* @param {string} options.dataPath the path to get the data in the result object
|
|
159
|
+
* @param {string} options.foundPath the path to get the lookups of the found data (optional)
|
|
160
|
+
* @param {string} options.notFoundPath the path to get the lookups of the not found data (optional)
|
|
161
|
+
* @returns {Promise<Object>} result Resolves with an object
|
|
162
|
+
* @returns {Array} result.resultArray an array of entities found
|
|
163
|
+
* @returns {Array} result.foundArray an array of the lookups of the found entities (if foundPath provided)
|
|
164
|
+
* @returns {Array} result.notFoundArray an array of the lookups of the not found entities (if notFoundPath provided)
|
|
140
165
|
*/
|
|
141
166
|
_request(options) {
|
|
142
|
-
const {resource, params, dataPath} = options;
|
|
167
|
+
const {resource, params, dataPath, foundPath, notFoundPath} = options;
|
|
143
168
|
|
|
144
169
|
const requestId = uuid.v4();
|
|
145
170
|
const eventName = this._getResultEventName(requestId);
|
|
146
171
|
const result = {};
|
|
147
172
|
let expectedSeqNums;
|
|
173
|
+
let notFoundArray;
|
|
148
174
|
|
|
149
175
|
return new Promise((resolve) => {
|
|
150
176
|
this.listenTo(this, eventName, (data) => {
|
|
151
|
-
const resultData = get(data, dataPath);
|
|
177
|
+
const resultData = get(data, dataPath, []);
|
|
178
|
+
let found;
|
|
152
179
|
|
|
153
|
-
|
|
180
|
+
if (foundPath) {
|
|
181
|
+
found = get(data, foundPath, []);
|
|
182
|
+
}
|
|
183
|
+
result[data.sequence] = foundPath ? {resultData, found} : {resultData};
|
|
154
184
|
|
|
155
185
|
if (data.finished) {
|
|
156
186
|
expectedSeqNums = range(data.sequence + 1).map(String);
|
|
187
|
+
if (notFoundPath) {
|
|
188
|
+
notFoundArray = get(data, notFoundPath, []);
|
|
189
|
+
}
|
|
157
190
|
}
|
|
158
191
|
|
|
159
192
|
const done = isEqual(expectedSeqNums, Object.keys(result));
|
|
160
193
|
|
|
161
194
|
if (done) {
|
|
162
|
-
const resultArray = [];
|
|
195
|
+
const resultArray: any[] = [];
|
|
196
|
+
const foundArray: any[] = [];
|
|
197
|
+
|
|
163
198
|
expectedSeqNums.forEach((index) => {
|
|
164
199
|
const seqResult = result[index];
|
|
200
|
+
|
|
165
201
|
if (seqResult) {
|
|
166
|
-
resultArray.push(...seqResult);
|
|
202
|
+
resultArray.push(...seqResult.resultData);
|
|
203
|
+
if (foundPath) {
|
|
204
|
+
foundArray.push(...seqResult.found);
|
|
205
|
+
}
|
|
167
206
|
}
|
|
168
207
|
});
|
|
169
|
-
|
|
170
|
-
|
|
208
|
+
const resolveValue: {resultArray: any[]; foundArray?: any[]; notFoundArray?: any[]} = {
|
|
209
|
+
resultArray,
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
if (foundPath) {
|
|
213
|
+
resolveValue.foundArray = foundArray;
|
|
214
|
+
}
|
|
215
|
+
if (notFoundPath) {
|
|
216
|
+
resolveValue.notFoundArray = notFoundArray;
|
|
217
|
+
}
|
|
218
|
+
resolve(resolveValue);
|
|
171
219
|
this.stopListening(this, eventName);
|
|
172
220
|
}
|
|
173
221
|
});
|
|
@@ -181,59 +229,120 @@ const DSS = WebexPlugin.extend({
|
|
|
181
229
|
});
|
|
182
230
|
},
|
|
183
231
|
|
|
232
|
+
/**
|
|
233
|
+
* Uses a batcher to make the request to the directory service
|
|
234
|
+
* @param {Object} options
|
|
235
|
+
* @param {string} options.resource the URL to query
|
|
236
|
+
* @param {string} options.value the id or email to lookup
|
|
237
|
+
* @returns {Promise} Resolves with an array of entities found
|
|
238
|
+
*/
|
|
239
|
+
_batchedLookup(options) {
|
|
240
|
+
const {resource, lookupValue} = options;
|
|
241
|
+
const dataPath = LOOKUP_DATA_PATH;
|
|
242
|
+
const entitiesFoundPath = LOOKUP_FOUND_PATH;
|
|
243
|
+
const entitiesNotFoundPath = LOOKUP_NOT_FOUND_PATH;
|
|
244
|
+
const requestKey = LOOKUP_REQUEST_KEY;
|
|
245
|
+
|
|
246
|
+
this.batchers[resource] =
|
|
247
|
+
this.batchers[resource] ||
|
|
248
|
+
new DssBatcher({
|
|
249
|
+
resource,
|
|
250
|
+
dataPath,
|
|
251
|
+
entitiesFoundPath,
|
|
252
|
+
entitiesNotFoundPath,
|
|
253
|
+
requestKey,
|
|
254
|
+
parent: this,
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
return this.batchers[resource].request(lookupValue);
|
|
258
|
+
},
|
|
259
|
+
|
|
184
260
|
/**
|
|
185
261
|
* Retrieves detailed information about an entity
|
|
186
262
|
* @param {Object} options
|
|
187
263
|
* @param {UUID} options.id the id of the entity to lookup
|
|
188
|
-
* @returns {Promise} Resolves with
|
|
264
|
+
* @returns {Promise} Resolves with the entity found or null if not found
|
|
189
265
|
*/
|
|
190
266
|
lookupDetail(options: LookupDetailOptions) {
|
|
191
267
|
const {id} = options;
|
|
192
268
|
|
|
269
|
+
const resource = `/lookup/orgid/${this.webex.internal.device.orgId}/identity/${id}/detail`;
|
|
270
|
+
|
|
193
271
|
return this._request({
|
|
194
|
-
dataPath:
|
|
195
|
-
|
|
272
|
+
dataPath: LOOKUP_DATA_PATH,
|
|
273
|
+
foundPath: LOOKUP_FOUND_PATH,
|
|
274
|
+
resource,
|
|
275
|
+
}).then(({resultArray, foundArray}) => {
|
|
276
|
+
// TODO: find out what is actually returned!
|
|
277
|
+
if (foundArray[0] === id) {
|
|
278
|
+
return resultArray[0];
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return null;
|
|
196
282
|
});
|
|
197
283
|
},
|
|
198
284
|
|
|
199
285
|
/**
|
|
200
|
-
* Retrieves basic information about
|
|
286
|
+
* Retrieves basic information about an entity within an organization
|
|
201
287
|
* @param {Object} options
|
|
202
|
-
* @param {UUID} options.
|
|
288
|
+
* @param {UUID} options.id the id of the entity to lookup
|
|
203
289
|
* @param {UUID} options.entityProviderType the provider to query (optional)
|
|
204
|
-
* @
|
|
290
|
+
* @param {Boolean} options.shouldBatch whether to batch the query, set to false for single immediate result (defaults to true)
|
|
291
|
+
* @returns {Promise} Resolves with the entity found or null if not found
|
|
205
292
|
*/
|
|
206
293
|
lookup(options: LookupOptions) {
|
|
207
|
-
const {
|
|
294
|
+
const {id, entityProviderType, shouldBatch = true} = options;
|
|
208
295
|
|
|
209
296
|
const resource = entityProviderType
|
|
210
297
|
? `/lookup/orgid/${this.webex.internal.device.orgId}/entityprovidertype/${entityProviderType}`
|
|
211
298
|
: `/lookup/orgid/${this.webex.internal.device.orgId}/identities`;
|
|
212
299
|
|
|
300
|
+
if (shouldBatch) {
|
|
301
|
+
return this._batchedLookup({
|
|
302
|
+
resource,
|
|
303
|
+
lookupValue: id,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
213
307
|
return this._request({
|
|
214
|
-
dataPath:
|
|
308
|
+
dataPath: LOOKUP_DATA_PATH,
|
|
309
|
+
foundPath: LOOKUP_FOUND_PATH,
|
|
215
310
|
resource,
|
|
216
311
|
params: {
|
|
217
|
-
|
|
312
|
+
[LOOKUP_REQUEST_KEY]: [id],
|
|
218
313
|
},
|
|
314
|
+
}).then(({resultArray, foundArray}) => {
|
|
315
|
+
if (foundArray[0] === id) {
|
|
316
|
+
return resultArray[0];
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return null;
|
|
219
320
|
});
|
|
220
321
|
},
|
|
221
322
|
|
|
222
323
|
/**
|
|
223
|
-
* Retrieves basic information about
|
|
324
|
+
* Retrieves basic information about an enitity within an organization
|
|
224
325
|
* @param {Object} options
|
|
225
|
-
* @param {UUID} options.
|
|
226
|
-
* @returns {Promise} Resolves with
|
|
326
|
+
* @param {UUID} options.email the email of the entity to lookup
|
|
327
|
+
* @returns {Promise} Resolves with the entity found or rejects if not found
|
|
227
328
|
*/
|
|
228
329
|
lookupByEmail(options: LookupByEmailOptions) {
|
|
229
|
-
const {
|
|
330
|
+
const {email} = options;
|
|
331
|
+
const resource = `/lookup/orgid/${this.webex.internal.device.orgId}/emails`;
|
|
230
332
|
|
|
231
333
|
return this._request({
|
|
232
|
-
dataPath:
|
|
233
|
-
|
|
334
|
+
dataPath: LOOKUP_DATA_PATH,
|
|
335
|
+
foundPath: LOOKUP_FOUND_PATH,
|
|
336
|
+
resource,
|
|
234
337
|
params: {
|
|
235
|
-
|
|
338
|
+
[LOOKUP_REQUEST_KEY]: [email],
|
|
236
339
|
},
|
|
340
|
+
}).then(({resultArray, foundArray}) => {
|
|
341
|
+
if (foundArray[0] === email) {
|
|
342
|
+
return resultArray[0];
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return null;
|
|
237
346
|
});
|
|
238
347
|
},
|
|
239
348
|
|
|
@@ -249,14 +358,14 @@ const DSS = WebexPlugin.extend({
|
|
|
249
358
|
const {requestedTypes, resultSize, queryString} = options;
|
|
250
359
|
|
|
251
360
|
return this._request({
|
|
252
|
-
dataPath:
|
|
361
|
+
dataPath: SEARCH_DATA_PATH,
|
|
253
362
|
resource: `/search/orgid/${this.webex.internal.device.orgId}/entities`,
|
|
254
363
|
params: {
|
|
255
364
|
queryString,
|
|
256
365
|
resultSize,
|
|
257
366
|
requestedTypes,
|
|
258
367
|
},
|
|
259
|
-
});
|
|
368
|
+
}).then(({resultArray}) => resultArray);
|
|
260
369
|
},
|
|
261
370
|
});
|
|
262
371
|
|
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -11,12 +11,13 @@ export enum EntityProviderType {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface LookupOptions {
|
|
14
|
-
|
|
14
|
+
id: string;
|
|
15
15
|
entityProviderType?: EntityProviderType;
|
|
16
|
+
shouldBatch?: boolean;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export interface LookupByEmailOptions {
|
|
19
|
-
|
|
20
|
+
email: string;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
// eslint-disable-next-line no-shadow
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2022 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
/* eslint-disable no-underscore-dangle */
|
|
5
|
+
|
|
6
|
+
import {expect} from '@webex/test-helper-chai';
|
|
7
|
+
import sinon from 'sinon';
|
|
8
|
+
import DSS from '@webex/internal-plugin-dss';
|
|
9
|
+
import DssBatcher from '@webex/internal-plugin-dss/src/dss-batcher';
|
|
10
|
+
import MockWebex from '@webex/test-helper-mock-webex';
|
|
11
|
+
import {Defer} from '@webex/common';
|
|
12
|
+
|
|
13
|
+
describe('plugin-dss', () => {
|
|
14
|
+
describe('DssBatcher', () => {
|
|
15
|
+
let batcher;
|
|
16
|
+
let webex;
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
webex = MockWebex({
|
|
20
|
+
canAuthorize: false,
|
|
21
|
+
children: {
|
|
22
|
+
dss: DSS,
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
batcher = new DssBatcher({
|
|
26
|
+
resource: 'fakeResource',
|
|
27
|
+
dataPath: 'fakeDataPath',
|
|
28
|
+
entitiesFoundPath: 'fakeEntitiesFoundPath',
|
|
29
|
+
entitiesNotFoundPath: 'fakeEntitiesNotFoundPath',
|
|
30
|
+
requestKey: 'fakeRequestKey',
|
|
31
|
+
parent: webex.internal.dss,
|
|
32
|
+
});
|
|
33
|
+
webex.internal.dss.batchers.fakeResource = batcher;
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('#submitHttpRequest', () => {
|
|
37
|
+
it('calls dss._request with expected params', async () => {
|
|
38
|
+
webex.internal.dss._request = sinon.stub().returns(
|
|
39
|
+
Promise.resolve('some return value')
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const result = await batcher.submitHttpRequest(['id1']);
|
|
43
|
+
|
|
44
|
+
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
45
|
+
{
|
|
46
|
+
dataPath: 'fakeDataPath',
|
|
47
|
+
foundPath: 'fakeEntitiesFoundPath',
|
|
48
|
+
notFoundPath: 'fakeEntitiesNotFoundPath',
|
|
49
|
+
resource: 'fakeResource',
|
|
50
|
+
params: {
|
|
51
|
+
lookupValues: ['id1'],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
]);
|
|
55
|
+
expect(result).to.equal('some return value');
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('#handleHttpSuccess', () => {
|
|
60
|
+
it('calls acceptItem on each found or not found entity', async () => {
|
|
61
|
+
batcher.acceptItem = sinon.stub().returns(Promise.resolve(undefined));
|
|
62
|
+
const res = {
|
|
63
|
+
resultArray: [
|
|
64
|
+
'item1',
|
|
65
|
+
'item2',
|
|
66
|
+
],
|
|
67
|
+
foundArray: [
|
|
68
|
+
'id1',
|
|
69
|
+
'id2',
|
|
70
|
+
],
|
|
71
|
+
notFoundArray: [
|
|
72
|
+
'id3',
|
|
73
|
+
'id4',
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
const result = await batcher.handleHttpSuccess(res);
|
|
77
|
+
|
|
78
|
+
expect(batcher.acceptItem.getCalls().map((call) => call.args)).to.deep.equal([
|
|
79
|
+
[{requestValue: 'id1', entity: 'item1'}],
|
|
80
|
+
[{requestValue: 'id2', entity: 'item2'}],
|
|
81
|
+
[{requestValue: 'id3', entity: null}],
|
|
82
|
+
[{requestValue: 'id4', entity: null}],
|
|
83
|
+
]);
|
|
84
|
+
expect(result).to.deep.equal([undefined, undefined, undefined, undefined]);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('#didItemFail', () => {
|
|
89
|
+
it('returns true if item.entity is null', async () => {
|
|
90
|
+
const result = await batcher.didItemFail({entity: null});
|
|
91
|
+
|
|
92
|
+
expect(result).to.be.true;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('returns true if item.entity is not null', async () => {
|
|
96
|
+
const result = await batcher.didItemFail({entity: 'something'});
|
|
97
|
+
|
|
98
|
+
expect(result).to.be.false;
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe('#handleItemFailure', () => {
|
|
103
|
+
it('resolves defer for item with null', async () => {
|
|
104
|
+
const defer = new Defer();
|
|
105
|
+
|
|
106
|
+
batcher.getDeferredForResponse = sinon.stub().returns(Promise.resolve(defer));
|
|
107
|
+
const result = await batcher.handleItemFailure({requestValue: 'some request'});
|
|
108
|
+
const deferValue = await defer.promise;
|
|
109
|
+
|
|
110
|
+
expect(batcher.getDeferredForResponse.getCall(0).args).to.deep.equal([{requestValue: 'some request'}]);
|
|
111
|
+
expect(result).to.be.undefined;
|
|
112
|
+
expect(deferValue).to.be.null;
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe('#handleItemSuccess', () => {
|
|
117
|
+
it('resolves defer for item with item.entity', async () => {
|
|
118
|
+
const defer = new Defer();
|
|
119
|
+
|
|
120
|
+
batcher.getDeferredForResponse = sinon.stub().returns(Promise.resolve(defer));
|
|
121
|
+
const result = await batcher.handleItemSuccess({entity: 'some entity'});
|
|
122
|
+
const deferValue = await defer.promise;
|
|
123
|
+
|
|
124
|
+
expect(batcher.getDeferredForResponse.getCall(0).args).to.deep.equal([{entity: 'some entity'}]);
|
|
125
|
+
expect(result).to.be.undefined;
|
|
126
|
+
expect(deferValue).to.equal('some entity');
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe('#fingerprintRequest', () => {
|
|
131
|
+
it('returns request', async () => {
|
|
132
|
+
const result = await batcher.fingerprintRequest('some request');
|
|
133
|
+
|
|
134
|
+
expect(result).to.equal('some request');
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
describe('#fingerprintResponse', () => {
|
|
139
|
+
it('returns response requestValue', async () => {
|
|
140
|
+
const result = await batcher.fingerprintResponse({requestValue: 'some request'});
|
|
141
|
+
|
|
142
|
+
expect(result).to.equal('some request');
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|