@webex/plugin-meetings 3.0.0-beta.31 → 3.0.0-beta.310

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 (378) hide show
  1. package/README.md +46 -8
  2. package/dist/annotation/annotation.types.js +7 -0
  3. package/dist/annotation/annotation.types.js.map +1 -0
  4. package/dist/annotation/constants.js +49 -0
  5. package/dist/annotation/constants.js.map +1 -0
  6. package/dist/annotation/index.js +342 -0
  7. package/dist/annotation/index.js.map +1 -0
  8. package/dist/breakouts/breakout.js +94 -15
  9. package/dist/breakouts/breakout.js.map +1 -1
  10. package/dist/breakouts/edit-lock-error.js +52 -0
  11. package/dist/breakouts/edit-lock-error.js.map +1 -0
  12. package/dist/breakouts/events.js +45 -0
  13. package/dist/breakouts/events.js.map +1 -0
  14. package/dist/breakouts/index.js +709 -35
  15. package/dist/breakouts/index.js.map +1 -1
  16. package/dist/breakouts/utils.js +45 -1
  17. package/dist/breakouts/utils.js.map +1 -1
  18. package/dist/common/errors/no-meeting-info.js +51 -0
  19. package/dist/common/errors/no-meeting-info.js.map +1 -0
  20. package/dist/common/errors/reclaim-host-role-errors.js +158 -0
  21. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  22. package/dist/common/errors/webex-errors.js +48 -7
  23. package/dist/common/errors/webex-errors.js.map +1 -1
  24. package/dist/common/logs/logger-proxy.js +1 -1
  25. package/dist/common/logs/logger-proxy.js.map +1 -1
  26. package/dist/common/logs/request.js +5 -1
  27. package/dist/common/logs/request.js.map +1 -1
  28. package/dist/common/queue.js +24 -9
  29. package/dist/common/queue.js.map +1 -1
  30. package/dist/config.js +5 -11
  31. package/dist/config.js.map +1 -1
  32. package/dist/constants.js +233 -29
  33. package/dist/constants.js.map +1 -1
  34. package/dist/controls-options-manager/enums.js +14 -2
  35. package/dist/controls-options-manager/enums.js.map +1 -1
  36. package/dist/controls-options-manager/index.js +109 -15
  37. package/dist/controls-options-manager/index.js.map +1 -1
  38. package/dist/controls-options-manager/types.js +7 -0
  39. package/dist/controls-options-manager/types.js.map +1 -0
  40. package/dist/controls-options-manager/util.js +309 -18
  41. package/dist/controls-options-manager/util.js.map +1 -1
  42. package/dist/index.js +112 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/interpretation/collection.js +23 -0
  45. package/dist/interpretation/collection.js.map +1 -0
  46. package/dist/interpretation/index.js +366 -0
  47. package/dist/interpretation/index.js.map +1 -0
  48. package/dist/interpretation/siLanguage.js +25 -0
  49. package/dist/interpretation/siLanguage.js.map +1 -0
  50. package/dist/locus-info/controlsUtils.js +91 -2
  51. package/dist/locus-info/controlsUtils.js.map +1 -1
  52. package/dist/locus-info/index.js +383 -62
  53. package/dist/locus-info/index.js.map +1 -1
  54. package/dist/locus-info/infoUtils.js +7 -1
  55. package/dist/locus-info/infoUtils.js.map +1 -1
  56. package/dist/locus-info/mediaSharesUtils.js +57 -1
  57. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  58. package/dist/locus-info/parser.js +249 -72
  59. package/dist/locus-info/parser.js.map +1 -1
  60. package/dist/locus-info/selfUtils.js +89 -14
  61. package/dist/locus-info/selfUtils.js.map +1 -1
  62. package/dist/media/index.js +61 -116
  63. package/dist/media/index.js.map +1 -1
  64. package/dist/media/properties.js +73 -124
  65. package/dist/media/properties.js.map +1 -1
  66. package/dist/meeting/in-meeting-actions.js +82 -2
  67. package/dist/meeting/in-meeting-actions.js.map +1 -1
  68. package/dist/meeting/index.js +3777 -2929
  69. package/dist/meeting/index.js.map +1 -1
  70. package/dist/meeting/locusMediaRequest.js +292 -0
  71. package/dist/meeting/locusMediaRequest.js.map +1 -0
  72. package/dist/meeting/muteState.js +230 -124
  73. package/dist/meeting/muteState.js.map +1 -1
  74. package/dist/meeting/request.js +260 -196
  75. package/dist/meeting/request.js.map +1 -1
  76. package/dist/meeting/util.js +601 -417
  77. package/dist/meeting/util.js.map +1 -1
  78. package/dist/meeting-info/index.js +73 -7
  79. package/dist/meeting-info/index.js.map +1 -1
  80. package/dist/meeting-info/meeting-info-v2.js +192 -51
  81. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  82. package/dist/meeting-info/util.js +1 -1
  83. package/dist/meeting-info/util.js.map +1 -1
  84. package/dist/meeting-info/utilv2.js +36 -36
  85. package/dist/meeting-info/utilv2.js.map +1 -1
  86. package/dist/meetings/collection.js +39 -0
  87. package/dist/meetings/collection.js.map +1 -1
  88. package/dist/meetings/index.js +415 -115
  89. package/dist/meetings/index.js.map +1 -1
  90. package/dist/meetings/meetings.types.js +7 -0
  91. package/dist/meetings/meetings.types.js.map +1 -0
  92. package/dist/meetings/request.js +2 -0
  93. package/dist/meetings/request.js.map +1 -1
  94. package/dist/meetings/util.js +72 -6
  95. package/dist/meetings/util.js.map +1 -1
  96. package/dist/member/index.js +58 -0
  97. package/dist/member/index.js.map +1 -1
  98. package/dist/member/types.js +25 -0
  99. package/dist/member/types.js.map +1 -0
  100. package/dist/member/util.js +132 -25
  101. package/dist/member/util.js.map +1 -1
  102. package/dist/members/collection.js +10 -0
  103. package/dist/members/collection.js.map +1 -1
  104. package/dist/members/index.js +102 -6
  105. package/dist/members/index.js.map +1 -1
  106. package/dist/members/request.js +106 -38
  107. package/dist/members/request.js.map +1 -1
  108. package/dist/members/types.js +15 -0
  109. package/dist/members/types.js.map +1 -0
  110. package/dist/members/util.js +326 -232
  111. package/dist/members/util.js.map +1 -1
  112. package/dist/metrics/constants.js +13 -5
  113. package/dist/metrics/constants.js.map +1 -1
  114. package/dist/metrics/index.js +1 -468
  115. package/dist/metrics/index.js.map +1 -1
  116. package/dist/multistream/mediaRequestManager.js +238 -49
  117. package/dist/multistream/mediaRequestManager.js.map +1 -1
  118. package/dist/multistream/receiveSlot.js +29 -16
  119. package/dist/multistream/receiveSlot.js.map +1 -1
  120. package/dist/multistream/receiveSlotManager.js +39 -36
  121. package/dist/multistream/receiveSlotManager.js.map +1 -1
  122. package/dist/multistream/remoteMedia.js +44 -18
  123. package/dist/multistream/remoteMedia.js.map +1 -1
  124. package/dist/multistream/remoteMediaGroup.js +60 -3
  125. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  126. package/dist/multistream/remoteMediaManager.js +209 -59
  127. package/dist/multistream/remoteMediaManager.js.map +1 -1
  128. package/dist/multistream/sendSlotManager.js +233 -0
  129. package/dist/multistream/sendSlotManager.js.map +1 -0
  130. package/dist/reachability/index.js +225 -59
  131. package/dist/reachability/index.js.map +1 -1
  132. package/dist/reachability/request.js +17 -8
  133. package/dist/reachability/request.js.map +1 -1
  134. package/dist/reconnection-manager/index.js +201 -156
  135. package/dist/reconnection-manager/index.js.map +1 -1
  136. package/dist/recording-controller/index.js +21 -2
  137. package/dist/recording-controller/index.js.map +1 -1
  138. package/dist/recording-controller/util.js +9 -8
  139. package/dist/recording-controller/util.js.map +1 -1
  140. package/dist/roap/index.js +62 -32
  141. package/dist/roap/index.js.map +1 -1
  142. package/dist/roap/request.js +112 -97
  143. package/dist/roap/request.js.map +1 -1
  144. package/dist/roap/turnDiscovery.js +95 -36
  145. package/dist/roap/turnDiscovery.js.map +1 -1
  146. package/dist/rtcMetrics/constants.js +12 -0
  147. package/dist/rtcMetrics/constants.js.map +1 -0
  148. package/dist/rtcMetrics/index.js +117 -0
  149. package/dist/rtcMetrics/index.js.map +1 -0
  150. package/dist/statsAnalyzer/index.js +86 -78
  151. package/dist/statsAnalyzer/index.js.map +1 -1
  152. package/dist/statsAnalyzer/mqaUtil.js +11 -10
  153. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  154. package/dist/types/annotation/annotation.types.d.ts +42 -0
  155. package/dist/types/annotation/constants.d.ts +31 -0
  156. package/dist/types/annotation/index.d.ts +117 -0
  157. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  158. package/dist/types/breakouts/events.d.ts +8 -0
  159. package/dist/types/breakouts/utils.d.ts +14 -0
  160. package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
  161. package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
  162. package/dist/types/common/errors/webex-errors.d.ts +25 -1
  163. package/dist/types/common/logs/request.d.ts +2 -0
  164. package/dist/types/common/queue.d.ts +9 -7
  165. package/dist/types/config.d.ts +1 -7
  166. package/dist/types/constants.d.ts +194 -24
  167. package/dist/types/controls-options-manager/enums.d.ts +11 -1
  168. package/dist/types/controls-options-manager/index.d.ts +17 -1
  169. package/dist/types/controls-options-manager/types.d.ts +43 -0
  170. package/dist/types/controls-options-manager/util.d.ts +1 -7
  171. package/dist/types/index.d.ts +6 -4
  172. package/dist/types/interpretation/collection.d.ts +5 -0
  173. package/dist/types/interpretation/index.d.ts +5 -0
  174. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  175. package/dist/types/locus-info/index.d.ts +57 -4
  176. package/dist/types/locus-info/parser.d.ts +67 -6
  177. package/dist/types/media/index.d.ts +2 -0
  178. package/dist/types/media/properties.d.ts +34 -48
  179. package/dist/types/meeting/in-meeting-actions.d.ts +82 -2
  180. package/dist/types/meeting/index.d.ts +463 -510
  181. package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
  182. package/dist/types/meeting/muteState.d.ts +99 -23
  183. package/dist/types/meeting/request.d.ts +72 -43
  184. package/dist/types/meeting/util.d.ts +101 -1
  185. package/dist/types/meeting-info/index.d.ts +13 -1
  186. package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
  187. package/dist/types/meetings/collection.d.ts +17 -0
  188. package/dist/types/meetings/index.d.ts +98 -20
  189. package/dist/types/meetings/meetings.types.d.ts +4 -0
  190. package/dist/types/member/index.d.ts +14 -0
  191. package/dist/types/member/types.d.ts +32 -0
  192. package/dist/types/members/collection.d.ts +5 -0
  193. package/dist/types/members/index.d.ts +35 -2
  194. package/dist/types/members/request.d.ts +73 -9
  195. package/dist/types/members/types.d.ts +25 -0
  196. package/dist/types/members/util.d.ts +214 -1
  197. package/dist/types/metrics/constants.d.ts +12 -4
  198. package/dist/types/metrics/index.d.ts +4 -119
  199. package/dist/types/multistream/mediaRequestManager.d.ts +73 -5
  200. package/dist/types/multistream/receiveSlot.d.ts +13 -11
  201. package/dist/types/multistream/receiveSlotManager.d.ts +14 -4
  202. package/dist/types/multistream/remoteMedia.d.ts +8 -29
  203. package/dist/types/multistream/remoteMediaGroup.d.ts +0 -9
  204. package/dist/types/multistream/remoteMediaManager.d.ts +46 -2
  205. package/dist/types/multistream/sendSlotManager.d.ts +61 -0
  206. package/dist/types/reachability/index.d.ts +61 -7
  207. package/dist/types/reachability/request.d.ts +7 -3
  208. package/dist/types/reconnection-manager/index.d.ts +9 -0
  209. package/dist/types/recording-controller/index.d.ts +15 -1
  210. package/dist/types/recording-controller/util.d.ts +5 -4
  211. package/dist/types/roap/index.d.ts +2 -1
  212. package/dist/types/roap/request.d.ts +15 -11
  213. package/dist/types/roap/turnDiscovery.d.ts +21 -3
  214. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  215. package/dist/types/rtcMetrics/index.d.ts +47 -0
  216. package/dist/types/statsAnalyzer/index.d.ts +7 -1
  217. package/dist/types/webinar/collection.d.ts +16 -0
  218. package/dist/types/webinar/index.d.ts +5 -0
  219. package/dist/webinar/collection.js +44 -0
  220. package/dist/webinar/collection.js.map +1 -0
  221. package/dist/webinar/index.js +69 -0
  222. package/dist/webinar/index.js.map +1 -0
  223. package/package.json +23 -20
  224. package/src/annotation/annotation.types.ts +50 -0
  225. package/src/annotation/constants.ts +36 -0
  226. package/src/annotation/index.ts +328 -0
  227. package/src/breakouts/README.md +42 -12
  228. package/src/breakouts/breakout.ts +67 -9
  229. package/src/breakouts/edit-lock-error.ts +25 -0
  230. package/src/breakouts/events.ts +56 -0
  231. package/src/breakouts/index.ts +592 -20
  232. package/src/breakouts/utils.ts +42 -0
  233. package/src/common/errors/no-meeting-info.ts +24 -0
  234. package/src/common/errors/reclaim-host-role-errors.ts +134 -0
  235. package/src/common/errors/webex-errors.ts +44 -2
  236. package/src/common/logs/logger-proxy.ts +1 -1
  237. package/src/common/logs/request.ts +5 -1
  238. package/src/common/queue.ts +22 -8
  239. package/src/config.ts +4 -10
  240. package/src/constants.ts +221 -19
  241. package/src/controls-options-manager/enums.ts +12 -0
  242. package/src/controls-options-manager/index.ts +116 -21
  243. package/src/controls-options-manager/types.ts +59 -0
  244. package/src/controls-options-manager/util.ts +294 -14
  245. package/src/index.ts +40 -0
  246. package/src/interpretation/README.md +60 -0
  247. package/src/interpretation/collection.ts +19 -0
  248. package/src/interpretation/index.ts +332 -0
  249. package/src/interpretation/siLanguage.ts +18 -0
  250. package/src/locus-info/controlsUtils.ts +108 -0
  251. package/src/locus-info/index.ts +413 -59
  252. package/src/locus-info/infoUtils.ts +10 -2
  253. package/src/locus-info/mediaSharesUtils.ts +64 -0
  254. package/src/locus-info/parser.ts +258 -47
  255. package/src/locus-info/selfUtils.ts +81 -5
  256. package/src/media/index.ts +102 -122
  257. package/src/media/properties.ts +87 -110
  258. package/src/meeting/in-meeting-actions.ts +163 -3
  259. package/src/meeting/index.ts +3132 -2541
  260. package/src/meeting/locusMediaRequest.ts +313 -0
  261. package/src/meeting/muteState.ts +229 -131
  262. package/src/meeting/request.ts +177 -121
  263. package/src/meeting/util.ts +588 -394
  264. package/src/meeting-info/index.ts +81 -8
  265. package/src/meeting-info/meeting-info-v2.ts +170 -14
  266. package/src/meeting-info/util.ts +1 -1
  267. package/src/meeting-info/utilv2.ts +23 -23
  268. package/src/meetings/collection.ts +33 -0
  269. package/src/meetings/index.ts +445 -123
  270. package/src/meetings/meetings.types.ts +12 -0
  271. package/src/meetings/request.ts +2 -0
  272. package/src/meetings/util.ts +80 -11
  273. package/src/member/index.ts +58 -0
  274. package/src/member/types.ts +38 -0
  275. package/src/member/util.ts +141 -25
  276. package/src/members/collection.ts +8 -0
  277. package/src/members/index.ts +134 -8
  278. package/src/members/request.ts +97 -17
  279. package/src/members/types.ts +29 -0
  280. package/src/members/util.ts +333 -240
  281. package/src/metrics/constants.ts +12 -4
  282. package/src/metrics/index.ts +1 -490
  283. package/src/multistream/mediaRequestManager.ts +289 -79
  284. package/src/multistream/receiveSlot.ts +31 -17
  285. package/src/multistream/receiveSlotManager.ts +34 -24
  286. package/src/multistream/remoteMedia.ts +27 -2
  287. package/src/multistream/remoteMediaGroup.ts +59 -0
  288. package/src/multistream/remoteMediaManager.ts +148 -30
  289. package/src/multistream/sendSlotManager.ts +170 -0
  290. package/src/reachability/index.ts +228 -37
  291. package/src/reachability/request.ts +17 -8
  292. package/src/reconnection-manager/index.ts +83 -56
  293. package/src/recording-controller/index.ts +20 -3
  294. package/src/recording-controller/util.ts +26 -9
  295. package/src/roap/index.ts +63 -32
  296. package/src/roap/request.ts +100 -104
  297. package/src/roap/turnDiscovery.ts +48 -26
  298. package/src/rtcMetrics/constants.ts +3 -0
  299. package/src/rtcMetrics/index.ts +100 -0
  300. package/src/statsAnalyzer/index.ts +105 -91
  301. package/src/statsAnalyzer/mqaUtil.ts +13 -14
  302. package/src/webinar/collection.ts +31 -0
  303. package/src/webinar/index.ts +62 -0
  304. package/test/integration/spec/converged-space-meetings.js +60 -3
  305. package/test/integration/spec/journey.js +320 -261
  306. package/test/integration/spec/space-meeting.js +76 -3
  307. package/test/unit/spec/annotation/index.ts +418 -0
  308. package/test/unit/spec/breakouts/breakout.ts +118 -28
  309. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  310. package/test/unit/spec/breakouts/events.ts +89 -0
  311. package/test/unit/spec/breakouts/index.ts +1395 -69
  312. package/test/unit/spec/breakouts/utils.js +52 -1
  313. package/test/unit/spec/common/queue.js +31 -2
  314. package/test/unit/spec/controls-options-manager/index.js +163 -0
  315. package/test/unit/spec/controls-options-manager/util.js +576 -60
  316. package/test/unit/spec/fixture/locus.js +1 -0
  317. package/test/unit/spec/interpretation/collection.ts +15 -0
  318. package/test/unit/spec/interpretation/index.ts +589 -0
  319. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  320. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  321. package/test/unit/spec/locus-info/index.js +1304 -33
  322. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  323. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  324. package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
  325. package/test/unit/spec/locus-info/parser.js +116 -35
  326. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  327. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  328. package/test/unit/spec/media/index.ts +104 -37
  329. package/test/unit/spec/media/properties.ts +2 -2
  330. package/test/unit/spec/meeting/in-meeting-actions.ts +81 -3
  331. package/test/unit/spec/meeting/index.js +5216 -1956
  332. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  333. package/test/unit/spec/meeting/muteState.js +408 -208
  334. package/test/unit/spec/meeting/request.js +483 -49
  335. package/test/unit/spec/meeting/utils.js +679 -64
  336. package/test/unit/spec/meeting-info/index.js +300 -0
  337. package/test/unit/spec/meeting-info/meetinginfov2.js +526 -5
  338. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  339. package/test/unit/spec/meetings/collection.js +26 -0
  340. package/test/unit/spec/meetings/index.js +1011 -205
  341. package/test/unit/spec/meetings/utils.js +202 -2
  342. package/test/unit/spec/member/index.js +61 -6
  343. package/test/unit/spec/member/util.js +510 -34
  344. package/test/unit/spec/members/index.js +432 -1
  345. package/test/unit/spec/members/request.js +206 -27
  346. package/test/unit/spec/members/utils.js +210 -0
  347. package/test/unit/spec/metrics/index.js +1 -50
  348. package/test/unit/spec/multistream/mediaRequestManager.ts +803 -162
  349. package/test/unit/spec/multistream/receiveSlot.ts +28 -20
  350. package/test/unit/spec/multistream/receiveSlotManager.ts +32 -30
  351. package/test/unit/spec/multistream/remoteMedia.ts +30 -0
  352. package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
  353. package/test/unit/spec/multistream/remoteMediaManager.ts +326 -0
  354. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  355. package/test/unit/spec/reachability/index.ts +549 -9
  356. package/test/unit/spec/reachability/request.js +68 -0
  357. package/test/unit/spec/reconnection-manager/index.js +85 -9
  358. package/test/unit/spec/recording-controller/index.js +294 -218
  359. package/test/unit/spec/recording-controller/util.js +223 -96
  360. package/test/unit/spec/roap/index.ts +178 -64
  361. package/test/unit/spec/roap/request.ts +203 -85
  362. package/test/unit/spec/roap/turnDiscovery.ts +82 -36
  363. package/test/unit/spec/rtcMetrics/index.ts +73 -0
  364. package/test/unit/spec/stats-analyzer/index.js +136 -2
  365. package/test/unit/spec/webinar/collection.ts +13 -0
  366. package/test/unit/spec/webinar/index.ts +60 -0
  367. package/test/utils/integrationTestUtils.js +46 -0
  368. package/test/utils/testUtils.js +0 -52
  369. package/dist/meeting/effectsState.js +0 -262
  370. package/dist/meeting/effectsState.js.map +0 -1
  371. package/dist/metrics/config.js +0 -299
  372. package/dist/metrics/config.js.map +0 -1
  373. package/dist/types/meeting/effectsState.d.ts +0 -42
  374. package/dist/types/metrics/config.d.ts +0 -178
  375. package/src/index.js +0 -16
  376. package/src/meeting/effectsState.ts +0 -211
  377. package/src/metrics/config.ts +0 -495
  378. package/test/unit/spec/meeting/effectsState.js +0 -285
@@ -1,23 +1,31 @@
1
1
  import sinon from 'sinon';
2
2
  import {assert} from '@webex/test-helper-chai';
3
+ import Meetings from '@webex/plugin-meetings';
3
4
  import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
4
5
  import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
5
6
  import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
6
- import Metrics from '@webex/plugin-meetings/src/metrics/index';
7
- import {DISPLAY_HINTS} from '@webex/plugin-meetings/dist/constants';
7
+ import {SELF_POLICY, IP_VERSION} from '@webex/plugin-meetings/src/constants';
8
+ import MockWebex from '@webex/test-helper-mock-webex';
9
+ import * as BrowserDetectionModule from '@webex/plugin-meetings/src/common/browser-detection';
8
10
 
9
11
  describe('plugin-meetings', () => {
12
+ let webex;
10
13
  describe('Meeting utils function', () => {
11
14
  const sandbox = sinon.createSandbox();
12
15
  const meeting = {};
13
16
 
14
17
  beforeEach(() => {
15
- Metrics.postEvent = sinon.stub();
18
+ webex = new MockWebex({
19
+ children: {
20
+ meetings: Meetings,
21
+ },
22
+ });
16
23
  const logger = {
17
24
  info: sandbox.stub(),
18
25
  log: sandbox.stub(),
19
26
  error: sandbox.stub(),
20
27
  warn: sandbox.stub(),
28
+ debug: sandbox.stub(),
21
29
  };
22
30
 
23
31
  LoggerConfig.set({
@@ -26,42 +34,41 @@ describe('plugin-meetings', () => {
26
34
  });
27
35
  LoggerProxy.set(logger);
28
36
 
29
- meeting.closeLocalStream = sinon.stub().returns(Promise.resolve());
30
- meeting.closeLocalShare = sinon.stub().returns(Promise.resolve());
31
- meeting.closeRemoteTracks = sinon.stub().returns(Promise.resolve());
37
+ meeting.cleanupLocalStreams = sinon.stub().returns(Promise.resolve());
38
+ meeting.closeRemoteStreams = sinon.stub().returns(Promise.resolve());
32
39
  meeting.closePeerConnections = sinon.stub().returns(Promise.resolve());
33
40
 
34
- meeting.unsetLocalVideoTrack = sinon.stub();
35
- meeting.unsetLocalShareTrack = sinon.stub();
36
- meeting.unsetRemoteTracks = sinon.stub();
41
+ meeting.unsetRemoteStreams = sinon.stub();
37
42
  meeting.unsetPeerConnections = sinon.stub();
38
43
  meeting.reconnectionManager = {cleanUp: sinon.stub()};
39
44
  meeting.stopKeepAlive = sinon.stub();
40
45
  meeting.updateLLMConnection = sinon.stub();
41
46
  meeting.breakouts = {cleanUp: sinon.stub()};
47
+ meeting.annotaion = {cleanUp: sinon.stub()};
48
+ meeting.getWebexObject = sinon.stub().returns(webex);
49
+ meeting.simultaneousInterpretation = {cleanUp: sinon.stub()};
50
+ meeting.trigger = sinon.stub();
42
51
  });
43
52
 
44
53
  afterEach(() => {
45
54
  sandbox.restore();
55
+ sinon.restore();
46
56
  });
47
57
 
48
58
  describe('#cleanup', () => {
49
59
  it('do clean up on meeting object', async () => {
50
60
  await MeetingUtil.cleanUp(meeting);
51
- assert.calledOnce(meeting.closeLocalStream);
52
- assert.calledOnce(meeting.closeLocalStream);
53
- assert.calledOnce(meeting.closeLocalShare);
54
- assert.calledOnce(meeting.closeRemoteTracks);
61
+ assert.calledOnce(meeting.cleanupLocalStreams);
62
+ assert.calledOnce(meeting.closeRemoteStreams);
55
63
  assert.calledOnce(meeting.closePeerConnections);
56
64
 
57
- assert.calledOnce(meeting.unsetLocalVideoTrack);
58
- assert.calledOnce(meeting.unsetLocalShareTrack);
59
- assert.calledOnce(meeting.unsetRemoteTracks);
65
+ assert.calledOnce(meeting.unsetRemoteStreams);
60
66
  assert.calledOnce(meeting.unsetPeerConnections);
61
67
  assert.calledOnce(meeting.reconnectionManager.cleanUp);
62
68
  assert.calledOnce(meeting.stopKeepAlive);
63
69
  assert.calledOnce(meeting.updateLLMConnection);
64
70
  assert.calledOnce(meeting.breakouts.cleanUp);
71
+ assert.calledOnce(meeting.simultaneousInterpretation.cleanUp);
65
72
  });
66
73
  });
67
74
 
@@ -70,7 +77,7 @@ describe('plugin-meetings', () => {
70
77
  deviceId: 'device-1',
71
78
  });
72
79
 
73
- const mockTrack = {
80
+ const mockStream = {
74
81
  getSettings: fakeDevice,
75
82
  };
76
83
 
@@ -89,27 +96,27 @@ describe('plugin-meetings', () => {
89
96
  });
90
97
 
91
98
  describe('#handleAudioLogging', () => {
92
- it('should not log if called without track', () => {
99
+ it('should not log if called without stream', () => {
93
100
  MeetingUtil.handleAudioLogging();
94
101
  assert(!LoggerProxy.logger.log.called, 'log not called');
95
102
  });
96
103
 
97
- it('should log audioTrack settings', () => {
104
+ it('should log audioStream settings', () => {
98
105
  assert(MeetingUtil.handleAudioLogging, 'method is defined');
99
- MeetingUtil.handleAudioLogging(mockTrack);
106
+ MeetingUtil.handleAudioLogging(mockStream);
100
107
  assert(LoggerProxy.logger.log.called, 'log called');
101
108
  });
102
109
  });
103
110
 
104
111
  describe('#handleVideoLogging', () => {
105
- it('should not log if called without track', () => {
112
+ it('should not log if called without stream', () => {
106
113
  MeetingUtil.handleVideoLogging(null);
107
114
  assert(!LoggerProxy.logger.log.called, 'log not called');
108
115
  });
109
116
 
110
- it('should log videoTrack settings', () => {
117
+ it('should log videoStream settings', () => {
111
118
  assert(MeetingUtil.handleVideoLogging, 'method is defined');
112
- MeetingUtil.handleVideoLogging(mockTrack);
119
+ MeetingUtil.handleVideoLogging(mockStream);
113
120
  assert(LoggerProxy.logger.log.called, 'log called');
114
121
  });
115
122
  });
@@ -130,51 +137,216 @@ describe('plugin-meetings', () => {
130
137
  });
131
138
  });
132
139
 
133
- describe('remoteUpdateAudioVideo', () => {
134
- it('#Should call meetingRequest.remoteAudioVideoToggle with correct parameters (multistream)', async () => {
140
+ describe('addSequence', () => {
141
+ it('should add the sequence object to a request body', () => {
142
+ const body = {};
143
+
144
+ MeetingUtil.addSequence(
145
+ {
146
+ locusInfo: {
147
+ sequence: 'sequence',
148
+ },
149
+ },
150
+ body
151
+ );
152
+
153
+ assert.deepEqual(body, {
154
+ sequence: 'sequence',
155
+ });
156
+ });
157
+
158
+ it('should work with an undefined meeting', () => {
159
+ const body = {};
160
+
161
+ MeetingUtil.addSequence(undefined, body);
162
+
163
+ assert.deepEqual(body, {});
164
+ });
165
+
166
+ it('should work with an undefined locusInfo', () => {
167
+ const body = {};
168
+
169
+ MeetingUtil.addSequence({}, body);
170
+
171
+ assert.deepEqual(body, {});
172
+ });
173
+
174
+ it('should work with an undefined sequence', () => {
175
+ const body = {};
176
+
177
+ MeetingUtil.addSequence({locusInfo: {}}, body);
178
+
179
+ assert.deepEqual(body, {});
180
+ });
181
+ });
182
+
183
+ describe('updateLocusWithDelta', () => {
184
+ it('should call handleLocusDelta with the new delta locus', () => {
135
185
  const meeting = {
136
- correlationId: 'correlation id',
137
- isMultistream: true,
138
- mediaId: '12345',
139
- meetingJoinUrl: 'meetingJoinUrl',
140
- locusUrl: 'locusUrl',
141
- deviceUrl: 'some device url',
142
- selfId: 'self id',
143
- meetingRequest: {
144
- remoteAudioVideoToggle: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
186
+ locusInfo: {
187
+ handleLocusDelta: sinon.stub(),
145
188
  },
146
189
  };
147
190
 
148
- await MeetingUtil.remoteUpdateAudioVideo(true, false, meeting);
191
+ const originalResponse = {
192
+ body: {
193
+ locus: 'locus',
194
+ },
195
+ };
149
196
 
150
- assert.calledOnce(meeting.meetingRequest.remoteAudioVideoToggle);
151
- const parameter = meeting.meetingRequest.remoteAudioVideoToggle.getCall(0).args[0];
197
+ const response = MeetingUtil.updateLocusWithDelta(meeting, originalResponse);
152
198
 
153
- assert.equal(parameter.locusUrl, 'locusUrl');
154
- assert.equal(parameter.selfId, 'self id');
155
- assert.equal(parameter.correlationId, 'correlation id');
156
- assert.equal(parameter.deviceUrl, 'some device url');
157
- assert.deepEqual(parameter.localMedias, [
158
- {localSdp: '{"audioMuted":true,"videoMuted":false}', mediaId: '12345'},
159
- ]);
160
- assert.equal(parameter.preferTranscoding, false);
199
+ assert.deepEqual(response, originalResponse);
200
+ assert.calledOnceWithExactly(meeting.locusInfo.handleLocusDelta, 'locus', meeting);
201
+ });
202
+
203
+ it('should handle locus being missing from the response', () => {
204
+ const meeting = {
205
+ locusInfo: {
206
+ handleLocusDelta: sinon.stub(),
207
+ },
208
+ };
209
+
210
+ const originalResponse = {
211
+ body: {},
212
+ };
213
+
214
+ const response = MeetingUtil.updateLocusWithDelta(meeting, originalResponse);
215
+
216
+ assert.deepEqual(response, originalResponse);
217
+ assert.notCalled(meeting.locusInfo.handleLocusDelta);
218
+ });
219
+
220
+ it('should work with an undefined meeting', () => {
221
+ const originalResponse = {
222
+ body: {
223
+ locus: 'locus',
224
+ },
225
+ };
226
+
227
+ const response = MeetingUtil.updateLocusWithDelta(undefined, originalResponse);
228
+ assert.deepEqual(response, originalResponse);
229
+ });
230
+ });
231
+
232
+ describe('generateLocusDeltaRequest', () => {
233
+ it('generates the correct wrapper function', async () => {
234
+ const updateLocusWithDeltaSpy = sinon.spy(MeetingUtil, 'updateLocusWithDelta');
235
+ const addSequenceSpy = sinon.spy(MeetingUtil, 'addSequence');
236
+
237
+ const meeting = {
238
+ request: sinon.stub().returns(Promise.resolve('result')),
239
+ };
240
+
241
+ const locusDeltaRequest = MeetingUtil.generateLocusDeltaRequest(meeting);
242
+
243
+ const options = {
244
+ some: 'option',
245
+ body: {},
246
+ };
247
+
248
+ let result = await locusDeltaRequest(options);
249
+
250
+ assert.equal(result, 'result');
251
+ assert.calledOnceWithExactly(updateLocusWithDeltaSpy, meeting, 'result');
252
+ assert.calledOnceWithExactly(addSequenceSpy, meeting, options.body);
253
+
254
+ updateLocusWithDeltaSpy.resetHistory();
255
+ addSequenceSpy.resetHistory();
256
+
257
+ // body missing from options
258
+ result = await locusDeltaRequest({});
259
+ assert.equal(result, 'result');
260
+ assert.calledOnceWithExactly(updateLocusWithDeltaSpy, meeting, 'result');
261
+ assert.calledOnceWithExactly(addSequenceSpy, meeting, options.body);
262
+
263
+ // meeting disappears so the WeakRef returns undefined
264
+ sinon.stub(WeakRef.prototype, 'deref').returns(undefined);
265
+
266
+ result = await locusDeltaRequest(options);
267
+ assert.equal(result, undefined);
268
+
269
+ WeakRef.prototype.deref.restore();
270
+ });
271
+
272
+ it('calls generateBuildLocusDeltaRequestOptions as expected', () => {
273
+ const generateBuildLocusDeltaRequestOptionsSpy = sinon.spy(
274
+ MeetingUtil,
275
+ 'generateBuildLocusDeltaRequestOptions'
276
+ );
277
+
278
+ const meeting = {};
279
+
280
+ MeetingUtil.generateLocusDeltaRequest(meeting);
281
+
282
+ assert.calledOnceWithExactly(generateBuildLocusDeltaRequestOptionsSpy, meeting);
283
+ });
284
+ });
285
+
286
+ describe('selfSupportsFeature', () => {
287
+ it('returns true if there are no user policies', () => {
288
+ assert.equal(
289
+ MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_ANNOTATION, undefined),
290
+ true
291
+ );
161
292
  });
162
293
 
163
- it('#Should call meetingRequest.remoteAudioVideoToggle with preferTranscoding:true for non multistream connections', async () => {
294
+ it('returns true if policy is true', () => {
295
+ assert.equal(
296
+ MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_ANNOTATION, {
297
+ [SELF_POLICY.SUPPORT_ANNOTATION]: true,
298
+ }),
299
+ true
300
+ );
301
+ });
302
+
303
+ it('returns false if policy is false', () => {
304
+ assert.equal(
305
+ MeetingUtil.selfSupportsFeature(SELF_POLICY.SUPPORT_ANNOTATION, {
306
+ [SELF_POLICY.SUPPORT_ANNOTATION]: false,
307
+ }),
308
+ false
309
+ );
310
+ });
311
+ });
312
+
313
+ describe('remoteUpdateAudioVideo', () => {
314
+ it('#Should call meetingRequest.locusMediaRequest with correct parameters', async () => {
164
315
  const meeting = {
165
- isMultistream: false,
316
+ id: 'meeting-id',
166
317
  mediaId: '12345',
167
- meetingRequest: {
168
- remoteAudioVideoToggle: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
318
+ selfUrl: 'self url',
319
+ locusInfo: {
320
+ sequence: {},
169
321
  },
322
+ locusMediaRequest: {
323
+ send: sinon.stub().resolves({body: {}, headers: {}}),
324
+ },
325
+ getWebexObject: sinon.stub().returns(webex),
170
326
  };
171
327
 
172
- await MeetingUtil.remoteUpdateAudioVideo(true, false, meeting);
328
+ await MeetingUtil.remoteUpdateAudioVideo(meeting, true, false);
173
329
 
174
- assert.calledOnce(meeting.meetingRequest.remoteAudioVideoToggle);
175
- const parameter = meeting.meetingRequest.remoteAudioVideoToggle.getCall(0).args[0];
330
+ assert.calledOnceWithExactly(meeting.locusMediaRequest.send, {
331
+ mediaId: '12345',
332
+ muteOptions: {
333
+ audioMuted: true,
334
+ videoMuted: false,
335
+ },
336
+ selfUrl: 'self url',
337
+ sequence: {},
338
+ type: 'LocalMute',
339
+ });
176
340
 
177
- assert.equal(parameter.preferTranscoding, true);
341
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
342
+ name: 'client.locus.media.request',
343
+ options: {meetingId: meeting.id},
344
+ });
345
+
346
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
347
+ name: 'client.locus.media.response',
348
+ options: {meetingId: meeting.id},
349
+ });
178
350
  });
179
351
  });
180
352
 
@@ -184,8 +356,16 @@ describe('plugin-meetings', () => {
184
356
  meetingJoinUrl: 'meetingJoinUrl',
185
357
  locusUrl: 'locusUrl',
186
358
  meetingRequest: {
187
- joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
359
+ joinMeeting: sinon.stub().returns(
360
+ Promise.resolve({
361
+ body: {mediaConnections: 'mediaConnections'},
362
+ headers: {
363
+ trackingid: 'trackingId',
364
+ },
365
+ })
366
+ ),
188
367
  },
368
+ getWebexObject: sinon.stub().returns(webex),
189
369
  };
190
370
 
191
371
  MeetingUtil.parseLocusJoin = sinon.stub();
@@ -196,16 +376,38 @@ describe('plugin-meetings', () => {
196
376
 
197
377
  assert.equal(parameter.inviteeAddress, 'meetingJoinUrl');
198
378
  assert.equal(parameter.preferTranscoding, true);
379
+
380
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
381
+ name: 'client.locus.join.request',
382
+ options: {meetingId: meeting.id},
383
+ });
384
+
385
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
386
+ name: 'client.locus.join.response',
387
+ payload: {
388
+ trigger: 'loci-update',
389
+ identifiers: {
390
+ trackingId: 'trackingId',
391
+ },
392
+ },
393
+ options: {
394
+ meetingId: meeting.id,
395
+ mediaConnections: 'mediaConnections',
396
+ },
397
+ });
199
398
  });
200
399
 
201
400
  it('#Should call meetingRequest.joinMeeting with breakoutsSupported=true when passed in as true', async () => {
202
401
  const meeting = {
203
- meetingRequest: {joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}}))}
402
+ meetingRequest: {
403
+ joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
404
+ },
405
+ getWebexObject: sinon.stub().returns(webex),
204
406
  };
205
407
 
206
408
  MeetingUtil.parseLocusJoin = sinon.stub();
207
409
  await MeetingUtil.joinMeeting(meeting, {
208
- breakoutsSupported: true
410
+ breakoutsSupported: true,
209
411
  });
210
412
 
211
413
  assert.calledOnce(meeting.meetingRequest.joinMeeting);
@@ -214,6 +416,45 @@ describe('plugin-meetings', () => {
214
416
  assert.equal(parameter.breakoutsSupported, true);
215
417
  });
216
418
 
419
+ it('#Should call meetingRequest.joinMeeting with liveAnnotationSupported=true when passed in as true', async () => {
420
+ const meeting = {
421
+ meetingRequest: {
422
+ joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
423
+ },
424
+ getWebexObject: sinon.stub().returns(webex),
425
+ };
426
+
427
+ MeetingUtil.parseLocusJoin = sinon.stub();
428
+ await MeetingUtil.joinMeeting(meeting, {
429
+ liveAnnotationSupported: true,
430
+ });
431
+
432
+ assert.calledOnce(meeting.meetingRequest.joinMeeting);
433
+ const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
434
+
435
+ assert.equal(parameter.liveAnnotationSupported, true);
436
+ });
437
+
438
+ it('#Should call meetingRequest.joinMeeting with locale=en_UK, deviceCapabilities=["TEST"] when they are passed in as those values', async () => {
439
+ const meeting = {
440
+ meetingRequest: {
441
+ joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
442
+ },
443
+ getWebexObject: sinon.stub().returns(webex),
444
+ };
445
+
446
+ MeetingUtil.parseLocusJoin = sinon.stub();
447
+ await MeetingUtil.joinMeeting(meeting, {
448
+ locale: 'en_UK',
449
+ deviceCapabilities: ['TEST'],
450
+ });
451
+
452
+ assert.calledOnce(meeting.meetingRequest.joinMeeting);
453
+ const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
454
+
455
+ assert.equal(parameter.locale, 'en_UK');
456
+ assert.deepEqual(parameter.deviceCapabilities, ['TEST']);
457
+ });
217
458
 
218
459
  it('#Should call meetingRequest.joinMeeting with preferTranscoding=false when multistream is enabled', async () => {
219
460
  const meeting = {
@@ -223,6 +464,7 @@ describe('plugin-meetings', () => {
223
464
  meetingRequest: {
224
465
  joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
225
466
  },
467
+ getWebexObject: sinon.stub().returns(webex),
226
468
  };
227
469
 
228
470
  MeetingUtil.parseLocusJoin = sinon.stub();
@@ -242,6 +484,7 @@ describe('plugin-meetings', () => {
242
484
  meetingRequest: {
243
485
  joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
244
486
  },
487
+ getWebexObject: sinon.stub().returns(webex),
245
488
  };
246
489
 
247
490
  MeetingUtil.parseLocusJoin = sinon.stub();
@@ -260,6 +503,7 @@ describe('plugin-meetings', () => {
260
503
  meetingRequest: {
261
504
  joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
262
505
  },
506
+ getWebexObject: sinon.stub().returns(webex),
263
507
  };
264
508
 
265
509
  MeetingUtil.parseLocusJoin = sinon.stub();
@@ -271,6 +515,63 @@ describe('plugin-meetings', () => {
271
515
  assert.isUndefined(parameter.inviteeAddress);
272
516
  assert.equal(parameter.meetingNumber, 'meetingNumber');
273
517
  });
518
+
519
+ it('should pass in the locusClusterUrl from meetingInfo', async () => {
520
+ const meeting = {
521
+ meetingInfo: {
522
+ locusClusterUrl: 'locusClusterUrl',
523
+ },
524
+ meetingRequest: {
525
+ joinMeeting: sinon.stub().returns(Promise.resolve({body: {}, headers: {}})),
526
+ },
527
+ getWebexObject: sinon.stub().returns(webex),
528
+ };
529
+
530
+ MeetingUtil.parseLocusJoin = sinon.stub();
531
+ await MeetingUtil.joinMeeting(meeting, {});
532
+
533
+ assert.calledOnce(meeting.meetingRequest.joinMeeting);
534
+ const parameter = meeting.meetingRequest.joinMeeting.getCall(0).args[0];
535
+
536
+ assert.equal(parameter.locusClusterUrl, 'locusClusterUrl');
537
+ });
538
+ });
539
+
540
+ describe('joinMeetingOptions', () => {
541
+ it('sends client events correctly', async () => {
542
+ MeetingUtil.joinMeeting = sinon.stub().rejects({});
543
+ MeetingUtil.isPinOrGuest = sinon.stub().returns(true);
544
+ const meeting = {
545
+ id: 'meeting-id',
546
+ mediaId: '12345',
547
+ selfUrl: 'self url',
548
+ locusInfo: {
549
+ sequence: {},
550
+ },
551
+ locusMediaRequest: {
552
+ send: sinon.stub().resolves({body: {}, headers: {}}),
553
+ },
554
+ getWebexObject: sinon.stub().returns(webex),
555
+ };
556
+
557
+ try {
558
+ await MeetingUtil.joinMeetingOptions(meeting, {pin: true});
559
+
560
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
561
+ name: 'client.pin.collected',
562
+ options: {
563
+ meetingId: meeting.id,
564
+ },
565
+ });
566
+ } catch (err) {
567
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
568
+ name: 'client.pin.prompt',
569
+ options: {
570
+ meetingId: meeting.id,
571
+ },
572
+ });
573
+ }
574
+ });
274
575
  });
275
576
 
276
577
  describe('getUserDisplayHintsFromLocusInfo', () => {
@@ -344,6 +645,30 @@ describe('plugin-meetings', () => {
344
645
  });
345
646
  });
346
647
 
648
+ describe('canUserRenameSelfAndObserved', () => {
649
+ it('works as expected', () => {
650
+ assert.deepEqual(
651
+ MeetingUtil.canUserRenameSelfAndObserved(['CAN_RENAME_SELF_AND_OBSERVED']),
652
+ true
653
+ );
654
+ assert.deepEqual(MeetingUtil.canUserRenameSelfAndObserved([]), false);
655
+ });
656
+ });
657
+
658
+ describe('canUserRenameOthers', () => {
659
+ it('works as expected', () => {
660
+ assert.deepEqual(MeetingUtil.canUserRenameOthers(['CAN_RENAME_OTHERS']), true);
661
+ assert.deepEqual(MeetingUtil.canUserRenameOthers([]), false);
662
+ });
663
+ });
664
+
665
+ describe('canShareWhiteBoard', () => {
666
+ it('works as expected', () => {
667
+ assert.deepEqual(MeetingUtil.canShareWhiteBoard(['SHARE_WHITEBOARD']), true);
668
+ assert.deepEqual(MeetingUtil.canShareWhiteBoard([]), false);
669
+ });
670
+ });
671
+
347
672
  describe('bothLeaveAndEndMeetingAvailable', () => {
348
673
  it('works as expected', () => {
349
674
  assert.deepEqual(
@@ -387,6 +712,7 @@ describe('plugin-meetings', () => {
387
712
  });
388
713
 
389
714
  [
715
+ {functionName: 'isSaveTranscriptsEnabled', displayHint: 'SAVE_TRANSCRIPTS_ENABLED'},
390
716
  {functionName: 'canEnableClosedCaption', displayHint: 'CAPTION_START'},
391
717
  {functionName: 'canStartTranscribing', displayHint: 'TRANSCRIPTION_CONTROL_START'},
392
718
  {functionName: 'canStopTranscribing', displayHint: 'TRANSCRIPTION_CONTROL_STOP'},
@@ -405,17 +731,306 @@ describe('plugin-meetings', () => {
405
731
  });
406
732
  });
407
733
 
408
- describe('reactions', () => {
409
- describe('canEnableReactions', () => {
410
- [[null, DISPLAY_HINTS.ENABLE_REACTIONS, true], [null, DISPLAY_HINTS.DISABLE_REACTIONS, false], [null, undefined, null]].forEach(() => ([originalValue, displayHint, expected]) => {
411
- assert.deepEqual(MeetingUtil.canEnableReactions(originalValue, [displayHint]), expected);
734
+ describe('canManageBreakout', () => {
735
+ it('works as expected', () => {
736
+ assert.deepEqual(MeetingUtil.canManageBreakout(['BREAKOUT_MANAGEMENT']), true);
737
+ assert.deepEqual(MeetingUtil.canManageBreakout([]), false);
738
+ });
739
+ });
740
+
741
+ describe('canBroadcastMessageToBreakout', () => {
742
+ it('works as expected', () => {
743
+ assert.deepEqual(
744
+ MeetingUtil.canBroadcastMessageToBreakout(['BROADCAST_MESSAGE_TO_BREAKOUT'], {
745
+ [SELF_POLICY.SUPPORT_BROADCAST_MESSAGE]: true,
746
+ }),
747
+ true
748
+ );
749
+ assert.deepEqual(
750
+ MeetingUtil.canBroadcastMessageToBreakout([], {
751
+ [SELF_POLICY.SUPPORT_BROADCAST_MESSAGE]: true,
752
+ }),
753
+ false
754
+ );
755
+ assert.deepEqual(
756
+ MeetingUtil.canBroadcastMessageToBreakout(['BROADCAST_MESSAGE_TO_BREAKOUT'], {
757
+ [SELF_POLICY.SUPPORT_BROADCAST_MESSAGE]: false,
758
+ }),
759
+ false
760
+ );
761
+ assert.deepEqual(
762
+ MeetingUtil.canBroadcastMessageToBreakout(['BROADCAST_MESSAGE_TO_BREAKOUT'], undefined),
763
+ false
764
+ );
765
+ });
766
+ });
767
+
768
+ describe('isSuppressBreakoutSupport', () => {
769
+ it('works as expected', () => {
770
+ assert.deepEqual(
771
+ MeetingUtil.isSuppressBreakoutSupport(['UCF_SUPPRESS_BREAKOUTS_SUPPORT']),
772
+ true
773
+ );
774
+ assert.deepEqual(MeetingUtil.isSuppressBreakoutSupport([]), false);
775
+ });
776
+ });
777
+
778
+ describe('canAdmitLobbyToBreakout', () => {
779
+ it('works as expected', () => {
780
+ assert.deepEqual(MeetingUtil.canAdmitLobbyToBreakout(['DISABLE_LOBBY_TO_BREAKOUT']), false);
781
+ assert.deepEqual(MeetingUtil.canAdmitLobbyToBreakout([]), true);
782
+ });
783
+ });
784
+
785
+ describe('canUserAskForHelp', () => {
786
+ it('works as expected', () => {
787
+ assert.deepEqual(MeetingUtil.canUserAskForHelp(['DISABLE_ASK_FOR_HELP']), false);
788
+ assert.deepEqual(MeetingUtil.canUserAskForHelp([]), true);
789
+ });
790
+ });
791
+
792
+ describe('isBreakoutPreassignmentsEnabled', () => {
793
+ it('works as expected', () => {
794
+ assert.deepEqual(
795
+ MeetingUtil.isBreakoutPreassignmentsEnabled(['DISABLE_BREAKOUT_PREASSIGNMENTS']),
796
+ false
797
+ );
798
+ assert.deepEqual(MeetingUtil.isBreakoutPreassignmentsEnabled([]), true);
799
+ });
800
+ });
801
+
802
+ describe('parseInterpretationInfo', () => {
803
+ let meetingInfo = {};
804
+ beforeEach(() => {
805
+ meeting.simultaneousInterpretation = {
806
+ updateMeetingSIEnabled: sinon.stub(),
807
+ updateHostSIEnabled: sinon.stub(),
808
+ updateInterpretation: sinon.stub(),
809
+ siLanguages: [],
810
+ };
811
+ });
812
+ it('should update simultaneous interpretation settings with SI and host enabled', () => {
813
+ meetingInfo.turnOnSimultaneousInterpretation = true;
814
+ meetingInfo.meetingSiteSetting = {
815
+ enableHostInterpreterControlSI: true,
816
+ };
817
+ meetingInfo.simultaneousInterpretation = {
818
+ currentSIInterpreter: true,
819
+ siLanguages: [
820
+ {languageCode: 'en', languageGroupId: 1},
821
+ {languageCode: 'es', languageGroupId: 2},
822
+ ],
823
+ };
824
+
825
+ MeetingUtil.parseInterpretationInfo(meeting, meetingInfo);
826
+ assert.calledWith(meeting.simultaneousInterpretation.updateMeetingSIEnabled, true, true);
827
+ assert.calledWith(meeting.simultaneousInterpretation.updateHostSIEnabled, true);
828
+ assert.calledWith(meeting.simultaneousInterpretation.updateInterpretation, {
829
+ siLanguages: [
830
+ {languageName: 'en', languageCode: 1},
831
+ {languageName: 'es', languageCode: 2},
832
+ ],
833
+ });
834
+ });
835
+
836
+ it('should update simultaneous interpretation settings with host SI disabled', () => {
837
+ meetingInfo.meetingSiteSetting.enableHostInterpreterControlSI = false;
838
+ meetingInfo.simultaneousInterpretation.currentSIInterpreter = false;
839
+ MeetingUtil.parseInterpretationInfo(meeting, meetingInfo);
840
+ assert.calledWith(meeting.simultaneousInterpretation.updateMeetingSIEnabled, true, false);
841
+ assert.calledWith(meeting.simultaneousInterpretation.updateHostSIEnabled, false);
842
+ assert.calledWith(meeting.simultaneousInterpretation.updateInterpretation, {
843
+ siLanguages: [
844
+ {languageName: 'en', languageCode: 1},
845
+ {languageName: 'es', languageCode: 2},
846
+ ],
847
+ });
848
+ });
849
+ it('should update simultaneous interpretation settings with SI disabled', () => {
850
+ meetingInfo.turnOnSimultaneousInterpretation = false;
851
+ MeetingUtil.parseInterpretationInfo(meeting, meetingInfo);
852
+ assert.calledWith(meeting.simultaneousInterpretation.updateMeetingSIEnabled, false, false);
853
+ assert.calledWith(meeting.simultaneousInterpretation.updateHostSIEnabled, false);
854
+ });
855
+
856
+ it('should not update simultaneous interpretation settings for invalid input', () => {
857
+ // Call the function with invalid inputs
858
+ MeetingUtil.parseInterpretationInfo(null, null);
859
+
860
+ // Ensure that the update functions are not called
861
+ assert.notCalled(meeting.simultaneousInterpretation.updateMeetingSIEnabled);
862
+ assert.notCalled(meeting.simultaneousInterpretation.updateHostSIEnabled);
863
+ assert.notCalled(meeting.simultaneousInterpretation.updateInterpretation);
864
+ });
865
+ });
866
+
867
+ describe('prepareLeaveMeetingOptions', () => {
868
+ it('works as expected', () => {
869
+ const meeting = {
870
+ locusUrl: 'locusUrl',
871
+ selfId: 'selfId',
872
+ correlationId: 'correlationId',
873
+ resourceId: 'resourceId',
874
+ deviceUrl: 'deviceUrl',
875
+ };
876
+
877
+ const leaveOptions = MeetingUtil.prepareLeaveMeetingOptions(meeting, {
878
+ selfId: 'bob',
879
+ foo: 'bar',
880
+ });
881
+
882
+ assert.deepEqual(leaveOptions, {
883
+ correlationId: 'correlationId',
884
+ deviceUrl: 'deviceUrl',
885
+ foo: 'bar',
886
+ locusUrl: 'locusUrl',
887
+ resourceId: 'resourceId',
888
+ selfId: 'bob',
889
+ });
890
+ });
891
+ });
892
+
893
+ describe('leaveMeeting', () => {
894
+ it('calls prepareLeaveMeetingOptions as expected', () => {
895
+ const meeting = {
896
+ locusUrl: 'locusUrl',
897
+ selfId: 'selfId',
898
+ correlationId: 'correlationId',
899
+ resourceId: 'resourceId',
900
+ deviceUrl: 'deviceUrl',
901
+ locusInfo: {parsedLocus: {}},
902
+ meetingRequest: {
903
+ leaveMeeting: () => Promise.resolve(),
904
+ },
905
+ };
906
+
907
+ const prepareLeaveMeetingOptionsSpy = sinon.spy(MeetingUtil, 'prepareLeaveMeetingOptions');
908
+
909
+ MeetingUtil.leaveMeeting(meeting, {foo: 'bar'});
910
+
911
+ assert.calledOnce(prepareLeaveMeetingOptionsSpy);
912
+ assert.deepEqual(prepareLeaveMeetingOptionsSpy.getCall(0).args[0], meeting);
913
+ assert.deepEqual(prepareLeaveMeetingOptionsSpy.getCall(0).args[1], {foo: 'bar'});
914
+ });
915
+ });
916
+
917
+ describe('buildLeaveFetchRequestOptions', () => {
918
+ it('calls expected functions', () => {
919
+ const buildLeaveMeetingRequestOptionsSpy = sinon.stub();
920
+
921
+ const meeting = {
922
+ locusUrl: 'locusUrl',
923
+ selfId: 'selfId',
924
+ correlationId: 'correlationId',
925
+ resourceId: 'resourceId',
926
+ deviceUrl: 'deviceUrl',
927
+ meetingRequest: {
928
+ leaveMeeting: () => Promise.resolve(),
929
+ buildLeaveMeetingRequestOptions: buildLeaveMeetingRequestOptionsSpy,
930
+ },
931
+ };
932
+
933
+ const prepareLeaveMeetingOptionsSpy = sinon.spy(MeetingUtil, 'prepareLeaveMeetingOptions');
934
+
935
+ const options = MeetingUtil.buildLeaveFetchRequestOptions(meeting, {foo: 'bar'});
936
+
937
+ assert.calledOnce(prepareLeaveMeetingOptionsSpy);
938
+ assert.deepEqual(prepareLeaveMeetingOptionsSpy.getCall(0).args[0], meeting);
939
+ assert.deepEqual(prepareLeaveMeetingOptionsSpy.getCall(0).args[1], {foo: 'bar'});
940
+
941
+ assert.calledOnce(buildLeaveMeetingRequestOptionsSpy);
942
+ assert.deepEqual(buildLeaveMeetingRequestOptionsSpy.getCall(0).args[0], {
943
+ correlationId: 'correlationId',
944
+ deviceUrl: 'deviceUrl',
945
+ foo: 'bar',
946
+ locusUrl: 'locusUrl',
947
+ resourceId: 'resourceId',
948
+ selfId: 'selfId',
949
+ });
950
+ });
951
+ });
952
+
953
+ describe('generateBuildLocusDeltaRequestOptions', () => {
954
+ it('generates the correct wrapper function', async () => {
955
+ const addSequenceSpy = sinon.spy(MeetingUtil, 'addSequence');
956
+
957
+ const meeting = {locusInfo: {sequence: 123}};
958
+
959
+ const buildLocusDeltaRequestOptions =
960
+ MeetingUtil.generateBuildLocusDeltaRequestOptions(meeting);
961
+
962
+ let result = buildLocusDeltaRequestOptions({
963
+ some: 'option',
964
+ body: {},
965
+ });
966
+ assert.deepEqual(result, {some: 'option', body: {sequence: 123}});
967
+ assert.calledOnceWithExactly(addSequenceSpy, meeting, {sequence: 123});
968
+
969
+ addSequenceSpy.resetHistory();
970
+
971
+ // body missing from options
972
+ result = buildLocusDeltaRequestOptions({});
973
+ assert.deepEqual(result, {body: {sequence: 123}});
974
+ assert.calledOnceWithExactly(addSequenceSpy, meeting, {sequence: 123});
975
+
976
+ // meeting disappears so the WeakRef returns undefined
977
+ sinon.stub(WeakRef.prototype, 'deref').returns(undefined);
978
+
979
+ const input = {foo: 'bar'};
980
+ result = buildLocusDeltaRequestOptions(input);
981
+ assert.equal(result, input);
982
+ });
983
+ });
984
+
985
+ describe('getIpVersion', () => {
986
+ let isBrowserStub;
987
+ beforeEach(() => {
988
+ isBrowserStub = sinon.stub().returns(false);
989
+
990
+ sinon.stub(BrowserDetectionModule, 'default').returns({
991
+ isBrowser: isBrowserStub,
412
992
  });
413
993
  });
414
- describe('canEnableReactions', () => {
415
- [[null, DISPLAY_HINTS.REACTIONS_ACTIVE, true], [null, DISPLAY_HINTS.REACTIONS_INACTIVE, false], [null, undefined, null]].forEach(([originalValue, displayHint, expected]) => {
416
- assert.deepEqual(MeetingUtil.canSendReactions(originalValue, [displayHint]), expected);
994
+
995
+ afterEach(() => {
996
+ sinon.restore();
997
+ });
998
+
999
+ [
1000
+ {supportsIpV4: undefined, supportsIpV6: undefined, expectedOutput: IP_VERSION.unknown},
1001
+ {supportsIpV4: undefined, supportsIpV6: true, expectedOutput: IP_VERSION.only_ipv6},
1002
+ {supportsIpV4: undefined, supportsIpV6: false, expectedOutput: IP_VERSION.unknown},
1003
+ {supportsIpV4: true, supportsIpV6: undefined, expectedOutput: IP_VERSION.only_ipv4},
1004
+ {supportsIpV4: true, supportsIpV6: true, expectedOutput: IP_VERSION.ipv4_and_ipv6},
1005
+ {supportsIpV4: true, supportsIpV6: false, expectedOutput: IP_VERSION.only_ipv4},
1006
+ {supportsIpV4: false, supportsIpV6: undefined, expectedOutput: IP_VERSION.unknown},
1007
+ {supportsIpV4: false, supportsIpV6: true, expectedOutput: IP_VERSION.only_ipv6},
1008
+ {supportsIpV4: false, supportsIpV6: false, expectedOutput: IP_VERSION.unknown},
1009
+ ].forEach(({supportsIpV4, supportsIpV6, expectedOutput}) => {
1010
+ it(`returns ${expectedOutput} when supportsIpV4=${supportsIpV4} and supportsIpV6=${supportsIpV6}`, () => {
1011
+ sinon
1012
+ .stub(webex.internal.device.ipNetworkDetector, 'supportsIpV4')
1013
+ .get(() => supportsIpV4);
1014
+ sinon
1015
+ .stub(webex.internal.device.ipNetworkDetector, 'supportsIpV6')
1016
+ .get(() => supportsIpV6);
1017
+
1018
+ assert.equal(MeetingUtil.getIpVersion(webex), expectedOutput);
1019
+ });
1020
+
1021
+ it(`returns undefined when supportsIpV4=${supportsIpV4} and supportsIpV6=${supportsIpV6} and browser is firefox`, () => {
1022
+ sinon
1023
+ .stub(webex.internal.device.ipNetworkDetector, 'supportsIpV4')
1024
+ .get(() => supportsIpV4);
1025
+ sinon
1026
+ .stub(webex.internal.device.ipNetworkDetector, 'supportsIpV6')
1027
+ .get(() => supportsIpV6);
1028
+
1029
+ isBrowserStub.callsFake((name) => name === 'firefox');
1030
+
1031
+ assert.equal(MeetingUtil.getIpVersion(webex), undefined);
417
1032
  });
418
1033
  });
419
1034
  });
420
- })
1035
+ });
421
1036
  });