@webex/plugin-meetings 3.0.0-beta.24 → 3.0.0-beta.241

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