@webex/internal-plugin-dss 3.0.0-beta.19 → 3.0.0-beta.191
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 +8 -6
- package/src/config.ts +25 -0
- package/src/constants.ts +5 -0
- package/src/dss-batcher.ts +129 -0
- package/src/dss.ts +138 -28
- 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 +627 -61
package/test/unit/spec/dss.ts
CHANGED
|
@@ -1,28 +1,32 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Copyright (c) 2015-2022 Cisco Systems, Inc. See LICENSE file.
|
|
3
3
|
*/
|
|
4
|
+
/* eslint-disable no-underscore-dangle */
|
|
4
5
|
|
|
5
|
-
import {assert} from '@webex/test-helper-chai';
|
|
6
|
+
import {assert, expect} from '@webex/test-helper-chai';
|
|
6
7
|
import DSS from '@webex/internal-plugin-dss';
|
|
8
|
+
import {Batcher} from '@webex/webex-core';
|
|
7
9
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
8
10
|
import sinon from 'sinon';
|
|
9
|
-
import {expect} from 'chai';
|
|
10
11
|
import {set} from 'lodash';
|
|
11
12
|
import uuid from 'uuid';
|
|
13
|
+
import config from '@webex/internal-plugin-dss/src/config';
|
|
12
14
|
|
|
13
15
|
describe('plugin-dss', () => {
|
|
14
16
|
describe('DSS', () => {
|
|
15
17
|
let webex;
|
|
16
18
|
let uuidStub;
|
|
17
19
|
let mercuryCallbacks;
|
|
20
|
+
let clock;
|
|
18
21
|
|
|
19
22
|
beforeEach(() => {
|
|
20
|
-
webex =
|
|
23
|
+
webex = MockWebex({
|
|
21
24
|
canAuthorize: false,
|
|
22
25
|
children: {
|
|
23
26
|
dss: DSS,
|
|
24
27
|
},
|
|
25
28
|
});
|
|
29
|
+
webex.config.dss = config.dss;
|
|
26
30
|
|
|
27
31
|
uuidStub = sinon.stub(uuid, 'v4').returns('randomid');
|
|
28
32
|
|
|
@@ -39,10 +43,13 @@ describe('plugin-dss', () => {
|
|
|
39
43
|
}),
|
|
40
44
|
off: sinon.spy(),
|
|
41
45
|
};
|
|
46
|
+
|
|
47
|
+
clock = sinon.useFakeTimers();
|
|
42
48
|
});
|
|
43
49
|
|
|
44
50
|
afterEach(() => {
|
|
45
51
|
uuidStub.restore();
|
|
52
|
+
clock.restore();
|
|
46
53
|
});
|
|
47
54
|
|
|
48
55
|
describe('#register()', () => {
|
|
@@ -52,10 +59,12 @@ describe('plugin-dss', () => {
|
|
|
52
59
|
assert.callCount(webex.internal.mercury.on, 2);
|
|
53
60
|
|
|
54
61
|
const firstCallArgs = webex.internal.mercury.on.getCall(0).args;
|
|
62
|
+
|
|
55
63
|
expect(firstCallArgs[0]).to.equal('event:directory.lookup');
|
|
56
64
|
expect(firstCallArgs[1]).to.be.a('function');
|
|
57
65
|
|
|
58
66
|
const secondCallArgs = webex.internal.mercury.on.getCall(1).args;
|
|
67
|
+
|
|
59
68
|
expect(secondCallArgs[0]).to.equal('event:directory.search');
|
|
60
69
|
expect(secondCallArgs[1]).to.be.a('function');
|
|
61
70
|
|
|
@@ -81,9 +90,11 @@ describe('plugin-dss', () => {
|
|
|
81
90
|
assert.callCount(webex.internal.mercury.off, 2);
|
|
82
91
|
|
|
83
92
|
const firstCallArgs = webex.internal.mercury.off.getCall(0).args;
|
|
93
|
+
|
|
84
94
|
expect(firstCallArgs[0]).to.equal('event:directory.lookup');
|
|
85
95
|
|
|
86
96
|
const secondCallArgs = webex.internal.mercury.off.getCall(1).args;
|
|
97
|
+
|
|
87
98
|
expect(secondCallArgs[0]).to.equal('event:directory.search');
|
|
88
99
|
|
|
89
100
|
assert.equal(webex.internal.dss.registered, false);
|
|
@@ -91,24 +102,32 @@ describe('plugin-dss', () => {
|
|
|
91
102
|
|
|
92
103
|
it('handles unregister when it is not registered', async () => {
|
|
93
104
|
const result = await webex.internal.dss.unregister();
|
|
105
|
+
|
|
94
106
|
await expect(result).equal(undefined);
|
|
95
107
|
assert.equal(webex.internal.dss.registered, false);
|
|
96
108
|
});
|
|
97
109
|
});
|
|
98
110
|
|
|
99
|
-
const createData = (requestId, sequence, finished, dataPath) => {
|
|
111
|
+
const createData = (requestId, sequence, finished, dataPath, results) => {
|
|
100
112
|
const data = {
|
|
101
113
|
requestId,
|
|
102
114
|
sequence,
|
|
103
115
|
};
|
|
116
|
+
|
|
104
117
|
if (finished) {
|
|
105
118
|
(data as any).finished = finished;
|
|
106
119
|
}
|
|
107
|
-
set(data, dataPath,
|
|
120
|
+
set(data, dataPath, results);
|
|
121
|
+
|
|
108
122
|
return {data};
|
|
109
123
|
};
|
|
110
124
|
|
|
111
|
-
const
|
|
125
|
+
const testMakeRequest = async ({
|
|
126
|
+
method,
|
|
127
|
+
resource,
|
|
128
|
+
params,
|
|
129
|
+
bodyParams
|
|
130
|
+
}) => {
|
|
112
131
|
webex.request = sinon.stub();
|
|
113
132
|
|
|
114
133
|
await webex.internal.dss.register();
|
|
@@ -130,23 +149,59 @@ describe('plugin-dss', () => {
|
|
|
130
149
|
},
|
|
131
150
|
]);
|
|
132
151
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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));
|
|
136
165
|
|
|
137
|
-
|
|
138
|
-
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};
|
|
139
187
|
};
|
|
140
188
|
|
|
141
189
|
describe('#lookupDetail', () => {
|
|
142
190
|
it('calls _request correctly', async () => {
|
|
143
191
|
webex.internal.device.orgId = 'userOrgId';
|
|
144
|
-
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
|
+
);
|
|
145
198
|
|
|
146
199
|
const result = await webex.internal.dss.lookupDetail({id: 'test id'});
|
|
200
|
+
|
|
147
201
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
148
202
|
{
|
|
149
203
|
dataPath: 'lookupResult.entities',
|
|
204
|
+
foundPath: 'lookupResult.entitiesFound',
|
|
150
205
|
resource: '/lookup/orgid/userOrgId/identity/test id/detail',
|
|
151
206
|
},
|
|
152
207
|
]);
|
|
@@ -154,31 +209,57 @@ describe('plugin-dss', () => {
|
|
|
154
209
|
});
|
|
155
210
|
|
|
156
211
|
it('works correctly', async () => {
|
|
157
|
-
await
|
|
212
|
+
const {requestId, promise} = await testMakeRequest({
|
|
158
213
|
method: 'lookupDetail',
|
|
159
|
-
dataPath: 'lookupResult.entities',
|
|
160
|
-
event: 'event:directory.lookup',
|
|
161
214
|
resource: '/lookup/orgid/userOrgId/identity/test id/detail',
|
|
162
|
-
params: {
|
|
163
|
-
|
|
164
|
-
|
|
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'},
|
|
165
232
|
bodyParams: {},
|
|
166
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;
|
|
167
241
|
});
|
|
168
242
|
});
|
|
169
243
|
|
|
170
244
|
describe('#lookup', () => {
|
|
171
245
|
it('calls _request correctly', async () => {
|
|
172
246
|
webex.internal.device.orgId = 'userOrgId';
|
|
173
|
-
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});
|
|
174
255
|
|
|
175
|
-
const result = await webex.internal.dss.lookup({ids: ['id1', 'id2']});
|
|
176
256
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
177
257
|
{
|
|
178
258
|
dataPath: 'lookupResult.entities',
|
|
259
|
+
foundPath: 'lookupResult.entitiesFound',
|
|
179
260
|
resource: '/lookup/orgid/userOrgId/identities',
|
|
180
261
|
params: {
|
|
181
|
-
lookupValues: ['id1'
|
|
262
|
+
lookupValues: ['id1'],
|
|
182
263
|
},
|
|
183
264
|
},
|
|
184
265
|
]);
|
|
@@ -187,18 +268,26 @@ describe('plugin-dss', () => {
|
|
|
187
268
|
|
|
188
269
|
it('calls _request correctly with entityProviderType', async () => {
|
|
189
270
|
webex.internal.device.orgId = 'userOrgId';
|
|
190
|
-
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
|
+
);
|
|
191
277
|
|
|
192
278
|
const result = await webex.internal.dss.lookup({
|
|
193
|
-
|
|
279
|
+
id: 'id1',
|
|
194
280
|
entityProviderType: 'CI_USER',
|
|
281
|
+
shouldBatch: false,
|
|
195
282
|
});
|
|
283
|
+
|
|
196
284
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
197
285
|
{
|
|
198
286
|
dataPath: 'lookupResult.entities',
|
|
287
|
+
foundPath: 'lookupResult.entitiesFound',
|
|
199
288
|
resource: '/lookup/orgid/userOrgId/entityprovidertype/CI_USER',
|
|
200
289
|
params: {
|
|
201
|
-
lookupValues: ['id1'
|
|
290
|
+
lookupValues: ['id1'],
|
|
202
291
|
},
|
|
203
292
|
},
|
|
204
293
|
]);
|
|
@@ -206,35 +295,293 @@ describe('plugin-dss', () => {
|
|
|
206
295
|
});
|
|
207
296
|
|
|
208
297
|
it('works correctly', async () => {
|
|
209
|
-
await
|
|
298
|
+
const {requestId, promise} = await testMakeRequest({
|
|
210
299
|
method: 'lookup',
|
|
211
|
-
dataPath: 'lookupResult.entities',
|
|
212
|
-
event: 'event:directory.lookup',
|
|
213
300
|
resource: '/lookup/orgid/userOrgId/identities',
|
|
214
|
-
params: {
|
|
215
|
-
|
|
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',
|
|
216
341
|
},
|
|
217
|
-
|
|
218
|
-
|
|
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',
|
|
219
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
|
+
],
|
|
220
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');
|
|
221
560
|
});
|
|
222
561
|
});
|
|
223
562
|
|
|
224
563
|
describe('#lookupByEmail', () => {
|
|
225
564
|
it('calls _request correctly', async () => {
|
|
226
565
|
webex.internal.device.orgId = 'userOrgId';
|
|
227
|
-
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
|
+
);
|
|
228
572
|
|
|
229
573
|
const result = await webex.internal.dss.lookupByEmail({
|
|
230
|
-
|
|
574
|
+
email: 'email1',
|
|
231
575
|
});
|
|
576
|
+
|
|
232
577
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
233
578
|
{
|
|
234
579
|
dataPath: 'lookupResult.entities',
|
|
580
|
+
foundPath: 'lookupResult.entitiesFound',
|
|
235
581
|
resource: '/lookup/orgid/userOrgId/emails',
|
|
582
|
+
|
|
236
583
|
params: {
|
|
237
|
-
lookupValues: ['email1'
|
|
584
|
+
lookupValues: ['email1'],
|
|
238
585
|
},
|
|
239
586
|
},
|
|
240
587
|
]);
|
|
@@ -242,31 +589,51 @@ describe('plugin-dss', () => {
|
|
|
242
589
|
});
|
|
243
590
|
|
|
244
591
|
it('works correctly', async () => {
|
|
245
|
-
await
|
|
592
|
+
const {requestId, promise} = await testMakeRequest({
|
|
246
593
|
method: 'lookupByEmail',
|
|
247
|
-
dataPath: 'lookupResult.entities',
|
|
248
|
-
event: 'event:directory.lookup',
|
|
249
594
|
resource: '/lookup/orgid/userOrgId/emails',
|
|
250
|
-
params: {
|
|
251
|
-
|
|
252
|
-
},
|
|
253
|
-
bodyParams: {
|
|
254
|
-
lookupValues: ['email1', 'email2'],
|
|
255
|
-
},
|
|
595
|
+
params: {email: 'email1'},
|
|
596
|
+
bodyParams: {lookupValues: ['email1']},
|
|
256
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;
|
|
257
621
|
});
|
|
258
622
|
});
|
|
259
623
|
|
|
260
624
|
describe('#search', () => {
|
|
261
625
|
it('calls _request correctly', async () => {
|
|
262
626
|
webex.internal.device.orgId = 'userOrgId';
|
|
263
|
-
webex.internal.dss._request = sinon
|
|
627
|
+
webex.internal.dss._request = sinon
|
|
628
|
+
.stub()
|
|
629
|
+
.returns(Promise.resolve({resultArray: 'some return value'}));
|
|
264
630
|
|
|
265
631
|
const result = await webex.internal.dss.search({
|
|
266
632
|
requestedTypes: ['PERSON', 'ROBOT'],
|
|
267
633
|
resultSize: 100,
|
|
268
634
|
queryString: 'query',
|
|
269
635
|
});
|
|
636
|
+
|
|
270
637
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
271
638
|
{
|
|
272
639
|
dataPath: 'directoryEntities',
|
|
@@ -282,10 +649,8 @@ describe('plugin-dss', () => {
|
|
|
282
649
|
});
|
|
283
650
|
|
|
284
651
|
it('works correctly', async () => {
|
|
285
|
-
await
|
|
652
|
+
const {requestId, promise} = await testMakeRequest({
|
|
286
653
|
method: 'search',
|
|
287
|
-
event: 'event:directory.search',
|
|
288
|
-
dataPath: 'directoryEntities',
|
|
289
654
|
resource: '/search/orgid/userOrgId/entities',
|
|
290
655
|
params: {
|
|
291
656
|
requestedTypes: ['PERSON', 'ROBOT'],
|
|
@@ -298,6 +663,13 @@ describe('plugin-dss', () => {
|
|
|
298
663
|
queryString: 'query',
|
|
299
664
|
},
|
|
300
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']);
|
|
301
673
|
});
|
|
302
674
|
});
|
|
303
675
|
|
|
@@ -326,34 +698,228 @@ describe('plugin-dss', () => {
|
|
|
326
698
|
|
|
327
699
|
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
328
700
|
sequence: 1,
|
|
329
|
-
a: {
|
|
330
|
-
b: {
|
|
331
|
-
c: ['data1'],
|
|
332
|
-
},
|
|
333
|
-
},
|
|
701
|
+
a: {b: {c: ['data1']}},
|
|
334
702
|
});
|
|
335
|
-
|
|
336
703
|
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
337
704
|
sequence: 2,
|
|
338
705
|
finished: true,
|
|
339
|
-
a: {
|
|
340
|
-
|
|
341
|
-
|
|
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',
|
|
342
736
|
},
|
|
737
|
+
contentType: 'application/json',
|
|
738
|
+
method: 'POST',
|
|
739
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
343
740
|
},
|
|
344
|
-
|
|
741
|
+
]);
|
|
345
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
|
+
});
|
|
346
754
|
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
347
755
|
sequence: 0,
|
|
348
|
-
a: {
|
|
349
|
-
|
|
350
|
-
|
|
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',
|
|
351
785
|
},
|
|
786
|
+
contentType: 'application/json',
|
|
787
|
+
method: 'POST',
|
|
788
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
352
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'],
|
|
353
808
|
});
|
|
354
809
|
|
|
355
810
|
const result = await promise;
|
|
356
|
-
|
|
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);
|
|
357
923
|
});
|
|
358
924
|
});
|
|
359
925
|
});
|