@webex/plugin-meetings 3.0.0-beta.15 → 3.0.0-beta.151

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