@webex/internal-plugin-dss 3.0.0-beta.136 → 3.0.0-beta.137

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,27 +3,30 @@
3
3
  */
4
4
  /* eslint-disable no-underscore-dangle */
5
5
 
6
- import {assert} from '@webex/test-helper-chai';
6
+ import {assert, expect} from '@webex/test-helper-chai';
7
7
  import DSS from '@webex/internal-plugin-dss';
8
+ import {Batcher} from '@webex/webex-core';
8
9
  import MockWebex from '@webex/test-helper-mock-webex';
9
10
  import sinon from 'sinon';
10
- import {expect} from 'chai';
11
11
  import {set} from 'lodash';
12
12
  import uuid from 'uuid';
13
+ import config from '@webex/internal-plugin-dss/src/config';
13
14
 
14
15
  describe('plugin-dss', () => {
15
16
  describe('DSS', () => {
16
17
  let webex;
17
18
  let uuidStub;
18
19
  let mercuryCallbacks;
20
+ let clock;
19
21
 
20
22
  beforeEach(() => {
21
- webex = new MockWebex({
23
+ webex = MockWebex({
22
24
  canAuthorize: false,
23
25
  children: {
24
26
  dss: DSS,
25
27
  },
26
28
  });
29
+ webex.config.dss = config.dss;
27
30
 
28
31
  uuidStub = sinon.stub(uuid, 'v4').returns('randomid');
29
32
 
@@ -40,10 +43,13 @@ describe('plugin-dss', () => {
40
43
  }),
41
44
  off: sinon.spy(),
42
45
  };
46
+
47
+ clock = sinon.useFakeTimers();
43
48
  });
44
49
 
45
50
  afterEach(() => {
46
51
  uuidStub.restore();
52
+ clock.restore();
47
53
  });
48
54
 
49
55
  describe('#register()', () => {
@@ -53,10 +59,12 @@ describe('plugin-dss', () => {
53
59
  assert.callCount(webex.internal.mercury.on, 2);
54
60
 
55
61
  const firstCallArgs = webex.internal.mercury.on.getCall(0).args;
62
+
56
63
  expect(firstCallArgs[0]).to.equal('event:directory.lookup');
57
64
  expect(firstCallArgs[1]).to.be.a('function');
58
65
 
59
66
  const secondCallArgs = webex.internal.mercury.on.getCall(1).args;
67
+
60
68
  expect(secondCallArgs[0]).to.equal('event:directory.search');
61
69
  expect(secondCallArgs[1]).to.be.a('function');
62
70
 
@@ -82,9 +90,11 @@ describe('plugin-dss', () => {
82
90
  assert.callCount(webex.internal.mercury.off, 2);
83
91
 
84
92
  const firstCallArgs = webex.internal.mercury.off.getCall(0).args;
93
+
85
94
  expect(firstCallArgs[0]).to.equal('event:directory.lookup');
86
95
 
87
96
  const secondCallArgs = webex.internal.mercury.off.getCall(1).args;
97
+
88
98
  expect(secondCallArgs[0]).to.equal('event:directory.search');
89
99
 
90
100
  assert.equal(webex.internal.dss.registered, false);
@@ -92,24 +102,32 @@ describe('plugin-dss', () => {
92
102
 
93
103
  it('handles unregister when it is not registered', async () => {
94
104
  const result = await webex.internal.dss.unregister();
105
+
95
106
  await expect(result).equal(undefined);
96
107
  assert.equal(webex.internal.dss.registered, false);
97
108
  });
98
109
  });
99
110
 
100
- const createData = (requestId, sequence, finished, dataPath) => {
111
+ const createData = (requestId, sequence, finished, dataPath, results) => {
101
112
  const data = {
102
113
  requestId,
103
114
  sequence,
104
115
  };
116
+
105
117
  if (finished) {
106
118
  (data as any).finished = finished;
107
119
  }
108
- set(data, dataPath, [`data${sequence}`]);
120
+ set(data, dataPath, results);
121
+
109
122
  return {data};
110
123
  };
111
124
 
112
- const testRequest = async ({method, resource, params, bodyParams, dataPath, event}) => {
125
+ const testMakeRequest = async ({
126
+ method,
127
+ resource,
128
+ params,
129
+ bodyParams
130
+ }) => {
113
131
  webex.request = sinon.stub();
114
132
 
115
133
  await webex.internal.dss.register();
@@ -131,23 +149,59 @@ describe('plugin-dss', () => {
131
149
  },
132
150
  ]);
133
151
 
134
- mercuryCallbacks[event](createData(requestId, 1, false, dataPath));
135
- mercuryCallbacks[event](createData(requestId, 2, true, dataPath));
136
- 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));
137
165
 
138
- const result = await promise;
139
- 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};
140
187
  };
141
188
 
142
189
  describe('#lookupDetail', () => {
143
190
  it('calls _request correctly', async () => {
144
191
  webex.internal.device.orgId = 'userOrgId';
145
- webex.internal.dss._request = sinon.stub().returns(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
+ );
146
198
 
147
199
  const result = await webex.internal.dss.lookupDetail({id: 'test id'});
200
+
148
201
  expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
149
202
  {
150
203
  dataPath: 'lookupResult.entities',
204
+ foundPath: 'lookupResult.entitiesFound',
151
205
  resource: '/lookup/orgid/userOrgId/identity/test id/detail',
152
206
  },
153
207
  ]);
@@ -155,31 +209,57 @@ describe('plugin-dss', () => {
155
209
  });
156
210
 
157
211
  it('works correctly', async () => {
158
- await testRequest({
212
+ const {requestId, promise} = await testMakeRequest({
159
213
  method: 'lookupDetail',
160
- dataPath: 'lookupResult.entities',
161
- event: 'event:directory.lookup',
162
214
  resource: '/lookup/orgid/userOrgId/identity/test id/detail',
163
- params: {
164
- id: 'test id',
165
- },
215
+ params: {id: 'test id'},
216
+ bodyParams: {},
217
+ });
218
+
219
+ mercuryCallbacks['event:directory.lookup'](
220
+ createData(requestId, 0, true, 'lookupResult', {entities: ['data0'], entitiesFound: ['test id']})
221
+ );
222
+ const result = await promise;
223
+
224
+ expect(result).to.deep.equal('data0');
225
+ });
226
+
227
+ it('fails correctly if lookup fails', async () => {
228
+ const {requestId, promise} = await testMakeRequest({
229
+ method: 'lookupDetail',
230
+ resource: '/lookup/orgid/userOrgId/identity/test id/detail',
231
+ params: {id: 'test id'},
166
232
  bodyParams: {},
167
233
  });
234
+
235
+ mercuryCallbacks['event:directory.lookup'](
236
+ createData(requestId, 0, true, 'lookupResult', {entitiesNotFound: ['test id']})
237
+ );
238
+ const result = await promise;
239
+
240
+ expect(result).to.be.null;
168
241
  });
169
242
  });
170
243
 
171
244
  describe('#lookup', () => {
172
245
  it('calls _request correctly', async () => {
173
246
  webex.internal.device.orgId = 'userOrgId';
174
- webex.internal.dss._request = sinon.stub().returns(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});
175
255
 
176
- const result = await webex.internal.dss.lookup({ids: ['id1', 'id2']});
177
256
  expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
178
257
  {
179
258
  dataPath: 'lookupResult.entities',
259
+ foundPath: 'lookupResult.entitiesFound',
180
260
  resource: '/lookup/orgid/userOrgId/identities',
181
261
  params: {
182
- lookupValues: ['id1', 'id2'],
262
+ lookupValues: ['id1'],
183
263
  },
184
264
  },
185
265
  ]);
@@ -188,18 +268,26 @@ describe('plugin-dss', () => {
188
268
 
189
269
  it('calls _request correctly with entityProviderType', async () => {
190
270
  webex.internal.device.orgId = 'userOrgId';
191
- webex.internal.dss._request = sinon.stub().returns(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
+ );
192
277
 
193
278
  const result = await webex.internal.dss.lookup({
194
- ids: ['id1', 'id2'],
279
+ id: 'id1',
195
280
  entityProviderType: 'CI_USER',
281
+ shouldBatch: false,
196
282
  });
283
+
197
284
  expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
198
285
  {
199
286
  dataPath: 'lookupResult.entities',
287
+ foundPath: 'lookupResult.entitiesFound',
200
288
  resource: '/lookup/orgid/userOrgId/entityprovidertype/CI_USER',
201
289
  params: {
202
- lookupValues: ['id1', 'id2'],
290
+ lookupValues: ['id1'],
203
291
  },
204
292
  },
205
293
  ]);
@@ -207,35 +295,293 @@ describe('plugin-dss', () => {
207
295
  });
208
296
 
209
297
  it('works correctly', async () => {
210
- await testRequest({
298
+ const {requestId, promise} = await testMakeRequest({
211
299
  method: 'lookup',
212
- dataPath: 'lookupResult.entities',
213
- event: 'event:directory.lookup',
214
300
  resource: '/lookup/orgid/userOrgId/identities',
215
- params: {
216
- 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',
217
341
  },
218
- bodyParams: {
219
- 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',
220
361
  },
362
+ ]);
363
+ expect(result).to.equal('some return value');
364
+ });
365
+
366
+ it('Single batched lookup is made after 50 ms and works', async () => {
367
+ const {promises} = await testMakeBatchedRequests({
368
+ requests: [
369
+ {
370
+ id: 'randomid1',
371
+ resource: '/lookup/orgid/userOrgId/identities',
372
+ bodyParams: {lookupValues: ['id1']},
373
+ }
374
+ ],
375
+ calls: [
376
+ {
377
+ method: 'lookup',
378
+ params: {id: 'id1', shouldBatch: true},
379
+ }
380
+ ],
221
381
  });
382
+
383
+ mercuryCallbacks['event:directory.lookup'](
384
+ createData('randomid1', 0, true, 'lookupResult', {entities: ['data0'], entitiesFound: ['id1']})
385
+ );
386
+ const result = await promises[0];
387
+
388
+ expect(result).to.deep.equal('data0');
389
+ });
390
+
391
+ it('Single batched lookup fails correctly if lookup fails', async () => {
392
+ const {promises} = await testMakeBatchedRequests({
393
+ requests: [
394
+ {
395
+ id: 'randomid1',
396
+ resource: '/lookup/orgid/userOrgId/identities',
397
+ bodyParams: {lookupValues: ['id1']},
398
+ }
399
+ ],
400
+ calls: [
401
+ {
402
+ method: 'lookup',
403
+ params: {id: 'id1', shouldBatch: true},
404
+ }
405
+ ],
406
+ });
407
+
408
+ mercuryCallbacks['event:directory.lookup'](
409
+ createData('randomid1', 0, true, 'lookupResult', {entitiesNotFound: ['id1']})
410
+ );
411
+
412
+ const result = await promises[0];
413
+
414
+ expect(result).to.be.null;
415
+ });
416
+
417
+ it('Batch of 2 lookups is made after 50 ms and works', async () => {
418
+ const {promises} = await testMakeBatchedRequests({
419
+ requests: [
420
+ {
421
+ id: 'randomid1',
422
+ resource: '/lookup/orgid/userOrgId/identities',
423
+ bodyParams: {lookupValues: ['id1', 'id2']},
424
+ }
425
+ ],
426
+ calls: [
427
+ {
428
+ method: 'lookup',
429
+ params: {id: 'id1', shouldBatch: true},
430
+ },
431
+ {
432
+ method: 'lookup',
433
+ params: {id: 'id2', shouldBatch: true},
434
+ },
435
+ ],
436
+ });
437
+
438
+ mercuryCallbacks['event:directory.lookup'](
439
+ createData('randomid1', 0, true, 'lookupResult', {entities: ['data1', 'data2'], entitiesFound: ['id1', 'id2']})
440
+ );
441
+ const result1 = await promises[0];
442
+
443
+ expect(result1).to.equal('data1');
444
+ const result2 = await promises[1];
445
+
446
+ expect(result2).to.equal('data2');
447
+ });
448
+
449
+ it('Batch of 2 lookups is made after 50 ms and one fails correctly', async () => {
450
+ const {promises} = await testMakeBatchedRequests({
451
+ requests: [
452
+ {
453
+ id: 'randomid1',
454
+ resource: '/lookup/orgid/userOrgId/identities',
455
+ bodyParams: {lookupValues: ['id1', 'id2']},
456
+ }
457
+ ],
458
+ calls: [
459
+ {
460
+ method: 'lookup',
461
+ params: {id: 'id1', shouldBatch: true},
462
+ },
463
+ {
464
+ method: 'lookup',
465
+ params: {id: 'id2', shouldBatch: true},
466
+ },
467
+ ],
468
+ });
469
+
470
+ mercuryCallbacks['event:directory.lookup'](
471
+ createData('randomid1', 0, true, 'lookupResult', {entities: ['data2'], entitiesFound: ['id2'], entitiesNotFound: ['id1']})
472
+ );
473
+ const result1 = await promises[0];
474
+
475
+ expect(result1).to.be.null;
476
+
477
+ const result2 = await promises[1];
478
+
479
+ expect(result2).to.equal('data2');
480
+ });
481
+
482
+ it('Two unrelated lookups are made after 50 ms and work', async () => {
483
+ const {promises} = await testMakeBatchedRequests({
484
+ requests: [
485
+ {
486
+ id: 'randomid1',
487
+ resource: '/lookup/orgid/userOrgId/entityprovidertype/CI_USER',
488
+ bodyParams: {lookupValues: ['id1']},
489
+ },
490
+ {
491
+ id: 'randomid2',
492
+ resource: '/lookup/orgid/userOrgId/identities',
493
+ bodyParams: {lookupValues: ['id2']},
494
+ }
495
+ ],
496
+ calls: [
497
+ {
498
+ method: 'lookup',
499
+ params: {id: 'id1', entityProviderType: 'CI_USER', shouldBatch: true},
500
+ },
501
+ {
502
+ method: 'lookup',
503
+ params: {id: 'id2', shouldBatch: true},
504
+ },
505
+ ],
506
+ });
507
+
508
+ mercuryCallbacks['event:directory.lookup'](
509
+ createData('randomid1', 0, true, 'lookupResult', {entities: ['data1'], entitiesFound: ['id1']})
510
+ );
511
+ mercuryCallbacks['event:directory.lookup'](
512
+ createData('randomid2', 0, true, 'lookupResult', {entities: ['data2'], entitiesFound: ['id2']})
513
+ );
514
+ const result1 = await promises[0];
515
+
516
+ expect(result1).to.equal('data1');
517
+ const result2 = await promises[1];
518
+
519
+ expect(result2).to.equal('data2');
520
+ });
521
+
522
+ it('Two unrelated lookups are made after 50 ms and one fails correctly', async () => {
523
+ const {promises} = await testMakeBatchedRequests({
524
+ requests: [
525
+ {
526
+ id: 'randomid1',
527
+ resource: '/lookup/orgid/userOrgId/entityprovidertype/CI_USER',
528
+ bodyParams: {lookupValues: ['id1']},
529
+ },
530
+ {
531
+ id: 'randomid2',
532
+ resource: '/lookup/orgid/userOrgId/identities',
533
+ bodyParams: {lookupValues: ['id2']},
534
+ }
535
+ ],
536
+ calls: [
537
+ {
538
+ method: 'lookup',
539
+ params: {id: 'id1', entityProviderType: 'CI_USER', shouldBatch: true},
540
+ },
541
+ {
542
+ method: 'lookup',
543
+ params: {id: 'id2', shouldBatch: true},
544
+ },
545
+ ],
546
+ });
547
+
548
+ mercuryCallbacks['event:directory.lookup'](
549
+ createData('randomid1', 0, true, 'lookupResult', {entitiesNotFound: ['id1']})
550
+ );
551
+ mercuryCallbacks['event:directory.lookup'](
552
+ createData('randomid2', 0, true, 'lookupResult', {entities: ['data2'], entitiesFound: ['id2']})
553
+ );
554
+ const result1 = await promises[0];
555
+
556
+ expect(result1).to.be.null;
557
+ const result2 = await promises[1];
558
+
559
+ expect(result2).to.equal('data2');
222
560
  });
223
561
  });
224
562
 
225
563
  describe('#lookupByEmail', () => {
226
564
  it('calls _request correctly', async () => {
227
565
  webex.internal.device.orgId = 'userOrgId';
228
- webex.internal.dss._request = sinon.stub().returns(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
+ );
229
572
 
230
573
  const result = await webex.internal.dss.lookupByEmail({
231
- emails: ['email1', 'email2'],
574
+ email: 'email1',
232
575
  });
576
+
233
577
  expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
234
578
  {
235
579
  dataPath: 'lookupResult.entities',
580
+ foundPath: 'lookupResult.entitiesFound',
236
581
  resource: '/lookup/orgid/userOrgId/emails',
582
+
237
583
  params: {
238
- lookupValues: ['email1', 'email2'],
584
+ lookupValues: ['email1'],
239
585
  },
240
586
  },
241
587
  ]);
@@ -243,31 +589,51 @@ describe('plugin-dss', () => {
243
589
  });
244
590
 
245
591
  it('works correctly', async () => {
246
- await testRequest({
592
+ const {requestId, promise} = await testMakeRequest({
247
593
  method: 'lookupByEmail',
248
- dataPath: 'lookupResult.entities',
249
- event: 'event:directory.lookup',
250
594
  resource: '/lookup/orgid/userOrgId/emails',
251
- params: {
252
- emails: ['email1', 'email2'],
253
- },
254
- bodyParams: {
255
- lookupValues: ['email1', 'email2'],
256
- },
595
+ params: {email: 'email1'},
596
+ bodyParams: {lookupValues: ['email1']},
257
597
  });
598
+
599
+ mercuryCallbacks['event:directory.lookup'](
600
+ createData(requestId, 0, true, 'lookupResult', {entities: ['data0'], entitiesFound: ['email1']})
601
+ );
602
+ const result = await promise;
603
+
604
+ expect(result).to.deep.equal('data0');
605
+ });
606
+
607
+ it('fails correctly if lookup fails', async () => {
608
+ const {requestId, promise} = await testMakeRequest({
609
+ method: 'lookupByEmail',
610
+ resource: '/lookup/orgid/userOrgId/emails',
611
+ params: {email: 'email1'},
612
+ bodyParams: {lookupValues: ['email1']},
613
+ });
614
+
615
+ mercuryCallbacks['event:directory.lookup'](
616
+ createData(requestId, 0, true, 'lookupResult', {}) // entitiesNotFound isn't returned for email
617
+ );
618
+ const result = await promise;
619
+
620
+ expect(result).to.be.null;
258
621
  });
259
622
  });
260
623
 
261
624
  describe('#search', () => {
262
625
  it('calls _request correctly', async () => {
263
626
  webex.internal.device.orgId = 'userOrgId';
264
- webex.internal.dss._request = sinon.stub().returns(Promise.resolve('some return value'));
627
+ webex.internal.dss._request = sinon
628
+ .stub()
629
+ .returns(Promise.resolve({resultArray: 'some return value'}));
265
630
 
266
631
  const result = await webex.internal.dss.search({
267
632
  requestedTypes: ['PERSON', 'ROBOT'],
268
633
  resultSize: 100,
269
634
  queryString: 'query',
270
635
  });
636
+
271
637
  expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
272
638
  {
273
639
  dataPath: 'directoryEntities',
@@ -283,10 +649,8 @@ describe('plugin-dss', () => {
283
649
  });
284
650
 
285
651
  it('works correctly', async () => {
286
- await testRequest({
652
+ const {requestId, promise} = await testMakeRequest({
287
653
  method: 'search',
288
- event: 'event:directory.search',
289
- dataPath: 'directoryEntities',
290
654
  resource: '/search/orgid/userOrgId/entities',
291
655
  params: {
292
656
  requestedTypes: ['PERSON', 'ROBOT'],
@@ -299,6 +663,13 @@ describe('plugin-dss', () => {
299
663
  queryString: 'query',
300
664
  },
301
665
  });
666
+
667
+ mercuryCallbacks['event:directory.search'](createData(requestId, 1, false, 'directoryEntities', ['data1']));
668
+ mercuryCallbacks['event:directory.search'](createData(requestId, 2, true, 'directoryEntities', ['data2']));
669
+ mercuryCallbacks['event:directory.search'](createData(requestId, 0, false, 'directoryEntities', ['data0']));
670
+ const result = await promise;
671
+
672
+ expect(result).to.deep.equal(['data0', 'data1', 'data2']);
302
673
  });
303
674
  });
304
675
 
@@ -327,34 +698,228 @@ describe('plugin-dss', () => {
327
698
 
328
699
  webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
329
700
  sequence: 1,
330
- a: {
331
- b: {
332
- c: ['data1'],
333
- },
334
- },
701
+ a: {b: {c: ['data1']}},
335
702
  });
336
-
337
703
  webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
338
704
  sequence: 2,
339
705
  finished: true,
340
- a: {
341
- b: {
342
- 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',
343
736
  },
737
+ contentType: 'application/json',
738
+ method: 'POST',
739
+ resource: '/search/orgid/userOrgId/entities',
344
740
  },
345
- });
741
+ ]);
346
742
 
743
+ webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
744
+ sequence: 1,
745
+ a: {b: {c: ['data1']}},
746
+ someFoundPath: ['id1'],
747
+ });
748
+ webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
749
+ sequence: 2,
750
+ finished: true,
751
+ a: {b: {c: ['data2']}},
752
+ someFoundPath: ['id2'],
753
+ });
347
754
  webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
348
755
  sequence: 0,
349
- a: {
350
- b: {
351
- 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',
352
785
  },
786
+ contentType: 'application/json',
787
+ method: 'POST',
788
+ resource: '/search/orgid/userOrgId/entities',
353
789
  },
790
+ ]);
791
+
792
+ webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
793
+ sequence: 1,
794
+ a: {b: {c: ['data1']}},
795
+ someFoundPath: ['id1'],
796
+ });
797
+ webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
798
+ sequence: 2,
799
+ finished: true,
800
+ a: {b: {c: ['data2']}},
801
+ someFoundPath: ['id2'],
802
+ someNotFoundPath: ['id3'],
803
+ });
804
+ webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
805
+ sequence: 0,
806
+ a: {b: {c: ['data0']}},
807
+ someFoundPath: ['id0'],
354
808
  });
355
809
 
356
810
  const result = await promise;
357
- 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);
358
923
  });
359
924
  });
360
925
  });