@webex/webex-core 3.11.0-webex-services-ready.1 → 3.12.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.
@@ -34,53 +34,6 @@ describe('webex-core', () => {
34
34
  });
35
35
 
36
36
  describe('#initialize', () => {
37
- it('listens for "loaded" event instead of "ready" to avoid deadlock', () => {
38
- services.listenToOnce = sinon.stub();
39
- services.initialize();
40
-
41
- // Second listenToOnce call should be for 'loaded' event
42
- assert.equal(services.listenToOnce.getCall(1).args[1], 'loaded');
43
- });
44
-
45
- it('services.ready starts as false', () => {
46
- assert.isFalse(services.ready);
47
- });
48
-
49
- it('sets ready to true and triggers services:initialized when initialization succeeds with credentials', async () => {
50
- services.listenToOnce = sinon.stub();
51
- services.initServiceCatalogs = sinon.stub().returns(Promise.resolve());
52
- services.trigger = sinon.stub();
53
- services.webex.credentials = {
54
- supertoken: {
55
- access_token: 'token',
56
- },
57
- };
58
-
59
- services.initialize();
60
-
61
- // call the onLoaded callback
62
- services.listenToOnce.getCall(1).args[2]();
63
- await waitForAsync();
64
-
65
- assert.isTrue(services.ready);
66
- sinon.assert.calledWith(services.trigger, 'services:initialized');
67
- });
68
-
69
- it('sets ready to true and triggers services:initialized when initialization succeeds without credentials', async () => {
70
- services.listenToOnce = sinon.stub();
71
- services.collectPreauthCatalog = sinon.stub().returns(Promise.resolve());
72
- services.trigger = sinon.stub();
73
-
74
- services.initialize();
75
-
76
- // call the onLoaded callback
77
- services.listenToOnce.getCall(1).args[2]();
78
- await waitForAsync();
79
-
80
- assert.isTrue(services.ready);
81
- sinon.assert.calledWith(services.trigger, 'services:initialized');
82
- });
83
-
84
37
  it('initFailed is false when initialization succeeds and credentials are available', async () => {
85
38
  services.listenToOnce = sinon.stub();
86
39
  services.initServiceCatalogs = sinon.stub().returns(Promise.resolve());
@@ -92,7 +45,7 @@ describe('webex-core', () => {
92
45
 
93
46
  services.initialize();
94
47
 
95
- // call the onLoaded callback
48
+ // call the onReady callback
96
49
  services.listenToOnce.getCall(1).args[2]();
97
50
  await waitForAsync();
98
51
 
@@ -105,7 +58,7 @@ describe('webex-core', () => {
105
58
 
106
59
  services.initialize();
107
60
 
108
- // call the onLoaded callback
61
+ // call the onReady callback
109
62
  services.listenToOnce.getCall(1).args[2]();
110
63
  await waitForAsync();
111
64
 
@@ -116,7 +69,7 @@ describe('webex-core', () => {
116
69
  {error: new Error('failed'), expectedMessage: 'failed'},
117
70
  {error: undefined, expectedMessage: undefined},
118
71
  ])(
119
- 'sets initFailed to true when collectPreauthCatalog errors but still sets ready to true',
72
+ 'sets initFailed to true when collectPreauthCatalog errors',
120
73
  async ({error, expectedMessage}) => {
121
74
  services.collectPreauthCatalog = sinon.stub().callsFake(() => {
122
75
  return Promise.reject(error);
@@ -124,18 +77,15 @@ describe('webex-core', () => {
124
77
 
125
78
  services.listenToOnce = sinon.stub();
126
79
  services.logger.error = sinon.stub();
127
- services.trigger = sinon.stub();
128
80
 
129
81
  services.initialize();
130
82
 
131
- // call the onLoaded callback
83
+ // call the onReady callback
132
84
  services.listenToOnce.getCall(1).args[2]();
133
85
 
134
86
  await waitForAsync();
135
87
 
136
88
  assert.isTrue(services.initFailed);
137
- assert.isTrue(services.ready);
138
- sinon.assert.calledWith(services.trigger, 'services:initialized');
139
89
  sinon.assert.calledWith(
140
90
  services.logger.error,
141
91
  `services: failed to init initial services when no credentials available, ${expectedMessage}`
@@ -147,7 +97,7 @@ describe('webex-core', () => {
147
97
  {error: new Error('failed'), expectedMessage: 'failed'},
148
98
  {error: undefined, expectedMessage: undefined},
149
99
  ])(
150
- 'sets initFailed to true when initServiceCatalogs errors but still sets ready to true',
100
+ 'sets initFailed to true when initServiceCatalogs errors',
151
101
  async ({error, expectedMessage}) => {
152
102
  services.initServiceCatalogs = sinon.stub().callsFake(() => {
153
103
  return Promise.reject(error);
@@ -160,118 +110,21 @@ describe('webex-core', () => {
160
110
 
161
111
  services.listenToOnce = sinon.stub();
162
112
  services.logger.error = sinon.stub();
163
- services.trigger = sinon.stub();
164
113
 
165
114
  services.initialize();
166
115
 
167
- // call the onLoaded callback
116
+ // call the onReady callback
168
117
  services.listenToOnce.getCall(1).args[2]();
169
118
 
170
119
  await waitForAsync();
171
120
 
172
121
  assert.isTrue(services.initFailed);
173
- assert.isTrue(services.ready);
174
- sinon.assert.calledWith(services.trigger, 'services:initialized');
175
122
  sinon.assert.calledWith(
176
123
  services.logger.error,
177
124
  `services: failed to init initial services when credentials available, ${expectedMessage}`
178
125
  );
179
126
  }
180
127
  );
181
-
182
- describe('when change:canAuthorize fires', () => {
183
- it('calls initServiceCatalogs when canAuthorize becomes true and postauth catalog is not ready', async () => {
184
- services.listenToOnce = sinon.stub();
185
- services._loadCatalogFromCache = sinon.stub().returns(Promise.resolve(false));
186
- services.collectPreauthCatalog = sinon.stub().returns(Promise.resolve());
187
- services.initServiceCatalogs = sinon.stub().returns(Promise.resolve());
188
- services.trigger = sinon.stub();
189
- // Ensure no credentials so we go to the preauth path
190
- services.webex.credentials = {};
191
-
192
- services.initialize();
193
-
194
- // Get the catalog after initialize creates it
195
- const testCatalog = services._getCatalog();
196
- testCatalog.status.postauth.ready = false;
197
-
198
- // call the onLoaded callback (preauth path)
199
- services.listenToOnce.getCall(1).args[2]();
200
- await waitForAsync();
201
-
202
- // Now set canAuthorize to true to simulate auth completing
203
- services.webex.canAuthorize = true;
204
-
205
- // call the change:canAuthorize callback (should be call 2)
206
- services.listenToOnce.getCall(2).args[2]();
207
- await waitForAsync();
208
-
209
- sinon.assert.calledOnce(services.initServiceCatalogs);
210
- assert.isTrue(testCatalog.isReady);
211
- });
212
-
213
- it('does not call initServiceCatalogs when postauth catalog is already ready', async () => {
214
- services.listenToOnce = sinon.stub();
215
- services._loadCatalogFromCache = sinon.stub().returns(Promise.resolve(false));
216
- services.collectPreauthCatalog = sinon.stub().returns(Promise.resolve());
217
- services.initServiceCatalogs = sinon.stub().returns(Promise.resolve());
218
- services.trigger = sinon.stub();
219
- // Ensure no credentials so we go to the preauth path
220
- services.webex.credentials = {};
221
-
222
- services.initialize();
223
-
224
- // Get the catalog after initialize creates it
225
- const testCatalog = services._getCatalog();
226
-
227
- // call the onLoaded callback (preauth path)
228
- services.listenToOnce.getCall(1).args[2]();
229
- await waitForAsync();
230
-
231
- // Set canAuthorize to true and postauth as ready BEFORE calling the callback
232
- services.webex.canAuthorize = true;
233
- testCatalog.status.postauth.ready = true;
234
-
235
- // call the change:canAuthorize callback (should be call 2)
236
- services.listenToOnce.getCall(2).args[2]();
237
- await waitForAsync();
238
-
239
- sinon.assert.notCalled(services.initServiceCatalogs);
240
- });
241
-
242
- it('logs an error when initServiceCatalogs fails after auth', async () => {
243
- services.listenToOnce = sinon.stub();
244
- services._loadCatalogFromCache = sinon.stub().returns(Promise.resolve(false));
245
- services.collectPreauthCatalog = sinon.stub().returns(Promise.resolve());
246
- services.initServiceCatalogs = sinon.stub().rejects(new Error('auth failed'));
247
- services.logger.error = sinon.stub();
248
- services.trigger = sinon.stub();
249
- // Ensure no credentials so we go to the preauth path
250
- services.webex.credentials = {};
251
-
252
- services.initialize();
253
-
254
- // Get the catalog after initialize creates it
255
- const testCatalog = services._getCatalog();
256
- testCatalog.status.postauth.ready = false;
257
-
258
- // call the onLoaded callback (preauth path)
259
- services.listenToOnce.getCall(1).args[2]();
260
- await waitForAsync();
261
-
262
- // Now set canAuthorize to true to simulate auth completing
263
- services.webex.canAuthorize = true;
264
-
265
- // call the change:canAuthorize callback (should be call 2)
266
- services.listenToOnce.getCall(2).args[2]();
267
- await waitForAsync();
268
-
269
- sinon.assert.calledWith(
270
- services.logger.error,
271
- 'services: failed to init service catalogs after auth, auth failed'
272
- );
273
- });
274
- });
275
128
  });
276
129
 
277
130
  describe('#initServiceCatalogs', () => {
@@ -425,7 +278,7 @@ describe('webex-core', () => {
425
278
 
426
279
  services.initServiceCatalogs = sinon.stub().returns(Promise.resolve());
427
280
  services.webex.credentials = {
428
- getOrgId: sinon.stub().returns(''),
281
+ getOrgId: sinon.stub().returns('')
429
282
  };
430
283
  catalog.status = {};
431
284
  });
@@ -466,7 +319,7 @@ describe('webex-core', () => {
466
319
  const serviceGroup = 'postauth';
467
320
  const hostmap = {services: [{hostmap: 'hostmap'}]};
468
321
 
469
- services._formatReceivedHostmap = sinon.stub().returns({services: [{some: 'hostmap'}]});
322
+ services._formatReceivedHostmap = sinon.stub().returns({services : [{some: 'hostmap'}]});
470
323
 
471
324
  catalog.updateServiceGroups = sinon.stub().returns(Promise.resolve([{some: 'value'}]));
472
325
 
@@ -482,7 +335,7 @@ describe('webex-core', () => {
482
335
  const serviceGroup = 'postauth';
483
336
  const hostmap = {};
484
337
 
485
- services._formatReceivedHostmap = sinon.stub().returns({services: undefined});
338
+ services._formatReceivedHostmap = sinon.stub().returns({services : undefined});
486
339
 
487
340
  catalog.updateServiceGroups = sinon.stub().returns(Promise.resolve([{some: 'value'}]));
488
341
 
@@ -721,13 +574,13 @@ describe('webex-core', () => {
721
574
  });
722
575
 
723
576
  describe('#invalidateCache', () => {
724
- beforeEach(() => {
577
+ beforeEach( () => {
725
578
  services.initServiceCatalogs = sinon.stub().returns(Promise.resolve());
726
579
  services.webex.credentials = {
727
- getOrgId: sinon.stub().returns(''),
580
+ getOrgId: sinon.stub().returns('')
728
581
  };
729
582
  catalog.status = {};
730
- });
583
+ })
731
584
  it('should log the timestamp parameter', async () => {
732
585
  const timestamp = '1234567890';
733
586
  services.logger.info = sinon.stub();
@@ -735,11 +588,7 @@ describe('webex-core', () => {
735
588
 
736
589
  await services.invalidateCache(timestamp);
737
590
 
738
- assert.calledWith(
739
- services.logger.info,
740
- 'services: invalidate cache, timestamp:',
741
- timestamp
742
- );
591
+ assert.calledWith(services.logger.info, 'services: invalidate cache, timestamp:', timestamp);
743
592
  });
744
593
 
745
594
  it('should call initServiceCatalogs when invalidate timestamp is newer than catalog timestamp', async () => {
@@ -866,30 +715,30 @@ describe('webex-core', () => {
866
715
  // Arrange: seed internal _services with mobius (including duplicate baseUrl)
867
716
  services._services = [
868
717
  {
869
- id: 'urn:TEAM:us-east-2_a:mobius',
870
- serviceName: 'mobius',
871
- serviceUrls: [
872
- {baseUrl: 'https://mobius-us-east-2.prod.infra.webex.com/api/v1', priority: 5},
873
- {baseUrl: 'https://mobius-eu-central-1.prod.infra.webex.com/api/v1', priority: 10},
874
- {baseUrl: 'https://mobius-ap-southeast-2.prod.infra.webex.com/api/v1', priority: 15}, // duplicate
718
+ "id": "urn:TEAM:us-east-2_a:mobius",
719
+ "serviceName": 'mobius',
720
+ "serviceUrls": [
721
+ {"baseUrl": 'https://mobius-us-east-2.prod.infra.webex.com/api/v1', "priority": 5},
722
+ {"baseUrl": 'https://mobius-eu-central-1.prod.infra.webex.com/api/v1', "priority": 10},
723
+ {"baseUrl": 'https://mobius-ap-southeast-2.prod.infra.webex.com/api/v1', "priority": 15}, // duplicate
875
724
  ],
876
725
  },
877
726
  {
878
- id: 'urn:TEAM:ap-southeast-2_m:mobius',
879
- serviceName: 'mobius',
880
- serviceUrls: [
881
- {
882
- baseUrl: 'https://mobius-me-central-1.prod.infra.webex.com/api/v1',
883
- priority: 5,
884
- },
885
- {
886
- baseUrl: 'https://mobius-eu-central-1.prod.infra.webex.com/api/v1',
887
- priority: 10,
888
- },
889
- {
890
- baseUrl: 'https://mobius-ap-southeast-2.prod.infra.webex.com/api/v1',
891
- priority: 15,
892
- },
727
+ "id": "urn:TEAM:ap-southeast-2_m:mobius",
728
+ "serviceName": "mobius",
729
+ "serviceUrls": [
730
+ {
731
+ "baseUrl": "https://mobius-me-central-1.prod.infra.webex.com/api/v1",
732
+ "priority": 5
733
+ },
734
+ {
735
+ "baseUrl": "https://mobius-eu-central-1.prod.infra.webex.com/api/v1",
736
+ "priority": 10
737
+ },
738
+ {
739
+ "baseUrl": "https://mobius-ap-southeast-2.prod.infra.webex.com/api/v1",
740
+ "priority": 15
741
+ },
893
742
  ],
894
743
  },
895
744
  // Non-mobius service should be ignored by getMobiusClusters
@@ -907,64 +756,42 @@ describe('webex-core', () => {
907
756
  assert.deepEqual(
908
757
  clusters.map(({host, id, ttl, priority}) => ({host, id, ttl, priority})),
909
758
  [
910
- {
911
- host: 'mobius-us-east-2.prod.infra.webex.com',
912
- id: 'urn:TEAM:us-east-2_a:mobius',
913
- ttl: 0,
914
- priority: 5,
915
- },
916
- {
917
- host: 'mobius-eu-central-1.prod.infra.webex.com',
918
- id: 'urn:TEAM:us-east-2_a:mobius',
919
- ttl: 0,
920
- priority: 10,
921
- },
922
- {
923
- host: 'mobius-ap-southeast-2.prod.infra.webex.com',
924
- id: 'urn:TEAM:us-east-2_a:mobius',
925
- ttl: 0,
926
- priority: 15,
927
- },
928
- {
929
- host: 'mobius-me-central-1.prod.infra.webex.com',
930
- id: 'urn:TEAM:ap-southeast-2_m:mobius',
931
- ttl: 0,
932
- priority: 5,
933
- },
759
+ {host: 'mobius-us-east-2.prod.infra.webex.com', id: 'urn:TEAM:us-east-2_a:mobius', ttl: 0, priority: 5},
760
+ {host: 'mobius-eu-central-1.prod.infra.webex.com', id: 'urn:TEAM:us-east-2_a:mobius', ttl: 0, priority: 10},
761
+ {host: 'mobius-ap-southeast-2.prod.infra.webex.com', id: 'urn:TEAM:us-east-2_a:mobius', ttl: 0, priority: 15},
762
+ {host: 'mobius-me-central-1.prod.infra.webex.com', id: 'urn:TEAM:ap-southeast-2_m:mobius', ttl: 0, priority: 5},
934
763
  ]
935
764
  );
936
765
  });
937
766
  });
938
-
767
+
939
768
  describe('#isValidHost', () => {
940
769
  beforeEach(() => {
941
770
  // Setting up a mock services list
942
- services._services = [
943
- {
944
- id: 'urn:IDENTITY:PC75:adminAudit',
945
- serviceName: 'adminAudit',
946
- serviceUrls: [
947
- {
948
- baseUrl: 'https://audit-ci-r.wbx2.com/audit-ci/api/v2',
949
- priority: 5,
950
- },
951
- {
952
- baseUrl: 'https://audit-ci-t.wbx2.com/audit-ci/api/v2',
953
- priority: 10,
954
- },
955
- ],
956
- },
957
- {
958
- id: 'urn:IDENTITY:PC75:cdf',
959
- serviceName: 'cdf',
960
- serviceUrls: [
961
- {
962
- baseUrl: 'https://wapdavis.webex.com/davis/api/v1',
963
- priority: 5,
964
- },
965
- ],
966
- },
967
- ];
771
+ services._services = [{
772
+ "id": "urn:IDENTITY:PC75:adminAudit",
773
+ "serviceName": "adminAudit",
774
+ "serviceUrls": [
775
+ {
776
+ "baseUrl": "https://audit-ci-r.wbx2.com/audit-ci/api/v2",
777
+ "priority": 5
778
+ },
779
+ {
780
+ "baseUrl": "https://audit-ci-t.wbx2.com/audit-ci/api/v2",
781
+ "priority": 10
782
+ }
783
+ ]
784
+ },
785
+ {
786
+ "id": "urn:IDENTITY:PC75:cdf",
787
+ "serviceName": "cdf",
788
+ "serviceUrls": [
789
+ {
790
+ "baseUrl": "https://wapdavis.webex.com/davis/api/v1",
791
+ "priority": 5
792
+ }
793
+ ]
794
+ }];
968
795
  });
969
796
  afterAll(() => {
970
797
  // Clean up the mock services list
@@ -988,6 +815,57 @@ describe('webex-core', () => {
988
815
  });
989
816
  });
990
817
 
818
+ describe('#isIntegrationEnvironment', () => {
819
+ it('returns true when u2c URL contains "intb"', () => {
820
+ services.webex.config = {
821
+ services: {
822
+ discovery: {
823
+ u2c: 'https://u2c-intb.ciscospark.com/u2c/api/v1',
824
+ },
825
+ },
826
+ };
827
+ assert.isTrue(services.isIntegrationEnvironment());
828
+ });
829
+
830
+ it('returns false when u2c URL does not contain "intb" (production)', () => {
831
+ services.webex.config = {
832
+ services: {
833
+ discovery: {
834
+ u2c: 'https://u2c.wbx2.com/u2c/api/v1',
835
+ },
836
+ },
837
+ };
838
+ assert.isFalse(services.isIntegrationEnvironment());
839
+ });
840
+
841
+ it('returns false when u2c URL is for FedRAMP', () => {
842
+ services.webex.config = {
843
+ services: {
844
+ discovery: {
845
+ u2c: 'https://u2c.gov.ciscospark.com/u2c/api/v1',
846
+ },
847
+ },
848
+ };
849
+ assert.isFalse(services.isIntegrationEnvironment());
850
+ });
851
+
852
+ it('returns false when u2c URL is undefined', () => {
853
+ services.webex.config = {
854
+ services: {
855
+ discovery: {
856
+ u2c: undefined,
857
+ },
858
+ },
859
+ };
860
+ assert.isFalse(services.isIntegrationEnvironment());
861
+ });
862
+
863
+ it('returns false when config is not available', () => {
864
+ services.webex.config = undefined;
865
+ assert.isFalse(services.isIntegrationEnvironment());
866
+ });
867
+ });
868
+
991
869
  describe('U2C catalog cache behavior (v2)', () => {
992
870
  const CATALOG_CACHE_KEY_V2 = 'services.v2.u2cHostMap';
993
871
  let windowBackup;
@@ -397,8 +397,6 @@ describe('Webex', () => {
397
397
  return new Promise((resolve) => webex.once('loaded', resolve)).then(() => {
398
398
  assert.isFalse(webex.ready);
399
399
  assert.isFalse(webex.test.ready);
400
- // Set services.ready to true since it now blocks webex.ready
401
- webex.internal.services.ready = true;
402
400
  webex.test.ready = true;
403
401
  assert.isTrue(webex.test.ready);
404
402
  assert.isTrue(webex.ready);
@@ -82,8 +82,6 @@ describe('Webex', () => {
82
82
  assert.isFalse(webex.internal.test.ready);
83
83
  assert.isFalse(webex.internal.ready);
84
84
  assert.isFalse(webex.ready);
85
- // Set services.ready to true since it now blocks webex.ready
86
- webex.internal.services.ready = true;
87
85
  webex.internal.test.ready = true;
88
86
  assert.isTrue(webex.internal.ready);
89
87
  assert.isTrue(webex.ready);