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