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

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 -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 +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 +95 -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 +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 +76 -2
  65. package/dist/meeting/in-meeting-actions.js.map +1 -1
  66. package/dist/meeting/index.js +2640 -2436
  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 +217 -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 +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 +1430 -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 +37 -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 +70 -142
  301. package/src/media/properties.ts +41 -104
  302. package/src/mediaQualityMetrics/config.ts +379 -377
  303. package/src/meeting/in-meeting-actions.ts +151 -3
  304. package/src/meeting/index.ts +2029 -2033
  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 +80 -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 +331 -254
  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 +118 -22
  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 +2742 -1441
  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
@@ -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,15 +66,20 @@ 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(() => {
66
73
  MeetingsUtil.checkH264Support = sinon.stub();
67
- uuid1 = uuid.v4();
74
+ uuid1 = uuid.v4();
68
75
  url1 = `https://example.com/${uuid.v4()}`;
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,45 +791,52 @@ 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);
714
834
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns(undefined);
715
835
  webex.meetings.create = sinon.stub().returns(
716
836
  Promise.resolve({
837
+ id: 'meeting-id',
717
838
  locusInfo: {
839
+ ...locusInfo,
718
840
  initialSetup,
719
841
  },
720
842
  })
@@ -734,12 +856,16 @@ describe('plugin-meetings', () => {
734
856
  callbackAddress: uri1,
735
857
  },
736
858
  },
859
+ info: {
860
+ webExMeetingId
861
+ },
737
862
  },
738
863
  eventType: 'locus.difference',
739
864
  locusUrl: url1,
740
865
  });
741
- assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
866
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 6);
742
867
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
868
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
743
869
  assert.calledOnce(initialSetup);
744
870
  assert.calledWith(initialSetup, {
745
871
  id: uuid1,
@@ -753,6 +879,9 @@ describe('plugin-meetings', () => {
753
879
  callbackAddress: uri1,
754
880
  },
755
881
  },
882
+ info: {
883
+ webExMeetingId
884
+ },
756
885
  });
757
886
  });
758
887
  it('should setup the meeting by difference event without replaces', async () => {
@@ -764,12 +893,16 @@ describe('plugin-meetings', () => {
764
893
  callbackAddress: uri1,
765
894
  },
766
895
  },
896
+ info: {
897
+ webExMeetingId
898
+ },
767
899
  },
768
900
  eventType: 'locus.difference',
769
901
  locusUrl: url1,
770
902
  });
771
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
903
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
772
904
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
905
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
773
906
  assert.calledOnce(initialSetup);
774
907
  assert.calledWith(initialSetup, {
775
908
  id: uuid1,
@@ -778,8 +911,44 @@ describe('plugin-meetings', () => {
778
911
  callbackAddress: uri1,
779
912
  },
780
913
  },
914
+ info: {
915
+ webExMeetingId
916
+ },
917
+ });
918
+ });
919
+
920
+ it('sends client event correctly on finally', async () => {
921
+ webex.meetings.getMeetingByType = sinon.stub().returns(true);
922
+
923
+ await webex.meetings.handleLocusEvent({
924
+ locus: {
925
+ id: uuid1,
926
+ self: {
927
+ callBackInfo: {
928
+ callbackAddress: uri1,
929
+ },
930
+ },
931
+ info: {
932
+ webExMeetingId,
933
+ },
934
+ },
935
+ eventType: 'locus.difference',
936
+ locusUrl: url1,
937
+ });
938
+
939
+ await testUtils.flushPromises();
940
+
941
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
942
+ name: 'client.call.remote-started',
943
+ payload: {
944
+ trigger: 'mercury-event',
945
+ },
946
+ options: {
947
+ meetingId: 'meeting-id',
948
+ },
781
949
  });
782
950
  });
951
+
783
952
  it('should setup the meeting by a not difference event', async () => {
784
953
  await webex.meetings.handleLocusEvent({
785
954
  locus: {
@@ -789,12 +958,16 @@ describe('plugin-meetings', () => {
789
958
  callbackAddress: uri1,
790
959
  },
791
960
  },
961
+ info: {
962
+ webExMeetingId
963
+ },
792
964
  },
793
965
  eventType: test1,
794
966
  locusUrl: url1,
795
967
  });
796
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
968
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
797
969
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
970
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
798
971
  assert.calledOnce(initialSetup);
799
972
  assert.calledWith(initialSetup, {
800
973
  id: uuid1,
@@ -803,6 +976,9 @@ describe('plugin-meetings', () => {
803
976
  callbackAddress: uri1,
804
977
  },
805
978
  },
979
+ info: {
980
+ webExMeetingId
981
+ },
806
982
  });
807
983
  });
808
984
 
@@ -825,7 +1001,7 @@ describe('plugin-meetings', () => {
825
1001
 
826
1002
  it('should not try to match USM meetings by conversation url', async () => {
827
1003
  await webex.meetings.handleLocusEvent(generateFakeLocusData(true));
828
- assert.callCount(webex.meetings.meetingCollection.getByKey, 3);
1004
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
829
1005
  assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, [
830
1006
  'locusUrl',
831
1007
  url1,
@@ -842,7 +1018,7 @@ describe('plugin-meetings', () => {
842
1018
  });
843
1019
  it('should try to match non-USM meetings by conversation url', async () => {
844
1020
  await webex.meetings.handleLocusEvent(generateFakeLocusData(false));
845
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
1021
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
846
1022
  assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, [
847
1023
  'locusUrl',
848
1024
  url1,
@@ -873,6 +1049,7 @@ describe('plugin-meetings', () => {
873
1049
  });
874
1050
  describe('successful MeetingInfo.#fetchMeetingInfo', () => {
875
1051
  let clock, setTimeoutSpy, fakeMeetingStartTimeString, FAKE_TIME_TO_START;
1052
+ const FAKE_INFO_EXTRA_PARAMS = {mtid: 'm9fe0afd8c435e892afcce9ea25b97046', joinTXId: 'TSmrX61wNF'};
876
1053
 
877
1054
  beforeEach(() => {
878
1055
  clock = sinon.useFakeTimers();
@@ -902,13 +1079,14 @@ describe('plugin-meetings', () => {
902
1079
  meeting,
903
1080
  destination,
904
1081
  type,
1082
+ extraParams = {},
905
1083
  expectedMeetingData = {}
906
1084
  ) => {
907
1085
  assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
908
1086
  assert.calledOnce(MeetingsUtil.getMeetingAddedType);
909
1087
  assert.notCalled(setTimeoutSpy);
910
1088
  assert.calledThrice(TriggerProxy.trigger);
911
- assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, destination, type);
1089
+ assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, destination, type, null, null, undefined, undefined, extraParams, {meetingId: meeting.id});
912
1090
  assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
913
1091
 
914
1092
  if (expectedMeetingData.permissionToken) {
@@ -948,106 +1126,116 @@ describe('plugin-meetings', () => {
948
1126
  meetingJoinUrl: 'meetingJoinUrl',
949
1127
  };
950
1128
 
951
- checkCreateWithoutDelay(meeting, 'test destination', 'test type', expectedMeetingData);
1129
+ checkCreateWithoutDelay(meeting, 'test destination', 'test type', {}, expectedMeetingData);
952
1130
  });
953
1131
 
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
- };
1132
+ [undefined, FAKE_INFO_EXTRA_PARAMS].forEach((infoExtraParams) => {
1133
+ const infoExtraParamsProvided = infoExtraParams !== undefined;
960
1134
 
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
- });
1135
+ it(`creates the meeting from a successful meeting info fetch meeting resolve testing${infoExtraParamsProvided ? ' with infoExtraParams' : ''}`, async () => {
1136
+ const meeting = await webex.meetings.createMeeting('test destination', 'test type', false, infoExtraParams);
1137
+ const expectedMeetingData = {
1138
+ permissionToken: 'PT',
1139
+ meetingJoinUrl: 'meetingJoinUrl',
1140
+ };
968
1141
 
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
- };
1142
+ assert.instanceOf(
1143
+ meeting,
1144
+ Meeting,
1145
+ 'createMeeting should eventually resolve to a Meeting Object'
1146
+ );
1147
+ checkCreateWithoutDelay(meeting, 'test destination', 'test type', infoExtraParamsProvided ? infoExtraParams : {}, expectedMeetingData);
1148
+ });
985
1149
 
986
- const meeting = await webex.meetings.createMeeting(
987
- FAKE_LOCUS_MEETING,
988
- 'test type',
989
- true
990
- );
1150
+ it(`creates the meeting from a successful meeting info fetch with random delay${infoExtraParamsProvided ? ' with infoExtraParams' : ''}`, async () => {
1151
+ const FAKE_LOCUS_MEETING = {
1152
+ conversationUrl: 'locusConvURL',
1153
+ url: 'locusUrl',
1154
+ info: {
1155
+ webExMeetingId: 'locusMeetingId',
1156
+ sipUri: 'locusSipUri',
1157
+ owner: 'locusOwner',
1158
+ },
1159
+ meeting: {
1160
+ startTime: fakeMeetingStartTimeString,
1161
+ },
1162
+ fullState: {
1163
+ active: false,
1164
+ },
1165
+ };
991
1166
 
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
- );
1167
+ const meeting = await webex.meetings.createMeeting(
1168
+ FAKE_LOCUS_MEETING,
1169
+ 'test type',
1170
+ true,
1171
+ infoExtraParams
1172
+ );
1025
1173
 
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
- );
1174
+ assert.instanceOf(
1175
+ meeting,
1176
+ Meeting,
1177
+ 'createMeeting should eventually resolve to a Meeting Object'
1178
+ );
1179
+ assert.notCalled(webex.meetings.meetingInfo.fetchMeetingInfo);
1180
+ assert.calledOnce(setTimeoutSpy);
1181
+
1182
+ // Parse meeting info with locus object
1183
+ assert.equal(meeting.conversationUrl, 'locusConvURL');
1184
+ assert.equal(meeting.locusUrl, 'locusUrl');
1185
+ assert.equal(meeting.sipUri, 'locusSipUri');
1186
+ assert.equal(meeting.meetingNumber, 'locusMeetingId');
1187
+ assert.isUndefined(meeting.meetingJoinUrl);
1188
+ assert.equal(meeting.owner, 'locusOwner');
1189
+ assert.isUndefined(meeting.permissionToken);
1190
+
1191
+ // Add meeting and send trigger
1192
+ assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
1193
+ assert.calledTwice(TriggerProxy.trigger);
1194
+ assert.calledWith(
1195
+ TriggerProxy.trigger,
1196
+ sinon.match.instanceOf(Meetings),
1197
+ {
1198
+ file: 'meetings',
1199
+ function: 'createMeeting',
1200
+ },
1201
+ 'meeting:added',
1202
+ {
1203
+ meeting: sinon.match.instanceOf(Meeting),
1204
+ type: 'test meeting added type',
1205
+ }
1206
+ );
1033
1207
 
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');
1208
+ // When timer expires
1209
+ clock.tick(FAKE_TIME_TO_START);
1210
+ assert.calledWith(
1211
+ webex.meetings.meetingInfo.fetchMeetingInfo,
1212
+ FAKE_LOCUS_MEETING,
1213
+ 'test type',
1214
+ null,
1215
+ null,
1216
+ undefined,
1217
+ undefined,
1218
+ infoExtraParamsProvided ? infoExtraParams : {}
1219
+ );
1043
1220
 
1044
- assert.calledWith(
1045
- TriggerProxy.trigger,
1046
- meeting,
1047
- {file: 'meetings', function: 'fetchMeetingInfo'},
1048
- 'meeting:meetingInfoAvailable'
1049
- );
1050
- });
1221
+ // Parse meeting info is called again with new meeting info
1222
+ await testUtils.flushPromises();
1223
+ assert.equal(meeting.conversationUrl, 'locusConvURL');
1224
+ assert.equal(meeting.locusUrl, 'locusUrl');
1225
+ assert.equal(meeting.sipUri, 'locusSipUri');
1226
+ assert.equal(meeting.meetingNumber, 'locusMeetingId');
1227
+ assert.equal(meeting.meetingJoinUrl, 'meetingJoinUrl');
1228
+ assert.equal(meeting.owner, 'locusOwner');
1229
+ assert.equal(meeting.permissionToken, 'PT');
1230
+
1231
+ assert.calledWith(
1232
+ TriggerProxy.trigger,
1233
+ meeting,
1234
+ {file: 'meetings', function: 'fetchMeetingInfo'},
1235
+ 'meeting:meetingInfoAvailable'
1236
+ );
1237
+ });
1238
+ })
1051
1239
 
1052
1240
  it('creates the meeting from a successful meeting info fetch that has no random delay because it is active', async () => {
1053
1241
  const FAKE_LOCUS_MEETING = {
@@ -1188,6 +1376,63 @@ describe('plugin-meetings', () => {
1188
1376
  );
1189
1377
  });
1190
1378
  });
1379
+
1380
+ describe('rejected MeetingInfo.#fetchMeetingInfo - does not log for known Error types', () => {
1381
+ forEach(
1382
+ [
1383
+ {
1384
+ error: new CaptchaError(),
1385
+ debugLogMessage:
1386
+ 'Meetings:index#createMeeting --> Debug CaptchaError: Captcha is required. fetching /meetingInfo for creation.',
1387
+ },
1388
+ {
1389
+ error: new PasswordError(),
1390
+ debugLogMessage:
1391
+ 'Meetings:index#createMeeting --> Debug PasswordError: Password is required, please use verifyPassword() fetching /meetingInfo for creation.',
1392
+ },
1393
+ {
1394
+ error: new PermissionError(),
1395
+ debugLogMessage:
1396
+ '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.',
1397
+ },
1398
+ {
1399
+ error: new Error(),
1400
+ infoLogMessage: true,
1401
+ debugLogMessage:
1402
+ 'Meetings:index#createMeeting --> Debug Error fetching /meetingInfo for creation.',
1403
+ },
1404
+ ],
1405
+ ({error, debugLogMessage, infoLogMessage}) => {
1406
+ it('creates the meeting from a rejected meeting info fetch', async () => {
1407
+ webex.meetings.meetingInfo.fetchMeetingInfo = sinon
1408
+ .stub()
1409
+ .returns(Promise.reject(error));
1410
+
1411
+ LoggerProxy.logger.debug = sinon.stub();
1412
+ LoggerProxy.logger.info = sinon.stub();
1413
+
1414
+ const meeting = await webex.meetings.createMeeting('test destination', 'test type');
1415
+
1416
+ assert.instanceOf(
1417
+ meeting,
1418
+ Meeting,
1419
+ 'createMeeting should eventually resolve to a Meeting Object'
1420
+ );
1421
+
1422
+ assert.calledWith(LoggerProxy.logger.debug, debugLogMessage);
1423
+
1424
+ if (infoLogMessage) {
1425
+ assert.calledWith(
1426
+ LoggerProxy.logger.info,
1427
+ 'Meetings:index#createMeeting --> Info Unable to fetch meeting info for test destination.'
1428
+ );
1429
+ } else {
1430
+ assert.notCalled(LoggerProxy.logger.info);
1431
+ }
1432
+ });
1433
+ }
1434
+ );
1435
+ });
1191
1436
  });
1192
1437
  });
1193
1438
  describe('Public Event Triggers', () => {
@@ -1266,6 +1511,9 @@ describe('plugin-meetings', () => {
1266
1511
  });
1267
1512
 
1268
1513
  describe('#fetchUserPreferredWebexSite', () => {
1514
+
1515
+ let loggerProxySpy;
1516
+
1269
1517
  it('should call request.getMeetingPreferences to get the preferred webex site ', async () => {
1270
1518
  assert.isDefined(webex.meetings.preferredWebexSite);
1271
1519
  await webex.meetings.fetchUserPreferredWebexSite();
@@ -1273,7 +1521,24 @@ describe('plugin-meetings', () => {
1273
1521
  assert.equal(webex.meetings.preferredWebexSite, 'go.webex.com');
1274
1522
  });
1275
1523
 
1524
+ const setup = ({user} = {}) => {
1525
+ loggerProxySpy = sinon.spy(LoggerProxy.logger, 'error');
1526
+
1527
+ Object.assign(webex.internal, {
1528
+ services: {
1529
+ getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
1530
+ },
1531
+ user: {
1532
+ get: sinon.stub().returns(
1533
+ Promise.resolve(user)
1534
+ ),
1535
+ },
1536
+ });
1537
+ }
1538
+
1276
1539
  it('should not fail if UserPreferred info is not fetched ', async () => {
1540
+ setup();
1541
+
1277
1542
  Object.assign(webex.internal, {
1278
1543
  services: {
1279
1544
  getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
@@ -1283,7 +1548,62 @@ describe('plugin-meetings', () => {
1283
1548
  await webex.meetings.fetchUserPreferredWebexSite().then(() => {
1284
1549
  assert.equal(webex.meetings.preferredWebexSite, '');
1285
1550
  });
1551
+ assert.calledOnceWithExactly(
1552
+ loggerProxySpy,
1553
+ 'Failed to fetch preferred site from user - no site will be set'
1554
+ );
1555
+ });
1556
+
1557
+ it('should fall back to fetching the site from the user', async () => {
1558
+ setup({
1559
+ user: {
1560
+ userPreferences: {
1561
+ userPreferencesItems: {
1562
+ preferredWebExSite: 'site.webex.com',
1563
+ },
1564
+ },
1565
+ },
1566
+ });
1567
+
1568
+ await webex.meetings.fetchUserPreferredWebexSite();
1569
+
1570
+ assert.equal(webex.meetings.preferredWebexSite, 'site.webex.com');
1571
+ assert.notCalled(loggerProxySpy);
1572
+ });
1573
+
1574
+ forEach([
1575
+ {user: undefined},
1576
+ {user: {userPreferences: {}}},
1577
+ {user: {userPreferences: {userPreferencesItems: {}}}},
1578
+ {user: {userPreferences: {userPreferencesItems: {preferredWebExSite: undefined}}}},
1579
+ ], ({user}) => {
1580
+ it(`should handle invalid user data ${user}`, async () => {
1581
+ setup({user});
1582
+
1583
+ await webex.meetings.fetchUserPreferredWebexSite();
1584
+
1585
+ assert.equal(webex.meetings.preferredWebexSite, '');
1586
+ assert.calledOnceWithExactly(
1587
+ loggerProxySpy,
1588
+ 'Failed to fetch preferred site from user - no site will be set'
1589
+ );
1590
+ });
1591
+ });
1592
+
1593
+ it('should handle a get user failure', async () => {
1594
+ setup();
1595
+
1596
+ webex.internal.user.get.rejects(new Error());
1597
+
1598
+ await webex.meetings.fetchUserPreferredWebexSite();
1599
+
1600
+ assert.equal(webex.meetings.preferredWebexSite, '');
1601
+ assert.calledOnceWithExactly(
1602
+ loggerProxySpy,
1603
+ 'Failed to fetch preferred site from user - no site will be set'
1604
+ );
1286
1605
  });
1606
+
1287
1607
  });
1288
1608
  });
1289
1609
 
@@ -1367,5 +1687,411 @@ describe('plugin-meetings', () => {
1367
1687
  );
1368
1688
  });
1369
1689
  });
1690
+
1691
+ describe('#isNeedHandleMainLocus', () => {
1692
+ let meeting;
1693
+ let newLocus;
1694
+ beforeEach(() => {
1695
+ meeting = {
1696
+ controls: {},
1697
+ self: {},
1698
+ };
1699
+ newLocus = {
1700
+ controls: {},
1701
+ self: {},
1702
+ }
1703
+ });
1704
+ afterEach(() => {
1705
+ sinon.restore();
1706
+ });
1707
+ it('check normal case will return true', () => {
1708
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns(null);
1709
+ LoggerProxy.logger.log = sinon.stub();
1710
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1711
+ assert.equal(result, true);
1712
+ assert.calledWith(
1713
+ LoggerProxy.logger.log,
1714
+ 'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
1715
+ );
1716
+ });
1717
+
1718
+ it('check self joined and joined on this device, return true', () => {
1719
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns(null);
1720
+ newLocus.self.state = 'JOINED';
1721
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
1722
+
1723
+ LoggerProxy.logger.log = sinon.stub();
1724
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1725
+ assert.equal(result, true);
1726
+ assert.calledWith(
1727
+ LoggerProxy.logger.log,
1728
+ 'Meetings:index#isNeedHandleMainLocus --> self this device shown as JOINED in the main session'
1729
+ );
1730
+ });
1731
+
1732
+ it('if newLocus replaceAt time is expired, then return false', () => {
1733
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({joinedWith: {replaces: [{
1734
+ replaceAt: '2023-03-27T02:17:02.506Z',
1735
+ }]}});
1736
+ newLocus.self.state = 'JOINED';
1737
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
1738
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1739
+ replaces: [{
1740
+ replaceAt: '2023-03-27T02:17:01.506Z'
1741
+ }]
1742
+ })
1743
+
1744
+ LoggerProxy.logger.log = sinon.stub();
1745
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1746
+ assert.equal(result, false);
1747
+ assert.calledWith(
1748
+ LoggerProxy.logger.log,
1749
+ `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`
1750
+ );
1751
+ });
1752
+
1753
+ it('check current is in breakout join with this device, return false', () => {
1754
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({
1755
+ joinedWith: {
1756
+ correlationId: '111',
1757
+ },
1758
+ });
1759
+ newLocus.controls.breakout = {url: 'url'};
1760
+ meeting.correlationId = '111';
1761
+
1762
+ LoggerProxy.logger.log = sinon.stub();
1763
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1764
+ assert.equal(result, false);
1765
+ assert.calledWith(
1766
+ LoggerProxy.logger.log,
1767
+ `Meetings:index#isNeedHandleMainLocus --> there is active breakout session and joined on this device, and don't need to handle main session: url`
1768
+ );
1769
+ });
1770
+
1771
+ it('check self is moved and removed, return false', () => {
1772
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1773
+ newLocus.self.state = 'LEFT';
1774
+ newLocus.self.reason = 'MOVED';
1775
+ newLocus.self.removed = true;
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 moved main locus with self removed status or with device resource moved, not need to handle'
1782
+ );
1783
+ });
1784
+
1785
+ it('check self is moved and device resource removed, return false', () => {
1786
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1787
+ newLocus.self.state = 'LEFT';
1788
+ newLocus.self.reason = 'MOVED';
1789
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1790
+ state: 'LEFT',
1791
+ reason: 'MOVED',
1792
+ });
1793
+ LoggerProxy.logger.log = sinon.stub();
1794
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1795
+ assert.equal(result, false);
1796
+ assert.calledWith(
1797
+ LoggerProxy.logger.log,
1798
+ 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
1799
+ );
1800
+ });
1801
+
1802
+ it('check self is joined but device resource removed, return false', () => {
1803
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1804
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(false);
1805
+ newLocus.self.state = 'JOINED';
1806
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1807
+ state: 'LEFT',
1808
+ reason: 'MOVED',
1809
+ });
1810
+ LoggerProxy.logger.log = sinon.stub();
1811
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1812
+ assert.equal(result, false);
1813
+ assert.calledWith(
1814
+ LoggerProxy.logger.log,
1815
+ 'Meetings:index#isNeedHandleMainLocus --> self device left&moved in main locus with self joined status, not need to handle'
1816
+ );
1817
+ });
1818
+ });
1819
+
1820
+ describe('#isNeedHandleLocusDTO', () => {
1821
+ let meeting;
1822
+ let newLocus;
1823
+ beforeEach(() => {
1824
+ meeting = {
1825
+ controls: {},
1826
+ self: {},
1827
+ };
1828
+ newLocus = {
1829
+ controls: {},
1830
+ self: {},
1831
+ }
1832
+ });
1833
+ afterEach(() => {
1834
+ sinon.restore();
1835
+ });
1836
+ it('initial DTO , joined breakout session, return true', () => {
1837
+ newLocus.controls.breakout = {
1838
+ sessionType: 'BREAKOUT',
1839
+ };
1840
+ newLocus.self.state = 'JOINED';
1841
+ newLocus.fullState = {
1842
+ active: true,
1843
+ };
1844
+ LoggerProxy.logger.log = sinon.stub();
1845
+ const result = webex.meetings.isNeedHandleLocusDTO(null, newLocus);
1846
+ assert.equal(result, true);
1847
+ assert.calledWith(
1848
+ LoggerProxy.logger.log,
1849
+ `Meetings:index#isNeedHandleLocusDTO --> the first breakout session locusDTO active status: true`
1850
+ );
1851
+ });
1852
+ it('others go to check isNeedHandleMainLocus', () => {
1853
+ newLocus.controls.breakout = {
1854
+ sessionType: 'MAIN',
1855
+ };
1856
+ newLocus.self.state = 'JOINED';
1857
+
1858
+ LoggerProxy.logger.log = sinon.stub();
1859
+ const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
1860
+ assert.equal(result, true);
1861
+ assert.calledWith(
1862
+ LoggerProxy.logger.log,
1863
+ 'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
1864
+ );
1865
+ });
1866
+ it('joined breakout session, self status is moved, return false', () => {
1867
+ newLocus.controls.breakout = {
1868
+ sessionType: 'BREAKOUT',
1869
+ };
1870
+ newLocus.self.state = 'LEFT';
1871
+ newLocus.self.reason = 'MOVED';
1872
+
1873
+ LoggerProxy.logger.log = sinon.stub();
1874
+ const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
1875
+ assert.equal(result, false);
1876
+ });
1877
+ });
1878
+
1879
+ describe('#getCorrespondingMeetingByLocus', () => {
1880
+ let locus;
1881
+ let mockReturnMeeting = {meeting: 'meeting1'};
1882
+ const mockGetByKey = (keyWillReturnMeeting) => {
1883
+ webex.meetings.meetingCollection.getByKey = sinon.stub().callsFake((key) => {
1884
+ if (key === keyWillReturnMeeting) {
1885
+ return mockReturnMeeting;
1886
+ }
1887
+ return null;
1888
+ });
1889
+ };
1890
+
1891
+ beforeEach(() => {
1892
+ locus = {
1893
+ controls: {},
1894
+ self: {
1895
+ callbackInfo: {
1896
+ callbackAddress: 'address1',
1897
+ }
1898
+ },
1899
+ info: {
1900
+ webExMeetingId: '123456',
1901
+ isUnifiedSpaceMeeting: false,
1902
+ },
1903
+ conversationUrl: 'conversationUrl1'
1904
+ };
1905
+
1906
+ sinon.stub(MeetingsUtil, 'checkForCorrelationId').returns('correlationId1');
1907
+ });
1908
+ afterEach(() => {
1909
+ sinon.restore();
1910
+ });
1911
+ it('check the calls when no meeting found in meetingCollection', () => {
1912
+ mockGetByKey();
1913
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1914
+ assert.isNull(result);
1915
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
1916
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1917
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1918
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1919
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'conversationUrl', 'conversationUrl1');
1920
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', '123456');
1921
+ });
1922
+
1923
+ it('not try getByKey "conversationUrl" when isUnifiedSpaceMeeting is true', () => {
1924
+ mockGetByKey();
1925
+ locus.info.isUnifiedSpaceMeeting = true;
1926
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1927
+ assert.isNull(result);
1928
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
1929
+ })
1930
+
1931
+ it('check the calls when meeting found by key: locusUrl', () => {
1932
+ mockGetByKey('locusUrl');
1933
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1934
+ assert.deepEqual(result, mockReturnMeeting);
1935
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 1);
1936
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1937
+ });
1938
+
1939
+ it('check the calls when meeting found by key: correlationId', () => {
1940
+ mockGetByKey('correlationId');
1941
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1942
+ assert.deepEqual(result, mockReturnMeeting);
1943
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 2);
1944
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1945
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1946
+ });
1947
+
1948
+ it('check the calls when meeting found by key: sipUri', () => {
1949
+ mockGetByKey('sipUri');
1950
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1951
+ assert.deepEqual(result, mockReturnMeeting);
1952
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 3);
1953
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1954
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1955
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1956
+ });
1957
+
1958
+ it('check the calls when meeting found by key: conversationUrl', () => {
1959
+ mockGetByKey('conversationUrl');
1960
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1961
+ assert.deepEqual(result, mockReturnMeeting);
1962
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
1963
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1964
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1965
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1966
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'conversationUrl', 'conversationUrl1');
1967
+ });
1968
+
1969
+ it('check the calls when meeting found by key: meetingNumber', () => {
1970
+ mockGetByKey('meetingNumber');
1971
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1972
+ assert.deepEqual(result, mockReturnMeeting);
1973
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
1974
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1975
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1976
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1977
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'conversationUrl', 'conversationUrl1');
1978
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', '123456');
1979
+ });
1980
+ });
1981
+
1982
+ describe('#sortLocusArrayToUpdate', () => {
1983
+ let lociArray;
1984
+ let mainLocus;
1985
+ let breakoutLocus;
1986
+ beforeEach(() => {
1987
+ mainLocus = {
1988
+ url: 'mainUrl1',
1989
+ controls: {
1990
+ breakout: {
1991
+ sessionType: 'MAIN',
1992
+ url: 'breakoutUnifiedUrl1'
1993
+ }
1994
+ }
1995
+ };
1996
+ breakoutLocus = {
1997
+ url: 'breakoutUrl1',
1998
+ controls: {
1999
+ breakout: {
2000
+ sessionType: 'BREAKOUT',
2001
+ url: 'breakoutUnifiedUrl1'
2002
+ }
2003
+ }
2004
+ };
2005
+ lociArray = [mainLocus, breakoutLocus];
2006
+
2007
+ sinon.stub(MeetingsUtil, 'isValidBreakoutLocus').callsFake((locus) => {
2008
+ return locus.url === 'breakoutUrl1';
2009
+ });
2010
+ });
2011
+ afterEach(() => {
2012
+ sinon.restore();
2013
+ });
2014
+
2015
+ it('if both main and breakout locus is in array for non-exist meeting, return main locus to create first', () => {
2016
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns(undefined);
2017
+ const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
2018
+ assert.deepEqual(result, [mainLocus]);
2019
+ assert.deepEqual(webex.meetings.breakoutLocusForHandleLater, [breakoutLocus]);
2020
+ });
2021
+
2022
+ it('if both main and breakout locus is in array for an exist meeting, return all locus', () => {
2023
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns({});
2024
+ const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
2025
+ assert.deepEqual(result, [mainLocus, breakoutLocus]);
2026
+ assert.deepEqual(webex.meetings.breakoutLocusForHandleLater, []);
2027
+ });
2028
+
2029
+ it('if the breakout locus has no associated main locus, return all', () => {
2030
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns({});
2031
+ breakoutLocus.controls.breakout.url = 'testUrl';
2032
+ const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
2033
+ assert.deepEqual(result, [mainLocus, breakoutLocus]);
2034
+ });
2035
+ });
2036
+
2037
+ describe('#checkHandleBreakoutLocus', () => {
2038
+ let breakoutLocus;
2039
+ beforeEach(() => {
2040
+ breakoutLocus = {
2041
+ url: 'breakoutUrl1',
2042
+ controls: {
2043
+ breakout: {
2044
+ sessionType: 'BREAKOUT',
2045
+ url: 'breakoutUnifiedUrl1',
2046
+ }
2047
+ }
2048
+ };
2049
+
2050
+ webex.meetings.handleLocusEvent = sinon.stub();
2051
+ });
2052
+ afterEach(() => {
2053
+ sinon.restore();
2054
+ });
2055
+ it('do nothing if new created locus is null/no cached breakouts for updating', () => {
2056
+ webex.meetings.checkHandleBreakoutLocus(null);
2057
+ webex.meetings.breakoutLocusForHandleLater = null;
2058
+ webex.meetings.checkHandleBreakoutLocus({});
2059
+ webex.meetings.breakoutLocusForHandleLater = [];
2060
+ webex.meetings.checkHandleBreakoutLocus({});
2061
+ assert.notCalled(webex.meetings.handleLocusEvent);
2062
+ });
2063
+
2064
+ it('do nothing if new created locus is breakout locus', () => {
2065
+ webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
2066
+ webex.meetings.checkHandleBreakoutLocus(breakoutLocus);
2067
+ assert.notCalled(webex.meetings.handleLocusEvent);
2068
+ });
2069
+
2070
+ it('do nothing if no cached locus is associated with the new created locus', () => {
2071
+ webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
2072
+ webex.meetings.checkHandleBreakoutLocus({
2073
+ controls: {
2074
+ breakout: {
2075
+ sessionType: 'MAIN',
2076
+ url: 'breakoutUnifiedUrl2',
2077
+ }
2078
+ }
2079
+ });
2080
+ assert.notCalled(webex.meetings.handleLocusEvent);
2081
+ });
2082
+
2083
+ it('update the cached breakout locus which associate the new created locus', () => {
2084
+ webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
2085
+ webex.meetings.checkHandleBreakoutLocus({
2086
+ controls: {
2087
+ breakout: {
2088
+ sessionType: 'MAIN',
2089
+ url: 'breakoutUnifiedUrl1',
2090
+ }
2091
+ }
2092
+ });
2093
+ assert.calledWith(webex.meetings.handleLocusEvent, {locus: breakoutLocus, locusUrl: breakoutLocus.url});
2094
+ });
2095
+ });
1370
2096
  });
1371
2097
  });