@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.
@@ -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
 
@@ -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, [`data${sequence}`]);
120
+ set(data, dataPath, results);
121
+
107
122
  return {data};
108
123
  };
109
124
 
110
- const testRequest = async ({method, resource, params, bodyParams, dataPath, event}) => {
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
- mercuryCallbacks[event](createData(requestId, 1, false, dataPath));
133
- mercuryCallbacks[event](createData(requestId, 2, true, dataPath));
134
- 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));
135
165
 
136
- const result = await promise;
137
- 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};
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(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
+ );
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 testRequest({
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
- id: 'test id',
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(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});
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', 'id2'],
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(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
+ );
190
277
 
191
278
  const result = await webex.internal.dss.lookup({
192
- ids: ['id1', 'id2'],
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', 'id2'],
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 testRequest({
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
- 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',
215
341
  },
216
- bodyParams: {
217
- 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',
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(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
+ );
227
572
 
228
573
  const result = await webex.internal.dss.lookupByEmail({
229
- emails: ['email1', 'email2'],
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', 'email2'],
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 testRequest({
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
- emails: ['email1', 'email2'],
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.stub().returns(Promise.resolve('some return value'));
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 testRequest({
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
- b: {
340
- 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',
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
- b: {
349
- 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',
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
- 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);
356
923
  });
357
924
  });
358
925
  });