@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/test/unit/spec/dss.ts
CHANGED
|
@@ -3,27 +3,30 @@
|
|
|
3
3
|
*/
|
|
4
4
|
/* eslint-disable no-underscore-dangle */
|
|
5
5
|
|
|
6
|
-
import {assert} from '@webex/test-helper-chai';
|
|
6
|
+
import {assert, expect} from '@webex/test-helper-chai';
|
|
7
7
|
import DSS from '@webex/internal-plugin-dss';
|
|
8
|
+
import {Batcher} from '@webex/webex-core';
|
|
8
9
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
9
10
|
import sinon from 'sinon';
|
|
10
|
-
import {expect} from 'chai';
|
|
11
11
|
import {set} from 'lodash';
|
|
12
12
|
import uuid from 'uuid';
|
|
13
|
+
import config from '@webex/internal-plugin-dss/src/config';
|
|
13
14
|
|
|
14
15
|
describe('plugin-dss', () => {
|
|
15
16
|
describe('DSS', () => {
|
|
16
17
|
let webex;
|
|
17
18
|
let uuidStub;
|
|
18
19
|
let mercuryCallbacks;
|
|
20
|
+
let clock;
|
|
19
21
|
|
|
20
22
|
beforeEach(() => {
|
|
21
|
-
webex =
|
|
23
|
+
webex = MockWebex({
|
|
22
24
|
canAuthorize: false,
|
|
23
25
|
children: {
|
|
24
26
|
dss: DSS,
|
|
25
27
|
},
|
|
26
28
|
});
|
|
29
|
+
webex.config.dss = config.dss;
|
|
27
30
|
|
|
28
31
|
uuidStub = sinon.stub(uuid, 'v4').returns('randomid');
|
|
29
32
|
|
|
@@ -40,10 +43,13 @@ describe('plugin-dss', () => {
|
|
|
40
43
|
}),
|
|
41
44
|
off: sinon.spy(),
|
|
42
45
|
};
|
|
46
|
+
|
|
47
|
+
clock = sinon.useFakeTimers();
|
|
43
48
|
});
|
|
44
49
|
|
|
45
50
|
afterEach(() => {
|
|
46
51
|
uuidStub.restore();
|
|
52
|
+
clock.restore();
|
|
47
53
|
});
|
|
48
54
|
|
|
49
55
|
describe('#register()', () => {
|
|
@@ -53,10 +59,12 @@ describe('plugin-dss', () => {
|
|
|
53
59
|
assert.callCount(webex.internal.mercury.on, 2);
|
|
54
60
|
|
|
55
61
|
const firstCallArgs = webex.internal.mercury.on.getCall(0).args;
|
|
62
|
+
|
|
56
63
|
expect(firstCallArgs[0]).to.equal('event:directory.lookup');
|
|
57
64
|
expect(firstCallArgs[1]).to.be.a('function');
|
|
58
65
|
|
|
59
66
|
const secondCallArgs = webex.internal.mercury.on.getCall(1).args;
|
|
67
|
+
|
|
60
68
|
expect(secondCallArgs[0]).to.equal('event:directory.search');
|
|
61
69
|
expect(secondCallArgs[1]).to.be.a('function');
|
|
62
70
|
|
|
@@ -82,9 +90,11 @@ describe('plugin-dss', () => {
|
|
|
82
90
|
assert.callCount(webex.internal.mercury.off, 2);
|
|
83
91
|
|
|
84
92
|
const firstCallArgs = webex.internal.mercury.off.getCall(0).args;
|
|
93
|
+
|
|
85
94
|
expect(firstCallArgs[0]).to.equal('event:directory.lookup');
|
|
86
95
|
|
|
87
96
|
const secondCallArgs = webex.internal.mercury.off.getCall(1).args;
|
|
97
|
+
|
|
88
98
|
expect(secondCallArgs[0]).to.equal('event:directory.search');
|
|
89
99
|
|
|
90
100
|
assert.equal(webex.internal.dss.registered, false);
|
|
@@ -92,24 +102,32 @@ describe('plugin-dss', () => {
|
|
|
92
102
|
|
|
93
103
|
it('handles unregister when it is not registered', async () => {
|
|
94
104
|
const result = await webex.internal.dss.unregister();
|
|
105
|
+
|
|
95
106
|
await expect(result).equal(undefined);
|
|
96
107
|
assert.equal(webex.internal.dss.registered, false);
|
|
97
108
|
});
|
|
98
109
|
});
|
|
99
110
|
|
|
100
|
-
const createData = (requestId, sequence, finished, dataPath) => {
|
|
111
|
+
const createData = (requestId, sequence, finished, dataPath, results) => {
|
|
101
112
|
const data = {
|
|
102
113
|
requestId,
|
|
103
114
|
sequence,
|
|
104
115
|
};
|
|
116
|
+
|
|
105
117
|
if (finished) {
|
|
106
118
|
(data as any).finished = finished;
|
|
107
119
|
}
|
|
108
|
-
set(data, dataPath,
|
|
120
|
+
set(data, dataPath, results);
|
|
121
|
+
|
|
109
122
|
return {data};
|
|
110
123
|
};
|
|
111
124
|
|
|
112
|
-
const
|
|
125
|
+
const testMakeRequest = async ({
|
|
126
|
+
method,
|
|
127
|
+
resource,
|
|
128
|
+
params,
|
|
129
|
+
bodyParams
|
|
130
|
+
}) => {
|
|
113
131
|
webex.request = sinon.stub();
|
|
114
132
|
|
|
115
133
|
await webex.internal.dss.register();
|
|
@@ -131,23 +149,59 @@ describe('plugin-dss', () => {
|
|
|
131
149
|
},
|
|
132
150
|
]);
|
|
133
151
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
152
|
+
return {requestId, promise};
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const testMakeBatchedRequests = async ({
|
|
156
|
+
requests,
|
|
157
|
+
calls,
|
|
158
|
+
}) => {
|
|
159
|
+
requests.forEach((request, index) => { uuidStub.onCall(index).returns(request.id); });
|
|
160
|
+
webex.request = sinon.stub();
|
|
161
|
+
|
|
162
|
+
await webex.internal.dss.register();
|
|
163
|
+
|
|
164
|
+
const promises = calls.map((call) => webex.internal.dss[call.method](call.params));
|
|
137
165
|
|
|
138
|
-
|
|
139
|
-
expect(
|
|
166
|
+
await clock.tickAsync(49);
|
|
167
|
+
expect(webex.request.notCalled).to.be.true;
|
|
168
|
+
await clock.tickAsync(1);
|
|
169
|
+
expect(webex.request.called).to.be.true;
|
|
170
|
+
|
|
171
|
+
requests.forEach((request, index) => {
|
|
172
|
+
expect(webex.request.getCall(index).args).to.deep.equal([
|
|
173
|
+
{
|
|
174
|
+
service: 'directorySearch',
|
|
175
|
+
body: {
|
|
176
|
+
requestId: request.id,
|
|
177
|
+
...request.bodyParams,
|
|
178
|
+
},
|
|
179
|
+
contentType: 'application/json',
|
|
180
|
+
method: 'POST',
|
|
181
|
+
resource: request.resource,
|
|
182
|
+
},
|
|
183
|
+
]);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
return {promises};
|
|
140
187
|
};
|
|
141
188
|
|
|
142
189
|
describe('#lookupDetail', () => {
|
|
143
190
|
it('calls _request correctly', async () => {
|
|
144
191
|
webex.internal.device.orgId = 'userOrgId';
|
|
145
|
-
webex.internal.dss._request = sinon.stub().returns(
|
|
192
|
+
webex.internal.dss._request = sinon.stub().returns(
|
|
193
|
+
Promise.resolve({
|
|
194
|
+
resultArray: ['some return value'],
|
|
195
|
+
foundArray: ['test id'],
|
|
196
|
+
})
|
|
197
|
+
);
|
|
146
198
|
|
|
147
199
|
const result = await webex.internal.dss.lookupDetail({id: 'test id'});
|
|
200
|
+
|
|
148
201
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
149
202
|
{
|
|
150
203
|
dataPath: 'lookupResult.entities',
|
|
204
|
+
foundPath: 'lookupResult.entitiesFound',
|
|
151
205
|
resource: '/lookup/orgid/userOrgId/identity/test id/detail',
|
|
152
206
|
},
|
|
153
207
|
]);
|
|
@@ -155,31 +209,57 @@ describe('plugin-dss', () => {
|
|
|
155
209
|
});
|
|
156
210
|
|
|
157
211
|
it('works correctly', async () => {
|
|
158
|
-
await
|
|
212
|
+
const {requestId, promise} = await testMakeRequest({
|
|
159
213
|
method: 'lookupDetail',
|
|
160
|
-
dataPath: 'lookupResult.entities',
|
|
161
|
-
event: 'event:directory.lookup',
|
|
162
214
|
resource: '/lookup/orgid/userOrgId/identity/test id/detail',
|
|
163
|
-
params: {
|
|
164
|
-
|
|
165
|
-
|
|
215
|
+
params: {id: 'test id'},
|
|
216
|
+
bodyParams: {},
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
220
|
+
createData(requestId, 0, true, 'lookupResult', {entities: ['data0'], entitiesFound: ['test id']})
|
|
221
|
+
);
|
|
222
|
+
const result = await promise;
|
|
223
|
+
|
|
224
|
+
expect(result).to.deep.equal('data0');
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('fails correctly if lookup fails', async () => {
|
|
228
|
+
const {requestId, promise} = await testMakeRequest({
|
|
229
|
+
method: 'lookupDetail',
|
|
230
|
+
resource: '/lookup/orgid/userOrgId/identity/test id/detail',
|
|
231
|
+
params: {id: 'test id'},
|
|
166
232
|
bodyParams: {},
|
|
167
233
|
});
|
|
234
|
+
|
|
235
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
236
|
+
createData(requestId, 0, true, 'lookupResult', {entitiesNotFound: ['test id']})
|
|
237
|
+
);
|
|
238
|
+
const result = await promise;
|
|
239
|
+
|
|
240
|
+
expect(result).to.be.null;
|
|
168
241
|
});
|
|
169
242
|
});
|
|
170
243
|
|
|
171
244
|
describe('#lookup', () => {
|
|
172
245
|
it('calls _request correctly', async () => {
|
|
173
246
|
webex.internal.device.orgId = 'userOrgId';
|
|
174
|
-
webex.internal.dss._request = sinon.stub().returns(
|
|
247
|
+
webex.internal.dss._request = sinon.stub().returns(
|
|
248
|
+
Promise.resolve({
|
|
249
|
+
resultArray: ['some return value'],
|
|
250
|
+
foundArray: ['id1'],
|
|
251
|
+
})
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
const result = await webex.internal.dss.lookup({id: 'id1', shouldBatch: false});
|
|
175
255
|
|
|
176
|
-
const result = await webex.internal.dss.lookup({ids: ['id1', 'id2']});
|
|
177
256
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
178
257
|
{
|
|
179
258
|
dataPath: 'lookupResult.entities',
|
|
259
|
+
foundPath: 'lookupResult.entitiesFound',
|
|
180
260
|
resource: '/lookup/orgid/userOrgId/identities',
|
|
181
261
|
params: {
|
|
182
|
-
lookupValues: ['id1'
|
|
262
|
+
lookupValues: ['id1'],
|
|
183
263
|
},
|
|
184
264
|
},
|
|
185
265
|
]);
|
|
@@ -188,18 +268,26 @@ describe('plugin-dss', () => {
|
|
|
188
268
|
|
|
189
269
|
it('calls _request correctly with entityProviderType', async () => {
|
|
190
270
|
webex.internal.device.orgId = 'userOrgId';
|
|
191
|
-
webex.internal.dss._request = sinon.stub().returns(
|
|
271
|
+
webex.internal.dss._request = sinon.stub().returns(
|
|
272
|
+
Promise.resolve({
|
|
273
|
+
resultArray: ['some return value'],
|
|
274
|
+
foundArray: ['id1'],
|
|
275
|
+
})
|
|
276
|
+
);
|
|
192
277
|
|
|
193
278
|
const result = await webex.internal.dss.lookup({
|
|
194
|
-
|
|
279
|
+
id: 'id1',
|
|
195
280
|
entityProviderType: 'CI_USER',
|
|
281
|
+
shouldBatch: false,
|
|
196
282
|
});
|
|
283
|
+
|
|
197
284
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
198
285
|
{
|
|
199
286
|
dataPath: 'lookupResult.entities',
|
|
287
|
+
foundPath: 'lookupResult.entitiesFound',
|
|
200
288
|
resource: '/lookup/orgid/userOrgId/entityprovidertype/CI_USER',
|
|
201
289
|
params: {
|
|
202
|
-
lookupValues: ['id1'
|
|
290
|
+
lookupValues: ['id1'],
|
|
203
291
|
},
|
|
204
292
|
},
|
|
205
293
|
]);
|
|
@@ -207,35 +295,293 @@ describe('plugin-dss', () => {
|
|
|
207
295
|
});
|
|
208
296
|
|
|
209
297
|
it('works correctly', async () => {
|
|
210
|
-
await
|
|
298
|
+
const {requestId, promise} = await testMakeRequest({
|
|
211
299
|
method: 'lookup',
|
|
212
|
-
dataPath: 'lookupResult.entities',
|
|
213
|
-
event: 'event:directory.lookup',
|
|
214
300
|
resource: '/lookup/orgid/userOrgId/identities',
|
|
215
|
-
params: {
|
|
216
|
-
|
|
301
|
+
params: {id: 'id1', shouldBatch: false},
|
|
302
|
+
bodyParams: {lookupValues: ['id1']},
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
306
|
+
createData(requestId, 0, true, 'lookupResult', {entities: ['data0'], entitiesFound: ['id1']})
|
|
307
|
+
);
|
|
308
|
+
const result = await promise;
|
|
309
|
+
|
|
310
|
+
expect(result).to.deep.equal('data0');
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('fails correctly if lookup fails', async () => {
|
|
314
|
+
const {requestId, promise} = await testMakeRequest({
|
|
315
|
+
method: 'lookup',
|
|
316
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
317
|
+
params: {id: 'id1', shouldBatch: false},
|
|
318
|
+
bodyParams: {lookupValues: ['id1']},
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
322
|
+
createData(requestId, 0, true, 'lookupResult', {entitiesNotFound: ['id1']})
|
|
323
|
+
);
|
|
324
|
+
const result = await promise;
|
|
325
|
+
|
|
326
|
+
expect(result).to.be.null;
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it('calls _batchedLookup correctly', async () => {
|
|
330
|
+
webex.internal.device.orgId = 'userOrgId';
|
|
331
|
+
webex.internal.dss._batchedLookup = sinon.stub().returns(
|
|
332
|
+
Promise.resolve('some return value')
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
const result = await webex.internal.dss.lookup({id: 'id1'});
|
|
336
|
+
|
|
337
|
+
expect(webex.internal.dss._batchedLookup.getCall(0).args).to.deep.equal([
|
|
338
|
+
{
|
|
339
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
340
|
+
lookupValue: 'id1',
|
|
217
341
|
},
|
|
218
|
-
|
|
219
|
-
|
|
342
|
+
]);
|
|
343
|
+
expect(result).to.equal('some return value');
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it('calls _batchedLookup correctly with entityProviderType', async () => {
|
|
347
|
+
webex.internal.device.orgId = 'userOrgId';
|
|
348
|
+
webex.internal.dss._batchedLookup = sinon.stub().returns(
|
|
349
|
+
Promise.resolve('some return value'),
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
const result = await webex.internal.dss.lookup({
|
|
353
|
+
id: 'id1',
|
|
354
|
+
entityProviderType: 'CI_USER',
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
expect(webex.internal.dss._batchedLookup.getCall(0).args).to.deep.equal([
|
|
358
|
+
{
|
|
359
|
+
resource: '/lookup/orgid/userOrgId/entityprovidertype/CI_USER',
|
|
360
|
+
lookupValue: 'id1',
|
|
220
361
|
},
|
|
362
|
+
]);
|
|
363
|
+
expect(result).to.equal('some return value');
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
it('Single batched lookup is made after 50 ms and works', async () => {
|
|
367
|
+
const {promises} = await testMakeBatchedRequests({
|
|
368
|
+
requests: [
|
|
369
|
+
{
|
|
370
|
+
id: 'randomid1',
|
|
371
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
372
|
+
bodyParams: {lookupValues: ['id1']},
|
|
373
|
+
}
|
|
374
|
+
],
|
|
375
|
+
calls: [
|
|
376
|
+
{
|
|
377
|
+
method: 'lookup',
|
|
378
|
+
params: {id: 'id1', shouldBatch: true},
|
|
379
|
+
}
|
|
380
|
+
],
|
|
221
381
|
});
|
|
382
|
+
|
|
383
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
384
|
+
createData('randomid1', 0, true, 'lookupResult', {entities: ['data0'], entitiesFound: ['id1']})
|
|
385
|
+
);
|
|
386
|
+
const result = await promises[0];
|
|
387
|
+
|
|
388
|
+
expect(result).to.deep.equal('data0');
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it('Single batched lookup fails correctly if lookup fails', async () => {
|
|
392
|
+
const {promises} = await testMakeBatchedRequests({
|
|
393
|
+
requests: [
|
|
394
|
+
{
|
|
395
|
+
id: 'randomid1',
|
|
396
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
397
|
+
bodyParams: {lookupValues: ['id1']},
|
|
398
|
+
}
|
|
399
|
+
],
|
|
400
|
+
calls: [
|
|
401
|
+
{
|
|
402
|
+
method: 'lookup',
|
|
403
|
+
params: {id: 'id1', shouldBatch: true},
|
|
404
|
+
}
|
|
405
|
+
],
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
409
|
+
createData('randomid1', 0, true, 'lookupResult', {entitiesNotFound: ['id1']})
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
const result = await promises[0];
|
|
413
|
+
|
|
414
|
+
expect(result).to.be.null;
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
it('Batch of 2 lookups is made after 50 ms and works', async () => {
|
|
418
|
+
const {promises} = await testMakeBatchedRequests({
|
|
419
|
+
requests: [
|
|
420
|
+
{
|
|
421
|
+
id: 'randomid1',
|
|
422
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
423
|
+
bodyParams: {lookupValues: ['id1', 'id2']},
|
|
424
|
+
}
|
|
425
|
+
],
|
|
426
|
+
calls: [
|
|
427
|
+
{
|
|
428
|
+
method: 'lookup',
|
|
429
|
+
params: {id: 'id1', shouldBatch: true},
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
method: 'lookup',
|
|
433
|
+
params: {id: 'id2', shouldBatch: true},
|
|
434
|
+
},
|
|
435
|
+
],
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
439
|
+
createData('randomid1', 0, true, 'lookupResult', {entities: ['data1', 'data2'], entitiesFound: ['id1', 'id2']})
|
|
440
|
+
);
|
|
441
|
+
const result1 = await promises[0];
|
|
442
|
+
|
|
443
|
+
expect(result1).to.equal('data1');
|
|
444
|
+
const result2 = await promises[1];
|
|
445
|
+
|
|
446
|
+
expect(result2).to.equal('data2');
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
it('Batch of 2 lookups is made after 50 ms and one fails correctly', async () => {
|
|
450
|
+
const {promises} = await testMakeBatchedRequests({
|
|
451
|
+
requests: [
|
|
452
|
+
{
|
|
453
|
+
id: 'randomid1',
|
|
454
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
455
|
+
bodyParams: {lookupValues: ['id1', 'id2']},
|
|
456
|
+
}
|
|
457
|
+
],
|
|
458
|
+
calls: [
|
|
459
|
+
{
|
|
460
|
+
method: 'lookup',
|
|
461
|
+
params: {id: 'id1', shouldBatch: true},
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
method: 'lookup',
|
|
465
|
+
params: {id: 'id2', shouldBatch: true},
|
|
466
|
+
},
|
|
467
|
+
],
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
471
|
+
createData('randomid1', 0, true, 'lookupResult', {entities: ['data2'], entitiesFound: ['id2'], entitiesNotFound: ['id1']})
|
|
472
|
+
);
|
|
473
|
+
const result1 = await promises[0];
|
|
474
|
+
|
|
475
|
+
expect(result1).to.be.null;
|
|
476
|
+
|
|
477
|
+
const result2 = await promises[1];
|
|
478
|
+
|
|
479
|
+
expect(result2).to.equal('data2');
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
it('Two unrelated lookups are made after 50 ms and work', async () => {
|
|
483
|
+
const {promises} = await testMakeBatchedRequests({
|
|
484
|
+
requests: [
|
|
485
|
+
{
|
|
486
|
+
id: 'randomid1',
|
|
487
|
+
resource: '/lookup/orgid/userOrgId/entityprovidertype/CI_USER',
|
|
488
|
+
bodyParams: {lookupValues: ['id1']},
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
id: 'randomid2',
|
|
492
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
493
|
+
bodyParams: {lookupValues: ['id2']},
|
|
494
|
+
}
|
|
495
|
+
],
|
|
496
|
+
calls: [
|
|
497
|
+
{
|
|
498
|
+
method: 'lookup',
|
|
499
|
+
params: {id: 'id1', entityProviderType: 'CI_USER', shouldBatch: true},
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
method: 'lookup',
|
|
503
|
+
params: {id: 'id2', shouldBatch: true},
|
|
504
|
+
},
|
|
505
|
+
],
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
509
|
+
createData('randomid1', 0, true, 'lookupResult', {entities: ['data1'], entitiesFound: ['id1']})
|
|
510
|
+
);
|
|
511
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
512
|
+
createData('randomid2', 0, true, 'lookupResult', {entities: ['data2'], entitiesFound: ['id2']})
|
|
513
|
+
);
|
|
514
|
+
const result1 = await promises[0];
|
|
515
|
+
|
|
516
|
+
expect(result1).to.equal('data1');
|
|
517
|
+
const result2 = await promises[1];
|
|
518
|
+
|
|
519
|
+
expect(result2).to.equal('data2');
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
it('Two unrelated lookups are made after 50 ms and one fails correctly', async () => {
|
|
523
|
+
const {promises} = await testMakeBatchedRequests({
|
|
524
|
+
requests: [
|
|
525
|
+
{
|
|
526
|
+
id: 'randomid1',
|
|
527
|
+
resource: '/lookup/orgid/userOrgId/entityprovidertype/CI_USER',
|
|
528
|
+
bodyParams: {lookupValues: ['id1']},
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
id: 'randomid2',
|
|
532
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
533
|
+
bodyParams: {lookupValues: ['id2']},
|
|
534
|
+
}
|
|
535
|
+
],
|
|
536
|
+
calls: [
|
|
537
|
+
{
|
|
538
|
+
method: 'lookup',
|
|
539
|
+
params: {id: 'id1', entityProviderType: 'CI_USER', shouldBatch: true},
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
method: 'lookup',
|
|
543
|
+
params: {id: 'id2', shouldBatch: true},
|
|
544
|
+
},
|
|
545
|
+
],
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
549
|
+
createData('randomid1', 0, true, 'lookupResult', {entitiesNotFound: ['id1']})
|
|
550
|
+
);
|
|
551
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
552
|
+
createData('randomid2', 0, true, 'lookupResult', {entities: ['data2'], entitiesFound: ['id2']})
|
|
553
|
+
);
|
|
554
|
+
const result1 = await promises[0];
|
|
555
|
+
|
|
556
|
+
expect(result1).to.be.null;
|
|
557
|
+
const result2 = await promises[1];
|
|
558
|
+
|
|
559
|
+
expect(result2).to.equal('data2');
|
|
222
560
|
});
|
|
223
561
|
});
|
|
224
562
|
|
|
225
563
|
describe('#lookupByEmail', () => {
|
|
226
564
|
it('calls _request correctly', async () => {
|
|
227
565
|
webex.internal.device.orgId = 'userOrgId';
|
|
228
|
-
webex.internal.dss._request = sinon.stub().returns(
|
|
566
|
+
webex.internal.dss._request = sinon.stub().returns(
|
|
567
|
+
Promise.resolve({
|
|
568
|
+
resultArray: ['some return value'],
|
|
569
|
+
foundArray: ['email1'],
|
|
570
|
+
})
|
|
571
|
+
);
|
|
229
572
|
|
|
230
573
|
const result = await webex.internal.dss.lookupByEmail({
|
|
231
|
-
|
|
574
|
+
email: 'email1',
|
|
232
575
|
});
|
|
576
|
+
|
|
233
577
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
234
578
|
{
|
|
235
579
|
dataPath: 'lookupResult.entities',
|
|
580
|
+
foundPath: 'lookupResult.entitiesFound',
|
|
236
581
|
resource: '/lookup/orgid/userOrgId/emails',
|
|
582
|
+
|
|
237
583
|
params: {
|
|
238
|
-
lookupValues: ['email1'
|
|
584
|
+
lookupValues: ['email1'],
|
|
239
585
|
},
|
|
240
586
|
},
|
|
241
587
|
]);
|
|
@@ -243,31 +589,51 @@ describe('plugin-dss', () => {
|
|
|
243
589
|
});
|
|
244
590
|
|
|
245
591
|
it('works correctly', async () => {
|
|
246
|
-
await
|
|
592
|
+
const {requestId, promise} = await testMakeRequest({
|
|
247
593
|
method: 'lookupByEmail',
|
|
248
|
-
dataPath: 'lookupResult.entities',
|
|
249
|
-
event: 'event:directory.lookup',
|
|
250
594
|
resource: '/lookup/orgid/userOrgId/emails',
|
|
251
|
-
params: {
|
|
252
|
-
|
|
253
|
-
},
|
|
254
|
-
bodyParams: {
|
|
255
|
-
lookupValues: ['email1', 'email2'],
|
|
256
|
-
},
|
|
595
|
+
params: {email: 'email1'},
|
|
596
|
+
bodyParams: {lookupValues: ['email1']},
|
|
257
597
|
});
|
|
598
|
+
|
|
599
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
600
|
+
createData(requestId, 0, true, 'lookupResult', {entities: ['data0'], entitiesFound: ['email1']})
|
|
601
|
+
);
|
|
602
|
+
const result = await promise;
|
|
603
|
+
|
|
604
|
+
expect(result).to.deep.equal('data0');
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
it('fails correctly if lookup fails', async () => {
|
|
608
|
+
const {requestId, promise} = await testMakeRequest({
|
|
609
|
+
method: 'lookupByEmail',
|
|
610
|
+
resource: '/lookup/orgid/userOrgId/emails',
|
|
611
|
+
params: {email: 'email1'},
|
|
612
|
+
bodyParams: {lookupValues: ['email1']},
|
|
613
|
+
});
|
|
614
|
+
|
|
615
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
616
|
+
createData(requestId, 0, true, 'lookupResult', {}) // entitiesNotFound isn't returned for email
|
|
617
|
+
);
|
|
618
|
+
const result = await promise;
|
|
619
|
+
|
|
620
|
+
expect(result).to.be.null;
|
|
258
621
|
});
|
|
259
622
|
});
|
|
260
623
|
|
|
261
624
|
describe('#search', () => {
|
|
262
625
|
it('calls _request correctly', async () => {
|
|
263
626
|
webex.internal.device.orgId = 'userOrgId';
|
|
264
|
-
webex.internal.dss._request = sinon
|
|
627
|
+
webex.internal.dss._request = sinon
|
|
628
|
+
.stub()
|
|
629
|
+
.returns(Promise.resolve({resultArray: 'some return value'}));
|
|
265
630
|
|
|
266
631
|
const result = await webex.internal.dss.search({
|
|
267
632
|
requestedTypes: ['PERSON', 'ROBOT'],
|
|
268
633
|
resultSize: 100,
|
|
269
634
|
queryString: 'query',
|
|
270
635
|
});
|
|
636
|
+
|
|
271
637
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
272
638
|
{
|
|
273
639
|
dataPath: 'directoryEntities',
|
|
@@ -283,10 +649,8 @@ describe('plugin-dss', () => {
|
|
|
283
649
|
});
|
|
284
650
|
|
|
285
651
|
it('works correctly', async () => {
|
|
286
|
-
await
|
|
652
|
+
const {requestId, promise} = await testMakeRequest({
|
|
287
653
|
method: 'search',
|
|
288
|
-
event: 'event:directory.search',
|
|
289
|
-
dataPath: 'directoryEntities',
|
|
290
654
|
resource: '/search/orgid/userOrgId/entities',
|
|
291
655
|
params: {
|
|
292
656
|
requestedTypes: ['PERSON', 'ROBOT'],
|
|
@@ -299,6 +663,13 @@ describe('plugin-dss', () => {
|
|
|
299
663
|
queryString: 'query',
|
|
300
664
|
},
|
|
301
665
|
});
|
|
666
|
+
|
|
667
|
+
mercuryCallbacks['event:directory.search'](createData(requestId, 1, false, 'directoryEntities', ['data1']));
|
|
668
|
+
mercuryCallbacks['event:directory.search'](createData(requestId, 2, true, 'directoryEntities', ['data2']));
|
|
669
|
+
mercuryCallbacks['event:directory.search'](createData(requestId, 0, false, 'directoryEntities', ['data0']));
|
|
670
|
+
const result = await promise;
|
|
671
|
+
|
|
672
|
+
expect(result).to.deep.equal(['data0', 'data1', 'data2']);
|
|
302
673
|
});
|
|
303
674
|
});
|
|
304
675
|
|
|
@@ -327,34 +698,228 @@ describe('plugin-dss', () => {
|
|
|
327
698
|
|
|
328
699
|
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
329
700
|
sequence: 1,
|
|
330
|
-
a: {
|
|
331
|
-
b: {
|
|
332
|
-
c: ['data1'],
|
|
333
|
-
},
|
|
334
|
-
},
|
|
701
|
+
a: {b: {c: ['data1']}},
|
|
335
702
|
});
|
|
336
|
-
|
|
337
703
|
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
338
704
|
sequence: 2,
|
|
339
705
|
finished: true,
|
|
340
|
-
a: {
|
|
341
|
-
|
|
342
|
-
|
|
706
|
+
a: {b: {c: ['data2']}},
|
|
707
|
+
});
|
|
708
|
+
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
709
|
+
sequence: 0,
|
|
710
|
+
a: {b: {c: ['data0']}},
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
const result = await promise;
|
|
714
|
+
|
|
715
|
+
expect(result).to.deep.equal({
|
|
716
|
+
resultArray: ['data0', 'data1', 'data2'],
|
|
717
|
+
});
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
it('handles a request with foundPath correctly', async () => {
|
|
721
|
+
webex.request = sinon.stub();
|
|
722
|
+
uuid.v4.returns('randomid');
|
|
723
|
+
const promise = webex.internal.dss._request({
|
|
724
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
725
|
+
params: {some: 'param'},
|
|
726
|
+
dataPath: 'a.b.c',
|
|
727
|
+
foundPath: 'someFoundPath'
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
expect(webex.request.getCall(0).args).to.deep.equal([
|
|
731
|
+
{
|
|
732
|
+
service: 'directorySearch',
|
|
733
|
+
body: {
|
|
734
|
+
requestId: 'randomid',
|
|
735
|
+
some: 'param',
|
|
343
736
|
},
|
|
737
|
+
contentType: 'application/json',
|
|
738
|
+
method: 'POST',
|
|
739
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
344
740
|
},
|
|
345
|
-
|
|
741
|
+
]);
|
|
346
742
|
|
|
743
|
+
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
744
|
+
sequence: 1,
|
|
745
|
+
a: {b: {c: ['data1']}},
|
|
746
|
+
someFoundPath: ['id1'],
|
|
747
|
+
});
|
|
748
|
+
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
749
|
+
sequence: 2,
|
|
750
|
+
finished: true,
|
|
751
|
+
a: {b: {c: ['data2']}},
|
|
752
|
+
someFoundPath: ['id2'],
|
|
753
|
+
});
|
|
347
754
|
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
348
755
|
sequence: 0,
|
|
349
|
-
a: {
|
|
350
|
-
|
|
351
|
-
|
|
756
|
+
a: {b: {c: ['data0']}},
|
|
757
|
+
someFoundPath: ['id0'],
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
const result = await promise;
|
|
761
|
+
|
|
762
|
+
expect(result).to.deep.equal({
|
|
763
|
+
resultArray: ['data0', 'data1', 'data2'],
|
|
764
|
+
foundArray: ['id0', 'id1', 'id2'],
|
|
765
|
+
});
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
it('handles a request with foundPath and notFoundPath correctly', async () => {
|
|
769
|
+
webex.request = sinon.stub();
|
|
770
|
+
uuid.v4.returns('randomid');
|
|
771
|
+
const promise = webex.internal.dss._request({
|
|
772
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
773
|
+
params: {some: 'param'},
|
|
774
|
+
dataPath: 'a.b.c',
|
|
775
|
+
foundPath: 'someFoundPath',
|
|
776
|
+
notFoundPath: 'someNotFoundPath',
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
expect(webex.request.getCall(0).args).to.deep.equal([
|
|
780
|
+
{
|
|
781
|
+
service: 'directorySearch',
|
|
782
|
+
body: {
|
|
783
|
+
requestId: 'randomid',
|
|
784
|
+
some: 'param',
|
|
352
785
|
},
|
|
786
|
+
contentType: 'application/json',
|
|
787
|
+
method: 'POST',
|
|
788
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
353
789
|
},
|
|
790
|
+
]);
|
|
791
|
+
|
|
792
|
+
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
793
|
+
sequence: 1,
|
|
794
|
+
a: {b: {c: ['data1']}},
|
|
795
|
+
someFoundPath: ['id1'],
|
|
796
|
+
});
|
|
797
|
+
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
798
|
+
sequence: 2,
|
|
799
|
+
finished: true,
|
|
800
|
+
a: {b: {c: ['data2']}},
|
|
801
|
+
someFoundPath: ['id2'],
|
|
802
|
+
someNotFoundPath: ['id3'],
|
|
803
|
+
});
|
|
804
|
+
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
805
|
+
sequence: 0,
|
|
806
|
+
a: {b: {c: ['data0']}},
|
|
807
|
+
someFoundPath: ['id0'],
|
|
354
808
|
});
|
|
355
809
|
|
|
356
810
|
const result = await promise;
|
|
357
|
-
|
|
811
|
+
|
|
812
|
+
expect(result).to.deep.equal({
|
|
813
|
+
resultArray: ['data0', 'data1', 'data2'],
|
|
814
|
+
foundArray: ['id0', 'id1', 'id2'],
|
|
815
|
+
notFoundArray: ['id3'],
|
|
816
|
+
});
|
|
817
|
+
});
|
|
818
|
+
});
|
|
819
|
+
|
|
820
|
+
describe('#_batchedLookup', () => {
|
|
821
|
+
const checkStandardProperties = (batcher) => {
|
|
822
|
+
expect(batcher.dataPath).to.equal('lookupResult.entities');
|
|
823
|
+
expect(batcher.entitiesFoundPath).to.equal('lookupResult.entitiesFound');
|
|
824
|
+
expect(batcher.entitiesNotFoundPath).to.equal('lookupResult.entitiesNotFound');
|
|
825
|
+
expect(batcher.requestKey).to.equal('lookupValues');
|
|
826
|
+
expect(batcher.config).to.deep.equal({
|
|
827
|
+
batcherWait: 50,
|
|
828
|
+
batcherMaxCalls: 50,
|
|
829
|
+
batcherMaxWait: 150
|
|
830
|
+
});
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
it('calls batcher.request on new batcher for first lookup', async () => {
|
|
834
|
+
const resource = '/lookup/orgid/userOrgId/identities';
|
|
835
|
+
const response = 'response1';
|
|
836
|
+
|
|
837
|
+
Batcher.prototype.request = sinon.stub()
|
|
838
|
+
.returns(Promise.resolve(response));
|
|
839
|
+
|
|
840
|
+
expect(webex.internal.dss.batchers).to.deep.equal({});
|
|
841
|
+
|
|
842
|
+
const result = await webex.internal.dss._batchedLookup({
|
|
843
|
+
resource,
|
|
844
|
+
lookupValue: 'id1',
|
|
845
|
+
});
|
|
846
|
+
|
|
847
|
+
const batcher = webex.internal.dss.batchers[resource];
|
|
848
|
+
|
|
849
|
+
expect(batcher).to.exist;
|
|
850
|
+
expect(batcher.resource).to.equal(resource);
|
|
851
|
+
checkStandardProperties(batcher);
|
|
852
|
+
|
|
853
|
+
expect(Batcher.prototype.request.getCall(0).args).to.deep.equal(['id1']);
|
|
854
|
+
expect(result).to.equal(response);
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
it('calls batcher.request on new batcher for lookup with new reource', async () => {
|
|
858
|
+
const resource1 = '/lookup/orgid/userOrgId/identities';
|
|
859
|
+
const resource2 = '/lookup/orgid/userOrgId/entityprovidertype/CI_USER';
|
|
860
|
+
const response1 = 'response1';
|
|
861
|
+
const response2 = 'response2';
|
|
862
|
+
|
|
863
|
+
Batcher.prototype.request = sinon.stub()
|
|
864
|
+
.onFirstCall().returns(Promise.resolve(response1))
|
|
865
|
+
.onSecondCall()
|
|
866
|
+
.returns(Promise.resolve(response2));
|
|
867
|
+
|
|
868
|
+
expect(webex.internal.dss.batchers).to.deep.equal({});
|
|
869
|
+
|
|
870
|
+
await webex.internal.dss._batchedLookup({
|
|
871
|
+
resource: resource1,
|
|
872
|
+
lookupValue: 'id1',
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
const result = await webex.internal.dss._batchedLookup({
|
|
876
|
+
resource: resource2,
|
|
877
|
+
lookupValue: 'id2',
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
expect(webex.internal.dss.batchers[resource1]).to.exist;
|
|
881
|
+
const batcher = webex.internal.dss.batchers[resource2];
|
|
882
|
+
|
|
883
|
+
expect(batcher).to.exist;
|
|
884
|
+
expect(batcher.resource).to.equal(resource2);
|
|
885
|
+
checkStandardProperties(batcher);
|
|
886
|
+
|
|
887
|
+
expect(Batcher.prototype.request.getCall(1).args).to.deep.equal(['id2']);
|
|
888
|
+
expect(result).to.equal(response2);
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
it('calls batcher.request on existing batcher for lookup with existing reource', async () => {
|
|
892
|
+
const resource1 = '/lookup/orgid/userOrgId/identities';
|
|
893
|
+
const response1 = 'response1';
|
|
894
|
+
const response2 = 'response2';
|
|
895
|
+
|
|
896
|
+
Batcher.prototype.request = sinon.stub()
|
|
897
|
+
.onFirstCall().returns(Promise.resolve(response1))
|
|
898
|
+
.onSecondCall()
|
|
899
|
+
.returns(Promise.resolve(response2));
|
|
900
|
+
|
|
901
|
+
expect(webex.internal.dss.batchers).to.deep.equal({});
|
|
902
|
+
|
|
903
|
+
await webex.internal.dss._batchedLookup({
|
|
904
|
+
resource: resource1,
|
|
905
|
+
lookupValue: 'id1',
|
|
906
|
+
});
|
|
907
|
+
expect(webex.internal.dss.batchers[resource1]).to.exist;
|
|
908
|
+
const initialBatcher = webex.internal.dss.batchers[resource1];
|
|
909
|
+
|
|
910
|
+
const result = await webex.internal.dss._batchedLookup({
|
|
911
|
+
resource: resource1,
|
|
912
|
+
lookupValue: 'id2',
|
|
913
|
+
});
|
|
914
|
+
|
|
915
|
+
const batcher = webex.internal.dss.batchers[resource1];
|
|
916
|
+
|
|
917
|
+
expect(batcher).to.equal(initialBatcher);
|
|
918
|
+
expect(batcher.resource).to.equal(resource1);
|
|
919
|
+
checkStandardProperties(batcher);
|
|
920
|
+
|
|
921
|
+
expect(Batcher.prototype.request.getCall(1).args).to.deep.equal(['id2']);
|
|
922
|
+
expect(result).to.equal(response2);
|
|
358
923
|
});
|
|
359
924
|
});
|
|
360
925
|
});
|