@webex/plugin-meetings 3.0.0-beta.17 → 3.0.0-beta.171

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 (427) hide show
  1. package/README.md +45 -7
  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 +359 -0
  7. package/dist/annotation/index.js.map +1 -0
  8. package/dist/breakouts/breakout.js +216 -0
  9. package/dist/breakouts/breakout.js.map +1 -0
  10. package/dist/breakouts/collection.js +23 -0
  11. package/dist/breakouts/collection.js.map +1 -0
  12. package/dist/breakouts/edit-lock-error.js +52 -0
  13. package/dist/breakouts/edit-lock-error.js.map +1 -0
  14. package/dist/breakouts/events.js +45 -0
  15. package/dist/breakouts/events.js.map +1 -0
  16. package/dist/breakouts/index.js +1048 -0
  17. package/dist/breakouts/index.js.map +1 -0
  18. package/dist/breakouts/request.js +78 -0
  19. package/dist/breakouts/request.js.map +1 -0
  20. package/dist/breakouts/utils.js +67 -0
  21. package/dist/breakouts/utils.js.map +1 -0
  22. package/dist/common/errors/webex-errors.js +3 -2
  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/config.js +6 -8
  27. package/dist/config.js.map +1 -1
  28. package/dist/constants.js +194 -28
  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 +300 -0
  39. package/dist/controls-options-manager/util.js.map +1 -0
  40. package/dist/index.js +107 -0
  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 +214 -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 +92 -2
  49. package/dist/locus-info/controlsUtils.js.map +1 -1
  50. package/dist/locus-info/index.js +350 -41
  51. package/dist/locus-info/index.js.map +1 -1
  52. package/dist/locus-info/mediaSharesUtils.js +43 -1
  53. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  54. package/dist/locus-info/parser.js +2 -1
  55. package/dist/locus-info/parser.js.map +1 -1
  56. package/dist/locus-info/selfUtils.js +97 -14
  57. package/dist/locus-info/selfUtils.js.map +1 -1
  58. package/dist/media/index.js +41 -136
  59. package/dist/media/index.js.map +1 -1
  60. package/dist/media/properties.js +33 -94
  61. package/dist/media/properties.js.map +1 -1
  62. package/dist/mediaQualityMetrics/config.js +505 -493
  63. package/dist/mediaQualityMetrics/config.js.map +1 -1
  64. package/dist/meeting/in-meeting-actions.js +76 -2
  65. package/dist/meeting/in-meeting-actions.js.map +1 -1
  66. package/dist/meeting/index.js +2757 -2439
  67. package/dist/meeting/index.js.map +1 -1
  68. package/dist/meeting/locusMediaRequest.js +291 -0
  69. package/dist/meeting/locusMediaRequest.js.map +1 -0
  70. package/dist/meeting/muteState.js +229 -124
  71. package/dist/meeting/muteState.js.map +1 -1
  72. package/dist/meeting/request.js +191 -167
  73. package/dist/meeting/request.js.map +1 -1
  74. package/dist/meeting/request.type.js.map +1 -1
  75. package/dist/meeting/util.js +477 -466
  76. package/dist/meeting/util.js.map +1 -1
  77. package/dist/meeting-info/index.js +48 -7
  78. package/dist/meeting-info/index.js.map +1 -1
  79. package/dist/meeting-info/meeting-info-v2.js +172 -50
  80. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  81. package/dist/meeting-info/utilv2.js +20 -5
  82. package/dist/meeting-info/utilv2.js.map +1 -1
  83. package/dist/meetings/collection.js +22 -0
  84. package/dist/meetings/collection.js.map +1 -1
  85. package/dist/meetings/index.js +377 -82
  86. package/dist/meetings/index.js.map +1 -1
  87. package/dist/meetings/meetings.types.js +7 -0
  88. package/dist/meetings/meetings.types.js.map +1 -0
  89. package/dist/meetings/request.js +16 -12
  90. package/dist/meetings/request.js.map +1 -1
  91. package/dist/meetings/util.js +88 -1
  92. package/dist/meetings/util.js.map +1 -1
  93. package/dist/member/index.js +43 -0
  94. package/dist/member/index.js.map +1 -1
  95. package/dist/member/types.js +15 -0
  96. package/dist/member/types.js.map +1 -0
  97. package/dist/member/util.js +97 -3
  98. package/dist/member/util.js.map +1 -1
  99. package/dist/members/collection.js +10 -0
  100. package/dist/members/collection.js.map +1 -1
  101. package/dist/members/index.js +94 -11
  102. package/dist/members/index.js.map +1 -1
  103. package/dist/members/request.js +109 -39
  104. package/dist/members/request.js.map +1 -1
  105. package/dist/members/types.js +15 -0
  106. package/dist/members/types.js.map +1 -0
  107. package/dist/members/util.js +316 -233
  108. package/dist/members/util.js.map +1 -1
  109. package/dist/metrics/constants.js +3 -5
  110. package/dist/metrics/constants.js.map +1 -1
  111. package/dist/metrics/index.js +1 -468
  112. package/dist/metrics/index.js.map +1 -1
  113. package/dist/multistream/mediaRequestManager.js +265 -36
  114. package/dist/multistream/mediaRequestManager.js.map +1 -1
  115. package/dist/multistream/receiveSlot.js +52 -19
  116. package/dist/multistream/receiveSlot.js.map +1 -1
  117. package/dist/multistream/receiveSlotManager.js +53 -33
  118. package/dist/multistream/receiveSlotManager.js.map +1 -1
  119. package/dist/multistream/remoteMedia.js +44 -18
  120. package/dist/multistream/remoteMedia.js.map +1 -1
  121. package/dist/multistream/remoteMediaGroup.js +60 -3
  122. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  123. package/dist/multistream/remoteMediaManager.js +322 -103
  124. package/dist/multistream/remoteMediaManager.js.map +1 -1
  125. package/dist/networkQualityMonitor/index.js +4 -2
  126. package/dist/networkQualityMonitor/index.js.map +1 -1
  127. package/dist/reachability/index.js +117 -60
  128. package/dist/reachability/index.js.map +1 -1
  129. package/dist/reachability/request.js +12 -5
  130. package/dist/reachability/request.js.map +1 -1
  131. package/dist/reactions/constants.js +13 -0
  132. package/dist/reactions/constants.js.map +1 -0
  133. package/dist/reactions/reactions.js +2 -2
  134. package/dist/reactions/reactions.js.map +1 -1
  135. package/dist/reactions/reactions.type.js +18 -18
  136. package/dist/reactions/reactions.type.js.map +1 -1
  137. package/dist/reconnection-manager/index.js +216 -162
  138. package/dist/reconnection-manager/index.js.map +1 -1
  139. package/dist/recording-controller/enums.js +17 -0
  140. package/dist/recording-controller/enums.js.map +1 -0
  141. package/dist/recording-controller/index.js +363 -0
  142. package/dist/recording-controller/index.js.map +1 -0
  143. package/dist/recording-controller/util.js +64 -0
  144. package/dist/recording-controller/util.js.map +1 -0
  145. package/dist/roap/index.js +21 -29
  146. package/dist/roap/index.js.map +1 -1
  147. package/dist/roap/request.js +135 -94
  148. package/dist/roap/request.js.map +1 -1
  149. package/dist/roap/turnDiscovery.js +135 -53
  150. package/dist/roap/turnDiscovery.js.map +1 -1
  151. package/dist/statsAnalyzer/global.js +1 -93
  152. package/dist/statsAnalyzer/global.js.map +1 -1
  153. package/dist/statsAnalyzer/index.js +329 -314
  154. package/dist/statsAnalyzer/index.js.map +1 -1
  155. package/dist/statsAnalyzer/mqaUtil.js +103 -54
  156. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  157. package/dist/types/annotation/annotation.types.d.ts +43 -0
  158. package/dist/types/annotation/constants.d.ts +31 -0
  159. package/dist/types/annotation/index.d.ts +124 -0
  160. package/dist/types/breakouts/breakout.d.ts +8 -0
  161. package/dist/types/breakouts/collection.d.ts +5 -0
  162. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  163. package/dist/types/breakouts/events.d.ts +8 -0
  164. package/dist/types/breakouts/index.d.ts +5 -0
  165. package/dist/types/breakouts/request.d.ts +22 -0
  166. package/dist/types/breakouts/utils.d.ts +15 -0
  167. package/dist/types/common/browser-detection.d.ts +9 -0
  168. package/dist/types/common/collection.d.ts +48 -0
  169. package/dist/types/common/config.d.ts +2 -0
  170. package/dist/types/common/errors/captcha-error.d.ts +15 -0
  171. package/dist/types/common/errors/intent-to-join.d.ts +16 -0
  172. package/dist/types/common/errors/join-meeting.d.ts +17 -0
  173. package/dist/types/common/errors/media.d.ts +15 -0
  174. package/dist/types/common/errors/parameter.d.ts +15 -0
  175. package/dist/types/common/errors/password-error.d.ts +15 -0
  176. package/dist/types/common/errors/permission.d.ts +14 -0
  177. package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
  178. package/dist/types/common/errors/reconnection.d.ts +15 -0
  179. package/dist/types/common/errors/stats.d.ts +15 -0
  180. package/dist/types/common/errors/webex-errors.d.ts +69 -0
  181. package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
  182. package/dist/types/common/events/events-scope.d.ts +17 -0
  183. package/dist/types/common/events/events.d.ts +12 -0
  184. package/dist/types/common/events/trigger-proxy.d.ts +2 -0
  185. package/dist/types/common/events/util.d.ts +2 -0
  186. package/dist/types/common/logs/logger-config.d.ts +2 -0
  187. package/dist/types/common/logs/logger-proxy.d.ts +2 -0
  188. package/dist/types/common/logs/request.d.ts +34 -0
  189. package/dist/types/common/queue.d.ts +32 -0
  190. package/dist/types/config.d.ts +72 -0
  191. package/dist/types/constants.d.ts +1007 -0
  192. package/dist/types/controls-options-manager/constants.d.ts +4 -0
  193. package/dist/types/controls-options-manager/enums.d.ts +15 -0
  194. package/dist/types/controls-options-manager/index.d.ts +136 -0
  195. package/dist/types/controls-options-manager/types.d.ts +43 -0
  196. package/dist/types/controls-options-manager/util.d.ts +1 -0
  197. package/dist/types/index.d.ts +7 -0
  198. package/dist/types/interpretation/collection.d.ts +5 -0
  199. package/dist/types/interpretation/index.d.ts +5 -0
  200. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  201. package/dist/types/locus-info/controlsUtils.d.ts +2 -0
  202. package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
  203. package/dist/types/locus-info/fullState.d.ts +2 -0
  204. package/dist/types/locus-info/hostUtils.d.ts +2 -0
  205. package/dist/types/locus-info/index.d.ts +315 -0
  206. package/dist/types/locus-info/infoUtils.d.ts +2 -0
  207. package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
  208. package/dist/types/locus-info/parser.d.ts +212 -0
  209. package/dist/types/locus-info/selfUtils.d.ts +2 -0
  210. package/dist/types/media/index.d.ts +34 -0
  211. package/dist/types/media/properties.d.ts +93 -0
  212. package/dist/types/media/util.d.ts +2 -0
  213. package/dist/types/mediaQualityMetrics/config.d.ts +365 -0
  214. package/dist/types/meeting/in-meeting-actions.d.ts +149 -0
  215. package/dist/types/meeting/index.d.ts +1462 -0
  216. package/dist/types/meeting/locusMediaRequest.d.ts +70 -0
  217. package/dist/types/meeting/muteState.d.ts +184 -0
  218. package/dist/types/meeting/request.d.ts +270 -0
  219. package/dist/types/meeting/request.type.d.ts +11 -0
  220. package/dist/types/meeting/state.d.ts +9 -0
  221. package/dist/types/meeting/util.d.ts +77 -0
  222. package/dist/types/meeting-info/collection.d.ts +20 -0
  223. package/dist/types/meeting-info/index.d.ts +62 -0
  224. package/dist/types/meeting-info/meeting-info-v2.d.ts +122 -0
  225. package/dist/types/meeting-info/request.d.ts +22 -0
  226. package/dist/types/meeting-info/util.d.ts +2 -0
  227. package/dist/types/meeting-info/utilv2.d.ts +2 -0
  228. package/dist/types/meetings/collection.d.ts +31 -0
  229. package/dist/types/meetings/index.d.ts +365 -0
  230. package/dist/types/meetings/meetings.types.d.ts +4 -0
  231. package/dist/types/meetings/request.d.ts +27 -0
  232. package/dist/types/meetings/util.d.ts +18 -0
  233. package/dist/types/member/index.d.ts +158 -0
  234. package/dist/types/member/types.d.ts +21 -0
  235. package/dist/types/member/util.d.ts +2 -0
  236. package/dist/types/members/collection.d.ts +29 -0
  237. package/dist/types/members/index.d.ts +353 -0
  238. package/dist/types/members/request.d.ts +114 -0
  239. package/dist/types/members/types.d.ts +24 -0
  240. package/dist/types/members/util.d.ts +210 -0
  241. package/dist/types/metrics/constants.d.ts +55 -0
  242. package/dist/types/metrics/index.d.ts +45 -0
  243. package/dist/types/multistream/mediaRequestManager.d.ts +118 -0
  244. package/dist/types/multistream/receiveSlot.d.ts +68 -0
  245. package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
  246. package/dist/types/multistream/remoteMedia.d.ts +72 -0
  247. package/dist/types/multistream/remoteMediaGroup.d.ts +47 -0
  248. package/dist/types/multistream/remoteMediaManager.d.ts +277 -0
  249. package/dist/types/networkQualityMonitor/index.d.ts +70 -0
  250. package/dist/types/personal-meeting-room/index.d.ts +47 -0
  251. package/dist/types/personal-meeting-room/request.d.ts +14 -0
  252. package/dist/types/personal-meeting-room/util.d.ts +2 -0
  253. package/dist/types/reachability/index.d.ts +152 -0
  254. package/dist/types/reachability/request.d.ts +37 -0
  255. package/dist/types/reactions/constants.d.ts +3 -0
  256. package/dist/types/reactions/reactions.d.ts +4 -0
  257. package/dist/types/reactions/reactions.type.d.ts +52 -0
  258. package/dist/types/reconnection-manager/index.d.ts +126 -0
  259. package/dist/types/recording-controller/enums.d.ts +7 -0
  260. package/dist/types/recording-controller/index.d.ts +208 -0
  261. package/dist/types/recording-controller/util.d.ts +14 -0
  262. package/dist/types/roap/index.d.ts +77 -0
  263. package/dist/types/roap/request.d.ts +36 -0
  264. package/dist/types/roap/turnDiscovery.d.ts +91 -0
  265. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  266. package/dist/types/statsAnalyzer/index.d.ts +200 -0
  267. package/dist/types/statsAnalyzer/mqaUtil.d.ts +24 -0
  268. package/dist/types/transcription/index.d.ts +64 -0
  269. package/package.json +29 -21
  270. package/src/annotation/annotation.types.ts +52 -0
  271. package/src/annotation/constants.ts +36 -0
  272. package/src/annotation/index.ts +343 -0
  273. package/src/breakouts/README.md +220 -0
  274. package/src/breakouts/breakout.ts +188 -0
  275. package/src/breakouts/collection.ts +19 -0
  276. package/src/breakouts/edit-lock-error.ts +25 -0
  277. package/src/breakouts/events.ts +56 -0
  278. package/src/breakouts/index.ts +925 -0
  279. package/src/breakouts/request.ts +55 -0
  280. package/src/breakouts/utils.ts +57 -0
  281. package/src/common/errors/webex-errors.ts +6 -2
  282. package/src/common/logs/logger-proxy.ts +1 -1
  283. package/src/config.ts +5 -7
  284. package/src/constants.ts +183 -22
  285. package/src/controls-options-manager/constants.ts +5 -0
  286. package/src/controls-options-manager/enums.ts +18 -0
  287. package/src/controls-options-manager/index.ts +278 -0
  288. package/src/controls-options-manager/types.ts +59 -0
  289. package/src/controls-options-manager/util.ts +286 -0
  290. package/src/index.ts +39 -0
  291. package/src/interpretation/README.md +51 -0
  292. package/src/interpretation/collection.ts +19 -0
  293. package/src/interpretation/index.ts +182 -0
  294. package/src/interpretation/siLanguage.ts +18 -0
  295. package/src/locus-info/controlsUtils.ts +110 -0
  296. package/src/locus-info/index.ts +374 -38
  297. package/src/locus-info/mediaSharesUtils.ts +48 -0
  298. package/src/locus-info/parser.ts +2 -1
  299. package/src/locus-info/selfUtils.ts +86 -2
  300. package/src/media/index.ts +78 -144
  301. package/src/media/properties.ts +55 -99
  302. package/src/mediaQualityMetrics/config.ts +379 -377
  303. package/src/meeting/in-meeting-actions.ts +151 -3
  304. package/src/meeting/index.ts +2181 -2052
  305. package/src/meeting/locusMediaRequest.ts +309 -0
  306. package/src/meeting/muteState.ts +228 -132
  307. package/src/meeting/request.ts +100 -91
  308. package/src/meeting/request.type.ts +2 -0
  309. package/src/meeting/util.ts +450 -439
  310. package/src/meeting-info/index.ts +54 -8
  311. package/src/meeting-info/meeting-info-v2.ts +150 -14
  312. package/src/meeting-info/utilv2.ts +13 -3
  313. package/src/meetings/collection.ts +20 -0
  314. package/src/meetings/index.ts +396 -89
  315. package/src/meetings/meetings.types.ts +12 -0
  316. package/src/meetings/request.ts +3 -1
  317. package/src/meetings/util.ts +103 -4
  318. package/src/member/index.ts +42 -0
  319. package/src/member/types.ts +24 -0
  320. package/src/member/util.ts +95 -1
  321. package/src/members/collection.ts +8 -0
  322. package/src/members/index.ts +108 -6
  323. package/src/members/request.ts +98 -17
  324. package/src/members/types.ts +28 -0
  325. package/src/members/util.ts +319 -240
  326. package/src/metrics/constants.ts +2 -4
  327. package/src/metrics/index.ts +1 -490
  328. package/src/multistream/mediaRequestManager.ts +337 -63
  329. package/src/multistream/receiveSlot.ts +68 -26
  330. package/src/multistream/receiveSlotManager.ts +61 -38
  331. package/src/multistream/remoteMedia.ts +29 -3
  332. package/src/multistream/remoteMediaGroup.ts +61 -2
  333. package/src/multistream/remoteMediaManager.ts +260 -66
  334. package/src/networkQualityMonitor/index.ts +6 -6
  335. package/src/reachability/index.ts +75 -25
  336. package/src/reachability/request.ts +10 -5
  337. package/src/reactions/constants.ts +4 -0
  338. package/src/reactions/reactions.ts +4 -4
  339. package/src/reactions/reactions.type.ts +28 -3
  340. package/src/reconnection-manager/index.ts +83 -49
  341. package/src/recording-controller/enums.ts +8 -0
  342. package/src/recording-controller/index.ts +333 -0
  343. package/src/recording-controller/util.ts +75 -0
  344. package/src/roap/index.ts +21 -30
  345. package/src/roap/request.ts +72 -61
  346. package/src/roap/turnDiscovery.ts +51 -27
  347. package/src/statsAnalyzer/global.ts +1 -94
  348. package/src/statsAnalyzer/index.ts +380 -390
  349. package/src/statsAnalyzer/mqaUtil.ts +106 -99
  350. package/test/integration/spec/converged-space-meetings.js +233 -0
  351. package/test/integration/spec/journey.js +336 -259
  352. package/test/integration/spec/space-meeting.js +77 -4
  353. package/test/unit/spec/annotation/index.ts +436 -0
  354. package/test/unit/spec/breakouts/breakout.ts +237 -0
  355. package/test/unit/spec/breakouts/collection.ts +15 -0
  356. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  357. package/test/unit/spec/breakouts/events.ts +89 -0
  358. package/test/unit/spec/breakouts/index.ts +1790 -0
  359. package/test/unit/spec/breakouts/request.ts +104 -0
  360. package/test/unit/spec/breakouts/utils.js +72 -0
  361. package/test/unit/spec/controls-options-manager/index.js +287 -0
  362. package/test/unit/spec/controls-options-manager/util.js +518 -0
  363. package/test/unit/spec/fixture/locus.js +1 -0
  364. package/test/unit/spec/interpretation/collection.ts +15 -0
  365. package/test/unit/spec/interpretation/index.ts +329 -0
  366. package/test/unit/spec/interpretation/siLanguage.ts +26 -0
  367. package/test/unit/spec/locus-info/controlsUtils.js +323 -30
  368. package/test/unit/spec/locus-info/index.js +792 -4
  369. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  370. package/test/unit/spec/locus-info/selfConstant.js +48 -0
  371. package/test/unit/spec/locus-info/selfUtils.js +275 -0
  372. package/test/unit/spec/media/index.ts +130 -24
  373. package/test/unit/spec/media/properties.ts +9 -9
  374. package/test/unit/spec/meeting/in-meeting-actions.ts +75 -3
  375. package/test/unit/spec/meeting/index.js +2834 -1442
  376. package/test/unit/spec/meeting/locusMediaRequest.ts +436 -0
  377. package/test/unit/spec/meeting/muteState.js +370 -208
  378. package/test/unit/spec/meeting/request.js +354 -42
  379. package/test/unit/spec/meeting/utils.js +384 -170
  380. package/test/unit/spec/meeting-info/index.js +181 -0
  381. package/test/unit/spec/meeting-info/meetinginfov2.js +383 -5
  382. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  383. package/test/unit/spec/meetings/collection.js +14 -0
  384. package/test/unit/spec/meetings/index.js +847 -121
  385. package/test/unit/spec/meetings/utils.js +206 -2
  386. package/test/unit/spec/member/index.js +31 -0
  387. package/test/unit/spec/member/util.js +408 -32
  388. package/test/unit/spec/members/index.js +320 -1
  389. package/test/unit/spec/members/request.js +206 -27
  390. package/test/unit/spec/members/utils.js +184 -0
  391. package/test/unit/spec/metrics/index.js +1 -50
  392. package/test/unit/spec/multistream/mediaRequestManager.ts +1012 -109
  393. package/test/unit/spec/multistream/receiveSlot.ts +77 -18
  394. package/test/unit/spec/multistream/receiveSlotManager.ts +69 -39
  395. package/test/unit/spec/multistream/remoteMedia.ts +32 -2
  396. package/test/unit/spec/multistream/remoteMediaGroup.ts +271 -5
  397. package/test/unit/spec/multistream/remoteMediaManager.ts +672 -65
  398. package/test/unit/spec/networkQualityMonitor/index.js +4 -4
  399. package/test/unit/spec/reachability/index.ts +176 -25
  400. package/test/unit/spec/reachability/request.js +66 -0
  401. package/test/unit/spec/reconnection-manager/index.js +95 -13
  402. package/test/unit/spec/recording-controller/index.js +307 -0
  403. package/test/unit/spec/recording-controller/util.js +229 -0
  404. package/test/unit/spec/roap/index.ts +28 -52
  405. package/test/unit/spec/roap/request.ts +225 -0
  406. package/test/unit/spec/roap/turnDiscovery.ts +73 -34
  407. package/test/unit/spec/stats-analyzer/index.js +94 -43
  408. package/test/utils/constants.js +9 -0
  409. package/test/utils/integrationTestUtils.js +46 -0
  410. package/test/utils/testUtils.js +0 -45
  411. package/test/utils/webex-config.js +4 -0
  412. package/test/utils/webex-test-users.js +7 -3
  413. package/tsconfig.json +6 -0
  414. package/dist/media/internal-media-core-wrapper.js +0 -18
  415. package/dist/media/internal-media-core-wrapper.js.map +0 -1
  416. package/dist/meeting/effectsState.js +0 -262
  417. package/dist/meeting/effectsState.js.map +0 -1
  418. package/dist/metrics/config.js +0 -299
  419. package/dist/metrics/config.js.map +0 -1
  420. package/dist/multistream/multistreamMedia.js +0 -106
  421. package/dist/multistream/multistreamMedia.js.map +0 -1
  422. package/src/index.js +0 -15
  423. package/src/media/internal-media-core-wrapper.ts +0 -9
  424. package/src/meeting/effectsState.ts +0 -211
  425. package/src/metrics/config.ts +0 -495
  426. package/src/multistream/multistreamMedia.ts +0 -93
  427. package/test/unit/spec/meeting/effectsState.js +0 -281
@@ -16,9 +16,14 @@ import {
16
16
  LOCUSEVENT,
17
17
  EVENTS,
18
18
  DISPLAY_HINTS,
19
+ _CALL_,
20
+ LOCUS,
21
+ MEETING_STATE,
22
+ _MEETING_,
19
23
  } from '../../../../src/constants';
20
24
 
21
- import {self, selfWithInactivity} from './selfConstant';
25
+ import { self, selfWithInactivity } from "./selfConstant";
26
+ import uuid from "uuid";
22
27
 
23
28
  describe('plugin-meetings', () => {
24
29
  describe('LocusInfo index', () => {
@@ -66,8 +71,12 @@ describe('plugin-meetings', () => {
66
71
 
67
72
  beforeEach('setup new controls', () => {
68
73
  newControls = {
74
+ disallowUnmute: {enabled: true},
69
75
  lock: {},
70
76
  meetingFull: {},
77
+ muteOnEntry: {enabled: true},
78
+ raiseHand: {enabled: true},
79
+ reactions: {enabled: true, showDisplayNameWithReactions: true},
71
80
  record: {
72
81
  recording: false,
73
82
  paused: false,
@@ -76,12 +85,14 @@ describe('plugin-meetings', () => {
76
85
  modifiedBy: 'George Kittle',
77
86
  },
78
87
  },
79
- shareControl: {},
88
+ shareControl: {control: 'example-value'},
80
89
  transcribe: {},
90
+ viewTheParticipantList: {enabled: true},
81
91
  meetingContainer: {
82
92
  meetingContainerUrl: 'http://new-url.com',
83
93
  },
84
94
  entryExitTone: {enabled: true, mode: 'foo'},
95
+ video: {enabled: true},
85
96
  };
86
97
  });
87
98
 
@@ -95,6 +106,97 @@ describe('plugin-meetings', () => {
95
106
  assert.equal(locusInfo.controls, newControls);
96
107
  });
97
108
 
109
+ it('should trigger the CONTROLS_MUTE_ON_ENTRY_CHANGED event when necessary', () => {
110
+ locusInfo.controls = {};
111
+ locusInfo.emitScoped = sinon.stub();
112
+ locusInfo.updateControls(newControls);
113
+
114
+ assert.calledWith(
115
+ locusInfo.emitScoped,
116
+ {file: 'locus-info', function: 'updateControls'},
117
+ LOCUSINFO.EVENTS.CONTROLS_MUTE_ON_ENTRY_CHANGED,
118
+ {state: newControls.muteOnEntry},
119
+ );
120
+ });
121
+
122
+ it('should trigger the CONTROLS_SHARE_CONTROL_CHANGED event when necessary', () => {
123
+ locusInfo.controls = {};
124
+ locusInfo.emitScoped = sinon.stub();
125
+ locusInfo.updateControls(newControls);
126
+
127
+ assert.calledWith(
128
+ locusInfo.emitScoped,
129
+ {file: 'locus-info', function: 'updateControls'},
130
+ LOCUSINFO.EVENTS.CONTROLS_SHARE_CONTROL_CHANGED,
131
+ {state: newControls.shareControl},
132
+ );
133
+ });
134
+
135
+ it('should trigger the CONTROLS_DISALLOW_UNMUTE_CHANGED event when necessary', () => {
136
+ locusInfo.controls = {};
137
+ locusInfo.emitScoped = sinon.stub();
138
+ locusInfo.updateControls(newControls);
139
+
140
+ assert.calledWith(
141
+ locusInfo.emitScoped,
142
+ {file: 'locus-info', function: 'updateControls'},
143
+ LOCUSINFO.EVENTS.CONTROLS_DISALLOW_UNMUTE_CHANGED,
144
+ {state: newControls.disallowUnmute},
145
+ );
146
+ });
147
+
148
+ it('should trigger the CONTROLS_REACTIONS_CHANGED event when necessary', () => {
149
+ locusInfo.controls = {};
150
+ locusInfo.emitScoped = sinon.stub();
151
+ locusInfo.updateControls(newControls);
152
+
153
+ assert.calledWith(
154
+ locusInfo.emitScoped,
155
+ {file: 'locus-info', function: 'updateControls'},
156
+ LOCUSINFO.EVENTS.CONTROLS_REACTIONS_CHANGED,
157
+ {state: newControls.reactions},
158
+ );
159
+ });
160
+
161
+ it('should trigger the CONTROLS_VIEW_THE_PARTICIPANTS_LIST_CHANGED event when necessary', () => {
162
+ locusInfo.controls = {};
163
+ locusInfo.emitScoped = sinon.stub();
164
+ locusInfo.updateControls(newControls);
165
+
166
+ assert.calledWith(
167
+ locusInfo.emitScoped,
168
+ {file: 'locus-info', function: 'updateControls'},
169
+ LOCUSINFO.EVENTS.CONTROLS_VIEW_THE_PARTICIPANTS_LIST_CHANGED,
170
+ {state: newControls.viewTheParticipantList},
171
+ );
172
+ });
173
+
174
+ it('should trigger the CONTROLS_RAISE_HAND_CHANGED event when necessary', () => {
175
+ locusInfo.controls = {};
176
+ locusInfo.emitScoped = sinon.stub();
177
+ locusInfo.updateControls(newControls);
178
+
179
+ assert.calledWith(
180
+ locusInfo.emitScoped,
181
+ {file: 'locus-info', function: 'updateControls'},
182
+ LOCUSINFO.EVENTS.CONTROLS_RAISE_HAND_CHANGED,
183
+ {state: newControls.raiseHand},
184
+ );
185
+ });
186
+
187
+ it('should trigger the CONTROLS_VIDEO_CHANGED event when necessary', () => {
188
+ locusInfo.controls = {};
189
+ locusInfo.emitScoped = sinon.stub();
190
+ locusInfo.updateControls(newControls);
191
+
192
+ assert.calledWith(
193
+ locusInfo.emitScoped,
194
+ {file: 'locus-info', function: 'updateControls'},
195
+ LOCUSINFO.EVENTS.CONTROLS_VIDEO_CHANGED,
196
+ {state: newControls.video},
197
+ );
198
+ });
199
+
98
200
  it('should not trigger the CONTROLS_RECORDING_UPDATED event', () => {
99
201
  locusInfo.controls = {};
100
202
  locusInfo.emitScoped = sinon.stub();
@@ -277,6 +379,48 @@ describe('plugin-meetings', () => {
277
379
  );
278
380
  });
279
381
 
382
+ it('should update the breakout state', () => {
383
+ locusInfo.emitScoped = sinon.stub();
384
+ let tmpStub = sinon.stub(SelfUtils, 'getReplacedBreakoutMoveId').returns('breakoutMoveId');
385
+ newControls.breakout = { 'breakout': {} };
386
+ let selfInfo = {};
387
+
388
+ locusInfo.updateControls(newControls, selfInfo);
389
+
390
+ assert.calledWith(
391
+ locusInfo.emitScoped,
392
+ {
393
+ file: 'locus-info',
394
+ function: 'updateControls',
395
+ },
396
+ LOCUSINFO.EVENTS.CONTROLS_MEETING_BREAKOUT_UPDATED,
397
+ {
398
+ breakout: newControls.breakout,
399
+ }
400
+ );
401
+ tmpStub.restore();
402
+ });
403
+
404
+ it('should update the interpretation state', () => {
405
+ locusInfo.emitScoped = sinon.stub();
406
+ newControls.interpretation = {siLanguages: [{languageCode: 20, languageName: 'en'}]};
407
+ let selfInfo = {};
408
+
409
+ locusInfo.updateControls(newControls, selfInfo);
410
+
411
+ assert.calledWith(
412
+ locusInfo.emitScoped,
413
+ {
414
+ file: 'locus-info',
415
+ function: 'updateControls',
416
+ },
417
+ LOCUSINFO.EVENTS.CONTROLS_MEETING_INTERPRETATION_UPDATED,
418
+ {
419
+ interpretation: newControls.interpretation,
420
+ }
421
+ );
422
+ });
423
+
280
424
  it('should update the transcript state', () => {
281
425
  locusInfo.emitScoped = sinon.stub();
282
426
  locusInfo.controls = {
@@ -398,6 +542,39 @@ describe('plugin-meetings', () => {
398
542
  assert.notEqual(x.args[1], LOCUSINFO.EVENTS.CONTROLS_ENTRY_EXIT_TONE_UPDATED);
399
543
  });
400
544
  });
545
+
546
+ it('should update videoEnabled when changed', () => {
547
+ locusInfo.controls = {};
548
+
549
+ locusInfo.emitScoped = sinon.stub();
550
+ locusInfo.updateControls(newControls);
551
+
552
+ assert.calledWith(
553
+ locusInfo.emitScoped,
554
+ {
555
+ file: 'locus-info',
556
+ function: 'updateControls',
557
+ },
558
+ LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED,
559
+ {unmuteAllowed: true}
560
+ );
561
+
562
+ assert.equal(mockMeeting.unmuteVideoAllowed, true);
563
+ });
564
+
565
+ it('should not update videoEnabled when unchanged', () => {
566
+ locusInfo.controls = {videoEnabled: true};
567
+
568
+ locusInfo.emitScoped = sinon.stub();
569
+ locusInfo.updateControls(newControls);
570
+
571
+ locusInfo.emitScoped.getCalls().forEach((x) => {
572
+ // check that no calls in emitScoped are for SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED
573
+ assert.notEqual(x.args[1], LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED);
574
+ });
575
+
576
+ assert.equal(mockMeeting.unmuteVideoAllowed, undefined);
577
+ });
401
578
  });
402
579
 
403
580
  describe('#updateParticipants()', () => {
@@ -451,6 +628,7 @@ describe('plugin-meetings', () => {
451
628
  selfIdentity: '123',
452
629
  selfId: '2',
453
630
  hostId: '3',
631
+ isReplace: undefined,
454
632
  }
455
633
  );
456
634
  // note: in a real use case, recordingId, selfId, and hostId would all be the same
@@ -458,6 +636,43 @@ describe('plugin-meetings', () => {
458
636
  // are being correctly grabbed from locusInfo.parsedLocus within updateParticipants
459
637
  });
460
638
 
639
+ it('should call with breakout control info', () => {
640
+ locusInfo.parsedLocus = {
641
+ controls: {
642
+ record: {
643
+ modifiedBy: '1',
644
+ },
645
+ },
646
+ self: {
647
+ selfIdentity: '123',
648
+ selfId: '2',
649
+ },
650
+ host: {
651
+ hostId: '3',
652
+ },
653
+ };
654
+
655
+ locusInfo.emitScoped = sinon.stub();
656
+ locusInfo.updateParticipants({}, true);
657
+
658
+ assert.calledWith(
659
+ locusInfo.emitScoped,
660
+ {
661
+ file: 'locus-info',
662
+ function: 'updateParticipants',
663
+ },
664
+ EVENTS.LOCUS_INFO_UPDATE_PARTICIPANTS,
665
+ {
666
+ participants: {},
667
+ recordingId: '1',
668
+ selfIdentity: '123',
669
+ selfId: '2',
670
+ hostId: '3',
671
+ isReplace: true,
672
+ }
673
+ );
674
+ });
675
+
461
676
  it('should update the deltaParticipants object', () => {
462
677
  const prev = locusInfo.deltaParticipants;
463
678
 
@@ -664,6 +879,122 @@ describe('plugin-meetings', () => {
664
879
  );
665
880
  });
666
881
 
882
+ describe('SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED', () => {
883
+ it('should emit event when video muted on entry', () => {
884
+ // usually "previous self" is just undefined when we get first self from locus
885
+ locusInfo.self = undefined;
886
+ const selfWithMutedByOthers = cloneDeep(self);
887
+
888
+ // remoteVideoMuted
889
+ selfWithMutedByOthers.controls.video.muted = true;
890
+
891
+ locusInfo.webex.internal.device.url = self.deviceUrl;
892
+ locusInfo.emitScoped = sinon.stub();
893
+ locusInfo.updateSelf(selfWithMutedByOthers, []);
894
+
895
+ assert.calledWith(
896
+ locusInfo.emitScoped,
897
+ {
898
+ file: 'locus-info',
899
+ function: 'updateSelf',
900
+ },
901
+ LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED,
902
+ {muted: true}
903
+ );
904
+
905
+ // but sometimes "previous self" is defined, but without controls.audio.muted, so we test this here:
906
+ locusInfo.self = cloneDeep(self);
907
+ locusInfo.self.controls.video = {};
908
+
909
+ locusInfo.updateSelf(selfWithMutedByOthers, []);
910
+ assert.calledWith(
911
+ locusInfo.emitScoped,
912
+ {
913
+ file: 'locus-info',
914
+ function: 'updateSelf',
915
+ },
916
+ LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED,
917
+ {muted: true}
918
+ );
919
+ });
920
+
921
+ it('should not emit event when not muted on entry', () => {
922
+ locusInfo.self = undefined;
923
+ const selfWithMutedByOthersFalse = cloneDeep(self);
924
+
925
+ selfWithMutedByOthersFalse.controls.video.muted = false;
926
+
927
+ locusInfo.webex.internal.device.url = self.deviceUrl;
928
+ locusInfo.emitScoped = sinon.stub();
929
+ locusInfo.updateSelf(selfWithMutedByOthersFalse, []);
930
+
931
+ // we might get some calls to emitScoped, but we need to check that none of them are for SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED
932
+ locusInfo.emitScoped.getCalls().forEach((x) => {
933
+ assert.notEqual(x.args[1], LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED);
934
+ });
935
+ });
936
+
937
+ it('should emit event when remoteVideoMuted changed', () => {
938
+ locusInfo.self = self;
939
+ const selfWithMutedByOthers = cloneDeep(self);
940
+
941
+ selfWithMutedByOthers.controls.video.muted = true;
942
+
943
+ locusInfo.webex.internal.device.url = self.deviceUrl;
944
+ locusInfo.emitScoped = sinon.stub();
945
+ locusInfo.updateSelf(selfWithMutedByOthers, []);
946
+
947
+ assert.calledWith(
948
+ locusInfo.emitScoped,
949
+ {
950
+ file: 'locus-info',
951
+ function: 'updateSelf',
952
+ },
953
+ LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED,
954
+ {muted: true}
955
+ );
956
+ });
957
+ });
958
+
959
+ it('should trigger SELF_MEETING_BREAKOUTS_CHANGED when breakouts changed', () => {
960
+ locusInfo.self = self;
961
+ const selfWithBreakoutsChanged = cloneDeep(self);
962
+
963
+ selfWithBreakoutsChanged.controls.breakout.sessions.active[0].name = 'new name';
964
+
965
+ locusInfo.emitScoped = sinon.stub();
966
+ locusInfo.updateSelf(selfWithBreakoutsChanged, []);
967
+
968
+ assert.calledWith(
969
+ locusInfo.emitScoped,
970
+ {
971
+ file: 'locus-info',
972
+ function: 'updateSelf',
973
+ },
974
+ LOCUSINFO.EVENTS.SELF_MEETING_BREAKOUTS_CHANGED,
975
+ {
976
+ breakoutSessions: {
977
+ active: [
978
+ {
979
+ name: 'new name',
980
+ groupId: '0e73abb8-5584-49d8-be8d-806d2a8247ca',
981
+ sessionId: '1cf41ab1-2e57-4d95-b7e9-5613acddfb0f',
982
+ sessionType: 'BREAKOUT',
983
+ },
984
+ ],
985
+ allowed: [
986
+ {
987
+ name: 'Breakout session 2',
988
+ groupId: '0e73abb8-5584-49d8-be8d-806d2a8247ca',
989
+ sessionId: '1cf41ab1-2e57-4d95-b7e9-5613acddfb0f',
990
+ sessionType: 'BREAKOUT',
991
+ },
992
+ ],
993
+ },
994
+ }
995
+ );
996
+ });
997
+
667
998
  it('should trigger SELF_REMOTE_MUTE_STATUS_UPDATED if muted and disallowUnmute changed', () => {
668
999
  locusInfo.self = self;
669
1000
  const selfWithMutedByOthersAndDissalowUnmute = cloneDeep(self);
@@ -735,6 +1066,7 @@ describe('plugin-meetings', () => {
735
1066
  const selfWithRequestedToUnmute = cloneDeep(self);
736
1067
 
737
1068
  selfWithRequestedToUnmute.controls.audio.requestedToUnmute = true;
1069
+ selfWithRequestedToUnmute.controls.audio.lastModifiedRequestedToUnmute = '2023-06-16T19:25:04.369Z';
738
1070
 
739
1071
  locusInfo.webex.internal.device.url = self.deviceUrl;
740
1072
  locusInfo.emitScoped = sinon.stub();
@@ -889,6 +1221,88 @@ describe('plugin-meetings', () => {
889
1221
  {isSharingBlocked: true}
890
1222
  );
891
1223
  });
1224
+
1225
+ it('should trigger SELF_ROLES_CHANGED if self roles changed', () => {
1226
+ locusInfo.self = self;
1227
+ locusInfo.emitScoped = sinon.stub();
1228
+ const sampleNewSelf = cloneDeep(self);
1229
+ sampleNewSelf.controls.role.roles = [{type: 'COHOST', hasRole: true}];
1230
+
1231
+ locusInfo.updateSelf(sampleNewSelf, []);
1232
+
1233
+ assert.calledWith(
1234
+ locusInfo.emitScoped,
1235
+ {
1236
+ file: 'locus-info',
1237
+ function: 'updateSelf',
1238
+ },
1239
+ LOCUSINFO.EVENTS.SELF_ROLES_CHANGED,
1240
+ {oldRoles: ['PRESENTER'], newRoles: ['COHOST']}
1241
+ );
1242
+ });
1243
+
1244
+ it('should not trigger SELF_ROLES_CHANGED if self roles not changed', () => {
1245
+ locusInfo.self = self;
1246
+ locusInfo.emitScoped = sinon.stub();
1247
+ const sampleNewSelf = cloneDeep(self);
1248
+ sampleNewSelf.controls.role.roles = [{type: 'PRESENTER', hasRole: true}];
1249
+
1250
+ locusInfo.updateSelf(sampleNewSelf, []);
1251
+
1252
+ assert.neverCalledWith(
1253
+ locusInfo.emitScoped,
1254
+ {
1255
+ file: 'locus-info',
1256
+ function: 'updateSelf',
1257
+ },
1258
+ LOCUSINFO.EVENTS.SELF_ROLES_CHANGED,
1259
+ {oldRoles: ['PRESENTER'], newRoles: ['PRESENTER']}
1260
+ );
1261
+ });
1262
+
1263
+ it('should trigger SELF_MEETING_INTERPRETATION_CHANGED if self interpretation info changed', () => {
1264
+ locusInfo.self = self;
1265
+ locusInfo.emitScoped = sinon.stub();
1266
+ const sampleNewSelf = cloneDeep(self);
1267
+ sampleNewSelf.controls.interpretation.targetLanguage = 'it';
1268
+
1269
+ locusInfo.updateSelf(sampleNewSelf, []);
1270
+
1271
+ assert.calledWith(
1272
+ locusInfo.emitScoped,
1273
+ {
1274
+ file: 'locus-info',
1275
+ function: 'updateSelf',
1276
+ },
1277
+ LOCUSINFO.EVENTS.SELF_MEETING_INTERPRETATION_CHANGED,
1278
+ {
1279
+ interpretation: sampleNewSelf.controls.interpretation,
1280
+ selfParticipantId: self.id,
1281
+ }
1282
+ );
1283
+ });
1284
+
1285
+ it('should not trigger SELF_MEETING_INTERPRETATION_CHANGED if self interpretation info not changed', () => {
1286
+ locusInfo.self = self;
1287
+ locusInfo.emitScoped = sinon.stub();
1288
+ const sampleNewSelf = cloneDeep(self);
1289
+ sampleNewSelf.controls.interpretation.targetLanguage = 'cn'; // same with previous one
1290
+
1291
+ locusInfo.updateSelf(sampleNewSelf, []);
1292
+
1293
+ assert.neverCalledWith(
1294
+ locusInfo.emitScoped,
1295
+ {
1296
+ file: 'locus-info',
1297
+ function: 'updateSelf',
1298
+ },
1299
+ LOCUSINFO.EVENTS.SELF_MEETING_INTERPRETATION_CHANGED,
1300
+ {
1301
+ interpretation: sampleNewSelf.controls.interpretation,
1302
+ selfParticipantId: self.id,
1303
+ }
1304
+ );
1305
+ });
892
1306
  });
893
1307
 
894
1308
  describe('#updateMeetingInfo', () => {
@@ -962,7 +1376,7 @@ describe('plugin-meetings', () => {
962
1376
  function: 'updateMeetingInfo',
963
1377
  },
964
1378
  LOCUSINFO.EVENTS.MEETING_INFO_UPDATED,
965
- {info: locusInfo.parsedLocus.info, self},
1379
+ {info: locusInfo.parsedLocus.info, self},
966
1380
  ];
967
1381
 
968
1382
  if (expected) {
@@ -973,6 +1387,25 @@ describe('plugin-meetings', () => {
973
1387
  locusInfo.emitScoped.resetHistory();
974
1388
  };
975
1389
 
1390
+ const checkMeetingInfoUpdatedCalledForRoles = (expected) => {
1391
+ const expectedArgs = [
1392
+ locusInfo.emitScoped,
1393
+ {
1394
+ file: 'locus-info',
1395
+ function: 'updateMeetingInfo',
1396
+ },
1397
+ LOCUSINFO.EVENTS.MEETING_INFO_UPDATED,
1398
+ ];
1399
+
1400
+ if (expected) {
1401
+ assert.calledWith(...expectedArgs);
1402
+ } else {
1403
+ assert.neverCalledWith(...expectedArgs);
1404
+ }
1405
+ locusInfo.emitScoped.resetHistory();
1406
+ };
1407
+
1408
+
976
1409
  it('emits MEETING_INFO_UPDATED if the info changes', () => {
977
1410
  const initialInfo = cloneDeep(meetingInfo);
978
1411
 
@@ -998,6 +1431,16 @@ describe('plugin-meetings', () => {
998
1431
 
999
1432
  // since the info is the same it should not call trigger the event
1000
1433
  checkMeetingInfoUpdatedCalled(false);
1434
+
1435
+ // update it with the same info, but roles changed
1436
+ const updateSelf = cloneDeep(self);
1437
+ updateSelf?.controls?.role?.roles.push({
1438
+ type: 'COHOST',
1439
+ hasRole: true,
1440
+ });
1441
+ locusInfo.updateMeetingInfo(newInfo, updateSelf);
1442
+ // since the info is the same but roles changed, it should call trigger the event
1443
+ checkMeetingInfoUpdatedCalledForRoles(true);
1001
1444
  });
1002
1445
 
1003
1446
  it('gets roles from self if available', () => {
@@ -1103,6 +1546,7 @@ describe('plugin-meetings', () => {
1103
1546
  fakeLocus = {
1104
1547
  meeting: true,
1105
1548
  participants: true,
1549
+ url: 'newLocusUrl',
1106
1550
  };
1107
1551
  });
1108
1552
 
@@ -1147,6 +1591,55 @@ describe('plugin-meetings', () => {
1147
1591
  assert.isFunction(locusParser.onDeltaAction);
1148
1592
  });
1149
1593
 
1594
+ it('#updateLocusInfo ignores breakout LEFT message', () => {
1595
+ const newLocus = {
1596
+ self: {
1597
+ reason: 'MOVED',
1598
+ state: 'LEFT',
1599
+ },
1600
+ };
1601
+
1602
+ locusInfo.updateControls = sinon.stub();
1603
+ locusInfo.updateConversationUrl = sinon.stub();
1604
+ locusInfo.updateCreated = sinon.stub();
1605
+ locusInfo.updateFullState = sinon.stub();
1606
+ locusInfo.updateHostInfo = sinon.stub();
1607
+ locusInfo.updateMeetingInfo = sinon.stub();
1608
+ locusInfo.updateMediaShares = sinon.stub();
1609
+ locusInfo.updateParticipantsUrl = sinon.stub();
1610
+ locusInfo.updateReplace = sinon.stub();
1611
+ locusInfo.updateSelf = sinon.stub();
1612
+ locusInfo.updateLocusUrl = sinon.stub();
1613
+ locusInfo.updateAclUrl = sinon.stub();
1614
+ locusInfo.updateBasequence = sinon.stub();
1615
+ locusInfo.updateSequence = sinon.stub();
1616
+ locusInfo.updateMemberShip = sinon.stub();
1617
+ locusInfo.updateIdentifiers = sinon.stub();
1618
+ locusInfo.updateEmbeddedApps = sinon.stub();
1619
+ locusInfo.compareAndUpdate = sinon.stub();
1620
+
1621
+ locusInfo.updateLocusInfo(newLocus);
1622
+
1623
+ assert.notCalled(locusInfo.updateControls);
1624
+ assert.notCalled(locusInfo.updateConversationUrl);
1625
+ assert.notCalled(locusInfo.updateCreated);
1626
+ assert.notCalled(locusInfo.updateFullState);
1627
+ assert.notCalled(locusInfo.updateHostInfo);
1628
+ assert.notCalled(locusInfo.updateMeetingInfo);
1629
+ assert.notCalled(locusInfo.updateMediaShares);
1630
+ assert.notCalled(locusInfo.updateParticipantsUrl);
1631
+ assert.notCalled(locusInfo.updateReplace);
1632
+ assert.notCalled(locusInfo.updateSelf);
1633
+ assert.notCalled(locusInfo.updateLocusUrl);
1634
+ assert.notCalled(locusInfo.updateAclUrl);
1635
+ assert.notCalled(locusInfo.updateBasequence);
1636
+ assert.notCalled(locusInfo.updateSequence);
1637
+ assert.notCalled(locusInfo.updateMemberShip);
1638
+ assert.notCalled(locusInfo.updateIdentifiers);
1639
+ assert.notCalled(locusInfo.updateEmbeddedApps);
1640
+ assert.notCalled(locusInfo.compareAndUpdate);
1641
+ });
1642
+
1150
1643
  it('onFullLocus() updates the working-copy of locus parser', () => {
1151
1644
  const eventType = 'fakeEvent';
1152
1645
 
@@ -1196,12 +1689,18 @@ describe('plugin-meetings', () => {
1196
1689
  locusInfo: {
1197
1690
  onFullLocus: sandbox.stub(),
1198
1691
  },
1692
+ locusUrl: 'oldLocusUrl',
1199
1693
  };
1200
1694
 
1201
1695
  locusInfo.locusParser.resume = sandbox.stub();
1202
1696
  locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
1203
1697
 
1204
- assert.calledOnce(meeting.meetingRequest.getFullLocus);
1698
+ assert.calledOnceWithExactly(meeting.meetingRequest.getFullLocus,
1699
+ {
1700
+ desync: true,
1701
+ locusUrl: 'newLocusUrl',
1702
+ }
1703
+ );
1205
1704
  });
1206
1705
 
1207
1706
  it('getFullLocus handles DESYNC action correctly', () => {
@@ -1226,6 +1725,187 @@ describe('plugin-meetings', () => {
1226
1725
  assert.calledOnce(locusInfo.locusParser.resume);
1227
1726
  });
1228
1727
  });
1728
+
1729
+ it('onDeltaLocus handle delta data', () => {
1730
+ fakeLocus.participants = {};
1731
+ const fakeBreakout = {
1732
+ sessionId: 'sessionId',
1733
+ groupId: 'groupId',
1734
+ };
1735
+
1736
+ fakeLocus.controls = {
1737
+ breakout: fakeBreakout
1738
+ };
1739
+ locusInfo.controls = {
1740
+ breakout: {
1741
+ sessionId: 'sessionId',
1742
+ groupId: 'groupId',
1743
+ }
1744
+ }
1745
+ locusInfo.updateParticipants = sinon.stub();
1746
+ locusInfo.onDeltaLocus(fakeLocus);
1747
+ assert.calledWith(locusInfo.updateParticipants, {}, false);
1748
+
1749
+ fakeLocus.controls.breakout.sessionId = 'sessionId2';
1750
+ locusInfo.onDeltaLocus(fakeLocus);
1751
+ assert.calledWith(locusInfo.updateParticipants, {}, true);
1752
+ });
1753
+ });
1754
+
1755
+ describe('#updateLocusCache', () => {
1756
+ it('cache it if income locus is main session locus', () => {
1757
+ const locus = {url: 'url'};
1758
+ locusInfo.mainSessionLocusCache = null;
1759
+ locusInfo.updateLocusCache(locus);
1760
+
1761
+ assert.deepEqual(locusInfo.mainSessionLocusCache, locus);
1762
+ });
1763
+
1764
+ it('not cache it if income locus is breakout session locus', () => {
1765
+ const locus = {url: 'url', controls: {breakout: {sessionType: 'BREAKOUT'}}};
1766
+ locusInfo.mainSessionLocusCache = null;
1767
+ locusInfo.updateLocusCache(locus);
1768
+
1769
+ assert.isNull(locusInfo.mainSessionLocusCache);
1770
+ });
1771
+ });
1772
+
1773
+ describe('#getTheLocusToUpdate', () => {
1774
+ it('return the cache locus if return to main session', () => {
1775
+ locusInfo.mainSessionLocusCache = {url: 'url'};
1776
+ locusInfo.controls = {
1777
+ breakout: {
1778
+ sessionType: 'BREAKOUT'
1779
+ }
1780
+ }
1781
+ const newLocus = {
1782
+ controls: {
1783
+ breakout: {
1784
+ sessionType: 'MAIN',
1785
+ },
1786
+ },
1787
+ };
1788
+
1789
+ assert.deepEqual(locusInfo.getTheLocusToUpdate(newLocus), {url: 'url'});
1790
+ });
1791
+
1792
+ it('return the new locus if return to main session but no cache', () => {
1793
+ locusInfo.mainSessionLocusCache = null;
1794
+ locusInfo.controls = {
1795
+ breakout: {
1796
+ sessionType: 'BREAKOUT'
1797
+ }
1798
+ }
1799
+ const newLocus = {
1800
+ controls: {
1801
+ breakout: {
1802
+ sessionType: 'MAIN',
1803
+ },
1804
+ },
1805
+ };
1806
+
1807
+ assert.deepEqual(locusInfo.getTheLocusToUpdate(newLocus), newLocus);
1808
+ });
1809
+
1810
+ it('return the new locus if not return to main session', () => {
1811
+ locusInfo.mainSessionLocusCache = {url: 'url'};
1812
+ locusInfo.controls = {
1813
+ breakout: {
1814
+ sessionType: 'MAIN'
1815
+ }
1816
+ }
1817
+ const newLocus = {
1818
+ controls: {
1819
+ breakout: {
1820
+ sessionType: 'BREAKOUT',
1821
+ },
1822
+ },
1823
+ };
1824
+
1825
+ assert.deepEqual(locusInfo.getTheLocusToUpdate(newLocus), newLocus);
1826
+ });
1827
+ });
1828
+
1829
+ describe('#mergeParticipants', () => {
1830
+ let participants;
1831
+ let sourceParticipants;
1832
+ beforeEach(() => {
1833
+ participants = [{id: '111', status: 'JOINED'}, {id: '222'}];
1834
+ sourceParticipants = [{id: '111', status: 'LEFT'}, {id: '333'}];
1835
+ });
1836
+
1837
+ it('merge the participants, replace it by id if exist in old array', () => {
1838
+ const result = locusInfo.mergeParticipants(participants, sourceParticipants);
1839
+ assert.deepEqual(result, [{id: '111', status: 'LEFT'}, {id: '222'}, {id: '333'}]);
1840
+ });
1841
+
1842
+ it('return new participants if previous participants is empty', () => {
1843
+ const result = locusInfo.mergeParticipants([], sourceParticipants);
1844
+ assert.deepEqual(result, sourceParticipants);
1845
+ });
1846
+
1847
+ it('return new participants if previous participants is null/undefined', () => {
1848
+ let result = locusInfo.mergeParticipants(null, sourceParticipants);
1849
+ assert.deepEqual(result, sourceParticipants);
1850
+
1851
+ result = locusInfo.mergeParticipants(undefined, sourceParticipants);
1852
+ assert.deepEqual(result, sourceParticipants);
1853
+ });
1854
+
1855
+ it('return previous participants if new participants is empty', () => {
1856
+ const result = locusInfo.mergeParticipants(participants, []);
1857
+ assert.deepEqual(result, participants);
1858
+ });
1859
+
1860
+ it('return previous participants if new participants is null/undefined', () => {
1861
+ let result = locusInfo.mergeParticipants(participants, null);
1862
+ assert.deepEqual(result, participants);
1863
+
1864
+ result = locusInfo.mergeParticipants(participants, undefined);
1865
+ assert.deepEqual(result, participants);
1866
+ });
1867
+ });
1868
+
1869
+ describe('#updateMainSessionLocusCache', () => {
1870
+ let cachedLocus;
1871
+ let newLocus;
1872
+ beforeEach(() => {
1873
+ cachedLocus = {controls: {}, participants: [], info: {webExMeetingId: 'testId1', topic: 'test'}};
1874
+ newLocus = {self: {}, participants: [{id: '111'}], info: {testId: 'testId2', webExMeetingName: 'hello'}};
1875
+ });
1876
+ it('shallow merge new locus into cache', () => {
1877
+ locusInfo.mainSessionLocusCache = cachedLocus;
1878
+ locusInfo.updateMainSessionLocusCache(newLocus);
1879
+
1880
+ assert.deepEqual(locusInfo.mainSessionLocusCache, {
1881
+ controls: {},
1882
+ participants: [{id: '111'}],
1883
+ info: {testId: 'testId2', webExMeetingName: 'hello'},
1884
+ self: {},
1885
+ });
1886
+ });
1887
+
1888
+ it('cache new locus if no cache before', () => {
1889
+ locusInfo.mainSessionLocusCache = null;
1890
+ locusInfo.updateMainSessionLocusCache(newLocus);
1891
+
1892
+ assert.deepEqual(locusInfo.mainSessionLocusCache, newLocus);
1893
+ });
1894
+
1895
+ it('do nothing if new locus is null', () => {
1896
+ locusInfo.mainSessionLocusCache = cachedLocus;
1897
+ locusInfo.updateMainSessionLocusCache(null);
1898
+
1899
+ assert.deepEqual(locusInfo.mainSessionLocusCache, cachedLocus);
1900
+ });
1901
+ });
1902
+
1903
+ describe('#clearMainSessionLocusCache', () => {
1904
+ it('clear main session locus cache', () => {
1905
+ locusInfo.mainSessionLocusCache = {controls: {}};
1906
+ locusInfo.clearMainSessionLocusCache();
1907
+ assert.isNull(locusInfo.mainSessionLocusCache);
1908
+ })
1229
1909
  });
1230
1910
 
1231
1911
  describe('#handleOneonOneEvent', () => {
@@ -1268,5 +1948,113 @@ describe('plugin-meetings', () => {
1268
1948
  );
1269
1949
  });
1270
1950
  });
1951
+
1952
+ describe('#isMeetingActive', () => {
1953
+ it('sends client event correctly for state = inactive', () => {
1954
+ locusInfo.parsedLocus = {
1955
+ fullState: {
1956
+ type: _CALL_,
1957
+ },
1958
+ };
1959
+
1960
+ locusInfo.fullState = {
1961
+ state: LOCUS.STATE.INACTIVE,
1962
+ };
1963
+
1964
+ locusInfo.isMeetingActive();
1965
+
1966
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
1967
+ name: 'client.call.remote-ended',
1968
+ options: {
1969
+ meetingId: locusInfo.meetingId,
1970
+ },
1971
+ });
1972
+ });
1973
+
1974
+ it('sends client event correctly for state = PARTNER_LEFT', () => {
1975
+ locusInfo.getLocusPartner = sinon.stub().returns({state: MEETING_STATE.STATES.LEFT})
1976
+ locusInfo.parsedLocus = {
1977
+ fullState: {
1978
+ type: _CALL_,
1979
+ },
1980
+ self: {
1981
+ state: MEETING_STATE.STATES.DECLINED,
1982
+ },
1983
+ };
1984
+ locusInfo.isMeetingActive();
1985
+
1986
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
1987
+ name: 'client.call.remote-ended',
1988
+ options: {
1989
+ meetingId: locusInfo.meetingId,
1990
+ },
1991
+ });
1992
+ });
1993
+
1994
+ it('sends client event correctly for state = SELF_LEFT', () => {
1995
+ locusInfo.getLocusPartner = sinon.stub().returns({state: MEETING_STATE.STATES.LEFT})
1996
+ locusInfo.parsedLocus = {
1997
+ fullState: {
1998
+ type: _CALL_,
1999
+ },
2000
+ self: {
2001
+ state: MEETING_STATE.STATES.LEFT,
2002
+ },
2003
+ };
2004
+
2005
+ locusInfo.isMeetingActive();
2006
+
2007
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
2008
+ name: 'client.call.remote-ended',
2009
+ options: {
2010
+ meetingId: locusInfo.meetingId,
2011
+ },
2012
+ });
2013
+ });
2014
+
2015
+ it('sends client event correctly for state = MEETING_INACTIVE_TERMINATING', () => {
2016
+ locusInfo.getLocusPartner = sinon.stub().returns({state: MEETING_STATE.STATES.LEFT})
2017
+ locusInfo.parsedLocus = {
2018
+ fullState: {
2019
+ type: _MEETING_,
2020
+ },
2021
+ };
2022
+
2023
+ locusInfo.fullState = {
2024
+ state: LOCUS.STATE.INACTIVE,
2025
+ };
2026
+
2027
+ locusInfo.isMeetingActive();
2028
+
2029
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
2030
+ name: 'client.call.remote-ended',
2031
+ options: {
2032
+ meetingId: locusInfo.meetingId,
2033
+ },
2034
+ });
2035
+ });
2036
+
2037
+ it('sends client event correctly for state = FULLSTATE_REMOVED', () => {
2038
+ locusInfo.getLocusPartner = sinon.stub().returns({state: MEETING_STATE.STATES.LEFT})
2039
+ locusInfo.parsedLocus = {
2040
+ fullState: {
2041
+ type: _MEETING_,
2042
+ },
2043
+ };
2044
+
2045
+ locusInfo.fullState = {
2046
+ removed: true
2047
+ };
2048
+
2049
+ locusInfo.isMeetingActive();
2050
+
2051
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
2052
+ name: 'client.call.remote-ended',
2053
+ options: {
2054
+ meetingId: locusInfo.meetingId,
2055
+ },
2056
+ });
2057
+ });
2058
+ });
1271
2059
  });
1272
2060
  });