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