@webex/webex-core 3.12.0-next.5 → 3.12.0-next.50

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.
Files changed (56) hide show
  1. package/README.md +5 -2
  2. package/dist/config.js +38 -0
  3. package/dist/config.js.map +1 -1
  4. package/dist/credentials-config.js +12 -0
  5. package/dist/credentials-config.js.map +1 -1
  6. package/dist/index.js +7 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/interceptors/catalog-url.js +87 -0
  9. package/dist/interceptors/catalog-url.js.map +1 -0
  10. package/dist/interceptors/payload-transformer.js +25 -4
  11. package/dist/interceptors/payload-transformer.js.map +1 -1
  12. package/dist/lib/batcher.js +23 -7
  13. package/dist/lib/batcher.js.map +1 -1
  14. package/dist/lib/credentials/credentials.js +103 -4
  15. package/dist/lib/credentials/credentials.js.map +1 -1
  16. package/dist/lib/credentials/token.js +1 -1
  17. package/dist/lib/domains.js +90 -0
  18. package/dist/lib/domains.js.map +1 -0
  19. package/dist/lib/services/service-catalog.js +108 -18
  20. package/dist/lib/services/service-catalog.js.map +1 -1
  21. package/dist/lib/services/services.js +232 -34
  22. package/dist/lib/services/services.js.map +1 -1
  23. package/dist/lib/services-v2/service-catalog.js +14 -13
  24. package/dist/lib/services-v2/service-catalog.js.map +1 -1
  25. package/dist/lib/services-v2/services-v2.js +241 -37
  26. package/dist/lib/services-v2/services-v2.js.map +1 -1
  27. package/dist/plugins/logger.js +1 -1
  28. package/dist/webex-core.js +11 -3
  29. package/dist/webex-core.js.map +1 -1
  30. package/package.json +13 -13
  31. package/src/config.js +42 -0
  32. package/src/credentials-config.js +13 -0
  33. package/src/index.js +1 -0
  34. package/src/interceptors/catalog-url.js +66 -0
  35. package/src/interceptors/payload-transformer.js +23 -1
  36. package/src/lib/batcher.js +25 -10
  37. package/src/lib/credentials/credentials.js +93 -3
  38. package/src/lib/domains.ts +94 -0
  39. package/src/lib/services/service-catalog.js +112 -16
  40. package/src/lib/services/services.js +208 -20
  41. package/src/lib/services-v2/service-catalog.ts +16 -12
  42. package/src/lib/services-v2/services-v2.ts +218 -21
  43. package/src/webex-core.js +8 -0
  44. package/test/fixtures/activation-email.ts +22 -0
  45. package/test/integration/spec/services/services.js +183 -112
  46. package/test/integration/spec/services-v2/services-v2.js +169 -98
  47. package/test/unit/spec/credentials/credentials.js +247 -3
  48. package/test/unit/spec/interceptors/auth.js +56 -0
  49. package/test/unit/spec/interceptors/catalog-url.js +224 -0
  50. package/test/unit/spec/interceptors/payload-transformer.js +119 -1
  51. package/test/unit/spec/lib/batcher.js +56 -0
  52. package/test/unit/spec/services/service-catalog.js +368 -11
  53. package/test/unit/spec/services/services.js +440 -2
  54. package/test/unit/spec/services-v2/service-catalog.ts +134 -11
  55. package/test/unit/spec/services-v2/services-v2.ts +467 -0
  56. package/test/unit/spec/webex-core.js +77 -1
@@ -5,7 +5,7 @@
5
5
  import '@webex/internal-plugin-device';
6
6
 
7
7
  import {assert} from '@webex/test-helper-chai';
8
- import {flaky} from '@webex/test-helper-mocha';
8
+ import {flaky, retryOn429} from '@webex/test-helper-mocha';
9
9
  import WebexCore, {
10
10
  ServiceCatalog,
11
11
  ServiceRegistry,
@@ -20,6 +20,7 @@ import WebexCore, {
20
20
  import testUsers from '@webex/test-helper-test-users';
21
21
  import uuid from 'uuid';
22
22
  import sinon from 'sinon';
23
+ import {createActivationEmail} from '../../../fixtures/activation-email';
23
24
 
24
25
  /* eslint-disable no-underscore-dangle */
25
26
  describe('webex-core', () => {
@@ -408,11 +409,13 @@ describe('webex-core', () => {
408
409
  services._loadCatalogFromCache = sinon.stub().resolves(false);
409
410
  services.initServiceCatalogs = sinon.stub().resolves();
410
411
  services.initialize();
412
+ // The mode-specific ('ready'/'loaded') listener is registered inside the
413
+ // change:config handler, so fire change:config first, then 'ready'.
414
+ webex.trigger('change:config');
411
415
  webex.trigger('ready');
412
416
  // Wait for the async 'ready' handler to complete
413
417
  await new Promise((resolve) => setTimeout(resolve, 50));
414
418
  assert.called(services.initServiceCatalogs);
415
- assert.isTrue(catalog.isReady);
416
419
  });
417
420
 
418
421
  it('should collect different catalogs based on OrgId region', () =>
@@ -430,6 +433,45 @@ describe('webex-core', () => {
430
433
  done();
431
434
  }, 2000);
432
435
  });
436
+
437
+ it('blocks webex.ready until services.ready flips when waitForCatalogInit is enabled', async () => {
438
+ const gatedWebex = new WebexCore({
439
+ credentials: {supertoken: webexUser.token},
440
+ config: {services: {waitForCatalogInit: true}},
441
+ });
442
+
443
+ // Before init settles, webex.ready must be false because services.ready
444
+ // is a dependency and starts false in the gated path.
445
+ assert.isFalse(gatedWebex.internal.services.ready, 'services.ready should start false');
446
+ assert.isFalse(
447
+ gatedWebex.ready,
448
+ 'webex.ready should not fire while services.ready is false'
449
+ );
450
+
451
+ // Wait up to 30s for services init to complete and flip ready.
452
+ await new Promise((resolve, reject) => {
453
+ if (gatedWebex.internal.services.ready) {
454
+ resolve();
455
+
456
+ return;
457
+ }
458
+ const timer = setTimeout(
459
+ () => reject(new Error('timed out waiting for services.ready')),
460
+ 30_000
461
+ );
462
+
463
+ gatedWebex.internal.services.once('change:ready', () => {
464
+ clearTimeout(timer);
465
+ resolve();
466
+ });
467
+ });
468
+
469
+ assert.isTrue(
470
+ gatedWebex.internal.services.ready,
471
+ 'services.ready should flip true after init settles'
472
+ );
473
+ assert.isTrue(gatedWebex.ready, 'webex.ready should fire once services.ready flips');
474
+ });
433
475
  });
434
476
 
435
477
  describe('#initServiceCatalogs()', () => {
@@ -867,18 +909,22 @@ describe('webex-core', () => {
867
909
  }));
868
910
 
869
911
  it('validates an authorized user and webex instance', () =>
870
- services.validateUser({email: webexUser.email}).then((r) => {
871
- assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
872
- assert.equal(r.activated, true);
873
- assert.equal(r.exists, true);
874
- }));
912
+ retryOn429(() =>
913
+ services.validateUser({email: webexUser.email}).then((r) => {
914
+ assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
915
+ assert.equal(r.activated, true);
916
+ assert.equal(r.exists, true);
917
+ })
918
+ ));
875
919
 
876
920
  it('validates an authorized EU user and webex instance', () =>
877
- servicesEU.validateUser({email: webexUserEU.email}).then((r) => {
878
- assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
879
- assert.equal(r.activated, true);
880
- assert.equal(r.exists, true);
881
- }));
921
+ retryOn429(() =>
922
+ servicesEU.validateUser({email: webexUserEU.email}).then((r) => {
923
+ assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
924
+ assert.equal(r.activated, true);
925
+ assert.equal(r.exists, true);
926
+ })
927
+ ));
882
928
 
883
929
  it("returns a rejected promise if the provided email isn't valid", () =>
884
930
  unauthServices
@@ -891,131 +937,152 @@ describe('webex-core', () => {
891
937
  }));
892
938
 
893
939
  it('validates a non-existing user', () =>
894
- unauthServices
895
- .validateUser({email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`})
896
- .then((r) => {
940
+ retryOn429(() =>
941
+ unauthServices.validateUser({email: createActivationEmail()}).then((r) => {
897
942
  assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
898
943
  assert.equal(r.activated, false);
899
944
  assert.equal(r.exists, false);
900
945
  assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
901
946
  assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
902
947
  assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
903
- }));
948
+ })
949
+ ));
904
950
 
905
951
  it('validates new user with activationOptions suppressEmail false', () =>
906
- unauthServices
907
- .validateUser({
908
- email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
909
- activationOptions: {suppressEmail: false},
910
- })
911
- .then((r) => {
912
- assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
913
- assert.equal(r.activated, false);
914
- assert.equal(r.exists, false);
915
- assert.equal(r.user.verificationEmailTriggered, true);
916
- assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
917
- assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
918
- assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
919
- }));
952
+ retryOn429(() =>
953
+ unauthServices
954
+ .validateUser({
955
+ email: createActivationEmail(),
956
+ activationOptions: {suppressEmail: false},
957
+ })
958
+ .then((r) => {
959
+ assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
960
+ assert.equal(r.activated, false);
961
+ assert.equal(r.exists, false);
962
+ assert.equal(r.user.verificationEmailTriggered, true);
963
+ assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
964
+ assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
965
+ assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
966
+ })
967
+ ));
920
968
 
921
969
  it('validates new user with activationOptions suppressEmail true', () =>
922
- unauthServices
923
- .validateUser({
924
- email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
925
- activationOptions: {suppressEmail: true},
926
- })
927
- .then((r) => {
928
- assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
929
- assert.equal(r.activated, false);
930
- assert.equal(r.exists, false);
931
- assert.equal(r.user.verificationEmailTriggered, false);
932
- assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
933
- assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
934
- assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
935
- }));
970
+ retryOn429(() =>
971
+ unauthServices
972
+ .validateUser({
973
+ email: createActivationEmail(),
974
+ activationOptions: {suppressEmail: true},
975
+ })
976
+ .then((r) => {
977
+ assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
978
+ assert.equal(r.activated, false);
979
+ assert.equal(r.exists, false);
980
+ assert.equal(r.user.verificationEmailTriggered, false);
981
+ assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
982
+ assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
983
+ assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
984
+ })
985
+ ));
936
986
 
937
987
  it('validates an inactive user', () => {
938
988
  const inactive = 'webex.web.client+nonactivated@gmail.com';
939
989
 
940
- return unauthServices
941
- .validateUser({email: inactive, activationOptions: {suppressEmail: true}})
942
- .then((r) => {
990
+ return retryOn429(() =>
991
+ unauthServices
992
+ .validateUser({email: inactive, activationOptions: {suppressEmail: true}})
993
+ .then((r) => {
994
+ assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
995
+ assert.equal(r.activated, false, 'activated');
996
+ assert.equal(r.exists, true, 'exists');
997
+ assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
998
+ assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
999
+ assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
1000
+ })
1001
+ ).catch(() => {
1002
+ assert(true);
1003
+ });
1004
+ });
1005
+
1006
+ it('validates an existing user', () =>
1007
+ retryOn429(() =>
1008
+ unauthServices.validateUser({email: webexUser.email}).then((r) => {
943
1009
  assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
944
- assert.equal(r.activated, false, 'activated');
945
- assert.equal(r.exists, true, 'exists');
1010
+ assert.equal(r.activated, true);
1011
+ assert.equal(r.exists, true);
946
1012
  assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
947
- assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
1013
+ assert.isAbove(Object.keys(unauthServices.list(false, 'signin')).length, 0);
948
1014
  assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
949
1015
  })
950
- .catch(() => {
951
- assert(true);
952
- });
953
- });
954
-
955
- it('validates an existing user', () =>
956
- unauthServices.validateUser({email: webexUser.email}).then((r) => {
957
- assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
958
- assert.equal(r.activated, true);
959
- assert.equal(r.exists, true);
960
- assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
961
- assert.isAbove(Object.keys(unauthServices.list(false, 'signin')).length, 0);
962
- assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
963
- }));
1016
+ ));
964
1017
 
965
1018
  it('validates an existing EU user', () =>
966
- unauthServices.validateUser({email: webexUserEU.email}).then((r) => {
967
- assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
968
- assert.equal(r.activated, true);
969
- assert.equal(r.exists, true);
970
- assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
971
- assert.isAbove(Object.keys(unauthServices.list(false, 'signin')).length, 0);
972
- assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
973
- }));
1019
+ retryOn429(() =>
1020
+ unauthServices.validateUser({email: webexUserEU.email}).then((r) => {
1021
+ assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
1022
+ assert.equal(r.activated, true);
1023
+ assert.equal(r.exists, true);
1024
+ assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
1025
+ assert.isAbove(Object.keys(unauthServices.list(false, 'signin')).length, 0);
1026
+ assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
1027
+ })
1028
+ ));
974
1029
 
975
1030
  it('sends the prelogin user id as undefined when not specified', () => {
976
1031
  const requestStub = sandbox.spy(unauthServices, 'request');
977
1032
 
978
- return unauthServices
979
- .validateUser({
980
- email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
981
- activationOptions: {suppressEmail: true},
982
- })
983
- .then(() => {
984
- assert.isUndefined(getActivationRequest(requestStub).headers['x-prelogin-userid']);
985
- });
1033
+ return retryOn429(() => {
1034
+ requestStub.resetHistory();
1035
+
1036
+ return unauthServices
1037
+ .validateUser({
1038
+ email: createActivationEmail(),
1039
+ activationOptions: {suppressEmail: true},
1040
+ })
1041
+ .then(() => {
1042
+ assert.isUndefined(getActivationRequest(requestStub).headers['x-prelogin-userid']);
1043
+ });
1044
+ });
986
1045
  });
987
1046
 
988
1047
  it('sends the prelogin user id as provided when specified', () => {
989
1048
  const requestStub = sandbox.spy(unauthServices, 'request');
990
1049
  const preloginUserId = uuid.v4();
991
1050
 
992
- return unauthServices
993
- .validateUser({
994
- email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
995
- activationOptions: {suppressEmail: true},
996
- preloginUserId,
997
- })
998
- .then(() => {
999
- assert.strictEqual(
1000
- getActivationRequest(requestStub).headers['x-prelogin-userid'],
1001
- preloginUserId
1002
- );
1003
- });
1051
+ return retryOn429(() => {
1052
+ requestStub.resetHistory();
1053
+
1054
+ return unauthServices
1055
+ .validateUser({
1056
+ email: createActivationEmail(),
1057
+ activationOptions: {suppressEmail: true},
1058
+ preloginUserId,
1059
+ })
1060
+ .then(() => {
1061
+ assert.strictEqual(
1062
+ getActivationRequest(requestStub).headers['x-prelogin-userid'],
1063
+ preloginUserId
1064
+ );
1065
+ });
1066
+ });
1004
1067
  });
1005
1068
 
1006
1069
  it('uses the license service by default', () => {
1007
1070
  const requestStub = sandbox.spy(unauthServices, 'request');
1008
1071
 
1009
- return unauthServices
1010
- .validateUser({
1011
- email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
1012
- activationOptions: {suppressEmail: true},
1013
- })
1014
- .then(() => {
1015
- const request = getActivationRequest(requestStub, false);
1016
- assert.strictEqual(request.service, 'license');
1017
- assert.strictEqual(request.resource, 'users/activations');
1018
- });
1072
+ return retryOn429(() => {
1073
+ requestStub.resetHistory();
1074
+
1075
+ return unauthServices
1076
+ .validateUser({
1077
+ email: createActivationEmail(),
1078
+ activationOptions: {suppressEmail: true},
1079
+ })
1080
+ .then(() => {
1081
+ const request = getActivationRequest(requestStub, false);
1082
+ assert.strictEqual(request.service, 'license');
1083
+ assert.strictEqual(request.resource, 'users/activations');
1084
+ });
1085
+ });
1019
1086
  });
1020
1087
 
1021
1088
  it('uses the user-onboarding service when useUserOnboardingServiceForActivations config is true', () => {
@@ -1029,16 +1096,20 @@ describe('webex-core', () => {
1029
1096
  const userOnboardingServices = userOnboardingWebex.internal.services;
1030
1097
  const requestStub = sandbox.spy(userOnboardingServices, 'request');
1031
1098
 
1032
- return userOnboardingServices
1033
- .validateUser({
1034
- email: `Collabctg+webex-js-sdk-${uuid.v4()}@gmail.com`,
1035
- activationOptions: {suppressEmail: true},
1036
- })
1037
- .then(() => {
1038
- const request = getActivationRequest(requestStub, true);
1039
- assert.strictEqual(request.service, 'user-onboarding');
1040
- assert.strictEqual(request.resource, 'api/v1/users/activations');
1041
- });
1099
+ return retryOn429(() => {
1100
+ requestStub.resetHistory();
1101
+
1102
+ return userOnboardingServices
1103
+ .validateUser({
1104
+ email: createActivationEmail(),
1105
+ activationOptions: {suppressEmail: true},
1106
+ })
1107
+ .then(() => {
1108
+ const request = getActivationRequest(requestStub, true);
1109
+ assert.strictEqual(request.service, 'user-onboarding');
1110
+ assert.strictEqual(request.resource, 'api/v1/users/activations');
1111
+ });
1112
+ });
1042
1113
  });
1043
1114
  });
1044
1115