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

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.
@@ -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,164 @@ 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, 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
- reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure');
1049
- failurePayload = {
1050
- statusCode: 503,
1051
- body: mockKeepAliveBody
1052
- };
1053
- clearIntervalSpy = jest.spyOn(global, 'clearInterval');
1033
+ reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure'); // Clear previous event emissions
1054
1034
  lineEmitter.mockClear();
1055
- webex.request.mockRejectedValue(failurePayload);
1035
+
1036
+ // Assume registration is active
1056
1037
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
1057
- timer = reg.keepaliveTimer;
1058
- jest.advanceTimersByTime(5 * _registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
1059
- _context23.next = 14;
1060
- return flushPromises();
1061
- case 14:
1062
- expect(clearIntervalSpy).toBeCalledOnceWith(timer);
1063
1038
 
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
- expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
1068
- expect(reg.reconnectPending).toStrictEqual(false);
1069
- expect(reconnectSpy).toBeCalledOnceWith(_constants.KEEPALIVE_UTIL);
1070
- expect(restoreSpy).toBeCalledOnceWith(_constants.KEEPALIVE_UTIL);
1071
- 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({
1079
- file: _constants.REGISTRATION_FILE,
1080
- method: 'startKeepaliveTimer'
1081
- }));
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);
1039
+ // Use fake timers to trigger keepalive initialization
1040
+ jest.useFakeTimers();
1041
+ jest.advanceTimersByTime(_registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
1085
1042
 
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:
1043
+ // Simulate the worker sending a KEEPALIVE_FAILURE message with retry count at threshold.
1044
+ RETRY_COUNT_THRESHOLD = reg.isCCFlow ? 4 : 5;
1045
+ failureEvent = {
1046
+ data: {
1047
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1048
+ err: {
1049
+ statusCode: 503
1050
+ },
1051
+ keepAliveRetryCount: RETRY_COUNT_THRESHOLD
1052
+ }
1053
+ };
1054
+ reg.webWorker.onmessage(failureEvent);
1055
+ _context23.next = 12;
1056
+ return flushPromises();
1057
+ case 12:
1058
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
1059
+ expect(lineEmitter).toHaveBeenCalledWith(_types4.LINE_EVENTS.UNREGISTERED);
1060
+ expect(reconnectSpy).toBeCalledOnceWith('startKeepaliveTimer');
1061
+ jest.useRealTimers();
1062
+ case 16:
1093
1063
  case "end":
1094
1064
  return _context23.stop();
1095
1065
  }
1096
1066
  }, _callee23);
1097
1067
  })));
1098
1068
  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;
1069
+ var reconnectSpy, url;
1100
1070
  return _regenerator.default.wrap(function _callee24$(_context24) {
1101
1071
  while (1) switch (_context24.prev = _context24.next) {
1102
1072
  case 0:
1103
1073
  _context24.next = 2;
1104
1074
  return beforeEachSetupForKeepalive();
1105
1075
  case 2:
1106
- restoreSpy = jest.spyOn(reg, 'restorePreviousRegistration');
1107
- restartRegSpy = jest.spyOn(reg, 'restartRegistration');
1076
+ expect(reg.webWorker).toBeDefined();
1108
1077
  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);
1078
+ url = 'https://mobius-dfw.webex.com/api/v1/calling/web/';
1079
+ reg.webWorker.onmessage({
1080
+ data: {
1081
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1082
+ err: {
1083
+ statusCode: 503
1084
+ },
1085
+ keepAliveRetryCount: 5
1086
+ }
1087
+ });
1088
+ jest.advanceTimersByTime(1000);
1089
+ _context24.next = 9;
1090
+ return flushPromises();
1091
+ case 9:
1092
+ expect(reg.webWorker).toBeUndefined();
1093
+ expect(reconnectSpy).toBeCalledOnceWith(reg.startKeepaliveTimer.name);
1094
+ webex.request.mockResolvedValueOnce(successPayload);
1095
+ _context24.next = 14;
1096
+ return reg.triggerRegistration();
1097
+ case 14:
1129
1098
  _context24.next = 16;
1130
1099
  return flushPromises();
1131
1100
  case 16:
1132
- expect(clearIntervalSpy).toBeCalledOnceWith(timer);
1133
- expect(handleErrorSpy).toBeCalledTimes(5);
1101
+ expect(reg.webWorker).toBeDefined();
1102
+ reg.webWorker.onmessage({
1103
+ data: {
1104
+ type: _types.WorkerMessageType.KEEPALIVE_SUCCESS,
1105
+ statusCode: 200
1106
+ }
1107
+ });
1108
+
1109
+ // Advance timers and flush any remaining promises.
1110
+ jest.advanceTimersByTime(1000);
1111
+ _context24.next = 21;
1112
+ return flushPromises();
1113
+ case 21:
1134
1114
  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();
1115
+ // reconnectSpy should have been called only once.
1116
+ expect(reconnectSpy).toBeCalledTimes(1);
1117
+ expect(restoreSpy).toBeCalledOnceWith(reg.startKeepaliveTimer.name);
1118
+ expect(restartSpy).toBeCalledOnceWith(reg.startKeepaliveTimer.name);
1119
+ // Active Mobius URL should remain unchanged.
1138
1120
  expect(reg.getActiveMobiusUrl()).toStrictEqual(url);
1139
- expect(reg.reconnectPending).toStrictEqual(false);
1140
- expect(reg.keepaliveTimer).toBeTruthy();
1141
- expect(reg.keepaliveTimer).not.toBe(timer);
1142
1121
  case 26:
1143
1122
  case "end":
1144
1123
  return _context24.stop();
@@ -1146,42 +1125,84 @@ describe('Registration Tests', function () {
1146
1125
  }, _callee24);
1147
1126
  })));
1148
1127
  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
1128
  return _regenerator.default.wrap(function _callee25$(_context25) {
1151
1129
  while (1) switch (_context25.prev = _context25.next) {
1152
1130
  case 0:
1153
1131
  _context25.next = 2;
1154
1132
  return beforeEachSetupForKeepalive();
1155
1133
  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
1134
  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;
1135
+ expect(reg.webWorker).toBeDefined();
1136
+ webex.request.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockResolvedValue(successPayload);
1137
+ reg.webWorker.onmessage({
1138
+ data: {
1139
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1140
+ err: failurePayload,
1141
+ keepAliveRetryCount: reg.isCCFlow ? 4 : 5
1142
+ }
1143
+ });
1144
+ _context25.next = 8;
1170
1145
  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:
1146
+ case 8:
1147
+ expect(reg.webWorker).toBeUndefined();
1148
+ expect(handleErrorSpy).toBeCalledTimes(3);
1149
+ _context25.next = 12;
1150
+ return reg.triggerRegistration();
1151
+ case 12:
1152
+ _context25.next = 14;
1153
+ return flushPromises();
1154
+ case 14:
1155
+ expect(reg.webWorker).toBeDefined();
1156
+ reg.webWorker.onmessage({
1157
+ data: {
1158
+ type: _types.WorkerMessageType.KEEPALIVE_SUCCESS,
1159
+ statusCode: 200
1160
+ }
1161
+ });
1162
+ _context25.next = 18;
1163
+ return flushPromises();
1164
+ case 18:
1165
+ // In a complete failure‐then-recovery scenario, we expect another failure event to have been handled.
1166
+ // For that, simulate a second failure event on the new worker.
1167
+ reg.webWorker.onmessage({
1168
+ data: {
1169
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1170
+ err: failurePayload,
1171
+ keepAliveRetryCount: reg.isCCFlow ? 4 : 5
1172
+ }
1173
+ });
1174
+ _context25.next = 21;
1175
+ return flushPromises();
1176
+ case 21:
1177
+ expect(handleErrorSpy).toBeCalledTimes(4);
1178
+
1179
+ // And then re-register successfully:
1180
+ _context25.next = 24;
1181
+ return reg.triggerRegistration();
1182
+ case 24:
1183
+ _context25.next = 26;
1184
+ return flushPromises();
1185
+ case 26:
1186
+ expect(reg.webWorker).toBeDefined();
1187
+ reg.webWorker.onmessage({
1188
+ data: {
1189
+ type: _types.WorkerMessageType.KEEPALIVE_SUCCESS,
1190
+ statusCode: 200
1191
+ }
1192
+ });
1193
+ _context25.next = 30;
1194
+ return flushPromises();
1195
+ case 30:
1196
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
1197
+ expect(reg.webWorker).toBeDefined();
1198
+ case 32:
1178
1199
  case "end":
1179
1200
  return _context25.stop();
1180
1201
  }
1181
1202
  }, _callee25);
1182
1203
  })));
1183
1204
  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;
1205
+ var clearKeepaliveSpy, reconnectSpy;
1185
1206
  return _regenerator.default.wrap(function _callee26$(_context26) {
1186
1207
  while (1) switch (_context26.prev = _context26.next) {
1187
1208
  case 0:
@@ -1192,163 +1213,177 @@ describe('Registration Tests', function () {
1192
1213
  _context26.next = 3;
1193
1214
  return beforeEachSetupForKeepalive();
1194
1215
  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;
1216
+ webex.request.mockResolvedValueOnce(successPayload);
1217
+ _context26.next = 6;
1218
+ return reg.triggerRegistration();
1219
+ case 6:
1220
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
1221
+ expect(reg.webWorker).toBeDefined();
1222
+
1223
+ // Spy on clearKeepaliveTimer and simulate reconnectOnFailure behavior
1224
+ clearKeepaliveSpy = jest.spyOn(reg, 'clearKeepaliveTimer');
1225
+ reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure'); // Simulate a KEEPALIVE_FAILURE message from the worker with a retry count equal to threshold (4 for CC)
1226
+ reg.webWorker.onmessage({
1227
+ data: {
1228
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1229
+ err: {
1230
+ statusCode: 503
1231
+ },
1232
+ keepAliveRetryCount: 4
1233
+ }
1234
+ });
1235
+
1236
+ // Wait for any asynchronous actions to complete
1237
+ _context26.next = 13;
1217
1238
  return flushPromises();
1218
- case 19:
1219
- /* Active Url must match with the backup url as per the test */
1239
+ case 13:
1240
+ // Verify that the keepalive timer was cleared and reconnectOnFailure was triggered
1241
+ expect(clearKeepaliveSpy).toHaveBeenCalled();
1242
+ expect(reconnectSpy).toHaveBeenCalledWith(reg.startKeepaliveTimer.name);
1243
+
1244
+ // Verify that the active Mobius URL has been updated to the backup server and registration is active
1220
1245
  expect(reg.getActiveMobiusUrl()).toEqual(mobiusUris.backup[0]);
1221
- expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
1222
- case 21:
1246
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
1247
+ case 17:
1223
1248
  case "end":
1224
1249
  return _context26.stop();
1225
1250
  }
1226
1251
  }, _callee26);
1227
1252
  })));
1228
1253
  it('verify final error for keep-alive', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee27() {
1229
- var restoreSpy, restartRegSpy, reconnectSpy, failurePayload, clearIntervalSpy;
1254
+ var threshold, reconnectSpy;
1230
1255
  return _regenerator.default.wrap(function _callee27$(_context27) {
1231
1256
  while (1) switch (_context27.prev = _context27.next) {
1232
1257
  case 0:
1233
1258
  _context27.next = 2;
1234
1259
  return beforeEachSetupForKeepalive();
1235
1260
  case 2:
1236
- restoreSpy = jest.spyOn(reg, 'restorePreviousRegistration');
1237
- restartRegSpy = jest.spyOn(reg, 'restartRegistration');
1261
+ threshold = reg.isCCFlow ? 4 : 5;
1238
1262
  reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure');
1239
- failurePayload = {
1240
- statusCode: 404,
1241
- body: mockKeepAliveBody
1242
- };
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;
1250
- return flushPromises();
1251
- case 12:
1252
- expect(clearIntervalSpy).toBeCalledTimes(1);
1253
- expect(reg.getStatus()).toBe(_types.RegistrationStatus.INACTIVE);
1254
- expect(reconnectSpy).not.toBeCalled();
1255
- expect(restoreSpy).not.toBeCalled();
1256
- 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(), {
1266
- file: _constants.REGISTRATION_FILE,
1267
- method: _constants.KEEPALIVE_UTIL
1263
+ jest.spyOn(utils, 'handleRegistrationErrors').mockResolvedValue(true);
1264
+ reg.webWorker.onmessage({
1265
+ data: {
1266
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1267
+ err: {
1268
+ statusCode: 404
1269
+ },
1270
+ keepAliveRetryCount: threshold
1271
+ }
1268
1272
  });
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:
1273
+ _context27.next = 8;
1274
+ return flushPromises();
1275
+ case 8:
1276
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
1277
+ expect(lineEmitter).toHaveBeenCalledWith(_types4.LINE_EVENTS.UNREGISTERED);
1278
+ expect(reconnectSpy).not.toHaveBeenCalled();
1279
+ case 11:
1274
1280
  case "end":
1275
1281
  return _context27.stop();
1276
1282
  }
1277
1283
  }, _callee27);
1278
1284
  })));
1279
1285
  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;
1286
+ var clearTimerSpy, threshold, failureEvent;
1281
1287
  return _regenerator.default.wrap(function _callee28$(_context28) {
1282
1288
  while (1) switch (_context28.prev = _context28.next) {
1283
1289
  case 0:
1284
1290
  _context28.next = 2;
1285
1291
  return beforeEachSetupForKeepalive();
1286
1292
  case 2:
1287
- restoreSpy = jest.spyOn(reg, 'restorePreviousRegistration');
1288
- 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
1293
+ // Simulate an active call.
1294
+ reg.callManager.createCall();
1295
+ expect((0, _keys.default)(reg.callManager.getActiveCalls()).length).toBeGreaterThan(0);
1296
+ clearTimerSpy = jest.spyOn(reg, 'clearKeepaliveTimer');
1297
+ threshold = reg.isCCFlow ? 4 : 5; // Simulate a KEEPALIVE_FAILURE event with a 503 error at threshold.
1298
+ failureEvent = {
1299
+ data: {
1300
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1301
+ err: {
1302
+ statusCode: 503
1303
+ },
1304
+ keepAliveRetryCount: threshold
1305
+ }
1297
1306
  };
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;
1307
+ reg.webWorker.onmessage(failureEvent);
1308
+ _context28.next = 10;
1314
1309
  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.', {
1327
- file: _constants.REGISTRATION_FILE,
1328
- method: expect.any(String)
1329
- });
1330
- reconnectSpy.mockClear();
1310
+ case 10:
1311
+ // At this point, clearKeepaliveTimer was called so the worker is terminated.
1312
+ expect(clearTimerSpy).toHaveBeenCalled();
1313
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
1314
+ expect(reg.webWorker).toBeUndefined();
1331
1315
 
1332
- /* simulate call disconnect and Calling client will trigger reconnect upon receiving disconnect event from CallManager */
1316
+ // Now simulate call cleanup.
1333
1317
  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();
1342
- 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:
1318
+ webex.request.mockResolvedValueOnce(successPayload);
1319
+
1320
+ // Call reconnectOnFailure manually. With no active calls, this should trigger re-registration.
1321
+ _context28.next = 17;
1322
+ return reg.reconnectOnFailure('activeCallEnded');
1323
+ case 17:
1324
+ _context28.next = 19;
1325
+ return flushPromises();
1326
+ case 19:
1327
+ // After re-registration, registration status becomes ACTIVE and a new worker is created.
1328
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
1329
+ expect(reg.isReconnectPending()).toBe(false);
1330
+ expect(reg.webWorker).toBeDefined();
1331
+ case 22:
1347
1332
  case "end":
1348
1333
  return _context28.stop();
1349
1334
  }
1350
1335
  }, _callee28);
1351
1336
  })));
1337
+ it('should emit LINE_EVENTS.ERROR when keepalive fails with a final error', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee30() {
1338
+ return _regenerator.default.wrap(function _callee30$(_context30) {
1339
+ while (1) switch (_context30.prev = _context30.next) {
1340
+ case 0:
1341
+ _context30.next = 2;
1342
+ return beforeEachSetupForKeepalive();
1343
+ case 2:
1344
+ expect(reg.webWorker).toBeDefined();
1345
+ lineEmitter.mockClear();
1346
+ jest.spyOn(utils, 'handleRegistrationErrors').mockImplementationOnce( /*#__PURE__*/function () {
1347
+ var _ref30 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee29(error, callback) {
1348
+ var clientError;
1349
+ return _regenerator.default.wrap(function _callee29$(_context29) {
1350
+ while (1) switch (_context29.prev = _context29.next) {
1351
+ case 0:
1352
+ clientError = (0, _LineError.createLineError)('User is unauthorized due to an expired token. Sign out, then sign back in.', {}, _types3.ERROR_TYPE.TOKEN_ERROR, _types.RegistrationStatus.INACTIVE);
1353
+ callback(clientError, true);
1354
+ return _context29.abrupt("return", true);
1355
+ case 3:
1356
+ case "end":
1357
+ return _context29.stop();
1358
+ }
1359
+ }, _callee29);
1360
+ }));
1361
+ return function (_x, _x2) {
1362
+ return _ref30.apply(this, arguments);
1363
+ };
1364
+ }());
1365
+ reg.webWorker.onmessage({
1366
+ data: {
1367
+ type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
1368
+ err: {
1369
+ statusCode: 401,
1370
+ message: 'Unauthorized'
1371
+ },
1372
+ keepAliveRetryCount: 1
1373
+ }
1374
+ });
1375
+ _context30.next = 8;
1376
+ return flushPromises();
1377
+ case 8:
1378
+ expect(lineEmitter).toHaveBeenNthCalledWith(1, _types4.LINE_EVENTS.ERROR, undefined, new Error('User is unauthorized due to an expired token. Sign out, then sign back in.'));
1379
+ expect(reg.getStatus()).toBe(_types.RegistrationStatus.INACTIVE);
1380
+ expect(reg.webWorker).toBeUndefined();
1381
+ case 11:
1382
+ case "end":
1383
+ return _context30.stop();
1384
+ }
1385
+ }, _callee30);
1386
+ })));
1352
1387
  });
1353
1388
  });
1354
1389
  //# sourceMappingURL=register.test.js.map