@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.
@@ -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 = new MockWebex({
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, [`data${sequence}`]);
120
+ set(data, dataPath, results);
121
+
108
122
  return {data};
109
123
  };
110
124
 
111
- const testRequest = async ({method, resource, params, bodyParams, dataPath, event}) => {
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
- mercuryCallbacks[event](createData(requestId, 1, false, dataPath));
134
- mercuryCallbacks[event](createData(requestId, 2, true, dataPath));
135
- mercuryCallbacks[event](createData(requestId, 0, false, dataPath));
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
- const result = await promise;
138
- expect(result).to.deep.equal(['data0', 'data1', 'data2']);
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(Promise.resolve('some return value'));
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 testRequest({
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
- id: 'test id',
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(Promise.resolve('some return value'));
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', 'id2'],
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(Promise.resolve('some return value'));
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
- ids: ['id1', 'id2'],
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', 'id2'],
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 testRequest({
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
- ids: ['id1', 'id2'],
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
- bodyParams: {
218
- lookupValues: ['id1', 'id2'],
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(Promise.resolve('some return value'));
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
- emails: ['email1', 'email2'],
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', 'email2'],
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 testRequest({
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
- emails: ['email1', 'email2'],
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.stub().returns(Promise.resolve('some return value'));
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 testRequest({
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
- b: {
341
- c: ['data2'],
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
- b: {
350
- c: ['data0'],
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
- expect(result).to.deep.equal(['data0', 'data1', 'data2']);
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
  });