@webex/plugin-meetings 3.0.0-beta.16 → 3.0.0-beta.161

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 (424) hide show
  1. package/README.md +45 -1
  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 +212 -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 +43 -0
  15. package/dist/breakouts/events.js.map +1 -0
  16. package/dist/breakouts/index.js +1046 -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 +175 -26
  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 +77 -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 +317 -24
  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 +39 -134
  59. package/dist/media/index.js.map +1 -1
  60. package/dist/media/properties.js +19 -97
  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 +79 -1
  65. package/dist/meeting/in-meeting-actions.js.map +1 -1
  66. package/dist/meeting/index.js +2349 -2178
  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 +444 -443
  76. package/dist/meeting/util.js.map +1 -1
  77. package/dist/meeting-info/meeting-info-v2.js +157 -49
  78. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  79. package/dist/meeting-info/utilv2.js +20 -5
  80. package/dist/meeting-info/utilv2.js.map +1 -1
  81. package/dist/meetings/collection.js +22 -0
  82. package/dist/meetings/collection.js.map +1 -1
  83. package/dist/meetings/index.js +365 -73
  84. package/dist/meetings/index.js.map +1 -1
  85. package/dist/meetings/meetings.types.js +7 -0
  86. package/dist/meetings/meetings.types.js.map +1 -0
  87. package/dist/meetings/request.js +16 -12
  88. package/dist/meetings/request.js.map +1 -1
  89. package/dist/meetings/util.js +88 -1
  90. package/dist/meetings/util.js.map +1 -1
  91. package/dist/member/index.js +43 -0
  92. package/dist/member/index.js.map +1 -1
  93. package/dist/member/types.js +15 -0
  94. package/dist/member/types.js.map +1 -0
  95. package/dist/member/util.js +97 -3
  96. package/dist/member/util.js.map +1 -1
  97. package/dist/members/collection.js +10 -0
  98. package/dist/members/collection.js.map +1 -1
  99. package/dist/members/index.js +94 -11
  100. package/dist/members/index.js.map +1 -1
  101. package/dist/members/request.js +109 -39
  102. package/dist/members/request.js.map +1 -1
  103. package/dist/members/types.js +15 -0
  104. package/dist/members/types.js.map +1 -0
  105. package/dist/members/util.js +316 -233
  106. package/dist/members/util.js.map +1 -1
  107. package/dist/metrics/config.js +50 -14
  108. package/dist/metrics/config.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 +48 -29
  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 +190 -145
  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 +343 -0
  142. package/dist/recording-controller/index.js.map +1 -0
  143. package/dist/recording-controller/util.js +63 -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 +127 -92
  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 +2 -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 +987 -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 +86 -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 +1524 -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 +75 -0
  222. package/dist/types/meeting-info/collection.d.ts +20 -0
  223. package/dist/types/meeting-info/index.d.ts +57 -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 +364 -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/config.d.ts +195 -0
  242. package/dist/types/metrics/constants.d.ts +55 -0
  243. package/dist/types/metrics/index.d.ts +169 -0
  244. package/dist/types/multistream/mediaRequestManager.d.ts +118 -0
  245. package/dist/types/multistream/receiveSlot.d.ts +68 -0
  246. package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
  247. package/dist/types/multistream/remoteMedia.d.ts +72 -0
  248. package/dist/types/multistream/remoteMediaGroup.d.ts +47 -0
  249. package/dist/types/multistream/remoteMediaManager.d.ts +277 -0
  250. package/dist/types/networkQualityMonitor/index.d.ts +70 -0
  251. package/dist/types/personal-meeting-room/index.d.ts +47 -0
  252. package/dist/types/personal-meeting-room/request.d.ts +14 -0
  253. package/dist/types/personal-meeting-room/util.d.ts +2 -0
  254. package/dist/types/reachability/index.d.ts +152 -0
  255. package/dist/types/reachability/request.d.ts +37 -0
  256. package/dist/types/reactions/constants.d.ts +3 -0
  257. package/dist/types/reactions/reactions.d.ts +4 -0
  258. package/dist/types/reactions/reactions.type.d.ts +52 -0
  259. package/dist/types/reconnection-manager/index.d.ts +126 -0
  260. package/dist/types/recording-controller/enums.d.ts +7 -0
  261. package/dist/types/recording-controller/index.d.ts +193 -0
  262. package/dist/types/recording-controller/util.d.ts +13 -0
  263. package/dist/types/roap/index.d.ts +77 -0
  264. package/dist/types/roap/request.d.ts +36 -0
  265. package/dist/types/roap/turnDiscovery.d.ts +91 -0
  266. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  267. package/dist/types/statsAnalyzer/index.d.ts +200 -0
  268. package/dist/types/statsAnalyzer/mqaUtil.d.ts +24 -0
  269. package/dist/types/transcription/index.d.ts +64 -0
  270. package/package.json +28 -21
  271. package/src/annotation/annotation.types.ts +52 -0
  272. package/src/annotation/constants.ts +36 -0
  273. package/src/annotation/index.ts +343 -0
  274. package/src/breakouts/README.md +220 -0
  275. package/src/breakouts/breakout.ts +180 -0
  276. package/src/breakouts/collection.ts +19 -0
  277. package/src/breakouts/edit-lock-error.ts +25 -0
  278. package/src/breakouts/events.ts +37 -0
  279. package/src/breakouts/index.ts +921 -0
  280. package/src/breakouts/request.ts +55 -0
  281. package/src/breakouts/utils.ts +57 -0
  282. package/src/common/errors/webex-errors.ts +6 -2
  283. package/src/common/logs/logger-proxy.ts +1 -1
  284. package/src/config.ts +5 -7
  285. package/src/constants.ts +165 -20
  286. package/src/controls-options-manager/constants.ts +5 -0
  287. package/src/controls-options-manager/enums.ts +18 -0
  288. package/src/controls-options-manager/index.ts +278 -0
  289. package/src/controls-options-manager/types.ts +59 -0
  290. package/src/controls-options-manager/util.ts +286 -0
  291. package/src/index.ts +34 -0
  292. package/src/interpretation/README.md +51 -0
  293. package/src/interpretation/collection.ts +19 -0
  294. package/src/interpretation/index.ts +182 -0
  295. package/src/interpretation/siLanguage.ts +18 -0
  296. package/src/locus-info/controlsUtils.ts +110 -0
  297. package/src/locus-info/index.ts +339 -21
  298. package/src/locus-info/mediaSharesUtils.ts +48 -0
  299. package/src/locus-info/parser.ts +2 -1
  300. package/src/locus-info/selfUtils.ts +86 -2
  301. package/src/media/index.ts +70 -142
  302. package/src/media/properties.ts +41 -104
  303. package/src/mediaQualityMetrics/config.ts +379 -377
  304. package/src/meeting/in-meeting-actions.ts +156 -0
  305. package/src/meeting/index.ts +1779 -1741
  306. package/src/meeting/locusMediaRequest.ts +309 -0
  307. package/src/meeting/muteState.ts +228 -132
  308. package/src/meeting/request.ts +100 -91
  309. package/src/meeting/request.type.ts +2 -0
  310. package/src/meeting/util.ts +422 -421
  311. package/src/meeting-info/meeting-info-v2.ts +134 -13
  312. package/src/meeting-info/utilv2.ts +13 -3
  313. package/src/meetings/collection.ts +20 -0
  314. package/src/meetings/index.ts +385 -83
  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/config.ts +49 -10
  327. package/src/metrics/constants.ts +2 -4
  328. package/src/metrics/index.ts +43 -27
  329. package/src/multistream/mediaRequestManager.ts +337 -63
  330. package/src/multistream/receiveSlot.ts +68 -26
  331. package/src/multistream/receiveSlotManager.ts +61 -38
  332. package/src/multistream/remoteMedia.ts +29 -3
  333. package/src/multistream/remoteMediaGroup.ts +61 -2
  334. package/src/multistream/remoteMediaManager.ts +260 -66
  335. package/src/networkQualityMonitor/index.ts +6 -6
  336. package/src/reachability/index.ts +75 -25
  337. package/src/reachability/request.ts +10 -5
  338. package/src/reactions/constants.ts +4 -0
  339. package/src/reactions/reactions.ts +4 -4
  340. package/src/reactions/reactions.type.ts +28 -3
  341. package/src/reconnection-manager/index.ts +53 -32
  342. package/src/recording-controller/enums.ts +8 -0
  343. package/src/recording-controller/index.ts +315 -0
  344. package/src/recording-controller/util.ts +58 -0
  345. package/src/roap/index.ts +21 -30
  346. package/src/roap/request.ts +51 -52
  347. package/src/roap/turnDiscovery.ts +51 -27
  348. package/src/statsAnalyzer/global.ts +1 -94
  349. package/src/statsAnalyzer/index.ts +380 -390
  350. package/src/statsAnalyzer/mqaUtil.ts +106 -99
  351. package/test/integration/spec/converged-space-meetings.js +233 -0
  352. package/test/integration/spec/journey.js +331 -254
  353. package/test/integration/spec/space-meeting.js +77 -4
  354. package/test/unit/spec/annotation/index.ts +436 -0
  355. package/test/unit/spec/breakouts/breakout.ts +233 -0
  356. package/test/unit/spec/breakouts/collection.ts +15 -0
  357. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  358. package/test/unit/spec/breakouts/events.ts +77 -0
  359. package/test/unit/spec/breakouts/index.ts +1790 -0
  360. package/test/unit/spec/breakouts/request.ts +104 -0
  361. package/test/unit/spec/breakouts/utils.js +72 -0
  362. package/test/unit/spec/controls-options-manager/index.js +287 -0
  363. package/test/unit/spec/controls-options-manager/util.js +518 -0
  364. package/test/unit/spec/fixture/locus.js +1 -0
  365. package/test/unit/spec/interpretation/collection.ts +15 -0
  366. package/test/unit/spec/interpretation/index.ts +329 -0
  367. package/test/unit/spec/interpretation/siLanguage.ts +26 -0
  368. package/test/unit/spec/locus-info/controlsUtils.js +323 -30
  369. package/test/unit/spec/locus-info/index.js +680 -4
  370. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  371. package/test/unit/spec/locus-info/selfConstant.js +48 -0
  372. package/test/unit/spec/locus-info/selfUtils.js +275 -0
  373. package/test/unit/spec/media/index.ts +118 -22
  374. package/test/unit/spec/media/properties.ts +9 -9
  375. package/test/unit/spec/meeting/in-meeting-actions.ts +76 -0
  376. package/test/unit/spec/meeting/index.js +2695 -1513
  377. package/test/unit/spec/meeting/locusMediaRequest.ts +436 -0
  378. package/test/unit/spec/meeting/muteState.js +370 -208
  379. package/test/unit/spec/meeting/request.js +354 -42
  380. package/test/unit/spec/meeting/utils.js +270 -156
  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 +866 -120
  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 +98 -0
  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 +46 -13
  402. package/test/unit/spec/recording-controller/index.js +231 -0
  403. package/test/unit/spec/recording-controller/util.js +102 -0
  404. package/test/unit/spec/roap/index.ts +21 -51
  405. package/test/unit/spec/roap/request.ts +187 -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/multistream/multistreamMedia.js +0 -106
  419. package/dist/multistream/multistreamMedia.js.map +0 -1
  420. package/src/index.js +0 -15
  421. package/src/media/internal-media-core-wrapper.ts +0 -9
  422. package/src/meeting/effectsState.ts +0 -211
  423. package/src/multistream/multistreamMedia.ts +0 -93
  424. package/test/unit/spec/meeting/effectsState.js +0 -281
@@ -11,6 +11,7 @@ import sinon from 'sinon';
11
11
  import uuid from 'uuid';
12
12
  import StaticConfig from '@webex/plugin-meetings/src/common/config';
13
13
  import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
14
+ import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
14
15
  import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
15
16
  import Meeting from '@webex/plugin-meetings/src/meeting';
16
17
  import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
@@ -29,6 +30,11 @@ import {
29
30
  LOCUSINFO,
30
31
  EVENT_TRIGGERS,
31
32
  } from '../../../../src/constants';
33
+ import CaptchaError from '@webex/plugin-meetings/src/common/errors/captcha-error';
34
+ import { forEach } from 'lodash';
35
+ import PasswordError from '@webex/plugin-meetings/src/common/errors/password-error';
36
+ import PermissionError from '@webex/plugin-meetings/src/common/errors/permission';
37
+ import {NoiseReductionEffect,VirtualBackgroundEffect} from '@webex/media-helpers';
32
38
 
33
39
  describe('plugin-meetings', () => {
34
40
  const logger = {
@@ -60,6 +66,7 @@ describe('plugin-meetings', () => {
60
66
  let url1;
61
67
  let test1;
62
68
  let test2;
69
+ let locusInfo;
63
70
 
64
71
  describe('meetings index', () => {
65
72
  beforeEach(() => {
@@ -69,6 +76,10 @@ describe('plugin-meetings', () => {
69
76
  uri1 = `test-${uuid.v4()}@example.com`;
70
77
  test1 = `test-${uuid.v4()}`;
71
78
  test2 = `test2-${uuid.v4()}`;
79
+ locusInfo = {
80
+ parse: sinon.stub().returns(true),
81
+ updateMainSessionLocusCache: sinon.stub(),
82
+ };
72
83
  webex = new MockWebex({
73
84
  children: {
74
85
  device: Device,
@@ -107,6 +118,7 @@ describe('plugin-meetings', () => {
107
118
  });
108
119
 
109
120
  Object.assign(webex.internal, {
121
+ llm: {on: sinon.stub()},
110
122
  device: {
111
123
  deviceType: 'FAKE_DEVICE',
112
124
  register: sinon.stub().returns(Promise.resolve()),
@@ -150,6 +162,10 @@ describe('plugin-meetings', () => {
150
162
  webex.emit('ready');
151
163
  });
152
164
 
165
+ afterEach(() => {
166
+ sinon.restore();
167
+ });
168
+
153
169
  it('has a webex instance with a meetings property', () => {
154
170
  assert.exists(webex, 'webex was initialized with children');
155
171
  assert.exists(webex.meetings, 'meetings child was set up on the webex instance');
@@ -337,6 +353,100 @@ describe('plugin-meetings', () => {
337
353
  });
338
354
  });
339
355
 
356
+ describe('virtual background effect', () => {
357
+ beforeEach(() => {
358
+ webex.credentials = {
359
+ supertoken: {
360
+ access_token: "fake_token"
361
+ }
362
+ };
363
+ })
364
+
365
+ it('creates background effect', async () => {
366
+ const result = await webex.meetings.createVirtualBackgroundEffect();
367
+
368
+ assert.exists(result);
369
+ assert.instanceOf(result, VirtualBackgroundEffect);
370
+ assert.containsAllKeys(result, ['loadModel', 'isEnabled', 'isLoaded', 'options']);
371
+ assert.deepEqual(result.options, {
372
+ mode: 'BLUR',
373
+ blurStrength: 'STRONG',
374
+ generator: 'worker',
375
+ quality: 'LOW',
376
+ authToken: 'fake_token',
377
+ mirror: false
378
+ });
379
+ assert.exists(result.enable);
380
+ assert.exists(result.disable);
381
+ assert.exists(result.dispose);
382
+ });
383
+
384
+ it('creates background effect with custom options passed', async () => {
385
+ const effectOptions = {
386
+ generator: "local",
387
+ frameRate: 45,
388
+ mode: "IMAGE",
389
+ mirror: false,
390
+ quality: "HIGH",
391
+ blurStrength: "STRONG",
392
+ bgImageUrl: "https://test.webex.com/landscape.5a535788.jpg",
393
+ };
394
+
395
+ const result = await webex.meetings.createVirtualBackgroundEffect(effectOptions);
396
+
397
+ assert.exists(result);
398
+ assert.instanceOf(result, VirtualBackgroundEffect);
399
+ assert.containsAllKeys(result, ['loadModel', 'isEnabled', 'isLoaded', 'options']);
400
+ assert.deepEqual(result.options, {...effectOptions, authToken: "fake_token"});
401
+ assert.exists(result.enable);
402
+ assert.exists(result.disable);
403
+ assert.exists(result.dispose);
404
+ });
405
+ })
406
+
407
+ describe('noise reduction effect', () => {
408
+ beforeEach(() => {
409
+ webex.credentials = {
410
+ supertoken: {
411
+ access_token: "fake_token"
412
+ }
413
+ };
414
+ })
415
+
416
+ it('creates noise reduction effect', async () => {
417
+ const result = await webex.meetings.createNoiseReductionEffect({audioContext: {}});
418
+
419
+ assert.exists(result);
420
+ assert.instanceOf(result, NoiseReductionEffect);
421
+ assert.containsAllKeys(result, ['audioContext', 'isEnabled', 'isReady', 'options']);
422
+ assert.deepEqual(result.options, {
423
+ authToken: 'fake_token',
424
+ audioContext: {}
425
+ });
426
+ assert.exists(result.enable);
427
+ assert.exists(result.disable);
428
+ assert.exists(result.dispose);
429
+ });
430
+
431
+ it('creates noise reduction effect with custom options passed', async () => {
432
+ const effectOptions = {
433
+ audioContext: {},
434
+ mode: "WORKLET",
435
+ env: "prod"
436
+ };
437
+
438
+ const result = await webex.meetings.createNoiseReductionEffect(effectOptions);
439
+
440
+ assert.exists(result);
441
+ assert.instanceOf(result, NoiseReductionEffect);
442
+ assert.containsAllKeys(result, ['audioContext', 'isEnabled', 'isReady', 'options']);
443
+ assert.deepEqual(result.options, {...effectOptions, authToken: "fake_token"});
444
+ assert.exists(result.enable);
445
+ assert.exists(result.disable);
446
+ assert.exists(result.dispose);
447
+ });
448
+ })
449
+
340
450
  describe('gets', () => {
341
451
  describe('#getReachability', () => {
342
452
  it('should have #getReachability', () => {
@@ -442,21 +552,17 @@ describe('plugin-meetings', () => {
442
552
  );
443
553
  });
444
554
  describe('when meeting is returned', () => {
445
- let parse;
446
555
 
447
556
  beforeEach(() => {
448
- parse = sinon.stub().returns(true);
449
557
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
450
- locusInfo: {
451
- parse,
452
- },
558
+ locusInfo,
453
559
  });
454
560
  });
455
561
  it('tests the sync meeting calls for existing meeting', async () => {
456
562
  await webex.meetings.syncMeetings();
457
563
  assert.calledOnce(webex.meetings.request.getActiveMeetings);
458
564
  assert.calledOnce(webex.meetings.meetingCollection.getByKey);
459
- assert.calledOnce(parse);
565
+ assert.calledOnce(locusInfo.parse);
460
566
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
461
567
  });
462
568
  });
@@ -469,6 +575,7 @@ describe('plugin-meetings', () => {
469
575
  webex.meetings.create = sinon.stub().returns(
470
576
  Promise.resolve({
471
577
  locusInfo: {
578
+ ...locusInfo,
472
579
  initialSetup,
473
580
  },
474
581
  })
@@ -477,7 +584,7 @@ describe('plugin-meetings', () => {
477
584
  it('tests the sync meeting calls for not existing meeting', async () => {
478
585
  await webex.meetings.syncMeetings();
479
586
  assert.calledOnce(webex.meetings.request.getActiveMeetings);
480
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
587
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
481
588
  assert.calledOnce(initialSetup);
482
589
  assert.calledOnce(webex.meetings.create);
483
590
  assert.calledWith(webex.meetings.request.getActiveMeetings);
@@ -501,12 +608,9 @@ describe('plugin-meetings', () => {
501
608
 
502
609
  beforeEach(() => {
503
610
  destroySpy = sinon.spy(webex.meetings, 'destroy');
504
- parse = sinon.stub().returns(true);
505
611
  initialSetup = sinon.stub().returns(true);
506
612
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
507
- locusInfo: {
508
- parse,
509
- },
613
+ locusInfo,
510
614
  sendCallAnalyzerMetrics: sinon.stub(),
511
615
  });
512
616
  webex.meetings.meetingCollection.getAll = sinon.stub().returns({
@@ -580,7 +684,18 @@ describe('plugin-meetings', () => {
580
684
  assert.exists(create.then);
581
685
  await create;
582
686
  assert.calledOnce(webex.meetings.createMeeting);
583
- assert.calledWith(webex.meetings.createMeeting, test1, test2, FAKE_USE_RANDOM_DELAY);
687
+ assert.calledWith(webex.meetings.createMeeting, test1, test2, FAKE_USE_RANDOM_DELAY, {});
688
+ });
689
+
690
+ it('calls createMeeting with extra info params and returns its promise', async () => {
691
+ const FAKE_USE_RANDOM_DELAY = false;
692
+ const FAKE_INFO_EXTRA_PARAMS = {mtid: 'm9fe0afd8c435e892afcce9ea25b97046', joinTXId: 'TSmrX61wNF'};
693
+ const create = webex.meetings.create(test1, test2, FAKE_USE_RANDOM_DELAY, FAKE_INFO_EXTRA_PARAMS);
694
+
695
+ assert.exists(create.then);
696
+ await create;
697
+ assert.calledOnce(webex.meetings.createMeeting);
698
+ assert.calledWith(webex.meetings.createMeeting, test1, test2, FAKE_USE_RANDOM_DELAY, FAKE_INFO_EXTRA_PARAMS);
584
699
  });
585
700
 
586
701
  it('creates a new meeting when a scheduled meeting exists in the conversation', async () => {
@@ -676,38 +791,43 @@ describe('plugin-meetings', () => {
676
791
  });
677
792
  describe('#handleLocusEvent', () => {
678
793
  describe('there was a meeting', () => {
679
- let parse;
680
794
 
681
795
  beforeEach(() => {
682
- parse = sinon.stub().returns(true);
683
796
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
684
- locusInfo: {
685
- parse,
686
- },
797
+ locusInfo,
687
798
  });
688
799
  });
689
- it('should parse the meeting info', () => {
800
+ it('should parse the meeting info and update main session locus cache', () => {
801
+ sinon.stub(MeetingsUtil, 'isBreakoutLocusDTO').returns(false);
690
802
  webex.meetings.handleLocusEvent({
691
803
  locusUrl: url1,
692
804
  });
693
805
  assert.calledOnce(webex.meetings.meetingCollection.getByKey);
694
806
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
695
- assert.calledOnce(parse);
807
+ assert.calledOnce(locusInfo.parse);
808
+ assert.calledOnce(locusInfo.updateMainSessionLocusCache);
696
809
  assert.calledWith(
697
- parse,
810
+ locusInfo.parse,
698
811
  {
699
- locusInfo: {
700
- parse,
701
- },
812
+ locusInfo,
702
813
  },
703
814
  {
704
815
  locusUrl: url1,
705
816
  }
706
817
  );
707
818
  });
819
+
820
+ it('should not update main session locus cache', () => {
821
+ sinon.stub(MeetingsUtil, 'isBreakoutLocusDTO').returns(true);
822
+ webex.meetings.handleLocusEvent({
823
+ locusUrl: url1,
824
+ });
825
+ assert.notCalled(locusInfo.updateMainSessionLocusCache);
826
+ });
708
827
  });
709
828
  describe('there was not a meeting', () => {
710
829
  let initialSetup;
830
+ const webExMeetingId = '123456';
711
831
 
712
832
  beforeEach(() => {
713
833
  initialSetup = sinon.stub().returns(true);
@@ -715,6 +835,7 @@ describe('plugin-meetings', () => {
715
835
  webex.meetings.create = sinon.stub().returns(
716
836
  Promise.resolve({
717
837
  locusInfo: {
838
+ ...locusInfo,
718
839
  initialSetup,
719
840
  },
720
841
  })
@@ -734,12 +855,16 @@ describe('plugin-meetings', () => {
734
855
  callbackAddress: uri1,
735
856
  },
736
857
  },
858
+ info: {
859
+ webExMeetingId
860
+ },
737
861
  },
738
862
  eventType: 'locus.difference',
739
863
  locusUrl: url1,
740
864
  });
741
- assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
865
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 6);
742
866
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
867
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
743
868
  assert.calledOnce(initialSetup);
744
869
  assert.calledWith(initialSetup, {
745
870
  id: uuid1,
@@ -753,6 +878,9 @@ describe('plugin-meetings', () => {
753
878
  callbackAddress: uri1,
754
879
  },
755
880
  },
881
+ info: {
882
+ webExMeetingId
883
+ },
756
884
  });
757
885
  });
758
886
  it('should setup the meeting by difference event without replaces', async () => {
@@ -764,12 +892,16 @@ describe('plugin-meetings', () => {
764
892
  callbackAddress: uri1,
765
893
  },
766
894
  },
895
+ info: {
896
+ webExMeetingId
897
+ },
767
898
  },
768
899
  eventType: 'locus.difference',
769
900
  locusUrl: url1,
770
901
  });
771
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
902
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
772
903
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
904
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
773
905
  assert.calledOnce(initialSetup);
774
906
  assert.calledWith(initialSetup, {
775
907
  id: uuid1,
@@ -778,6 +910,9 @@ describe('plugin-meetings', () => {
778
910
  callbackAddress: uri1,
779
911
  },
780
912
  },
913
+ info: {
914
+ webExMeetingId
915
+ },
781
916
  });
782
917
  });
783
918
  it('should setup the meeting by a not difference event', async () => {
@@ -789,12 +924,16 @@ describe('plugin-meetings', () => {
789
924
  callbackAddress: uri1,
790
925
  },
791
926
  },
927
+ info: {
928
+ webExMeetingId
929
+ },
792
930
  },
793
931
  eventType: test1,
794
932
  locusUrl: url1,
795
933
  });
796
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
934
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
797
935
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
936
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
798
937
  assert.calledOnce(initialSetup);
799
938
  assert.calledWith(initialSetup, {
800
939
  id: uuid1,
@@ -803,6 +942,9 @@ describe('plugin-meetings', () => {
803
942
  callbackAddress: uri1,
804
943
  },
805
944
  },
945
+ info: {
946
+ webExMeetingId
947
+ },
806
948
  });
807
949
  });
808
950
 
@@ -825,7 +967,7 @@ describe('plugin-meetings', () => {
825
967
 
826
968
  it('should not try to match USM meetings by conversation url', async () => {
827
969
  await webex.meetings.handleLocusEvent(generateFakeLocusData(true));
828
- assert.callCount(webex.meetings.meetingCollection.getByKey, 3);
970
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
829
971
  assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, [
830
972
  'locusUrl',
831
973
  url1,
@@ -842,7 +984,7 @@ describe('plugin-meetings', () => {
842
984
  });
843
985
  it('should try to match non-USM meetings by conversation url', async () => {
844
986
  await webex.meetings.handleLocusEvent(generateFakeLocusData(false));
845
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
987
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
846
988
  assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, [
847
989
  'locusUrl',
848
990
  url1,
@@ -873,6 +1015,7 @@ describe('plugin-meetings', () => {
873
1015
  });
874
1016
  describe('successful MeetingInfo.#fetchMeetingInfo', () => {
875
1017
  let clock, setTimeoutSpy, fakeMeetingStartTimeString, FAKE_TIME_TO_START;
1018
+ const FAKE_INFO_EXTRA_PARAMS = {mtid: 'm9fe0afd8c435e892afcce9ea25b97046', joinTXId: 'TSmrX61wNF'};
876
1019
 
877
1020
  beforeEach(() => {
878
1021
  clock = sinon.useFakeTimers();
@@ -902,13 +1045,14 @@ describe('plugin-meetings', () => {
902
1045
  meeting,
903
1046
  destination,
904
1047
  type,
1048
+ extraParams = {},
905
1049
  expectedMeetingData = {}
906
1050
  ) => {
907
1051
  assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
908
1052
  assert.calledOnce(MeetingsUtil.getMeetingAddedType);
909
1053
  assert.notCalled(setTimeoutSpy);
910
1054
  assert.calledThrice(TriggerProxy.trigger);
911
- assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, destination, type);
1055
+ assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, destination, type, null, null, undefined, undefined, extraParams, {meetingId: meeting.id});
912
1056
  assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
913
1057
 
914
1058
  if (expectedMeetingData.permissionToken) {
@@ -948,106 +1092,116 @@ describe('plugin-meetings', () => {
948
1092
  meetingJoinUrl: 'meetingJoinUrl',
949
1093
  };
950
1094
 
951
- checkCreateWithoutDelay(meeting, 'test destination', 'test type', expectedMeetingData);
1095
+ checkCreateWithoutDelay(meeting, 'test destination', 'test type', {}, expectedMeetingData);
952
1096
  });
953
1097
 
954
- it('creates the meeting from a successful meeting info fetch meeting resolve testing', async () => {
955
- const meeting = await webex.meetings.createMeeting('test destination', 'test type');
956
- const expectedMeetingData = {
957
- permissionToken: 'PT',
958
- meetingJoinUrl: 'meetingJoinUrl',
959
- };
1098
+ [undefined, FAKE_INFO_EXTRA_PARAMS].forEach((infoExtraParams) => {
1099
+ const infoExtraParamsProvided = infoExtraParams !== undefined;
960
1100
 
961
- assert.instanceOf(
962
- meeting,
963
- Meeting,
964
- 'createMeeting should eventually resolve to a Meeting Object'
965
- );
966
- checkCreateWithoutDelay(meeting, 'test destination', 'test type', expectedMeetingData);
967
- });
1101
+ it(`creates the meeting from a successful meeting info fetch meeting resolve testing${infoExtraParamsProvided ? ' with infoExtraParams' : ''}`, async () => {
1102
+ const meeting = await webex.meetings.createMeeting('test destination', 'test type', false, infoExtraParams);
1103
+ const expectedMeetingData = {
1104
+ permissionToken: 'PT',
1105
+ meetingJoinUrl: 'meetingJoinUrl',
1106
+ };
968
1107
 
969
- it('creates the meeting from a successful meeting info fetch with random delay', async () => {
970
- const FAKE_LOCUS_MEETING = {
971
- conversationUrl: 'locusConvURL',
972
- url: 'locusUrl',
973
- info: {
974
- webExMeetingId: 'locusMeetingId',
975
- sipUri: 'locusSipUri',
976
- owner: 'locusOwner',
977
- },
978
- meeting: {
979
- startTime: fakeMeetingStartTimeString,
980
- },
981
- fullState: {
982
- active: false,
983
- },
984
- };
1108
+ assert.instanceOf(
1109
+ meeting,
1110
+ Meeting,
1111
+ 'createMeeting should eventually resolve to a Meeting Object'
1112
+ );
1113
+ checkCreateWithoutDelay(meeting, 'test destination', 'test type', infoExtraParamsProvided ? infoExtraParams : {}, expectedMeetingData);
1114
+ });
985
1115
 
986
- const meeting = await webex.meetings.createMeeting(
987
- FAKE_LOCUS_MEETING,
988
- 'test type',
989
- true
990
- );
1116
+ it(`creates the meeting from a successful meeting info fetch with random delay${infoExtraParamsProvided ? ' with infoExtraParams' : ''}`, async () => {
1117
+ const FAKE_LOCUS_MEETING = {
1118
+ conversationUrl: 'locusConvURL',
1119
+ url: 'locusUrl',
1120
+ info: {
1121
+ webExMeetingId: 'locusMeetingId',
1122
+ sipUri: 'locusSipUri',
1123
+ owner: 'locusOwner',
1124
+ },
1125
+ meeting: {
1126
+ startTime: fakeMeetingStartTimeString,
1127
+ },
1128
+ fullState: {
1129
+ active: false,
1130
+ },
1131
+ };
991
1132
 
992
- assert.instanceOf(
993
- meeting,
994
- Meeting,
995
- 'createMeeting should eventually resolve to a Meeting Object'
996
- );
997
- assert.notCalled(webex.meetings.meetingInfo.fetchMeetingInfo);
998
- assert.calledOnce(setTimeoutSpy);
999
-
1000
- // Parse meeting info with locus object
1001
- assert.equal(meeting.conversationUrl, 'locusConvURL');
1002
- assert.equal(meeting.locusUrl, 'locusUrl');
1003
- assert.equal(meeting.sipUri, 'locusSipUri');
1004
- assert.equal(meeting.meetingNumber, 'locusMeetingId');
1005
- assert.isUndefined(meeting.meetingJoinUrl);
1006
- assert.equal(meeting.owner, 'locusOwner');
1007
- assert.isUndefined(meeting.permissionToken);
1008
-
1009
- // Add meeting and send trigger
1010
- assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
1011
- assert.calledTwice(TriggerProxy.trigger);
1012
- assert.calledWith(
1013
- TriggerProxy.trigger,
1014
- sinon.match.instanceOf(Meetings),
1015
- {
1016
- file: 'meetings',
1017
- function: 'createMeeting',
1018
- },
1019
- 'meeting:added',
1020
- {
1021
- meeting: sinon.match.instanceOf(Meeting),
1022
- type: 'test meeting added type',
1023
- }
1024
- );
1133
+ const meeting = await webex.meetings.createMeeting(
1134
+ FAKE_LOCUS_MEETING,
1135
+ 'test type',
1136
+ true,
1137
+ infoExtraParams
1138
+ );
1025
1139
 
1026
- // When timer expires
1027
- clock.tick(FAKE_TIME_TO_START);
1028
- assert.calledWith(
1029
- webex.meetings.meetingInfo.fetchMeetingInfo,
1030
- FAKE_LOCUS_MEETING,
1031
- 'test type'
1032
- );
1140
+ assert.instanceOf(
1141
+ meeting,
1142
+ Meeting,
1143
+ 'createMeeting should eventually resolve to a Meeting Object'
1144
+ );
1145
+ assert.notCalled(webex.meetings.meetingInfo.fetchMeetingInfo);
1146
+ assert.calledOnce(setTimeoutSpy);
1147
+
1148
+ // Parse meeting info with locus object
1149
+ assert.equal(meeting.conversationUrl, 'locusConvURL');
1150
+ assert.equal(meeting.locusUrl, 'locusUrl');
1151
+ assert.equal(meeting.sipUri, 'locusSipUri');
1152
+ assert.equal(meeting.meetingNumber, 'locusMeetingId');
1153
+ assert.isUndefined(meeting.meetingJoinUrl);
1154
+ assert.equal(meeting.owner, 'locusOwner');
1155
+ assert.isUndefined(meeting.permissionToken);
1156
+
1157
+ // Add meeting and send trigger
1158
+ assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
1159
+ assert.calledTwice(TriggerProxy.trigger);
1160
+ assert.calledWith(
1161
+ TriggerProxy.trigger,
1162
+ sinon.match.instanceOf(Meetings),
1163
+ {
1164
+ file: 'meetings',
1165
+ function: 'createMeeting',
1166
+ },
1167
+ 'meeting:added',
1168
+ {
1169
+ meeting: sinon.match.instanceOf(Meeting),
1170
+ type: 'test meeting added type',
1171
+ }
1172
+ );
1033
1173
 
1034
- // Parse meeting info is called again with new meeting info
1035
- await testUtils.flushPromises();
1036
- assert.equal(meeting.conversationUrl, 'locusConvURL');
1037
- assert.equal(meeting.locusUrl, 'locusUrl');
1038
- assert.equal(meeting.sipUri, 'locusSipUri');
1039
- assert.equal(meeting.meetingNumber, 'locusMeetingId');
1040
- assert.equal(meeting.meetingJoinUrl, 'meetingJoinUrl');
1041
- assert.equal(meeting.owner, 'locusOwner');
1042
- assert.equal(meeting.permissionToken, 'PT');
1174
+ // When timer expires
1175
+ clock.tick(FAKE_TIME_TO_START);
1176
+ assert.calledWith(
1177
+ webex.meetings.meetingInfo.fetchMeetingInfo,
1178
+ FAKE_LOCUS_MEETING,
1179
+ 'test type',
1180
+ null,
1181
+ null,
1182
+ undefined,
1183
+ undefined,
1184
+ infoExtraParamsProvided ? infoExtraParams : {}
1185
+ );
1043
1186
 
1044
- assert.calledWith(
1045
- TriggerProxy.trigger,
1046
- meeting,
1047
- {file: 'meetings', function: 'fetchMeetingInfo'},
1048
- 'meeting:meetingInfoAvailable'
1049
- );
1050
- });
1187
+ // Parse meeting info is called again with new meeting info
1188
+ await testUtils.flushPromises();
1189
+ assert.equal(meeting.conversationUrl, 'locusConvURL');
1190
+ assert.equal(meeting.locusUrl, 'locusUrl');
1191
+ assert.equal(meeting.sipUri, 'locusSipUri');
1192
+ assert.equal(meeting.meetingNumber, 'locusMeetingId');
1193
+ assert.equal(meeting.meetingJoinUrl, 'meetingJoinUrl');
1194
+ assert.equal(meeting.owner, 'locusOwner');
1195
+ assert.equal(meeting.permissionToken, 'PT');
1196
+
1197
+ assert.calledWith(
1198
+ TriggerProxy.trigger,
1199
+ meeting,
1200
+ {file: 'meetings', function: 'fetchMeetingInfo'},
1201
+ 'meeting:meetingInfoAvailable'
1202
+ );
1203
+ });
1204
+ })
1051
1205
 
1052
1206
  it('creates the meeting from a successful meeting info fetch that has no random delay because it is active', async () => {
1053
1207
  const FAKE_LOCUS_MEETING = {
@@ -1188,6 +1342,63 @@ describe('plugin-meetings', () => {
1188
1342
  );
1189
1343
  });
1190
1344
  });
1345
+
1346
+ describe('rejected MeetingInfo.#fetchMeetingInfo - does not log for known Error types', () => {
1347
+ forEach(
1348
+ [
1349
+ {
1350
+ error: new CaptchaError(),
1351
+ debugLogMessage:
1352
+ 'Meetings:index#createMeeting --> Debug CaptchaError: Captcha is required. fetching /meetingInfo for creation.',
1353
+ },
1354
+ {
1355
+ error: new PasswordError(),
1356
+ debugLogMessage:
1357
+ 'Meetings:index#createMeeting --> Debug PasswordError: Password is required, please use verifyPassword() fetching /meetingInfo for creation.',
1358
+ },
1359
+ {
1360
+ error: new PermissionError(),
1361
+ debugLogMessage:
1362
+ 'Meetings:index#createMeeting --> Debug PermissionError: Not allowed to execute the function, some properties on server, or local client state do not allow you to complete this action. fetching /meetingInfo for creation.',
1363
+ },
1364
+ {
1365
+ error: new Error(),
1366
+ infoLogMessage: true,
1367
+ debugLogMessage:
1368
+ 'Meetings:index#createMeeting --> Debug Error fetching /meetingInfo for creation.',
1369
+ },
1370
+ ],
1371
+ ({error, debugLogMessage, infoLogMessage}) => {
1372
+ it('creates the meeting from a rejected meeting info fetch', async () => {
1373
+ webex.meetings.meetingInfo.fetchMeetingInfo = sinon
1374
+ .stub()
1375
+ .returns(Promise.reject(error));
1376
+
1377
+ LoggerProxy.logger.debug = sinon.stub();
1378
+ LoggerProxy.logger.info = sinon.stub();
1379
+
1380
+ const meeting = await webex.meetings.createMeeting('test destination', 'test type');
1381
+
1382
+ assert.instanceOf(
1383
+ meeting,
1384
+ Meeting,
1385
+ 'createMeeting should eventually resolve to a Meeting Object'
1386
+ );
1387
+
1388
+ assert.calledWith(LoggerProxy.logger.debug, debugLogMessage);
1389
+
1390
+ if (infoLogMessage) {
1391
+ assert.calledWith(
1392
+ LoggerProxy.logger.info,
1393
+ 'Meetings:index#createMeeting --> Info Unable to fetch meeting info for test destination.'
1394
+ );
1395
+ } else {
1396
+ assert.notCalled(LoggerProxy.logger.info);
1397
+ }
1398
+ });
1399
+ }
1400
+ );
1401
+ });
1191
1402
  });
1192
1403
  });
1193
1404
  describe('Public Event Triggers', () => {
@@ -1266,6 +1477,9 @@ describe('plugin-meetings', () => {
1266
1477
  });
1267
1478
 
1268
1479
  describe('#fetchUserPreferredWebexSite', () => {
1480
+
1481
+ let loggerProxySpy;
1482
+
1269
1483
  it('should call request.getMeetingPreferences to get the preferred webex site ', async () => {
1270
1484
  assert.isDefined(webex.meetings.preferredWebexSite);
1271
1485
  await webex.meetings.fetchUserPreferredWebexSite();
@@ -1273,7 +1487,24 @@ describe('plugin-meetings', () => {
1273
1487
  assert.equal(webex.meetings.preferredWebexSite, 'go.webex.com');
1274
1488
  });
1275
1489
 
1490
+ const setup = ({user} = {}) => {
1491
+ loggerProxySpy = sinon.spy(LoggerProxy.logger, 'error');
1492
+
1493
+ Object.assign(webex.internal, {
1494
+ services: {
1495
+ getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
1496
+ },
1497
+ user: {
1498
+ get: sinon.stub().returns(
1499
+ Promise.resolve(user)
1500
+ ),
1501
+ },
1502
+ });
1503
+ }
1504
+
1276
1505
  it('should not fail if UserPreferred info is not fetched ', async () => {
1506
+ setup();
1507
+
1277
1508
  Object.assign(webex.internal, {
1278
1509
  services: {
1279
1510
  getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
@@ -1283,7 +1514,62 @@ describe('plugin-meetings', () => {
1283
1514
  await webex.meetings.fetchUserPreferredWebexSite().then(() => {
1284
1515
  assert.equal(webex.meetings.preferredWebexSite, '');
1285
1516
  });
1517
+ assert.calledOnceWithExactly(
1518
+ loggerProxySpy,
1519
+ 'Failed to fetch preferred site from user - no site will be set'
1520
+ );
1521
+ });
1522
+
1523
+ it('should fall back to fetching the site from the user', async () => {
1524
+ setup({
1525
+ user: {
1526
+ userPreferences: {
1527
+ userPreferencesItems: {
1528
+ preferredWebExSite: 'site.webex.com',
1529
+ },
1530
+ },
1531
+ },
1532
+ });
1533
+
1534
+ await webex.meetings.fetchUserPreferredWebexSite();
1535
+
1536
+ assert.equal(webex.meetings.preferredWebexSite, 'site.webex.com');
1537
+ assert.notCalled(loggerProxySpy);
1538
+ });
1539
+
1540
+ forEach([
1541
+ {user: undefined},
1542
+ {user: {userPreferences: {}}},
1543
+ {user: {userPreferences: {userPreferencesItems: {}}}},
1544
+ {user: {userPreferences: {userPreferencesItems: {preferredWebExSite: undefined}}}},
1545
+ ], ({user}) => {
1546
+ it(`should handle invalid user data ${user}`, async () => {
1547
+ setup({user});
1548
+
1549
+ await webex.meetings.fetchUserPreferredWebexSite();
1550
+
1551
+ assert.equal(webex.meetings.preferredWebexSite, '');
1552
+ assert.calledOnceWithExactly(
1553
+ loggerProxySpy,
1554
+ 'Failed to fetch preferred site from user - no site will be set'
1555
+ );
1556
+ });
1557
+ });
1558
+
1559
+ it('should handle a get user failure', async () => {
1560
+ setup();
1561
+
1562
+ webex.internal.user.get.rejects(new Error());
1563
+
1564
+ await webex.meetings.fetchUserPreferredWebexSite();
1565
+
1566
+ assert.equal(webex.meetings.preferredWebexSite, '');
1567
+ assert.calledOnceWithExactly(
1568
+ loggerProxySpy,
1569
+ 'Failed to fetch preferred site from user - no site will be set'
1570
+ );
1286
1571
  });
1572
+
1287
1573
  });
1288
1574
  });
1289
1575
 
@@ -1367,5 +1653,465 @@ describe('plugin-meetings', () => {
1367
1653
  );
1368
1654
  });
1369
1655
  });
1656
+
1657
+ describe('#isNeedHandleMainLocus', () => {
1658
+ let meeting;
1659
+ let newLocus;
1660
+ beforeEach(() => {
1661
+ meeting = {
1662
+ controls: {},
1663
+ self: {},
1664
+ };
1665
+ newLocus = {
1666
+ controls: {},
1667
+ self: {},
1668
+ }
1669
+ });
1670
+ afterEach(() => {
1671
+ sinon.restore();
1672
+ });
1673
+ it('check normal case will return true', () => {
1674
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns(null);
1675
+ LoggerProxy.logger.log = sinon.stub();
1676
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1677
+ assert.equal(result, true);
1678
+ assert.calledWith(
1679
+ LoggerProxy.logger.log,
1680
+ 'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
1681
+ );
1682
+ });
1683
+
1684
+ it('check self joined and joined on this device, return true', () => {
1685
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns(null);
1686
+ newLocus.self.state = 'JOINED';
1687
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
1688
+
1689
+ LoggerProxy.logger.log = sinon.stub();
1690
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1691
+ assert.equal(result, true);
1692
+ assert.calledWith(
1693
+ LoggerProxy.logger.log,
1694
+ 'Meetings:index#isNeedHandleMainLocus --> self this device shown as JOINED in the main session'
1695
+ );
1696
+ });
1697
+
1698
+ it('if newLocus replaceAt time is expired, then return false', () => {
1699
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({joinedWith: {replaces: [{
1700
+ replaceAt: '2023-03-27T02:17:02.506Z',
1701
+ }]}});
1702
+ newLocus.self.state = 'JOINED';
1703
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
1704
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1705
+ replaces: [{
1706
+ replaceAt: '2023-03-27T02:17:01.506Z'
1707
+ }]
1708
+ })
1709
+
1710
+ LoggerProxy.logger.log = sinon.stub();
1711
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1712
+ assert.equal(result, false);
1713
+ assert.calledWith(
1714
+ LoggerProxy.logger.log,
1715
+ `Meetings:index#isNeedHandleMainLocus --> this is expired main joined status locus_dto replacedAt 2023-03-27T02:17:01.506Z bo replacedAt 2023-03-27T02:17:02.506Z`
1716
+ );
1717
+ });
1718
+
1719
+ it('check current is in breakout join with this device, return false', () => {
1720
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({
1721
+ joinedWith: {
1722
+ correlationId: '111',
1723
+ },
1724
+ });
1725
+ newLocus.controls.breakout = {url: 'url'};
1726
+ meeting.correlationId = '111';
1727
+
1728
+ LoggerProxy.logger.log = sinon.stub();
1729
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1730
+ assert.equal(result, false);
1731
+ assert.calledWith(
1732
+ LoggerProxy.logger.log,
1733
+ `Meetings:index#isNeedHandleMainLocus --> there is active breakout session and joined on this device, and don't need to handle main session: url`
1734
+ );
1735
+ });
1736
+
1737
+ it('check self is moved and removed, return false', () => {
1738
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1739
+ newLocus.self.state = 'LEFT';
1740
+ newLocus.self.reason = 'MOVED';
1741
+ newLocus.self.removed = true;
1742
+ LoggerProxy.logger.log = sinon.stub();
1743
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1744
+ assert.equal(result, false);
1745
+ assert.calledWith(
1746
+ LoggerProxy.logger.log,
1747
+ 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
1748
+ );
1749
+ });
1750
+
1751
+ it('check self is moved and device resource removed, return false', () => {
1752
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1753
+ newLocus.self.state = 'LEFT';
1754
+ newLocus.self.reason = 'MOVED';
1755
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1756
+ state: 'LEFT',
1757
+ reason: 'MOVED',
1758
+ });
1759
+ LoggerProxy.logger.log = sinon.stub();
1760
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1761
+ assert.equal(result, false);
1762
+ assert.calledWith(
1763
+ LoggerProxy.logger.log,
1764
+ 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
1765
+ );
1766
+ });
1767
+
1768
+ it('check self is joined but device resource removed, return false', () => {
1769
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1770
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(false);
1771
+ newLocus.self.state = 'JOINED';
1772
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1773
+ state: 'LEFT',
1774
+ reason: 'MOVED',
1775
+ });
1776
+ LoggerProxy.logger.log = sinon.stub();
1777
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1778
+ assert.equal(result, false);
1779
+ assert.calledWith(
1780
+ LoggerProxy.logger.log,
1781
+ 'Meetings:index#isNeedHandleMainLocus --> self device left&moved in main locus with self joined status, not need to handle'
1782
+ );
1783
+ });
1784
+ });
1785
+
1786
+ describe('#isNeedHandleLocusDTO', () => {
1787
+ let meeting;
1788
+ let newLocus;
1789
+ beforeEach(() => {
1790
+ meeting = {
1791
+ controls: {},
1792
+ self: {},
1793
+ };
1794
+ newLocus = {
1795
+ controls: {},
1796
+ self: {},
1797
+ }
1798
+ });
1799
+ afterEach(() => {
1800
+ sinon.restore();
1801
+ });
1802
+ it('initial DTO , joined breakout session, return true', () => {
1803
+ newLocus.controls.breakout = {
1804
+ sessionType: 'BREAKOUT',
1805
+ };
1806
+ newLocus.self.state = 'JOINED';
1807
+ newLocus.fullState = {
1808
+ active: true,
1809
+ };
1810
+ LoggerProxy.logger.log = sinon.stub();
1811
+ const result = webex.meetings.isNeedHandleLocusDTO(null, newLocus);
1812
+ assert.equal(result, true);
1813
+ assert.calledWith(
1814
+ LoggerProxy.logger.log,
1815
+ `Meetings:index#isNeedHandleLocusDTO --> the first breakout session locusDTO active status: true`
1816
+ );
1817
+ });
1818
+ it('others go to check isNeedHandleMainLocus', () => {
1819
+ newLocus.controls.breakout = {
1820
+ sessionType: 'MAIN',
1821
+ };
1822
+ newLocus.self.state = 'JOINED';
1823
+
1824
+ LoggerProxy.logger.log = sinon.stub();
1825
+ const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
1826
+ assert.equal(result, true);
1827
+ assert.calledWith(
1828
+ LoggerProxy.logger.log,
1829
+ 'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
1830
+ );
1831
+ });
1832
+ it('joined breakout session, self status is moved, return false', () => {
1833
+ newLocus.controls.breakout = {
1834
+ sessionType: 'BREAKOUT',
1835
+ };
1836
+ newLocus.self.state = 'LEFT';
1837
+ newLocus.self.reason = 'MOVED';
1838
+
1839
+ LoggerProxy.logger.log = sinon.stub();
1840
+ const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
1841
+ assert.equal(result, false);
1842
+ });
1843
+ });
1844
+
1845
+ describe('#getCorrespondingMeetingByLocus', () => {
1846
+ let locus;
1847
+ let mockReturnMeeting = {meeting: 'meeting1'};
1848
+ const mockGetByKey = (keyWillReturnMeeting) => {
1849
+ webex.meetings.meetingCollection.getByKey = sinon.stub().callsFake((key) => {
1850
+ if (key === keyWillReturnMeeting) {
1851
+ return mockReturnMeeting;
1852
+ }
1853
+ return null;
1854
+ });
1855
+ };
1856
+
1857
+ beforeEach(() => {
1858
+ locus = {
1859
+ controls: {},
1860
+ self: {
1861
+ callbackInfo: {
1862
+ callbackAddress: 'address1',
1863
+ }
1864
+ },
1865
+ info: {
1866
+ webExMeetingId: '123456',
1867
+ isUnifiedSpaceMeeting: false,
1868
+ },
1869
+ conversationUrl: 'conversationUrl1'
1870
+ };
1871
+
1872
+ sinon.stub(MeetingsUtil, 'checkForCorrelationId').returns('correlationId1');
1873
+ });
1874
+ afterEach(() => {
1875
+ sinon.restore();
1876
+ });
1877
+ it('check the calls when no meeting found in meetingCollection', () => {
1878
+ mockGetByKey();
1879
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1880
+ assert.isNull(result);
1881
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
1882
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1883
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1884
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1885
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'conversationUrl', 'conversationUrl1');
1886
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', '123456');
1887
+ });
1888
+
1889
+ it('not try getByKey "conversationUrl" when isUnifiedSpaceMeeting is true', () => {
1890
+ mockGetByKey();
1891
+ locus.info.isUnifiedSpaceMeeting = true;
1892
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1893
+ assert.isNull(result);
1894
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
1895
+ })
1896
+
1897
+ it('check the calls when meeting found by key: locusUrl', () => {
1898
+ mockGetByKey('locusUrl');
1899
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1900
+ assert.deepEqual(result, mockReturnMeeting);
1901
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 1);
1902
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1903
+ });
1904
+
1905
+ it('check the calls when meeting found by key: correlationId', () => {
1906
+ mockGetByKey('correlationId');
1907
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1908
+ assert.deepEqual(result, mockReturnMeeting);
1909
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 2);
1910
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1911
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1912
+ });
1913
+
1914
+ it('check the calls when meeting found by key: sipUri', () => {
1915
+ mockGetByKey('sipUri');
1916
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1917
+ assert.deepEqual(result, mockReturnMeeting);
1918
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 3);
1919
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1920
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1921
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1922
+ });
1923
+
1924
+ it('check the calls when meeting found by key: conversationUrl', () => {
1925
+ mockGetByKey('conversationUrl');
1926
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1927
+ assert.deepEqual(result, mockReturnMeeting);
1928
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
1929
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1930
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1931
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1932
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'conversationUrl', 'conversationUrl1');
1933
+ });
1934
+
1935
+ it('check the calls when meeting found by key: meetingNumber', () => {
1936
+ mockGetByKey('meetingNumber');
1937
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1938
+ assert.deepEqual(result, mockReturnMeeting);
1939
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
1940
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1941
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1942
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1943
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'conversationUrl', 'conversationUrl1');
1944
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', '123456');
1945
+ });
1946
+ });
1947
+
1948
+ describe('#sortLocusArrayToUpdate', () => {
1949
+ let lociArray;
1950
+ let mainLocus;
1951
+ let breakoutLocus;
1952
+ beforeEach(() => {
1953
+ mainLocus = {
1954
+ url: 'mainUrl1',
1955
+ controls: {
1956
+ breakout: {
1957
+ sessionType: 'MAIN',
1958
+ url: 'breakoutUnifiedUrl1'
1959
+ }
1960
+ }
1961
+ };
1962
+ breakoutLocus = {
1963
+ url: 'breakoutUrl1',
1964
+ controls: {
1965
+ breakout: {
1966
+ sessionType: 'BREAKOUT',
1967
+ url: 'breakoutUnifiedUrl1'
1968
+ }
1969
+ }
1970
+ };
1971
+ lociArray = [mainLocus, breakoutLocus];
1972
+
1973
+ sinon.stub(MeetingsUtil, 'isValidBreakoutLocus').callsFake((locus) => {
1974
+ return locus.url === 'breakoutUrl1';
1975
+ });
1976
+ });
1977
+ afterEach(() => {
1978
+ sinon.restore();
1979
+ });
1980
+
1981
+ it('if both main and breakout locus is in array for non-exist meeting, return main locus to create first', () => {
1982
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns(undefined);
1983
+ const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
1984
+ assert.deepEqual(result, [mainLocus]);
1985
+ assert.deepEqual(webex.meetings.breakoutLocusForHandleLater, [breakoutLocus]);
1986
+ });
1987
+
1988
+ it('if both main and breakout locus is in array for an exist meeting, return all locus', () => {
1989
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns({});
1990
+ const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
1991
+ assert.deepEqual(result, [mainLocus, breakoutLocus]);
1992
+ assert.deepEqual(webex.meetings.breakoutLocusForHandleLater, []);
1993
+ });
1994
+
1995
+ it('if the breakout locus has no associated main locus, return all', () => {
1996
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns({});
1997
+ breakoutLocus.controls.breakout.url = 'testUrl';
1998
+ const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
1999
+ assert.deepEqual(result, [mainLocus, breakoutLocus]);
2000
+ });
2001
+ });
2002
+
2003
+ describe('#checkHandleBreakoutLocus', () => {
2004
+ let breakoutLocus;
2005
+ beforeEach(() => {
2006
+ breakoutLocus = {
2007
+ url: 'breakoutUrl1',
2008
+ controls: {
2009
+ breakout: {
2010
+ sessionType: 'BREAKOUT',
2011
+ url: 'breakoutUnifiedUrl1',
2012
+ }
2013
+ }
2014
+ };
2015
+
2016
+ webex.meetings.handleLocusEvent = sinon.stub();
2017
+ });
2018
+ afterEach(() => {
2019
+ sinon.restore();
2020
+ });
2021
+ it('do nothing if new created locus is null/no cached breakouts for updating', () => {
2022
+ webex.meetings.checkHandleBreakoutLocus(null);
2023
+ webex.meetings.breakoutLocusForHandleLater = null;
2024
+ webex.meetings.checkHandleBreakoutLocus({});
2025
+ webex.meetings.breakoutLocusForHandleLater = [];
2026
+ webex.meetings.checkHandleBreakoutLocus({});
2027
+ assert.notCalled(webex.meetings.handleLocusEvent);
2028
+ });
2029
+
2030
+ it('do nothing if new created locus is breakout locus', () => {
2031
+ webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
2032
+ webex.meetings.checkHandleBreakoutLocus(breakoutLocus);
2033
+ assert.notCalled(webex.meetings.handleLocusEvent);
2034
+ });
2035
+
2036
+ it('do nothing if no cached locus is associated with the new created locus', () => {
2037
+ webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
2038
+ webex.meetings.checkHandleBreakoutLocus({
2039
+ controls: {
2040
+ breakout: {
2041
+ sessionType: 'MAIN',
2042
+ url: 'breakoutUnifiedUrl2',
2043
+ }
2044
+ }
2045
+ });
2046
+ assert.notCalled(webex.meetings.handleLocusEvent);
2047
+ });
2048
+
2049
+ it('update the cached breakout locus which associate the new created locus', () => {
2050
+ webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
2051
+ webex.meetings.checkHandleBreakoutLocus({
2052
+ controls: {
2053
+ breakout: {
2054
+ sessionType: 'MAIN',
2055
+ url: 'breakoutUnifiedUrl1',
2056
+ }
2057
+ }
2058
+ });
2059
+ assert.calledWith(webex.meetings.handleLocusEvent, {locus: breakoutLocus, locusUrl: breakoutLocus.url});
2060
+ });
2061
+ });
2062
+
2063
+ describe('#getAnalyzerMetricsPrePayload', () => {
2064
+ it('userType & userLogin & environment testing for CA data', async () => {
2065
+ const FAKE_LOCUS_MEETING = {
2066
+ conversationUrl: 'locusConvURL',
2067
+ url: 'locusUrl',
2068
+ info: {
2069
+ webExMeetingId: 'locusMeetingId',
2070
+ sipUri: 'locusSipUri',
2071
+ owner: 'locusOwner',
2072
+ },
2073
+ meeting: {
2074
+ startTime: "",
2075
+ },
2076
+ fullState: {
2077
+ active: false,
2078
+ },
2079
+ };
2080
+
2081
+ const meeting = await webex.meetings.createMeeting(
2082
+ FAKE_LOCUS_MEETING,
2083
+ 'test type',
2084
+ true
2085
+ );
2086
+ meeting.roles = ['MODERATOR','COHOST','ATTENDEE'];
2087
+ meeting.guest = true;
2088
+ const options = {
2089
+ event: 'event',
2090
+ trackingId: 'trackingId',
2091
+ locus: {},
2092
+ mediaConnections: null,
2093
+ errors: {}
2094
+ };
2095
+ webex.internal.services.get = sinon.stub();
2096
+ webex.canAuthorize = true;
2097
+ webex.credentials = {isUnverifiedGuest: true};
2098
+ meeting.getAnalyzerMetricsPrePayload(options);
2099
+ assert.equal(options.userType, 'host');
2100
+ assert.equal(options.loginType, 'unverified-guest');
2101
+ meeting.roles = ['COHOST','ATTENDEE'];
2102
+ meeting.guest = false;
2103
+ webex.canAuthorize = true;
2104
+ webex.credentials = {isUnverifiedGuest: false};
2105
+ meeting.getAnalyzerMetricsPrePayload(options);
2106
+ assert.equal(options.userType, 'cohost');
2107
+ assert.equal(options.loginType, 'login-ci');
2108
+ meeting.roles = ['ATTENDEE'];
2109
+ meeting.getAnalyzerMetricsPrePayload(options);
2110
+ assert.equal(options.userType, 'attendee');
2111
+ meeting.environment = "prod";
2112
+ meeting.getAnalyzerMetricsPrePayload(options);
2113
+ assert.equal(options.environment, 'prod');
2114
+ });
2115
+ });
1370
2116
  });
1371
2117
  });