@webex/internal-plugin-dss 3.0.0-bnr.5 → 3.0.0-next.10
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/.eslintrc.js +6 -0
- package/babel.config.js +3 -0
- package/dist/config.js +35 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.js +14 -17
- package/dist/constants.js.map +1 -1
- package/dist/dss-batcher.js +138 -0
- package/dist/dss-batcher.js.map +1 -0
- package/dist/dss-errors.js +49 -0
- package/dist/dss-errors.js.map +1 -0
- package/dist/dss.js +197 -42
- package/dist/dss.js.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/types.js +6 -9
- package/dist/types.js.map +1 -1
- package/jest.config.js +3 -0
- package/package.json +27 -8
- package/process +1 -0
- package/src/config.ts +31 -0
- package/src/constants.ts +5 -0
- package/src/dss-batcher.ts +129 -0
- package/src/dss-errors.ts +36 -0
- package/src/dss.ts +187 -32
- package/src/index.ts +2 -1
- package/src/types.ts +28 -3
- package/test/unit/spec/dss-batcher.ts +139 -0
- package/test/unit/spec/dss.ts +996 -63
- package/dist/internal-plugin-dss.d.ts +0 -4
- package/dist/tsdoc-metadata.json +0 -11
- package/dist/types/constants.d.ts +0 -14
- package/dist/types/dss.d.ts +0 -3
- package/dist/types/index.d.ts +0 -1
- package/dist/types/types.d.ts +0 -28
package/test/unit/spec/dss.ts
CHANGED
|
@@ -1,28 +1,35 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Copyright (c) 2015-2022 Cisco Systems, Inc. See LICENSE file.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
import
|
|
4
|
+
/* eslint-disable no-underscore-dangle */
|
|
5
|
+
import chai from 'chai';
|
|
6
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
7
|
+
import {assert, expect} from '@webex/test-helper-chai';
|
|
6
8
|
import DSS from '@webex/internal-plugin-dss';
|
|
9
|
+
import {Batcher} from '@webex/webex-core';
|
|
7
10
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
8
11
|
import sinon from 'sinon';
|
|
9
|
-
import {expect} from 'chai';
|
|
10
12
|
import {set} from 'lodash';
|
|
11
13
|
import uuid from 'uuid';
|
|
14
|
+
import config from '@webex/internal-plugin-dss/src/config';
|
|
12
15
|
|
|
16
|
+
chai.use(chaiAsPromised);
|
|
13
17
|
describe('plugin-dss', () => {
|
|
14
18
|
describe('DSS', () => {
|
|
19
|
+
const originalBatcherRequest = Batcher.prototype.request;
|
|
15
20
|
let webex;
|
|
16
21
|
let uuidStub;
|
|
17
22
|
let mercuryCallbacks;
|
|
23
|
+
let clock;
|
|
18
24
|
|
|
19
25
|
beforeEach(() => {
|
|
20
|
-
webex =
|
|
26
|
+
webex = MockWebex({
|
|
21
27
|
canAuthorize: false,
|
|
22
28
|
children: {
|
|
23
29
|
dss: DSS,
|
|
24
30
|
},
|
|
25
31
|
});
|
|
32
|
+
webex.config.dss = config.dss;
|
|
26
33
|
|
|
27
34
|
uuidStub = sinon.stub(uuid, 'v4').returns('randomid');
|
|
28
35
|
|
|
@@ -39,10 +46,14 @@ describe('plugin-dss', () => {
|
|
|
39
46
|
}),
|
|
40
47
|
off: sinon.spy(),
|
|
41
48
|
};
|
|
49
|
+
|
|
50
|
+
clock = sinon.useFakeTimers();
|
|
42
51
|
});
|
|
43
52
|
|
|
44
53
|
afterEach(() => {
|
|
45
54
|
uuidStub.restore();
|
|
55
|
+
clock.restore();
|
|
56
|
+
Batcher.prototype.request = originalBatcherRequest;
|
|
46
57
|
});
|
|
47
58
|
|
|
48
59
|
describe('#register()', () => {
|
|
@@ -52,10 +63,12 @@ describe('plugin-dss', () => {
|
|
|
52
63
|
assert.callCount(webex.internal.mercury.on, 2);
|
|
53
64
|
|
|
54
65
|
const firstCallArgs = webex.internal.mercury.on.getCall(0).args;
|
|
66
|
+
|
|
55
67
|
expect(firstCallArgs[0]).to.equal('event:directory.lookup');
|
|
56
68
|
expect(firstCallArgs[1]).to.be.a('function');
|
|
57
69
|
|
|
58
70
|
const secondCallArgs = webex.internal.mercury.on.getCall(1).args;
|
|
71
|
+
|
|
59
72
|
expect(secondCallArgs[0]).to.equal('event:directory.search');
|
|
60
73
|
expect(secondCallArgs[1]).to.be.a('function');
|
|
61
74
|
|
|
@@ -81,9 +94,11 @@ describe('plugin-dss', () => {
|
|
|
81
94
|
assert.callCount(webex.internal.mercury.off, 2);
|
|
82
95
|
|
|
83
96
|
const firstCallArgs = webex.internal.mercury.off.getCall(0).args;
|
|
97
|
+
|
|
84
98
|
expect(firstCallArgs[0]).to.equal('event:directory.lookup');
|
|
85
99
|
|
|
86
100
|
const secondCallArgs = webex.internal.mercury.off.getCall(1).args;
|
|
101
|
+
|
|
87
102
|
expect(secondCallArgs[0]).to.equal('event:directory.search');
|
|
88
103
|
|
|
89
104
|
assert.equal(webex.internal.dss.registered, false);
|
|
@@ -91,24 +106,27 @@ describe('plugin-dss', () => {
|
|
|
91
106
|
|
|
92
107
|
it('handles unregister when it is not registered', async () => {
|
|
93
108
|
const result = await webex.internal.dss.unregister();
|
|
109
|
+
|
|
94
110
|
await expect(result).equal(undefined);
|
|
95
111
|
assert.equal(webex.internal.dss.registered, false);
|
|
96
112
|
});
|
|
97
113
|
});
|
|
98
114
|
|
|
99
|
-
const createData = (requestId, sequence, finished, dataPath) => {
|
|
115
|
+
const createData = (requestId, sequence, finished, dataPath, results) => {
|
|
100
116
|
const data = {
|
|
101
117
|
requestId,
|
|
102
118
|
sequence,
|
|
103
119
|
};
|
|
120
|
+
|
|
104
121
|
if (finished) {
|
|
105
122
|
(data as any).finished = finished;
|
|
106
123
|
}
|
|
107
|
-
set(data, dataPath,
|
|
124
|
+
set(data, dataPath, results);
|
|
125
|
+
|
|
108
126
|
return {data};
|
|
109
127
|
};
|
|
110
128
|
|
|
111
|
-
const
|
|
129
|
+
const testMakeRequest = async ({method, resource, params, bodyParams}) => {
|
|
112
130
|
webex.request = sinon.stub();
|
|
113
131
|
|
|
114
132
|
await webex.internal.dss.register();
|
|
@@ -130,23 +148,58 @@ describe('plugin-dss', () => {
|
|
|
130
148
|
},
|
|
131
149
|
]);
|
|
132
150
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
151
|
+
return {requestId, promise};
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const testMakeBatchedRequests = async ({requests, calls}) => {
|
|
155
|
+
requests.forEach((request, index) => {
|
|
156
|
+
uuidStub.onCall(index).returns(request.id);
|
|
157
|
+
});
|
|
158
|
+
webex.request = sinon.stub();
|
|
159
|
+
|
|
160
|
+
await webex.internal.dss.register();
|
|
161
|
+
|
|
162
|
+
const promises = calls.map((call) => webex.internal.dss[call.method](call.params));
|
|
163
|
+
|
|
164
|
+
await clock.tickAsync(49);
|
|
165
|
+
expect(webex.request.notCalled).to.be.true;
|
|
166
|
+
await clock.tickAsync(1);
|
|
167
|
+
expect(webex.request.called).to.be.true;
|
|
168
|
+
|
|
169
|
+
requests.forEach((request, index) => {
|
|
170
|
+
expect(webex.request.getCall(index).args).to.deep.equal([
|
|
171
|
+
{
|
|
172
|
+
service: 'directorySearch',
|
|
173
|
+
body: {
|
|
174
|
+
requestId: request.id,
|
|
175
|
+
...request.bodyParams,
|
|
176
|
+
},
|
|
177
|
+
contentType: 'application/json',
|
|
178
|
+
method: 'POST',
|
|
179
|
+
resource: request.resource,
|
|
180
|
+
},
|
|
181
|
+
]);
|
|
182
|
+
});
|
|
136
183
|
|
|
137
|
-
|
|
138
|
-
expect(result).to.deep.equal(['data0', 'data1', 'data2']);
|
|
184
|
+
return {promises};
|
|
139
185
|
};
|
|
140
186
|
|
|
141
187
|
describe('#lookupDetail', () => {
|
|
142
188
|
it('calls _request correctly', async () => {
|
|
143
189
|
webex.internal.device.orgId = 'userOrgId';
|
|
144
|
-
webex.internal.dss._request = sinon.stub().returns(
|
|
190
|
+
webex.internal.dss._request = sinon.stub().returns(
|
|
191
|
+
Promise.resolve({
|
|
192
|
+
resultArray: ['some return value'],
|
|
193
|
+
foundArray: ['test id'],
|
|
194
|
+
})
|
|
195
|
+
);
|
|
145
196
|
|
|
146
197
|
const result = await webex.internal.dss.lookupDetail({id: 'test id'});
|
|
198
|
+
|
|
147
199
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
148
200
|
{
|
|
149
201
|
dataPath: 'lookupResult.entities',
|
|
202
|
+
foundPath: 'lookupResult.entitiesFound',
|
|
150
203
|
resource: '/lookup/orgid/userOrgId/identity/test id/detail',
|
|
151
204
|
},
|
|
152
205
|
]);
|
|
@@ -154,31 +207,97 @@ describe('plugin-dss', () => {
|
|
|
154
207
|
});
|
|
155
208
|
|
|
156
209
|
it('works correctly', async () => {
|
|
157
|
-
await
|
|
210
|
+
const {requestId, promise} = await testMakeRequest({
|
|
158
211
|
method: 'lookupDetail',
|
|
159
|
-
dataPath: 'lookupResult.entities',
|
|
160
|
-
event: 'event:directory.lookup',
|
|
161
212
|
resource: '/lookup/orgid/userOrgId/identity/test id/detail',
|
|
162
|
-
params: {
|
|
163
|
-
|
|
164
|
-
|
|
213
|
+
params: {id: 'test id'},
|
|
214
|
+
bodyParams: {},
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
218
|
+
createData(requestId, 0, true, 'lookupResult', {
|
|
219
|
+
entities: ['data0'],
|
|
220
|
+
entitiesFound: ['test id'],
|
|
221
|
+
})
|
|
222
|
+
);
|
|
223
|
+
const result = await promise;
|
|
224
|
+
|
|
225
|
+
expect(result).to.deep.equal('data0');
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('fails correctly if lookup fails', async () => {
|
|
229
|
+
const {requestId, promise} = await testMakeRequest({
|
|
230
|
+
method: 'lookupDetail',
|
|
231
|
+
resource: '/lookup/orgid/userOrgId/identity/test id/detail',
|
|
232
|
+
params: {id: 'test id'},
|
|
165
233
|
bodyParams: {},
|
|
166
234
|
});
|
|
235
|
+
|
|
236
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
237
|
+
createData(requestId, 0, true, 'lookupResult', {entitiesNotFound: ['test id']})
|
|
238
|
+
);
|
|
239
|
+
const result = await promise;
|
|
240
|
+
|
|
241
|
+
expect(result).to.be.null;
|
|
242
|
+
});
|
|
243
|
+
it('fails with default timeout when mercury does not respond', async () => {
|
|
244
|
+
const {promise} = await testMakeRequest({
|
|
245
|
+
method: 'lookupDetail',
|
|
246
|
+
resource: '/lookup/orgid/userOrgId/identity/test id/detail',
|
|
247
|
+
params: {id: 'test id'},
|
|
248
|
+
bodyParams: {},
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
promise.catch(() => {}); // to prevent the test from failing due to unhandled promise rejection
|
|
252
|
+
|
|
253
|
+
await clock.tickAsync(6000);
|
|
254
|
+
|
|
255
|
+
return assert.isRejected(
|
|
256
|
+
promise,
|
|
257
|
+
'The DSS did not respond within 6000 ms.' +
|
|
258
|
+
'\n Request Id: randomid' +
|
|
259
|
+
'\n Resource: /lookup/orgid/userOrgId/identity/test id/detail' +
|
|
260
|
+
'\n Params: undefined'
|
|
261
|
+
);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('does not fail with timeout when mercury response in time', async () => {
|
|
265
|
+
const {requestId, promise} = await testMakeRequest({
|
|
266
|
+
method: 'lookupDetail',
|
|
267
|
+
resource: '/lookup/orgid/userOrgId/identity/test id/detail',
|
|
268
|
+
params: {id: 'test id'},
|
|
269
|
+
bodyParams: {},
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
await clock.tickAsync(499);
|
|
273
|
+
|
|
274
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
275
|
+
createData(requestId, 0, true, 'lookupResult', {entitiesNotFound: ['test id']})
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
return assert.isFulfilled(promise);
|
|
167
279
|
});
|
|
168
280
|
});
|
|
169
281
|
|
|
170
282
|
describe('#lookup', () => {
|
|
171
283
|
it('calls _request correctly', async () => {
|
|
172
284
|
webex.internal.device.orgId = 'userOrgId';
|
|
173
|
-
webex.internal.dss._request = sinon.stub().returns(
|
|
285
|
+
webex.internal.dss._request = sinon.stub().returns(
|
|
286
|
+
Promise.resolve({
|
|
287
|
+
resultArray: ['some return value'],
|
|
288
|
+
foundArray: ['id1'],
|
|
289
|
+
})
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const result = await webex.internal.dss.lookup({id: 'id1', shouldBatch: false});
|
|
174
293
|
|
|
175
|
-
const result = await webex.internal.dss.lookup({ids: ['id1', 'id2']});
|
|
176
294
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
177
295
|
{
|
|
178
296
|
dataPath: 'lookupResult.entities',
|
|
297
|
+
foundPath: 'lookupResult.entitiesFound',
|
|
179
298
|
resource: '/lookup/orgid/userOrgId/identities',
|
|
180
299
|
params: {
|
|
181
|
-
lookupValues: ['id1'
|
|
300
|
+
lookupValues: ['id1'],
|
|
182
301
|
},
|
|
183
302
|
},
|
|
184
303
|
]);
|
|
@@ -187,18 +306,26 @@ describe('plugin-dss', () => {
|
|
|
187
306
|
|
|
188
307
|
it('calls _request correctly with entityProviderType', async () => {
|
|
189
308
|
webex.internal.device.orgId = 'userOrgId';
|
|
190
|
-
webex.internal.dss._request = sinon.stub().returns(
|
|
309
|
+
webex.internal.dss._request = sinon.stub().returns(
|
|
310
|
+
Promise.resolve({
|
|
311
|
+
resultArray: ['some return value'],
|
|
312
|
+
foundArray: ['id1'],
|
|
313
|
+
})
|
|
314
|
+
);
|
|
191
315
|
|
|
192
316
|
const result = await webex.internal.dss.lookup({
|
|
193
|
-
|
|
317
|
+
id: 'id1',
|
|
194
318
|
entityProviderType: 'CI_USER',
|
|
319
|
+
shouldBatch: false,
|
|
195
320
|
});
|
|
321
|
+
|
|
196
322
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
197
323
|
{
|
|
198
324
|
dataPath: 'lookupResult.entities',
|
|
325
|
+
foundPath: 'lookupResult.entitiesFound',
|
|
199
326
|
resource: '/lookup/orgid/userOrgId/entityprovidertype/CI_USER',
|
|
200
327
|
params: {
|
|
201
|
-
lookupValues: ['id1'
|
|
328
|
+
lookupValues: ['id1'],
|
|
202
329
|
},
|
|
203
330
|
},
|
|
204
331
|
]);
|
|
@@ -206,35 +333,350 @@ describe('plugin-dss', () => {
|
|
|
206
333
|
});
|
|
207
334
|
|
|
208
335
|
it('works correctly', async () => {
|
|
209
|
-
await
|
|
336
|
+
const {requestId, promise} = await testMakeRequest({
|
|
210
337
|
method: 'lookup',
|
|
211
|
-
dataPath: 'lookupResult.entities',
|
|
212
|
-
event: 'event:directory.lookup',
|
|
213
338
|
resource: '/lookup/orgid/userOrgId/identities',
|
|
214
|
-
params: {
|
|
215
|
-
|
|
339
|
+
params: {id: 'id1', shouldBatch: false},
|
|
340
|
+
bodyParams: {lookupValues: ['id1']},
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
344
|
+
createData(requestId, 0, true, 'lookupResult', {
|
|
345
|
+
entities: ['data0'],
|
|
346
|
+
entitiesFound: ['id1'],
|
|
347
|
+
})
|
|
348
|
+
);
|
|
349
|
+
const result = await promise;
|
|
350
|
+
|
|
351
|
+
expect(result).to.deep.equal('data0');
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
it('fails correctly if lookup fails', async () => {
|
|
355
|
+
const {requestId, promise} = await testMakeRequest({
|
|
356
|
+
method: 'lookup',
|
|
357
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
358
|
+
params: {id: 'id1', shouldBatch: false},
|
|
359
|
+
bodyParams: {lookupValues: ['id1']},
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
363
|
+
createData(requestId, 0, true, 'lookupResult', {entitiesNotFound: ['id1']})
|
|
364
|
+
);
|
|
365
|
+
const result = await promise;
|
|
366
|
+
|
|
367
|
+
expect(result).to.be.null;
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
it('calls _batchedLookup correctly', async () => {
|
|
371
|
+
webex.internal.device.orgId = 'userOrgId';
|
|
372
|
+
webex.internal.dss._batchedLookup = sinon
|
|
373
|
+
.stub()
|
|
374
|
+
.returns(Promise.resolve('some return value'));
|
|
375
|
+
|
|
376
|
+
const result = await webex.internal.dss.lookup({id: 'id1'});
|
|
377
|
+
|
|
378
|
+
expect(webex.internal.dss._batchedLookup.getCall(0).args).to.deep.equal([
|
|
379
|
+
{
|
|
380
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
381
|
+
lookupValue: 'id1',
|
|
216
382
|
},
|
|
217
|
-
|
|
218
|
-
|
|
383
|
+
]);
|
|
384
|
+
expect(result).to.equal('some return value');
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it('calls _batchedLookup correctly with entityProviderType', async () => {
|
|
388
|
+
webex.internal.device.orgId = 'userOrgId';
|
|
389
|
+
webex.internal.dss._batchedLookup = sinon
|
|
390
|
+
.stub()
|
|
391
|
+
.returns(Promise.resolve('some return value'));
|
|
392
|
+
|
|
393
|
+
const result = await webex.internal.dss.lookup({
|
|
394
|
+
id: 'id1',
|
|
395
|
+
entityProviderType: 'CI_USER',
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
expect(webex.internal.dss._batchedLookup.getCall(0).args).to.deep.equal([
|
|
399
|
+
{
|
|
400
|
+
resource: '/lookup/orgid/userOrgId/entityprovidertype/CI_USER',
|
|
401
|
+
lookupValue: 'id1',
|
|
219
402
|
},
|
|
403
|
+
]);
|
|
404
|
+
expect(result).to.equal('some return value');
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it('Single batched lookup is made after 50 ms and works', async () => {
|
|
408
|
+
const {promises} = await testMakeBatchedRequests({
|
|
409
|
+
requests: [
|
|
410
|
+
{
|
|
411
|
+
id: 'randomid1',
|
|
412
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
413
|
+
bodyParams: {lookupValues: ['id1']},
|
|
414
|
+
},
|
|
415
|
+
],
|
|
416
|
+
calls: [
|
|
417
|
+
{
|
|
418
|
+
method: 'lookup',
|
|
419
|
+
params: {id: 'id1', shouldBatch: true},
|
|
420
|
+
},
|
|
421
|
+
],
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
425
|
+
createData('randomid1', 0, true, 'lookupResult', {
|
|
426
|
+
entities: ['data0'],
|
|
427
|
+
entitiesFound: ['id1'],
|
|
428
|
+
})
|
|
429
|
+
);
|
|
430
|
+
const result = await promises[0];
|
|
431
|
+
|
|
432
|
+
expect(result).to.deep.equal('data0');
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
it('Single batched lookup fails correctly if lookup fails', async () => {
|
|
436
|
+
const {promises} = await testMakeBatchedRequests({
|
|
437
|
+
requests: [
|
|
438
|
+
{
|
|
439
|
+
id: 'randomid1',
|
|
440
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
441
|
+
bodyParams: {lookupValues: ['id1']},
|
|
442
|
+
},
|
|
443
|
+
],
|
|
444
|
+
calls: [
|
|
445
|
+
{
|
|
446
|
+
method: 'lookup',
|
|
447
|
+
params: {id: 'id1', shouldBatch: true},
|
|
448
|
+
},
|
|
449
|
+
],
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
453
|
+
createData('randomid1', 0, true, 'lookupResult', {entitiesNotFound: ['id1']})
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
const result = await promises[0];
|
|
457
|
+
|
|
458
|
+
expect(result).to.be.null;
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
it('Batch of 2 lookups is made after 50 ms and works', async () => {
|
|
462
|
+
const {promises} = await testMakeBatchedRequests({
|
|
463
|
+
requests: [
|
|
464
|
+
{
|
|
465
|
+
id: 'randomid1',
|
|
466
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
467
|
+
bodyParams: {lookupValues: ['id1', 'id2']},
|
|
468
|
+
},
|
|
469
|
+
],
|
|
470
|
+
calls: [
|
|
471
|
+
{
|
|
472
|
+
method: 'lookup',
|
|
473
|
+
params: {id: 'id1', shouldBatch: true},
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
method: 'lookup',
|
|
477
|
+
params: {id: 'id2', shouldBatch: true},
|
|
478
|
+
},
|
|
479
|
+
],
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
483
|
+
createData('randomid1', 0, true, 'lookupResult', {
|
|
484
|
+
entities: ['data1', 'data2'],
|
|
485
|
+
entitiesFound: ['id1', 'id2'],
|
|
486
|
+
})
|
|
487
|
+
);
|
|
488
|
+
const result1 = await promises[0];
|
|
489
|
+
|
|
490
|
+
expect(result1).to.equal('data1');
|
|
491
|
+
const result2 = await promises[1];
|
|
492
|
+
|
|
493
|
+
expect(result2).to.equal('data2');
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
it('Batch of 2 lookups is made after 50 ms and one fails correctly', async () => {
|
|
497
|
+
const {promises} = await testMakeBatchedRequests({
|
|
498
|
+
requests: [
|
|
499
|
+
{
|
|
500
|
+
id: 'randomid1',
|
|
501
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
502
|
+
bodyParams: {lookupValues: ['id1', 'id2']},
|
|
503
|
+
},
|
|
504
|
+
],
|
|
505
|
+
calls: [
|
|
506
|
+
{
|
|
507
|
+
method: 'lookup',
|
|
508
|
+
params: {id: 'id1', shouldBatch: true},
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
method: 'lookup',
|
|
512
|
+
params: {id: 'id2', shouldBatch: true},
|
|
513
|
+
},
|
|
514
|
+
],
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
518
|
+
createData('randomid1', 0, true, 'lookupResult', {
|
|
519
|
+
entities: ['data2'],
|
|
520
|
+
entitiesFound: ['id2'],
|
|
521
|
+
entitiesNotFound: ['id1'],
|
|
522
|
+
})
|
|
523
|
+
);
|
|
524
|
+
const result1 = await promises[0];
|
|
525
|
+
|
|
526
|
+
expect(result1).to.be.null;
|
|
527
|
+
|
|
528
|
+
const result2 = await promises[1];
|
|
529
|
+
|
|
530
|
+
expect(result2).to.equal('data2');
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
it('Two unrelated lookups are made after 50 ms and work', async () => {
|
|
534
|
+
const {promises} = await testMakeBatchedRequests({
|
|
535
|
+
requests: [
|
|
536
|
+
{
|
|
537
|
+
id: 'randomid1',
|
|
538
|
+
resource: '/lookup/orgid/userOrgId/entityprovidertype/CI_USER',
|
|
539
|
+
bodyParams: {lookupValues: ['id1']},
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
id: 'randomid2',
|
|
543
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
544
|
+
bodyParams: {lookupValues: ['id2']},
|
|
545
|
+
},
|
|
546
|
+
],
|
|
547
|
+
calls: [
|
|
548
|
+
{
|
|
549
|
+
method: 'lookup',
|
|
550
|
+
params: {id: 'id1', entityProviderType: 'CI_USER', shouldBatch: true},
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
method: 'lookup',
|
|
554
|
+
params: {id: 'id2', shouldBatch: true},
|
|
555
|
+
},
|
|
556
|
+
],
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
560
|
+
createData('randomid1', 0, true, 'lookupResult', {
|
|
561
|
+
entities: ['data1'],
|
|
562
|
+
entitiesFound: ['id1'],
|
|
563
|
+
})
|
|
564
|
+
);
|
|
565
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
566
|
+
createData('randomid2', 0, true, 'lookupResult', {
|
|
567
|
+
entities: ['data2'],
|
|
568
|
+
entitiesFound: ['id2'],
|
|
569
|
+
})
|
|
570
|
+
);
|
|
571
|
+
const result1 = await promises[0];
|
|
572
|
+
|
|
573
|
+
expect(result1).to.equal('data1');
|
|
574
|
+
const result2 = await promises[1];
|
|
575
|
+
|
|
576
|
+
expect(result2).to.equal('data2');
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
it('Two unrelated lookups are made after 50 ms and one fails correctly', async () => {
|
|
580
|
+
const {promises} = await testMakeBatchedRequests({
|
|
581
|
+
requests: [
|
|
582
|
+
{
|
|
583
|
+
id: 'randomid1',
|
|
584
|
+
resource: '/lookup/orgid/userOrgId/entityprovidertype/CI_USER',
|
|
585
|
+
bodyParams: {lookupValues: ['id1']},
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
id: 'randomid2',
|
|
589
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
590
|
+
bodyParams: {lookupValues: ['id2']},
|
|
591
|
+
},
|
|
592
|
+
],
|
|
593
|
+
calls: [
|
|
594
|
+
{
|
|
595
|
+
method: 'lookup',
|
|
596
|
+
params: {id: 'id1', entityProviderType: 'CI_USER', shouldBatch: true},
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
method: 'lookup',
|
|
600
|
+
params: {id: 'id2', shouldBatch: true},
|
|
601
|
+
},
|
|
602
|
+
],
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
606
|
+
createData('randomid1', 0, true, 'lookupResult', {entitiesNotFound: ['id1']})
|
|
607
|
+
);
|
|
608
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
609
|
+
createData('randomid2', 0, true, 'lookupResult', {
|
|
610
|
+
entities: ['data2'],
|
|
611
|
+
entitiesFound: ['id2'],
|
|
612
|
+
})
|
|
613
|
+
);
|
|
614
|
+
const result1 = await promises[0];
|
|
615
|
+
|
|
616
|
+
expect(result1).to.be.null;
|
|
617
|
+
const result2 = await promises[1];
|
|
618
|
+
|
|
619
|
+
expect(result2).to.equal('data2');
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
it('fails with default timeout when mercury does not respond', async () => {
|
|
623
|
+
return testMakeRequest({
|
|
624
|
+
method: 'lookup',
|
|
625
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
626
|
+
params: {id: 'id1', shouldBatch: false},
|
|
627
|
+
bodyParams: {lookupValues: ['id1']},
|
|
628
|
+
}).then(async ({promise}) => {
|
|
629
|
+
promise.catch((err) => {
|
|
630
|
+
expect(err.toString()).equal(
|
|
631
|
+
'DssTimeoutError: The DSS did not respond within 6000 ms.' +
|
|
632
|
+
'\n Request Id: randomid' +
|
|
633
|
+
'\n Resource: /lookup/orgid/userOrgId/identities' +
|
|
634
|
+
'\n Params: {"lookupValues":["id1"]}'
|
|
635
|
+
);
|
|
636
|
+
});
|
|
637
|
+
await clock.tickAsync(6000);
|
|
220
638
|
});
|
|
221
639
|
});
|
|
640
|
+
|
|
641
|
+
it('does not fail with timeout when mercury response in time', async () => {
|
|
642
|
+
const {promise, requestId} = await testMakeRequest({
|
|
643
|
+
method: 'lookup',
|
|
644
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
645
|
+
params: {id: 'id1', shouldBatch: false},
|
|
646
|
+
bodyParams: {lookupValues: ['id1']},
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
await clock.tickAsync(499);
|
|
650
|
+
|
|
651
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
652
|
+
createData(requestId, 0, true, 'lookupResult', {entitiesNotFound: ['test id']})
|
|
653
|
+
);
|
|
654
|
+
|
|
655
|
+
return assert.isFulfilled(promise);
|
|
656
|
+
});
|
|
222
657
|
});
|
|
223
658
|
|
|
224
659
|
describe('#lookupByEmail', () => {
|
|
225
660
|
it('calls _request correctly', async () => {
|
|
226
661
|
webex.internal.device.orgId = 'userOrgId';
|
|
227
|
-
webex.internal.dss._request = sinon.stub().returns(
|
|
662
|
+
webex.internal.dss._request = sinon.stub().returns(
|
|
663
|
+
Promise.resolve({
|
|
664
|
+
resultArray: ['some return value'],
|
|
665
|
+
foundArray: ['email1'],
|
|
666
|
+
})
|
|
667
|
+
);
|
|
228
668
|
|
|
229
669
|
const result = await webex.internal.dss.lookupByEmail({
|
|
230
|
-
|
|
670
|
+
email: 'email1',
|
|
231
671
|
});
|
|
672
|
+
|
|
232
673
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
233
674
|
{
|
|
234
675
|
dataPath: 'lookupResult.entities',
|
|
676
|
+
foundPath: 'lookupResult.entitiesFound',
|
|
235
677
|
resource: '/lookup/orgid/userOrgId/emails',
|
|
236
678
|
params: {
|
|
237
|
-
lookupValues: ['email1'
|
|
679
|
+
lookupValues: ['email1'],
|
|
238
680
|
},
|
|
239
681
|
},
|
|
240
682
|
]);
|
|
@@ -242,31 +684,90 @@ describe('plugin-dss', () => {
|
|
|
242
684
|
});
|
|
243
685
|
|
|
244
686
|
it('works correctly', async () => {
|
|
245
|
-
await
|
|
687
|
+
const {requestId, promise} = await testMakeRequest({
|
|
246
688
|
method: 'lookupByEmail',
|
|
247
|
-
dataPath: 'lookupResult.entities',
|
|
248
|
-
event: 'event:directory.lookup',
|
|
249
689
|
resource: '/lookup/orgid/userOrgId/emails',
|
|
250
|
-
params: {
|
|
251
|
-
|
|
252
|
-
},
|
|
253
|
-
bodyParams: {
|
|
254
|
-
lookupValues: ['email1', 'email2'],
|
|
255
|
-
},
|
|
690
|
+
params: {email: 'email1'},
|
|
691
|
+
bodyParams: {lookupValues: ['email1']},
|
|
256
692
|
});
|
|
693
|
+
|
|
694
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
695
|
+
createData(requestId, 0, true, 'lookupResult', {
|
|
696
|
+
entities: ['data0'],
|
|
697
|
+
entitiesFound: ['email1'],
|
|
698
|
+
})
|
|
699
|
+
);
|
|
700
|
+
const result = await promise;
|
|
701
|
+
|
|
702
|
+
expect(result).to.deep.equal('data0');
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
it('fails correctly if lookup fails', async () => {
|
|
706
|
+
const {requestId, promise} = await testMakeRequest({
|
|
707
|
+
method: 'lookupByEmail',
|
|
708
|
+
resource: '/lookup/orgid/userOrgId/emails',
|
|
709
|
+
params: {email: 'email1'},
|
|
710
|
+
bodyParams: {lookupValues: ['email1']},
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
714
|
+
createData(requestId, 0, true, 'lookupResult', {}) // entitiesNotFound isn't returned for email
|
|
715
|
+
);
|
|
716
|
+
const result = await promise;
|
|
717
|
+
|
|
718
|
+
expect(result).to.be.null;
|
|
719
|
+
});
|
|
720
|
+
|
|
721
|
+
it('fails with default timeout when mercury does not respond', async () => {
|
|
722
|
+
return testMakeRequest({
|
|
723
|
+
method: 'lookupByEmail',
|
|
724
|
+
resource: '/lookup/orgid/userOrgId/emails',
|
|
725
|
+
params: {email: 'email1'},
|
|
726
|
+
bodyParams: {lookupValues: ['email1']},
|
|
727
|
+
}).then(async ({promise}) => {
|
|
728
|
+
promise.catch((err) => {
|
|
729
|
+
expect(err.toString()).equal(
|
|
730
|
+
'DssTimeoutError: The DSS did not respond within 6000 ms.' +
|
|
731
|
+
'\n Request Id: randomid' +
|
|
732
|
+
'\n Resource: /lookup/orgid/userOrgId/emails' +
|
|
733
|
+
'\n Params: {"lookupValues":["email1"]}'
|
|
734
|
+
);
|
|
735
|
+
});
|
|
736
|
+
await clock.tickAsync(6000);
|
|
737
|
+
});
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
it('does not fail with timeout when mercury response in time', async () => {
|
|
741
|
+
const {requestId, promise} = await testMakeRequest({
|
|
742
|
+
method: 'lookupByEmail',
|
|
743
|
+
resource: '/lookup/orgid/userOrgId/emails',
|
|
744
|
+
params: {email: 'email1'},
|
|
745
|
+
bodyParams: {lookupValues: ['email1']},
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
await clock.tickAsync(5999);
|
|
749
|
+
|
|
750
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
751
|
+
createData(requestId, 0, true, 'lookupResult', {}) // entitiesNotFound isn't returned for email
|
|
752
|
+
);
|
|
753
|
+
|
|
754
|
+
return assert.isFulfilled(promise);
|
|
257
755
|
});
|
|
258
756
|
});
|
|
259
757
|
|
|
260
758
|
describe('#search', () => {
|
|
261
759
|
it('calls _request correctly', async () => {
|
|
262
760
|
webex.internal.device.orgId = 'userOrgId';
|
|
263
|
-
webex.internal.dss._request = sinon
|
|
761
|
+
webex.internal.dss._request = sinon
|
|
762
|
+
.stub()
|
|
763
|
+
.returns(Promise.resolve({resultArray: 'some return value'}));
|
|
264
764
|
|
|
265
765
|
const result = await webex.internal.dss.search({
|
|
266
766
|
requestedTypes: ['PERSON', 'ROBOT'],
|
|
267
767
|
resultSize: 100,
|
|
268
768
|
queryString: 'query',
|
|
269
769
|
});
|
|
770
|
+
|
|
270
771
|
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
271
772
|
{
|
|
272
773
|
dataPath: 'directoryEntities',
|
|
@@ -282,10 +783,8 @@ describe('plugin-dss', () => {
|
|
|
282
783
|
});
|
|
283
784
|
|
|
284
785
|
it('works correctly', async () => {
|
|
285
|
-
await
|
|
786
|
+
const {requestId, promise} = await testMakeRequest({
|
|
286
787
|
method: 'search',
|
|
287
|
-
event: 'event:directory.search',
|
|
288
|
-
dataPath: 'directoryEntities',
|
|
289
788
|
resource: '/search/orgid/userOrgId/entities',
|
|
290
789
|
params: {
|
|
291
790
|
requestedTypes: ['PERSON', 'ROBOT'],
|
|
@@ -298,13 +797,118 @@ describe('plugin-dss', () => {
|
|
|
298
797
|
queryString: 'query',
|
|
299
798
|
},
|
|
300
799
|
});
|
|
800
|
+
|
|
801
|
+
mercuryCallbacks['event:directory.search'](
|
|
802
|
+
createData(requestId, 1, false, 'directoryEntities', ['data1'])
|
|
803
|
+
);
|
|
804
|
+
mercuryCallbacks['event:directory.search'](
|
|
805
|
+
createData(requestId, 2, true, 'directoryEntities', ['data2'])
|
|
806
|
+
);
|
|
807
|
+
mercuryCallbacks['event:directory.search'](
|
|
808
|
+
createData(requestId, 0, false, 'directoryEntities', ['data0'])
|
|
809
|
+
);
|
|
810
|
+
const result = await promise;
|
|
811
|
+
|
|
812
|
+
expect(result).to.deep.equal(['data0', 'data1', 'data2']);
|
|
813
|
+
});
|
|
814
|
+
|
|
815
|
+
it('fails with default timeout when mercury does not respond', async () => {
|
|
816
|
+
return testMakeRequest({
|
|
817
|
+
method: 'search',
|
|
818
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
819
|
+
params: {
|
|
820
|
+
requestedTypes: ['PERSON', 'ROBOT'],
|
|
821
|
+
resultSize: 100,
|
|
822
|
+
queryString: 'query',
|
|
823
|
+
},
|
|
824
|
+
bodyParams: {
|
|
825
|
+
requestedTypes: ['PERSON', 'ROBOT'],
|
|
826
|
+
resultSize: 100,
|
|
827
|
+
queryString: 'query',
|
|
828
|
+
},
|
|
829
|
+
}).then(async ({promise}) => {
|
|
830
|
+
promise.catch((err) => {
|
|
831
|
+
expect(err.toString()).equal(
|
|
832
|
+
'DssTimeoutError: The DSS did not respond within 6000 ms.' +
|
|
833
|
+
'\n Request Id: randomid' +
|
|
834
|
+
'\n Resource: /search/orgid/userOrgId/entities' +
|
|
835
|
+
'\n Params: {"queryString":"query","resultSize":100,"requestedTypes":["PERSON","ROBOT"]}'
|
|
836
|
+
);
|
|
837
|
+
});
|
|
838
|
+
await clock.tickAsync(6000);
|
|
839
|
+
});
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
it('does not fail with timeout when mercury response in time', async () => {
|
|
843
|
+
const {requestId, promise} = await testMakeRequest({
|
|
844
|
+
method: 'search',
|
|
845
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
846
|
+
params: {
|
|
847
|
+
requestedTypes: ['PERSON', 'ROBOT'],
|
|
848
|
+
resultSize: 100,
|
|
849
|
+
queryString: 'query',
|
|
850
|
+
},
|
|
851
|
+
bodyParams: {
|
|
852
|
+
requestedTypes: ['PERSON', 'ROBOT'],
|
|
853
|
+
resultSize: 100,
|
|
854
|
+
queryString: 'query',
|
|
855
|
+
},
|
|
856
|
+
});
|
|
857
|
+
|
|
858
|
+
await clock.tickAsync(5999);
|
|
859
|
+
|
|
860
|
+
mercuryCallbacks['event:directory.search'](
|
|
861
|
+
createData(requestId, 1, false, 'directoryEntities', ['data1'])
|
|
862
|
+
);
|
|
863
|
+
mercuryCallbacks['event:directory.search'](
|
|
864
|
+
createData(requestId, 2, true, 'directoryEntities', ['data2'])
|
|
865
|
+
);
|
|
866
|
+
mercuryCallbacks['event:directory.search'](
|
|
867
|
+
createData(requestId, 0, false, 'directoryEntities', ['data0'])
|
|
868
|
+
);
|
|
869
|
+
|
|
870
|
+
return assert.isFulfilled(promise);
|
|
871
|
+
});
|
|
872
|
+
|
|
873
|
+
it('fails with timeout when request only partially resolved', async () => {
|
|
874
|
+
return testMakeRequest({
|
|
875
|
+
method: 'search',
|
|
876
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
877
|
+
params: {
|
|
878
|
+
requestedTypes: ['PERSON', 'ROBOT'],
|
|
879
|
+
resultSize: 100,
|
|
880
|
+
queryString: 'query',
|
|
881
|
+
},
|
|
882
|
+
bodyParams: {
|
|
883
|
+
requestedTypes: ['PERSON', 'ROBOT'],
|
|
884
|
+
resultSize: 100,
|
|
885
|
+
queryString: 'query',
|
|
886
|
+
},
|
|
887
|
+
}).then(async ({requestId, promise}) => {
|
|
888
|
+
mercuryCallbacks['event:directory.search'](
|
|
889
|
+
createData(requestId, 2, true, 'directoryEntities', ['data2'])
|
|
890
|
+
);
|
|
891
|
+
mercuryCallbacks['event:directory.search'](
|
|
892
|
+
createData(requestId, 0, false, 'directoryEntities', ['data0'])
|
|
893
|
+
);
|
|
894
|
+
|
|
895
|
+
promise.catch((err) => {
|
|
896
|
+
expect(err.toString()).equal(
|
|
897
|
+
'DssTimeoutError: The DSS did not respond within 6000 ms.' +
|
|
898
|
+
'\n Request Id: randomid' +
|
|
899
|
+
'\n Resource: /search/orgid/userOrgId/entities' +
|
|
900
|
+
'\n Params: {"queryString":"query","resultSize":100,"requestedTypes":["PERSON","ROBOT"]}'
|
|
901
|
+
);
|
|
902
|
+
});
|
|
903
|
+
await clock.tickAsync(6000);
|
|
904
|
+
});
|
|
301
905
|
});
|
|
302
906
|
});
|
|
303
907
|
|
|
304
908
|
describe('#_request', () => {
|
|
305
909
|
it('handles a request correctly', async () => {
|
|
306
910
|
webex.request = sinon.stub();
|
|
307
|
-
uuid.v4
|
|
911
|
+
uuid.v4();
|
|
308
912
|
const promise = webex.internal.dss._request({
|
|
309
913
|
resource: '/search/orgid/userOrgId/entities',
|
|
310
914
|
params: {some: 'param'},
|
|
@@ -326,34 +930,363 @@ describe('plugin-dss', () => {
|
|
|
326
930
|
|
|
327
931
|
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
328
932
|
sequence: 1,
|
|
329
|
-
a: {
|
|
330
|
-
b: {
|
|
331
|
-
c: ['data1'],
|
|
332
|
-
},
|
|
333
|
-
},
|
|
933
|
+
a: {b: {c: ['data1']}},
|
|
334
934
|
});
|
|
335
|
-
|
|
336
935
|
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
337
936
|
sequence: 2,
|
|
338
937
|
finished: true,
|
|
339
|
-
a: {
|
|
340
|
-
|
|
341
|
-
|
|
938
|
+
a: {b: {c: ['data2']}},
|
|
939
|
+
});
|
|
940
|
+
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
941
|
+
sequence: 0,
|
|
942
|
+
a: {b: {c: ['data0']}},
|
|
943
|
+
});
|
|
944
|
+
|
|
945
|
+
const result = await promise;
|
|
946
|
+
|
|
947
|
+
expect(result).to.deep.equal({
|
|
948
|
+
resultArray: ['data0', 'data1', 'data2'],
|
|
949
|
+
});
|
|
950
|
+
});
|
|
951
|
+
|
|
952
|
+
it('handles a request with foundPath correctly', async () => {
|
|
953
|
+
webex.request = sinon.stub();
|
|
954
|
+
uuid.v4.returns('randomid');
|
|
955
|
+
const promise = webex.internal.dss._request({
|
|
956
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
957
|
+
params: {some: 'param'},
|
|
958
|
+
dataPath: 'a.b.c',
|
|
959
|
+
foundPath: 'someFoundPath',
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
expect(webex.request.getCall(0).args).to.deep.equal([
|
|
963
|
+
{
|
|
964
|
+
service: 'directorySearch',
|
|
965
|
+
body: {
|
|
966
|
+
requestId: 'randomid',
|
|
967
|
+
some: 'param',
|
|
342
968
|
},
|
|
969
|
+
contentType: 'application/json',
|
|
970
|
+
method: 'POST',
|
|
971
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
343
972
|
},
|
|
344
|
-
|
|
973
|
+
]);
|
|
345
974
|
|
|
975
|
+
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
976
|
+
sequence: 1,
|
|
977
|
+
a: {b: {c: ['data1']}},
|
|
978
|
+
someFoundPath: ['id1'],
|
|
979
|
+
});
|
|
980
|
+
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
981
|
+
sequence: 2,
|
|
982
|
+
finished: true,
|
|
983
|
+
a: {b: {c: ['data2']}},
|
|
984
|
+
someFoundPath: ['id2'],
|
|
985
|
+
});
|
|
346
986
|
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
347
987
|
sequence: 0,
|
|
348
|
-
a: {
|
|
349
|
-
|
|
350
|
-
|
|
988
|
+
a: {b: {c: ['data0']}},
|
|
989
|
+
someFoundPath: ['id0'],
|
|
990
|
+
});
|
|
991
|
+
|
|
992
|
+
const result = await promise;
|
|
993
|
+
|
|
994
|
+
expect(result).to.deep.equal({
|
|
995
|
+
resultArray: ['data0', 'data1', 'data2'],
|
|
996
|
+
foundArray: ['id0', 'id1', 'id2'],
|
|
997
|
+
});
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
it('handles a request with foundPath and notFoundPath correctly', async () => {
|
|
1001
|
+
webex.request = sinon.stub();
|
|
1002
|
+
uuid.v4.returns('randomid');
|
|
1003
|
+
const promise = webex.internal.dss._request({
|
|
1004
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
1005
|
+
params: {some: 'param'},
|
|
1006
|
+
dataPath: 'a.b.c',
|
|
1007
|
+
foundPath: 'someFoundPath',
|
|
1008
|
+
notFoundPath: 'someNotFoundPath',
|
|
1009
|
+
});
|
|
1010
|
+
|
|
1011
|
+
expect(webex.request.getCall(0).args).to.deep.equal([
|
|
1012
|
+
{
|
|
1013
|
+
service: 'directorySearch',
|
|
1014
|
+
body: {
|
|
1015
|
+
requestId: 'randomid',
|
|
1016
|
+
some: 'param',
|
|
351
1017
|
},
|
|
1018
|
+
contentType: 'application/json',
|
|
1019
|
+
method: 'POST',
|
|
1020
|
+
resource: '/search/orgid/userOrgId/entities',
|
|
352
1021
|
},
|
|
1022
|
+
]);
|
|
1023
|
+
|
|
1024
|
+
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
1025
|
+
sequence: 1,
|
|
1026
|
+
a: {b: {c: ['data1']}},
|
|
1027
|
+
someFoundPath: ['id1'],
|
|
1028
|
+
});
|
|
1029
|
+
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
1030
|
+
sequence: 2,
|
|
1031
|
+
finished: true,
|
|
1032
|
+
a: {b: {c: ['data2']}},
|
|
1033
|
+
someFoundPath: ['id2'],
|
|
1034
|
+
someNotFoundPath: ['id3'],
|
|
1035
|
+
});
|
|
1036
|
+
webex.internal.dss.trigger(webex.internal.dss._getResultEventName('randomid'), {
|
|
1037
|
+
sequence: 0,
|
|
1038
|
+
a: {b: {c: ['data0']}},
|
|
1039
|
+
someFoundPath: ['id0'],
|
|
353
1040
|
});
|
|
354
1041
|
|
|
355
1042
|
const result = await promise;
|
|
356
|
-
|
|
1043
|
+
|
|
1044
|
+
expect(result).to.deep.equal({
|
|
1045
|
+
resultArray: ['data0', 'data1', 'data2'],
|
|
1046
|
+
foundArray: ['id0', 'id1', 'id2'],
|
|
1047
|
+
notFoundArray: ['id3'],
|
|
1048
|
+
});
|
|
1049
|
+
});
|
|
1050
|
+
});
|
|
1051
|
+
|
|
1052
|
+
describe('#_batchedLookup', () => {
|
|
1053
|
+
const checkStandardProperties = (batcher) => {
|
|
1054
|
+
expect(batcher.dataPath).to.equal('lookupResult.entities');
|
|
1055
|
+
expect(batcher.entitiesFoundPath).to.equal('lookupResult.entitiesFound');
|
|
1056
|
+
expect(batcher.entitiesNotFoundPath).to.equal('lookupResult.entitiesNotFound');
|
|
1057
|
+
expect(batcher.requestKey).to.equal('lookupValues');
|
|
1058
|
+
expect(batcher.config).to.deep.equal({
|
|
1059
|
+
batcherWait: 50,
|
|
1060
|
+
batcherMaxCalls: 50,
|
|
1061
|
+
batcherMaxWait: 150,
|
|
1062
|
+
requestTimeout: 6000,
|
|
1063
|
+
});
|
|
1064
|
+
};
|
|
1065
|
+
|
|
1066
|
+
it('calls batcher.request on new batcher for first lookup', async () => {
|
|
1067
|
+
const resource = '/lookup/orgid/userOrgId/identities';
|
|
1068
|
+
const response = 'response1';
|
|
1069
|
+
|
|
1070
|
+
Batcher.prototype.request = sinon.stub().returns(Promise.resolve(response));
|
|
1071
|
+
|
|
1072
|
+
expect(webex.internal.dss.batchers).to.deep.equal({});
|
|
1073
|
+
|
|
1074
|
+
const result = await webex.internal.dss._batchedLookup({
|
|
1075
|
+
resource,
|
|
1076
|
+
lookupValue: 'id1',
|
|
1077
|
+
});
|
|
1078
|
+
|
|
1079
|
+
const batcher = webex.internal.dss.batchers[resource];
|
|
1080
|
+
|
|
1081
|
+
expect(batcher).to.exist;
|
|
1082
|
+
expect(batcher.resource).to.equal(resource);
|
|
1083
|
+
checkStandardProperties(batcher);
|
|
1084
|
+
|
|
1085
|
+
expect(Batcher.prototype.request.getCall(0).args).to.deep.equal(['id1']);
|
|
1086
|
+
expect(result).to.equal(response);
|
|
1087
|
+
});
|
|
1088
|
+
|
|
1089
|
+
it('calls batcher.request on new batcher for lookup with new resource', async () => {
|
|
1090
|
+
const resource1 = '/lookup/orgid/userOrgId/identities';
|
|
1091
|
+
const resource2 = '/lookup/orgid/userOrgId/entityprovidertype/CI_USER';
|
|
1092
|
+
const response1 = 'response1';
|
|
1093
|
+
const response2 = 'response2';
|
|
1094
|
+
|
|
1095
|
+
Batcher.prototype.request = sinon
|
|
1096
|
+
.stub()
|
|
1097
|
+
.onFirstCall()
|
|
1098
|
+
.returns(Promise.resolve(response1))
|
|
1099
|
+
.onSecondCall()
|
|
1100
|
+
.returns(Promise.resolve(response2));
|
|
1101
|
+
|
|
1102
|
+
expect(webex.internal.dss.batchers).to.deep.equal({});
|
|
1103
|
+
|
|
1104
|
+
await webex.internal.dss._batchedLookup({
|
|
1105
|
+
resource: resource1,
|
|
1106
|
+
lookupValue: 'id1',
|
|
1107
|
+
});
|
|
1108
|
+
|
|
1109
|
+
const result = await webex.internal.dss._batchedLookup({
|
|
1110
|
+
resource: resource2,
|
|
1111
|
+
lookupValue: 'id2',
|
|
1112
|
+
});
|
|
1113
|
+
|
|
1114
|
+
expect(webex.internal.dss.batchers[resource1]).to.exist;
|
|
1115
|
+
const batcher = webex.internal.dss.batchers[resource2];
|
|
1116
|
+
|
|
1117
|
+
expect(batcher).to.exist;
|
|
1118
|
+
expect(batcher.resource).to.equal(resource2);
|
|
1119
|
+
checkStandardProperties(batcher);
|
|
1120
|
+
|
|
1121
|
+
expect(Batcher.prototype.request.getCall(1).args).to.deep.equal(['id2']);
|
|
1122
|
+
expect(result).to.equal(response2);
|
|
1123
|
+
});
|
|
1124
|
+
|
|
1125
|
+
it('calls batcher.request on existing batcher for lookup with existing reource', async () => {
|
|
1126
|
+
const resource1 = '/lookup/orgid/userOrgId/identities';
|
|
1127
|
+
const response1 = 'response1';
|
|
1128
|
+
const response2 = 'response2';
|
|
1129
|
+
|
|
1130
|
+
Batcher.prototype.request = sinon
|
|
1131
|
+
.stub()
|
|
1132
|
+
.onFirstCall()
|
|
1133
|
+
.returns(Promise.resolve(response1))
|
|
1134
|
+
.onSecondCall()
|
|
1135
|
+
.returns(Promise.resolve(response2));
|
|
1136
|
+
|
|
1137
|
+
expect(webex.internal.dss.batchers).to.deep.equal({});
|
|
1138
|
+
|
|
1139
|
+
await webex.internal.dss._batchedLookup({
|
|
1140
|
+
resource: resource1,
|
|
1141
|
+
lookupValue: 'id1',
|
|
1142
|
+
});
|
|
1143
|
+
expect(webex.internal.dss.batchers[resource1]).to.exist;
|
|
1144
|
+
const initialBatcher = webex.internal.dss.batchers[resource1];
|
|
1145
|
+
|
|
1146
|
+
const result = await webex.internal.dss._batchedLookup({
|
|
1147
|
+
resource: resource1,
|
|
1148
|
+
lookupValue: 'id2',
|
|
1149
|
+
});
|
|
1150
|
+
|
|
1151
|
+
const batcher = webex.internal.dss.batchers[resource1];
|
|
1152
|
+
|
|
1153
|
+
expect(batcher).to.equal(initialBatcher);
|
|
1154
|
+
expect(batcher.resource).to.equal(resource1);
|
|
1155
|
+
checkStandardProperties(batcher);
|
|
1156
|
+
|
|
1157
|
+
expect(Batcher.prototype.request.getCall(1).args).to.deep.equal(['id2']);
|
|
1158
|
+
expect(result).to.equal(response2);
|
|
1159
|
+
});
|
|
1160
|
+
// TODO - https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-518037
|
|
1161
|
+
it.skip('fails fails when mercury does not respond, later batches can still pass ok', async () => {
|
|
1162
|
+
// Batch 1
|
|
1163
|
+
const {
|
|
1164
|
+
promises: [p1, p2, p3],
|
|
1165
|
+
} = await testMakeBatchedRequests({
|
|
1166
|
+
requests: [
|
|
1167
|
+
{
|
|
1168
|
+
id: 'req-id-1',
|
|
1169
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
1170
|
+
bodyParams: {lookupValues: ['id1', 'id2', 'id3']},
|
|
1171
|
+
},
|
|
1172
|
+
],
|
|
1173
|
+
calls: [
|
|
1174
|
+
{
|
|
1175
|
+
method: 'lookup',
|
|
1176
|
+
params: {id: 'id1', shouldBatch: true},
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
method: 'lookup',
|
|
1180
|
+
params: {id: 'id2', shouldBatch: true},
|
|
1181
|
+
},
|
|
1182
|
+
{
|
|
1183
|
+
method: 'lookup',
|
|
1184
|
+
params: {id: 'id3', shouldBatch: true},
|
|
1185
|
+
},
|
|
1186
|
+
],
|
|
1187
|
+
});
|
|
1188
|
+
|
|
1189
|
+
// Batch 2
|
|
1190
|
+
const {
|
|
1191
|
+
promises: [p4],
|
|
1192
|
+
} = await testMakeBatchedRequests({
|
|
1193
|
+
requests: [
|
|
1194
|
+
{
|
|
1195
|
+
id: 'randomid',
|
|
1196
|
+
resource: '/lookup/orgid/userOrgId/identities',
|
|
1197
|
+
bodyParams: {lookupValues: ['id4']},
|
|
1198
|
+
},
|
|
1199
|
+
],
|
|
1200
|
+
calls: [
|
|
1201
|
+
{
|
|
1202
|
+
method: 'lookup',
|
|
1203
|
+
params: {id: 'id4', shouldBatch: true},
|
|
1204
|
+
},
|
|
1205
|
+
],
|
|
1206
|
+
});
|
|
1207
|
+
|
|
1208
|
+
// Batch 1 - only 1 mercury response out of 2 received
|
|
1209
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
1210
|
+
createData('req-id-1', 0, false, 'lookupResult', {
|
|
1211
|
+
entitiesFound: ['id1', 'id3'],
|
|
1212
|
+
entities: ['data1', 'data3'],
|
|
1213
|
+
})
|
|
1214
|
+
);
|
|
1215
|
+
|
|
1216
|
+
// Batch 2 - response
|
|
1217
|
+
mercuryCallbacks['event:directory.lookup'](
|
|
1218
|
+
createData('randomid', 0, true, 'lookupResult', {entitiesNotFound: ['id4']})
|
|
1219
|
+
);
|
|
1220
|
+
|
|
1221
|
+
// Timeout
|
|
1222
|
+
await clock.tickAsync(6000);
|
|
1223
|
+
|
|
1224
|
+
return Promise.all([
|
|
1225
|
+
assert.isRejected(
|
|
1226
|
+
p1,
|
|
1227
|
+
'The DSS did not respond within 6000 ms.' +
|
|
1228
|
+
'\n Request Id: req-id-1' +
|
|
1229
|
+
'\n Resource: /lookup/orgid/userOrgId/identities' +
|
|
1230
|
+
'\n Params: {"lookupValues":["id1","id2","id3"]}'
|
|
1231
|
+
),
|
|
1232
|
+
assert.isRejected(
|
|
1233
|
+
p2,
|
|
1234
|
+
'The DSS did not respond within 6000 ms.' +
|
|
1235
|
+
'\n Request Id: req-id-1' +
|
|
1236
|
+
'\n Resource: /lookup/orgid/userOrgId/identities' +
|
|
1237
|
+
'\n Params: {"lookupValues":["id1","id2","id3"]}'
|
|
1238
|
+
),
|
|
1239
|
+
assert.isRejected(
|
|
1240
|
+
p3,
|
|
1241
|
+
'The DSS did not respond within 6000 ms.' +
|
|
1242
|
+
'\n Request Id: req-id-1' +
|
|
1243
|
+
'\n Resource: /lookup/orgid/userOrgId/identities' +
|
|
1244
|
+
'\n Params: {"lookupValues":["id1","id2","id3"]}'
|
|
1245
|
+
),
|
|
1246
|
+
assert.isFulfilled(p4),
|
|
1247
|
+
]);
|
|
1248
|
+
});
|
|
1249
|
+
});
|
|
1250
|
+
|
|
1251
|
+
describe('#searchPlaces', () => {
|
|
1252
|
+
it('calls _request correctly', async () => {
|
|
1253
|
+
webex.internal.device.orgId = 'userOrgId';
|
|
1254
|
+
webex.internal.dss._request = sinon.stub().returns(Promise.resolve('some return value'));
|
|
1255
|
+
|
|
1256
|
+
const result = await webex.internal.dss.searchPlaces({
|
|
1257
|
+
resultSize: 100,
|
|
1258
|
+
queryString: 'query',
|
|
1259
|
+
isOnlySchedulableRooms: true,
|
|
1260
|
+
});
|
|
1261
|
+
expect(webex.internal.dss._request.getCall(0).args).to.deep.equal([
|
|
1262
|
+
{
|
|
1263
|
+
dataPath: 'directoryEntities',
|
|
1264
|
+
resource: '/search/orgid/userOrgId/places',
|
|
1265
|
+
params: {
|
|
1266
|
+
queryString: 'query',
|
|
1267
|
+
resultSize: 100,
|
|
1268
|
+
isOnlySchedulableRooms: true,
|
|
1269
|
+
},
|
|
1270
|
+
},
|
|
1271
|
+
]);
|
|
1272
|
+
expect(result).to.equal('some return value');
|
|
1273
|
+
});
|
|
1274
|
+
|
|
1275
|
+
it('works correctly', async () => {
|
|
1276
|
+
await testMakeRequest({
|
|
1277
|
+
method: 'searchPlaces',
|
|
1278
|
+
resource: '/search/orgid/userOrgId/places',
|
|
1279
|
+
params: {
|
|
1280
|
+
isOnlySchedulableRooms: true,
|
|
1281
|
+
resultSize: 100,
|
|
1282
|
+
queryString: 'query',
|
|
1283
|
+
},
|
|
1284
|
+
bodyParams: {
|
|
1285
|
+
isOnlySchedulableRooms: true,
|
|
1286
|
+
resultSize: 100,
|
|
1287
|
+
queryString: 'query',
|
|
1288
|
+
},
|
|
1289
|
+
});
|
|
357
1290
|
});
|
|
358
1291
|
});
|
|
359
1292
|
});
|