@webex/plugin-meetings 3.6.0 → 3.7.0-ipv6-multi-turn-urls.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (332) hide show
  1. package/README.md +2 -1
  2. package/dist/breakouts/breakout.js +1 -1
  3. package/dist/breakouts/index.js +1 -1
  4. package/dist/common/errors/join-webinar-error.js +50 -0
  5. package/dist/common/errors/join-webinar-error.js.map +1 -0
  6. package/dist/config.js +4 -1
  7. package/dist/config.js.map +1 -1
  8. package/dist/constants.js +54 -4
  9. package/dist/constants.js.map +1 -1
  10. package/dist/controls-options-manager/enums.js +1 -0
  11. package/dist/controls-options-manager/enums.js.map +1 -1
  12. package/dist/controls-options-manager/index.js +10 -3
  13. package/dist/controls-options-manager/index.js.map +1 -1
  14. package/dist/controls-options-manager/types.js.map +1 -1
  15. package/dist/controls-options-manager/util.js +12 -0
  16. package/dist/controls-options-manager/util.js.map +1 -1
  17. package/dist/index.js +7 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/interpretation/index.js +1 -1
  20. package/dist/interpretation/siLanguage.js +1 -1
  21. package/dist/locus-info/controlsUtils.js +28 -4
  22. package/dist/locus-info/controlsUtils.js.map +1 -1
  23. package/dist/locus-info/fullState.js +2 -1
  24. package/dist/locus-info/fullState.js.map +1 -1
  25. package/dist/locus-info/index.js +61 -3
  26. package/dist/locus-info/index.js.map +1 -1
  27. package/dist/locus-info/parser.js +5 -1
  28. package/dist/locus-info/parser.js.map +1 -1
  29. package/dist/media/index.js +29 -1
  30. package/dist/media/index.js.map +1 -1
  31. package/dist/meeting/in-meeting-actions.js +29 -1
  32. package/dist/meeting/in-meeting-actions.js.map +1 -1
  33. package/dist/meeting/index.js +807 -540
  34. package/dist/meeting/index.js.map +1 -1
  35. package/dist/meeting/locusMediaRequest.js +2 -6
  36. package/dist/meeting/locusMediaRequest.js.map +1 -1
  37. package/dist/meeting/muteState.js +5 -2
  38. package/dist/meeting/muteState.js.map +1 -1
  39. package/dist/meeting/request.js +21 -29
  40. package/dist/meeting/request.js.map +1 -1
  41. package/dist/meeting/util.js +98 -61
  42. package/dist/meeting/util.js.map +1 -1
  43. package/dist/meeting-info/meeting-info-v2.js +80 -17
  44. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  45. package/dist/meetings/index.js +29 -2
  46. package/dist/meetings/index.js.map +1 -1
  47. package/dist/members/index.js +3 -2
  48. package/dist/members/index.js.map +1 -1
  49. package/dist/members/util.js +13 -7
  50. package/dist/members/util.js.map +1 -1
  51. package/dist/metrics/constants.js +4 -1
  52. package/dist/metrics/constants.js.map +1 -1
  53. package/dist/multistream/remoteMedia.js +34 -15
  54. package/dist/multistream/remoteMedia.js.map +1 -1
  55. package/dist/reachability/clusterReachability.js +12 -15
  56. package/dist/reachability/clusterReachability.js.map +1 -1
  57. package/dist/reachability/index.js +433 -136
  58. package/dist/reachability/index.js.map +1 -1
  59. package/dist/{rtcMetrics/constants.js → reachability/reachability.types.js} +1 -5
  60. package/dist/reachability/reachability.types.js.map +1 -0
  61. package/dist/reachability/request.js +23 -9
  62. package/dist/reachability/request.js.map +1 -1
  63. package/dist/recording-controller/enums.js +8 -4
  64. package/dist/recording-controller/enums.js.map +1 -1
  65. package/dist/recording-controller/index.js +18 -9
  66. package/dist/recording-controller/index.js.map +1 -1
  67. package/dist/recording-controller/util.js +13 -9
  68. package/dist/recording-controller/util.js.map +1 -1
  69. package/dist/roap/index.js +5 -7
  70. package/dist/roap/index.js.map +1 -1
  71. package/dist/roap/request.js +45 -79
  72. package/dist/roap/request.js.map +1 -1
  73. package/dist/roap/turnDiscovery.js +3 -6
  74. package/dist/roap/turnDiscovery.js.map +1 -1
  75. package/dist/{common/errors/parameter.d.ts → types/common/errors/join-webinar-error.d.ts} +4 -5
  76. package/dist/types/config.d.ts +3 -0
  77. package/dist/types/constants.d.ts +43 -0
  78. package/dist/types/controls-options-manager/enums.d.ts +2 -1
  79. package/dist/types/controls-options-manager/index.d.ts +2 -1
  80. package/dist/types/controls-options-manager/types.d.ts +2 -0
  81. package/dist/types/index.d.ts +2 -1
  82. package/dist/types/locus-info/index.d.ts +9 -0
  83. package/dist/types/meeting/in-meeting-actions.d.ts +28 -0
  84. package/dist/types/meeting/index.d.ts +34 -3
  85. package/dist/types/meeting/locusMediaRequest.d.ts +2 -3
  86. package/dist/types/meeting/muteState.d.ts +2 -1
  87. package/dist/types/meeting/request.d.ts +2 -2
  88. package/dist/types/meeting/util.d.ts +2 -2
  89. package/dist/types/meeting-info/meeting-info-v2.d.ts +23 -0
  90. package/dist/types/meetings/index.d.ts +13 -1
  91. package/dist/types/members/index.d.ts +2 -1
  92. package/dist/types/members/util.d.ts +5 -1
  93. package/dist/types/metrics/constants.d.ts +3 -0
  94. package/dist/types/multistream/remoteMedia.d.ts +1 -0
  95. package/dist/types/reachability/clusterReachability.d.ts +1 -10
  96. package/dist/types/reachability/index.d.ts +74 -35
  97. package/dist/types/reachability/reachability.types.d.ts +64 -0
  98. package/dist/types/reachability/request.d.ts +5 -1
  99. package/dist/types/recording-controller/enums.d.ts +5 -2
  100. package/dist/types/recording-controller/index.d.ts +1 -0
  101. package/dist/types/recording-controller/util.d.ts +2 -1
  102. package/dist/types/roap/request.d.ts +1 -13
  103. package/dist/webinar/index.js +382 -19
  104. package/dist/webinar/index.js.map +1 -1
  105. package/package.json +22 -22
  106. package/src/common/errors/join-webinar-error.ts +24 -0
  107. package/src/config.ts +3 -0
  108. package/src/constants.ts +52 -0
  109. package/src/controls-options-manager/enums.ts +1 -0
  110. package/src/controls-options-manager/index.ts +19 -2
  111. package/src/controls-options-manager/types.ts +2 -0
  112. package/src/controls-options-manager/util.ts +12 -0
  113. package/src/index.ts +2 -0
  114. package/src/locus-info/controlsUtils.ts +46 -2
  115. package/src/locus-info/fullState.ts +1 -0
  116. package/src/locus-info/index.ts +60 -0
  117. package/src/locus-info/parser.ts +8 -1
  118. package/src/media/index.ts +15 -0
  119. package/src/meeting/in-meeting-actions.ts +58 -0
  120. package/src/meeting/index.ts +268 -32
  121. package/src/meeting/locusMediaRequest.ts +4 -8
  122. package/src/meeting/muteState.ts +6 -2
  123. package/src/meeting/request.ts +4 -11
  124. package/src/meeting/util.ts +31 -6
  125. package/src/meeting-info/meeting-info-v2.ts +63 -0
  126. package/src/meetings/index.ts +74 -40
  127. package/src/members/index.ts +4 -2
  128. package/src/members/util.ts +4 -1
  129. package/src/metrics/constants.ts +3 -0
  130. package/src/multistream/remoteMedia.ts +33 -15
  131. package/src/reachability/clusterReachability.ts +5 -15
  132. package/src/reachability/index.ts +285 -77
  133. package/src/reachability/reachability.types.ts +85 -0
  134. package/src/reachability/request.ts +55 -30
  135. package/src/recording-controller/enums.ts +5 -2
  136. package/src/recording-controller/index.ts +17 -4
  137. package/src/recording-controller/util.ts +20 -5
  138. package/src/roap/index.ts +4 -5
  139. package/src/roap/request.ts +32 -44
  140. package/src/roap/turnDiscovery.ts +2 -4
  141. package/src/webinar/index.ts +223 -17
  142. package/test/unit/spec/controls-options-manager/index.js +56 -32
  143. package/test/unit/spec/controls-options-manager/util.js +44 -0
  144. package/test/unit/spec/locus-info/controlsUtils.js +80 -4
  145. package/test/unit/spec/locus-info/index.js +88 -2
  146. package/test/unit/spec/meeting/in-meeting-actions.ts +31 -1
  147. package/test/unit/spec/meeting/index.js +407 -82
  148. package/test/unit/spec/meeting/locusMediaRequest.ts +18 -11
  149. package/test/unit/spec/meeting/muteState.js +8 -4
  150. package/test/unit/spec/meeting/request.js +3 -26
  151. package/test/unit/spec/meeting/utils.js +71 -14
  152. package/test/unit/spec/meeting-info/meetinginfov2.js +42 -0
  153. package/test/unit/spec/meetings/index.js +41 -6
  154. package/test/unit/spec/members/index.js +25 -2
  155. package/test/unit/spec/members/request.js +37 -3
  156. package/test/unit/spec/members/utils.js +110 -1
  157. package/test/unit/spec/multistream/remoteMedia.ts +27 -9
  158. package/test/unit/spec/reachability/clusterReachability.ts +7 -0
  159. package/test/unit/spec/reachability/index.ts +265 -1
  160. package/test/unit/spec/reachability/request.js +56 -15
  161. package/test/unit/spec/recording-controller/index.js +61 -5
  162. package/test/unit/spec/recording-controller/util.js +39 -3
  163. package/test/unit/spec/roap/index.ts +1 -1
  164. package/test/unit/spec/roap/request.ts +51 -109
  165. package/test/unit/spec/roap/turnDiscovery.ts +202 -147
  166. package/test/unit/spec/webinar/index.ts +443 -14
  167. package/dist/annotation/annotation.types.d.ts +0 -42
  168. package/dist/annotation/constants.d.ts +0 -31
  169. package/dist/annotation/index.d.ts +0 -117
  170. package/dist/breakouts/breakout.d.ts +0 -8
  171. package/dist/breakouts/collection.d.ts +0 -5
  172. package/dist/breakouts/edit-lock-error.d.ts +0 -15
  173. package/dist/breakouts/events.d.ts +0 -8
  174. package/dist/breakouts/index.d.ts +0 -5
  175. package/dist/breakouts/request.d.ts +0 -22
  176. package/dist/breakouts/utils.d.ts +0 -15
  177. package/dist/common/browser-detection.d.ts +0 -9
  178. package/dist/common/collection.d.ts +0 -48
  179. package/dist/common/config.d.ts +0 -2
  180. package/dist/common/errors/captcha-error.d.ts +0 -15
  181. package/dist/common/errors/intent-to-join.d.ts +0 -16
  182. package/dist/common/errors/join-meeting.d.ts +0 -17
  183. package/dist/common/errors/media.d.ts +0 -15
  184. package/dist/common/errors/no-meeting-info.d.ts +0 -14
  185. package/dist/common/errors/password-error.d.ts +0 -15
  186. package/dist/common/errors/permission.d.ts +0 -14
  187. package/dist/common/errors/reclaim-host-role-error.js +0 -149
  188. package/dist/common/errors/reclaim-host-role-error.js.map +0 -1
  189. package/dist/common/errors/reclaim-host-role-errors.d.ts +0 -60
  190. package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
  191. package/dist/common/errors/reconnection-in-progress.js +0 -33
  192. package/dist/common/errors/reconnection-in-progress.js.map +0 -1
  193. package/dist/common/errors/reconnection.d.ts +0 -15
  194. package/dist/common/errors/stats.d.ts +0 -15
  195. package/dist/common/errors/webex-errors.d.ts +0 -93
  196. package/dist/common/errors/webex-meetings-error.d.ts +0 -20
  197. package/dist/common/events/events-scope.d.ts +0 -17
  198. package/dist/common/events/events.d.ts +0 -12
  199. package/dist/common/events/trigger-proxy.d.ts +0 -2
  200. package/dist/common/events/util.d.ts +0 -2
  201. package/dist/common/logs/logger-config.d.ts +0 -2
  202. package/dist/common/logs/logger-proxy.d.ts +0 -2
  203. package/dist/common/logs/request.d.ts +0 -36
  204. package/dist/common/queue.d.ts +0 -34
  205. package/dist/config.d.ts +0 -72
  206. package/dist/constants.d.ts +0 -1088
  207. package/dist/controls-options-manager/constants.d.ts +0 -4
  208. package/dist/controls-options-manager/enums.d.ts +0 -15
  209. package/dist/controls-options-manager/index.d.ts +0 -136
  210. package/dist/controls-options-manager/types.d.ts +0 -43
  211. package/dist/controls-options-manager/util.d.ts +0 -1
  212. package/dist/index.d.ts +0 -7
  213. package/dist/interceptors/index.d.ts +0 -2
  214. package/dist/interceptors/locusRetry.d.ts +0 -27
  215. package/dist/interpretation/collection.d.ts +0 -5
  216. package/dist/interpretation/index.d.ts +0 -5
  217. package/dist/interpretation/siLanguage.d.ts +0 -5
  218. package/dist/locus-info/controlsUtils.d.ts +0 -2
  219. package/dist/locus-info/embeddedAppsUtils.d.ts +0 -2
  220. package/dist/locus-info/fullState.d.ts +0 -2
  221. package/dist/locus-info/hostUtils.d.ts +0 -2
  222. package/dist/locus-info/index.d.ts +0 -322
  223. package/dist/locus-info/infoUtils.d.ts +0 -2
  224. package/dist/locus-info/mediaSharesUtils.d.ts +0 -2
  225. package/dist/locus-info/parser.d.ts +0 -272
  226. package/dist/locus-info/selfUtils.d.ts +0 -2
  227. package/dist/media/index.d.ts +0 -34
  228. package/dist/media/properties.d.ts +0 -93
  229. package/dist/media/util.d.ts +0 -2
  230. package/dist/mediaQualityMetrics/config.d.ts +0 -241
  231. package/dist/mediaQualityMetrics/config.js +0 -502
  232. package/dist/mediaQualityMetrics/config.js.map +0 -1
  233. package/dist/meeting/effectsState.js +0 -260
  234. package/dist/meeting/effectsState.js.map +0 -1
  235. package/dist/meeting/in-meeting-actions.d.ts +0 -167
  236. package/dist/meeting/index.d.ts +0 -1825
  237. package/dist/meeting/locusMediaRequest.d.ts +0 -74
  238. package/dist/meeting/muteState.d.ts +0 -178
  239. package/dist/meeting/request.d.ts +0 -295
  240. package/dist/meeting/request.type.d.ts +0 -11
  241. package/dist/meeting/state.d.ts +0 -9
  242. package/dist/meeting/util.d.ts +0 -119
  243. package/dist/meeting/voicea-meeting.d.ts +0 -16
  244. package/dist/meeting-info/collection.d.ts +0 -20
  245. package/dist/meeting-info/index.d.ts +0 -69
  246. package/dist/meeting-info/meeting-info-v2.d.ts +0 -123
  247. package/dist/meeting-info/request.d.ts +0 -22
  248. package/dist/meeting-info/util.d.ts +0 -2
  249. package/dist/meeting-info/utilv2.d.ts +0 -2
  250. package/dist/meetings/collection.d.ts +0 -40
  251. package/dist/meetings/index.d.ts +0 -390
  252. package/dist/meetings/meetings.types.d.ts +0 -4
  253. package/dist/meetings/request.d.ts +0 -27
  254. package/dist/meetings/util.d.ts +0 -18
  255. package/dist/member/index.d.ts +0 -160
  256. package/dist/member/member.types.js +0 -17
  257. package/dist/member/member.types.js.map +0 -1
  258. package/dist/member/types.d.ts +0 -32
  259. package/dist/member/util.d.ts +0 -2
  260. package/dist/members/collection.d.ts +0 -29
  261. package/dist/members/index.d.ts +0 -353
  262. package/dist/members/request.d.ts +0 -114
  263. package/dist/members/types.d.ts +0 -25
  264. package/dist/members/util.d.ts +0 -215
  265. package/dist/metrics/config.js +0 -276
  266. package/dist/metrics/config.js.map +0 -1
  267. package/dist/metrics/constants.d.ts +0 -70
  268. package/dist/metrics/index.d.ts +0 -45
  269. package/dist/multistream/mediaRequestManager.d.ts +0 -119
  270. package/dist/multistream/receiveSlot.d.ts +0 -68
  271. package/dist/multistream/receiveSlotManager.d.ts +0 -56
  272. package/dist/multistream/remoteMedia.d.ts +0 -72
  273. package/dist/multistream/remoteMediaGroup.d.ts +0 -49
  274. package/dist/multistream/remoteMediaManager.d.ts +0 -300
  275. package/dist/multistream/sendSlotManager.d.ts +0 -69
  276. package/dist/networkQualityMonitor/index.d.ts +0 -70
  277. package/dist/networkQualityMonitor/index.js +0 -221
  278. package/dist/networkQualityMonitor/index.js.map +0 -1
  279. package/dist/peer-connection-manager/index.js +0 -671
  280. package/dist/peer-connection-manager/index.js.map +0 -1
  281. package/dist/peer-connection-manager/util.js +0 -109
  282. package/dist/peer-connection-manager/util.js.map +0 -1
  283. package/dist/personal-meeting-room/index.d.ts +0 -47
  284. package/dist/personal-meeting-room/request.d.ts +0 -14
  285. package/dist/personal-meeting-room/util.d.ts +0 -2
  286. package/dist/reachability/clusterReachability.d.ts +0 -109
  287. package/dist/reachability/index.d.ts +0 -105
  288. package/dist/reachability/request.d.ts +0 -39
  289. package/dist/reachability/util.d.ts +0 -8
  290. package/dist/reactions/constants.d.ts +0 -3
  291. package/dist/reactions/reactions.d.ts +0 -4
  292. package/dist/reactions/reactions.type.d.ts +0 -52
  293. package/dist/reconnection-manager/index.d.ts +0 -136
  294. package/dist/recording-controller/enums.d.ts +0 -7
  295. package/dist/recording-controller/index.d.ts +0 -207
  296. package/dist/recording-controller/util.d.ts +0 -14
  297. package/dist/roap/collection.js +0 -62
  298. package/dist/roap/collection.js.map +0 -1
  299. package/dist/roap/handler.js +0 -275
  300. package/dist/roap/handler.js.map +0 -1
  301. package/dist/roap/index.d.ts +0 -86
  302. package/dist/roap/request.d.ts +0 -39
  303. package/dist/roap/state.js +0 -126
  304. package/dist/roap/state.js.map +0 -1
  305. package/dist/roap/turnDiscovery.d.ts +0 -155
  306. package/dist/roap/util.js +0 -75
  307. package/dist/roap/util.js.map +0 -1
  308. package/dist/rtcMetrics/constants.d.ts +0 -4
  309. package/dist/rtcMetrics/constants.js.map +0 -1
  310. package/dist/rtcMetrics/index.d.ts +0 -61
  311. package/dist/rtcMetrics/index.js +0 -197
  312. package/dist/rtcMetrics/index.js.map +0 -1
  313. package/dist/statsAnalyzer/global.d.ts +0 -36
  314. package/dist/statsAnalyzer/global.js +0 -126
  315. package/dist/statsAnalyzer/global.js.map +0 -1
  316. package/dist/statsAnalyzer/index.d.ts +0 -217
  317. package/dist/statsAnalyzer/index.js +0 -1013
  318. package/dist/statsAnalyzer/index.js.map +0 -1
  319. package/dist/statsAnalyzer/mqaUtil.d.ts +0 -48
  320. package/dist/statsAnalyzer/mqaUtil.js +0 -179
  321. package/dist/statsAnalyzer/mqaUtil.js.map +0 -1
  322. package/dist/transcription/index.d.ts +0 -64
  323. package/dist/types/common/errors/reconnection-in-progress.d.ts +0 -9
  324. package/dist/types/mediaQualityMetrics/config.d.ts +0 -241
  325. package/dist/types/networkQualityMonitor/index.d.ts +0 -70
  326. package/dist/types/rtcMetrics/constants.d.ts +0 -4
  327. package/dist/types/rtcMetrics/index.d.ts +0 -71
  328. package/dist/types/statsAnalyzer/global.d.ts +0 -36
  329. package/dist/types/statsAnalyzer/index.d.ts +0 -217
  330. package/dist/types/statsAnalyzer/mqaUtil.d.ts +0 -48
  331. package/dist/webinar/collection.d.ts +0 -16
  332. package/dist/webinar/index.d.ts +0 -5
@@ -101,7 +101,7 @@ describe('plugin-meetings', () => {
101
101
  });
102
102
  });
103
103
  describe('#generateLowerAllHandsMemberOptions', () => {
104
- it('returns the correct options', () => {
104
+ it('returns the correct options without roles', () => {
105
105
  const requestingParticipantId = 'test';
106
106
  const locusUrl = 'urlTest1';
107
107
 
@@ -113,6 +113,20 @@ describe('plugin-meetings', () => {
113
113
  }
114
114
  );
115
115
  });
116
+ it('returns the correct options with roles', () => {
117
+ const requestingParticipantId = 'test';
118
+ const locusUrl = 'urlTest1';
119
+ const roles = ['panelist'];
120
+
121
+ assert.deepEqual(
122
+ MembersUtil.generateLowerAllHandsMemberOptions(requestingParticipantId, locusUrl, roles),
123
+ {
124
+ requestingParticipantId,
125
+ locusUrl,
126
+ roles,
127
+ }
128
+ );
129
+ });
116
130
  });
117
131
  describe('#generateEditDisplayNameMemberOptions', () => {
118
132
  it('returns the correct options', () => {
@@ -248,5 +262,100 @@ describe('plugin-meetings', () => {
248
262
  testParams(false);
249
263
  });
250
264
  });
265
+
266
+ describe('#getAddMemberBody', () => {
267
+ it('returns the correct body with email address and roles', () => {
268
+ const options = {
269
+ invitee: {
270
+ emailAddress: 'test@example.com',
271
+ roles: ['role1', 'role2'],
272
+ },
273
+ alertIfActive: true,
274
+ };
275
+
276
+ assert.deepEqual(MembersUtil.getAddMemberBody(options), {
277
+ invitees: [
278
+ {
279
+ address: 'test@example.com',
280
+ roles: ['role1', 'role2'],
281
+ },
282
+ ],
283
+ alertIfActive: true,
284
+ });
285
+ });
286
+
287
+ it('returns the correct body with phone number and no roles', () => {
288
+ const options = {
289
+ invitee: {
290
+ phoneNumber: '1234567890',
291
+ },
292
+ alertIfActive: false,
293
+ };
294
+
295
+ assert.deepEqual(MembersUtil.getAddMemberBody(options), {
296
+ invitees: [
297
+ {
298
+ address: '1234567890',
299
+ },
300
+ ],
301
+ alertIfActive: false,
302
+ });
303
+ });
304
+
305
+ it('returns the correct body with fallback to email', () => {
306
+ const options = {
307
+ invitee: {
308
+ email: 'fallback@example.com',
309
+ },
310
+ alertIfActive: true,
311
+ };
312
+
313
+ assert.deepEqual(MembersUtil.getAddMemberBody(options), {
314
+ invitees: [
315
+ {
316
+ address: 'fallback@example.com',
317
+ },
318
+ ],
319
+ alertIfActive: true,
320
+ });
321
+ });
322
+
323
+ it('handles missing `alertIfActive` gracefully', () => {
324
+ const options = {
325
+ invitee: {
326
+ emailAddress: 'test@example.com',
327
+ roles: ['role1'],
328
+ },
329
+ };
330
+
331
+ assert.deepEqual(MembersUtil.getAddMemberBody(options), {
332
+ invitees: [
333
+ {
334
+ address: 'test@example.com',
335
+ roles: ['role1'],
336
+ },
337
+ ],
338
+ alertIfActive: undefined,
339
+ });
340
+ });
341
+
342
+ it('ignores roles if not provided', () => {
343
+ const options = {
344
+ invitee: {
345
+ emailAddress: 'test@example.com',
346
+ },
347
+ alertIfActive: false,
348
+ };
349
+
350
+ assert.deepEqual(MembersUtil.getAddMemberBody(options), {
351
+ invitees: [
352
+ {
353
+ address: 'test@example.com',
354
+ },
355
+ ],
356
+ alertIfActive: false,
357
+ });
358
+ });
359
+ });
251
360
  });
252
361
  });
@@ -7,7 +7,7 @@ import {RemoteMedia, RemoteMediaEvents} from '@webex/plugin-meetings/src/multist
7
7
  import {ReceiveSlotEvents} from '@webex/plugin-meetings/src/multistream/receiveSlot';
8
8
  import sinon from 'sinon';
9
9
  import {assert} from '@webex/test-helper-chai';
10
- import { forEach } from 'lodash';
10
+ import {forEach} from 'lodash';
11
11
 
12
12
  describe('RemoteMedia', () => {
13
13
  let remoteMedia;
@@ -227,7 +227,6 @@ describe('RemoteMedia', () => {
227
227
  });
228
228
 
229
229
  describe('setSizeHint()', () => {
230
-
231
230
  it('works if the receive slot is undefined', () => {
232
231
  remoteMedia.receiveSlot = undefined;
233
232
  remoteMedia.setSizeHint(100, 100);
@@ -235,14 +234,33 @@ describe('RemoteMedia', () => {
235
234
 
236
235
  forEach(
237
236
  [
238
- {height: 134, fs: 60},
239
- {height: 135, fs: 240},
240
- {height: 269, fs: 240},
241
- {height: 270, fs: 920},
242
- {height: 539, fs: 920},
243
- {height: 540, fs: 3600},
237
+ {width: 0, height: 0},
238
+ {width: 135, height: 0},
239
+ {width: 0, height: 240},
240
+ ],
241
+ ({width, height}) => {
242
+ it(`skip updating the max fs when applied ${width}:${height}`, () => {
243
+ remoteMedia.setSizeHint(width, height);
244
+
245
+ assert.notCalled(fakeReceiveSlot.setMaxFs);
246
+ });
247
+ }
248
+ );
249
+
250
+ forEach(
251
+ [
252
+ {height: 90, fs: 60}, // 90p
253
+ {height: 98, fs: 60},
254
+ {height: 99, fs: 240}, // 180p
255
+ {height: 180, fs: 240},
256
+ {height: 197, fs: 240},
257
+ {height: 198, fs: 920}, // 360p
258
+ {height: 360, fs: 920},
259
+ {height: 395, fs: 920},
260
+ {height: 396, fs: 3600}, // 720p
244
261
  {height: 720, fs: 3600},
245
- {height: 721, fs: 8192},
262
+ {height: 721, fs: 8192}, // 1080p
263
+ {height: 1080, fs: 8192},
246
264
  ],
247
265
  ({height, fs}) => {
248
266
  it(`sets the max fs to ${fs} correctly when height is ${height}`, () => {
@@ -15,6 +15,7 @@ describe('ClusterReachability', () => {
15
15
  let previousRTCPeerConnection;
16
16
  let clusterReachability;
17
17
  let fakePeerConnection;
18
+ let gatherIceCandidatesSpy;
18
19
 
19
20
  const emittedEvents: Record<Events, (ResultEventData | ClientMediaIpsUpdatedEventData)[]> = {
20
21
  [Events.resultReady]: [],
@@ -44,6 +45,8 @@ describe('ClusterReachability', () => {
44
45
  xtls: ['stun:xtls1.webex.com', 'stun:xtls2.webex.com:443'],
45
46
  });
46
47
 
48
+ gatherIceCandidatesSpy = sinon.spy(clusterReachability, 'gatherIceCandidates');
49
+
47
50
  resetEmittedEvents();
48
51
 
49
52
  clusterReachability.on(Events.resultReady, (data: ResultEventData) => {
@@ -151,6 +154,10 @@ describe('ClusterReachability', () => {
151
154
  assert.calledOnceWithExactly(fakePeerConnection.createOffer, {offerToReceiveAudio: true});
152
155
  assert.calledOnce(fakePeerConnection.setLocalDescription);
153
156
 
157
+ // Make sure that gatherIceCandidates is called before setLocalDescription
158
+ // as setLocalDescription triggers the ICE gathering process
159
+ assert.isTrue(gatherIceCandidatesSpy.calledBefore(fakePeerConnection.setLocalDescription));
160
+
154
161
  clusterReachability.abort();
155
162
  await promise;
156
163
 
@@ -1234,7 +1234,7 @@ describe('gatherReachability', () => {
1234
1234
  assert.equal(receivedEvents['done'], 1);
1235
1235
 
1236
1236
  // and that ip network detection was started
1237
- assert.calledOnceWithExactly(webex.internal.device.ipNetworkDetector.detect);
1237
+ assert.calledOnceWithExactly(webex.internal.device.ipNetworkDetector.detect, true);
1238
1238
 
1239
1239
  // finally, check the metrics - they should contain values from ipNetworkDetector
1240
1240
  assert.calledWith(Metrics.sendBehavioralMetric, 'js_sdk_reachability_completed', {
@@ -1664,6 +1664,270 @@ describe('gatherReachability', () => {
1664
1664
 
1665
1665
  assert.neverCalledWith(clusterReachabilityCtorStub);
1666
1666
  });
1667
+
1668
+ describe('fallback mechanism and multiple calls to getClusters', () => {
1669
+ let receivedEvents;
1670
+
1671
+ const mockGetClustersEmptyResult = {
1672
+ discoveryOptions: {
1673
+ ['early-call-min-clusters']: 0,
1674
+ ['report-version']: 1,
1675
+ },
1676
+ clusters: {}, // empty cluster list
1677
+ joinCookie: {id: 'cookie'},
1678
+ };
1679
+
1680
+ beforeEach(() => {
1681
+ webex.config.meetings.experimental = {
1682
+ enableTcpReachability: true,
1683
+ enableTlsReachability: true,
1684
+ };
1685
+
1686
+ receivedEvents = {
1687
+ done: 0,
1688
+ };
1689
+ });
1690
+
1691
+ it('keeps retrying if minimum required clusters are not reached', async () => {
1692
+ const reachability = new Reachability(webex);
1693
+
1694
+ reachability.on('reachability:done', () => {
1695
+ receivedEvents.done += 1;
1696
+ });
1697
+
1698
+ const mockGetClustersResult1 = {
1699
+ discoveryOptions: {
1700
+ ['early-call-min-clusters']: 2,
1701
+ ['report-version']: 1,
1702
+ },
1703
+ clusters: {
1704
+ clusterA0: {
1705
+ udp: ['udp-urlA'],
1706
+ tcp: ['tcp-urlA'],
1707
+ xtls: ['xtls-urlA'],
1708
+ isVideoMesh: false,
1709
+ },
1710
+ clusterB0: {
1711
+ udp: ['udp-urlB'],
1712
+ tcp: ['tcp-urlB'],
1713
+ xtls: ['xtls-urlB'],
1714
+ isVideoMesh: false,
1715
+ },
1716
+ },
1717
+ joinCookie: {id: 'cookie1'},
1718
+ };
1719
+ const mockGetClustersResult2 = {
1720
+ discoveryOptions: {
1721
+ ['early-call-min-clusters']: 2,
1722
+ ['report-version']: 1,
1723
+ },
1724
+ clusters: {
1725
+ clusterA1: {
1726
+ udp: ['udp-urlA'],
1727
+ tcp: ['tcp-urlA'],
1728
+ xtls: ['xtls-urlA'],
1729
+ isVideoMesh: false,
1730
+ },
1731
+ clusterB1: {
1732
+ udp: ['udp-urlB'],
1733
+ tcp: ['tcp-urlB'],
1734
+ xtls: ['xtls-urlB'],
1735
+ isVideoMesh: false,
1736
+ },
1737
+ },
1738
+ joinCookie: {id: 'cookie2'},
1739
+ };
1740
+ const mockGetClustersResult3 = {
1741
+ discoveryOptions: {
1742
+ ['early-call-min-clusters']: 1,
1743
+ ['report-version']: 1,
1744
+ },
1745
+ clusters: {
1746
+ clusterA2: {
1747
+ udp: ['udp-urlA'],
1748
+ tcp: ['tcp-urlA'],
1749
+ xtls: ['xtls-urlA'],
1750
+ isVideoMesh: false,
1751
+ },
1752
+ clusterB2: {
1753
+ udp: ['udp-urlB'],
1754
+ tcp: ['tcp-urlB'],
1755
+ xtls: ['xtls-urlB'],
1756
+ isVideoMesh: false,
1757
+ },
1758
+ },
1759
+ joinCookie: {id: 'cookie3'},
1760
+ };
1761
+
1762
+ reachability.reachabilityRequest.getClusters = sinon.stub();
1763
+ reachability.reachabilityRequest.getClusters.onCall(0).returns(mockGetClustersResult1);
1764
+ reachability.reachabilityRequest.getClusters.onCall(1).returns(mockGetClustersResult2);
1765
+
1766
+ reachability.reachabilityRequest.getClusters.onCall(2).returns(mockGetClustersResult3);
1767
+
1768
+ const resultPromise = reachability.gatherReachability('test');
1769
+
1770
+ await testUtils.flushPromises();
1771
+
1772
+ // trigger some mock result events from ClusterReachability instances,
1773
+ // but only from 1 cluster, so not enough to reach the minimum required
1774
+ mockClusterReachabilityInstances['clusterA0'].emitFakeResult('udp', {
1775
+ result: 'reachable',
1776
+ clientMediaIPs: ['1.2.3.4'],
1777
+ latencyInMilliseconds: 11,
1778
+ });
1779
+
1780
+ clock.tick(3000);
1781
+ await resultPromise;
1782
+ await testUtils.flushPromises();
1783
+
1784
+ // because the minimum was not reached, another call to getClusters should be made
1785
+ assert.calledTwice(reachability.reachabilityRequest.getClusters);
1786
+
1787
+ // simulate no results this time
1788
+
1789
+ // check that while the 2nd attempt is in progress, the join cookie is already available from the 2nd call to getClusters
1790
+ const clientMediaPreferences = await reachability.getClientMediaPreferences(
1791
+ true,
1792
+ IP_VERSION.unknown
1793
+ );
1794
+
1795
+ assert.deepEqual(clientMediaPreferences.joinCookie, mockGetClustersResult2.joinCookie);
1796
+
1797
+ clock.tick(3000);
1798
+ await testUtils.flushPromises();
1799
+
1800
+ assert.calledThrice(reachability.reachabilityRequest.getClusters);
1801
+
1802
+ await testUtils.flushPromises();
1803
+
1804
+ // this time 1 result will be enough to reach the minimum
1805
+ mockClusterReachabilityInstances['clusterA2'].emitFakeResult('udp', {
1806
+ result: 'reachable',
1807
+ clientMediaIPs: ['1.2.3.4'],
1808
+ latencyInMilliseconds: 11,
1809
+ });
1810
+ clock.tick(3000);
1811
+
1812
+ // the reachability results should include only results from the last attempt
1813
+ await checkResults(
1814
+ {
1815
+ clusterA2: {
1816
+ udp: {result: 'reachable', clientMediaIPs: ['1.2.3.4'], latencyInMilliseconds: 11},
1817
+ tcp: {result: 'unreachable'},
1818
+ xtls: {result: 'unreachable'},
1819
+ isVideoMesh: false,
1820
+ },
1821
+ clusterB2: {
1822
+ udp: {result: 'unreachable'},
1823
+ tcp: {result: 'unreachable'},
1824
+ xtls: {result: 'unreachable'},
1825
+ isVideoMesh: false,
1826
+ },
1827
+ },
1828
+ mockGetClustersResult3.joinCookie
1829
+ );
1830
+
1831
+ // wait some more time to make sure that there are no timers that fire from one of the previous checks
1832
+ clock.tick(20000);
1833
+
1834
+ // as the first 2 attempts failed and didn't reach the overall timeout, there should be only 1 done event emitted
1835
+ assert.equal(receivedEvents.done, 1);
1836
+ });
1837
+
1838
+ it('handles getClusters() returning empty list on 1st call', async () => {
1839
+ const reachability = new Reachability(webex);
1840
+
1841
+ reachability.on('reachability:done', () => {
1842
+ receivedEvents.done += 1;
1843
+ });
1844
+
1845
+ reachability.reachabilityRequest.getClusters = sinon
1846
+ .stub()
1847
+ .resolves(mockGetClustersEmptyResult);
1848
+
1849
+ const resultPromise = reachability.gatherReachability('test');
1850
+
1851
+ await testUtils.flushPromises();
1852
+
1853
+ clock.tick(3000);
1854
+ await resultPromise;
1855
+ await testUtils.flushPromises();
1856
+
1857
+ assert.calledOnce(reachability.reachabilityRequest.getClusters);
1858
+ reachability.reachabilityRequest.getClusters.resetHistory();
1859
+
1860
+ assert.equal(receivedEvents.done, 1);
1861
+ await checkResults({}, mockGetClustersEmptyResult.joinCookie);
1862
+
1863
+ // because we didn't actually test anything (we got empty cluster list from getClusters()), we should
1864
+ // not say that webex backend is unreachable
1865
+ assert.equal(await reachability.isWebexMediaBackendUnreachable(), false);
1866
+
1867
+ // wait to check that there are no other things happening
1868
+ clock.tick(20000);
1869
+ await testUtils.flushPromises();
1870
+
1871
+ assert.notCalled(reachability.reachabilityRequest.getClusters);
1872
+ assert.equal(receivedEvents.done, 1);
1873
+ });
1874
+
1875
+ it('handles getClusters() returning empty list on 2nd call', async () => {
1876
+ const reachability = new Reachability(webex);
1877
+
1878
+ reachability.on('reachability:done', () => {
1879
+ receivedEvents.done += 1;
1880
+ });
1881
+
1882
+ const mockGetClustersResult1 = {
1883
+ discoveryOptions: {
1884
+ ['early-call-min-clusters']: 2,
1885
+ ['report-version']: 1,
1886
+ },
1887
+ clusters: {
1888
+ clusterA0: {
1889
+ udp: ['udp-urlA'],
1890
+ tcp: ['tcp-urlA'],
1891
+ xtls: ['xtls-urlA'],
1892
+ isVideoMesh: false,
1893
+ },
1894
+ clusterB0: {
1895
+ udp: ['udp-urlB'],
1896
+ tcp: ['tcp-urlB'],
1897
+ xtls: ['xtls-urlB'],
1898
+ isVideoMesh: false,
1899
+ },
1900
+ },
1901
+ joinCookie: {id: 'cookie1'},
1902
+ };
1903
+
1904
+ reachability.reachabilityRequest.getClusters = sinon.stub();
1905
+ reachability.reachabilityRequest.getClusters.onCall(0).returns(mockGetClustersResult1);
1906
+ reachability.reachabilityRequest.getClusters.onCall(1).returns(mockGetClustersEmptyResult);
1907
+
1908
+ const resultPromise = reachability.gatherReachability('test');
1909
+
1910
+ await testUtils.flushPromises();
1911
+
1912
+ clock.tick(3000);
1913
+ await resultPromise;
1914
+ await testUtils.flushPromises();
1915
+
1916
+ // because the minimum was not reached, another call to getClusters should be made
1917
+ assert.calledTwice(reachability.reachabilityRequest.getClusters);
1918
+
1919
+ // the reachability results should include only results from the last attempt
1920
+ await checkResults({}, mockGetClustersEmptyResult.joinCookie);
1921
+
1922
+ // as the first 2 attempts failed and didn't reach the overall timeout, there should be only 1 done event emitted
1923
+ assert.equal(receivedEvents.done, 1);
1924
+ // because we didn't actually test anything (we got empty cluster list from getClusters()), we should
1925
+ // not say that webex backend is unreachable
1926
+ assert.equal(await reachability.isWebexMediaBackendUnreachable(), false);
1927
+ });
1928
+ });
1929
+
1930
+
1667
1931
  });
1668
1932
 
1669
1933
  describe('getReachabilityResults', () => {
@@ -35,16 +35,11 @@ describe('plugin-meetings/reachability', () => {
35
35
  });
36
36
 
37
37
  describe('#getClusters', () => {
38
+ let previousReport;
38
39
 
39
40
  beforeEach(() => {
40
41
  sinon.spy(webex.internal.newMetrics.callDiagnosticLatencies, 'measureLatency');
41
- });
42
42
 
43
- afterEach(() => {
44
- sinon.restore();
45
- });
46
-
47
- it('sends a GET request with the correct params', async () => {
48
43
  webex.request = sinon.mock().returns(Promise.resolve({
49
44
  body: {
50
45
  clusterClasses: {
@@ -57,21 +52,67 @@ describe('plugin-meetings/reachability', () => {
57
52
  }
58
53
  }));
59
54
 
60
- const res = await reachabilityRequest.getClusters(IP_VERSION.only_ipv4);
61
- const requestParams = webex.request.getCall(0).args[0];
55
+ webex.config.meetings.reachabilityGetClusterTimeout = 3000;
62
56
 
63
- assert.equal(requestParams.method, 'GET');
64
- assert.equal(requestParams.resource, `clusters`);
65
- assert.equal(requestParams.api, 'calliopeDiscovery');
66
- assert.equal(requestParams.shouldRefreshAccessToken, false);
57
+ previousReport = {
58
+ id: 'fake previous report',
59
+ }
60
+ });
61
+
62
+ afterEach(() => {
63
+ sinon.restore();
64
+ });
65
+
66
+ it('sends a POST request with the correct params when trigger is "startup"', async () => {
67
+ const res = await reachabilityRequest.getClusters('startup', IP_VERSION.only_ipv4, previousReport);
68
+ const requestParams = webex.request.getCall(0).args[0];
67
69
 
68
- assert.deepEqual(requestParams.qs, {
69
- JCSupport: 1,
70
- ipver: 4,
70
+ assert.deepEqual(requestParams, {
71
+ method: 'POST',
72
+ resource: `clusters`,
73
+ api: 'calliopeDiscovery',
74
+ shouldRefreshAccessToken: false,
75
+ timeout: 3000,
76
+ body: {
77
+ ipver: IP_VERSION.only_ipv4,
78
+ 'supported-options': {
79
+ 'report-version': 1,
80
+ 'early-call-min-clusters': true,
81
+ },
82
+ 'previous-report': previousReport,
83
+ trigger: 'startup',
84
+ },
71
85
  });
86
+
72
87
  assert.deepEqual(res.clusters.clusterId, {udp: "testUDP", isVideoMesh: true})
73
88
  assert.deepEqual(res.joinCookie, {anycastEntryPoint: "aws-eu-west-1"})
74
89
  assert.calledOnceWithExactly(webex.internal.newMetrics.callDiagnosticLatencies.measureLatency, sinon.match.func, 'internal.get.cluster.time');
75
90
  });
91
+
92
+ it('sends a POST request with the correct params when trigger is other than "startup"', async () => {
93
+ const res = await reachabilityRequest.getClusters('early-call/no-min-reached', IP_VERSION.only_ipv4, previousReport);
94
+ const requestParams = webex.request.getCall(0).args[0];
95
+
96
+ assert.deepEqual(requestParams, {
97
+ method: 'POST',
98
+ resource: `clusters`,
99
+ api: 'calliopeDiscovery',
100
+ shouldRefreshAccessToken: false,
101
+ timeout: 3000,
102
+ body: {
103
+ ipver: IP_VERSION.only_ipv4,
104
+ 'supported-options': {
105
+ 'report-version': 1,
106
+ 'early-call-min-clusters': true,
107
+ },
108
+ 'previous-report': previousReport,
109
+ trigger: 'early-call/no-min-reached',
110
+ },
111
+ });
112
+
113
+ assert.deepEqual(res.clusters.clusterId, {udp: "testUDP", isVideoMesh: true})
114
+ assert.deepEqual(res.joinCookie, {anycastEntryPoint: "aws-eu-west-1"})
115
+ assert.notCalled(webex.internal.newMetrics.callDiagnosticLatencies.measureLatency);
116
+ });
76
117
  });
77
118
  });
@@ -221,7 +221,21 @@ describe('plugin-meetings', () => {
221
221
 
222
222
  assert.calledWith(request.request, {
223
223
  uri: `test/loci/id/recording`,
224
- body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'start'}},
224
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'start'}, recordingType: 'cloud'},
225
+ method: HTTP_VERBS.PUT,
226
+ });
227
+
228
+ assert.deepEqual(result, request.request.firstCall.returnValue);
229
+ });
230
+
231
+ it('can start premise recording when the correct display hint is present', () => {
232
+ controller.setDisplayHints(['PREMISE_RECORDING_CONTROL_START']);
233
+
234
+ const result = controller.startRecording();
235
+
236
+ assert.calledWith(request.request, {
237
+ uri: `test/loci/id/recording`,
238
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'start'}, recordingType: 'premise'},
225
239
  method: HTTP_VERBS.PUT,
226
240
  });
227
241
 
@@ -238,14 +252,28 @@ describe('plugin-meetings', () => {
238
252
  assert.isRejected(result);
239
253
  });
240
254
 
241
- it('can start recording when the correct display hint is present', () => {
255
+ it('can stop recording when the correct display hint is present', () => {
242
256
  controller.setDisplayHints(['RECORDING_CONTROL_STOP']);
243
257
 
244
258
  const result = controller.stopRecording();
245
259
 
246
260
  assert.calledWith(request.request, {
247
261
  uri: `test/loci/id/recording`,
248
- body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'stop'}},
262
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'stop'}, recordingType: 'cloud'},
263
+ method: HTTP_VERBS.PUT,
264
+ });
265
+
266
+ assert.deepEqual(result, request.request.firstCall.returnValue);
267
+ });
268
+
269
+ it('can stop premise recording when the correct display hint is present', () => {
270
+ controller.setDisplayHints(['PREMISE_RECORDING_CONTROL_STOP']);
271
+
272
+ const result = controller.stopRecording();
273
+
274
+ assert.calledWith(request.request, {
275
+ uri: `test/loci/id/recording`,
276
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'stop'}, recordingType: 'premise'},
249
277
  method: HTTP_VERBS.PUT,
250
278
  });
251
279
 
@@ -269,7 +297,21 @@ describe('plugin-meetings', () => {
269
297
 
270
298
  assert.calledWith(request.request, {
271
299
  uri: `test/loci/id/recording`,
272
- body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'pause'}},
300
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'pause'}, recordingType: 'cloud'},
301
+ method: HTTP_VERBS.PUT,
302
+ });
303
+
304
+ assert.deepEqual(result, request.request.firstCall.returnValue);
305
+ });
306
+
307
+ it('can pause premise recording when the correct display hint is present', () => {
308
+ controller.setDisplayHints(['PREMISE_RECORDING_CONTROL_PAUSE']);
309
+
310
+ const result = controller.pauseRecording();
311
+
312
+ assert.calledWith(request.request, {
313
+ uri: `test/loci/id/recording`,
314
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'pause'}, recordingType: 'premise'},
273
315
  method: HTTP_VERBS.PUT,
274
316
  });
275
317
 
@@ -293,7 +335,21 @@ describe('plugin-meetings', () => {
293
335
 
294
336
  assert.calledWith(request.request, {
295
337
  uri: `test/loci/id/recording`,
296
- body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'resume'}},
338
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'resume'}, recordingType: 'cloud'},
339
+ method: HTTP_VERBS.PUT,
340
+ });
341
+
342
+ assert.deepEqual(result, request.request.firstCall.returnValue);
343
+ });
344
+
345
+ it('can resume premise recording when the correct display hint is present', () => {
346
+ controller.setDisplayHints(['PREMISE_RECORDING_CONTROL_RESUME']);
347
+
348
+ const result = controller.resumeRecording();
349
+
350
+ assert.calledWith(request.request, {
351
+ uri: `test/loci/id/recording`,
352
+ body: {meetingInfo: {locusSessionId: 'testId'}, recording: {action: 'resume'}, recordingType: 'premise'},
297
353
  method: HTTP_VERBS.PUT,
298
354
  });
299
355