@webex/plugin-meetings 3.0.0 → 3.1.0-next.10

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 (272) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/common/errors/{reconnection-in-progress.js → reconnection-not-started.js} +27 -15
  4. package/dist/common/errors/reconnection-not-started.js.map +1 -0
  5. package/dist/config.js +2 -1
  6. package/dist/config.js.map +1 -1
  7. package/dist/constants.js +18 -6
  8. package/dist/constants.js.map +1 -1
  9. package/dist/index.js +86 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/interpretation/index.js +16 -2
  12. package/dist/interpretation/index.js.map +1 -1
  13. package/dist/interpretation/siLanguage.js +1 -1
  14. package/dist/locus-info/controlsUtils.js +7 -1
  15. package/dist/locus-info/controlsUtils.js.map +1 -1
  16. package/dist/locus-info/index.js +10 -0
  17. package/dist/locus-info/index.js.map +1 -1
  18. package/dist/locus-info/mediaSharesUtils.js +15 -1
  19. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  20. package/dist/locus-info/selfUtils.js +5 -0
  21. package/dist/locus-info/selfUtils.js.map +1 -1
  22. package/dist/media/MediaConnectionAwaiter.js +163 -0
  23. package/dist/media/MediaConnectionAwaiter.js.map +1 -0
  24. package/dist/media/index.js +4 -1
  25. package/dist/media/index.js.map +1 -1
  26. package/dist/media/properties.js +106 -81
  27. package/dist/media/properties.js.map +1 -1
  28. package/dist/meeting/in-meeting-actions.js +6 -0
  29. package/dist/meeting/in-meeting-actions.js.map +1 -1
  30. package/dist/meeting/index.js +1010 -753
  31. package/dist/meeting/index.js.map +1 -1
  32. package/dist/meeting/muteState.js +37 -25
  33. package/dist/meeting/muteState.js.map +1 -1
  34. package/dist/meeting/request.js +32 -23
  35. package/dist/meeting/request.js.map +1 -1
  36. package/dist/meeting/util.js +10 -0
  37. package/dist/meeting/util.js.map +1 -1
  38. package/dist/meeting-info/util.js +304 -267
  39. package/dist/meeting-info/util.js.map +1 -1
  40. package/dist/meeting-info/utilv2.js +334 -295
  41. package/dist/meeting-info/utilv2.js.map +1 -1
  42. package/dist/meetings/index.js +21 -23
  43. package/dist/meetings/index.js.map +1 -1
  44. package/dist/multistream/mediaRequestManager.js +1 -1
  45. package/dist/multistream/mediaRequestManager.js.map +1 -1
  46. package/dist/multistream/remoteMediaGroup.js +16 -2
  47. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  48. package/dist/multistream/remoteMediaManager.js +179 -65
  49. package/dist/multistream/remoteMediaManager.js.map +1 -1
  50. package/dist/multistream/sendSlotManager.js +22 -0
  51. package/dist/multistream/sendSlotManager.js.map +1 -1
  52. package/dist/reachability/clusterReachability.js +29 -15
  53. package/dist/reachability/clusterReachability.js.map +1 -1
  54. package/dist/reachability/index.js +18 -2
  55. package/dist/reachability/index.js.map +1 -1
  56. package/dist/reachability/request.js +12 -10
  57. package/dist/reachability/request.js.map +1 -1
  58. package/dist/reachability/util.js +19 -0
  59. package/dist/reachability/util.js.map +1 -1
  60. package/dist/reconnection-manager/index.js +140 -110
  61. package/dist/reconnection-manager/index.js.map +1 -1
  62. package/dist/roap/index.js +15 -0
  63. package/dist/roap/index.js.map +1 -1
  64. package/dist/roap/request.js +3 -3
  65. package/dist/roap/request.js.map +1 -1
  66. package/dist/roap/turnDiscovery.js +307 -126
  67. package/dist/roap/turnDiscovery.js.map +1 -1
  68. package/dist/statsAnalyzer/index.js +57 -30
  69. package/dist/statsAnalyzer/index.js.map +1 -1
  70. package/dist/statsAnalyzer/mqaUtil.js +3 -0
  71. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  72. package/dist/types/common/errors/reconnection-not-started.d.ts +13 -0
  73. package/dist/{config.d.ts → types/config.d.ts} +1 -0
  74. package/dist/{constants.d.ts → types/constants.d.ts} +15 -6
  75. package/dist/types/index.d.ts +19 -0
  76. package/dist/types/media/MediaConnectionAwaiter.d.ts +61 -0
  77. package/dist/{media → types/media}/properties.d.ts +26 -2
  78. package/dist/{meeting → types/meeting}/in-meeting-actions.d.ts +6 -0
  79. package/dist/{meeting → types/meeting}/index.d.ts +29 -12
  80. package/dist/{meeting → types/meeting}/muteState.d.ts +2 -8
  81. package/dist/{meeting → types/meeting}/request.d.ts +3 -0
  82. package/dist/{meeting → types/meeting}/util.d.ts +3 -0
  83. package/dist/{meeting-info → types/meeting-info}/index.d.ts +1 -1
  84. package/dist/{meeting-info → types/meeting-info}/meeting-info-v2.d.ts +1 -1
  85. package/dist/types/meeting-info/util.d.ts +49 -0
  86. package/dist/types/meeting-info/utilv2.d.ts +65 -0
  87. package/dist/{meetings → types/meetings}/index.d.ts +9 -16
  88. package/dist/{multistream → types/multistream}/mediaRequestManager.d.ts +2 -1
  89. package/dist/{multistream → types/multistream}/remoteMediaGroup.d.ts +2 -0
  90. package/dist/{multistream → types/multistream}/remoteMediaManager.d.ts +15 -0
  91. package/dist/{multistream → types/multistream}/sendSlotManager.d.ts +9 -1
  92. package/dist/{reachability → types/reachability}/clusterReachability.d.ts +1 -0
  93. package/dist/{reachability → types/reachability}/index.d.ts +4 -0
  94. package/dist/{reachability → types/reachability}/util.d.ts +7 -0
  95. package/dist/{reconnection-manager → types/reconnection-manager}/index.d.ts +4 -14
  96. package/dist/{roap → types/roap}/index.d.ts +10 -2
  97. package/dist/{roap → types/roap}/turnDiscovery.d.ts +64 -17
  98. package/dist/webinar/index.js +1 -1
  99. package/package.json +23 -23
  100. package/src/common/errors/reconnection-not-started.ts +25 -0
  101. package/src/config.ts +1 -0
  102. package/src/constants.ts +18 -6
  103. package/src/index.ts +31 -0
  104. package/src/interpretation/index.ts +18 -1
  105. package/src/locus-info/controlsUtils.ts +11 -0
  106. package/src/locus-info/index.ts +16 -0
  107. package/src/locus-info/mediaSharesUtils.ts +16 -0
  108. package/src/locus-info/selfUtils.ts +5 -0
  109. package/src/media/MediaConnectionAwaiter.ts +174 -0
  110. package/src/media/index.ts +3 -1
  111. package/src/media/properties.ts +73 -46
  112. package/src/meeting/in-meeting-actions.ts +12 -0
  113. package/src/meeting/index.ts +389 -180
  114. package/src/meeting/muteState.ts +34 -20
  115. package/src/meeting/request.ts +18 -2
  116. package/src/meeting/util.ts +9 -0
  117. package/src/meeting-info/util.ts +241 -233
  118. package/src/meeting-info/utilv2.ts +250 -243
  119. package/src/meetings/index.ts +20 -24
  120. package/src/multistream/mediaRequestManager.ts +4 -1
  121. package/src/multistream/remoteMediaGroup.ts +19 -0
  122. package/src/multistream/remoteMediaManager.ts +101 -16
  123. package/src/multistream/sendSlotManager.ts +28 -0
  124. package/src/reachability/clusterReachability.ts +20 -5
  125. package/src/reachability/index.ts +24 -1
  126. package/src/reachability/request.ts +15 -11
  127. package/src/reachability/util.ts +21 -0
  128. package/src/reconnection-manager/index.ts +129 -106
  129. package/src/roap/index.ts +25 -3
  130. package/src/roap/request.ts +3 -3
  131. package/src/roap/turnDiscovery.ts +244 -78
  132. package/src/statsAnalyzer/index.ts +67 -27
  133. package/src/statsAnalyzer/mqaUtil.ts +5 -0
  134. package/test/integration/spec/journey.js +14 -14
  135. package/test/integration/spec/space-meeting.js +1 -1
  136. package/test/unit/spec/interpretation/index.ts +39 -3
  137. package/test/unit/spec/locus-info/controlsUtils.js +20 -0
  138. package/test/unit/spec/locus-info/index.js +49 -19
  139. package/test/unit/spec/locus-info/mediaSharesUtils.ts +9 -0
  140. package/test/unit/spec/locus-info/selfUtils.js +42 -12
  141. package/test/unit/spec/media/MediaConnectionAwaiter.ts +344 -0
  142. package/test/unit/spec/media/index.ts +89 -78
  143. package/test/unit/spec/media/properties.ts +160 -209
  144. package/test/unit/spec/meeting/in-meeting-actions.ts +6 -0
  145. package/test/unit/spec/meeting/index.js +833 -205
  146. package/test/unit/spec/meeting/muteState.js +219 -67
  147. package/test/unit/spec/meeting/request.js +21 -0
  148. package/test/unit/spec/meeting/utils.js +9 -1
  149. package/test/unit/spec/meeting-info/utilv2.js +6 -0
  150. package/test/unit/spec/meetings/index.js +41 -26
  151. package/test/unit/spec/multistream/mediaRequestManager.ts +20 -2
  152. package/test/unit/spec/multistream/remoteMediaGroup.ts +79 -1
  153. package/test/unit/spec/multistream/remoteMediaManager.ts +199 -1
  154. package/test/unit/spec/multistream/sendSlotManager.ts +50 -18
  155. package/test/unit/spec/reachability/clusterReachability.ts +86 -22
  156. package/test/unit/spec/reachability/index.ts +197 -60
  157. package/test/unit/spec/reachability/request.js +15 -7
  158. package/test/unit/spec/reachability/util.ts +32 -2
  159. package/test/unit/spec/reconnection-manager/index.js +155 -39
  160. package/test/unit/spec/roap/index.ts +61 -6
  161. package/test/unit/spec/roap/turnDiscovery.ts +298 -16
  162. package/test/unit/spec/stats-analyzer/index.js +190 -0
  163. package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
  164. package/dist/common/errors/reconnection-in-progress.js.map +0 -1
  165. package/dist/index.d.ts +0 -7
  166. package/dist/meeting-info/util.d.ts +0 -2
  167. package/dist/meeting-info/utilv2.d.ts +0 -2
  168. package/dist/member/member.types.d.ts +0 -11
  169. package/dist/member/member.types.js +0 -17
  170. package/dist/member/member.types.js.map +0 -1
  171. package/src/common/errors/reconnection-in-progress.ts +0 -8
  172. package/src/member/member.types.ts +0 -13
  173. /package/dist/{annotation → types/annotation}/annotation.types.d.ts +0 -0
  174. /package/dist/{annotation → types/annotation}/constants.d.ts +0 -0
  175. /package/dist/{annotation → types/annotation}/index.d.ts +0 -0
  176. /package/dist/{breakouts → types/breakouts}/breakout.d.ts +0 -0
  177. /package/dist/{breakouts → types/breakouts}/collection.d.ts +0 -0
  178. /package/dist/{breakouts → types/breakouts}/edit-lock-error.d.ts +0 -0
  179. /package/dist/{breakouts → types/breakouts}/events.d.ts +0 -0
  180. /package/dist/{breakouts → types/breakouts}/index.d.ts +0 -0
  181. /package/dist/{breakouts → types/breakouts}/request.d.ts +0 -0
  182. /package/dist/{breakouts → types/breakouts}/utils.d.ts +0 -0
  183. /package/dist/{common → types/common}/browser-detection.d.ts +0 -0
  184. /package/dist/{common → types/common}/collection.d.ts +0 -0
  185. /package/dist/{common → types/common}/config.d.ts +0 -0
  186. /package/dist/{common → types/common}/errors/captcha-error.d.ts +0 -0
  187. /package/dist/{common → types/common}/errors/intent-to-join.d.ts +0 -0
  188. /package/dist/{common → types/common}/errors/join-meeting.d.ts +0 -0
  189. /package/dist/{common → types/common}/errors/media.d.ts +0 -0
  190. /package/dist/{common → types/common}/errors/no-meeting-info.d.ts +0 -0
  191. /package/dist/{common → types/common}/errors/parameter.d.ts +0 -0
  192. /package/dist/{common → types/common}/errors/password-error.d.ts +0 -0
  193. /package/dist/{common → types/common}/errors/permission.d.ts +0 -0
  194. /package/dist/{common → types/common}/errors/reclaim-host-role-errors.d.ts +0 -0
  195. /package/dist/{common → types/common}/errors/reconnection.d.ts +0 -0
  196. /package/dist/{common → types/common}/errors/stats.d.ts +0 -0
  197. /package/dist/{common → types/common}/errors/webex-errors.d.ts +0 -0
  198. /package/dist/{common → types/common}/errors/webex-meetings-error.d.ts +0 -0
  199. /package/dist/{common → types/common}/events/events-scope.d.ts +0 -0
  200. /package/dist/{common → types/common}/events/events.d.ts +0 -0
  201. /package/dist/{common → types/common}/events/trigger-proxy.d.ts +0 -0
  202. /package/dist/{common → types/common}/events/util.d.ts +0 -0
  203. /package/dist/{common → types/common}/logs/logger-config.d.ts +0 -0
  204. /package/dist/{common → types/common}/logs/logger-proxy.d.ts +0 -0
  205. /package/dist/{common → types/common}/logs/request.d.ts +0 -0
  206. /package/dist/{common → types/common}/queue.d.ts +0 -0
  207. /package/dist/{controls-options-manager → types/controls-options-manager}/constants.d.ts +0 -0
  208. /package/dist/{controls-options-manager → types/controls-options-manager}/enums.d.ts +0 -0
  209. /package/dist/{controls-options-manager → types/controls-options-manager}/index.d.ts +0 -0
  210. /package/dist/{controls-options-manager → types/controls-options-manager}/types.d.ts +0 -0
  211. /package/dist/{controls-options-manager → types/controls-options-manager}/util.d.ts +0 -0
  212. /package/dist/{interceptors → types/interceptors}/index.d.ts +0 -0
  213. /package/dist/{interceptors → types/interceptors}/locusRetry.d.ts +0 -0
  214. /package/dist/{interpretation → types/interpretation}/collection.d.ts +0 -0
  215. /package/dist/{interpretation → types/interpretation}/index.d.ts +0 -0
  216. /package/dist/{interpretation → types/interpretation}/siLanguage.d.ts +0 -0
  217. /package/dist/{locus-info → types/locus-info}/controlsUtils.d.ts +0 -0
  218. /package/dist/{locus-info → types/locus-info}/embeddedAppsUtils.d.ts +0 -0
  219. /package/dist/{locus-info → types/locus-info}/fullState.d.ts +0 -0
  220. /package/dist/{locus-info → types/locus-info}/hostUtils.d.ts +0 -0
  221. /package/dist/{locus-info → types/locus-info}/index.d.ts +0 -0
  222. /package/dist/{locus-info → types/locus-info}/infoUtils.d.ts +0 -0
  223. /package/dist/{locus-info → types/locus-info}/mediaSharesUtils.d.ts +0 -0
  224. /package/dist/{locus-info → types/locus-info}/parser.d.ts +0 -0
  225. /package/dist/{locus-info → types/locus-info}/selfUtils.d.ts +0 -0
  226. /package/dist/{media → types/media}/index.d.ts +0 -0
  227. /package/dist/{media → types/media}/util.d.ts +0 -0
  228. /package/dist/{mediaQualityMetrics → types/mediaQualityMetrics}/config.d.ts +0 -0
  229. /package/dist/{meeting → types/meeting}/locusMediaRequest.d.ts +0 -0
  230. /package/dist/{meeting → types/meeting}/request.type.d.ts +0 -0
  231. /package/dist/{meeting → types/meeting}/state.d.ts +0 -0
  232. /package/dist/{meeting → types/meeting}/voicea-meeting.d.ts +0 -0
  233. /package/dist/{meeting-info → types/meeting-info}/collection.d.ts +0 -0
  234. /package/dist/{meeting-info → types/meeting-info}/request.d.ts +0 -0
  235. /package/dist/{meetings → types/meetings}/collection.d.ts +0 -0
  236. /package/dist/{meetings → types/meetings}/meetings.types.d.ts +0 -0
  237. /package/dist/{meetings → types/meetings}/request.d.ts +0 -0
  238. /package/dist/{meetings → types/meetings}/util.d.ts +0 -0
  239. /package/dist/{member → types/member}/index.d.ts +0 -0
  240. /package/dist/{member → types/member}/types.d.ts +0 -0
  241. /package/dist/{member → types/member}/util.d.ts +0 -0
  242. /package/dist/{members → types/members}/collection.d.ts +0 -0
  243. /package/dist/{members → types/members}/index.d.ts +0 -0
  244. /package/dist/{members → types/members}/request.d.ts +0 -0
  245. /package/dist/{members → types/members}/types.d.ts +0 -0
  246. /package/dist/{members → types/members}/util.d.ts +0 -0
  247. /package/dist/{metrics → types/metrics}/constants.d.ts +0 -0
  248. /package/dist/{metrics → types/metrics}/index.d.ts +0 -0
  249. /package/dist/{multistream → types/multistream}/receiveSlot.d.ts +0 -0
  250. /package/dist/{multistream → types/multistream}/receiveSlotManager.d.ts +0 -0
  251. /package/dist/{multistream → types/multistream}/remoteMedia.d.ts +0 -0
  252. /package/dist/{networkQualityMonitor → types/networkQualityMonitor}/index.d.ts +0 -0
  253. /package/dist/{personal-meeting-room → types/personal-meeting-room}/index.d.ts +0 -0
  254. /package/dist/{personal-meeting-room → types/personal-meeting-room}/request.d.ts +0 -0
  255. /package/dist/{personal-meeting-room → types/personal-meeting-room}/util.d.ts +0 -0
  256. /package/dist/{reachability → types/reachability}/request.d.ts +0 -0
  257. /package/dist/{reactions → types/reactions}/constants.d.ts +0 -0
  258. /package/dist/{reactions → types/reactions}/reactions.d.ts +0 -0
  259. /package/dist/{reactions → types/reactions}/reactions.type.d.ts +0 -0
  260. /package/dist/{recording-controller → types/recording-controller}/enums.d.ts +0 -0
  261. /package/dist/{recording-controller → types/recording-controller}/index.d.ts +0 -0
  262. /package/dist/{recording-controller → types/recording-controller}/util.d.ts +0 -0
  263. /package/dist/{roap → types/roap}/request.d.ts +0 -0
  264. /package/dist/{rtcMetrics → types/rtcMetrics}/constants.d.ts +0 -0
  265. /package/dist/{rtcMetrics → types/rtcMetrics}/index.d.ts +0 -0
  266. /package/dist/{statsAnalyzer → types/statsAnalyzer}/global.d.ts +0 -0
  267. /package/dist/{statsAnalyzer → types/statsAnalyzer}/index.d.ts +0 -0
  268. /package/dist/{statsAnalyzer → types/statsAnalyzer}/mqaUtil.d.ts +0 -0
  269. /package/dist/{transcription → types/transcription}/index.d.ts +0 -0
  270. /package/dist/{webinar → types/webinar}/collection.d.ts +0 -0
  271. /package/dist/{webinar → types/webinar}/index.d.ts +0 -0
  272. /package/test/unit/spec/locus-info/{lib/selfConstant.js → selfConstant.js} +0 -0
@@ -1,6 +1,9 @@
1
1
  import {assert} from '@webex/test-helper-chai';
2
2
 
3
- import {convertStunUrlToTurn} from '@webex/plugin-meetings/src/reachability/util';
3
+ import {
4
+ convertStunUrlToTurn,
5
+ convertStunUrlToTurnTls,
6
+ } from '@webex/plugin-meetings/src/reachability/util';
4
7
 
5
8
  describe('plugin-meetings/src/reachability/util', () => {
6
9
  describe('#convertStunUrlToTurn()', () => {
@@ -34,7 +37,34 @@ describe('plugin-meetings/src/reachability/util', () => {
34
37
  });
35
38
 
36
39
  it('show fail if stunUrl is not a STUN url', () => {
37
- assert.throws(() => convertStunUrlToTurn('http://webex.com', 'tcp'), 'Not a STUN URL: http://webex.com');
40
+ assert.throws(
41
+ () => convertStunUrlToTurn('http://webex.com', 'tcp'),
42
+ 'Not a STUN URL: http://webex.com'
43
+ );
44
+ });
45
+ });
46
+
47
+ describe('#convertStunUrlToTurnTls()', () => {
48
+ it(`should convert to a turns url`, () => {
49
+ const turnsUrl = convertStunUrlToTurnTls(
50
+ 'stun:external-media91.public.wjfkm-a-10.prod.infra.webex.com:443'
51
+ );
52
+
53
+ assert.equal(
54
+ turnsUrl,
55
+ 'turns:external-media91.public.wjfkm-a-10.prod.infra.webex.com:443?transport=tcp'
56
+ );
57
+ });
58
+
59
+ it('show fail if stunUrl is not a valid url', () => {
60
+ assert.throws(() => convertStunUrlToTurn('not a url', 'tcp'), 'Invalid URL: not a url');
61
+ });
62
+
63
+ it('show fail if stunUrl is not a STUN url', () => {
64
+ assert.throws(
65
+ () => convertStunUrlToTurn('http://webex.com', 'tcp'),
66
+ 'Not a STUN URL: http://webex.com'
67
+ );
38
68
  });
39
69
  });
40
70
  });
@@ -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 () => {
@@ -144,6 +151,34 @@ describe('plugin-meetings', () => {
144
151
  });
145
152
  });
146
153
 
154
+ // this can happen when we land on a video mesh node
155
+ it('does not use TURN server if TURN url is an empty string', async () => {
156
+ const rm = new ReconnectionManager(fakeMeeting);
157
+
158
+ fakeMeeting.roap.doTurnDiscovery.resolves({
159
+ turnServerInfo: {
160
+ url: '',
161
+ username: 'whatever',
162
+ password: 'whatever',
163
+ },
164
+ turnDiscoverySkippedReason: undefined,
165
+ });
166
+
167
+ await rm.reconnect();
168
+
169
+ assert.calledOnce(fakeMeeting.roap.doTurnDiscovery);
170
+ assert.calledWith(fakeMeeting.roap.doTurnDiscovery, fakeMeeting, true, true);
171
+ assert.calledOnce(fakeMediaConnection.reconnect);
172
+ assert.calledWith(fakeMediaConnection.reconnect, []);
173
+
174
+ assert.calledWith(fakeMeeting.webex.internal.newMetrics.submitClientEvent, {
175
+ name: 'client.media.reconnecting',
176
+ options: {
177
+ meetingId: rm.meeting.id,
178
+ },
179
+ });
180
+ });
181
+
147
182
  it('does not clear previous requests and re-request media for non-multistream meetings', async () => {
148
183
  fakeMeeting.isMultistream = false;
149
184
  const rm = new ReconnectionManager(fakeMeeting);
@@ -195,6 +230,99 @@ describe('plugin-meetings', () => {
195
230
  });
196
231
  }
197
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
+ });
198
326
  });
199
327
 
200
328
  /**
@@ -288,29 +416,41 @@ describe('plugin-meetings', () => {
288
416
 
289
417
  describe('waitForIceReconnect()', () => {
290
418
  describe('when ice is marked as not disconnected', () => {
419
+ let clock;
420
+
291
421
  beforeEach(() => {
422
+ clock = sinon.useFakeTimers();
292
423
  reconnectionManager.iceState.disconnected = false;
293
424
  });
294
425
 
426
+ afterEach(() => {
427
+ clock.restore();
428
+ });
429
+
295
430
  it('should set the disconnected state to true', () => {
296
- reconnectionManager.waitForIceReconnect();
431
+ const promise = reconnectionManager.waitForIceReconnect();
297
432
 
298
433
  assert.isTrue(reconnectionManager.iceState.disconnected);
434
+
435
+ // we let the timer expire
436
+ clock.tick(reconnectionManager.iceState.timeoutDuration);
437
+ assert.isRejected(promise);
299
438
  });
300
439
 
301
- it('should return a promise that rejects after a duration', (done) => {
302
- reconnectionManager.iceState.timeoutDuration = 100;
440
+ it('should return a promise that rejects after a duration', async () => {
441
+ const promise = reconnectionManager.waitForIceReconnect();
303
442
 
304
- assert.isRejected(reconnectionManager.waitForIceReconnect());
305
- done();
443
+ // we let the timer expire
444
+ clock.tick(reconnectionManager.iceState.timeoutDuration);
445
+ assert.isRejected(promise);
306
446
  });
307
447
 
308
- it('should resolve return a resolved promise when triggered', () => {
448
+ it('should resolve when ICE is reconnected', async () => {
309
449
  const promise = reconnectionManager.waitForIceReconnect();
310
450
 
311
- reconnectionManager.iceState.resolve();
451
+ reconnectionManager.iceReconnected();
312
452
 
313
- assert.isFulfilled(promise);
453
+ await promise;
314
454
  });
315
455
  });
316
456
 
@@ -331,30 +471,6 @@ describe('plugin-meetings', () => {
331
471
  });
332
472
  });
333
473
 
334
- describe('setStatus()', () => {
335
- beforeEach(() => {
336
- reconnectionManager.status = RECONNECTION.STATE.DEFAULT_STATUS;
337
- });
338
-
339
- it('should correctly change status to in progress', () => {
340
- reconnectionManager.setStatus(RECONNECTION.STATE.IN_PROGRESS);
341
-
342
- assert.equal(reconnectionManager.status, RECONNECTION.STATE.IN_PROGRESS);
343
- });
344
-
345
- it('should correctly change status to complete', () => {
346
- reconnectionManager.setStatus(RECONNECTION.STATE.COMPLETE);
347
-
348
- assert.equal(reconnectionManager.status, RECONNECTION.STATE.COMPLETE);
349
- });
350
-
351
- it('should correctly change status to failure', () => {
352
- reconnectionManager.setStatus(RECONNECTION.STATE.FAILURE);
353
-
354
- assert.equal(reconnectionManager.status, RECONNECTION.STATE.FAILURE);
355
- });
356
- });
357
-
358
474
  describe('cleanUp()', () => {
359
475
  it('should call reset and keep reference to meeting object', () => {
360
476
  const resetSpy = sinon.spy(reconnectionManager, 'reset');
@@ -13,15 +13,23 @@ import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
13
13
  import { IP_VERSION } from '../../../../src/constants';
14
14
 
15
15
  describe('Roap', () => {
16
+ let webex;
17
+
18
+ const RESULT = {something: 'some value'};
19
+ const meeting = {id: 'some meeting id'} as Meeting;
20
+
21
+ beforeEach(() => {
22
+ webex = new MockWebex({});
23
+ });
24
+
25
+ afterEach(() => {
26
+ sinon.restore();
27
+ });
28
+
16
29
  describe('doTurnDiscovery', () => {
17
30
  [false, true].forEach(function (isReconnecting) {
18
31
  [false, true, undefined].forEach(function (isForced) {
19
32
  it(`calls this.turnDiscovery.doTurnDiscovery() and forwards all the arguments when isReconnecting = ${isReconnecting} and isForced = ${isForced}`, async () => {
20
- const webex = new MockWebex({});
21
-
22
- const RESULT = {something: 'some value'};
23
- const meeting = {id: 'some meeting id'} as Meeting;
24
-
25
33
  const doTurnDiscoveryStub = sinon
26
34
  .stub(TurnDiscovery.prototype, 'doTurnDiscovery')
27
35
  .resolves(RESULT);
@@ -32,11 +40,58 @@ describe('Roap', () => {
32
40
 
33
41
  assert.calledOnceWithExactly(doTurnDiscoveryStub, meeting, isReconnecting, isForced);
34
42
  assert.deepEqual(result, RESULT);
43
+ });
44
+ });
45
+ });
46
+
47
+ describe('generateTurnDiscoveryRequestMessage', () => {
48
+ [false, true].forEach(function (isForced) {
49
+ it(`calls this.turnDiscovery.generateTurnDiscoveryRequestMessage with isForced=${isForced}`, async () => {
50
+ const generateTurnDiscoveryRequestMessageStub = sinon
51
+ .stub(TurnDiscovery.prototype, 'generateTurnDiscoveryRequestMessage')
52
+ .resolves(RESULT);
53
+
54
+ const roap = new Roap({}, {parent: webex});
35
55
 
36
- sinon.restore();
56
+ const result = await roap.generateTurnDiscoveryRequestMessage(meeting, isForced);
57
+
58
+ assert.calledOnceWithExactly(generateTurnDiscoveryRequestMessageStub, meeting, isForced);
59
+ assert.deepEqual(result, RESULT);
37
60
  });
38
61
  });
39
62
  });
63
+
64
+ describe('handleTurnDiscoveryHttpResponse', () => {
65
+ it('calls this.turnDiscovery.handleTurnDiscoveryHttpResponse', async () => {
66
+ const handleTurnDiscoveryHttpResponseStub = sinon
67
+ .stub(TurnDiscovery.prototype, 'handleTurnDiscoveryHttpResponse')
68
+ .resolves(RESULT);
69
+
70
+ const httpReponse = {some: 'http response'};
71
+
72
+ const roap = new Roap({}, {parent: webex});
73
+
74
+ const result = await roap.handleTurnDiscoveryHttpResponse(meeting, httpReponse);
75
+
76
+ assert.calledOnceWithExactly(handleTurnDiscoveryHttpResponseStub, meeting, httpReponse);
77
+ assert.deepEqual(result, RESULT);
78
+ });
79
+ });
80
+
81
+ describe('abortTurnDiscovery', () => {
82
+ it('calls this.turnDiscovery.abort', async () => {
83
+ const abortStub = sinon
84
+ .stub(TurnDiscovery.prototype, 'abort')
85
+ .returns(RESULT);
86
+
87
+ const roap = new Roap({}, {parent: webex});
88
+
89
+ const result = await roap.abortTurnDiscovery();
90
+
91
+ assert.calledOnceWithExactly(abortStub);
92
+ assert.deepEqual(result, RESULT);
93
+ });
94
+ });
40
95
  });
41
96
 
42
97
  describe('sendRoapMediaRequest', () => {