@webex/webex-core 3.9.0 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/interceptors/proxy.js +97 -0
- package/dist/interceptors/proxy.js.map +1 -0
- package/dist/lib/batcher.js +1 -1
- package/dist/lib/credentials/credentials.js +1 -1
- package/dist/lib/credentials/token.js +1 -1
- package/dist/lib/services/services.js +1 -1
- package/dist/lib/services-v2/service-catalog.js +11 -1
- package/dist/lib/services-v2/service-catalog.js.map +1 -1
- package/dist/lib/services-v2/services-v2.js +106 -46
- package/dist/lib/services-v2/services-v2.js.map +1 -1
- package/dist/lib/services-v2/types.js.map +1 -1
- package/dist/plugins/logger.js +1 -1
- package/dist/webex-core.js +51 -59
- package/dist/webex-core.js.map +1 -1
- package/package.json +14 -14
- package/src/index.js +1 -0
- package/src/interceptors/proxy.js +70 -0
- package/src/lib/services-v2/service-catalog.ts +14 -1
- package/src/lib/services-v2/services-v2.ts +73 -11
- package/src/lib/services-v2/types.ts +1 -1
- package/src/webex-core.js +10 -2
- package/test/integration/spec/services-v2/service-catalog.js +51 -15
- package/test/integration/spec/services-v2/services-v2.js +79 -4
- package/test/unit/spec/interceptors/proxy.js +73 -0
- package/test/unit/spec/services-v2/services-v2.ts +189 -6
- package/test/unit/spec/webex-core.js +62 -2
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
formattedServiceHostmapEntryConv,
|
|
20
20
|
serviceHostmapV2,
|
|
21
21
|
} from '../../../fixtures/host-catalog-v2';
|
|
22
|
+
import {cloneDeep} from 'lodash';
|
|
22
23
|
|
|
23
24
|
describe('webex-core', () => {
|
|
24
25
|
describe('ServiceCatalogV2', () => {
|
|
@@ -394,13 +395,13 @@ describe('webex-core', () => {
|
|
|
394
395
|
);
|
|
395
396
|
|
|
396
397
|
it('resolves to an authed u2c hostmap when no params specified', () => {
|
|
397
|
-
assert.typeOf(fullRemoteHM, 'array');
|
|
398
|
-
assert.isAbove(fullRemoteHM.length, 0);
|
|
398
|
+
assert.typeOf(fullRemoteHM.services, 'array');
|
|
399
|
+
assert.isAbove(fullRemoteHM.services.length, 0);
|
|
399
400
|
});
|
|
400
401
|
|
|
401
402
|
it('resolves to a limited u2c hostmap when params specified', () => {
|
|
402
|
-
assert.typeOf(limitedRemoteHM, 'array');
|
|
403
|
-
assert.isAbove(limitedRemoteHM.length, 0);
|
|
403
|
+
assert.typeOf(limitedRemoteHM.services, 'array');
|
|
404
|
+
assert.isAbove(limitedRemoteHM.services.length, 0);
|
|
404
405
|
});
|
|
405
406
|
|
|
406
407
|
it('rejects if the params provided are invalid', () =>
|
|
@@ -449,7 +450,7 @@ describe('webex-core', () => {
|
|
|
449
450
|
catalog
|
|
450
451
|
.waitForCatalog('postauth', 1)
|
|
451
452
|
.then(() => assert(true, 'promise resolved'))
|
|
452
|
-
.finally(() => catalog.updateServiceGroups('postauth', formattedHM));
|
|
453
|
+
.finally(() => catalog.updateServiceGroups('postauth', formattedHM.services));
|
|
453
454
|
});
|
|
454
455
|
});
|
|
455
456
|
|
|
@@ -463,7 +464,7 @@ describe('webex-core', () => {
|
|
|
463
464
|
});
|
|
464
465
|
|
|
465
466
|
it('removes any unused urls from current services', () => {
|
|
466
|
-
catalog.updateServiceGroups('preauth', formattedHM);
|
|
467
|
+
catalog.updateServiceGroups('preauth', formattedHM.services);
|
|
467
468
|
|
|
468
469
|
const originalLength = catalog.serviceGroups.preauth.length;
|
|
469
470
|
|
|
@@ -473,9 +474,9 @@ describe('webex-core', () => {
|
|
|
473
474
|
});
|
|
474
475
|
|
|
475
476
|
it('updates the target catalog to contain the provided hosts', () => {
|
|
476
|
-
catalog.updateServiceGroups('preauth', formattedHM);
|
|
477
|
+
catalog.updateServiceGroups('preauth', formattedHM.services);
|
|
477
478
|
|
|
478
|
-
assert.equal(catalog.serviceGroups.preauth.length, formattedHM.length);
|
|
479
|
+
assert.equal(catalog.serviceGroups.preauth.length, formattedHM.services.length);
|
|
479
480
|
});
|
|
480
481
|
|
|
481
482
|
it('updates any existing ServiceUrls', () => {
|
|
@@ -601,21 +602,21 @@ describe('webex-core', () => {
|
|
|
601
602
|
format: 'U2Cv2',
|
|
602
603
|
};
|
|
603
604
|
|
|
604
|
-
catalog.updateServiceGroups('preauth', formattedHM);
|
|
605
|
+
catalog.updateServiceGroups('preauth', formattedHM.services);
|
|
605
606
|
|
|
606
607
|
const oldServiceDetails = catalog._getAllServiceDetails('preauth');
|
|
607
608
|
|
|
608
609
|
const newFormattedHM = services._formatReceivedHostmap(newServiceHM);
|
|
609
610
|
|
|
610
|
-
catalog.updateServiceGroups('preauth', newFormattedHM);
|
|
611
|
+
catalog.updateServiceGroups('preauth', newFormattedHM.services);
|
|
611
612
|
|
|
612
613
|
oldServiceDetails.forEach((serviceDetail) =>
|
|
613
|
-
assert.isTrue(!!formattedHM.find((service) => service.id === serviceDetail.id))
|
|
614
|
+
assert.isTrue(!!formattedHM.services.find((service) => service.id === serviceDetail.id))
|
|
614
615
|
);
|
|
615
616
|
|
|
616
617
|
const newServiceDetails = catalog._getAllServiceDetails('preauth');
|
|
617
618
|
|
|
618
|
-
formattedHM.forEach((oldServiceDetail) =>
|
|
619
|
+
formattedHM.services.forEach((oldServiceDetail) =>
|
|
619
620
|
assert.notEqual(
|
|
620
621
|
oldServiceDetail.serviceUrls[0].baseUrl,
|
|
621
622
|
newServiceDetails.find((service) => service.id === oldServiceDetail.id).get()
|
|
@@ -624,7 +625,7 @@ describe('webex-core', () => {
|
|
|
624
625
|
});
|
|
625
626
|
|
|
626
627
|
it('creates an array of equal length of active services', () => {
|
|
627
|
-
assert.equal(serviceHostmap.services.length, formattedHM.length);
|
|
628
|
+
assert.equal(serviceHostmap.services.length, formattedHM.services.length);
|
|
628
629
|
});
|
|
629
630
|
|
|
630
631
|
it('creates an array with matching host data', () => {
|
|
@@ -646,7 +647,7 @@ describe('webex-core', () => {
|
|
|
646
647
|
done();
|
|
647
648
|
});
|
|
648
649
|
|
|
649
|
-
catalog.updateServiceGroups('preauth', formattedHM);
|
|
650
|
+
catalog.updateServiceGroups('preauth', formattedHM.services);
|
|
650
651
|
});
|
|
651
652
|
|
|
652
653
|
it('updates the services list', (done) => {
|
|
@@ -657,7 +658,42 @@ describe('webex-core', () => {
|
|
|
657
658
|
done();
|
|
658
659
|
});
|
|
659
660
|
|
|
660
|
-
catalog.updateServiceGroups('preauth', formattedHM);
|
|
661
|
+
catalog.updateServiceGroups('preauth', formattedHM.services);
|
|
662
|
+
});
|
|
663
|
+
it('make sure the serviceUrls is in Priority order', (done) => {
|
|
664
|
+
const notInOrderServiceHM = {
|
|
665
|
+
activeServices: {
|
|
666
|
+
conversation: 'urn:TEAM:us-east-2_a:conversation',
|
|
667
|
+
idbroker: 'urn:TEAM:us-east-2_a:idbroker',
|
|
668
|
+
locus: 'urn:TEAM:us-east-2_a:locus',
|
|
669
|
+
mercury: 'urn:TEAM:us-east-2_a:mercury',
|
|
670
|
+
},
|
|
671
|
+
services: [
|
|
672
|
+
{
|
|
673
|
+
id: 'urn:TEAM:us-east-2_a:conversation',
|
|
674
|
+
serviceName: 'conversation',
|
|
675
|
+
serviceUrls: [
|
|
676
|
+
{
|
|
677
|
+
baseUrl: 'https://example-1.svc.webex.com/conversation/api/v1',
|
|
678
|
+
priority: 2,
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
baseUrl: 'https://conv-a.wbx2.com/conversation/api/v1',
|
|
682
|
+
priority: 1,
|
|
683
|
+
},
|
|
684
|
+
],
|
|
685
|
+
},
|
|
686
|
+
],
|
|
687
|
+
orgId: '3e0e410f-f83f-4ee4-ac32-12692e99355c',
|
|
688
|
+
timestamp: '1745533341',
|
|
689
|
+
format: 'U2Cv2',
|
|
690
|
+
};
|
|
691
|
+
const notInOrderFormattedHM = services._formatReceivedHostmap(notInOrderServiceHM);
|
|
692
|
+
const checkFormattedHM = cloneDeep(notInOrderFormattedHM);
|
|
693
|
+
catalog.updateServiceGroups('preauth', notInOrderFormattedHM.services);
|
|
694
|
+
assert.deepEqual(catalog._getServiceDetail('urn:TEAM:us-east-2_a:conversation')?.serviceUrls[0], checkFormattedHM.services[0].serviceUrls[1])
|
|
695
|
+
assert.equal( catalog.get('urn:TEAM:us-east-2_a:conversation'), 'https://conv-a.wbx2.com/conversation/api/v1')
|
|
696
|
+
done();
|
|
661
697
|
});
|
|
662
698
|
});
|
|
663
699
|
});
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
formattedServiceHostmapEntryConv,
|
|
24
24
|
formattedServiceHostmapEntryMercury,
|
|
25
25
|
formattedServiceHostmapEntryTest,
|
|
26
|
+
serviceHostmapV2
|
|
26
27
|
} from '../../../fixtures/host-catalog-v2';
|
|
27
28
|
|
|
28
29
|
// /* eslint-disable no-underscore-dangle */
|
|
@@ -389,6 +390,32 @@ describe('webex-core', () => {
|
|
|
389
390
|
.then(() => assert.calledTwice(services.updateServices))
|
|
390
391
|
);
|
|
391
392
|
});
|
|
393
|
+
|
|
394
|
+
it('should call services#collectPreauthCatalog with the OrgId and forceRefresh is true', () => {
|
|
395
|
+
services.collectPreauthCatalog = sinon.stub().resolves();
|
|
396
|
+
|
|
397
|
+
return services.initServiceCatalogs(true).then(() =>
|
|
398
|
+
assert.calledWith(
|
|
399
|
+
services.collectPreauthCatalog,
|
|
400
|
+
sinon.match({
|
|
401
|
+
orgId: webex.credentials.getOrgId(),
|
|
402
|
+
}),
|
|
403
|
+
sinon.match(true)
|
|
404
|
+
)
|
|
405
|
+
);
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it('should call services#updateServices() with forceRefresh is true', () => {
|
|
409
|
+
services.updateServices = sinon.stub().resolves();
|
|
410
|
+
|
|
411
|
+
return (
|
|
412
|
+
services
|
|
413
|
+
.initServiceCatalogs(true)
|
|
414
|
+
// services#updateServices() gets called once by the limited catalog
|
|
415
|
+
// retrieval and should get called again when authorized.
|
|
416
|
+
.then(() => assert.calledTwice(services.updateServices) && assert.calledWith(services.updateServices, sinon.match({forceRefresh: true})))
|
|
417
|
+
);
|
|
418
|
+
});
|
|
392
419
|
});
|
|
393
420
|
|
|
394
421
|
describe('#isAllowedDomainUrl()', () => {
|
|
@@ -513,6 +540,54 @@ describe('webex-core', () => {
|
|
|
513
540
|
});
|
|
514
541
|
});
|
|
515
542
|
|
|
543
|
+
describe('#switchActiveClusterIds', () => {
|
|
544
|
+
let requestStub;
|
|
545
|
+
|
|
546
|
+
beforeEach(() => {
|
|
547
|
+
services._formatReceivedHostmap(serviceHostmapV2);
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
afterEach(() => {
|
|
551
|
+
requestStub.restore();
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
it('fetches new catalog when id does not exist', () => {
|
|
555
|
+
requestStub = sinon
|
|
556
|
+
.stub(webex.internal.newMetrics.callDiagnosticLatencies, 'measureLatency')
|
|
557
|
+
.returns(
|
|
558
|
+
Promise.resolve({
|
|
559
|
+
body: {
|
|
560
|
+
activeServices: {
|
|
561
|
+
...serviceHostmapV2.activeServices,
|
|
562
|
+
conversation: 'urn:TEAM:me-central-1_asdf:conversation',
|
|
563
|
+
},
|
|
564
|
+
services: [
|
|
565
|
+
...serviceHostmapV2.services,
|
|
566
|
+
{
|
|
567
|
+
id: 'urn:TEAM:me-central-1_asdf:conversation',
|
|
568
|
+
serviceName: 'conversation',
|
|
569
|
+
serviceUrls: [{baseUrl: 'baseurl.com', priority: 1}],
|
|
570
|
+
},
|
|
571
|
+
],
|
|
572
|
+
},
|
|
573
|
+
})
|
|
574
|
+
);
|
|
575
|
+
|
|
576
|
+
services
|
|
577
|
+
.switchActiveClusterIds({
|
|
578
|
+
conversation: 'urn:TEAM:me-central-1_asdf:conversation',
|
|
579
|
+
})
|
|
580
|
+
.then(() => {
|
|
581
|
+
assert.equal(
|
|
582
|
+
!!services._services.find(
|
|
583
|
+
(service) => service.id === 'urn:TEAM:me-central-1_asdf:conversation'
|
|
584
|
+
),
|
|
585
|
+
true
|
|
586
|
+
);
|
|
587
|
+
});
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
|
|
516
591
|
describe('#updateServices()', () => {
|
|
517
592
|
it('returns a Promise that and resolves on success', (done) => {
|
|
518
593
|
const servicesPromise = services.updateServices();
|
|
@@ -1034,13 +1109,13 @@ describe('webex-core', () => {
|
|
|
1034
1109
|
);
|
|
1035
1110
|
|
|
1036
1111
|
it('resolves to an authed u2c hostmap when no params specified', () => {
|
|
1037
|
-
assert.typeOf(fullRemoteHM, 'array');
|
|
1038
|
-
assert.isAbove(fullRemoteHM.length, 0);
|
|
1112
|
+
assert.typeOf(fullRemoteHM.services, 'array');
|
|
1113
|
+
assert.isAbove(fullRemoteHM.services.length, 0);
|
|
1039
1114
|
});
|
|
1040
1115
|
|
|
1041
1116
|
it('resolves to a limited u2c hostmap when params specified', () => {
|
|
1042
|
-
assert.typeOf(limitedRemoteHM, 'array');
|
|
1043
|
-
assert.isAbove(limitedRemoteHM.length, 0);
|
|
1117
|
+
assert.typeOf(limitedRemoteHM.services, 'array');
|
|
1118
|
+
assert.isAbove(limitedRemoteHM.services.length, 0);
|
|
1044
1119
|
});
|
|
1045
1120
|
|
|
1046
1121
|
it('rejects if the params provided are invalid', () =>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {assert} from '@webex/test-helper-chai';
|
|
6
|
+
import {skipInBrowser, skipInNode} from '@webex/test-helper-mocha';
|
|
7
|
+
import {ProxyInterceptor} from '@webex/webex-core';
|
|
8
|
+
|
|
9
|
+
import pkg from '../../../../package';
|
|
10
|
+
|
|
11
|
+
describe('webex-core', () => {
|
|
12
|
+
describe('Interceptors', () => {
|
|
13
|
+
describe('ProxyInterceptor', () => {
|
|
14
|
+
describe('#onRequest', () => {
|
|
15
|
+
it('defaults to no proxy', () => {
|
|
16
|
+
const interceptor = Reflect.apply(
|
|
17
|
+
ProxyInterceptor.create,
|
|
18
|
+
{
|
|
19
|
+
version: pkg.version,
|
|
20
|
+
},
|
|
21
|
+
[]
|
|
22
|
+
);
|
|
23
|
+
const options = {};
|
|
24
|
+
|
|
25
|
+
interceptor.onRequest(options);
|
|
26
|
+
|
|
27
|
+
assert.isUndefined(options.proxy);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
skipInBrowser(describe)('#onRequestNode', () => {
|
|
31
|
+
it('allows custom proxy in node', () => {
|
|
32
|
+
const interceptor = Reflect.apply(
|
|
33
|
+
ProxyInterceptor.create,
|
|
34
|
+
{
|
|
35
|
+
version: pkg.version,
|
|
36
|
+
config: {
|
|
37
|
+
proxy: 'http://proxy.company.com'
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
[]
|
|
41
|
+
);
|
|
42
|
+
const options = {};
|
|
43
|
+
|
|
44
|
+
interceptor.onRequest(options);
|
|
45
|
+
|
|
46
|
+
assert.property(options, 'proxy');
|
|
47
|
+
assert.equal(options.proxy, 'http://proxy.company.com');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
skipInNode(describe)('#onRequestBrowser', () => {
|
|
52
|
+
it('removes custom proxy in browser', () => {
|
|
53
|
+
const interceptor = Reflect.apply(
|
|
54
|
+
ProxyInterceptor.create,
|
|
55
|
+
{
|
|
56
|
+
version: pkg.version,
|
|
57
|
+
config: {
|
|
58
|
+
proxy: 'http://proxy.company.com'
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
[]
|
|
62
|
+
);
|
|
63
|
+
const options = {};
|
|
64
|
+
|
|
65
|
+
interceptor.onRequest(options);
|
|
66
|
+
|
|
67
|
+
assert.isUndefined(options.proxy);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -268,12 +268,58 @@ describe('webex-core', () => {
|
|
|
268
268
|
});
|
|
269
269
|
});
|
|
270
270
|
|
|
271
|
+
describe('#switchActiveClusterIds', () => {
|
|
272
|
+
let serviceHostmap;
|
|
273
|
+
let formattedHM;
|
|
274
|
+
|
|
275
|
+
beforeEach(() => {
|
|
276
|
+
serviceHostmap = serviceHostmapV2;
|
|
277
|
+
formattedHM = services._formatReceivedHostmap(serviceHostmap);
|
|
278
|
+
|
|
279
|
+
services.initServiceCatalogs = sinon.stub().returns(Promise.resolve());
|
|
280
|
+
services.webex.credentials = {
|
|
281
|
+
getOrgId: sinon.stub().returns('')
|
|
282
|
+
};
|
|
283
|
+
catalog.status = {};
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('switches properly when id exists', async () => {
|
|
287
|
+
services._updateActiveServices = sinon.stub().callsFake((data) => {
|
|
288
|
+
Object.assign(services._activeServices, data);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
await services.switchActiveClusterIds({
|
|
292
|
+
conversation: 'urn:TEAM:me-central-1_d:conversation',
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
296
|
+
|
|
297
|
+
assert.calledWith(services._updateActiveServices, {
|
|
298
|
+
conversation: 'urn:TEAM:me-central-1_d:conversation',
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
assert.equal(services._activeServices.conversation, 'urn:TEAM:me-central-1_d:conversation');
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('makes request to fetch when id does not exist', async () => {
|
|
305
|
+
services._updateActiveServices = sinon.stub().callsFake((data) => {
|
|
306
|
+
Object.assign(services._activeServices, data);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
await services.switchActiveClusterIds({
|
|
310
|
+
conversation: 'urn:TEAM:me-central-1_asdf:conversation',
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
|
|
271
317
|
describe('#updateCatalog', () => {
|
|
272
318
|
it('updates the catalog', async () => {
|
|
273
319
|
const serviceGroup = 'postauth';
|
|
274
|
-
const hostmap = [{hostmap: 'hostmap'}];
|
|
320
|
+
const hostmap = {services: [{hostmap: 'hostmap'}]};
|
|
275
321
|
|
|
276
|
-
services._formatReceivedHostmap = sinon.stub().returns([{some: 'hostmap'}]);
|
|
322
|
+
services._formatReceivedHostmap = sinon.stub().returns({services : [{some: 'hostmap'}]});
|
|
277
323
|
|
|
278
324
|
catalog.updateServiceGroups = sinon.stub().returns(Promise.resolve([{some: 'value'}]));
|
|
279
325
|
|
|
@@ -401,7 +447,7 @@ describe('webex-core', () => {
|
|
|
401
447
|
formattedHM = services._formatReceivedHostmap(serviceHostmap);
|
|
402
448
|
|
|
403
449
|
assert(
|
|
404
|
-
serviceHostmap.services.length >= formattedHM.length,
|
|
450
|
+
serviceHostmap.services.length >= formattedHM.services.length,
|
|
405
451
|
'length is not equal or less than'
|
|
406
452
|
);
|
|
407
453
|
});
|
|
@@ -409,7 +455,7 @@ describe('webex-core', () => {
|
|
|
409
455
|
it('has all keys in host map hosts', () => {
|
|
410
456
|
formattedHM = services._formatReceivedHostmap(serviceHostmap);
|
|
411
457
|
|
|
412
|
-
formattedHM.forEach((service) => {
|
|
458
|
+
formattedHM.services.forEach((service) => {
|
|
413
459
|
assert.hasAllKeys(
|
|
414
460
|
service,
|
|
415
461
|
['id', 'serviceName', 'serviceUrls'],
|
|
@@ -428,7 +474,7 @@ describe('webex-core', () => {
|
|
|
428
474
|
it('creates a formmated host map containing all received host map service entries', () => {
|
|
429
475
|
formattedHM = services._formatReceivedHostmap(serviceHostmap);
|
|
430
476
|
|
|
431
|
-
formattedHM.forEach((service) => {
|
|
477
|
+
formattedHM.services.forEach((service) => {
|
|
432
478
|
const foundServiceKey = Object.keys(serviceHostmap.activeServices).find(
|
|
433
479
|
(key) => service.serviceName === key
|
|
434
480
|
);
|
|
@@ -440,7 +486,7 @@ describe('webex-core', () => {
|
|
|
440
486
|
it('creates the expected formatted host map', () => {
|
|
441
487
|
formattedHM = services._formatReceivedHostmap(serviceHostmap);
|
|
442
488
|
|
|
443
|
-
assert.deepEqual(formattedHM, formattedServiceHostmapV2);
|
|
489
|
+
assert.deepEqual(formattedHM.services, formattedServiceHostmapV2);
|
|
444
490
|
});
|
|
445
491
|
|
|
446
492
|
it('has hostCatalog updated', () => {
|
|
@@ -512,5 +558,142 @@ describe('webex-core', () => {
|
|
|
512
558
|
assert.equal(webex.config.credentials.authorizeUrl, authUrl);
|
|
513
559
|
});
|
|
514
560
|
});
|
|
561
|
+
|
|
562
|
+
describe('#invalidateCache', () => {
|
|
563
|
+
beforeEach( () => {
|
|
564
|
+
services.initServiceCatalogs = sinon.stub().returns(Promise.resolve());
|
|
565
|
+
services.webex.credentials = {
|
|
566
|
+
getOrgId: sinon.stub().returns('')
|
|
567
|
+
};
|
|
568
|
+
catalog.status = {};
|
|
569
|
+
})
|
|
570
|
+
it('should log the timestamp parameter', async () => {
|
|
571
|
+
const timestamp = '1234567890';
|
|
572
|
+
services.logger.info = sinon.stub();
|
|
573
|
+
services._getCatalog = sinon.stub().returns({timestamp: '1234567880'});
|
|
574
|
+
|
|
575
|
+
await services.invalidateCache(timestamp);
|
|
576
|
+
|
|
577
|
+
assert.calledWith(services.logger.info, 'services: invalidate cache, timestamp:', timestamp);
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
it('should call initServiceCatalogs when invalidate timestamp is newer than catalog timestamp', async () => {
|
|
581
|
+
const newTimestamp = '1234567890';
|
|
582
|
+
const oldTimestamp = '1234567880';
|
|
583
|
+
services.logger.info = sinon.stub();
|
|
584
|
+
services._getCatalog = sinon.stub().returns({timestamp: oldTimestamp});
|
|
585
|
+
|
|
586
|
+
await services.invalidateCache(newTimestamp);
|
|
587
|
+
|
|
588
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
589
|
+
assert.calledWith(services.logger.info, 'services: invalidateCache, refresh services');
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
it('should not call initServiceCatalogs when invalidate timestamp is older than catalog timestamp', async () => {
|
|
593
|
+
const oldTimestamp = '1234567880';
|
|
594
|
+
const newTimestamp = '1234567890';
|
|
595
|
+
services._getCatalog = sinon.stub().returns({timestamp: newTimestamp});
|
|
596
|
+
await services.invalidateCache(oldTimestamp);
|
|
597
|
+
|
|
598
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
it('should not call initServiceCatalogs when invalidate timestamp equals catalog timestamp', async () => {
|
|
602
|
+
const timestamp = '1234567890';
|
|
603
|
+
services._getCatalog = sinon.stub().returns({timestamp: timestamp});
|
|
604
|
+
|
|
605
|
+
await services.invalidateCache(timestamp);
|
|
606
|
+
|
|
607
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
it('should handle numeric timestamp strings correctly', async () => {
|
|
611
|
+
const newTimestamp = '1700000000';
|
|
612
|
+
const oldTimestamp = '1600000000';
|
|
613
|
+
services._getCatalog = sinon.stub().returns({timestamp: oldTimestamp});
|
|
614
|
+
|
|
615
|
+
await services.invalidateCache(newTimestamp);
|
|
616
|
+
|
|
617
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
it('should handle undefined catalog gracefully', async () => {
|
|
621
|
+
const timestamp = '1234567890';
|
|
622
|
+
services._getCatalog = sinon.stub().returns(undefined);
|
|
623
|
+
|
|
624
|
+
await services.invalidateCache(timestamp);
|
|
625
|
+
|
|
626
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
it('should handle catalog without timestamp gracefully', async () => {
|
|
630
|
+
const timestamp = '1234567890';
|
|
631
|
+
services._getCatalog = sinon.stub().returns({});
|
|
632
|
+
|
|
633
|
+
await services.invalidateCache(timestamp);
|
|
634
|
+
|
|
635
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
it('should handle null catalog timestamp gracefully', async () => {
|
|
639
|
+
const timestamp = '1234567890';
|
|
640
|
+
services._getCatalog = sinon.stub().returns({timestamp: null});
|
|
641
|
+
|
|
642
|
+
await services.invalidateCache(timestamp);
|
|
643
|
+
|
|
644
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
it('should handle undefined timestamp parameter gracefully', async () => {
|
|
648
|
+
services._getCatalog = sinon.stub().returns({timestamp: '1234567890'});
|
|
649
|
+
|
|
650
|
+
await services.invalidateCache(undefined);
|
|
651
|
+
|
|
652
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
it('should handle null timestamp parameter gracefully', async () => {
|
|
656
|
+
services._getCatalog = sinon.stub().returns({timestamp: '1234567890'});
|
|
657
|
+
|
|
658
|
+
await services.invalidateCache(null);
|
|
659
|
+
|
|
660
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
it('should handle empty string timestamp parameter gracefully', async () => {
|
|
664
|
+
services._getCatalog = sinon.stub().returns({timestamp: '1234567890'});
|
|
665
|
+
|
|
666
|
+
await services.invalidateCache('');
|
|
667
|
+
|
|
668
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
it('should handle non-numeric timestamp strings gracefully', async () => {
|
|
672
|
+
const invalidTimestamp = 'not-a-number';
|
|
673
|
+
services._getCatalog = sinon.stub().returns({timestamp: '1234567890'});
|
|
674
|
+
|
|
675
|
+
await services.invalidateCache(invalidTimestamp);
|
|
676
|
+
|
|
677
|
+
assert.notCalled(services.initServiceCatalogs);
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
it('should handle non-numeric catalog timestamp gracefully', async () => {
|
|
681
|
+
const timestamp = '1234567890';
|
|
682
|
+
services._getCatalog = sinon.stub().returns({timestamp: 'not-a-number'});
|
|
683
|
+
|
|
684
|
+
await services.invalidateCache(timestamp);
|
|
685
|
+
|
|
686
|
+
assert.calledOnce(services.initServiceCatalogs);
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
it('should return a resolved Promise', async () => {
|
|
690
|
+
const timestamp = '1234567890';
|
|
691
|
+
services._getCatalog = sinon.stub().returns({timestamp: '1234567880'});
|
|
692
|
+
|
|
693
|
+
const result = await services.invalidateCache(timestamp);
|
|
694
|
+
|
|
695
|
+
assert.isUndefined(result);
|
|
696
|
+
});
|
|
697
|
+
});
|
|
515
698
|
});
|
|
516
699
|
});
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import {EventEmitter} from 'events';
|
|
5
6
|
import {assert} from '@webex/test-helper-chai';
|
|
6
7
|
import sinon from 'sinon';
|
|
7
8
|
import WebexCore, {
|
|
@@ -13,6 +14,7 @@ import WebexCore, {
|
|
|
13
14
|
} from '@webex/webex-core';
|
|
14
15
|
import {set} from 'lodash';
|
|
15
16
|
import {version} from '@webex/webex-core/package';
|
|
17
|
+
import {proxyEvents} from '@webex/common/src/events';
|
|
16
18
|
// TODO: fix circular dependency core->metrics->core https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-515520
|
|
17
19
|
require('@webex/internal-plugin-metrics');
|
|
18
20
|
|
|
@@ -177,11 +179,11 @@ describe('Webex', () => {
|
|
|
177
179
|
|
|
178
180
|
describe('initializes with interceptors', () => {
|
|
179
181
|
[
|
|
180
|
-
// 4 pre, 4 post,
|
|
182
|
+
// 4 pre, 4 post, 10 remaining default = 18
|
|
181
183
|
[
|
|
182
184
|
'defaults to existing interceptors if undefined',
|
|
183
185
|
undefined,
|
|
184
|
-
|
|
186
|
+
18,
|
|
185
187
|
[
|
|
186
188
|
'RequestTimingInterceptor',
|
|
187
189
|
'RequestEventInterceptor',
|
|
@@ -189,6 +191,7 @@ describe('Webex', () => {
|
|
|
189
191
|
'RateLimitInterceptor',
|
|
190
192
|
'ServiceInterceptor',
|
|
191
193
|
'UserAgentInterceptor',
|
|
194
|
+
'ProxyInterceptor',
|
|
192
195
|
'WebexUserAgentInterceptor',
|
|
193
196
|
'AuthInterceptor',
|
|
194
197
|
'PayloadTransformerInterceptor',
|
|
@@ -263,6 +266,63 @@ describe('Webex', () => {
|
|
|
263
266
|
});
|
|
264
267
|
});
|
|
265
268
|
|
|
269
|
+
describe('#upload()', () => {
|
|
270
|
+
it('rejects when no object is specified', () => {
|
|
271
|
+
return webex.upload().catch((err) => {
|
|
272
|
+
assert.equal(err.message, '`options.file` is required');
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it('rejects when no file is specified', () => {
|
|
277
|
+
return webex.upload({}).catch((err) => {
|
|
278
|
+
assert.equal(err.message, '`options.file` is required');
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('passes through progress events to caller', () => {
|
|
283
|
+
const uploadEventEmitter = new EventEmitter();
|
|
284
|
+
|
|
285
|
+
webex._uploadPhaseInitialize = sinon.stub().callsFake(() => {
|
|
286
|
+
return Promise.resolve();
|
|
287
|
+
});
|
|
288
|
+
webex._uploadPhaseUpload = sinon.stub().callsFake(() => {
|
|
289
|
+
const promise = Promise.resolve();
|
|
290
|
+
|
|
291
|
+
proxyEvents(uploadEventEmitter, promise);
|
|
292
|
+
|
|
293
|
+
return promise;
|
|
294
|
+
});
|
|
295
|
+
webex._uploadPhaseFinalize = sinon.stub().callsFake(() => {
|
|
296
|
+
return Promise.resolve({
|
|
297
|
+
body: {
|
|
298
|
+
url: 'https://example.com/download',
|
|
299
|
+
},
|
|
300
|
+
headers: {
|
|
301
|
+
'Content-Type': 'image/png',
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
const uploader = webex.upload({file: {}});
|
|
307
|
+
|
|
308
|
+
assert.isFunction(uploader.on);
|
|
309
|
+
|
|
310
|
+
return uploader.then((res) => {
|
|
311
|
+
const progressStub = sinon.stub();
|
|
312
|
+
uploader.on('progress', progressStub);
|
|
313
|
+
|
|
314
|
+
uploadEventEmitter.emit('progress', {percent: 25});
|
|
315
|
+
|
|
316
|
+
assert.isTrue(progressStub.calledOnce);
|
|
317
|
+
assert.isTrue(webex._uploadPhaseInitialize.calledOnce);
|
|
318
|
+
assert.isTrue(webex._uploadPhaseUpload.calledOnce);
|
|
319
|
+
assert.isTrue(webex._uploadPhaseFinalize.calledOnce);
|
|
320
|
+
assert.equal(res.url, 'https://example.com/download');
|
|
321
|
+
assert.equal(res['Content-Type'], 'image/png');
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
|
|
266
326
|
it('emits the `loaded` event when the storage layer has loaded all data', () => {
|
|
267
327
|
// I'd love to do this with mock webex, or at least, a mock plugin, but I
|
|
268
328
|
// couldn't get it to work. We do get better coverage this way, but it means
|