@webex/plugin-meetings 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/common/errors/reconnection-not-started.js +46 -0
  4. package/dist/common/errors/reconnection-not-started.js.map +1 -0
  5. package/dist/constants.js +16 -5
  6. package/dist/constants.js.map +1 -1
  7. package/dist/index.js +80 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/interpretation/index.js +1 -1
  10. package/dist/interpretation/siLanguage.js +1 -1
  11. package/dist/locus-info/controlsUtils.js +7 -1
  12. package/dist/locus-info/controlsUtils.js.map +1 -1
  13. package/dist/locus-info/index.js +10 -0
  14. package/dist/locus-info/index.js.map +1 -1
  15. package/dist/media/properties.js +102 -57
  16. package/dist/media/properties.js.map +1 -1
  17. package/dist/mediaQualityMetrics/config.js +10 -10
  18. package/dist/mediaQualityMetrics/config.js.map +1 -1
  19. package/dist/meeting/in-meeting-actions.js +6 -0
  20. package/dist/meeting/in-meeting-actions.js.map +1 -1
  21. package/dist/meeting/index.js +564 -475
  22. package/dist/meeting/index.js.map +1 -1
  23. package/dist/meeting/locusMediaRequest.js +27 -0
  24. package/dist/meeting/locusMediaRequest.js.map +1 -1
  25. package/dist/meeting/util.js +9 -16
  26. package/dist/meeting/util.js.map +1 -1
  27. package/dist/meeting/voicea-meeting.js +37 -49
  28. package/dist/meeting/voicea-meeting.js.map +1 -1
  29. package/dist/meeting-info/util.js +304 -267
  30. package/dist/meeting-info/util.js.map +1 -1
  31. package/dist/meeting-info/utilv2.js +334 -298
  32. package/dist/meeting-info/utilv2.js.map +1 -1
  33. package/dist/meetings/index.js +12 -28
  34. package/dist/meetings/index.js.map +1 -1
  35. package/dist/reachability/index.js +88 -9
  36. package/dist/reachability/index.js.map +1 -1
  37. package/dist/reconnection-manager/index.js +138 -109
  38. package/dist/reconnection-manager/index.js.map +1 -1
  39. package/dist/roap/request.js +3 -27
  40. package/dist/roap/request.js.map +1 -1
  41. package/dist/statsAnalyzer/index.js +8 -2
  42. package/dist/statsAnalyzer/index.js.map +1 -1
  43. package/dist/statsAnalyzer/mqaUtil.js +17 -0
  44. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  45. package/dist/types/annotation/annotation.types.d.ts +42 -0
  46. package/dist/types/annotation/constants.d.ts +31 -0
  47. package/dist/types/annotation/index.d.ts +117 -0
  48. package/dist/types/breakouts/breakout.d.ts +8 -0
  49. package/dist/types/breakouts/collection.d.ts +5 -0
  50. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  51. package/dist/types/breakouts/events.d.ts +8 -0
  52. package/dist/types/breakouts/index.d.ts +5 -0
  53. package/dist/types/breakouts/request.d.ts +22 -0
  54. package/dist/types/breakouts/utils.d.ts +15 -0
  55. package/dist/types/common/browser-detection.d.ts +9 -0
  56. package/dist/types/common/collection.d.ts +48 -0
  57. package/dist/types/common/config.d.ts +2 -0
  58. package/dist/types/common/errors/captcha-error.d.ts +15 -0
  59. package/dist/types/common/errors/intent-to-join.d.ts +16 -0
  60. package/dist/types/common/errors/join-meeting.d.ts +17 -0
  61. package/dist/types/common/errors/media.d.ts +15 -0
  62. package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
  63. package/dist/types/common/errors/parameter.d.ts +15 -0
  64. package/dist/types/common/errors/password-error.d.ts +15 -0
  65. package/dist/types/common/errors/permission.d.ts +14 -0
  66. package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
  67. package/dist/types/common/errors/reconnection-not-started.d.ts +13 -0
  68. package/dist/types/common/errors/reconnection.d.ts +15 -0
  69. package/dist/types/common/errors/stats.d.ts +15 -0
  70. package/dist/types/common/errors/webex-errors.d.ts +93 -0
  71. package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
  72. package/dist/types/common/events/events-scope.d.ts +17 -0
  73. package/dist/types/common/events/events.d.ts +12 -0
  74. package/dist/types/common/events/trigger-proxy.d.ts +2 -0
  75. package/dist/types/common/events/util.d.ts +2 -0
  76. package/dist/types/common/logs/logger-config.d.ts +2 -0
  77. package/dist/types/common/logs/logger-proxy.d.ts +2 -0
  78. package/dist/types/common/logs/request.d.ts +36 -0
  79. package/dist/types/common/queue.d.ts +34 -0
  80. package/dist/types/config.d.ts +73 -0
  81. package/dist/types/constants.d.ts +1098 -0
  82. package/dist/types/controls-options-manager/constants.d.ts +4 -0
  83. package/dist/types/controls-options-manager/enums.d.ts +15 -0
  84. package/dist/types/controls-options-manager/index.d.ts +136 -0
  85. package/dist/types/controls-options-manager/types.d.ts +43 -0
  86. package/dist/types/controls-options-manager/util.d.ts +1 -0
  87. package/dist/types/index.d.ts +19 -0
  88. package/dist/types/interceptors/index.d.ts +2 -0
  89. package/dist/types/interceptors/locusRetry.d.ts +27 -0
  90. package/dist/types/interpretation/collection.d.ts +5 -0
  91. package/dist/types/interpretation/index.d.ts +5 -0
  92. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  93. package/dist/types/locus-info/controlsUtils.d.ts +2 -0
  94. package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
  95. package/dist/types/locus-info/fullState.d.ts +2 -0
  96. package/dist/types/locus-info/hostUtils.d.ts +2 -0
  97. package/dist/types/locus-info/index.d.ts +322 -0
  98. package/dist/types/locus-info/infoUtils.d.ts +2 -0
  99. package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
  100. package/dist/types/locus-info/parser.d.ts +272 -0
  101. package/dist/types/locus-info/selfUtils.d.ts +2 -0
  102. package/dist/types/media/MediaConnectionAwaiter.d.ts +61 -0
  103. package/dist/types/media/index.d.ts +34 -0
  104. package/dist/types/media/properties.d.ts +117 -0
  105. package/dist/types/media/util.d.ts +2 -0
  106. package/dist/types/mediaQualityMetrics/config.d.ts +247 -0
  107. package/dist/types/meeting/in-meeting-actions.d.ts +173 -0
  108. package/dist/types/meeting/index.d.ts +1832 -0
  109. package/dist/types/meeting/locusMediaRequest.d.ts +75 -0
  110. package/dist/types/meeting/muteState.d.ts +178 -0
  111. package/dist/types/meeting/request.d.ts +295 -0
  112. package/dist/types/meeting/request.type.d.ts +11 -0
  113. package/dist/types/meeting/state.d.ts +9 -0
  114. package/dist/types/meeting/util.d.ts +122 -0
  115. package/dist/types/meeting/voicea-meeting.d.ts +17 -0
  116. package/dist/types/meeting-info/collection.d.ts +20 -0
  117. package/dist/types/meeting-info/index.d.ts +69 -0
  118. package/dist/types/meeting-info/meeting-info-v2.d.ts +123 -0
  119. package/dist/types/meeting-info/request.d.ts +22 -0
  120. package/dist/types/meeting-info/util.d.ts +49 -0
  121. package/dist/types/meeting-info/utilv2.d.ts +65 -0
  122. package/dist/types/meetings/collection.d.ts +40 -0
  123. package/dist/types/meetings/index.d.ts +383 -0
  124. package/dist/types/meetings/meetings.types.d.ts +4 -0
  125. package/dist/types/meetings/request.d.ts +27 -0
  126. package/dist/types/meetings/util.d.ts +18 -0
  127. package/dist/types/member/index.d.ts +160 -0
  128. package/dist/types/member/types.d.ts +32 -0
  129. package/dist/types/member/util.d.ts +2 -0
  130. package/dist/types/members/collection.d.ts +29 -0
  131. package/dist/types/members/index.d.ts +353 -0
  132. package/dist/types/members/request.d.ts +114 -0
  133. package/dist/types/members/types.d.ts +25 -0
  134. package/dist/types/members/util.d.ts +215 -0
  135. package/dist/types/metrics/constants.d.ts +70 -0
  136. package/dist/types/metrics/index.d.ts +45 -0
  137. package/dist/types/multistream/mediaRequestManager.d.ts +119 -0
  138. package/dist/types/multistream/receiveSlot.d.ts +68 -0
  139. package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
  140. package/dist/types/multistream/remoteMedia.d.ts +72 -0
  141. package/dist/types/multistream/remoteMediaGroup.d.ts +49 -0
  142. package/dist/types/multistream/remoteMediaManager.d.ts +300 -0
  143. package/dist/types/multistream/sendSlotManager.d.ts +69 -0
  144. package/dist/types/networkQualityMonitor/index.d.ts +70 -0
  145. package/dist/types/personal-meeting-room/index.d.ts +47 -0
  146. package/dist/types/personal-meeting-room/request.d.ts +14 -0
  147. package/dist/types/personal-meeting-room/util.d.ts +2 -0
  148. package/dist/types/reachability/clusterReachability.d.ts +110 -0
  149. package/dist/types/reachability/index.d.ts +120 -0
  150. package/dist/types/reachability/request.d.ts +39 -0
  151. package/dist/types/reachability/util.d.ts +15 -0
  152. package/dist/types/reactions/constants.d.ts +3 -0
  153. package/dist/types/reactions/reactions.d.ts +4 -0
  154. package/dist/types/reactions/reactions.type.d.ts +52 -0
  155. package/dist/types/reconnection-manager/index.d.ts +126 -0
  156. package/dist/types/recording-controller/enums.d.ts +7 -0
  157. package/dist/types/recording-controller/index.d.ts +207 -0
  158. package/dist/types/recording-controller/util.d.ts +14 -0
  159. package/dist/types/roap/index.d.ts +86 -0
  160. package/dist/types/roap/request.d.ts +39 -0
  161. package/dist/types/roap/turnDiscovery.d.ts +155 -0
  162. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  163. package/dist/types/rtcMetrics/index.d.ts +61 -0
  164. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  165. package/dist/types/statsAnalyzer/index.d.ts +217 -0
  166. package/dist/types/statsAnalyzer/mqaUtil.d.ts +48 -0
  167. package/dist/types/transcription/index.d.ts +64 -0
  168. package/dist/types/webinar/collection.d.ts +16 -0
  169. package/dist/types/webinar/index.d.ts +5 -0
  170. package/dist/webinar/index.js +1 -1
  171. package/package.json +22 -22
  172. package/src/common/errors/reconnection-not-started.ts +25 -0
  173. package/src/constants.ts +14 -5
  174. package/src/index.ts +30 -0
  175. package/src/locus-info/controlsUtils.ts +11 -0
  176. package/src/locus-info/index.ts +16 -0
  177. package/src/media/properties.ts +67 -15
  178. package/src/mediaQualityMetrics/config.ts +13 -7
  179. package/src/meeting/in-meeting-actions.ts +12 -0
  180. package/src/meeting/index.ts +144 -107
  181. package/src/meeting/locusMediaRequest.ts +31 -0
  182. package/src/meeting/util.ts +9 -16
  183. package/src/meeting/voicea-meeting.ts +44 -46
  184. package/src/meeting-info/util.ts +241 -233
  185. package/src/meeting-info/utilv2.ts +250 -244
  186. package/src/meetings/index.ts +15 -27
  187. package/src/reachability/index.ts +60 -0
  188. package/src/reconnection-manager/index.ts +128 -105
  189. package/src/roap/request.ts +1 -24
  190. package/src/statsAnalyzer/index.ts +10 -3
  191. package/src/statsAnalyzer/mqaUtil.ts +23 -0
  192. package/test/unit/spec/locus-info/controlsUtils.js +20 -0
  193. package/test/unit/spec/locus-info/index.js +21 -0
  194. package/test/unit/spec/media/properties.ts +145 -140
  195. package/test/unit/spec/meeting/in-meeting-actions.ts +6 -0
  196. package/test/unit/spec/meeting/index.js +271 -105
  197. package/test/unit/spec/meeting/locusMediaRequest.ts +49 -0
  198. package/test/unit/spec/meeting/utils.js +3 -10
  199. package/test/unit/spec/meeting/voicea-meeting.ts +5 -14
  200. package/test/unit/spec/meetings/index.js +59 -17
  201. package/test/unit/spec/reachability/index.ts +266 -0
  202. package/test/unit/spec/reconnection-manager/index.js +127 -39
  203. package/test/unit/spec/roap/request.ts +0 -37
  204. package/test/unit/spec/stats-analyzer/index.js +100 -8
  205. package/src/common/errors/reconnection-in-progress.ts +0 -8
@@ -141,6 +141,272 @@ describe('isAnyPublicClusterReachable', () => {
141
141
  });
142
142
  });
143
143
 
144
+
145
+ describe('isWebexMediaBackendUnreachable', () => {
146
+ let webex;
147
+
148
+ beforeEach(() => {
149
+ webex = new MockWebex();
150
+
151
+ sinon.stub(MeetingUtil, 'getIpVersion').returns(IP_VERSION.unknown);
152
+ });
153
+
154
+ afterEach(() => {
155
+ sinon.restore();
156
+ });
157
+
158
+ const runCheck = async (mockStorage: any, expectedValue: boolean) => {
159
+ if (mockStorage) {
160
+ await webex.boundedStorage.put(
161
+ 'Reachability',
162
+ 'reachability.result',
163
+ JSON.stringify(mockStorage)
164
+ );
165
+ }
166
+ const reachability = new Reachability(webex);
167
+
168
+ const result = await reachability.isWebexMediaBackendUnreachable();
169
+
170
+ assert.equal(result, expectedValue);
171
+ };
172
+
173
+ [
174
+ {
175
+ title: 'no clusters at all',
176
+ mockStorage: {},
177
+ expectedResult: false,
178
+ },
179
+ {
180
+ title: 'clusters without results',
181
+ mockStorage: {a: {}, b: {}},
182
+ expectedResult: false,
183
+ },
184
+ {
185
+ title: 'all clusters untested',
186
+ mockStorage: {
187
+ a: {udp: 'untested'},
188
+ b: {udp: 'untested', tcp: 'untested'},
189
+ },
190
+ expectedResult: false,
191
+ },
192
+ {
193
+ title: 'one cluster with udp reachable',
194
+ mockStorage: {x: {udp: {result: 'reachable'}, tcp: {result: 'unreachable'}}},
195
+ expectedResult: false,
196
+ },
197
+ {
198
+ title: 'one cluster with tcp reachable',
199
+ mockStorage: {x: {tcp: {result: 'reachable'}}},
200
+ expectedResult: false,
201
+ },
202
+ {
203
+ title: 'one cluster with xtls reachable',
204
+ mockStorage: {x: {xtls: {result: 'reachable'}}, y: {xtls: {result: 'unreachable'}}},
205
+ expectedResult: false,
206
+ },
207
+ {
208
+ title: 'multiple clusters with various protocols reachable',
209
+ mockStorage: {
210
+ a: {udp: {result: 'reachable'}, tcp: {result: 'reachable'}},
211
+ b: {udp: {result: 'unreachable'}, tcp: {result: 'reachable'}},
212
+ c: {tcp: {result: 'reachable'}},
213
+ d: {xtls: {result: 'reachable'}},
214
+ },
215
+ expectedResult: false,
216
+ },
217
+ {
218
+ title: 'multiple clusters with all protocols unreachable',
219
+ mockStorage: {
220
+ a: {
221
+ udp: {result: 'unreachable'},
222
+ tcp: {result: 'unreachable'},
223
+ xtls: {result: 'unreachable'},
224
+ },
225
+ b: {
226
+ udp: {result: 'unreachable'},
227
+ tcp: {result: 'unreachable'},
228
+ xtls: {result: 'unreachable'},
229
+ },
230
+ c: {
231
+ udp: {result: 'unreachable'},
232
+ tcp: {result: 'unreachable'},
233
+ xtls: {result: 'unreachable'},
234
+ },
235
+ },
236
+ expectedResult: true,
237
+ },
238
+ {
239
+ title: 'multiple clusters with UDP and TCP protocols unreachable, but TLS not tested',
240
+ mockStorage: {
241
+ a: {
242
+ udp: {result: 'unreachable'},
243
+ tcp: {result: 'unreachable'},
244
+ xtls: {result: 'untested'},
245
+ },
246
+ b: {
247
+ udp: {result: 'unreachable'},
248
+ tcp: {result: 'unreachable'},
249
+ xtls: {result: 'untested'},
250
+ },
251
+ c: {
252
+ udp: {result: 'unreachable'},
253
+ tcp: {result: 'unreachable'},
254
+ xtls: {result: 'untested'},
255
+ },
256
+ },
257
+ expectedResult: false,
258
+ },
259
+ {
260
+ title: 'multiple clusters with UDP and TCP protocols unreachable, but TLS missing',
261
+ mockStorage: {
262
+ a: {
263
+ udp: {result: 'unreachable'},
264
+ tcp: {result: 'unreachable'},
265
+ },
266
+ b: {
267
+ udp: {result: 'unreachable'},
268
+ tcp: {result: 'unreachable'},
269
+ },
270
+ c: {
271
+ udp: {result: 'unreachable'},
272
+ tcp: {result: 'unreachable'},
273
+ },
274
+ },
275
+ expectedResult: false,
276
+ },
277
+ {
278
+ title: 'multiple clusters with UDP and TLS protocols unreachable, but TCP not tested',
279
+ mockStorage: {
280
+ a: {
281
+ udp: {result: 'unreachable'},
282
+ tcp: {result: 'untested'},
283
+ xtls: {result: 'unreachable'},
284
+ },
285
+ b: {
286
+ udp: {result: 'unreachable'},
287
+ tcp: {result: 'untested'},
288
+ xtls: {result: 'unreachable'},
289
+ },
290
+ c: {
291
+ udp: {result: 'unreachable'},
292
+ tcp: {result: 'untested'},
293
+ xtls: {result: 'unreachable'},
294
+ },
295
+ },
296
+ expectedResult: false,
297
+ },
298
+ {
299
+ title: 'multiple clusters with UDP and TLS protocols unreachable, but TCP missing',
300
+ mockStorage: {
301
+ a: {
302
+ udp: {result: 'unreachable'},
303
+ xtls: {result: 'unreachable'},
304
+ },
305
+ b: {
306
+ udp: {result: 'unreachable'},
307
+ xtls: {result: 'unreachable'},
308
+ },
309
+ c: {
310
+ udp: {result: 'unreachable'},
311
+ xtls: {result: 'unreachable'},
312
+ },
313
+ },
314
+ expectedResult: false,
315
+ },
316
+ {
317
+ title: 'multiple clusters with all protocols unreachable, some untested',
318
+ mockStorage: {
319
+ a: {
320
+ udp: {result: 'unreachable'},
321
+ tcp: {result: 'unreachable'},
322
+ xtls: {result: 'unreachable'},
323
+ },
324
+ b: {udp: {result: 'unreachable'}, tcp: {result: 'untested'}, xtls: {result: 'unreachable'}},
325
+ c: {udp: {result: 'unreachable'}, tcp: {result: 'unreachable'}, xtls: {result: 'untested'}},
326
+ },
327
+ expectedResult: true,
328
+ },
329
+ {
330
+ title: 'multiple clusters with all protocols unreachable, except for 1 reachable on udp',
331
+ mockStorage: {
332
+ a: {
333
+ udp: {result: 'reachable'},
334
+ tcp: {result: 'unreachable'},
335
+ xtls: {result: 'unreachable'},
336
+ },
337
+ b: {
338
+ udp: {result: 'unreachable'},
339
+ tcp: {result: 'unreachable'},
340
+ xtls: {result: 'unreachable'},
341
+ },
342
+ c: {
343
+ udp: {result: 'unreachable'},
344
+ tcp: {result: 'unreachable'},
345
+ xtls: {result: 'unreachable'},
346
+ },
347
+ },
348
+ expectedResult: false,
349
+ },
350
+ {
351
+ title: 'multiple clusters with all protocols unreachable, except for 1 reachable on tcp',
352
+ mockStorage: {
353
+ a: {
354
+ udp: {result: 'unreachable'},
355
+ tcp: {result: 'unreachable'},
356
+ xtls: {result: 'unreachable'},
357
+ },
358
+ b: {
359
+ udp: {result: 'unreachable'},
360
+ tcp: {result: 'unreachable'},
361
+ xtls: {result: 'unreachable'},
362
+ },
363
+ c: {
364
+ udp: {result: 'unreachable'},
365
+ tcp: {result: 'reachable'},
366
+ xtls: {result: 'unreachable'},
367
+ },
368
+ },
369
+ expectedResult: false,
370
+ },
371
+ {
372
+ title: 'multiple clusters with all protocols unreachable, except for 1 reachable on xtls',
373
+ mockStorage: {
374
+ a: {
375
+ udp: {result: 'unreachable'},
376
+ tcp: {result: 'unreachable'},
377
+ xtls: {result: 'unreachable'},
378
+ },
379
+ b: {
380
+ udp: {result: 'unreachable'},
381
+ tcp: {result: 'unreachable'},
382
+ xtls: {result: 'reachable'},
383
+ },
384
+ c: {
385
+ udp: {result: 'unreachable'},
386
+ tcp: {result: 'unreachable'},
387
+ xtls: {result: 'unreachable'},
388
+ },
389
+ },
390
+ expectedResult: false,
391
+ },
392
+ {
393
+ title: 'multiple clusters with some missing results',
394
+ mockStorage: {
395
+ a: {udp: {result: 'unreachable'}},
396
+ b: {tcp: {result: 'unreachable'}},
397
+ c: {xtls: {result: 'unreachable'}},
398
+ d: {},
399
+ },
400
+ expectedResult: true,
401
+ },
402
+ ].forEach(({mockStorage, expectedResult, title}) => {
403
+ it(`returns ${expectedResult} when ${title}`, async () => {
404
+ await runCheck(mockStorage, expectedResult);
405
+ });
406
+ });
407
+ });
408
+
409
+
144
410
  describe('gatherReachability', () => {
145
411
  let webex;
146
412
 
@@ -2,11 +2,14 @@ import 'jsdom-global/register';
2
2
  import chai from 'chai';
3
3
  import chaiAsPromised from 'chai-as-promised';
4
4
  import sinon from 'sinon';
5
+ import {Defer} from '@webex/common';
5
6
  import ReconnectionManager from '@webex/plugin-meetings/src/reconnection-manager';
7
+ import ReconnectionNotStartedError from '@webex/plugin-meetings/src/common/errors/reconnection-not-started';
8
+ import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
9
+ import Metrics from '@webex/plugin-meetings/src/metrics';
6
10
  import { RECONNECTION } from '../../../../src/constants';
7
11
  import LoggerProxy from '../../../../src/common/logs/logger-proxy';
8
12
  import LoggerConfig from '../../../../src/common/logs/logger-config';
9
-
10
13
  const {assert} = chai;
11
14
 
12
15
  chai.use(chaiAsPromised);
@@ -14,18 +17,15 @@ sinon.assert.expose(chai.assert, {prefix: ''});
14
17
 
15
18
  describe('plugin-meetings', () => {
16
19
  describe('ReconnectionManager.reconnect', () => {
17
- const sandbox = sinon.createSandbox();
18
20
  let fakeMediaConnection;
19
21
  let fakeMeeting;
20
22
  let loggerSpy;
21
23
 
22
- before(() => {
24
+ beforeEach(() => {
23
25
  LoggerConfig.set({ enable: false });
24
26
  LoggerProxy.set();
25
- loggerSpy = sandbox.spy(LoggerProxy.logger, 'info');
26
- });
27
+ loggerSpy = sinon.spy(LoggerProxy.logger, 'info');
27
28
 
28
- beforeEach(() => {
29
29
  fakeMediaConnection = {
30
30
  initiateOffer: sinon.stub().resolves({}),
31
31
  reconnect: sinon.stub().resolves({}),
@@ -33,6 +33,7 @@ describe('plugin-meetings', () => {
33
33
  fakeMeeting = {
34
34
  closePeerConnections: sinon.stub().resolves({}),
35
35
  createMediaConnection: sinon.stub().returns(fakeMediaConnection),
36
+ correlationId: 'correlationId',
36
37
  config: {
37
38
  reconnection: {
38
39
  enabled: true,
@@ -47,6 +48,7 @@ describe('plugin-meetings', () => {
47
48
  },
48
49
  },
49
50
  },
51
+ locusUrl: 'test/id',
50
52
  mediaProperties: {
51
53
  unsetPeerConnection: sinon.stub(),
52
54
  webrtcMediaConnection: fakeMediaConnection,
@@ -83,11 +85,16 @@ describe('plugin-meetings', () => {
83
85
  }
84
86
  }
85
87
  },
88
+ trigger: sinon.stub(),
86
89
  };
90
+
91
+ sinon.stub(TriggerProxy, 'trigger').returns(true);
92
+ sinon.stub(Metrics, 'sendBehavioralMetric');
87
93
  });
88
94
 
89
95
  afterEach(() => {
90
- sandbox.reset();
96
+ sinon.reset();
97
+ sinon.restore();
91
98
  });
92
99
 
93
100
  it('calls syncMeetings', async () => {
@@ -223,6 +230,99 @@ describe('plugin-meetings', () => {
223
230
  });
224
231
  }
225
232
  });
233
+
234
+ it('sends the right metrics and events when succeeds', async () => {
235
+ const rm = new ReconnectionManager(fakeMeeting);
236
+
237
+ await rm.reconnect();
238
+
239
+ assert.calledWith(
240
+ TriggerProxy.trigger,
241
+ fakeMeeting,
242
+ {file: 'reconnection-manager/index', function: 'reconnect'},
243
+ 'meeting:reconnectionSuccess'
244
+ );
245
+ assert.calledWithMatch(fakeMeeting.webex.internal.newMetrics.submitClientEvent, {
246
+ name: 'client.media.recovered',
247
+ payload: {
248
+ recoveredBy: 'new',
249
+ },
250
+ options: {
251
+ meetingId: fakeMeeting.id,
252
+ },
253
+ });
254
+ assert.equal(rm.status, RECONNECTION.STATE.DEFAULT_STATUS);
255
+ });
256
+
257
+ it('sends the right metrics and events when fails', async () => {
258
+ const rm = new ReconnectionManager(fakeMeeting);
259
+
260
+ sinon.stub(rm, 'executeReconnection').rejects(new Error('fake error'));
261
+
262
+ await assert.isRejected(rm.reconnect());
263
+
264
+ assert.calledWith(
265
+ TriggerProxy.trigger,
266
+ fakeMeeting,
267
+ {file: 'reconnection-manager/index', function: 'reconnect'},
268
+ 'meeting:reconnectionFailure'
269
+ );
270
+ assert.calledWithMatch(fakeMeeting.webex.internal.newMetrics.submitClientEvent, {
271
+ name: 'client.call.aborted',
272
+ payload: {
273
+ errors: [
274
+ {
275
+ category: 'expected',
276
+ errorCode: 2008,
277
+ fatal: true,
278
+ name: 'media-engine',
279
+ shownToUser: false,
280
+ },
281
+ ],
282
+ },
283
+ options: {
284
+ meetingId: fakeMeeting.id,
285
+ },
286
+ });
287
+ assert.calledWith(Metrics.sendBehavioralMetric, 'js_sdk_meeting_reconnect_failures', {
288
+ correlation_id: fakeMeeting.correlationId,
289
+ locus_id: 'id',
290
+ reason: 'fake error',
291
+ stack: sinon.match.any,
292
+ });
293
+ assert.equal(rm.status, RECONNECTION.STATE.DEFAULT_STATUS);
294
+ });
295
+
296
+ it('throws ReconnectionNotStartedError if reconnection is already in progress', async () => {
297
+ const rm = new ReconnectionManager(fakeMeeting);
298
+ const defer = new Defer();
299
+
300
+ sinon.stub(rm, 'executeReconnection').returns(defer.promise);
301
+
302
+ rm.reconnect();
303
+
304
+ try {
305
+ await rm.reconnect();
306
+
307
+ fail("rm.reconnect() should have thrown, but it hasn't");
308
+ } catch (e) {
309
+ assert.instanceOf(e, ReconnectionNotStartedError);
310
+ }
311
+ });
312
+
313
+ it('throws ReconnectionNotStartedError if reconnection is disabled in config', async () => {
314
+ fakeMeeting.config.reconnection.enabled = false;
315
+
316
+ const rm = new ReconnectionManager(fakeMeeting);
317
+
318
+ try {
319
+ await rm.reconnect();
320
+
321
+ fail("rm.reconnect() should have thrown, but it hasn't");
322
+ } catch (e) {
323
+ assert.instanceOf(e, ReconnectionNotStartedError);
324
+ }
325
+ });
226
326
  });
227
327
 
228
328
  /**
@@ -316,29 +416,41 @@ describe('plugin-meetings', () => {
316
416
 
317
417
  describe('waitForIceReconnect()', () => {
318
418
  describe('when ice is marked as not disconnected', () => {
419
+ let clock;
420
+
319
421
  beforeEach(() => {
422
+ clock = sinon.useFakeTimers();
320
423
  reconnectionManager.iceState.disconnected = false;
321
424
  });
322
425
 
426
+ afterEach(() => {
427
+ clock.restore();
428
+ });
429
+
323
430
  it('should set the disconnected state to true', () => {
324
- reconnectionManager.waitForIceReconnect();
431
+ const promise = reconnectionManager.waitForIceReconnect();
325
432
 
326
433
  assert.isTrue(reconnectionManager.iceState.disconnected);
434
+
435
+ // we let the timer expire
436
+ clock.tick(reconnectionManager.iceState.timeoutDuration);
437
+ assert.isRejected(promise);
327
438
  });
328
439
 
329
- it('should return a promise that rejects after a duration', (done) => {
330
- reconnectionManager.iceState.timeoutDuration = 100;
440
+ it('should return a promise that rejects after a duration', async () => {
441
+ const promise = reconnectionManager.waitForIceReconnect();
331
442
 
332
- assert.isRejected(reconnectionManager.waitForIceReconnect());
333
- done();
443
+ // we let the timer expire
444
+ clock.tick(reconnectionManager.iceState.timeoutDuration);
445
+ assert.isRejected(promise);
334
446
  });
335
447
 
336
- it('should resolve return a resolved promise when triggered', () => {
448
+ it('should resolve when ICE is reconnected', async () => {
337
449
  const promise = reconnectionManager.waitForIceReconnect();
338
450
 
339
- reconnectionManager.iceState.resolve();
451
+ reconnectionManager.iceReconnected();
340
452
 
341
- assert.isFulfilled(promise);
453
+ await promise;
342
454
  });
343
455
  });
344
456
 
@@ -359,30 +471,6 @@ describe('plugin-meetings', () => {
359
471
  });
360
472
  });
361
473
 
362
- describe('setStatus()', () => {
363
- beforeEach(() => {
364
- reconnectionManager.status = RECONNECTION.STATE.DEFAULT_STATUS;
365
- });
366
-
367
- it('should correctly change status to in progress', () => {
368
- reconnectionManager.setStatus(RECONNECTION.STATE.IN_PROGRESS);
369
-
370
- assert.equal(reconnectionManager.status, RECONNECTION.STATE.IN_PROGRESS);
371
- });
372
-
373
- it('should correctly change status to complete', () => {
374
- reconnectionManager.setStatus(RECONNECTION.STATE.COMPLETE);
375
-
376
- assert.equal(reconnectionManager.status, RECONNECTION.STATE.COMPLETE);
377
- });
378
-
379
- it('should correctly change status to failure', () => {
380
- reconnectionManager.setStatus(RECONNECTION.STATE.FAILURE);
381
-
382
- assert.equal(reconnectionManager.status, RECONNECTION.STATE.FAILURE);
383
- });
384
- });
385
-
386
474
  describe('cleanUp()', () => {
387
475
  it('should call reset and keep reference to meeting object', () => {
388
476
  const resetSpy = sinon.spy(reconnectionManager, 'reset');
@@ -133,20 +133,6 @@ describe('plugin-meetings/roap', () => {
133
133
  locusMediaRequest,
134
134
  });
135
135
 
136
- assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
137
- name: 'client.locus.media.request',
138
- options: {
139
- meetingId: 'meeting-id',
140
- },
141
- });
142
-
143
- assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
144
- name: 'client.locus.media.response',
145
- options: {
146
- meetingId: 'meeting-id',
147
- },
148
- });
149
-
150
136
  const requestParams = locusMediaRequest.send.getCall(0).args[0];
151
137
  assert.deepEqual(requestParams, {
152
138
  type: 'RoapMessage',
@@ -175,29 +161,6 @@ describe('plugin-meetings/roap', () => {
175
161
  },
176
162
  });
177
163
  });
178
-
179
- it('sends correct client event when fails', async () => {
180
- const locusMediaRequest = {send: sinon.stub().rejects({code: 300, message: 'error'})};
181
- try {
182
- await roapRequest.sendRoap({
183
- locusSelfUrl: locusUrl,
184
- mediaId: 'mediaId',
185
- roapMessage: {
186
- seq: 'seq',
187
- },
188
- meetingId: 'meeting-id',
189
- locusMediaRequest,
190
- });
191
- } catch (err) {
192
- assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
193
- name: 'client.locus.media.response',
194
- options: {
195
- meetingId: 'meeting-id',
196
- rawError: {code: 300, message: 'error'},
197
- },
198
- });
199
- }
200
- });
201
164
  });
202
165
 
203
166
  it('calls attachReachabilityData when sendRoap', async () => {