@webex/internal-plugin-dss 3.0.0-beta.21 → 3.0.0-beta.211
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 +36 -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-errors.js +50 -0
- package/dist/dss-errors.js.map +1 -0
- package/dist/dss.js +162 -31
- package/dist/dss.js.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/types.js +0 -1
- package/dist/types.js.map +1 -1
- package/package.json +9 -6
- 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 +22 -3
- package/test/unit/spec/dss-batcher.ts +139 -0
- package/test/unit/spec/dss.ts +952 -62
package/src/dss.ts
CHANGED
|
@@ -2,17 +2,19 @@
|
|
|
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,
|
|
12
15
|
LookupOptions,
|
|
13
16
|
LookupByEmailOptions,
|
|
14
17
|
} from './types';
|
|
15
|
-
|
|
16
18
|
import {
|
|
17
19
|
DSS_REGISTERED,
|
|
18
20
|
DSS_UNREGISTERED,
|
|
@@ -21,7 +23,15 @@ import {
|
|
|
21
23
|
DSS_SERVICE_NAME,
|
|
22
24
|
DSS_SEARCH_MERCURY_EVENT,
|
|
23
25
|
DSS_RESULT,
|
|
26
|
+
LOOKUP_DATA_PATH,
|
|
27
|
+
LOOKUP_FOUND_PATH,
|
|
28
|
+
LOOKUP_NOT_FOUND_PATH,
|
|
29
|
+
LOOKUP_REQUEST_KEY,
|
|
30
|
+
SEARCH_DATA_PATH,
|
|
24
31
|
} from './constants';
|
|
32
|
+
import DssBatcher from './dss-batcher';
|
|
33
|
+
import {DssTimeoutError} from './dss-errors';
|
|
34
|
+
import {BatcherOptions, RequestOptions, RequestResult} from './types';
|
|
25
35
|
|
|
26
36
|
const DSS = WebexPlugin.extend({
|
|
27
37
|
namespace: 'DSS',
|
|
@@ -34,6 +44,18 @@ const DSS = WebexPlugin.extend({
|
|
|
34
44
|
*/
|
|
35
45
|
registered: false,
|
|
36
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Initializer
|
|
49
|
+
* @private
|
|
50
|
+
* @param {Object} attrs
|
|
51
|
+
* @param {Object} options
|
|
52
|
+
* @returns {undefined}
|
|
53
|
+
*/
|
|
54
|
+
initialize(...args) {
|
|
55
|
+
Reflect.apply(WebexPlugin.prototype.initialize, this, args);
|
|
56
|
+
this.batchers = {};
|
|
57
|
+
},
|
|
58
|
+
|
|
37
59
|
/**
|
|
38
60
|
* Explicitly sets up the DSS plugin by connecting to mercury, and listening for DSS events.
|
|
39
61
|
* @returns {Promise}
|
|
@@ -113,6 +135,7 @@ const DSS = WebexPlugin.extend({
|
|
|
113
135
|
},
|
|
114
136
|
|
|
115
137
|
/**
|
|
138
|
+
* constructs the event name based on request id
|
|
116
139
|
* @param {UUID} requestId the id of the request
|
|
117
140
|
* @returns {string}
|
|
118
141
|
*/
|
|
@@ -121,6 +144,7 @@ const DSS = WebexPlugin.extend({
|
|
|
121
144
|
},
|
|
122
145
|
|
|
123
146
|
/**
|
|
147
|
+
* Takes incoming data and triggers correct events
|
|
124
148
|
* @param {Object} data the event data
|
|
125
149
|
* @returns {undefined}
|
|
126
150
|
*/
|
|
@@ -133,40 +157,78 @@ const DSS = WebexPlugin.extend({
|
|
|
133
157
|
* Makes the request to the directory service
|
|
134
158
|
* @param {Object} options
|
|
135
159
|
* @param {string} options.resource the URL to query
|
|
136
|
-
* @param {
|
|
137
|
-
* @param {string} options.dataPath
|
|
138
|
-
* @
|
|
160
|
+
* @param {Mixed} options.params additional params for the body of the request
|
|
161
|
+
* @param {string} options.dataPath the path to get the data in the result object
|
|
162
|
+
* @param {string} [options.foundPath] the path to get the lookups of the found data
|
|
163
|
+
* @param {string} [options.notFoundPath] the path to get the lookups of the not found data
|
|
164
|
+
* @returns {Promise<Object>} result Resolves with an object
|
|
165
|
+
* @returns {Array} result.resultArray an array of entities found
|
|
166
|
+
* @returns {Array} result.foundArray an array of the lookups of the found entities (if foundPath provided)
|
|
167
|
+
* @returns {Array} result.notFoundArray an array of the lookups of the not found entities (if notFoundPath provided)
|
|
168
|
+
* @throws {DssTimeoutError} when server does not respond in the specified timeframe
|
|
139
169
|
*/
|
|
140
|
-
_request(options) {
|
|
141
|
-
const {resource, params, dataPath} = options;
|
|
170
|
+
_request(options: RequestOptions): Promise<RequestResult> {
|
|
171
|
+
const {resource, params, dataPath, foundPath, notFoundPath} = options;
|
|
142
172
|
|
|
173
|
+
const timeout = this.config.requestTimeout;
|
|
143
174
|
const requestId = uuid.v4();
|
|
144
175
|
const eventName = this._getResultEventName(requestId);
|
|
145
176
|
const result = {};
|
|
146
|
-
let expectedSeqNums;
|
|
177
|
+
let expectedSeqNums: string[];
|
|
178
|
+
let notFoundArray: unknown[];
|
|
179
|
+
|
|
180
|
+
return new Promise((resolve, reject) => {
|
|
181
|
+
const timer = new Timer(() => {
|
|
182
|
+
this.stopListening(this, eventName);
|
|
183
|
+
reject(new DssTimeoutError({requestId, timeout, resource, params}));
|
|
184
|
+
}, timeout);
|
|
147
185
|
|
|
148
|
-
return new Promise((resolve) => {
|
|
149
186
|
this.listenTo(this, eventName, (data) => {
|
|
150
|
-
|
|
187
|
+
timer.reset();
|
|
188
|
+
const resultData = get(data, dataPath, []);
|
|
189
|
+
let found;
|
|
151
190
|
|
|
152
|
-
|
|
191
|
+
if (foundPath) {
|
|
192
|
+
found = get(data, foundPath, []);
|
|
193
|
+
}
|
|
194
|
+
result[data.sequence] = foundPath ? {resultData, found} : {resultData};
|
|
153
195
|
|
|
154
196
|
if (data.finished) {
|
|
155
197
|
expectedSeqNums = range(data.sequence + 1).map(String);
|
|
198
|
+
if (notFoundPath) {
|
|
199
|
+
notFoundArray = get(data, notFoundPath, []);
|
|
200
|
+
}
|
|
156
201
|
}
|
|
157
202
|
|
|
158
203
|
const done = isEqual(expectedSeqNums, Object.keys(result));
|
|
159
204
|
|
|
160
205
|
if (done) {
|
|
161
|
-
|
|
206
|
+
timer.cancel();
|
|
207
|
+
|
|
208
|
+
const resultArray: any[] = [];
|
|
209
|
+
const foundArray: any[] = [];
|
|
210
|
+
|
|
162
211
|
expectedSeqNums.forEach((index) => {
|
|
163
212
|
const seqResult = result[index];
|
|
213
|
+
|
|
164
214
|
if (seqResult) {
|
|
165
|
-
resultArray.push(...seqResult);
|
|
215
|
+
resultArray.push(...seqResult.resultData);
|
|
216
|
+
if (foundPath) {
|
|
217
|
+
foundArray.push(...seqResult.found);
|
|
218
|
+
}
|
|
166
219
|
}
|
|
167
220
|
});
|
|
168
|
-
|
|
169
|
-
|
|
221
|
+
const resolveValue: RequestResult = {
|
|
222
|
+
resultArray,
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
if (foundPath) {
|
|
226
|
+
resolveValue.foundArray = foundArray;
|
|
227
|
+
}
|
|
228
|
+
if (notFoundPath) {
|
|
229
|
+
resolveValue.notFoundArray = notFoundArray;
|
|
230
|
+
}
|
|
231
|
+
resolve(resolveValue);
|
|
170
232
|
this.stopListening(this, eventName);
|
|
171
233
|
}
|
|
172
234
|
});
|
|
@@ -177,62 +239,128 @@ const DSS = WebexPlugin.extend({
|
|
|
177
239
|
contentType: 'application/json',
|
|
178
240
|
body: {requestId, ...params},
|
|
179
241
|
});
|
|
242
|
+
timer.start();
|
|
180
243
|
});
|
|
181
244
|
},
|
|
182
245
|
|
|
246
|
+
/**
|
|
247
|
+
* Uses a batcher to make the request to the directory service
|
|
248
|
+
* @param {Object} options
|
|
249
|
+
* @param {string} options.resource the URL to query
|
|
250
|
+
* @param {string} options.value the id or email to lookup
|
|
251
|
+
* @returns {Promise} Resolves with an array of entities found
|
|
252
|
+
* @throws {DssTimeoutError} when server does not respond in the specified timeframe
|
|
253
|
+
*/
|
|
254
|
+
_batchedLookup(options: BatcherOptions) {
|
|
255
|
+
const {resource, lookupValue} = options;
|
|
256
|
+
const dataPath = LOOKUP_DATA_PATH;
|
|
257
|
+
const entitiesFoundPath = LOOKUP_FOUND_PATH;
|
|
258
|
+
const entitiesNotFoundPath = LOOKUP_NOT_FOUND_PATH;
|
|
259
|
+
const requestKey = LOOKUP_REQUEST_KEY;
|
|
260
|
+
|
|
261
|
+
this.batchers[resource] =
|
|
262
|
+
this.batchers[resource] ||
|
|
263
|
+
new DssBatcher({
|
|
264
|
+
resource,
|
|
265
|
+
dataPath,
|
|
266
|
+
entitiesFoundPath,
|
|
267
|
+
entitiesNotFoundPath,
|
|
268
|
+
requestKey,
|
|
269
|
+
parent: this,
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
return this.batchers[resource].request(lookupValue);
|
|
273
|
+
},
|
|
274
|
+
|
|
183
275
|
/**
|
|
184
276
|
* Retrieves detailed information about an entity
|
|
185
277
|
* @param {Object} options
|
|
186
278
|
* @param {UUID} options.id the id of the entity to lookup
|
|
187
|
-
* @returns {Promise} Resolves with
|
|
279
|
+
* @returns {Promise} Resolves with the entity found or null if not found
|
|
280
|
+
* @throws {DssTimeoutError} when server does not respond in the specified timeframe
|
|
188
281
|
*/
|
|
189
282
|
lookupDetail(options: LookupDetailOptions) {
|
|
190
283
|
const {id} = options;
|
|
191
284
|
|
|
285
|
+
const resource = `/lookup/orgid/${this.webex.internal.device.orgId}/identity/${id}/detail`;
|
|
286
|
+
|
|
192
287
|
return this._request({
|
|
193
|
-
dataPath:
|
|
194
|
-
|
|
288
|
+
dataPath: LOOKUP_DATA_PATH,
|
|
289
|
+
foundPath: LOOKUP_FOUND_PATH,
|
|
290
|
+
resource,
|
|
291
|
+
}).then(({resultArray, foundArray}) => {
|
|
292
|
+
// TODO: find out what is actually returned!
|
|
293
|
+
if (foundArray[0] === id) {
|
|
294
|
+
return resultArray[0];
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return null;
|
|
195
298
|
});
|
|
196
299
|
},
|
|
197
300
|
|
|
198
301
|
/**
|
|
199
|
-
* Retrieves basic information about
|
|
302
|
+
* Retrieves basic information about an entity within an organization
|
|
200
303
|
* @param {Object} options
|
|
201
|
-
* @param {UUID} options.
|
|
202
|
-
* @param {UUID} options.entityProviderType the provider to query
|
|
203
|
-
* @
|
|
304
|
+
* @param {UUID} options.id the id of the entity to lookup
|
|
305
|
+
* @param {UUID} [options.entityProviderType] the provider to query
|
|
306
|
+
* @param {Boolean} options.shouldBatch whether to batch the query, set to false for single immediate result (defaults to true)
|
|
307
|
+
* @returns {Promise} Resolves with the entity found or null if not found
|
|
308
|
+
* @throws {DssTimeoutError} when server does not respond in the specified timeframe
|
|
204
309
|
*/
|
|
205
310
|
lookup(options: LookupOptions) {
|
|
206
|
-
const {
|
|
311
|
+
const {id, entityProviderType, shouldBatch = true} = options;
|
|
207
312
|
|
|
208
313
|
const resource = entityProviderType
|
|
209
314
|
? `/lookup/orgid/${this.webex.internal.device.orgId}/entityprovidertype/${entityProviderType}`
|
|
210
315
|
: `/lookup/orgid/${this.webex.internal.device.orgId}/identities`;
|
|
211
316
|
|
|
317
|
+
if (shouldBatch) {
|
|
318
|
+
return this._batchedLookup({
|
|
319
|
+
resource,
|
|
320
|
+
lookupValue: id,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
212
324
|
return this._request({
|
|
213
|
-
dataPath:
|
|
325
|
+
dataPath: LOOKUP_DATA_PATH,
|
|
326
|
+
foundPath: LOOKUP_FOUND_PATH,
|
|
214
327
|
resource,
|
|
215
328
|
params: {
|
|
216
|
-
|
|
329
|
+
[LOOKUP_REQUEST_KEY]: [id],
|
|
217
330
|
},
|
|
331
|
+
}).then(({resultArray, foundArray}) => {
|
|
332
|
+
if (foundArray[0] === id) {
|
|
333
|
+
return resultArray[0];
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return null;
|
|
218
337
|
});
|
|
219
338
|
},
|
|
220
339
|
|
|
221
340
|
/**
|
|
222
|
-
* Retrieves basic information about
|
|
341
|
+
* Retrieves basic information about an enitity within an organization
|
|
223
342
|
* @param {Object} options
|
|
224
|
-
* @param {UUID} options.
|
|
225
|
-
* @returns {Promise} Resolves with
|
|
343
|
+
* @param {UUID} options.email the email of the entity to lookup
|
|
344
|
+
* @returns {Promise} Resolves with the entity found or rejects if not found
|
|
345
|
+
* @throws {DssTimeoutError} when server does not respond in the specified timeframe
|
|
226
346
|
*/
|
|
227
347
|
lookupByEmail(options: LookupByEmailOptions) {
|
|
228
|
-
const {
|
|
348
|
+
const {email} = options;
|
|
349
|
+
const resource = `/lookup/orgid/${this.webex.internal.device.orgId}/emails`;
|
|
229
350
|
|
|
230
351
|
return this._request({
|
|
231
|
-
dataPath:
|
|
232
|
-
|
|
352
|
+
dataPath: LOOKUP_DATA_PATH,
|
|
353
|
+
foundPath: LOOKUP_FOUND_PATH,
|
|
354
|
+
resource,
|
|
233
355
|
params: {
|
|
234
|
-
|
|
356
|
+
[LOOKUP_REQUEST_KEY]: [email],
|
|
235
357
|
},
|
|
358
|
+
}).then(({resultArray, foundArray}) => {
|
|
359
|
+
if (foundArray[0] === email) {
|
|
360
|
+
return resultArray[0];
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return null;
|
|
236
364
|
});
|
|
237
365
|
},
|
|
238
366
|
|
|
@@ -243,19 +371,20 @@ const DSS = WebexPlugin.extend({
|
|
|
243
371
|
* @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
|
|
244
372
|
* @param {number} options.resultSize The maximum number of results returned from each provider
|
|
245
373
|
* @returns {Promise} Resolves with an array of entities found
|
|
374
|
+
* @throws {DssTimeoutError} when server does not respond in the specified timeframe
|
|
246
375
|
*/
|
|
247
376
|
search(options: SearchOptions) {
|
|
248
377
|
const {requestedTypes, resultSize, queryString} = options;
|
|
249
378
|
|
|
250
379
|
return this._request({
|
|
251
|
-
dataPath:
|
|
380
|
+
dataPath: SEARCH_DATA_PATH,
|
|
252
381
|
resource: `/search/orgid/${this.webex.internal.device.orgId}/entities`,
|
|
253
382
|
params: {
|
|
254
383
|
queryString,
|
|
255
384
|
resultSize,
|
|
256
385
|
requestedTypes,
|
|
257
386
|
},
|
|
258
|
-
});
|
|
387
|
+
}).then(({resultArray}) => resultArray);
|
|
259
388
|
},
|
|
260
389
|
});
|
|
261
390
|
|
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
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
|
}
|
|
4
18
|
|
|
5
|
-
// eslint-disable-next-line no-shadow
|
|
6
19
|
export enum EntityProviderType {
|
|
7
20
|
CI_USER = 'CI_USER',
|
|
8
21
|
CI_MACHINE = 'CI_MACHINE',
|
|
@@ -11,12 +24,13 @@ export enum EntityProviderType {
|
|
|
11
24
|
}
|
|
12
25
|
|
|
13
26
|
export interface LookupOptions {
|
|
14
|
-
|
|
27
|
+
id: string;
|
|
15
28
|
entityProviderType?: EntityProviderType;
|
|
29
|
+
shouldBatch?: boolean;
|
|
16
30
|
}
|
|
17
31
|
|
|
18
32
|
export interface LookupByEmailOptions {
|
|
19
|
-
|
|
33
|
+
email: string;
|
|
20
34
|
}
|
|
21
35
|
|
|
22
36
|
// eslint-disable-next-line no-shadow
|
|
@@ -33,3 +47,8 @@ export interface SearchOptions {
|
|
|
33
47
|
resultSize: number;
|
|
34
48
|
queryString: string;
|
|
35
49
|
}
|
|
50
|
+
|
|
51
|
+
export interface BatcherOptions {
|
|
52
|
+
resource: string;
|
|
53
|
+
lookupValue: string;
|
|
54
|
+
}
|
|
@@ -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
|
+
});
|