@webex/calling 3.8.0-web-workers-keepalive.2 → 3.8.1-next.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.
Files changed (161) hide show
  1. package/dist/CallHistory/CallHistory.js +100 -63
  2. package/dist/CallHistory/CallHistory.js.map +1 -1
  3. package/dist/CallHistory/CallHistory.test.js +115 -19
  4. package/dist/CallHistory/CallHistory.test.js.map +1 -1
  5. package/dist/CallHistory/constants.js +9 -1
  6. package/dist/CallHistory/constants.js.map +1 -1
  7. package/dist/CallSettings/CallSettings.js +46 -13
  8. package/dist/CallSettings/CallSettings.js.map +1 -1
  9. package/dist/CallSettings/UcmBackendConnector.js +62 -18
  10. package/dist/CallSettings/UcmBackendConnector.js.map +1 -1
  11. package/dist/CallSettings/UcmBackendConnector.test.js +70 -7
  12. package/dist/CallSettings/UcmBackendConnector.test.js.map +1 -1
  13. package/dist/CallSettings/WxCallBackendConnector.js +153 -103
  14. package/dist/CallSettings/WxCallBackendConnector.js.map +1 -1
  15. package/dist/CallSettings/WxCallBackendConnector.test.js +52 -15
  16. package/dist/CallSettings/WxCallBackendConnector.test.js.map +1 -1
  17. package/dist/CallSettings/constants.js +15 -1
  18. package/dist/CallSettings/constants.js.map +1 -1
  19. package/dist/CallingClient/CallingClient.js +220 -159
  20. package/dist/CallingClient/CallingClient.js.map +1 -1
  21. package/dist/CallingClient/CallingClient.test.js +53 -24
  22. package/dist/CallingClient/CallingClient.test.js.map +1 -1
  23. package/dist/CallingClient/calling/call.js +251 -189
  24. package/dist/CallingClient/calling/call.js.map +1 -1
  25. package/dist/CallingClient/calling/call.test.js +96 -41
  26. package/dist/CallingClient/calling/call.test.js.map +1 -1
  27. package/dist/CallingClient/calling/callManager.js +73 -48
  28. package/dist/CallingClient/calling/callManager.js.map +1 -1
  29. package/dist/CallingClient/calling/callManager.test.js +96 -37
  30. package/dist/CallingClient/calling/callManager.test.js.map +1 -1
  31. package/dist/CallingClient/constants.js +105 -3
  32. package/dist/CallingClient/constants.js.map +1 -1
  33. package/dist/CallingClient/line/index.js +47 -18
  34. package/dist/CallingClient/line/index.js.map +1 -1
  35. package/dist/CallingClient/line/line.test.js +12 -6
  36. package/dist/CallingClient/line/line.test.js.map +1 -1
  37. package/dist/CallingClient/registration/register.js +591 -529
  38. package/dist/CallingClient/registration/register.js.map +1 -1
  39. package/dist/CallingClient/registration/register.test.js +806 -457
  40. package/dist/CallingClient/registration/register.test.js.map +1 -1
  41. package/dist/CallingClient/registration/types.js.map +1 -1
  42. package/dist/Contacts/ContactsClient.js +156 -102
  43. package/dist/Contacts/ContactsClient.js.map +1 -1
  44. package/dist/Contacts/ContactsClient.test.js +197 -49
  45. package/dist/Contacts/ContactsClient.test.js.map +1 -1
  46. package/dist/Contacts/constants.js +11 -1
  47. package/dist/Contacts/constants.js.map +1 -1
  48. package/dist/Errors/types.js +2 -0
  49. package/dist/Errors/types.js.map +1 -1
  50. package/dist/Events/impl/index.js +1 -1
  51. package/dist/Events/impl/index.js.map +1 -1
  52. package/dist/Metrics/index.js +102 -41
  53. package/dist/Metrics/index.js.map +1 -1
  54. package/dist/Metrics/index.test.js +10 -4
  55. package/dist/Metrics/index.test.js.map +1 -1
  56. package/dist/Metrics/types.js +4 -1
  57. package/dist/Metrics/types.js.map +1 -1
  58. package/dist/SDKConnector/types.js.map +1 -1
  59. package/dist/Voicemail/BroadworksBackendConnector.js +154 -91
  60. package/dist/Voicemail/BroadworksBackendConnector.js.map +1 -1
  61. package/dist/Voicemail/BroadworksBackendConnector.test.js +99 -19
  62. package/dist/Voicemail/BroadworksBackendConnector.test.js.map +1 -1
  63. package/dist/Voicemail/UcmBackendConnector.js +105 -54
  64. package/dist/Voicemail/UcmBackendConnector.js.map +1 -1
  65. package/dist/Voicemail/UcmBackendConnector.test.js +127 -17
  66. package/dist/Voicemail/UcmBackendConnector.test.js.map +1 -1
  67. package/dist/Voicemail/Voicemail.js +198 -79
  68. package/dist/Voicemail/Voicemail.js.map +1 -1
  69. package/dist/Voicemail/Voicemail.test.js +188 -23
  70. package/dist/Voicemail/Voicemail.test.js.map +1 -1
  71. package/dist/Voicemail/WxCallBackendConnector.js +123 -76
  72. package/dist/Voicemail/WxCallBackendConnector.js.map +1 -1
  73. package/dist/Voicemail/WxCallBackendConnector.test.js +69 -6
  74. package/dist/Voicemail/WxCallBackendConnector.test.js.map +1 -1
  75. package/dist/Voicemail/constants.js +25 -1
  76. package/dist/Voicemail/constants.js.map +1 -1
  77. package/dist/common/Utils.js +168 -104
  78. package/dist/common/Utils.js.map +1 -1
  79. package/dist/common/Utils.test.js +199 -35
  80. package/dist/common/Utils.test.js.map +1 -1
  81. package/dist/common/constants.js +2 -1
  82. package/dist/common/constants.js.map +1 -1
  83. package/dist/common/types.js +1 -8
  84. package/dist/common/types.js.map +1 -1
  85. package/dist/module/CallHistory/CallHistory.js +32 -13
  86. package/dist/module/CallHistory/constants.js +6 -0
  87. package/dist/module/CallSettings/CallSettings.js +36 -3
  88. package/dist/module/CallSettings/UcmBackendConnector.js +50 -5
  89. package/dist/module/CallSettings/WxCallBackendConnector.js +54 -18
  90. package/dist/module/CallSettings/constants.js +12 -0
  91. package/dist/module/CallingClient/CallingClient.js +54 -16
  92. package/dist/module/CallingClient/calling/call.js +172 -121
  93. package/dist/module/CallingClient/calling/callManager.js +51 -26
  94. package/dist/module/CallingClient/constants.js +102 -2
  95. package/dist/module/CallingClient/line/index.js +37 -8
  96. package/dist/module/CallingClient/registration/register.js +151 -108
  97. package/dist/module/Contacts/ContactsClient.js +65 -21
  98. package/dist/module/Contacts/constants.js +10 -0
  99. package/dist/module/Errors/types.js +2 -0
  100. package/dist/module/Events/impl/index.js +1 -1
  101. package/dist/module/Metrics/index.js +57 -2
  102. package/dist/module/Metrics/types.js +3 -0
  103. package/dist/module/Voicemail/BroadworksBackendConnector.js +66 -17
  104. package/dist/module/Voicemail/UcmBackendConnector.js +51 -11
  105. package/dist/module/Voicemail/Voicemail.js +109 -9
  106. package/dist/module/Voicemail/WxCallBackendConnector.js +50 -17
  107. package/dist/module/Voicemail/constants.js +21 -0
  108. package/dist/module/common/Utils.js +51 -12
  109. package/dist/module/common/constants.js +1 -0
  110. package/dist/module/common/types.js +0 -7
  111. package/dist/types/CallHistory/CallHistory.d.ts.map +1 -1
  112. package/dist/types/CallHistory/constants.d.ts +6 -0
  113. package/dist/types/CallHistory/constants.d.ts.map +1 -1
  114. package/dist/types/CallSettings/CallSettings.d.ts.map +1 -1
  115. package/dist/types/CallSettings/UcmBackendConnector.d.ts.map +1 -1
  116. package/dist/types/CallSettings/WxCallBackendConnector.d.ts.map +1 -1
  117. package/dist/types/CallSettings/constants.d.ts +12 -0
  118. package/dist/types/CallSettings/constants.d.ts.map +1 -1
  119. package/dist/types/CallingClient/CallingClient.d.ts +2 -3
  120. package/dist/types/CallingClient/CallingClient.d.ts.map +1 -1
  121. package/dist/types/CallingClient/calling/call.d.ts.map +1 -1
  122. package/dist/types/CallingClient/calling/callManager.d.ts.map +1 -1
  123. package/dist/types/CallingClient/constants.d.ts +102 -2
  124. package/dist/types/CallingClient/constants.d.ts.map +1 -1
  125. package/dist/types/CallingClient/line/index.d.ts.map +1 -1
  126. package/dist/types/CallingClient/registration/register.d.ts +5 -2
  127. package/dist/types/CallingClient/registration/register.d.ts.map +1 -1
  128. package/dist/types/CallingClient/registration/types.d.ts +1 -0
  129. package/dist/types/CallingClient/registration/types.d.ts.map +1 -1
  130. package/dist/types/Contacts/ContactsClient.d.ts.map +1 -1
  131. package/dist/types/Contacts/constants.d.ts +10 -0
  132. package/dist/types/Contacts/constants.d.ts.map +1 -1
  133. package/dist/types/Errors/types.d.ts +2 -0
  134. package/dist/types/Errors/types.d.ts.map +1 -1
  135. package/dist/types/Metrics/index.d.ts +1 -1
  136. package/dist/types/Metrics/index.d.ts.map +1 -1
  137. package/dist/types/Metrics/types.d.ts +7 -2
  138. package/dist/types/Metrics/types.d.ts.map +1 -1
  139. package/dist/types/SDKConnector/types.d.ts +8 -2
  140. package/dist/types/SDKConnector/types.d.ts.map +1 -1
  141. package/dist/types/Voicemail/BroadworksBackendConnector.d.ts.map +1 -1
  142. package/dist/types/Voicemail/UcmBackendConnector.d.ts.map +1 -1
  143. package/dist/types/Voicemail/Voicemail.d.ts +1 -1
  144. package/dist/types/Voicemail/Voicemail.d.ts.map +1 -1
  145. package/dist/types/Voicemail/WxCallBackendConnector.d.ts.map +1 -1
  146. package/dist/types/Voicemail/constants.d.ts +21 -0
  147. package/dist/types/Voicemail/constants.d.ts.map +1 -1
  148. package/dist/types/common/Utils.d.ts +4 -4
  149. package/dist/types/common/Utils.d.ts.map +1 -1
  150. package/dist/types/common/constants.d.ts +1 -0
  151. package/dist/types/common/constants.d.ts.map +1 -1
  152. package/dist/types/common/types.d.ts +11 -11
  153. package/dist/types/common/types.d.ts.map +1 -1
  154. package/package.json +4 -5
  155. package/dist/CallingClient/registration/webWorker.js +0 -115
  156. package/dist/CallingClient/registration/webWorker.js.map +0 -1
  157. package/dist/CallingClient/registration/webWorker.test.js +0 -256
  158. package/dist/CallingClient/registration/webWorker.test.js.map +0 -1
  159. package/dist/module/CallingClient/registration/webWorker.js +0 -59
  160. package/dist/types/CallingClient/registration/webWorker.d.ts +0 -2
  161. package/dist/types/CallingClient/registration/webWorker.d.ts.map +0 -1
@@ -28,6 +28,7 @@ var _types3 = require("../../Errors/types");
28
28
  var _constants = require("../constants");
29
29
  var _types4 = require("../line/types");
30
30
  var _LineError = require("../../Errors/catalog/LineError");
31
+ var _types5 = require("../../Metrics/types");
31
32
  function _getRequireWildcardCache(e) { if ("function" != typeof _WeakMap) return null; var r = new _WeakMap(), t = new _WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
32
33
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = _Object$defineProperty && _Object$getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? _Object$getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? _Object$defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
33
34
  function ownKeys(e, r) { var t = _Object$keys2(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
@@ -37,9 +38,11 @@ var MockServiceData = {
37
38
  indicator: _types.ServiceIndicator.CALLING,
38
39
  domain: ''
39
40
  };
40
- var logSpy = jest.spyOn(_Logger.default, 'info');
41
+ var logSpy = jest.spyOn(_Logger.default, 'log');
42
+ var infoSpy = jest.spyOn(_Logger.default, 'info');
41
43
  var warnSpy = jest.spyOn(_Logger.default, 'warn');
42
44
  var handleErrorSpy = jest.spyOn(utils, 'handleRegistrationErrors');
45
+ jest.spyOn(utils, 'uploadLogs').mockResolvedValue();
43
46
  describe('Registration Tests', function () {
44
47
  var originalProcessNextTick = process.nextTick;
45
48
  function flushPromises() {
@@ -70,30 +73,64 @@ describe('Registration Tests', function () {
70
73
  });
71
74
  var failurePayload = {
72
75
  statusCode: 500,
73
- body: _registerFixtures.mockPostResponse
76
+ body: _registerFixtures.mockPostResponse,
77
+ headers: {
78
+ trackingid: 'webex-js-sdk_06bafdd0-2f9b-4cd7-b438-9c0d95ecec9b_15'
79
+ }
80
+ };
81
+ var failurePayload429One = {
82
+ statusCode: 429,
83
+ body: _registerFixtures.mockPostResponse,
84
+ headers: {
85
+ 'retry-after': 42
86
+ }
87
+ };
88
+ var failurePayload429Two = {
89
+ statusCode: 429,
90
+ body: _registerFixtures.mockPostResponse,
91
+ headers: {
92
+ 'retry-after': 33
93
+ }
94
+ };
95
+ var failurePayload429Three = {
96
+ statusCode: 429,
97
+ body: _registerFixtures.mockPostResponse,
98
+ headers: {
99
+ 'retry-after': 136
100
+ }
74
101
  };
75
- var failurePayload429 = {
102
+ var failurePayload429Four = {
76
103
  statusCode: 429,
77
- body: _registerFixtures.mockPostResponse
104
+ body: _registerFixtures.mockPostResponse,
105
+ headers: {
106
+ 'retry-after': 81
107
+ }
78
108
  };
79
109
  var successPayload = {
80
110
  statusCode: 200,
81
- body: _registerFixtures.mockPostResponse
111
+ body: _registerFixtures.mockPostResponse,
112
+ headers: {
113
+ trackingid: 'webex-js-sdk_06bafdd0-2f9b-4cd7-b438-9c0d95ecec9b_15'
114
+ }
82
115
  };
83
116
  var reg;
84
117
  var restartSpy;
85
- var failbackRetry429Spy;
86
118
  var restoreSpy;
87
119
  var postRegistrationSpy;
120
+ var failoverSpy;
121
+ var retry429Spy;
122
+ var metricSpy;
88
123
  var setupRegistration = function setupRegistration(mockServiceData) {
89
124
  var mutex = new _asyncMutex.Mutex();
90
125
  reg = (0, _register.createRegistration)(webex, mockServiceData, mutex, lineEmitter, _types2.LOGGER.INFO);
91
126
  reg.setMobiusServers(mobiusUris.primary, mobiusUris.backup);
92
127
  jest.clearAllMocks();
93
128
  restartSpy = jest.spyOn(reg, 'restartRegistration');
94
- failbackRetry429Spy = jest.spyOn(reg, _constants.FAILBACK_429_RETRY_UTIL);
95
129
  restoreSpy = jest.spyOn(reg, 'restorePreviousRegistration');
96
130
  postRegistrationSpy = jest.spyOn(reg, 'postRegistration');
131
+ failoverSpy = jest.spyOn(reg, 'startFailoverTimer');
132
+ retry429Spy = jest.spyOn(reg, 'handle429Retry');
133
+ metricSpy = jest.spyOn(reg.metricManager, 'submitRegistrationMetric');
97
134
  };
98
135
  beforeEach(function () {
99
136
  setupRegistration(MockServiceData);
@@ -109,7 +146,10 @@ describe('Registration Tests', function () {
109
146
  while (1) switch (_context.prev = _context.next) {
110
147
  case 0:
111
148
  webex.request.mockReturnValueOnce({
112
- body: _registerFixtures.mockPostResponse
149
+ body: _registerFixtures.mockPostResponse,
150
+ headers: {
151
+ trackingid: 'webex-js-sdk_06bafdd0-2f9b-4cd7-b438-9c0d95ecec9b_15'
152
+ }
113
153
  });
114
154
  _context.next = 3;
115
155
  return reg.triggerRegistration();
@@ -121,7 +161,14 @@ describe('Registration Tests', function () {
121
161
  expect(lineEmitter).toBeCalledTimes(2);
122
162
  expect(lineEmitter).toBeCalledWith(_types4.LINE_EVENTS.CONNECTING);
123
163
  expect(lineEmitter).toBeCalledWith(_types4.LINE_EVENTS.REGISTERED, _registerFixtures.mockPostResponse);
124
- case 8:
164
+
165
+ // Check that log.log was called for successful registration
166
+ expect(logSpy).toBeCalledWith("Registration successful for deviceId: ".concat(_registerFixtures.mockPostResponse.device.deviceId, " userId: ").concat(_registerFixtures.mockPostResponse.userId), expect.objectContaining({
167
+ file: _constants.REGISTRATION_FILE,
168
+ method: expect.any(String)
169
+ }));
170
+ expect(metricSpy).toBeCalledWith(_types5.METRIC_EVENT.REGISTRATION, _types5.REG_ACTION.REGISTER, _types5.METRIC_TYPE.BEHAVIORAL, _constants.REGISTRATION_UTIL, 'PRIMARY', 'webex-js-sdk_06bafdd0-2f9b-4cd7-b438-9c0d95ecec9b_15', undefined, undefined);
171
+ case 10:
125
172
  case "end":
126
173
  return _context.stop();
127
174
  }
@@ -134,7 +181,8 @@ describe('Registration Tests', function () {
134
181
  case 0:
135
182
  webex.request.mockRejectedValue({
136
183
  body: _registerFixtures.mockPostResponse,
137
- statusCode: 401
184
+ statusCode: 401,
185
+ headers: {}
138
186
  });
139
187
  _context2.next = 3;
140
188
  return reg.triggerRegistration();
@@ -147,7 +195,8 @@ describe('Registration Tests', function () {
147
195
  expect(lineEmitter).toBeCalledTimes(2);
148
196
  expect(lineEmitter).nthCalledWith(1, _types4.LINE_EVENTS.CONNECTING);
149
197
  expect(lineEmitter).nthCalledWith(2, _types4.LINE_EVENTS.ERROR, undefined, error);
150
- case 9:
198
+ expect(metricSpy).toBeCalledWith(_types5.METRIC_EVENT.REGISTRATION_ERROR, _types5.REG_ACTION.REGISTER, _types5.METRIC_TYPE.BEHAVIORAL, _constants.REGISTRATION_UTIL, 'PRIMARY', '', undefined, error);
199
+ case 10:
151
200
  case "end":
152
201
  return _context2.stop();
153
202
  }
@@ -166,7 +215,10 @@ describe('Registration Tests', function () {
166
215
  statusCode: 403
167
216
  }).mockResolvedValueOnce({
168
217
  statusCode: 200,
169
- body: _registerFixtures.mockPostResponse
218
+ body: _registerFixtures.mockPostResponse,
219
+ headers: {
220
+ trackingid: 'webex-js-sdk_06bafdd0-2f9b-4cd7-b438-9c0d95ecec9b_15'
221
+ }
170
222
  });
171
223
  global.fetch = jest.fn(function () {
172
224
  return _promise.default.resolve({
@@ -188,34 +240,360 @@ describe('Registration Tests', function () {
188
240
  headers: expect.anything()
189
241
  });
190
242
  expect(warnSpy).toBeCalledWith('User device limit exceeded', expect.anything());
191
- expect(logSpy).toBeCalledWith('Registration restoration in progress.', expect.anything());
192
- expect(logSpy).toBeCalledWith('Registration restored successfully.', expect.anything());
243
+ expect(infoSpy).toBeCalledWith('Registration restoration in progress.', expect.anything());
244
+ expect(infoSpy).toBeCalledWith('Registration restored successfully.', expect.anything());
193
245
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
194
246
  expect(lineEmitter).toBeCalledTimes(4);
195
247
  expect(lineEmitter).nthCalledWith(1, _types4.LINE_EVENTS.CONNECTING);
196
248
  expect(lineEmitter).nthCalledWith(2, _types4.LINE_EVENTS.UNREGISTERED);
197
249
  expect(lineEmitter).nthCalledWith(3, _types4.LINE_EVENTS.CONNECTING);
198
250
  expect(lineEmitter).nthCalledWith(4, _types4.LINE_EVENTS.REGISTERED, _registerFixtures.mockPostResponse);
199
- case 17:
251
+ expect(metricSpy).toBeCalledWith(_types5.METRIC_EVENT.REGISTRATION, _types5.REG_ACTION.REGISTER, _types5.METRIC_TYPE.BEHAVIORAL, _constants.REGISTRATION_UTIL, 'UNKNOWN', 'webex-js-sdk_06bafdd0-2f9b-4cd7-b438-9c0d95ecec9b_15', undefined, undefined);
252
+ case 18:
200
253
  case "end":
201
254
  return _context3.stop();
202
255
  }
203
256
  }, _callee3);
204
257
  })));
205
- describe('Registration failover tests', function () {
206
- it('verify unreachable primary with reachable backup servers', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4() {
258
+ describe('429 handling tests', function () {
259
+ var loggerContext = {
260
+ file: _constants.REGISTRATION_FILE,
261
+ method: _constants.FAILOVER_UTIL
262
+ };
263
+ var logSpy = jest.spyOn(_Logger.default, 'log');
264
+ beforeEach(function () {
265
+ mobiusUris.backup.pop();
266
+ });
267
+ afterEach(function () {
268
+ mobiusUris.backup.push(_registerFixtures.URL);
269
+ jest.clearAllMocks();
270
+ });
271
+ it('handle 429 received during initial registration failure and first attempt with primary', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4() {
207
272
  return _regenerator.default.wrap(function _callee4$(_context4) {
208
273
  while (1) switch (_context4.prev = _context4.next) {
274
+ case 0:
275
+ jest.useFakeTimers();
276
+ logSpy.mockClear();
277
+ webex.request.mockRejectedValueOnce(failurePayload429One).mockRejectedValueOnce(failurePayload429Two).mockRejectedValueOnce(failurePayload);
278
+ _context4.next = 5;
279
+ return reg.triggerRegistration();
280
+ case 5:
281
+ /* Initial registration failed with 429 with higher retyrAfter, interval should be updtaed with retryAfter.
282
+ * The first attempt to register with primary should be made after retryAfter seconds.
283
+ */
284
+
285
+ expect(webex.request).toHaveBeenNthCalledWith(1, _objectSpread(_objectSpread({}, mockResponse), {}, {
286
+ method: 'POST',
287
+ uri: "".concat(mobiusUris.primary[0], "device")
288
+ }));
289
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
290
+ expect(retry429Spy).toBeCalledOnceWith(failurePayload429One.headers['retry-after'], 'triggerRegistration');
291
+ expect(reg.retryAfter).toEqual(failurePayload429One.headers['retry-after']);
292
+ expect(failoverSpy).toBeCalledOnceWith();
293
+ expect(logSpy).toBeCalledWith("Scheduled retry with primary in ".concat(failurePayload429One.headers['retry-after'], " seconds, number of attempts : 1"), loggerContext);
294
+ retry429Spy.mockClear();
295
+ failoverSpy.mockClear();
296
+ jest.advanceTimersByTime(Number(failurePayload429One.headers['retry-after']) * _constants.SEC_TO_MSEC_MFACTOR);
297
+ _context4.next = 16;
298
+ return flushPromises();
299
+ case 16:
300
+ /* The first attempt to register with primary failed with 429 with lower retryAfter, interval should remain the same.
301
+ * The second attempt to register with primary will be scheduled as per the interval calculated.
302
+ */
303
+
304
+ expect(webex.request).toHaveBeenNthCalledWith(2, _objectSpread(_objectSpread({}, mockResponse), {}, {
305
+ method: 'POST',
306
+ uri: "".concat(mobiusUris.primary[0], "device")
307
+ }));
308
+ expect(retry429Spy).toBeCalledOnceWith(failurePayload429Two.headers['retry-after'], 'startFailoverTimer');
309
+ expect(reg.retryAfter).toEqual(failurePayload429Two.headers['retry-after']);
310
+ expect(failoverSpy).toBeCalledOnceWith(2, failurePayload429One.headers['retry-after']);
311
+ retry429Spy.mockClear();
312
+ failoverSpy.mockClear();
313
+ jest.advanceTimersByTime(43 * _constants.SEC_TO_MSEC_MFACTOR);
314
+ _context4.next = 25;
315
+ return flushPromises();
316
+ case 25:
317
+ /* The second attempt to register with primary failed with 500, the retryAfter should be undefined.
318
+ * The third attempt to register with primary will be scheduled as per the interval calculated.
319
+ */
320
+ expect(webex.request).toHaveBeenNthCalledWith(3, _objectSpread(_objectSpread({}, mockResponse), {}, {
321
+ method: 'POST',
322
+ uri: "".concat(mobiusUris.primary[0], "device")
323
+ }));
324
+ expect(retry429Spy).not.toBeCalled();
325
+ expect(reg.retryAfter).toEqual(undefined);
326
+ expect(failoverSpy).toBeCalledOnceWith(3, 85);
327
+ case 29:
328
+ case "end":
329
+ return _context4.stop();
330
+ }
331
+ }, _callee4);
332
+ })));
333
+ it('handle 429 received with higher retryAfter than the interval when interval with elapsedTime is already reaching threshold timer so we failover immediately', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5() {
334
+ return _regenerator.default.wrap(function _callee5$(_context5) {
335
+ while (1) switch (_context5.prev = _context5.next) {
336
+ case 0:
337
+ reg.isCCFlow = true;
338
+ jest.spyOn(reg, 'getRegRetryInterval').mockReturnValueOnce(33).mockReturnValueOnce(40).mockReturnValueOnce(47).mockReturnValueOnce(52);
339
+ jest.useFakeTimers();
340
+ webex.request.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload429One).mockResolvedValueOnce(successPayload);
341
+ _context5.next = 6;
342
+ return reg.triggerRegistration();
343
+ case 6:
344
+ expect(webex.request).toHaveBeenNthCalledWith(1, _objectSpread(_objectSpread({}, mockResponse), {}, {
345
+ method: 'POST',
346
+ uri: "".concat(mobiusUris.primary[0], "device")
347
+ }));
348
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
349
+ expect(retry429Spy).not.toBeCalled();
350
+ expect(failoverSpy).toBeCalledOnceWith();
351
+ expect(logSpy).toBeCalledWith("Scheduled retry with primary in 33 seconds, number of attempts : 1", loggerContext);
352
+ failoverSpy.mockClear();
353
+ jest.advanceTimersByTime(33 * _constants.SEC_TO_MSEC_MFACTOR);
354
+ _context5.next = 15;
355
+ return flushPromises();
356
+ case 15:
357
+ expect(webex.request).toHaveBeenNthCalledWith(2, _objectSpread(_objectSpread({}, mockResponse), {}, {
358
+ method: 'POST',
359
+ uri: "".concat(mobiusUris.primary[0], "device")
360
+ }));
361
+ expect(retry429Spy).not.toBeCalled();
362
+ expect(failoverSpy).toBeCalledOnceWith(2, 33);
363
+ expect(logSpy).toBeCalledWith("Scheduled retry with primary in 40 seconds, number of attempts : 2", loggerContext);
364
+ logSpy.mockClear();
365
+ failoverSpy.mockClear();
366
+ jest.advanceTimersByTime(40 * _constants.SEC_TO_MSEC_MFACTOR);
367
+ _context5.next = 24;
368
+ return flushPromises();
369
+ case 24:
370
+ expect(webex.request).toHaveBeenNthCalledWith(3, _objectSpread(_objectSpread({}, mockResponse), {}, {
371
+ method: 'POST',
372
+ uri: "".concat(mobiusUris.primary[0], "device")
373
+ }));
374
+ expect(retry429Spy).toBeCalledOnceWith(failurePayload429One.headers['retry-after'], 'startFailoverTimer');
375
+ expect(failoverSpy).toBeCalledOnceWith(3, 73);
376
+ expect(logSpy).not.toBeCalledWith("Scheduled retry with primary in ".concat(failurePayload429One.headers['retry-after'], " seconds, number of attempts : 3"), loggerContext);
377
+ expect(infoSpy).toBeCalledWith("Failing over to backup servers.", loggerContext);
378
+ expect(webex.request).toHaveBeenNthCalledWith(4, _objectSpread(_objectSpread({}, mockResponse), {}, {
379
+ method: 'POST',
380
+ uri: "".concat(mobiusUris.backup[0], "device")
381
+ }));
382
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
383
+ case 31:
384
+ case "end":
385
+ return _context5.stop();
386
+ }
387
+ }, _callee5);
388
+ })));
389
+ it('handle 429 received while the last attempt for primary', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee6() {
390
+ return _regenerator.default.wrap(function _callee6$(_context6) {
391
+ while (1) switch (_context6.prev = _context6.next) {
392
+ case 0:
393
+ reg.isCCFlow = true;
394
+ jest.spyOn(reg, 'getRegRetryInterval').mockReturnValueOnce(33).mockReturnValueOnce(40).mockReturnValueOnce(47).mockReturnValueOnce(52);
395
+ jest.useFakeTimers();
396
+ webex.request.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload429One).mockResolvedValueOnce(successPayload);
397
+ _context6.next = 6;
398
+ return reg.triggerRegistration();
399
+ case 6:
400
+ /* Initial registration and first 2 attempts with primary failed with non-final 5xx error responses.
401
+ * Last attempt with primary failed with 429, the retryAfter should be used to schedule the next attempt but
402
+ * the failover is triggered before the scheduling logic kicks in.
403
+ */
404
+ expect(webex.request).toHaveBeenNthCalledWith(1, _objectSpread(_objectSpread({}, mockResponse), {}, {
405
+ method: 'POST',
406
+ uri: "".concat(mobiusUris.primary[0], "device")
407
+ }));
408
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
409
+ expect(retry429Spy).not.toBeCalled();
410
+ expect(failoverSpy).toBeCalledOnceWith();
411
+ expect(logSpy).toBeCalledWith("Scheduled retry with primary in 33 seconds, number of attempts : 1", loggerContext);
412
+ failoverSpy.mockClear();
413
+ jest.advanceTimersByTime(33 * _constants.SEC_TO_MSEC_MFACTOR);
414
+ _context6.next = 15;
415
+ return flushPromises();
416
+ case 15:
417
+ expect(webex.request).toHaveBeenNthCalledWith(2, _objectSpread(_objectSpread({}, mockResponse), {}, {
418
+ method: 'POST',
419
+ uri: "".concat(mobiusUris.primary[0], "device")
420
+ }));
421
+ expect(retry429Spy).not.toBeCalled();
422
+ expect(failoverSpy).toBeCalledOnceWith(2, 33);
423
+ expect(logSpy).toBeCalledWith("Scheduled retry with primary in 40 seconds, number of attempts : 2", loggerContext);
424
+ logSpy.mockClear();
425
+ failoverSpy.mockClear();
426
+ jest.advanceTimersByTime(40 * _constants.SEC_TO_MSEC_MFACTOR);
427
+ _context6.next = 24;
428
+ return flushPromises();
429
+ case 24:
430
+ expect(webex.request).toHaveBeenNthCalledWith(3, _objectSpread(_objectSpread({}, mockResponse), {}, {
431
+ method: 'POST',
432
+ uri: "".concat(mobiusUris.primary[0], "device")
433
+ }));
434
+ expect(retry429Spy).not.toBeCalled();
435
+ expect(failoverSpy).toBeCalledOnceWith(3, 73);
436
+ expect(logSpy).toBeCalledWith("Scheduled retry with primary in 41 seconds, number of attempts : 3", loggerContext);
437
+ failoverSpy.mockClear();
438
+ jest.advanceTimersByTime(41 * _constants.SEC_TO_MSEC_MFACTOR);
439
+ _context6.next = 32;
440
+ return flushPromises();
441
+ case 32:
442
+ expect(webex.request).toHaveBeenNthCalledWith(4, _objectSpread(_objectSpread({}, mockResponse), {}, {
443
+ method: 'POST',
444
+ uri: "".concat(mobiusUris.primary[0], "device")
445
+ }));
446
+ expect(retry429Spy).toBeCalledOnceWith(failurePayload429One.headers['retry-after'], 'startFailoverTimer');
447
+ expect(failoverSpy).toBeCalledOnceWith(4, 114);
448
+ expect(infoSpy).toBeCalledWith("Failing over to backup servers.", loggerContext);
449
+ expect(webex.request).toHaveBeenNthCalledWith(5, _objectSpread(_objectSpread({}, mockResponse), {}, {
450
+ method: 'POST',
451
+ uri: "".concat(mobiusUris.backup[0], "device")
452
+ }));
453
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
454
+ case 38:
455
+ case "end":
456
+ return _context6.stop();
457
+ }
458
+ }, _callee6);
459
+ })));
460
+ it('handle 429 received while failing over to backup server for CC flow', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee7() {
461
+ return _regenerator.default.wrap(function _callee7$(_context7) {
462
+ while (1) switch (_context7.prev = _context7.next) {
463
+ case 0:
464
+ reg.isCCFlow = true;
465
+ jest.useFakeTimers();
466
+ webex.request.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload429One).mockResolvedValueOnce(successPayload);
467
+ _context7.next = 5;
468
+ return reg.triggerRegistration();
469
+ case 5:
470
+ jest.advanceTimersByTime(_constants.REG_TRY_BACKUP_TIMER_VAL_FOR_CC_IN_SEC * _constants.SEC_TO_MSEC_MFACTOR);
471
+ _context7.next = 8;
472
+ return flushPromises();
473
+ case 8:
474
+ expect(webex.request).toBeCalledTimes(3);
475
+ expect(webex.request).toHaveBeenNthCalledWith(1, _objectSpread(_objectSpread({}, mockResponse), {}, {
476
+ method: 'POST',
477
+ uri: "".concat(mobiusUris.primary[0], "device")
478
+ }));
479
+ expect(webex.request).toHaveBeenNthCalledWith(2, _objectSpread(_objectSpread({}, mockResponse), {}, {
480
+ method: 'POST',
481
+ uri: "".concat(mobiusUris.primary[0], "device")
482
+ }));
483
+
484
+ /* Failover to backup server failed with 429, the retryAfter is used to schedule the next attempt with backup server.
485
+ * Interval will be updated with retryAfter as interval calculated is less than the retryAfter.
486
+ */
487
+ expect(webex.request).toHaveBeenNthCalledWith(3, _objectSpread(_objectSpread({}, mockResponse), {}, {
488
+ method: 'POST',
489
+ uri: "".concat(mobiusUris.backup[0], "device")
490
+ }));
491
+ expect(retry429Spy).toBeCalledOnceWith(failurePayload429One.headers['retry-after'], 'startFailoverTimer');
492
+ expect(logSpy).toBeCalledWith("Scheduled retry with backup servers in ".concat(failurePayload429One.headers['retry-after'], " seconds."), loggerContext);
493
+ webex.request.mockClear();
494
+ jest.advanceTimersByTime(Number(failurePayload429One.headers['retry-after']) * _constants.SEC_TO_MSEC_MFACTOR);
495
+ _context7.next = 18;
496
+ return flushPromises();
497
+ case 18:
498
+ expect(webex.request).toBeCalledOnceWith(_objectSpread(_objectSpread({}, mockResponse), {}, {
499
+ method: 'POST',
500
+ uri: "".concat(mobiusUris.backup[0], "device")
501
+ }));
502
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
503
+ case 20:
504
+ case "end":
505
+ return _context7.stop();
506
+ }
507
+ }, _callee7);
508
+ })));
509
+ it('checking the retryAfter exceeding the threshold timers in first attempt itself', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee8() {
510
+ return _regenerator.default.wrap(function _callee8$(_context8) {
511
+ while (1) switch (_context8.prev = _context8.next) {
512
+ case 0:
513
+ reg.isCCFlow = true;
514
+ jest.useFakeTimers();
515
+ jest.spyOn(reg, 'getRegRetryInterval').mockReturnValueOnce(40);
516
+ webex.request.mockRejectedValueOnce(failurePayload429Three);
517
+ _context8.next = 6;
518
+ return reg.triggerRegistration();
519
+ case 6:
520
+ expect(webex.request).toHaveBeenNthCalledWith(1, _objectSpread(_objectSpread({}, mockResponse), {}, {
521
+ method: 'POST',
522
+ uri: "".concat(mobiusUris.primary[0], "device")
523
+ }));
524
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
525
+ expect(failoverSpy).toBeCalledOnceWith();
526
+ expect(infoSpy).toBeCalledWith("Failing over to backup servers.", loggerContext);
527
+ expect(logSpy).not.toBeCalledWith("Scheduled retry with primary in 40 seconds, number of attempts : 1", loggerContext);
528
+ expect(logSpy).not.toBeCalledWith("Scheduled retry with primary in ".concat(failurePayload429Three.headers['retry-after'], " seconds, number of attempts : 1"), loggerContext);
529
+ expect(webex.request).toHaveBeenNthCalledWith(2, _objectSpread(_objectSpread({}, mockResponse), {}, {
530
+ method: 'POST',
531
+ uri: "".concat(mobiusUris.backup[0], "device")
532
+ }));
533
+ case 13:
534
+ case "end":
535
+ return _context8.stop();
536
+ }
537
+ }, _callee8);
538
+ })));
539
+ it('checking the retryAfter exceeding the threshold timers in later attempts', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee9() {
540
+ return _regenerator.default.wrap(function _callee9$(_context9) {
541
+ while (1) switch (_context9.prev = _context9.next) {
542
+ case 0:
543
+ reg.isCCFlow = true;
544
+ jest.useFakeTimers();
545
+ jest.spyOn(reg, 'getRegRetryInterval').mockReturnValueOnce(39).mockReturnValueOnce(43);
546
+ webex.request.mockRejectedValueOnce(failurePayload429One).mockRejectedValueOnce(failurePayload429Four).mockResolvedValueOnce(successPayload);
547
+ _context9.next = 6;
548
+ return reg.triggerRegistration();
549
+ case 6:
550
+ expect(webex.request).toHaveBeenNthCalledWith(1, _objectSpread(_objectSpread({}, mockResponse), {}, {
551
+ method: 'POST',
552
+ uri: "".concat(mobiusUris.primary[0], "device")
553
+ }));
554
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
555
+ expect(failoverSpy).toBeCalledOnceWith();
556
+ expect(logSpy).toBeCalledWith("Scheduled retry with primary in ".concat(failurePayload429One.headers['retry-after'], " seconds, number of attempts : 1"), loggerContext);
557
+ failoverSpy.mockClear();
558
+ jest.advanceTimersByTime(Number(failurePayload429One.headers['retry-after']) * _constants.SEC_TO_MSEC_MFACTOR);
559
+ _context9.next = 14;
560
+ return flushPromises();
561
+ case 14:
562
+ expect(webex.request).toHaveBeenNthCalledWith(2, _objectSpread(_objectSpread({}, mockResponse), {}, {
563
+ method: 'POST',
564
+ uri: "".concat(mobiusUris.primary[0], "device")
565
+ }));
566
+ expect(failoverSpy).toBeCalledOnceWith(2, failurePayload429One.headers['retry-after']);
567
+ expect(logSpy).not.toBeCalledWith("Scheduled retry with primary in 43 seconds, number of attempts : 2", loggerContext);
568
+ expect(infoSpy).toBeCalledWith("Failing over to backup servers.", loggerContext);
569
+ expect(logSpy).not.toBeCalledWith("Scheduled retry with primary in ".concat(failurePayload429Four.headers['retry-after'], " seconds, number of attempts : 2"), loggerContext);
570
+ expect(infoSpy).toBeCalledWith("Failing over to backup servers.", loggerContext);
571
+ expect(webex.request).toHaveBeenNthCalledWith(3, _objectSpread(_objectSpread({}, mockResponse), {}, {
572
+ method: 'POST',
573
+ uri: "".concat(mobiusUris.backup[0], "device")
574
+ }));
575
+ expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
576
+ case 22:
577
+ case "end":
578
+ return _context9.stop();
579
+ }
580
+ }, _callee9);
581
+ })));
582
+ });
583
+ describe('Registration failover tests', function () {
584
+ it('verify unreachable primary with reachable backup servers', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee10() {
585
+ return _regenerator.default.wrap(function _callee10$(_context10) {
586
+ while (1) switch (_context10.prev = _context10.next) {
209
587
  case 0:
210
588
  jest.useFakeTimers();
211
589
  // try the primary twice and register successfully with backup servers
212
590
  webex.request.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockResolvedValueOnce(successPayload);
213
591
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.IDLE);
214
- _context4.next = 5;
592
+ _context10.next = 5;
215
593
  return reg.triggerRegistration();
216
594
  case 5:
217
595
  jest.advanceTimersByTime(_constants.REG_TRY_BACKUP_TIMER_VAL_IN_SEC * _constants.SEC_TO_MSEC_MFACTOR);
218
- _context4.next = 8;
596
+ _context10.next = 8;
219
597
  return flushPromises();
220
598
  case 8:
221
599
  expect(webex.request).toBeCalledTimes(3);
@@ -230,15 +608,16 @@ describe('Registration Tests', function () {
230
608
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
231
609
  /* Active Url must match with the backup url as per the test */
232
610
  expect(reg.getActiveMobiusUrl()).toEqual(mobiusUris.backup[0]);
233
- case 13:
611
+ expect(metricSpy).toHaveBeenNthCalledWith(3, _types5.METRIC_EVENT.REGISTRATION, _types5.REG_ACTION.REGISTER, _types5.METRIC_TYPE.BEHAVIORAL, _constants.FAILOVER_UTIL, 'BACKUP', 'webex-js-sdk_06bafdd0-2f9b-4cd7-b438-9c0d95ecec9b_15', undefined, undefined);
612
+ case 14:
234
613
  case "end":
235
- return _context4.stop();
614
+ return _context10.stop();
236
615
  }
237
- }, _callee4);
616
+ }, _callee10);
238
617
  })));
239
- it('cc: verify unreachable primary with reachable backup server', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5() {
240
- return _regenerator.default.wrap(function _callee5$(_context5) {
241
- while (1) switch (_context5.prev = _context5.next) {
618
+ it('cc: verify unreachable primary with reachable backup server', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee11() {
619
+ return _regenerator.default.wrap(function _callee11$(_context11) {
620
+ while (1) switch (_context11.prev = _context11.next) {
242
621
  case 0:
243
622
  setupRegistration(_objectSpread(_objectSpread({}, MockServiceData), {}, {
244
623
  indicator: _types.ServiceIndicator.CONTACT_CENTER
@@ -246,11 +625,11 @@ describe('Registration Tests', function () {
246
625
  jest.useFakeTimers();
247
626
  webex.request.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockResolvedValueOnce(successPayload);
248
627
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.IDLE);
249
- _context5.next = 6;
628
+ _context11.next = 6;
250
629
  return reg.triggerRegistration();
251
630
  case 6:
252
631
  jest.advanceTimersByTime(_constants.REG_TRY_BACKUP_TIMER_VAL_FOR_CC_IN_SEC * _constants.SEC_TO_MSEC_MFACTOR);
253
- _context5.next = 9;
632
+ _context11.next = 9;
254
633
  return flushPromises();
255
634
  case 9:
256
635
  expect(webex.request).toBeCalledTimes(3);
@@ -267,27 +646,27 @@ describe('Registration Tests', function () {
267
646
  expect(reg.getActiveMobiusUrl()).toEqual(mobiusUris.backup[0]);
268
647
  case 14:
269
648
  case "end":
270
- return _context5.stop();
649
+ return _context11.stop();
271
650
  }
272
- }, _callee5);
651
+ }, _callee11);
273
652
  })));
274
- it('verify unreachable primary and backup servers', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee6() {
275
- return _regenerator.default.wrap(function _callee6$(_context6) {
276
- while (1) switch (_context6.prev = _context6.next) {
653
+ it('verify unreachable primary and backup servers', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee12() {
654
+ return _regenerator.default.wrap(function _callee12$(_context12) {
655
+ while (1) switch (_context12.prev = _context12.next) {
277
656
  case 0:
278
657
  jest.useFakeTimers();
279
658
  // try the primary twice and register successfully with backup servers
280
659
  webex.request.mockRejectedValue(failurePayload);
281
660
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.IDLE);
282
- _context6.next = 5;
661
+ _context12.next = 5;
283
662
  return reg.triggerRegistration();
284
663
  case 5:
285
664
  jest.advanceTimersByTime(_constants.REG_TRY_BACKUP_TIMER_VAL_IN_SEC * _constants.SEC_TO_MSEC_MFACTOR);
286
- _context6.next = 8;
665
+ _context12.next = 8;
287
666
  return flushPromises();
288
667
  case 8:
289
668
  jest.advanceTimersByTime(_constants.REG_TRY_BACKUP_TIMER_VAL_IN_SEC * _constants.SEC_TO_MSEC_MFACTOR);
290
- _context6.next = 11;
669
+ _context12.next = 11;
291
670
  return flushPromises();
292
671
  case 11:
293
672
  /*
@@ -312,26 +691,27 @@ describe('Registration Tests', function () {
312
691
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
313
692
  case 17:
314
693
  case "end":
315
- return _context6.stop();
694
+ return _context12.stop();
316
695
  }
317
- }, _callee6);
696
+ }, _callee12);
318
697
  })));
319
698
  });
320
699
  describe('Registration failback tests', function () {
321
- beforeEach( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee7() {
322
- return _regenerator.default.wrap(function _callee7$(_context7) {
323
- while (1) switch (_context7.prev = _context7.next) {
700
+ beforeEach( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee13() {
701
+ return _regenerator.default.wrap(function _callee13$(_context13) {
702
+ while (1) switch (_context13.prev = _context13.next) {
324
703
  case 0:
325
704
  /* keep keepalive as active so that it wont interfere with the failback tests */
705
+ jest.spyOn(reg, 'postKeepAlive').mockResolvedValue(successPayload);
326
706
  jest.useFakeTimers();
327
707
  postRegistrationSpy.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockResolvedValueOnce(successPayload);
328
- _context7.next = 4;
708
+ _context13.next = 5;
329
709
  return reg.triggerRegistration();
330
- case 4:
710
+ case 5:
331
711
  jest.advanceTimersByTime(_constants.REG_TRY_BACKUP_TIMER_VAL_IN_SEC * _constants.SEC_TO_MSEC_MFACTOR);
332
- _context7.next = 7;
712
+ _context13.next = 8;
333
713
  return flushPromises();
334
- case 7:
714
+ case 8:
335
715
  reg.rehomingIntervalMin = _constants.DEFAULT_REHOMING_INTERVAL_MIN;
336
716
  reg.rehomingIntervalMax = _constants.DEFAULT_REHOMING_INTERVAL_MAX;
337
717
 
@@ -341,19 +721,19 @@ describe('Registration Tests', function () {
341
721
  /* Active Url must match with the backup url as per the test */
342
722
  expect(reg.getActiveMobiusUrl()).toStrictEqual(mobiusUris.backup[0]);
343
723
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
344
- case 12:
724
+ case 13:
345
725
  case "end":
346
- return _context7.stop();
726
+ return _context13.stop();
347
727
  }
348
- }, _callee7);
728
+ }, _callee13);
349
729
  })));
350
730
  afterEach(function () {
351
731
  jest.clearAllTimers();
352
732
  jest.clearAllMocks();
353
733
  });
354
- it('verify 429 error with failback to primary after initial registration with backup: Restore failure', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee8() {
355
- return _regenerator.default.wrap(function _callee8$(_context8) {
356
- while (1) switch (_context8.prev = _context8.next) {
734
+ it('verify 429 error with failback to primary after initial registration with backup: Restore failure', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee14() {
735
+ return _regenerator.default.wrap(function _callee14$(_context14) {
736
+ while (1) switch (_context14.prev = _context14.next) {
357
737
  case 0:
358
738
  // delete should be successful
359
739
  global.fetch = jest.fn(function () {
@@ -363,61 +743,66 @@ describe('Registration Tests', function () {
363
743
  }
364
744
  });
365
745
  });
366
- postRegistrationSpy.mockRejectedValue(failurePayload429);
746
+ postRegistrationSpy.mockRejectedValue(failurePayload429Two);
367
747
 
368
748
  /* Wait for failback to be triggered. */
369
749
  jest.advanceTimersByTime(reg.rehomingIntervalMax * _constants.MINUTES_TO_SEC_MFACTOR * _constants.SEC_TO_MSEC_MFACTOR);
370
- _context8.next = 5;
750
+ _context14.next = 5;
371
751
  return flushPromises();
372
752
  case 5:
373
- expect(logSpy).toBeCalledWith("Attempting failback to primary.", {
753
+ expect(infoSpy).toBeCalledWith("Attempting failback to primary.", {
374
754
  method: 'executeFailback',
375
755
  file: _constants.REGISTRATION_FILE
376
756
  });
377
- expect(failbackRetry429Spy).toBeCalledOnceWith();
757
+ jest.advanceTimersByTime(10000);
758
+ _context14.next = 9;
759
+ return flushPromises();
760
+ case 9:
761
+ expect(retry429Spy).toBeCalledWith(failurePayload429Two.headers['retry-after'], 'executeFailback');
378
762
  expect(reg.failback429RetryAttempts).toBe(0);
379
763
  expect(reg.getStatus()).toBe(_types.RegistrationStatus.INACTIVE);
380
- expect(restoreSpy).toBeCalledOnceWith(_constants.FAILBACK_429_RETRY_UTIL);
381
- expect(restartSpy).toBeCalledOnceWith(_constants.FAILBACK_429_RETRY_UTIL);
764
+ expect(restoreSpy).toBeCalledOnceWith(_constants.REG_429_RETRY_UTIL);
765
+ expect(restartSpy).toBeCalledOnceWith(_constants.REG_429_RETRY_UTIL);
382
766
  expect(reg.failbackTimer).toBe(undefined);
383
767
  expect(reg.rehomingIntervalMin).toBe(_constants.DEFAULT_REHOMING_INTERVAL_MIN);
384
768
  expect(reg.rehomingIntervalMax).toBe(_constants.DEFAULT_REHOMING_INTERVAL_MAX);
385
- case 14:
769
+ case 17:
386
770
  case "end":
387
- return _context8.stop();
771
+ return _context14.stop();
388
772
  }
389
- }, _callee8);
773
+ }, _callee14);
390
774
  })));
391
- it('verify unsuccessful failback to primary after initial registration with backup: Restore failure', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee9() {
392
- return _regenerator.default.wrap(function _callee9$(_context9) {
393
- while (1) switch (_context9.prev = _context9.next) {
775
+ it('verify unsuccessful failback to primary after initial registration with backup: Restore failure', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee15() {
776
+ return _regenerator.default.wrap(function _callee15$(_context15) {
777
+ while (1) switch (_context15.prev = _context15.next) {
394
778
  case 0:
395
779
  postRegistrationSpy.mockRejectedValue(failurePayload);
396
780
 
397
781
  /* Wait for failback to be triggered. */
398
782
  jest.advanceTimersByTime(reg.rehomingIntervalMax * _constants.MINUTES_TO_SEC_MFACTOR * _constants.SEC_TO_MSEC_MFACTOR);
399
- _context9.next = 4;
783
+ _context15.next = 4;
400
784
  return flushPromises();
401
785
  case 4:
402
- expect(logSpy).toBeCalledWith("Attempting failback to primary.", {
786
+ expect(infoSpy).toBeCalledWith("Attempting failback to primary.", {
403
787
  method: 'executeFailback',
404
788
  file: _constants.REGISTRATION_FILE
405
789
  });
406
790
  expect(reg.getStatus()).toBe(_types.RegistrationStatus.INACTIVE);
407
791
  expect(restoreSpy).toBeCalledOnceWith(_constants.FAILBACK_UTIL);
792
+ expect(reg.getStatus()).toBe(_types.RegistrationStatus.INACTIVE);
408
793
  expect(restartSpy).toBeCalledOnceWith(_constants.FAILBACK_UTIL);
409
794
  expect(reg.rehomingIntervalMin).toBe(_constants.DEFAULT_REHOMING_INTERVAL_MIN);
410
795
  expect(reg.rehomingIntervalMax).toBe(_constants.DEFAULT_REHOMING_INTERVAL_MAX);
411
- case 10:
796
+ case 11:
412
797
  case "end":
413
- return _context9.stop();
798
+ return _context15.stop();
414
799
  }
415
- }, _callee9);
800
+ }, _callee15);
416
801
  })));
417
- it('verify unsuccessful failback to primary after initial registration with backup: Restore failure with final error', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee10() {
802
+ it('verify unsuccessful failback to primary after initial registration with backup: Restore failure with final error', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee16() {
418
803
  var finalErrorPayload;
419
- return _regenerator.default.wrap(function _callee10$(_context10) {
420
- while (1) switch (_context10.prev = _context10.next) {
804
+ return _regenerator.default.wrap(function _callee16$(_context16) {
805
+ while (1) switch (_context16.prev = _context16.next) {
421
806
  case 0:
422
807
  finalErrorPayload = {
423
808
  statusCode: 401,
@@ -427,10 +812,10 @@ describe('Registration Tests', function () {
427
812
  postRegistrationSpy.mockRejectedValue(finalErrorPayload).mockRejectedValueOnce(failurePayload);
428
813
  /* Wait for failback to be triggered. */
429
814
  jest.advanceTimersByTime(reg.rehomingIntervalMax * _constants.MINUTES_TO_SEC_MFACTOR * _constants.SEC_TO_MSEC_MFACTOR);
430
- _context10.next = 6;
815
+ _context16.next = 6;
431
816
  return flushPromises();
432
817
  case 6:
433
- expect(logSpy).toBeCalledWith("Attempting failback to primary.", {
818
+ expect(infoSpy).toBeCalledWith("Attempting failback to primary.", {
434
819
  method: 'executeFailback',
435
820
  file: _constants.REGISTRATION_FILE
436
821
  });
@@ -442,22 +827,22 @@ describe('Registration Tests', function () {
442
827
  expect(reg.rehomingIntervalMax).toBe(_constants.DEFAULT_REHOMING_INTERVAL_MAX);
443
828
  case 13:
444
829
  case "end":
445
- return _context10.stop();
830
+ return _context16.stop();
446
831
  }
447
- }, _callee10);
832
+ }, _callee16);
448
833
  })));
449
- it('verify unsuccessful failback to primary after initial registration with backup: Restore success', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee11() {
450
- return _regenerator.default.wrap(function _callee11$(_context11) {
451
- while (1) switch (_context11.prev = _context11.next) {
834
+ it('verify unsuccessful failback to primary after initial registration with backup: Restore success', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee17() {
835
+ return _regenerator.default.wrap(function _callee17$(_context17) {
836
+ while (1) switch (_context17.prev = _context17.next) {
452
837
  case 0:
453
838
  postRegistrationSpy.mockRejectedValueOnce(failurePayload).mockResolvedValue(successPayload);
454
839
 
455
840
  /* Wait for failback to be triggered. */
456
841
  jest.advanceTimersByTime(reg.rehomingIntervalMax * _constants.MINUTES_TO_SEC_MFACTOR * _constants.SEC_TO_MSEC_MFACTOR);
457
- _context11.next = 4;
842
+ _context17.next = 4;
458
843
  return flushPromises();
459
844
  case 4:
460
- expect(logSpy).toBeCalledWith("Attempting failback to primary.", {
845
+ expect(infoSpy).toBeCalledWith("Attempting failback to primary.", {
461
846
  method: 'executeFailback',
462
847
  file: _constants.REGISTRATION_FILE
463
848
  });
@@ -470,22 +855,22 @@ describe('Registration Tests', function () {
470
855
  expect(reg.rehomingIntervalMax).toBe(_constants.DEFAULT_REHOMING_INTERVAL_MAX);
471
856
  case 11:
472
857
  case "end":
473
- return _context11.stop();
858
+ return _context17.stop();
474
859
  }
475
- }, _callee11);
860
+ }, _callee17);
476
861
  })));
477
- it('verify successful failback to primary after initial registration with backup', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee12() {
478
- return _regenerator.default.wrap(function _callee12$(_context12) {
479
- while (1) switch (_context12.prev = _context12.next) {
862
+ it('verify successful failback to primary after initial registration with backup', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee18() {
863
+ return _regenerator.default.wrap(function _callee18$(_context18) {
864
+ while (1) switch (_context18.prev = _context18.next) {
480
865
  case 0:
481
866
  postRegistrationSpy.mockResolvedValue(successPayload);
482
867
 
483
868
  /* Wait for failback to be triggered. */
484
869
  jest.advanceTimersByTime(reg.rehomingIntervalMax * _constants.MINUTES_TO_SEC_MFACTOR * _constants.SEC_TO_MSEC_MFACTOR);
485
- _context12.next = 4;
870
+ _context18.next = 4;
486
871
  return flushPromises();
487
872
  case 4:
488
- expect(logSpy).toBeCalledWith("Attempting failback to primary.", {
873
+ expect(infoSpy).toBeCalledWith("Attempting failback to primary.", {
489
874
  method: 'executeFailback',
490
875
  file: _constants.REGISTRATION_FILE
491
876
  });
@@ -499,13 +884,13 @@ describe('Registration Tests', function () {
499
884
  expect(reg.rehomingIntervalMax).toBe(_registerFixtures.mockPostResponse.rehomingIntervalMax);
500
885
  case 11:
501
886
  case "end":
502
- return _context12.stop();
887
+ return _context18.stop();
503
888
  }
504
- }, _callee12);
889
+ }, _callee18);
505
890
  })));
506
- it('verify unsuccessful failback attempt due to active call', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee13() {
507
- return _regenerator.default.wrap(function _callee13$(_context13) {
508
- while (1) switch (_context13.prev = _context13.next) {
891
+ it('verify unsuccessful failback attempt due to active call', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee19() {
892
+ return _regenerator.default.wrap(function _callee19$(_context19) {
893
+ while (1) switch (_context19.prev = _context19.next) {
509
894
  case 0:
510
895
  /** create a new call */
511
896
  reg.callManager.createCall();
@@ -514,10 +899,10 @@ describe('Registration Tests', function () {
514
899
 
515
900
  /* Wait for failback to be triggered. */
516
901
  jest.advanceTimersByTime(reg.rehomingIntervalMax * _constants.MINUTES_TO_SEC_MFACTOR * _constants.SEC_TO_MSEC_MFACTOR);
517
- _context13.next = 6;
902
+ _context19.next = 6;
518
903
  return flushPromises();
519
904
  case 6:
520
- expect(logSpy).toBeCalledWith("Active calls present, deferring failback to next cycle.", {
905
+ expect(infoSpy).toBeCalledWith("Active calls present, deferring failback to next cycle.", {
521
906
  method: 'executeFailback',
522
907
  file: _constants.REGISTRATION_FILE
523
908
  });
@@ -527,7 +912,7 @@ describe('Registration Tests', function () {
527
912
  expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
528
913
  expect(restoreSpy).not.toBeCalled();
529
914
  expect(restartSpy).not.toBeCalled();
530
- expect(logSpy).toBeCalledWith('Active calls present, deferring failback to next cycle.', {
915
+ expect(infoSpy).toBeCalledWith('Active calls present, deferring failback to next cycle.', {
531
916
  file: _constants.REGISTRATION_FILE,
532
917
  method: _constants.FAILBACK_UTIL
533
918
  });
@@ -535,470 +920,434 @@ describe('Registration Tests', function () {
535
920
  expect(reg.rehomingIntervalMax).toBe(_constants.DEFAULT_REHOMING_INTERVAL_MAX);
536
921
  case 14:
537
922
  case "end":
538
- return _context13.stop();
923
+ return _context19.stop();
539
924
  }
540
- }, _callee13);
925
+ }, _callee19);
541
926
  })));
542
927
  });
543
928
 
544
929
  // Keep-alive related test cases
545
930
  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
+ };
546
938
  var beforeEachSetupForKeepalive = /*#__PURE__*/function () {
547
- var _ref14 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee14() {
548
- return _regenerator.default.wrap(function _callee14$(_context14) {
549
- while (1) switch (_context14.prev = _context14.next) {
939
+ var _ref20 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee20() {
940
+ return _regenerator.default.wrap(function _callee20$(_context20) {
941
+ while (1) switch (_context20.prev = _context20.next) {
550
942
  case 0:
551
943
  postRegistrationSpy.mockResolvedValueOnce(successPayload);
552
944
  jest.useFakeTimers();
553
- _context14.next = 4;
945
+ _context20.next = 4;
554
946
  return reg.triggerRegistration();
555
947
  case 4:
556
948
  expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
557
- expect(reg.webWorker).toBeDefined();
558
- case 6:
949
+ case 5:
559
950
  case "end":
560
- return _context14.stop();
951
+ return _context20.stop();
561
952
  }
562
- }, _callee14);
953
+ }, _callee20);
563
954
  }));
564
955
  return function beforeEachSetupForKeepalive() {
565
- return _ref14.apply(this, arguments);
956
+ return _ref20.apply(this, arguments);
566
957
  };
567
958
  }();
568
959
  afterEach(function () {
569
960
  jest.clearAllTimers();
570
961
  jest.clearAllMocks();
571
- reg.clearKeepaliveTimer();
962
+ if (reg.keepaliveTimer) {
963
+ clearInterval(reg.keepaliveTimer);
964
+ reg.keepaliveTimer = undefined;
965
+ }
572
966
  reg.reconnectPending = false;
573
967
  var calls = (0, _values.default)(reg.callManager.getActiveCalls());
574
968
  calls.forEach(function (call) {
575
969
  call.end();
576
970
  });
577
971
  });
578
- it('verify successful keep-alive cases', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee15() {
579
- var postMessageSpy;
580
- return _regenerator.default.wrap(function _callee15$(_context15) {
581
- while (1) switch (_context15.prev = _context15.next) {
972
+ it('verify successful keep-alive cases', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee21() {
973
+ var keepAlivePayload, funcSpy;
974
+ return _regenerator.default.wrap(function _callee21$(_context21) {
975
+ while (1) switch (_context21.prev = _context21.next) {
582
976
  case 0:
583
- postMessageSpy = jest.spyOn(Worker.prototype, 'postMessage');
584
- _context15.next = 3;
977
+ _context21.next = 2;
585
978
  return beforeEachSetupForKeepalive();
586
- case 3:
587
- expect(reg.webWorker).toBeDefined();
588
- expect(postMessageSpy).toHaveBeenCalledWith(expect.objectContaining({
589
- type: 'START_KEEPALIVE',
590
- accessToken: expect.any(String),
591
- deviceUrl: expect.any(String),
592
- interval: expect.any(Number),
593
- retryCountThreshold: expect.any(Number),
594
- url: expect.any(String)
595
- }));
596
- reg.webWorker.onmessage({
597
- data: {
598
- type: 'KEEPALIVE_SUCCESS',
599
- statusCode: 200
600
- }
601
- });
602
- expect(lineEmitter).toBeCalledWith(_types4.LINE_EVENTS.RECONNECTED);
603
- case 7:
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:
604
995
  case "end":
605
- return _context15.stop();
996
+ return _context21.stop();
606
997
  }
607
- }, _callee15);
998
+ }, _callee21);
608
999
  })));
609
- it('verify failure keep-alive cases: Retry Success', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee16() {
610
- var worker;
611
- return _regenerator.default.wrap(function _callee16$(_context16) {
612
- while (1) switch (_context16.prev = _context16.next) {
1000
+ it('verify failure keep-alive cases: Retry Success', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee22() {
1001
+ var failurePayload, successPayload, timer;
1002
+ return _regenerator.default.wrap(function _callee22$(_context22) {
1003
+ while (1) switch (_context22.prev = _context22.next) {
613
1004
  case 0:
614
- _context16.next = 2;
1005
+ _context22.next = 2;
615
1006
  return beforeEachSetupForKeepalive();
616
1007
  case 2:
617
- worker = reg.webWorker;
1008
+ failurePayload = {
1009
+ statusCode: 503,
1010
+ body: mockKeepAliveBody
1011
+ };
1012
+ successPayload = {
1013
+ statusCode: 200,
1014
+ body: mockKeepAliveBody
1015
+ };
1016
+ timer = reg.keepaliveTimer;
618
1017
  lineEmitter.mockClear();
619
- worker.onmessage({
620
- data: {
621
- type: 'KEEPALIVE_FAILURE',
622
- err: {
623
- statusCode: 503
624
- },
625
- keepAliveRetryCount: 1
626
- }
627
- });
628
- worker.onmessage({
629
- data: {
630
- type: 'KEEPALIVE_SUCCESS',
631
- statusCode: 200
632
- }
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
633
1026
  });
634
- expect(lineEmitter).toHaveBeenCalledWith(_types4.LINE_EVENTS.RECONNECTED);
635
- case 7:
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:
636
1033
  case "end":
637
- return _context16.stop();
1034
+ return _context22.stop();
638
1035
  }
639
- }, _callee16);
1036
+ }, _callee22);
640
1037
  })));
641
- it('verify failure keep-alive cases: Restore failure', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee17() {
642
- var reconnectSpy, RETRY_COUNT_THRESHOLD, failureEvent;
643
- return _regenerator.default.wrap(function _callee17$(_context17) {
644
- while (1) switch (_context17.prev = _context17.next) {
1038
+ 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;
1040
+ return _regenerator.default.wrap(function _callee23$(_context23) {
1041
+ while (1) switch (_context23.prev = _context23.next) {
645
1042
  case 0:
646
- _context17.next = 2;
1043
+ _context23.next = 2;
647
1044
  return beforeEachSetupForKeepalive();
648
1045
  case 2:
649
- reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure'); // Clear previous event emissions
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');
650
1054
  lineEmitter.mockClear();
651
-
652
- // Assume registration is active
1055
+ webex.request.mockRejectedValue(failurePayload);
653
1056
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
654
-
655
- // Use fake timers to trigger keepalive initialization
656
- jest.useFakeTimers();
657
- jest.advanceTimersByTime(_registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
658
-
659
- // Simulate the worker sending a KEEPALIVE_FAILURE message with retry count at threshold.
660
- RETRY_COUNT_THRESHOLD = reg.isCCFlow ? 4 : 5;
661
- failureEvent = {
662
- data: {
663
- type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
664
- err: {
665
- statusCode: 503
666
- },
667
- keepAliveRetryCount: RETRY_COUNT_THRESHOLD
668
- }
669
- };
670
- reg.webWorker.onmessage(failureEvent);
671
- _context17.next = 12;
1057
+ timer = reg.keepaliveTimer;
1058
+ jest.advanceTimersByTime(5 * _registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
1059
+ _context23.next = 14;
672
1060
  return flushPromises();
673
- case 12:
1061
+ 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);
674
1067
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
675
- expect(lineEmitter).toHaveBeenCalledWith(_types4.LINE_EVENTS.UNREGISTERED);
676
- expect(reconnectSpy).toBeCalledOnceWith('startKeepaliveTimer');
677
- jest.useRealTimers();
678
- case 16:
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);
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:
679
1093
  case "end":
680
- return _context17.stop();
1094
+ return _context23.stop();
681
1095
  }
682
- }, _callee17);
1096
+ }, _callee23);
683
1097
  })));
684
- it('verify failure keep-alive cases: Restore Success', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee18() {
685
- var reconnectSpy, url;
686
- return _regenerator.default.wrap(function _callee18$(_context18) {
687
- while (1) switch (_context18.prev = _context18.next) {
1098
+ 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;
1100
+ return _regenerator.default.wrap(function _callee24$(_context24) {
1101
+ while (1) switch (_context24.prev = _context24.next) {
688
1102
  case 0:
689
- _context18.next = 2;
1103
+ _context24.next = 2;
690
1104
  return beforeEachSetupForKeepalive();
691
1105
  case 2:
692
- expect(reg.webWorker).toBeDefined();
1106
+ restoreSpy = jest.spyOn(reg, 'restorePreviousRegistration');
1107
+ restartRegSpy = jest.spyOn(reg, 'restartRegistration');
693
1108
  reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure');
694
- url = 'https://mobius-dfw.webex.com/api/v1/calling/web/';
695
- reg.webWorker.onmessage({
696
- data: {
697
- type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
698
- err: {
699
- statusCode: 503
700
- },
701
- keepAliveRetryCount: 5
702
- }
703
- });
704
- jest.advanceTimersByTime(1000);
705
- _context18.next = 9;
706
- return flushPromises();
707
- case 9:
708
- expect(reg.webWorker).toBeUndefined();
709
- expect(reconnectSpy).toBeCalledOnceWith(reg.startKeepaliveTimer.name);
710
- webex.request.mockResolvedValueOnce(successPayload);
711
- _context18.next = 14;
712
- return reg.triggerRegistration();
713
- case 14:
714
- _context18.next = 16;
715
- return flushPromises();
716
- case 16:
717
- expect(reg.webWorker).toBeDefined();
718
- reg.webWorker.onmessage({
719
- data: {
720
- type: _types.WorkerMessageType.KEEPALIVE_SUCCESS,
721
- statusCode: 200
722
- }
723
- });
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);
724
1122
 
725
- // Advance timers and flush any remaining promises.
726
- jest.advanceTimersByTime(1000);
727
- _context18.next = 21;
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);
1129
+ _context24.next = 16;
728
1130
  return flushPromises();
729
- case 21:
1131
+ case 16:
1132
+ expect(clearIntervalSpy).toBeCalledOnceWith(timer);
1133
+ expect(handleErrorSpy).toBeCalledTimes(5);
730
1134
  expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
731
- // reconnectSpy should have been called only once.
732
- expect(reconnectSpy).toBeCalledTimes(1);
733
- expect(restoreSpy).toBeCalledOnceWith(reg.startKeepaliveTimer.name);
734
- expect(restartSpy).toBeCalledOnceWith(reg.startKeepaliveTimer.name);
735
- // Active Mobius URL should remain unchanged.
1135
+ expect(reconnectSpy).toBeCalledOnceWith(_constants.KEEPALIVE_UTIL);
1136
+ expect(restoreSpy).toBeCalledOnceWith(_constants.KEEPALIVE_UTIL);
1137
+ expect(restartRegSpy).not.toBeCalled();
736
1138
  expect(reg.getActiveMobiusUrl()).toStrictEqual(url);
1139
+ expect(reg.reconnectPending).toStrictEqual(false);
1140
+ expect(reg.keepaliveTimer).toBeTruthy();
1141
+ expect(reg.keepaliveTimer).not.toBe(timer);
737
1142
  case 26:
738
1143
  case "end":
739
- return _context18.stop();
1144
+ return _context24.stop();
740
1145
  }
741
- }, _callee18);
1146
+ }, _callee24);
742
1147
  })));
743
- it('verify failure followed by recovery of keepalive', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee19() {
744
- return _regenerator.default.wrap(function _callee19$(_context19) {
745
- while (1) switch (_context19.prev = _context19.next) {
1148
+ 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
+ return _regenerator.default.wrap(function _callee25$(_context25) {
1151
+ while (1) switch (_context25.prev = _context25.next) {
746
1152
  case 0:
747
- _context19.next = 2;
1153
+ _context25.next = 2;
748
1154
  return beforeEachSetupForKeepalive();
749
1155
  case 2:
750
- expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
751
- expect(reg.webWorker).toBeDefined();
1156
+ failurePayload = {
1157
+ statusCode: 503,
1158
+ body: mockKeepAliveBody
1159
+ };
1160
+ successPayload = {
1161
+ statusCode: 200,
1162
+ body: mockKeepAliveBody
1163
+ };
1164
+ clearIntervalSpy = jest.spyOn(global, 'clearInterval');
752
1165
  webex.request.mockRejectedValueOnce(failurePayload).mockRejectedValueOnce(failurePayload).mockResolvedValue(successPayload);
753
- reg.webWorker.onmessage({
754
- data: {
755
- type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
756
- err: failurePayload,
757
- keepAliveRetryCount: reg.isCCFlow ? 4 : 5
758
- }
759
- });
760
- _context19.next = 8;
761
- return flushPromises();
762
- case 8:
763
- expect(reg.webWorker).toBeUndefined();
764
- expect(handleErrorSpy).toBeCalledTimes(3);
765
- _context19.next = 12;
766
- return reg.triggerRegistration();
767
- case 12:
768
- _context19.next = 14;
769
- return flushPromises();
770
- case 14:
771
- expect(reg.webWorker).toBeDefined();
772
- reg.webWorker.onmessage({
773
- data: {
774
- type: _types.WorkerMessageType.KEEPALIVE_SUCCESS,
775
- statusCode: 200
776
- }
777
- });
778
- _context19.next = 18;
779
- return flushPromises();
780
- case 18:
781
- // In a complete failure‐then-recovery scenario, we expect another failure event to have been handled.
782
- // For that, simulate a second failure event on the new worker.
783
- reg.webWorker.onmessage({
784
- data: {
785
- type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
786
- err: failurePayload,
787
- keepAliveRetryCount: reg.isCCFlow ? 4 : 5
788
- }
789
- });
790
- _context19.next = 21;
791
- return flushPromises();
792
- case 21:
793
- expect(handleErrorSpy).toBeCalledTimes(4);
794
-
795
- // And then re-register successfully:
796
- _context19.next = 24;
797
- return reg.triggerRegistration();
798
- case 24:
799
- _context19.next = 26;
800
- return flushPromises();
801
- case 26:
802
- expect(reg.webWorker).toBeDefined();
803
- reg.webWorker.onmessage({
804
- data: {
805
- type: _types.WorkerMessageType.KEEPALIVE_SUCCESS,
806
- statusCode: 200
807
- }
808
- });
809
- _context19.next = 30;
1166
+ 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;
810
1170
  return flushPromises();
811
- case 30:
812
- expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
813
- expect(reg.webWorker).toBeDefined();
814
- case 32:
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:
815
1178
  case "end":
816
- return _context19.stop();
1179
+ return _context25.stop();
817
1180
  }
818
- }, _callee19);
1181
+ }, _callee25);
819
1182
  })));
820
- it('cc: verify failover to backup server after 4 keep alive failure with primary server', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee20() {
821
- var clearKeepaliveSpy, reconnectSpy;
822
- return _regenerator.default.wrap(function _callee20$(_context20) {
823
- while (1) switch (_context20.prev = _context20.next) {
1183
+ 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;
1185
+ return _regenerator.default.wrap(function _callee26$(_context26) {
1186
+ while (1) switch (_context26.prev = _context26.next) {
824
1187
  case 0:
825
1188
  // Register with contact center service
826
1189
  setupRegistration(_objectSpread(_objectSpread({}, MockServiceData), {}, {
827
1190
  indicator: _types.ServiceIndicator.CONTACT_CENTER
828
1191
  }));
829
- _context20.next = 3;
1192
+ _context26.next = 3;
830
1193
  return beforeEachSetupForKeepalive();
831
1194
  case 3:
832
- webex.request.mockResolvedValueOnce(successPayload);
833
- _context20.next = 6;
834
- return reg.triggerRegistration();
835
- case 6:
836
- expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
837
- expect(reg.webWorker).toBeDefined();
838
-
839
- // Spy on clearKeepaliveTimer and simulate reconnectOnFailure behavior
840
- clearKeepaliveSpy = jest.spyOn(reg, 'clearKeepaliveTimer');
841
- reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure'); // Simulate a KEEPALIVE_FAILURE message from the worker with a retry count equal to threshold (4 for CC)
842
- reg.webWorker.onmessage({
843
- data: {
844
- type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
845
- err: {
846
- statusCode: 503
847
- },
848
- keepAliveRetryCount: 4
849
- }
850
- });
851
-
852
- // Wait for any asynchronous actions to complete
853
- _context20.next = 13;
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;
854
1209
  return flushPromises();
855
- case 13:
856
- // Verify that the keepalive timer was cleared and reconnectOnFailure was triggered
857
- expect(clearKeepaliveSpy).toHaveBeenCalled();
858
- expect(reconnectSpy).toHaveBeenCalledWith(reg.startKeepaliveTimer.name);
859
-
860
- // Verify that the active Mobius URL has been updated to the backup server and registration is active
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;
1217
+ return flushPromises();
1218
+ case 19:
1219
+ /* Active Url must match with the backup url as per the test */
861
1220
  expect(reg.getActiveMobiusUrl()).toEqual(mobiusUris.backup[0]);
862
- expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
863
- case 17:
1221
+ expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
1222
+ case 21:
864
1223
  case "end":
865
- return _context20.stop();
1224
+ return _context26.stop();
866
1225
  }
867
- }, _callee20);
1226
+ }, _callee26);
868
1227
  })));
869
- it('verify final error for keep-alive', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee21() {
870
- var threshold, reconnectSpy;
871
- return _regenerator.default.wrap(function _callee21$(_context21) {
872
- while (1) switch (_context21.prev = _context21.next) {
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;
1230
+ return _regenerator.default.wrap(function _callee27$(_context27) {
1231
+ while (1) switch (_context27.prev = _context27.next) {
873
1232
  case 0:
874
- _context21.next = 2;
1233
+ _context27.next = 2;
875
1234
  return beforeEachSetupForKeepalive();
876
1235
  case 2:
877
- threshold = reg.isCCFlow ? 4 : 5;
1236
+ restoreSpy = jest.spyOn(reg, 'restorePreviousRegistration');
1237
+ restartRegSpy = jest.spyOn(reg, 'restartRegistration');
878
1238
  reconnectSpy = jest.spyOn(reg, 'reconnectOnFailure');
879
- jest.spyOn(utils, 'handleRegistrationErrors').mockResolvedValue(true);
880
- reg.webWorker.onmessage({
881
- data: {
882
- type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
883
- err: {
884
- statusCode: 404
885
- },
886
- keepAliveRetryCount: threshold
887
- }
888
- });
889
- _context21.next = 8;
890
- return flushPromises();
891
- case 8:
892
- expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
893
- expect(lineEmitter).toHaveBeenCalledWith(_types4.LINE_EVENTS.UNREGISTERED);
894
- expect(reconnectSpy).not.toHaveBeenCalled();
895
- case 11:
896
- case "end":
897
- return _context21.stop();
898
- }
899
- }, _callee21);
900
- })));
901
- it('verify failure keep-alive case with active call present: Restore Success after call ends', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee22() {
902
- var clearTimerSpy, threshold, failureEvent;
903
- return _regenerator.default.wrap(function _callee22$(_context22) {
904
- while (1) switch (_context22.prev = _context22.next) {
905
- case 0:
906
- _context22.next = 2;
907
- return beforeEachSetupForKeepalive();
908
- case 2:
909
- // Simulate an active call.
910
- reg.callManager.createCall();
911
- expect((0, _keys.default)(reg.callManager.getActiveCalls()).length).toBeGreaterThan(0);
912
- clearTimerSpy = jest.spyOn(reg, 'clearKeepaliveTimer');
913
- threshold = reg.isCCFlow ? 4 : 5; // Simulate a KEEPALIVE_FAILURE event with a 503 error at threshold.
914
- failureEvent = {
915
- data: {
916
- type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
917
- err: {
918
- statusCode: 503
919
- },
920
- keepAliveRetryCount: threshold
921
- }
1239
+ failurePayload = {
1240
+ statusCode: 404,
1241
+ body: mockKeepAliveBody
922
1242
  };
923
- reg.webWorker.onmessage(failureEvent);
924
- _context22.next = 10;
925
- return flushPromises();
926
- case 10:
927
- // At this point, clearKeepaliveTimer was called so the worker is terminated.
928
- expect(clearTimerSpy).toHaveBeenCalled();
929
- expect(reg.getStatus()).toEqual(_types.RegistrationStatus.INACTIVE);
930
- expect(reg.webWorker).toBeUndefined();
931
-
932
- // Now simulate call cleanup.
933
- reg.callManager.callCollection = {};
934
- webex.request.mockResolvedValueOnce(successPayload);
1243
+ clearIntervalSpy = jest.spyOn(global, 'clearInterval');
1244
+ webex.request.mockRejectedValue(failurePayload);
1245
+ expect(reg.getStatus()).toBe(_types.RegistrationStatus.ACTIVE);
935
1246
 
936
- // Call reconnectOnFailure manually. With no active calls, this should trigger re-registration.
937
- _context22.next = 17;
938
- return reg.reconnectOnFailure('activeCallEnded');
939
- case 17:
940
- _context22.next = 19;
1247
+ /* send one keepalive */
1248
+ jest.advanceTimersByTime(_registerFixtures.mockPostResponse.keepaliveInterval * _constants.SEC_TO_MSEC_MFACTOR);
1249
+ _context27.next = 12;
941
1250
  return flushPromises();
942
- case 19:
943
- // After re-registration, registration status becomes ACTIVE and a new worker is created.
944
- expect(reg.getStatus()).toEqual(_types.RegistrationStatus.ACTIVE);
945
- expect(reg.isReconnectPending()).toBe(false);
946
- expect(reg.webWorker).toBeDefined();
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
1268
+ });
1269
+ expect(warnSpy).toBeCalledWith('Keep-alive missed 1 times. Status -> 404 ', expect.objectContaining({
1270
+ file: _constants.REGISTRATION_FILE,
1271
+ method: 'startKeepaliveTimer'
1272
+ }));
947
1273
  case 22:
948
1274
  case "end":
949
- return _context22.stop();
1275
+ return _context27.stop();
950
1276
  }
951
- }, _callee22);
1277
+ }, _callee27);
952
1278
  })));
953
- it('should emit LINE_EVENTS.ERROR when keepalive fails with a final error', /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee24() {
954
- return _regenerator.default.wrap(function _callee24$(_context24) {
955
- while (1) switch (_context24.prev = _context24.next) {
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;
1281
+ return _regenerator.default.wrap(function _callee28$(_context28) {
1282
+ while (1) switch (_context28.prev = _context28.next) {
956
1283
  case 0:
957
- _context24.next = 2;
1284
+ _context28.next = 2;
958
1285
  return beforeEachSetupForKeepalive();
959
1286
  case 2:
960
- expect(reg.webWorker).toBeDefined();
961
- lineEmitter.mockClear();
962
- jest.spyOn(utils, 'handleRegistrationErrors').mockImplementationOnce( /*#__PURE__*/function () {
963
- var _ref24 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee23(error, callback) {
964
- var clientError;
965
- return _regenerator.default.wrap(function _callee23$(_context23) {
966
- while (1) switch (_context23.prev = _context23.next) {
967
- case 0:
968
- 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);
969
- callback(clientError, true);
970
- return _context23.abrupt("return", true);
971
- case 3:
972
- case "end":
973
- return _context23.stop();
974
- }
975
- }, _callee23);
976
- }));
977
- return function (_x, _x2) {
978
- return _ref24.apply(this, arguments);
979
- };
980
- }());
981
- reg.webWorker.onmessage({
982
- data: {
983
- type: _types.WorkerMessageType.KEEPALIVE_FAILURE,
984
- err: {
985
- statusCode: 401,
986
- message: 'Unauthorized'
987
- },
988
- keepAliveRetryCount: 1
989
- }
990
- });
991
- _context24.next = 8;
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
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;
992
1314
  return flushPromises();
993
- case 8:
994
- 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.'));
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);
995
1320
  expect(reg.getStatus()).toBe(_types.RegistrationStatus.INACTIVE);
996
- expect(reg.webWorker).toBeUndefined();
997
- case 11:
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();
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();
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:
998
1347
  case "end":
999
- return _context24.stop();
1348
+ return _context28.stop();
1000
1349
  }
1001
- }, _callee24);
1350
+ }, _callee28);
1002
1351
  })));
1003
1352
  });
1004
1353
  });