@webex/calling 3.8.1-next.8 → 3.8.1-web-workers-keepalive.2

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 (29) hide show
  1. package/dist/CallingClient/CallingClient.test.js +8 -6
  2. package/dist/CallingClient/CallingClient.test.js.map +1 -1
  3. package/dist/CallingClient/line/line.test.js +4 -10
  4. package/dist/CallingClient/line/line.test.js.map +1 -1
  5. package/dist/CallingClient/registration/register.js +351 -345
  6. package/dist/CallingClient/registration/register.js.map +1 -1
  7. package/dist/CallingClient/registration/register.test.js +292 -263
  8. package/dist/CallingClient/registration/register.test.js.map +1 -1
  9. package/dist/CallingClient/registration/webWorker.js +115 -0
  10. package/dist/CallingClient/registration/webWorker.js.map +1 -0
  11. package/dist/CallingClient/registration/webWorker.test.js +256 -0
  12. package/dist/CallingClient/registration/webWorker.test.js.map +1 -0
  13. package/dist/CallingClient/registration/webWorkerStr.js +15 -0
  14. package/dist/CallingClient/registration/webWorkerStr.js.map +1 -0
  15. package/dist/common/types.js +8 -1
  16. package/dist/common/types.js.map +1 -1
  17. package/dist/module/CallingClient/registration/register.js +54 -54
  18. package/dist/module/CallingClient/registration/webWorker.js +59 -0
  19. package/dist/module/CallingClient/registration/webWorkerStr.js +93 -0
  20. package/dist/module/common/types.js +7 -0
  21. package/dist/types/CallingClient/registration/register.d.ts +1 -2
  22. package/dist/types/CallingClient/registration/register.d.ts.map +1 -1
  23. package/dist/types/CallingClient/registration/webWorker.d.ts +2 -0
  24. package/dist/types/CallingClient/registration/webWorker.d.ts.map +1 -0
  25. package/dist/types/CallingClient/registration/webWorkerStr.d.ts +3 -0
  26. package/dist/types/CallingClient/registration/webWorkerStr.d.ts.map +1 -0
  27. package/dist/types/common/types.d.ts +12 -0
  28. package/dist/types/common/types.d.ts.map +1 -1
  29. package/package.json +4 -3
@@ -702,16 +702,15 @@ describe('Registration Tests', function () {
702
702
  while (1) switch (_context13.prev = _context13.next) {
703
703
  case 0:
704
704
  /* keep keepalive as active so that it wont interfere with the failback tests */
705
- jest.spyOn(reg, 'postKeepAlive').mockResolvedValue(successPayload);
706
705
  jest.useFakeTimers();
707
706
  postRegistrationSpy.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockResolvedValueOnce(successPayload);
708
- _context13.next = 5;
707
+ _context13.next = 4;
709
708
  return reg.triggerRegistration();
710
- case 5:
709
+ case 4:
711
710
  jest.advanceTimersByTime(_constants.REG_TRY_BACKUP_TIMER_VAL_IN_SEC * _constants.SEC_TO_MSEC_MFACTOR);
712
- _context13.next = 8;
711
+ _context13.next = 7;
713
712
  return flushPromises();
714
- case 8:
713
+ case 7:
715
714
  reg.rehomingIntervalMin = _constants.DEFAULT_REHOMING_INTERVAL_MIN;
716
715
  reg.rehomingIntervalMax = _constants.DEFAULT_REHOMING_INTERVAL_MAX;
717
716
 
@@ -721,7 +720,7 @@ describe('Registration Tests', function () {
721
720
  /* Active Url must match with the backup url as per the test */
722
721
  expect(reg.getActiveMobiusUrl()).toStrictEqual(mobiusUris.backup[0]);
723
722
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
724
- case 13:
723
+ case 12:
725
724
  case "end":
726
725
  return _context13.stop();
727
726
  }
@@ -928,13 +927,6 @@ describe('Registration Tests', function () {
928
927
 
929
928
  // Keep-alive related test cases
930
929
  describe('Keep-alive Tests', function () {
931
- var logObj = {
932
- file: _constants.REGISTRATION_FILE,
933
- method: 'startKeepaliveTimer'
934
- };
935
- var mockKeepAliveBody = {
936
- device: _registerFixtures.mockPostResponse.device
937
- };
938
930
  var beforeEachSetupForKeepalive = /*#__PURE__*/function () {
939
931
  var _ref20 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee20() {
940
932
  return _regenerator.default.wrap(function _callee20$(_context20) {
@@ -946,7 +938,8 @@ describe('Registration Tests', function () {
946
938
  return reg.triggerRegistration();
947
939
  case 4:
948
940
  expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
949
- case 5:
941
+ expect(reg.webWorker).toBeDefined();
942
+ case 6:
950
943
  case "end":
951
944
  return _context20.stop();
952
945
  }
@@ -959,10 +952,7 @@ describe('Registration Tests', function () {
959
952
  afterEach(function () {
960
953
  jest.clearAllTimers();
961
954
  jest.clearAllMocks();
962
- if (reg.keepaliveTimer) {
963
- clearInterval(reg.keepaliveTimer);
964
- reg.keepaliveTimer = undefined;
965
- }
955
+ reg.clearKeepaliveTimer();
966
956
  reg.reconnectPending = false;
967
957
  var calls = (0, _values.default)(reg.callManager.getActiveCalls());
968
958
  calls.forEach(function (call) {
@@ -970,175 +960,172 @@ describe('Registration Tests', function () {
970
960
  });
971
961
  });
972
962
  it('verify successful keep-alive cases', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee21() {
973
- var keepAlivePayload, funcSpy;
963
+ var postMessageSpy;
974
964
  return _regenerator.default.wrap(function _callee21$(_context21) {
975
965
  while (1) switch (_context21.prev = _context21.next) {
976
966
  case 0:
977
- _context21.next = 2;
967
+ postMessageSpy = jest.spyOn(Worker.prototype, 'postMessage');
968
+ _context21.next = 3;
978
969
  return beforeEachSetupForKeepalive();
979
- case 2:
980
- keepAlivePayload = {
981
- statusCode: 200,
982
- body: mockKeepAliveBody
983
- };
984
- webex.request.mockReturnValue(keepAlivePayload);
985
- funcSpy = jest.spyOn(reg, 'postKeepAlive');
986
- jest.advanceTimersByTime(2 * _registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
987
- _context21.next = 8;
988
- return flushPromises();
989
- case 8:
990
- expect(funcSpy).toBeCalledTimes(2); // should be called 2 times: first try and after the interval.
991
-
992
- expect(logSpy).toBeCalledWith('Sent Keepalive, status: 200', logObj);
993
- expect(infoSpy).not.toBeCalledWith('Sent Keepalive, status: 200', logObj);
994
- case 11:
970
+ case 3:
971
+ expect(reg.webWorker).toBeDefined();
972
+ expect(postMessageSpy).toHaveBeenCalledWith(expect.objectContaining({
973
+ type: 'START_KEEPALIVE',
974
+ accessToken: expect.any(String),
975
+ deviceUrl: expect.any(String),
976
+ interval: expect.any(Number),
977
+ retryCountThreshold: expect.any(Number),
978
+ url: expect.any(String)
979
+ }));
980
+ reg.webWorker.onmessage({
981
+ data: {
982
+ type: 'KEEPALIVE_SUCCESS',
983
+ statusCode: 200
984
+ }
985
+ });
986
+ expect(lineEmitter).toBeCalledWith(_types4.LINE_EVENTS.RECONNECTED);
987
+ case 7:
995
988
  case "end":
996
989
  return _context21.stop();
997
990
  }
998
991
  }, _callee21);
999
992
  })));
1000
993
  it('verify failure keep-alive cases: Retry Success', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee22() {
1001
- var failurePayload, successPayload, timer;
994
+ var worker;
1002
995
  return _regenerator.default.wrap(function _callee22$(_context22) {
1003
996
  while (1) switch (_context22.prev = _context22.next) {
1004
997
  case 0:
1005
998
  _context22.next = 2;
1006
999
  return beforeEachSetupForKeepalive();
1007
1000
  case 2:
1008
- failurePayload = {
1009
- statusCode: 503,
1010
- body: mockKeepAliveBody
1011
- };
1012
- successPayload = {
1013
- statusCode: 200,
1014
- body: mockKeepAliveBody
1015
- };
1016
- timer = reg.keepaliveTimer;
1001
+ worker = reg.webWorker;
1017
1002
  lineEmitter.mockClear();
1018
- webex.request.mockRejectedValueOnce(failurePayload).mockResolvedValue(successPayload);
1019
- jest.advanceTimersByTime(2 * _registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
1020
- _context22.next = 10;
1021
- return flushPromises();
1022
- case 10:
1023
- expect(handleErrorSpy).toBeCalledOnceWith(failurePayload, expect.anything(), {
1024
- method: 'startKeepaliveTimer',
1025
- file: _constants.REGISTRATION_FILE
1003
+ worker.onmessage({
1004
+ data: {
1005
+ type: 'KEEPALIVE_FAILURE',
1006
+ err: {
1007
+ statusCode: 503
1008
+ },
1009
+ keepAliveRetryCount: 1
1010
+ }
1026
1011
  });
1027
- expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
1028
- expect(reg.keepaliveTimer).toBe(timer);
1029
- expect(lineEmitter).nthCalledWith(1, _types4.LINE_EVENTS.RECONNECTING);
1030
- expect(lineEmitter).nthCalledWith(2, _types4.LINE_EVENTS.RECONNECTED);
1031
- expect(lineEmitter).toBeCalledTimes(2);
1032
- case 16:
1012
+ worker.onmessage({
1013
+ data: {
1014
+ type: 'KEEPALIVE_SUCCESS',
1015
+ statusCode: 200
1016
+ }
1017
+ });
1018
+ expect(lineEmitter).toHaveBeenCalledWith(_types4.LINE_EVENTS.RECONNECTED);
1019
+ case 7:
1033
1020
  case "end":
1034
1021
  return _context22.stop();
1035
1022
  }
1036
1023
  }, _callee22);
1037
1024
  })));
1038
1025
  it('verify failure keep-alive cases: Restore failure', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee23() {
1039
- var restoreSpy, restartRegSpy, reconnectSpy, failurePayload, clearIntervalSpy, timer;
1026
+ var reconnectSpy, restoreSpy, restartRegSpy, RETRY_COUNT_THRESHOLD, failureEvent;
1040
1027
  return _regenerator.default.wrap(function _callee23$(_context23) {
1041
1028
  while (1) switch (_context23.prev = _context23.next) {
1042
1029
  case 0:
1043
1030
  _context23.next = 2;
1044
1031
  return beforeEachSetupForKeepalive();
1045
1032
  case 2:
1046
- restoreSpy = jest.spyOn(reg, 'restorePreviousRegistration');
1047
- restartRegSpy = jest.spyOn(reg, 'restartRegistration');
1048
1033
  reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure');
1049
- failurePayload = {
1050
- statusCode: 503,
1051
- body: mockKeepAliveBody
1052
- };
1053
- clearIntervalSpy = jest.spyOn(global, 'clearInterval');
1034
+ restoreSpy = jest.spyOn(reg, 'restorePreviousRegistration');
1035
+ restartRegSpy = jest.spyOn(reg, 'restartRegistration'); // Clear previous event emissions
1054
1036
  lineEmitter.mockClear();
1055
- webex.request.mockRejectedValue(failurePayload);
1037
+
1038
+ // Assume registration is active
1056
1039
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
1057
- timer = reg.keepaliveTimer;
1058
- jest.advanceTimersByTime(5 * _registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
1040
+
1041
+ // Use fake timers to trigger keepalive initialization
1042
+ jest.useFakeTimers();
1043
+ jest.advanceTimersByTime(_registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
1044
+
1045
+ // Simulate the worker sending a KEEPALIVE_FAILURE message with retry count at threshold.
1046
+ RETRY_COUNT_THRESHOLD = reg.isCCFlow ? 4 : 5;
1047
+ failureEvent = {
1048
+ data: {
1049
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1050
+ err: {
1051
+ statusCode: 503
1052
+ },
1053
+ keepAliveRetryCount: RETRY_COUNT_THRESHOLD
1054
+ }
1055
+ };
1056
+ reg.webWorker.onmessage(failureEvent);
1059
1057
  _context23.next = 14;
1060
1058
  return flushPromises();
1061
1059
  case 14:
1062
- expect(clearIntervalSpy).toBeCalledOnceWith(timer);
1063
-
1064
- // sendKeepAlive tries to retry 5 times before accepting failure
1065
- // later 2 attempts to register with primary server
1066
- expect(handleErrorSpy).toBeCalledTimes(7);
1067
1060
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
1068
- expect(reg.reconnectPending).toStrictEqual(false);
1061
+ expect(lineEmitter).toHaveBeenCalledWith(_types4.LINE_EVENTS.UNREGISTERED);
1069
1062
  expect(reconnectSpy).toBeCalledOnceWith(_constants.KEEPALIVE_UTIL);
1070
1063
  expect(restoreSpy).toBeCalledOnceWith(_constants.KEEPALIVE_UTIL);
1071
1064
  expect(restartRegSpy).toBeCalledOnceWith(_constants.KEEPALIVE_UTIL);
1072
- expect(warnSpy).toHaveBeenCalledWith('Keep-alive missed 1 times. Status -> 503 ', expect.objectContaining({
1073
- file: _constants.REGISTRATION_FILE,
1074
- method: 'startKeepaliveTimer'
1075
- }));
1076
- expect(webex.request).toBeCalledTimes(7);
1077
- expect(reg.keepaliveTimer).toBe(undefined);
1078
- expect(warnSpy).toHaveBeenCalledWith('Keep-alive missed 1 times. Status -> 503 ', expect.objectContaining({
1065
+ jest.useRealTimers();
1066
+ expect(warnSpy).toHaveBeenCalledWith('Keep-alive missed 5 times. Status -> 503 ', expect.objectContaining({
1079
1067
  file: _constants.REGISTRATION_FILE,
1080
1068
  method: 'startKeepaliveTimer'
1081
1069
  }));
1082
- expect(lineEmitter).nthCalledWith(1, _types4.LINE_EVENTS.RECONNECTING);
1083
- expect(lineEmitter).nthCalledWith(4, _types4.LINE_EVENTS.RECONNECTING);
1084
- expect(lineEmitter).nthCalledWith(5, _types4.LINE_EVENTS.UNREGISTERED);
1085
-
1086
- /** there will be 2 registration attempts */
1087
- expect(lineEmitter).nthCalledWith(6, _types4.LINE_EVENTS.CONNECTING);
1088
- expect(lineEmitter).nthCalledWith(7, _types4.LINE_EVENTS.UNREGISTERED);
1089
- expect(lineEmitter).nthCalledWith(8, _types4.LINE_EVENTS.CONNECTING);
1090
- expect(lineEmitter).nthCalledWith(9, _types4.LINE_EVENTS.UNREGISTERED);
1091
- expect(lineEmitter).toBeCalledTimes(9);
1092
- case 33:
1070
+ case 21:
1093
1071
  case "end":
1094
1072
  return _context23.stop();
1095
1073
  }
1096
1074
  }, _callee23);
1097
1075
  })));
1098
1076
  it('verify failure keep-alive cases: Restore Success', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee24() {
1099
- var restoreSpy, restartRegSpy, reconnectSpy, failurePayload, successPayload, clearIntervalSpy, url, timer;
1077
+ var reconnectSpy, url;
1100
1078
  return _regenerator.default.wrap(function _callee24$(_context24) {
1101
1079
  while (1) switch (_context24.prev = _context24.next) {
1102
1080
  case 0:
1103
1081
  _context24.next = 2;
1104
1082
  return beforeEachSetupForKeepalive();
1105
1083
  case 2:
1106
- restoreSpy = jest.spyOn(reg, 'restorePreviousRegistration');
1107
- restartRegSpy = jest.spyOn(reg, 'restartRegistration');
1084
+ expect(reg.webWorker).toBeDefined();
1108
1085
  reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure');
1109
- failurePayload = {
1110
- statusCode: 503,
1111
- body: mockKeepAliveBody
1112
- };
1113
- successPayload = {
1114
- statusCode: 200,
1115
- body: mockKeepAliveBody
1116
- };
1117
- clearIntervalSpy = jest.spyOn(global, 'clearInterval');
1118
- webex.request.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockResolvedValue(successPayload);
1119
-
1120
- /* successful registration */
1121
- // webex.request.mockResolvedValue(successPayload);
1122
-
1123
- expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
1124
- url = 'https://mobius.asydm-m-1.prod.infra.webex.com/api/v1';
1125
- /* set active Url and expect the registration to restore to this url */
1126
- reg.setActiveMobiusUrl(url);
1127
- timer = reg.keepaliveTimer;
1128
- jest.advanceTimersByTime(5 * _registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
1086
+ url = 'https://mobius-dfw.webex.com/api/v1/calling/web/';
1087
+ reg.webWorker.onmessage({
1088
+ data: {
1089
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1090
+ err: {
1091
+ statusCode: 503
1092
+ },
1093
+ keepAliveRetryCount: 5
1094
+ }
1095
+ });
1096
+ jest.advanceTimersByTime(1000);
1097
+ _context24.next = 9;
1098
+ return flushPromises();
1099
+ case 9:
1100
+ expect(reg.webWorker).toBeUndefined();
1101
+ expect(reconnectSpy).toBeCalledOnceWith(reg.startKeepaliveTimer.name);
1102
+ webex.request.mockResolvedValueOnce(successPayload);
1103
+ _context24.next = 14;
1104
+ return reg.triggerRegistration();
1105
+ case 14:
1129
1106
  _context24.next = 16;
1130
1107
  return flushPromises();
1131
1108
  case 16:
1132
- expect(clearIntervalSpy).toBeCalledOnceWith(timer);
1133
- expect(handleErrorSpy).toBeCalledTimes(5);
1109
+ expect(reg.webWorker).toBeDefined();
1110
+ reg.webWorker.onmessage({
1111
+ data: {
1112
+ type: _types.WorkerMessageType.KEEPALIVE_SUCCESS,
1113
+ statusCode: 200
1114
+ }
1115
+ });
1116
+
1117
+ // Advance timers and flush any remaining promises.
1118
+ jest.advanceTimersByTime(1000);
1119
+ _context24.next = 21;
1120
+ return flushPromises();
1121
+ case 21:
1134
1122
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
1135
- expect(reconnectSpy).toBeCalledOnceWith(_constants.KEEPALIVE_UTIL);
1136
- expect(restoreSpy).toBeCalledOnceWith(_constants.KEEPALIVE_UTIL);
1137
- expect(restartRegSpy).not.toBeCalled();
1123
+ // reconnectSpy should have been called only once.
1124
+ expect(reconnectSpy).toBeCalledTimes(1);
1125
+ expect(restoreSpy).toBeCalledOnceWith(reg.startKeepaliveTimer.name);
1126
+ expect(restartSpy).toBeCalledOnceWith(reg.startKeepaliveTimer.name);
1127
+ // Active Mobius URL should remain unchanged.
1138
1128
  expect(reg.getActiveMobiusUrl()).toStrictEqual(url);
1139
- expect(reg.reconnectPending).toStrictEqual(false);
1140
- expect(reg.keepaliveTimer).toBeTruthy();
1141
- expect(reg.keepaliveTimer).not.toBe(timer);
1142
1129
  case 26:
1143
1130
  case "end":
1144
1131
  return _context24.stop();
@@ -1146,42 +1133,84 @@ describe('Registration Tests', function () {
1146
1133
  }, _callee24);
1147
1134
  })));
1148
1135
  it('verify failure followed by recovery of keepalive', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee25() {
1149
- var failurePayload, successPayload, clearIntervalSpy, timer;
1150
1136
  return _regenerator.default.wrap(function _callee25$(_context25) {
1151
1137
  while (1) switch (_context25.prev = _context25.next) {
1152
1138
  case 0:
1153
1139
  _context25.next = 2;
1154
1140
  return beforeEachSetupForKeepalive();
1155
1141
  case 2:
1156
- failurePayload = {
1157
- statusCode: 503,
1158
- body: mockKeepAliveBody
1159
- };
1160
- successPayload = {
1161
- statusCode: 200,
1162
- body: mockKeepAliveBody
1163
- };
1164
- clearIntervalSpy = jest.spyOn(global, 'clearInterval');
1165
- webex.request.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockResolvedValue(successPayload);
1166
1142
  expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
1167
- timer = reg.keepaliveTimer; // sendKeepAlive tries to retry 3 times and receiving success on third time
1168
- jest.advanceTimersByTime(3 * _registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
1169
- _context25.next = 11;
1143
+ expect(reg.webWorker).toBeDefined();
1144
+ webex.request.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockResolvedValue(successPayload);
1145
+ reg.webWorker.onmessage({
1146
+ data: {
1147
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1148
+ err: failurePayload,
1149
+ keepAliveRetryCount: reg.isCCFlow ? 4 : 5
1150
+ }
1151
+ });
1152
+ _context25.next = 8;
1170
1153
  return flushPromises();
1171
- case 11:
1172
- expect(webex.request).toBeCalledTimes(3);
1173
- expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
1174
- expect(handleErrorSpy).toBeCalledTimes(2);
1175
- expect(clearIntervalSpy).not.toBeCalled();
1176
- expect(reg.keepaliveTimer).toBe(timer);
1177
- case 16:
1154
+ case 8:
1155
+ expect(reg.webWorker).toBeUndefined();
1156
+ expect(handleErrorSpy).toBeCalledTimes(3);
1157
+ _context25.next = 12;
1158
+ return reg.triggerRegistration();
1159
+ case 12:
1160
+ _context25.next = 14;
1161
+ return flushPromises();
1162
+ case 14:
1163
+ expect(reg.webWorker).toBeDefined();
1164
+ reg.webWorker.onmessage({
1165
+ data: {
1166
+ type: _types.WorkerMessageType.KEEPALIVE_SUCCESS,
1167
+ statusCode: 200
1168
+ }
1169
+ });
1170
+ _context25.next = 18;
1171
+ return flushPromises();
1172
+ case 18:
1173
+ // In a complete failure‐then-recovery scenario, we expect another failure event to have been handled.
1174
+ // For that, simulate a second failure event on the new worker.
1175
+ reg.webWorker.onmessage({
1176
+ data: {
1177
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1178
+ err: failurePayload,
1179
+ keepAliveRetryCount: reg.isCCFlow ? 4 : 5
1180
+ }
1181
+ });
1182
+ _context25.next = 21;
1183
+ return flushPromises();
1184
+ case 21:
1185
+ expect(handleErrorSpy).toBeCalledTimes(4);
1186
+
1187
+ // And then re-register successfully:
1188
+ _context25.next = 24;
1189
+ return reg.triggerRegistration();
1190
+ case 24:
1191
+ _context25.next = 26;
1192
+ return flushPromises();
1193
+ case 26:
1194
+ expect(reg.webWorker).toBeDefined();
1195
+ reg.webWorker.onmessage({
1196
+ data: {
1197
+ type: _types.WorkerMessageType.KEEPALIVE_SUCCESS,
1198
+ statusCode: 200
1199
+ }
1200
+ });
1201
+ _context25.next = 30;
1202
+ return flushPromises();
1203
+ case 30:
1204
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
1205
+ expect(reg.webWorker).toBeDefined();
1206
+ case 32:
1178
1207
  case "end":
1179
1208
  return _context25.stop();
1180
1209
  }
1181
1210
  }, _callee25);
1182
1211
  })));
1183
1212
  it('cc: verify failover to backup server after 4 keep alive failure with primary server', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee26() {
1184
- var failurePayload, successPayload, clearIntervalSpy, timer;
1213
+ var clearKeepaliveSpy, reconnectSpy;
1185
1214
  return _regenerator.default.wrap(function _callee26$(_context26) {
1186
1215
  while (1) switch (_context26.prev = _context26.next) {
1187
1216
  case 0:
@@ -1192,158 +1221,158 @@ describe('Registration Tests', function () {
1192
1221
  _context26.next = 3;
1193
1222
  return beforeEachSetupForKeepalive();
1194
1223
  case 3:
1195
- failurePayload = {
1196
- statusCode: 503,
1197
- body: mockKeepAliveBody
1198
- };
1199
- successPayload = {
1200
- statusCode: 200,
1201
- body: mockKeepAliveBody
1202
- };
1203
- clearIntervalSpy = jest.spyOn(global, 'clearInterval');
1204
- jest.spyOn(reg, 'postKeepAlive').mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockResolvedValue(successPayload);
1205
- expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
1206
- timer = reg.keepaliveTimer;
1207
- jest.advanceTimersByTime(5 * _registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
1208
- _context26.next = 12;
1209
- return flushPromises();
1210
- case 12:
1211
- expect(clearIntervalSpy).toBeCalledOnceWith(timer);
1212
- expect(reg.getStatus()).toBe(_types.RegistrationStatus.INACTIVE);
1213
- expect(reg.keepaliveTimer).not.toBe(timer);
1214
- webex.request.mockResolvedValue(successPayload);
1215
- jest.advanceTimersByTime(_constants.REG_TRY_BACKUP_TIMER_VAL_FOR_CC_IN_SEC * _constants.SEC_TO_MSEC_MFACTOR);
1216
- _context26.next = 19;
1224
+ webex.request.mockResolvedValueOnce(successPayload);
1225
+ _context26.next = 6;
1226
+ return reg.triggerRegistration();
1227
+ case 6:
1228
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
1229
+ expect(reg.webWorker).toBeDefined();
1230
+
1231
+ // Spy on clearKeepaliveTimer and simulate reconnectOnFailure behavior
1232
+ clearKeepaliveSpy = jest.spyOn(reg, 'clearKeepaliveTimer');
1233
+ reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure'); // Simulate a KEEPALIVE_FAILURE message from the worker with a retry count equal to threshold (4 for CC)
1234
+ reg.webWorker.onmessage({
1235
+ data: {
1236
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1237
+ err: {
1238
+ statusCode: 503
1239
+ },
1240
+ keepAliveRetryCount: 4
1241
+ }
1242
+ });
1243
+
1244
+ // Wait for any asynchronous actions to complete
1245
+ _context26.next = 13;
1217
1246
  return flushPromises();
1218
- case 19:
1219
- /* Active Url must match with the backup url as per the test */
1247
+ case 13:
1248
+ // Verify that the keepalive timer was cleared and reconnectOnFailure was triggered
1249
+ expect(clearKeepaliveSpy).toHaveBeenCalled();
1250
+ expect(reconnectSpy).toHaveBeenCalledWith(reg.startKeepaliveTimer.name);
1251
+
1252
+ // Verify that the active Mobius URL has been updated to the backup server and registration is active
1220
1253
  expect(reg.getActiveMobiusUrl()).toEqual(mobiusUris.backup[0]);
1221
- expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
1222
- case 21:
1254
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
1255
+ case 17:
1223
1256
  case "end":
1224
1257
  return _context26.stop();
1225
1258
  }
1226
1259
  }, _callee26);
1227
1260
  })));
1228
- it('verify final error for keep-alive', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee27() {
1229
- var restoreSpy, restartRegSpy, reconnectSpy, failurePayload, clearIntervalSpy;
1261
+ it('verify failure keep-alive case with active call present: Restore Success after call ends', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee27() {
1262
+ var reconnectSpy, restoreSpy, restartRegSpy, clearTimerSpy, threshold, failureEvent;
1230
1263
  return _regenerator.default.wrap(function _callee27$(_context27) {
1231
1264
  while (1) switch (_context27.prev = _context27.next) {
1232
1265
  case 0:
1233
1266
  _context27.next = 2;
1234
1267
  return beforeEachSetupForKeepalive();
1235
1268
  case 2:
1236
- restoreSpy = jest.spyOn(reg, 'restorePreviousRegistration');
1237
- restartRegSpy = jest.spyOn(reg, 'restartRegistration');
1238
1269
  reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure');
1239
- failurePayload = {
1240
- statusCode: 404,
1241
- body: mockKeepAliveBody
1270
+ restoreSpy = jest.spyOn(reg, 'restorePreviousRegistration');
1271
+ restartRegSpy = jest.spyOn(reg, 'restartRegistration'); // Simulate an active call.
1272
+ reg.callManager.createCall();
1273
+ expect((0, _keys.default)(reg.callManager.getActiveCalls()).length).toBe(1);
1274
+ clearTimerSpy = jest.spyOn(reg, 'clearKeepaliveTimer');
1275
+ threshold = reg.isCCFlow ? 4 : 5; // Simulate a KEEPALIVE_FAILURE event with a 503 error at threshold.
1276
+ failureEvent = {
1277
+ data: {
1278
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1279
+ err: {
1280
+ statusCode: 503
1281
+ },
1282
+ keepAliveRetryCount: threshold
1283
+ }
1242
1284
  };
1243
- clearIntervalSpy = jest.spyOn(global, 'clearInterval');
1244
- webex.request.mockRejectedValue(failurePayload);
1245
- expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
1246
-
1247
- /* send one keepalive */
1248
- jest.advanceTimersByTime(_registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
1249
- _context27.next = 12;
1285
+ reg.webWorker.onmessage(failureEvent);
1286
+ _context27.next = 13;
1250
1287
  return flushPromises();
1251
- case 12:
1252
- expect(clearIntervalSpy).toBeCalledTimes(1);
1253
- expect(reg.getStatus()).toBe(_types.RegistrationStatus.INACTIVE);
1254
- expect(reconnectSpy).not.toBeCalled();
1288
+ case 13:
1289
+ // At this point, clearKeepaliveTimer was called so the worker is terminated.
1290
+ expect(clearTimerSpy).toHaveBeenCalled();
1291
+ expect(reg.webWorker).toBeUndefined();
1292
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
1293
+ expect(lineEmitter).lastCalledWith(_types4.LINE_EVENTS.UNREGISTERED);
1294
+ expect(reg.keepaliveTimer).toStrictEqual(undefined);
1295
+ expect(reg.failbackTimer).toStrictEqual(undefined);
1296
+ expect(reconnectSpy).toBeCalledOnceWith(_constants.KEEPALIVE_UTIL);
1255
1297
  expect(restoreSpy).not.toBeCalled();
1256
1298
  expect(restartRegSpy).not.toBeCalled();
1257
- expect(reg.reconnectPending).toStrictEqual(false);
1258
- expect(webex.request).toBeCalledOnceWith({
1259
- headers: mockResponse.headers,
1260
- uri: "".concat(mockKeepAliveBody.device.uri, "/status"),
1261
- method: 'POST',
1262
- service: mockResponse.service
1263
- });
1264
- expect(reg.keepaliveTimer).toBe(undefined);
1265
- expect(handleErrorSpy).toBeCalledOnceWith(failurePayload, expect.anything(), {
1299
+ expect(reg.reconnectPending).toStrictEqual(true);
1300
+ expect(infoSpy).toBeCalledWith('Active call(s) present, deferred reconnect till call cleanup.', {
1266
1301
  file: _constants.REGISTRATION_FILE,
1267
- method: _constants.KEEPALIVE_UTIL
1302
+ method: expect.any(String)
1268
1303
  });
1269
- expect(warnSpy).toBeCalledWith('Keep-alive missed 1 times. Status -> 404 ', expect.objectContaining({
1270
- file: _constants.REGISTRATION_FILE,
1271
- method: 'startKeepaliveTimer'
1272
- }));
1273
- case 22:
1304
+ reconnectSpy.mockClear();
1305
+
1306
+ // Now simulate call cleanup.
1307
+ reg.callManager.callCollection = {};
1308
+ webex.request.mockResolvedValueOnce(successPayload);
1309
+
1310
+ // Call reconnectOnFailure manually. With no active calls, this should trigger re-registration.
1311
+ _context27.next = 29;
1312
+ return reg.reconnectOnFailure(_constants.CALLS_CLEARED_HANDLER_UTIL);
1313
+ case 29:
1314
+ _context27.next = 31;
1315
+ return flushPromises();
1316
+ case 31:
1317
+ expect((0, _keys.default)(reg.callManager.getActiveCalls()).length).toBe(0);
1318
+ // After re-registration, registration status becomes ACTIVE and a new worker is created.
1319
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
1320
+ expect(reg.webWorker).toBeDefined();
1321
+ expect(reconnectSpy).toBeCalledOnceWith(_constants.CALLS_CLEARED_HANDLER_UTIL);
1322
+ expect(restoreSpy).toBeCalledOnceWith(_constants.CALLS_CLEARED_HANDLER_UTIL);
1323
+ expect(restartRegSpy).not.toBeCalled();
1324
+ expect(reg.reconnectPending).toStrictEqual(false);
1325
+ case 38:
1274
1326
  case "end":
1275
1327
  return _context27.stop();
1276
1328
  }
1277
1329
  }, _callee27);
1278
1330
  })));
1279
- it('verify failure keep-alive case with active call present: Restore Success after call ends', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee28() {
1280
- var restoreSpy, restartRegSpy, reconnectSpy, failurePayload, successPayload, clearIntervalSpy, url, timer, call;
1331
+ it('checks for keep-alive failure with final error: 404', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee28() {
1332
+ var reconnectSpy, restoreSpy, restartRegSpy, clearTimerSpy;
1281
1333
  return _regenerator.default.wrap(function _callee28$(_context28) {
1282
1334
  while (1) switch (_context28.prev = _context28.next) {
1283
1335
  case 0:
1284
1336
  _context28.next = 2;
1285
1337
  return beforeEachSetupForKeepalive();
1286
1338
  case 2:
1339
+ reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure');
1287
1340
  restoreSpy = jest.spyOn(reg, 'restorePreviousRegistration');
1288
1341
  restartRegSpy = jest.spyOn(reg, 'restartRegistration');
1289
- reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure');
1290
- failurePayload = {
1291
- statusCode: 503,
1292
- body: mockKeepAliveBody
1293
- };
1294
- successPayload = {
1295
- statusCode: 200,
1296
- body: mockKeepAliveBody
1297
- };
1298
- clearIntervalSpy = jest.spyOn(global, 'clearInterval');
1299
- webex.request.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockResolvedValue(successPayload);
1300
-
1301
- // jest.spyOn(callingClient['registration'], 'createDevice').mockResolvedValue(successPayload);
1302
- url = 'https://mobius.asydm-m-1.prod.infra.webex.com/api/v1';
1303
- reg.setActiveMobiusUrl(url);
1304
- expect(reg.reconnectPending).toStrictEqual(false);
1305
- timer = reg.keepaliveTimer;
1306
- /* add a call to the callManager */
1307
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1308
- call = reg.callManager.createCall();
1309
- expect((0, _keys.default)(reg.callManager.getActiveCalls()).length).toBe(1);
1310
-
1311
- /* send one keepalive */
1312
- jest.advanceTimersByTime(5 * _registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
1313
- _context28.next = 18;
1342
+ clearTimerSpy = jest.spyOn(reg, 'clearKeepaliveTimer');
1343
+ jest.spyOn(utils, 'handleRegistrationErrors').mockResolvedValue(true);
1344
+ reg.webWorker.onmessage({
1345
+ data: {
1346
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1347
+ err: {
1348
+ statusCode: 404
1349
+ },
1350
+ keepAliveRetryCount: 1
1351
+ }
1352
+ });
1353
+ _context28.next = 10;
1314
1354
  return flushPromises();
1315
- case 18:
1316
- expect(clearIntervalSpy).toBeCalledOnceWith(timer);
1317
- expect(handleErrorSpy).toBeCalledTimes(5);
1318
- expect(reg.keepaliveTimer).toStrictEqual(undefined);
1319
- expect(reg.failbackTimer).toStrictEqual(undefined);
1320
- expect(reg.getStatus()).toBe(_types.RegistrationStatus.INACTIVE);
1321
- expect(lineEmitter).lastCalledWith(_types4.LINE_EVENTS.UNREGISTERED);
1322
- expect(reconnectSpy).toBeCalledOnceWith(_constants.KEEPALIVE_UTIL);
1323
- expect(restoreSpy).not.toBeCalled();
1324
- expect(restartRegSpy).not.toBeCalled();
1325
- expect(reg.reconnectPending).toStrictEqual(true);
1326
- expect(infoSpy).toBeCalledWith('Active call(s) present, deferred reconnect till call cleanup.', {
1355
+ case 10:
1356
+ expect(warnSpy).toBeCalledWith('Keep-alive missed 1 times. Status -> 404 ', expect.objectContaining({
1327
1357
  file: _constants.REGISTRATION_FILE,
1328
- method: expect.any(String)
1358
+ method: 'startKeepaliveTimer'
1359
+ }));
1360
+ expect(handleErrorSpy).toBeCalledOnceWith({
1361
+ statusCode: 404
1362
+ }, expect.anything(), {
1363
+ file: _constants.REGISTRATION_FILE,
1364
+ method: _constants.KEEPALIVE_UTIL
1329
1365
  });
1330
- reconnectSpy.mockClear();
1331
-
1332
- /* simulate call disconnect and Calling client will trigger reconnect upon receiving disconnect event from CallManager */
1333
- reg.callManager.callCollection = {};
1334
- _context28.next = 33;
1335
- return reg.reconnectOnFailure(_constants.CALLS_CLEARED_HANDLER_UTIL);
1336
- case 33:
1337
- expect((0, _keys.default)(reg.callManager.getActiveCalls()).length).toBe(0);
1338
- expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
1339
- expect(reconnectSpy).toBeCalledOnceWith(_constants.CALLS_CLEARED_HANDLER_UTIL);
1340
- expect(restoreSpy).toBeCalledOnceWith(_constants.CALLS_CLEARED_HANDLER_UTIL);
1341
- expect(restartRegSpy).not.toBeCalled();
1366
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
1367
+ expect(lineEmitter).toHaveBeenCalledWith(_types4.LINE_EVENTS.UNREGISTERED);
1368
+ expect(clearTimerSpy).toBeCalledTimes(1);
1369
+ expect(reconnectSpy).not.toHaveBeenCalled();
1370
+ expect(restoreSpy).not.toHaveBeenCalled();
1371
+ expect(restartRegSpy).not.toHaveBeenCalled();
1342
1372
  expect(reg.reconnectPending).toStrictEqual(false);
1343
- expect(reg.getActiveMobiusUrl()).toStrictEqual(url);
1344
- expect(reg.keepaliveTimer).toBeTruthy();
1345
- expect(reg.keepaliveTimer).not.toBe(timer);
1346
- case 42:
1373
+ expect(reg.keepaliveTimer).toBe(undefined);
1374
+ expect(reg.webWorker).toBeUndefined();
1375
+ case 21:
1347
1376
  case "end":
1348
1377
  return _context28.stop();
1349
1378
  }