@webex/plugin-meetings 3.0.0-beta.2 → 3.0.0-beta.200

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 (576) hide show
  1. package/README.md +45 -7
  2. package/UPGRADING.md +9 -9
  3. package/browsers.js +19 -24
  4. package/dist/annotation/annotation.types.js +7 -0
  5. package/dist/annotation/annotation.types.js.map +1 -0
  6. package/dist/annotation/constants.js +49 -0
  7. package/dist/annotation/constants.js.map +1 -0
  8. package/dist/annotation/index.js +342 -0
  9. package/dist/annotation/index.js.map +1 -0
  10. package/dist/breakouts/breakout.js +216 -0
  11. package/dist/breakouts/breakout.js.map +1 -0
  12. package/dist/breakouts/collection.js +23 -0
  13. package/dist/breakouts/collection.js.map +1 -0
  14. package/dist/breakouts/edit-lock-error.js +52 -0
  15. package/dist/breakouts/edit-lock-error.js.map +1 -0
  16. package/dist/breakouts/events.js +45 -0
  17. package/dist/breakouts/events.js.map +1 -0
  18. package/dist/breakouts/index.js +1048 -0
  19. package/dist/breakouts/index.js.map +1 -0
  20. package/dist/breakouts/request.js +78 -0
  21. package/dist/breakouts/request.js.map +1 -0
  22. package/dist/breakouts/utils.js +67 -0
  23. package/dist/breakouts/utils.js.map +1 -0
  24. package/dist/common/browser-detection.js +1 -20
  25. package/dist/common/browser-detection.js.map +1 -1
  26. package/dist/common/collection.js +5 -20
  27. package/dist/common/collection.js.map +1 -1
  28. package/dist/common/config.js +0 -7
  29. package/dist/common/config.js.map +1 -1
  30. package/dist/common/errors/captcha-error.js +10 -24
  31. package/dist/common/errors/captcha-error.js.map +1 -1
  32. package/dist/common/errors/intent-to-join.js +11 -24
  33. package/dist/common/errors/intent-to-join.js.map +1 -1
  34. package/dist/common/errors/join-meeting.js +12 -25
  35. package/dist/common/errors/join-meeting.js.map +1 -1
  36. package/dist/common/errors/media.js +10 -24
  37. package/dist/common/errors/media.js.map +1 -1
  38. package/dist/common/errors/parameter.js +5 -33
  39. package/dist/common/errors/parameter.js.map +1 -1
  40. package/dist/common/errors/password-error.js +10 -24
  41. package/dist/common/errors/password-error.js.map +1 -1
  42. package/dist/common/errors/permission.js +9 -23
  43. package/dist/common/errors/permission.js.map +1 -1
  44. package/dist/common/errors/reconnection-in-progress.js +0 -17
  45. package/dist/common/errors/reconnection-in-progress.js.map +1 -1
  46. package/dist/common/errors/reconnection.js +10 -24
  47. package/dist/common/errors/reconnection.js.map +1 -1
  48. package/dist/common/errors/stats.js +10 -24
  49. package/dist/common/errors/stats.js.map +1 -1
  50. package/dist/common/errors/webex-errors.js +9 -43
  51. package/dist/common/errors/webex-errors.js.map +1 -1
  52. package/dist/common/errors/webex-meetings-error.js +5 -25
  53. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  54. package/dist/common/events/events-scope.js +0 -22
  55. package/dist/common/events/events-scope.js.map +1 -1
  56. package/dist/common/events/events.js +0 -23
  57. package/dist/common/events/events.js.map +1 -1
  58. package/dist/common/events/trigger-proxy.js +0 -12
  59. package/dist/common/events/trigger-proxy.js.map +1 -1
  60. package/dist/common/events/util.js +0 -15
  61. package/dist/common/events/util.js.map +1 -1
  62. package/dist/common/logs/logger-config.js +0 -4
  63. package/dist/common/logs/logger-config.js.map +1 -1
  64. package/dist/common/logs/logger-proxy.js +1 -8
  65. package/dist/common/logs/logger-proxy.js.map +1 -1
  66. package/dist/common/logs/request.js +37 -60
  67. package/dist/common/logs/request.js.map +1 -1
  68. package/dist/common/queue.js +28 -23
  69. package/dist/common/queue.js.map +1 -1
  70. package/dist/config.js +8 -13
  71. package/dist/config.js.map +1 -1
  72. package/dist/constants.js +250 -66
  73. package/dist/constants.js.map +1 -1
  74. package/dist/controls-options-manager/constants.js +14 -0
  75. package/dist/controls-options-manager/constants.js.map +1 -0
  76. package/dist/controls-options-manager/enums.js +27 -0
  77. package/dist/controls-options-manager/enums.js.map +1 -0
  78. package/dist/controls-options-manager/index.js +297 -0
  79. package/dist/controls-options-manager/index.js.map +1 -0
  80. package/dist/controls-options-manager/types.js +7 -0
  81. package/dist/controls-options-manager/types.js.map +1 -0
  82. package/dist/controls-options-manager/util.js +319 -0
  83. package/dist/controls-options-manager/util.js.map +1 -0
  84. package/dist/index.js +108 -17
  85. package/dist/index.js.map +1 -1
  86. package/dist/interpretation/collection.js +23 -0
  87. package/dist/interpretation/collection.js.map +1 -0
  88. package/dist/interpretation/index.js +366 -0
  89. package/dist/interpretation/index.js.map +1 -0
  90. package/dist/interpretation/siLanguage.js +25 -0
  91. package/dist/interpretation/siLanguage.js.map +1 -0
  92. package/dist/locus-info/controlsUtils.js +101 -29
  93. package/dist/locus-info/controlsUtils.js.map +1 -1
  94. package/dist/locus-info/embeddedAppsUtils.js +3 -26
  95. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  96. package/dist/locus-info/fullState.js +0 -15
  97. package/dist/locus-info/fullState.js.map +1 -1
  98. package/dist/locus-info/hostUtils.js +4 -12
  99. package/dist/locus-info/hostUtils.js.map +1 -1
  100. package/dist/locus-info/index.js +532 -240
  101. package/dist/locus-info/index.js.map +1 -1
  102. package/dist/locus-info/infoUtils.js +3 -37
  103. package/dist/locus-info/infoUtils.js.map +1 -1
  104. package/dist/locus-info/mediaSharesUtils.js +54 -38
  105. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  106. package/dist/locus-info/parser.js +284 -154
  107. package/dist/locus-info/parser.js.map +1 -1
  108. package/dist/locus-info/selfUtils.js +110 -92
  109. package/dist/locus-info/selfUtils.js.map +1 -1
  110. package/dist/media/index.js +95 -226
  111. package/dist/media/index.js.map +1 -1
  112. package/dist/media/properties.js +99 -194
  113. package/dist/media/properties.js.map +1 -1
  114. package/dist/media/util.js +2 -9
  115. package/dist/media/util.js.map +1 -1
  116. package/dist/mediaQualityMetrics/config.js +505 -495
  117. package/dist/mediaQualityMetrics/config.js.map +1 -1
  118. package/dist/meeting/in-meeting-actions.js +83 -14
  119. package/dist/meeting/in-meeting-actions.js.map +1 -1
  120. package/dist/meeting/index.js +3478 -3563
  121. package/dist/meeting/index.js.map +1 -1
  122. package/dist/meeting/locusMediaRequest.js +291 -0
  123. package/dist/meeting/locusMediaRequest.js.map +1 -0
  124. package/dist/meeting/muteState.js +247 -183
  125. package/dist/meeting/muteState.js.map +1 -1
  126. package/dist/meeting/request.js +344 -344
  127. package/dist/meeting/request.js.map +1 -1
  128. package/dist/meeting/request.type.js +7 -0
  129. package/dist/meeting/request.type.js.map +1 -0
  130. package/dist/meeting/state.js +21 -31
  131. package/dist/meeting/state.js.map +1 -1
  132. package/dist/meeting/util.js +529 -588
  133. package/dist/meeting/util.js.map +1 -1
  134. package/dist/meeting-info/collection.js +6 -25
  135. package/dist/meeting-info/collection.js.map +1 -1
  136. package/dist/meeting-info/index.js +62 -39
  137. package/dist/meeting-info/index.js.map +1 -1
  138. package/dist/meeting-info/meeting-info-v2.js +328 -283
  139. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  140. package/dist/meeting-info/request.js +3 -15
  141. package/dist/meeting-info/request.js.map +1 -1
  142. package/dist/meeting-info/util.js +98 -183
  143. package/dist/meeting-info/util.js.map +1 -1
  144. package/dist/meeting-info/utilv2.js +156 -232
  145. package/dist/meeting-info/utilv2.js.map +1 -1
  146. package/dist/meetings/collection.js +26 -19
  147. package/dist/meetings/collection.js.map +1 -1
  148. package/dist/meetings/index.js +795 -574
  149. package/dist/meetings/index.js.map +1 -1
  150. package/dist/meetings/meetings.types.js +7 -0
  151. package/dist/meetings/meetings.types.js.map +1 -0
  152. package/dist/meetings/request.js +26 -41
  153. package/dist/meetings/request.js.map +1 -1
  154. package/dist/meetings/util.js +186 -155
  155. package/dist/meetings/util.js.map +1 -1
  156. package/dist/member/index.js +126 -85
  157. package/dist/member/index.js.map +1 -1
  158. package/dist/member/types.js +25 -0
  159. package/dist/member/types.js.map +1 -0
  160. package/dist/member/util.js +147 -88
  161. package/dist/member/util.js.map +1 -1
  162. package/dist/members/collection.js +13 -12
  163. package/dist/members/collection.js.map +1 -1
  164. package/dist/members/index.js +178 -204
  165. package/dist/members/index.js.map +1 -1
  166. package/dist/members/request.js +113 -68
  167. package/dist/members/request.js.map +1 -1
  168. package/dist/members/types.js +15 -0
  169. package/dist/members/types.js.map +1 -0
  170. package/dist/members/util.js +314 -260
  171. package/dist/members/util.js.map +1 -1
  172. package/dist/metrics/constants.js +4 -7
  173. package/dist/metrics/constants.js.map +1 -1
  174. package/dist/metrics/index.js +11 -558
  175. package/dist/metrics/index.js.map +1 -1
  176. package/dist/multistream/mediaRequestManager.js +264 -50
  177. package/dist/multistream/mediaRequestManager.js.map +1 -1
  178. package/dist/multistream/receiveSlot.js +58 -65
  179. package/dist/multistream/receiveSlot.js.map +1 -1
  180. package/dist/multistream/receiveSlotManager.js +76 -95
  181. package/dist/multistream/receiveSlotManager.js.map +1 -1
  182. package/dist/multistream/remoteMedia.js +62 -76
  183. package/dist/multistream/remoteMedia.js.map +1 -1
  184. package/dist/multistream/remoteMediaGroup.js +66 -43
  185. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  186. package/dist/multistream/remoteMediaManager.js +502 -442
  187. package/dist/multistream/remoteMediaManager.js.map +1 -1
  188. package/dist/networkQualityMonitor/index.js +40 -59
  189. package/dist/networkQualityMonitor/index.js.map +1 -1
  190. package/dist/personal-meeting-room/index.js +21 -45
  191. package/dist/personal-meeting-room/index.js.map +1 -1
  192. package/dist/personal-meeting-room/request.js +1 -31
  193. package/dist/personal-meeting-room/request.js.map +1 -1
  194. package/dist/personal-meeting-room/util.js +0 -13
  195. package/dist/personal-meeting-room/util.js.map +1 -1
  196. package/dist/reachability/index.js +192 -191
  197. package/dist/reachability/index.js.map +1 -1
  198. package/dist/reachability/request.js +15 -23
  199. package/dist/reachability/request.js.map +1 -1
  200. package/dist/reactions/constants.js +13 -0
  201. package/dist/reactions/constants.js.map +1 -0
  202. package/dist/reactions/reactions.js +109 -0
  203. package/dist/reactions/reactions.js.map +1 -0
  204. package/dist/reactions/reactions.type.js +36 -0
  205. package/dist/reactions/reactions.type.js.map +1 -0
  206. package/dist/reconnection-manager/index.js +384 -476
  207. package/dist/reconnection-manager/index.js.map +1 -1
  208. package/dist/recording-controller/enums.js +17 -0
  209. package/dist/recording-controller/enums.js.map +1 -0
  210. package/dist/recording-controller/index.js +363 -0
  211. package/dist/recording-controller/index.js.map +1 -0
  212. package/dist/recording-controller/util.js +64 -0
  213. package/dist/recording-controller/util.js.map +1 -0
  214. package/dist/roap/index.js +58 -91
  215. package/dist/roap/index.js.map +1 -1
  216. package/dist/roap/request.js +137 -135
  217. package/dist/roap/request.js.map +1 -1
  218. package/dist/roap/turnDiscovery.js +148 -100
  219. package/dist/roap/turnDiscovery.js.map +1 -1
  220. package/dist/rtcMetrics/constants.js +12 -0
  221. package/dist/rtcMetrics/constants.js.map +1 -0
  222. package/dist/rtcMetrics/index.js +115 -0
  223. package/dist/rtcMetrics/index.js.map +1 -0
  224. package/dist/statsAnalyzer/global.js +1 -95
  225. package/dist/statsAnalyzer/global.js.map +1 -1
  226. package/dist/statsAnalyzer/index.js +385 -460
  227. package/dist/statsAnalyzer/index.js.map +1 -1
  228. package/dist/statsAnalyzer/mqaUtil.js +143 -87
  229. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  230. package/dist/transcription/index.js +22 -47
  231. package/dist/transcription/index.js.map +1 -1
  232. package/dist/types/annotation/annotation.types.d.ts +42 -0
  233. package/dist/types/annotation/constants.d.ts +31 -0
  234. package/dist/types/annotation/index.d.ts +117 -0
  235. package/dist/types/breakouts/breakout.d.ts +8 -0
  236. package/dist/types/breakouts/collection.d.ts +5 -0
  237. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  238. package/dist/types/breakouts/events.d.ts +8 -0
  239. package/dist/types/breakouts/index.d.ts +5 -0
  240. package/dist/types/breakouts/request.d.ts +22 -0
  241. package/dist/types/breakouts/utils.d.ts +15 -0
  242. package/dist/types/common/browser-detection.d.ts +9 -0
  243. package/dist/types/common/collection.d.ts +48 -0
  244. package/dist/types/common/config.d.ts +2 -0
  245. package/dist/types/common/errors/captcha-error.d.ts +15 -0
  246. package/dist/types/common/errors/intent-to-join.d.ts +16 -0
  247. package/dist/types/common/errors/join-meeting.d.ts +17 -0
  248. package/dist/types/common/errors/media.d.ts +15 -0
  249. package/dist/types/common/errors/parameter.d.ts +15 -0
  250. package/dist/types/common/errors/password-error.d.ts +15 -0
  251. package/dist/types/common/errors/permission.d.ts +14 -0
  252. package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
  253. package/dist/types/common/errors/reconnection.d.ts +15 -0
  254. package/dist/types/common/errors/stats.d.ts +15 -0
  255. package/dist/types/common/errors/webex-errors.d.ts +69 -0
  256. package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
  257. package/dist/types/common/events/events-scope.d.ts +17 -0
  258. package/dist/types/common/events/events.d.ts +12 -0
  259. package/dist/types/common/events/trigger-proxy.d.ts +2 -0
  260. package/dist/types/common/events/util.d.ts +2 -0
  261. package/dist/types/common/logs/logger-config.d.ts +2 -0
  262. package/dist/types/common/logs/logger-proxy.d.ts +2 -0
  263. package/dist/types/common/logs/request.d.ts +34 -0
  264. package/dist/types/common/queue.d.ts +34 -0
  265. package/dist/types/config.d.ts +72 -0
  266. package/dist/types/constants.d.ts +1016 -0
  267. package/dist/types/controls-options-manager/constants.d.ts +4 -0
  268. package/dist/types/controls-options-manager/enums.d.ts +15 -0
  269. package/dist/types/controls-options-manager/index.d.ts +136 -0
  270. package/dist/types/controls-options-manager/types.d.ts +43 -0
  271. package/dist/types/controls-options-manager/util.d.ts +1 -0
  272. package/dist/types/index.d.ts +7 -0
  273. package/dist/types/interpretation/collection.d.ts +5 -0
  274. package/dist/types/interpretation/index.d.ts +5 -0
  275. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  276. package/dist/types/locus-info/controlsUtils.d.ts +2 -0
  277. package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
  278. package/dist/types/locus-info/fullState.d.ts +2 -0
  279. package/dist/types/locus-info/hostUtils.d.ts +2 -0
  280. package/dist/types/locus-info/index.d.ts +322 -0
  281. package/dist/types/locus-info/infoUtils.d.ts +2 -0
  282. package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
  283. package/dist/types/locus-info/parser.d.ts +271 -0
  284. package/dist/types/locus-info/selfUtils.d.ts +2 -0
  285. package/dist/types/media/index.d.ts +34 -0
  286. package/dist/types/media/properties.d.ts +93 -0
  287. package/dist/types/media/util.d.ts +2 -0
  288. package/dist/types/mediaQualityMetrics/config.d.ts +365 -0
  289. package/dist/types/meeting/in-meeting-actions.d.ts +153 -0
  290. package/dist/types/meeting/index.d.ts +1471 -0
  291. package/dist/types/meeting/locusMediaRequest.d.ts +70 -0
  292. package/dist/types/meeting/muteState.d.ts +184 -0
  293. package/dist/types/meeting/request.d.ts +257 -0
  294. package/dist/types/meeting/request.type.d.ts +11 -0
  295. package/dist/types/meeting/state.d.ts +9 -0
  296. package/dist/types/meeting/util.d.ts +78 -0
  297. package/dist/types/meeting-info/collection.d.ts +20 -0
  298. package/dist/types/meeting-info/index.d.ts +62 -0
  299. package/dist/types/meeting-info/meeting-info-v2.d.ts +122 -0
  300. package/dist/types/meeting-info/request.d.ts +22 -0
  301. package/dist/types/meeting-info/util.d.ts +2 -0
  302. package/dist/types/meeting-info/utilv2.d.ts +2 -0
  303. package/dist/types/meetings/collection.d.ts +31 -0
  304. package/dist/types/meetings/index.d.ts +367 -0
  305. package/dist/types/meetings/meetings.types.d.ts +4 -0
  306. package/dist/types/meetings/request.d.ts +27 -0
  307. package/dist/types/meetings/util.d.ts +18 -0
  308. package/dist/types/member/index.d.ts +159 -0
  309. package/dist/types/member/types.d.ts +32 -0
  310. package/dist/types/member/util.d.ts +2 -0
  311. package/dist/types/members/collection.d.ts +29 -0
  312. package/dist/types/members/index.d.ts +353 -0
  313. package/dist/types/members/request.d.ts +114 -0
  314. package/dist/types/members/types.d.ts +24 -0
  315. package/dist/types/members/util.d.ts +210 -0
  316. package/dist/types/metrics/constants.d.ts +55 -0
  317. package/dist/types/metrics/index.d.ts +45 -0
  318. package/dist/types/multistream/mediaRequestManager.d.ts +118 -0
  319. package/dist/types/multistream/receiveSlot.d.ts +68 -0
  320. package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
  321. package/dist/types/multistream/remoteMedia.d.ts +72 -0
  322. package/dist/types/multistream/remoteMediaGroup.d.ts +47 -0
  323. package/dist/types/multistream/remoteMediaManager.d.ts +277 -0
  324. package/dist/types/networkQualityMonitor/index.d.ts +70 -0
  325. package/dist/types/personal-meeting-room/index.d.ts +47 -0
  326. package/dist/types/personal-meeting-room/request.d.ts +14 -0
  327. package/dist/types/personal-meeting-room/util.d.ts +2 -0
  328. package/dist/types/reachability/index.d.ts +152 -0
  329. package/dist/types/reachability/request.d.ts +37 -0
  330. package/dist/types/reactions/constants.d.ts +3 -0
  331. package/dist/types/reactions/reactions.d.ts +4 -0
  332. package/dist/types/reactions/reactions.type.d.ts +52 -0
  333. package/dist/types/reconnection-manager/index.d.ts +126 -0
  334. package/dist/types/recording-controller/enums.d.ts +7 -0
  335. package/dist/types/recording-controller/index.d.ts +208 -0
  336. package/dist/types/recording-controller/util.d.ts +14 -0
  337. package/dist/types/roap/index.d.ts +77 -0
  338. package/dist/types/roap/request.d.ts +36 -0
  339. package/dist/types/roap/turnDiscovery.d.ts +91 -0
  340. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  341. package/dist/types/rtcMetrics/index.d.ts +46 -0
  342. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  343. package/dist/types/statsAnalyzer/index.d.ts +200 -0
  344. package/dist/types/statsAnalyzer/mqaUtil.d.ts +24 -0
  345. package/dist/types/transcription/index.d.ts +64 -0
  346. package/internal-README.md +7 -6
  347. package/package.json +29 -21
  348. package/src/annotation/annotation.types.ts +50 -0
  349. package/src/annotation/constants.ts +36 -0
  350. package/src/annotation/index.ts +328 -0
  351. package/src/breakouts/README.md +220 -0
  352. package/src/breakouts/breakout.ts +188 -0
  353. package/src/breakouts/collection.ts +19 -0
  354. package/src/breakouts/edit-lock-error.ts +25 -0
  355. package/src/breakouts/events.ts +56 -0
  356. package/src/breakouts/index.ts +925 -0
  357. package/src/breakouts/request.ts +55 -0
  358. package/src/breakouts/utils.ts +57 -0
  359. package/src/common/{browser-detection.js → browser-detection.ts} +9 -6
  360. package/src/common/collection.ts +9 -7
  361. package/src/common/{config.js → config.ts} +1 -1
  362. package/src/common/errors/{captcha-error.js → captcha-error.ts} +11 -7
  363. package/src/common/errors/{intent-to-join.js → intent-to-join.ts} +12 -7
  364. package/src/common/errors/{join-meeting.js → join-meeting.ts} +17 -8
  365. package/src/common/errors/{media.js → media.ts} +11 -7
  366. package/src/common/errors/parameter.ts +11 -7
  367. package/src/common/errors/{password-error.js → password-error.ts} +11 -7
  368. package/src/common/errors/{permission.js → permission.ts} +10 -6
  369. package/src/common/errors/{reconnection.js → reconnection.ts} +11 -7
  370. package/src/common/errors/{stats.js → stats.ts} +11 -7
  371. package/src/common/errors/{webex-errors.js → webex-errors.ts} +14 -9
  372. package/src/common/errors/{webex-meetings-error.js → webex-meetings-error.ts} +4 -2
  373. package/src/common/events/{events-scope.js → events-scope.ts} +6 -2
  374. package/src/common/events/{events.js → events.ts} +5 -1
  375. package/src/common/events/{trigger-proxy.js → trigger-proxy.ts} +9 -5
  376. package/src/common/events/{util.js → util.ts} +2 -3
  377. package/src/common/logs/{logger-config.js → logger-config.ts} +1 -2
  378. package/src/common/logs/logger-proxy.ts +44 -0
  379. package/src/common/logs/{request.js → request.ts} +22 -9
  380. package/src/common/queue.ts +22 -9
  381. package/src/{config.js → config.ts} +17 -17
  382. package/src/constants.ts +197 -22
  383. package/src/controls-options-manager/constants.ts +5 -0
  384. package/src/controls-options-manager/enums.ts +18 -0
  385. package/src/controls-options-manager/index.ts +278 -0
  386. package/src/controls-options-manager/types.ts +59 -0
  387. package/src/controls-options-manager/util.ts +300 -0
  388. package/src/index.ts +39 -0
  389. package/src/interpretation/README.md +60 -0
  390. package/src/interpretation/collection.ts +19 -0
  391. package/src/interpretation/index.ts +332 -0
  392. package/src/interpretation/siLanguage.ts +18 -0
  393. package/src/locus-info/controlsUtils.ts +222 -0
  394. package/src/locus-info/{embeddedAppsUtils.js → embeddedAppsUtils.ts} +5 -6
  395. package/src/locus-info/{fullState.js → fullState.ts} +16 -12
  396. package/src/locus-info/{hostUtils.js → hostUtils.ts} +9 -8
  397. package/src/locus-info/{index.js → index.ts} +518 -111
  398. package/src/locus-info/{infoUtils.js → infoUtils.ts} +19 -8
  399. package/src/locus-info/{mediaSharesUtils.js → mediaSharesUtils.ts} +65 -17
  400. package/src/locus-info/{parser.js → parser.ts} +271 -98
  401. package/src/locus-info/{selfUtils.js → selfUtils.ts} +199 -68
  402. package/src/media/index.ts +456 -0
  403. package/src/media/{properties.js → properties.ts} +80 -102
  404. package/src/media/{util.js → util.ts} +2 -2
  405. package/src/mediaQualityMetrics/config.ts +384 -0
  406. package/src/meeting/in-meeting-actions.ts +171 -3
  407. package/src/meeting/index.ts +7070 -0
  408. package/src/meeting/locusMediaRequest.ts +309 -0
  409. package/src/meeting/muteState.ts +450 -0
  410. package/src/meeting/{request.js → request.ts} +354 -214
  411. package/src/meeting/request.type.ts +13 -0
  412. package/src/meeting/{state.js → state.ts} +50 -35
  413. package/src/meeting/util.ts +615 -0
  414. package/src/meeting-info/{collection.js → collection.ts} +6 -2
  415. package/src/meeting-info/index.ts +183 -0
  416. package/src/meeting-info/meeting-info-v2.ts +407 -0
  417. package/src/meeting-info/{request.js → request.ts} +14 -4
  418. package/src/meeting-info/{util.js → util.ts} +60 -51
  419. package/src/meeting-info/{utilv2.js → utilv2.ts} +77 -60
  420. package/src/meetings/{collection.js → collection.ts} +26 -3
  421. package/src/meetings/index.ts +1467 -0
  422. package/src/meetings/meetings.types.ts +12 -0
  423. package/src/meetings/{request.js → request.ts} +34 -25
  424. package/src/meetings/{util.js → util.ts} +137 -36
  425. package/src/member/{index.js → index.ts} +151 -56
  426. package/src/member/types.ts +38 -0
  427. package/src/member/util.ts +383 -0
  428. package/src/members/{collection.js → collection.ts} +10 -2
  429. package/src/members/{index.js → index.ts} +323 -145
  430. package/src/members/request.ts +255 -0
  431. package/src/members/types.ts +28 -0
  432. package/src/members/util.ts +339 -0
  433. package/src/metrics/{constants.js → constants.ts} +2 -6
  434. package/src/metrics/index.ts +73 -0
  435. package/src/multistream/mediaRequestManager.ts +337 -61
  436. package/src/multistream/receiveSlot.ts +69 -26
  437. package/src/multistream/receiveSlotManager.ts +66 -42
  438. package/src/multistream/remoteMedia.ts +40 -5
  439. package/src/multistream/remoteMediaGroup.ts +63 -3
  440. package/src/multistream/remoteMediaManager.ts +263 -66
  441. package/src/networkQualityMonitor/{index.js → index.ts} +41 -29
  442. package/src/personal-meeting-room/{index.js → index.ts} +28 -19
  443. package/src/personal-meeting-room/{request.js → request.ts} +13 -4
  444. package/src/personal-meeting-room/{util.js → util.ts} +4 -4
  445. package/src/reachability/{index.js → index.ts} +157 -94
  446. package/src/reachability/request.ts +46 -35
  447. package/src/reactions/constants.ts +4 -0
  448. package/src/reactions/reactions.ts +104 -0
  449. package/src/reactions/reactions.type.ts +62 -0
  450. package/src/reconnection-manager/{index.js → index.ts} +254 -136
  451. package/src/recording-controller/enums.ts +8 -0
  452. package/src/recording-controller/index.ts +333 -0
  453. package/src/recording-controller/util.ts +75 -0
  454. package/src/roap/{index.js → index.ts} +86 -78
  455. package/src/roap/request.ts +163 -0
  456. package/src/roap/turnDiscovery.ts +111 -49
  457. package/src/rtcMetrics/constants.ts +3 -0
  458. package/src/rtcMetrics/index.ts +96 -0
  459. package/src/statsAnalyzer/global.ts +37 -0
  460. package/src/statsAnalyzer/index.ts +1272 -0
  461. package/src/statsAnalyzer/mqaUtil.ts +291 -0
  462. package/src/transcription/{index.js → index.ts} +46 -39
  463. package/test/integration/spec/converged-space-meetings.js +233 -0
  464. package/test/integration/spec/journey.js +804 -526
  465. package/test/integration/spec/space-meeting.js +391 -204
  466. package/test/integration/spec/transcription.js +7 -8
  467. package/test/unit/spec/annotation/index.ts +418 -0
  468. package/test/unit/spec/breakouts/breakout.ts +237 -0
  469. package/test/unit/spec/breakouts/collection.ts +15 -0
  470. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  471. package/test/unit/spec/breakouts/events.ts +89 -0
  472. package/test/unit/spec/breakouts/index.ts +1790 -0
  473. package/test/unit/spec/breakouts/request.ts +104 -0
  474. package/test/unit/spec/breakouts/utils.js +72 -0
  475. package/test/unit/spec/common/browser-detection.js +9 -28
  476. package/test/unit/spec/common/queue.js +31 -2
  477. package/test/unit/spec/controls-options-manager/index.js +287 -0
  478. package/test/unit/spec/controls-options-manager/util.js +582 -0
  479. package/test/unit/spec/fixture/locus.js +93 -90
  480. package/test/unit/spec/interpretation/collection.ts +15 -0
  481. package/test/unit/spec/interpretation/index.ts +589 -0
  482. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  483. package/test/unit/spec/locus-info/controlsUtils.js +325 -32
  484. package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
  485. package/test/unit/spec/locus-info/index.js +1176 -18
  486. package/test/unit/spec/locus-info/infoUtils.js +41 -32
  487. package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +88 -430
  488. package/test/unit/spec/locus-info/lib/SeqCmp.json +513 -685
  489. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  490. package/test/unit/spec/locus-info/parser.js +65 -31
  491. package/test/unit/spec/locus-info/selfConstant.js +120 -103
  492. package/test/unit/spec/locus-info/selfUtils.js +296 -12
  493. package/test/unit/spec/media/index.ts +162 -68
  494. package/test/unit/spec/media/properties.ts +9 -9
  495. package/test/unit/spec/meeting/in-meeting-actions.ts +82 -3
  496. package/test/unit/spec/meeting/index.js +4569 -1773
  497. package/test/unit/spec/meeting/locusMediaRequest.ts +436 -0
  498. package/test/unit/spec/meeting/muteState.js +382 -211
  499. package/test/unit/spec/meeting/request.js +444 -78
  500. package/test/unit/spec/meeting/utils.js +517 -192
  501. package/test/unit/spec/meeting-info/index.js +181 -0
  502. package/test/unit/spec/meeting-info/meetinginfov2.js +481 -76
  503. package/test/unit/spec/meeting-info/request.js +7 -9
  504. package/test/unit/spec/meeting-info/util.js +11 -12
  505. package/test/unit/spec/meeting-info/utilv2.js +131 -74
  506. package/test/unit/spec/meetings/collection.js +15 -1
  507. package/test/unit/spec/meetings/index.js +1254 -330
  508. package/test/unit/spec/meetings/utils.js +220 -14
  509. package/test/unit/spec/member/index.js +58 -5
  510. package/test/unit/spec/member/util.js +494 -26
  511. package/test/unit/spec/members/index.js +423 -55
  512. package/test/unit/spec/members/request.js +228 -40
  513. package/test/unit/spec/members/utils.js +191 -4
  514. package/test/unit/spec/metrics/index.js +12 -66
  515. package/test/unit/spec/multistream/mediaRequestManager.ts +1013 -106
  516. package/test/unit/spec/multistream/receiveSlot.ts +77 -18
  517. package/test/unit/spec/multistream/receiveSlotManager.ts +69 -39
  518. package/test/unit/spec/multistream/remoteMedia.ts +40 -2
  519. package/test/unit/spec/multistream/remoteMediaGroup.ts +271 -5
  520. package/test/unit/spec/multistream/remoteMediaManager.ts +730 -65
  521. package/test/unit/spec/networkQualityMonitor/index.js +24 -18
  522. package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -7
  523. package/test/unit/spec/reachability/index.ts +176 -27
  524. package/test/unit/spec/reachability/request.js +66 -0
  525. package/test/unit/spec/reconnection-manager/index.js +155 -9
  526. package/test/unit/spec/recording-controller/index.js +307 -0
  527. package/test/unit/spec/recording-controller/util.js +229 -0
  528. package/test/unit/spec/roap/index.ts +28 -52
  529. package/test/unit/spec/roap/request.ts +225 -0
  530. package/test/unit/spec/roap/turnDiscovery.ts +92 -50
  531. package/test/unit/spec/rtcMetrics/index.ts +60 -0
  532. package/test/unit/spec/stats-analyzer/index.js +116 -60
  533. package/test/utils/cmr.js +44 -42
  534. package/test/utils/constants.js +9 -0
  535. package/test/utils/integrationTestUtils.js +46 -0
  536. package/test/utils/testUtils.js +63 -99
  537. package/test/utils/webex-config.js +22 -18
  538. package/test/utils/webex-test-users.js +57 -50
  539. package/tsconfig.json +6 -0
  540. package/dist/media/internal-media-core-wrapper.js +0 -22
  541. package/dist/media/internal-media-core-wrapper.js.map +0 -1
  542. package/dist/meeting/effectsState.js +0 -327
  543. package/dist/meeting/effectsState.js.map +0 -1
  544. package/dist/metrics/config.js +0 -301
  545. package/dist/metrics/config.js.map +0 -1
  546. package/dist/multistream/multistreamMedia.js +0 -116
  547. package/dist/multistream/multistreamMedia.js.map +0 -1
  548. package/dist/peer-connection-manager/util.js +0 -124
  549. package/dist/peer-connection-manager/util.js.map +0 -1
  550. package/src/common/logs/logger-proxy.js +0 -33
  551. package/src/index.js +0 -15
  552. package/src/locus-info/controlsUtils.js +0 -102
  553. package/src/media/index.js +0 -459
  554. package/src/media/internal-media-core-wrapper.ts +0 -9
  555. package/src/mediaQualityMetrics/config.js +0 -382
  556. package/src/meeting/effectsState.js +0 -205
  557. package/src/meeting/index.js +0 -6284
  558. package/src/meeting/muteState.js +0 -318
  559. package/src/meeting/util.js +0 -506
  560. package/src/meeting-info/index.js +0 -131
  561. package/src/meeting-info/meeting-info-v2.js +0 -255
  562. package/src/meetings/index.js +0 -1015
  563. package/src/member/util.js +0 -254
  564. package/src/members/request.js +0 -131
  565. package/src/members/util.js +0 -258
  566. package/src/metrics/config.js +0 -324
  567. package/src/metrics/index.js +0 -530
  568. package/src/multistream/multistreamMedia.ts +0 -92
  569. package/src/peer-connection-manager/util.ts +0 -117
  570. package/src/roap/request.js +0 -127
  571. package/src/statsAnalyzer/global.js +0 -133
  572. package/src/statsAnalyzer/index.js +0 -1006
  573. package/src/statsAnalyzer/mqaUtil.js +0 -173
  574. package/test/unit/spec/meeting/effectsState.js +0 -291
  575. package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -389
  576. /package/src/common/errors/{reconnection-in-progress.js → reconnection-in-progress.ts} +0 -0
@@ -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';
@@ -27,8 +28,13 @@ import {
27
28
  ONLINE,
28
29
  ROAP,
29
30
  LOCUSINFO,
30
- EVENT_TRIGGERS
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 = {
@@ -37,19 +43,21 @@ describe('plugin-meetings', () => {
37
43
  error: () => {},
38
44
  warn: () => {},
39
45
  trace: () => {},
40
- debug: () => {}
46
+ debug: () => {},
41
47
  };
42
48
 
43
49
  beforeEach(() => {
44
50
  StaticConfig.set({
45
51
  bandwidth: {
46
- audio: 50, video: 500
47
- }
52
+ audio: 50,
53
+ video: 500,
54
+ },
48
55
  });
49
56
  LoggerConfig.set({
50
- verboseEvents: true, enable: false
57
+ verboseEvents: true,
58
+ enable: false,
51
59
  });
52
- TriggerProxy.trigger = sinon.stub().returns(true);
60
+ sinon.stub(TriggerProxy, 'trigger').returns(true);
53
61
  });
54
62
 
55
63
  let webex;
@@ -58,26 +66,30 @@ describe('plugin-meetings', () => {
58
66
  let url1;
59
67
  let test1;
60
68
  let test2;
69
+ let locusInfo;
61
70
 
62
71
  describe('meetings index', () => {
63
72
  beforeEach(() => {
64
73
  MeetingsUtil.checkH264Support = sinon.stub();
65
- uuid1 = uuid.v4();
74
+ uuid1 = uuid.v4();
66
75
  url1 = `https://example.com/${uuid.v4()}`;
67
76
  uri1 = `test-${uuid.v4()}@example.com`;
68
77
  test1 = `test-${uuid.v4()}`;
69
78
  test2 = `test2-${uuid.v4()}`;
79
+ locusInfo = {
80
+ parse: sinon.stub().returns(true),
81
+ updateMainSessionLocusCache: sinon.stub(),
82
+ };
70
83
  webex = new MockWebex({
71
84
  children: {
72
85
  device: Device,
73
86
  mercury: Mercury,
74
- meetings: Meetings
75
- }
87
+ meetings: Meetings,
88
+ },
76
89
  });
77
90
 
78
-
79
91
  Object.assign(webex, {
80
- logging: logger
92
+ logging: logger,
81
93
  });
82
94
 
83
95
  Object.assign(webex.meetings.config, {
@@ -86,68 +98,74 @@ describe('plugin-meetings', () => {
86
98
  // the server supports, minimums have to be tested
87
99
  audio: 64000,
88
100
  video: 4000000,
89
- startBitrate: 2000
101
+ startBitrate: 2000,
90
102
  },
91
103
  experimental: {
92
- enableUnifiedMeetings: true
104
+ enableUnifiedMeetings: true,
93
105
  },
94
106
  logging: {
95
107
  enable: true,
96
- verboseEvents: true
97
- }
108
+ verboseEvents: true,
109
+ },
98
110
  });
99
111
 
100
112
  Object.assign(webex, {
101
- logger
113
+ logger,
102
114
  });
103
115
 
104
116
  Object.assign(webex.meetings, {
105
- startReachability: sinon.stub().returns(Promise.resolve())
117
+ startReachability: sinon.stub().returns(Promise.resolve()),
106
118
  });
107
119
 
108
120
  Object.assign(webex.internal, {
121
+ llm: {on: sinon.stub()},
109
122
  device: {
110
123
  deviceType: 'FAKE_DEVICE',
111
124
  register: sinon.stub().returns(Promise.resolve()),
112
- unregister: sinon.stub().returns(Promise.resolve())
125
+ unregister: sinon.stub().returns(Promise.resolve()),
113
126
  },
114
127
  mercury: {
115
128
  connect: sinon.stub().returns(Promise.resolve()),
116
129
  disconnect: sinon.stub().returns(Promise.resolve()),
117
130
  on: () => {},
118
- off: () => {}
131
+ off: () => {},
119
132
  },
120
133
  services: {
121
- getMeetingPreferences: sinon.stub().returns(Promise.resolve({
122
- sites: [
123
- {
124
- siteUrl: 'site1-example.webex.com',
125
- default: false
126
- },
127
- {
128
- siteUrl: 'site2-example.webex.com',
129
- default: false
130
- },
131
- {
132
- siteUrl: 'site3-example.webex.com',
133
- default: false
134
- },
135
- {
136
- siteUrl: 'go.webex.com',
137
- default: true
138
- }
139
- ]
140
- })),
141
- fetchClientRegionInfo: sinon.stub().returns(Promise.resolve())
134
+ getMeetingPreferences: sinon.stub().returns(
135
+ Promise.resolve({
136
+ sites: [
137
+ {
138
+ siteUrl: 'site1-example.webex.com',
139
+ default: false,
140
+ },
141
+ {
142
+ siteUrl: 'site2-example.webex.com',
143
+ default: false,
144
+ },
145
+ {
146
+ siteUrl: 'site3-example.webex.com',
147
+ default: false,
148
+ },
149
+ {
150
+ siteUrl: 'go.webex.com',
151
+ default: true,
152
+ },
153
+ ],
154
+ })
155
+ ),
156
+ fetchClientRegionInfo: sinon.stub().returns(Promise.resolve()),
142
157
  },
143
158
  metrics: {
144
- submitClientMetrics: sinon.stub().returns(Promise.resolve())
145
- }
146
-
159
+ submitClientMetrics: sinon.stub().returns(Promise.resolve()),
160
+ },
147
161
  });
148
162
  webex.emit('ready');
149
163
  });
150
164
 
165
+ afterEach(() => {
166
+ sinon.restore();
167
+ });
168
+
151
169
  it('has a webex instance with a meetings property', () => {
152
170
  assert.exists(webex, 'webex was initialized with children');
153
171
  assert.exists(webex.meetings, 'meetings child was set up on the webex instance');
@@ -177,10 +195,14 @@ describe('plugin-meetings', () => {
177
195
 
178
196
  describe('failure', () => {
179
197
  it('should not accept non boolean input', () => {
180
- const currentEnableUnifiedMeetings = webex.meetings.config.experimental.enableUnifiedMeetings;
198
+ const currentEnableUnifiedMeetings =
199
+ webex.meetings.config.experimental.enableUnifiedMeetings;
181
200
 
182
201
  webex.meetings._toggleUnifiedMeetings('test');
183
- assert.equal(webex.meetings.config.experimental.enableUnifiedMeetings, currentEnableUnifiedMeetings);
202
+ assert.equal(
203
+ webex.meetings.config.experimental.enableUnifiedMeetings,
204
+ currentEnableUnifiedMeetings
205
+ );
184
206
  });
185
207
  });
186
208
  });
@@ -202,7 +224,10 @@ describe('plugin-meetings', () => {
202
224
  const currentEnableAdhocMeetings = webex.meetings.config.experimental.enableAdhocMeetings;
203
225
 
204
226
  webex.meetings._toggleAdhocMeetings('test');
205
- assert.equal(webex.meetings.config.experimental.enableAdhocMeetings, currentEnableAdhocMeetings);
227
+ assert.equal(
228
+ webex.meetings.config.experimental.enableAdhocMeetings,
229
+ currentEnableAdhocMeetings
230
+ );
206
231
  });
207
232
  });
208
233
  });
@@ -227,18 +252,25 @@ describe('plugin-meetings', () => {
227
252
  const currentEnableTurnDiscovery = webex.meetings.config.experimental.enableTurnDiscovery;
228
253
 
229
254
  webex.meetings._toggleTurnDiscovery('test');
230
- assert.equal(webex.meetings.config.experimental.enableAdhocMeetings, currentEnableTurnDiscovery);
255
+ assert.equal(
256
+ webex.meetings.config.experimental.enableAdhocMeetings,
257
+ currentEnableTurnDiscovery
258
+ );
231
259
  });
232
260
  });
233
261
  });
234
262
 
235
-
236
263
  describe('Public API Contracts', () => {
237
264
  describe('#register', () => {
238
265
  it('emits an event and resolves when register succeeds', async () => {
239
266
  webex.canAuthorize = true;
240
267
  await webex.meetings.register();
241
- assert.calledWith(TriggerProxy.trigger, sinon.match.instanceOf(Meetings), {file: 'meetings', function: 'register'}, 'meetings:registered');
268
+ assert.calledWith(
269
+ TriggerProxy.trigger,
270
+ sinon.match.instanceOf(Meetings),
271
+ {file: 'meetings', function: 'register'},
272
+ 'meetings:registered'
273
+ );
242
274
  assert.isTrue(webex.meetings.registered);
243
275
  });
244
276
 
@@ -284,9 +316,15 @@ describe('plugin-meetings', () => {
284
316
  it('emits an event and resolves when unregister succeeds', (done) => {
285
317
  webex.meetings.registered = true;
286
318
  webex.meetings.unregister().then(() => {
287
- assert.calledWith(TriggerProxy.trigger, sinon.match.instanceOf(Meetings), {
288
- file: 'meetings', function: 'unregister'
289
- }, 'meetings:unregistered');
319
+ assert.calledWith(
320
+ TriggerProxy.trigger,
321
+ sinon.match.instanceOf(Meetings),
322
+ {
323
+ file: 'meetings',
324
+ function: 'unregister',
325
+ },
326
+ 'meetings:unregistered'
327
+ );
290
328
  assert.isFalse(webex.meetings.registered);
291
329
  done();
292
330
  });
@@ -315,6 +353,100 @@ describe('plugin-meetings', () => {
315
353
  });
316
354
  });
317
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
+
318
450
  describe('gets', () => {
319
451
  describe('#getReachability', () => {
320
452
  it('should have #getReachability', () => {
@@ -324,7 +456,10 @@ describe('plugin-meetings', () => {
324
456
  it('does not get a reachability instance', () => {
325
457
  const reachability = webex.meetings.getReachability();
326
458
 
327
- assert.notExists(reachability, 'reachability is undefined because #setReachability has not been called');
459
+ assert.notExists(
460
+ reachability,
461
+ 'reachability is undefined because #setReachability has not been called'
462
+ );
328
463
  });
329
464
  });
330
465
  describe('after #setReachability', () => {
@@ -337,7 +472,10 @@ describe('plugin-meetings', () => {
337
472
  it('gets the reachability data instance from webex.meetings', () => {
338
473
  const reachability = webex.meetings.getReachability();
339
474
 
340
- assert.exists(reachability, 'reachability is defined because #setReachability has been called');
475
+ assert.exists(
476
+ reachability,
477
+ 'reachability is defined because #setReachability has been called'
478
+ );
341
479
  assert.instanceOf(reachability, Reachability, 'should be a reachability instance');
342
480
  });
343
481
  });
@@ -349,8 +487,15 @@ describe('plugin-meetings', () => {
349
487
  it('gets the personal meeting room instance from webex.meetings', () => {
350
488
  const personalMeetingRoom = webex.meetings.getPersonalMeetingRoom();
351
489
 
352
- assert.exists(personalMeetingRoom, 'personal meeting room instance is set up at object creation');
353
- assert.instanceOf(personalMeetingRoom, PersonalMeetingRoom, 'should be a personal meeting room instance');
490
+ assert.exists(
491
+ personalMeetingRoom,
492
+ 'personal meeting room instance is set up at object creation'
493
+ );
494
+ assert.instanceOf(
495
+ personalMeetingRoom,
496
+ PersonalMeetingRoom,
497
+ 'should be a personal meeting room instance'
498
+ );
354
499
  });
355
500
  });
356
501
  describe('Static shortcut proxy methods', () => {
@@ -379,11 +524,11 @@ describe('plugin-meetings', () => {
379
524
  describe('#getAllMeetings', () => {
380
525
  it('calls MeetingCollection to get all meetings with supplied options', () => {
381
526
  webex.meetings.getAllMeetings({
382
- test: test1
527
+ test: test1,
383
528
  });
384
529
  assert.calledOnce(webex.meetings.meetingCollection.getAll);
385
530
  assert.calledWith(webex.meetings.meetingCollection.getAll, {
386
- test: test1
531
+ test: test1,
387
532
  });
388
533
  });
389
534
  });
@@ -396,28 +541,28 @@ describe('plugin-meetings', () => {
396
541
  });
397
542
  describe('succesful requests', () => {
398
543
  beforeEach(() => {
399
- webex.meetings.request.getActiveMeetings = sinon.stub().returns(Promise.resolve({
400
- loci: [{
401
- url: url1
402
- }]
403
- }));
544
+ webex.meetings.request.getActiveMeetings = sinon.stub().returns(
545
+ Promise.resolve({
546
+ loci: [
547
+ {
548
+ url: url1,
549
+ },
550
+ ],
551
+ })
552
+ );
404
553
  });
405
554
  describe('when meeting is returned', () => {
406
- let parse;
407
555
 
408
556
  beforeEach(() => {
409
- parse = sinon.stub().returns(true);
410
557
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
411
- locusInfo: {
412
- parse
413
- }
558
+ locusInfo,
414
559
  });
415
560
  });
416
561
  it('tests the sync meeting calls for existing meeting', async () => {
417
562
  await webex.meetings.syncMeetings();
418
563
  assert.calledOnce(webex.meetings.request.getActiveMeetings);
419
564
  assert.calledOnce(webex.meetings.meetingCollection.getByKey);
420
- assert.calledOnce(parse);
565
+ assert.calledOnce(locusInfo.parse);
421
566
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
422
567
  });
423
568
  });
@@ -427,25 +572,32 @@ describe('plugin-meetings', () => {
427
572
  beforeEach(() => {
428
573
  initialSetup = sinon.stub().returns(true);
429
574
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns(null);
430
- webex.meetings.create = sinon.stub().returns(Promise.resolve({
431
- locusInfo: {
432
- initialSetup
433
- }
434
- }));
575
+ webex.meetings.create = sinon.stub().returns(
576
+ Promise.resolve({
577
+ locusInfo: {
578
+ ...locusInfo,
579
+ initialSetup,
580
+ },
581
+ })
582
+ );
435
583
  });
436
584
  it('tests the sync meeting calls for not existing meeting', async () => {
437
585
  await webex.meetings.syncMeetings();
438
586
  assert.calledOnce(webex.meetings.request.getActiveMeetings);
439
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
587
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
440
588
  assert.calledOnce(initialSetup);
441
589
  assert.calledOnce(webex.meetings.create);
442
590
  assert.calledWith(webex.meetings.request.getActiveMeetings);
443
591
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
444
- assert.calledWith(webex.meetings.create, {
445
- url: url1
446
- }, 'LOCUS_ID');
592
+ assert.calledWith(
593
+ webex.meetings.create,
594
+ {
595
+ url: url1,
596
+ },
597
+ 'LOCUS_ID'
598
+ );
447
599
  assert.calledWith(initialSetup, {
448
- url: url1
600
+ url: url1,
449
601
  });
450
602
  });
451
603
  });
@@ -456,28 +608,30 @@ describe('plugin-meetings', () => {
456
608
 
457
609
  beforeEach(() => {
458
610
  destroySpy = sinon.spy(webex.meetings, 'destroy');
459
- parse = sinon.stub().returns(true);
460
611
  initialSetup = sinon.stub().returns(true);
461
612
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
462
- locusInfo: {
463
- parse
464
- },
465
- sendCallAnalyzerMetrics: sinon.stub()
613
+ locusInfo,
614
+ sendCallAnalyzerMetrics: sinon.stub(),
466
615
  });
467
616
  webex.meetings.meetingCollection.getAll = sinon.stub().returns({
468
617
  meetingutk: {
469
- locusUrl: 'fdfdjfdhj', sendCallAnalyzerMetrics: sinon.stub()
470
- }
471
- });
472
- webex.meetings.create = sinon.stub().returns(Promise.resolve({
473
- locusInfo: {
474
- initialSetup
618
+ locusUrl: 'fdfdjfdhj',
619
+ sendCallAnalyzerMetrics: sinon.stub(),
475
620
  },
476
- sendCallAnalyzerMetrics: sinon.stub()
477
- }));
478
- webex.meetings.request.getActiveMeetings = sinon.stub().returns(Promise.resolve({
479
- loci: []
480
- }));
621
+ });
622
+ webex.meetings.create = sinon.stub().returns(
623
+ Promise.resolve({
624
+ locusInfo: {
625
+ initialSetup,
626
+ },
627
+ sendCallAnalyzerMetrics: sinon.stub(),
628
+ })
629
+ );
630
+ webex.meetings.request.getActiveMeetings = sinon.stub().returns(
631
+ Promise.resolve({
632
+ loci: [],
633
+ })
634
+ );
481
635
  MeetingUtil.cleanUp = sinon.stub().returns(Promise.resolve());
482
636
  });
483
637
  it('destroy non active meetings', async () => {
@@ -499,43 +653,52 @@ describe('plugin-meetings', () => {
499
653
  beforeEach(() => {
500
654
  infoOptions = {
501
655
  destination: 'dest-example',
502
- type: 'CONVERSATION_URL'
656
+ type: 'CONVERSATION_URL',
503
657
  };
504
658
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns();
505
- webex.meetings.createMeeting = sinon.stub().returns(Promise.resolve({
506
- on: () => true
507
- }));
659
+ webex.meetings.createMeeting = sinon.stub().returns(
660
+ Promise.resolve({
661
+ on: () => true,
662
+ })
663
+ );
508
664
  });
509
665
 
510
- it('should call MeetingInfo#fetchInfoOptions() with proper params',
511
- () => {
512
- webex.meetings.meetingInfo.fetchInfoOptions = sinon.stub().resolves(
513
- infoOptions
514
- );
666
+ it('should call MeetingInfo#fetchInfoOptions() with proper params', () => {
667
+ webex.meetings.meetingInfo.fetchInfoOptions = sinon.stub().resolves(infoOptions);
515
668
 
516
- return webex.meetings.create(
669
+ return webex.meetings.create(infoOptions.destination, infoOptions.type).then(() => {
670
+ assert.calledWith(
671
+ webex.meetings.meetingInfo.fetchInfoOptions,
517
672
  infoOptions.destination,
518
673
  infoOptions.type
519
- )
520
- .then(() => {
521
- assert.calledWith(
522
- webex.meetings.meetingInfo.fetchInfoOptions,
523
- infoOptions.destination,
524
- infoOptions.type
525
- );
674
+ );
526
675
 
527
- assert.calledTwice(webex.meetings.meetingCollection.getByKey);
528
- });
676
+ assert.calledTwice(webex.meetings.meetingCollection.getByKey);
529
677
  });
678
+ });
530
679
 
531
680
  it('calls createMeeting and returns its promise', async () => {
532
681
  const FAKE_USE_RANDOM_DELAY = true;
533
- const create = webex.meetings.create(test1, test2, FAKE_USE_RANDOM_DELAY);
682
+ const correlationId = 'my-correlationId';
683
+ const create = webex.meetings.create(test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId);
534
684
 
535
685
  assert.exists(create.then);
536
686
  await create;
537
687
  assert.calledOnce(webex.meetings.createMeeting);
538
- assert.calledWith(webex.meetings.createMeeting, test1, test2, FAKE_USE_RANDOM_DELAY);
688
+ assert.calledWith(webex.meetings.createMeeting, test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId);
689
+ });
690
+
691
+ it('calls createMeeting with extra info params and returns its promise', async () => {
692
+ const FAKE_USE_RANDOM_DELAY = false;
693
+ const correlationId = 'my-correlationId';
694
+
695
+ const FAKE_INFO_EXTRA_PARAMS = {mtid: 'm9fe0afd8c435e892afcce9ea25b97046', joinTXId: 'TSmrX61wNF'};
696
+ const create = webex.meetings.create(test1, test2, FAKE_USE_RANDOM_DELAY, FAKE_INFO_EXTRA_PARAMS, correlationId);
697
+
698
+ assert.exists(create.then);
699
+ await create;
700
+ assert.calledOnce(webex.meetings.createMeeting);
701
+ assert.calledWith(webex.meetings.createMeeting, test1, test2, FAKE_USE_RANDOM_DELAY, FAKE_INFO_EXTRA_PARAMS, correlationId);
539
702
  });
540
703
 
541
704
  it('creates a new meeting when a scheduled meeting exists in the conversation', async () => {
@@ -565,9 +728,9 @@ describe('plugin-meetings', () => {
565
728
  return undefined;
566
729
  });
567
730
 
568
- webex.meetings.meetingInfo.fetchInfoOptions = sinon.stub().resolves(
569
- scheduledMeetingFixture
570
- );
731
+ webex.meetings.meetingInfo.fetchInfoOptions = sinon
732
+ .stub()
733
+ .resolves(scheduledMeetingFixture);
571
734
 
572
735
  webex.meetings.meetingCollection.set(scheduledMeetingFixture);
573
736
 
@@ -602,99 +765,126 @@ describe('plugin-meetings', () => {
602
765
  it('doesnt call handle locus mercury for a locus roap event', () => {
603
766
  webex.meetings.handleLocusMercury({
604
767
  data: {
605
- eventType: 'locus.message.roap'
606
- }
768
+ eventType: 'locus.message.roap',
769
+ },
607
770
  });
608
771
  assert.notCalled(webex.meetings.handleLocusEvent);
609
772
  });
610
773
  it('doesnt call handle locus mercury for an undefined eventType', () => {
611
774
  webex.meetings.handleLocusMercury({
612
- data: {
613
- }
775
+ data: {},
614
776
  });
615
777
  assert.notCalled(webex.meetings.handleLocusEvent);
616
778
  });
617
779
  it('calls handle locus mercury for all locus events', () => {
618
780
  webex.meetings.handleLocusMercury({
619
781
  data: {
620
- eventType: test1
621
- }
782
+ eventType: test1,
783
+ },
622
784
  });
623
785
  assert.calledOnce(webex.meetings.handleLocusEvent);
624
- assert.calledWith(webex.meetings.handleLocusEvent, {
625
- eventType: test1
626
- }, true);
786
+ assert.calledWith(
787
+ webex.meetings.handleLocusEvent,
788
+ {
789
+ eventType: test1,
790
+ },
791
+ true
792
+ );
627
793
  });
628
794
  });
629
795
  describe('#handleLocusEvent', () => {
630
796
  describe('there was a meeting', () => {
631
- let parse;
632
797
 
633
798
  beforeEach(() => {
634
- parse = sinon.stub().returns(true);
635
799
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
636
- locusInfo: {
637
- parse
638
- }
800
+ locusInfo,
639
801
  });
640
802
  });
641
- it('should parse the meeting info', () => {
803
+ it('should parse the meeting info and update main session locus cache', () => {
804
+ sinon.stub(MeetingsUtil, 'isBreakoutLocusDTO').returns(false);
642
805
  webex.meetings.handleLocusEvent({
643
- locusUrl: url1
806
+ locusUrl: url1,
644
807
  });
645
808
  assert.calledOnce(webex.meetings.meetingCollection.getByKey);
646
809
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
647
- assert.calledOnce(parse);
648
- assert.calledWith(parse, {
649
- locusInfo: {
650
- parse
810
+ assert.calledOnce(locusInfo.parse);
811
+ assert.calledOnce(locusInfo.updateMainSessionLocusCache);
812
+ assert.calledWith(
813
+ locusInfo.parse,
814
+ {
815
+ locusInfo,
816
+ },
817
+ {
818
+ locusUrl: url1,
651
819
  }
652
- }, {
653
- locusUrl: url1
820
+ );
821
+ });
822
+
823
+ it('should not update main session locus cache', () => {
824
+ sinon.stub(MeetingsUtil, 'isBreakoutLocusDTO').returns(true);
825
+ webex.meetings.handleLocusEvent({
826
+ locusUrl: url1,
654
827
  });
828
+ assert.notCalled(locusInfo.updateMainSessionLocusCache);
655
829
  });
656
830
  });
657
831
  describe('there was not a meeting', () => {
658
832
  let initialSetup;
833
+ const webExMeetingId = '123456';
659
834
 
660
835
  beforeEach(() => {
661
836
  initialSetup = sinon.stub().returns(true);
662
837
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns(undefined);
663
- webex.meetings.create = sinon.stub().returns(Promise.resolve({
664
- locusInfo: {
665
- initialSetup
666
- }
667
- }));
838
+ webex.meetings.create = sinon.stub().returns(
839
+ Promise.resolve({
840
+ id: 'meeting-id',
841
+ locusInfo: {
842
+ ...locusInfo,
843
+ initialSetup,
844
+ },
845
+ })
846
+ );
668
847
  });
669
848
  it('should setup the meeting by difference event', async () => {
670
849
  await webex.meetings.handleLocusEvent({
671
850
  locus: {
672
851
  id: uuid1,
673
- replaces: [{
674
- locusUrl: 'http:locusUrl'
675
- }],
852
+ replaces: [
853
+ {
854
+ locusUrl: 'http:locusUrl',
855
+ },
856
+ ],
676
857
  self: {
677
858
  callBackInfo: {
678
- callbackAddress: uri1
679
- }
680
- }
859
+ callbackAddress: uri1,
860
+ },
861
+ },
862
+ info: {
863
+ webExMeetingId
864
+ },
681
865
  },
682
866
  eventType: 'locus.difference',
683
- locusUrl: url1
867
+ locusUrl: url1,
684
868
  });
685
- assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
869
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 6);
686
870
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
871
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
687
872
  assert.calledOnce(initialSetup);
688
873
  assert.calledWith(initialSetup, {
689
874
  id: uuid1,
690
- replaces: [{
691
- locusUrl: 'http:locusUrl'
692
- }],
875
+ replaces: [
876
+ {
877
+ locusUrl: 'http:locusUrl',
878
+ },
879
+ ],
693
880
  self: {
694
881
  callBackInfo: {
695
- callbackAddress: uri1
696
- }
697
- }
882
+ callbackAddress: uri1,
883
+ },
884
+ },
885
+ info: {
886
+ webExMeetingId
887
+ },
698
888
  });
699
889
  });
700
890
  it('should setup the meeting by difference event without replaces', async () => {
@@ -703,48 +893,95 @@ describe('plugin-meetings', () => {
703
893
  id: uuid1,
704
894
  self: {
705
895
  callBackInfo: {
706
- callbackAddress: uri1
707
- }
708
- }
896
+ callbackAddress: uri1,
897
+ },
898
+ },
899
+ info: {
900
+ webExMeetingId
901
+ },
709
902
  },
710
903
  eventType: 'locus.difference',
711
- locusUrl: url1
904
+ locusUrl: url1,
712
905
  });
713
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
906
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
714
907
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
908
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
715
909
  assert.calledOnce(initialSetup);
716
910
  assert.calledWith(initialSetup, {
717
911
  id: uuid1,
718
912
  self: {
719
913
  callBackInfo: {
720
- callbackAddress: uri1
721
- }
722
- }
914
+ callbackAddress: uri1,
915
+ },
916
+ },
917
+ info: {
918
+ webExMeetingId
919
+ },
723
920
  });
724
921
  });
922
+
923
+ it('sends client event correctly on finally', async () => {
924
+ webex.meetings.getMeetingByType = sinon.stub().returns(true);
925
+
926
+ await webex.meetings.handleLocusEvent({
927
+ locus: {
928
+ id: uuid1,
929
+ self: {
930
+ callBackInfo: {
931
+ callbackAddress: uri1,
932
+ },
933
+ },
934
+ info: {
935
+ webExMeetingId,
936
+ },
937
+ },
938
+ eventType: 'locus.difference',
939
+ locusUrl: url1,
940
+ });
941
+
942
+ await testUtils.flushPromises();
943
+
944
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
945
+ name: 'client.call.remote-started',
946
+ payload: {
947
+ trigger: 'mercury-event',
948
+ },
949
+ options: {
950
+ meetingId: 'meeting-id',
951
+ },
952
+ });
953
+ });
954
+
725
955
  it('should setup the meeting by a not difference event', async () => {
726
956
  await webex.meetings.handleLocusEvent({
727
957
  locus: {
728
958
  id: uuid1,
729
959
  self: {
730
960
  callBackInfo: {
731
- callbackAddress: uri1
732
- }
733
- }
961
+ callbackAddress: uri1,
962
+ },
963
+ },
964
+ info: {
965
+ webExMeetingId
966
+ },
734
967
  },
735
968
  eventType: test1,
736
- locusUrl: url1
969
+ locusUrl: url1,
737
970
  });
738
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
971
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
739
972
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
973
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', webExMeetingId);
740
974
  assert.calledOnce(initialSetup);
741
975
  assert.calledWith(initialSetup, {
742
976
  id: uuid1,
743
977
  self: {
744
978
  callBackInfo: {
745
- callbackAddress: uri1
746
- }
747
- }
979
+ callbackAddress: uri1,
980
+ },
981
+ },
982
+ info: {
983
+ webExMeetingId
984
+ },
748
985
  });
749
986
  });
750
987
 
@@ -753,13 +990,13 @@ describe('plugin-meetings', () => {
753
990
  id: uuid1,
754
991
  self: {
755
992
  callbackInfo: {
756
- callbackAddress: uri1
757
- }
993
+ callbackAddress: uri1,
994
+ },
758
995
  },
759
996
  info: {
760
- isUnifiedSpaceMeeting
997
+ isUnifiedSpaceMeeting,
761
998
  },
762
- conversationUrl: 'fakeConvoUrl'
999
+ conversationUrl: 'fakeConvoUrl',
763
1000
  },
764
1001
  eventType: test1,
765
1002
  locusUrl: url1,
@@ -767,19 +1004,40 @@ describe('plugin-meetings', () => {
767
1004
 
768
1005
  it('should not try to match USM meetings by conversation url', async () => {
769
1006
  await webex.meetings.handleLocusEvent(generateFakeLocusData(true));
770
- assert.callCount(webex.meetings.meetingCollection.getByKey, 3);
771
- assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, ['locusUrl', url1]);
772
- assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(1).args, ['correlationId', false]);
773
- assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(2).args, ['sipUri', uri1]);
1007
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
1008
+ assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, [
1009
+ 'locusUrl',
1010
+ url1,
1011
+ ]);
1012
+ assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(1).args, [
1013
+ 'correlationId',
1014
+ false,
1015
+ ]);
1016
+ assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(2).args, [
1017
+ 'sipUri',
1018
+ uri1,
1019
+ ]);
774
1020
  assert.calledOnce(initialSetup);
775
1021
  });
776
1022
  it('should try to match non-USM meetings by conversation url', async () => {
777
1023
  await webex.meetings.handleLocusEvent(generateFakeLocusData(false));
778
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
779
- assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, ['locusUrl', url1]);
780
- assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(1).args, ['correlationId', false]);
781
- assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(2).args, ['sipUri', uri1]);
782
- assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(3).args, ['conversationUrl', 'fakeConvoUrl']);
1024
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
1025
+ assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, [
1026
+ 'locusUrl',
1027
+ url1,
1028
+ ]);
1029
+ assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(1).args, [
1030
+ 'correlationId',
1031
+ false,
1032
+ ]);
1033
+ assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(2).args, [
1034
+ 'sipUri',
1035
+ uri1,
1036
+ ]);
1037
+ assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(3).args, [
1038
+ 'conversationUrl',
1039
+ 'fakeConvoUrl',
1040
+ ]);
783
1041
  assert.calledOnce(initialSetup);
784
1042
  });
785
1043
  });
@@ -794,15 +1052,19 @@ describe('plugin-meetings', () => {
794
1052
  });
795
1053
  describe('successful MeetingInfo.#fetchMeetingInfo', () => {
796
1054
  let clock, setTimeoutSpy, fakeMeetingStartTimeString, FAKE_TIME_TO_START;
1055
+ const FAKE_INFO_EXTRA_PARAMS = {mtid: 'm9fe0afd8c435e892afcce9ea25b97046', joinTXId: 'TSmrX61wNF'};
797
1056
 
798
1057
  beforeEach(() => {
799
1058
  clock = sinon.useFakeTimers();
800
1059
  setTimeoutSpy = sinon.spy(clock, 'setTimeout');
801
- webex.meetings.meetingInfo.fetchMeetingInfo = sinon.stub().returns(Promise.resolve({
802
- body: {
803
- permissionToken: 'PT', meetingJoinUrl: 'meetingJoinUrl'
804
- }
805
- }));
1060
+ webex.meetings.meetingInfo.fetchMeetingInfo = sinon.stub().returns(
1061
+ Promise.resolve({
1062
+ body: {
1063
+ permissionToken: 'PT',
1064
+ meetingJoinUrl: 'meetingJoinUrl',
1065
+ },
1066
+ })
1067
+ );
806
1068
  const nowTimeStamp = Date.now();
807
1069
 
808
1070
  FAKE_TIME_TO_START = 0.1 * 60 * 1000;
@@ -816,12 +1078,18 @@ describe('plugin-meetings', () => {
816
1078
  clock.restore();
817
1079
  });
818
1080
 
819
- const checkCreateWithoutDelay = (meeting, destination, type, expectedMeetingData = {}) => {
1081
+ const checkCreateWithoutDelay = (
1082
+ meeting,
1083
+ destination,
1084
+ type,
1085
+ extraParams = {},
1086
+ expectedMeetingData = {}
1087
+ ) => {
820
1088
  assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
821
1089
  assert.calledOnce(MeetingsUtil.getMeetingAddedType);
822
1090
  assert.notCalled(setTimeoutSpy);
823
- assert.calledThrice(TriggerProxy.trigger);
824
- assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, destination, type);
1091
+ assert.callCount(TriggerProxy.trigger, 4);
1092
+ assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, destination, type, null, null, undefined, undefined, extraParams, {meetingId: meeting.id});
825
1093
  assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
826
1094
 
827
1095
  if (expectedMeetingData.permissionToken) {
@@ -830,14 +1098,30 @@ describe('plugin-meetings', () => {
830
1098
  if (expectedMeetingData.meetingJoinUrl) {
831
1099
  assert.equal(meeting.meetingJoinUrl, expectedMeetingData.meetingJoinUrl);
832
1100
  }
1101
+ if(expectedMeetingData.correlationId) {
1102
+ assert.equal(meeting.correlationId, expectedMeetingData.correlationId);
1103
+ }
833
1104
  assert.equal(meeting.destination, destination);
834
1105
  assert.equal(meeting.destinationType, type);
835
- assert.calledWith(TriggerProxy.trigger, sinon.match.instanceOf(Meetings), {
836
- file: 'meetings', function: 'createMeeting'
837
- }, 'meeting:added', {
838
- meeting: sinon.match.instanceOf(Meeting), type: 'test meeting added type'
839
- });
840
- assert.calledWith(TriggerProxy.trigger, meeting, {file: 'meetings', function: 'fetchMeetingInfo'}, 'meeting:meetingInfoAvailable');
1106
+ assert.calledWith(
1107
+ TriggerProxy.trigger,
1108
+ sinon.match.instanceOf(Meetings),
1109
+ {
1110
+ file: 'meetings',
1111
+ function: 'createMeeting',
1112
+ },
1113
+ 'meeting:added',
1114
+ {
1115
+ meeting: sinon.match.instanceOf(Meeting),
1116
+ type: 'test meeting added type',
1117
+ }
1118
+ );
1119
+ assert.calledWith(
1120
+ TriggerProxy.trigger,
1121
+ meeting,
1122
+ {file: 'meetings', function: 'fetchMeetingInfo'},
1123
+ 'meeting:meetingInfoAvailable'
1124
+ );
841
1125
  };
842
1126
 
843
1127
  it('creates the meeting from a successful meeting info fetch promise testing', async () => {
@@ -845,80 +1129,120 @@ describe('plugin-meetings', () => {
845
1129
 
846
1130
  const expectedMeetingData = {
847
1131
  permissionToken: 'PT',
848
- meetingJoinUrl: 'meetingJoinUrl'
849
- };
850
-
851
- checkCreateWithoutDelay(meeting, 'test destination', 'test type', expectedMeetingData);
852
- });
853
-
854
- it('creates the meeting from a successful meeting info fetch meeting resolve testing', async () => {
855
- const meeting = await webex.meetings.createMeeting('test destination', 'test type');
856
- const expectedMeetingData = {
857
- permissionToken: 'PT',
858
- meetingJoinUrl: 'meetingJoinUrl'
1132
+ meetingJoinUrl: 'meetingJoinUrl',
1133
+ correlationId: meeting.id,
859
1134
  };
860
1135
 
861
- assert.instanceOf(meeting, Meeting, 'createMeeting should eventually resolve to a Meeting Object');
862
- checkCreateWithoutDelay(meeting, 'test destination', 'test type', expectedMeetingData);
1136
+ checkCreateWithoutDelay(meeting, 'test destination', 'test type', {}, expectedMeetingData);
863
1137
  });
864
1138
 
865
- it('creates the meeting from a successful meeting info fetch with random delay', async () => {
866
- const FAKE_LOCUS_MEETING = {
867
- conversationUrl: 'locusConvURL',
868
- url: 'locusUrl',
869
- info: {
870
- webExMeetingId: 'locusMeetingId',
871
- sipUri: 'locusSipUri',
872
- owner: 'locusOwner'
873
- },
874
- meeting: {
875
- startTime: fakeMeetingStartTimeString
876
- },
877
- fullState: {
878
- active: false
879
- }
880
- };
881
-
882
- const meeting = await webex.meetings.createMeeting(FAKE_LOCUS_MEETING, 'test type', true);
883
-
884
- assert.instanceOf(meeting, Meeting, 'createMeeting should eventually resolve to a Meeting Object');
885
- assert.notCalled(webex.meetings.meetingInfo.fetchMeetingInfo);
886
- assert.calledOnce(setTimeoutSpy);
887
-
888
- // Parse meeting info with locus object
889
- assert.equal(meeting.conversationUrl, 'locusConvURL');
890
- assert.equal(meeting.locusUrl, 'locusUrl');
891
- assert.equal(meeting.sipUri, 'locusSipUri');
892
- assert.equal(meeting.meetingNumber, 'locusMeetingId');
893
- assert.isUndefined(meeting.meetingJoinUrl);
894
- assert.equal(meeting.owner, 'locusOwner');
895
- assert.isUndefined(meeting.permissionToken);
896
-
897
- // Add meeting and send trigger
898
- assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
899
- assert.calledTwice(TriggerProxy.trigger);
900
- assert.calledWith(TriggerProxy.trigger, sinon.match.instanceOf(Meetings), {
901
- file: 'meetings', function: 'createMeeting'
902
- }, 'meeting:added', {
903
- meeting: sinon.match.instanceOf(Meeting), type: 'test meeting added type'
1139
+ [undefined, FAKE_INFO_EXTRA_PARAMS].forEach((infoExtraParams) => {
1140
+ const infoExtraParamsProvided = infoExtraParams !== undefined;
1141
+
1142
+ it(`creates the meeting from a successful meeting info fetch meeting resolve testing${infoExtraParamsProvided ? ' with infoExtraParams' : ''}`, async () => {
1143
+ const meeting = await webex.meetings.createMeeting('test destination', 'test type', false, infoExtraParams);
1144
+ const expectedMeetingData = {
1145
+ permissionToken: 'PT',
1146
+ meetingJoinUrl: 'meetingJoinUrl',
1147
+ };
1148
+
1149
+ assert.instanceOf(
1150
+ meeting,
1151
+ Meeting,
1152
+ 'createMeeting should eventually resolve to a Meeting Object'
1153
+ );
1154
+ checkCreateWithoutDelay(meeting, 'test destination', 'test type', infoExtraParamsProvided ? infoExtraParams : {}, expectedMeetingData);
904
1155
  });
905
1156
 
906
- // When timer expires
907
- clock.tick(FAKE_TIME_TO_START);
908
- assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, FAKE_LOCUS_MEETING, 'test type');
909
-
910
- // Parse meeting info is called again with new meeting info
911
- await testUtils.flushPromises();
912
- assert.equal(meeting.conversationUrl, 'locusConvURL');
913
- assert.equal(meeting.locusUrl, 'locusUrl');
914
- assert.equal(meeting.sipUri, 'locusSipUri');
915
- assert.equal(meeting.meetingNumber, 'locusMeetingId');
916
- assert.equal(meeting.meetingJoinUrl, 'meetingJoinUrl');
917
- assert.equal(meeting.owner, 'locusOwner');
918
- assert.equal(meeting.permissionToken, 'PT');
919
-
920
- assert.calledWith(TriggerProxy.trigger, meeting, {file: 'meetings', function: 'fetchMeetingInfo'}, 'meeting:meetingInfoAvailable');
921
- });
1157
+ it(`creates the meeting from a successful meeting info fetch with random delay${infoExtraParamsProvided ? ' with infoExtraParams' : ''}`, async () => {
1158
+ const FAKE_LOCUS_MEETING = {
1159
+ conversationUrl: 'locusConvURL',
1160
+ url: 'locusUrl',
1161
+ info: {
1162
+ webExMeetingId: 'locusMeetingId',
1163
+ sipUri: 'locusSipUri',
1164
+ owner: 'locusOwner',
1165
+ },
1166
+ meeting: {
1167
+ startTime: fakeMeetingStartTimeString,
1168
+ },
1169
+ fullState: {
1170
+ active: false,
1171
+ },
1172
+ };
1173
+
1174
+ const meeting = await webex.meetings.createMeeting(
1175
+ FAKE_LOCUS_MEETING,
1176
+ 'test type',
1177
+ true,
1178
+ infoExtraParams
1179
+ );
1180
+
1181
+ assert.instanceOf(
1182
+ meeting,
1183
+ Meeting,
1184
+ 'createMeeting should eventually resolve to a Meeting Object'
1185
+ );
1186
+ assert.notCalled(webex.meetings.meetingInfo.fetchMeetingInfo);
1187
+ assert.calledOnce(setTimeoutSpy);
1188
+
1189
+ // Parse meeting info with locus object
1190
+ assert.equal(meeting.conversationUrl, 'locusConvURL');
1191
+ assert.equal(meeting.locusUrl, 'locusUrl');
1192
+ assert.equal(meeting.sipUri, 'locusSipUri');
1193
+ assert.equal(meeting.meetingNumber, 'locusMeetingId');
1194
+ assert.isUndefined(meeting.meetingJoinUrl);
1195
+ assert.equal(meeting.owner, 'locusOwner');
1196
+ assert.isUndefined(meeting.permissionToken);
1197
+
1198
+ // Add meeting and send trigger
1199
+ assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
1200
+ assert.calledTwice(TriggerProxy.trigger);
1201
+ assert.calledWith(
1202
+ TriggerProxy.trigger,
1203
+ sinon.match.instanceOf(Meetings),
1204
+ {
1205
+ file: 'meetings',
1206
+ function: 'createMeeting',
1207
+ },
1208
+ 'meeting:added',
1209
+ {
1210
+ meeting: sinon.match.instanceOf(Meeting),
1211
+ type: 'test meeting added type',
1212
+ }
1213
+ );
1214
+
1215
+ // When timer expires
1216
+ clock.tick(FAKE_TIME_TO_START);
1217
+ assert.calledWith(
1218
+ webex.meetings.meetingInfo.fetchMeetingInfo,
1219
+ FAKE_LOCUS_MEETING,
1220
+ 'test type',
1221
+ null,
1222
+ null,
1223
+ undefined,
1224
+ undefined,
1225
+ infoExtraParamsProvided ? infoExtraParams : {}
1226
+ );
1227
+
1228
+ // Parse meeting info is called again with new meeting info
1229
+ await testUtils.flushPromises();
1230
+ assert.equal(meeting.conversationUrl, 'locusConvURL');
1231
+ assert.equal(meeting.locusUrl, 'locusUrl');
1232
+ assert.equal(meeting.sipUri, 'locusSipUri');
1233
+ assert.equal(meeting.meetingNumber, 'locusMeetingId');
1234
+ assert.equal(meeting.meetingJoinUrl, 'meetingJoinUrl');
1235
+ assert.equal(meeting.owner, 'locusOwner');
1236
+ assert.equal(meeting.permissionToken, 'PT');
1237
+
1238
+ assert.calledWith(
1239
+ TriggerProxy.trigger,
1240
+ meeting,
1241
+ {file: 'meetings', function: 'fetchMeetingInfo'},
1242
+ 'meeting:meetingInfoAvailable'
1243
+ );
1244
+ });
1245
+ })
922
1246
 
923
1247
  it('creates the meeting from a successful meeting info fetch that has no random delay because it is active', async () => {
924
1248
  const FAKE_LOCUS_MEETING = {
@@ -927,19 +1251,27 @@ describe('plugin-meetings', () => {
927
1251
  info: {
928
1252
  webExMeetingId: 'locusMeetingId',
929
1253
  sipUri: 'locusSipUri',
930
- owner: 'locusOwner'
1254
+ owner: 'locusOwner',
931
1255
  },
932
1256
  meeting: {
933
- startTime: fakeMeetingStartTimeString
1257
+ startTime: fakeMeetingStartTimeString,
934
1258
  },
935
1259
  fullState: {
936
- active: true
937
- }
1260
+ active: true,
1261
+ },
938
1262
  };
939
1263
 
940
- const meeting = await webex.meetings.createMeeting(FAKE_LOCUS_MEETING, 'test type', true);
1264
+ const meeting = await webex.meetings.createMeeting(
1265
+ FAKE_LOCUS_MEETING,
1266
+ 'test type',
1267
+ true
1268
+ );
941
1269
 
942
- assert.instanceOf(meeting, Meeting, 'createMeeting should eventually resolve to a Meeting Object');
1270
+ assert.instanceOf(
1271
+ meeting,
1272
+ Meeting,
1273
+ 'createMeeting should eventually resolve to a Meeting Object'
1274
+ );
943
1275
  checkCreateWithoutDelay(meeting, FAKE_LOCUS_MEETING, 'test type');
944
1276
  });
945
1277
 
@@ -950,27 +1282,35 @@ describe('plugin-meetings', () => {
950
1282
  info: {
951
1283
  webExMeetingId: 'locusMeetingId',
952
1284
  sipUri: 'locusSipUri',
953
- owner: 'locusOwner'
1285
+ owner: 'locusOwner',
954
1286
  },
955
1287
  meeting: {
956
- startTime: fakeMeetingStartTimeString - (1 * 60 * 60 * 1000)
1288
+ startTime: fakeMeetingStartTimeString - 1 * 60 * 60 * 1000,
957
1289
  },
958
1290
  fullState: {
959
- active: false
960
- }
1291
+ active: false,
1292
+ },
961
1293
  };
962
1294
 
963
- const meeting = await webex.meetings.createMeeting(FAKE_LOCUS_MEETING, 'test type', true);
1295
+ const meeting = await webex.meetings.createMeeting(
1296
+ FAKE_LOCUS_MEETING,
1297
+ 'test type',
1298
+ true
1299
+ );
964
1300
 
965
- assert.instanceOf(meeting, Meeting, 'createMeeting should eventually resolve to a Meeting Object');
1301
+ assert.instanceOf(
1302
+ meeting,
1303
+ Meeting,
1304
+ 'createMeeting should eventually resolve to a Meeting Object'
1305
+ );
966
1306
  checkCreateWithoutDelay(meeting, FAKE_LOCUS_MEETING, 'test type');
967
1307
  });
968
1308
 
969
1309
  it('creates the meeting from a successful meeting info fetch that has no random delay because enableUnifiedMeetings is disabled', async () => {
970
1310
  Object.assign(webex.meetings.config, {
971
1311
  experimental: {
972
- enableUnifiedMeetings: false
973
- }
1312
+ enableUnifiedMeetings: false,
1313
+ },
974
1314
  });
975
1315
  const FAKE_LOCUS_MEETING = {
976
1316
  conversationUrl: 'locusConvURL',
@@ -978,45 +1318,138 @@ describe('plugin-meetings', () => {
978
1318
  info: {
979
1319
  webExMeetingId: 'locusMeetingId',
980
1320
  sipUri: 'locusSipUri',
981
- owner: 'locusOwner'
1321
+ owner: 'locusOwner',
982
1322
  },
983
1323
  meeting: {
984
- startTime: fakeMeetingStartTimeString
1324
+ startTime: fakeMeetingStartTimeString,
985
1325
  },
986
1326
  fullState: {
987
- active: false
988
- }
1327
+ active: false,
1328
+ },
989
1329
  };
990
1330
 
991
- const meeting = await webex.meetings.createMeeting(FAKE_LOCUS_MEETING, 'test type', true);
1331
+ const meeting = await webex.meetings.createMeeting(
1332
+ FAKE_LOCUS_MEETING,
1333
+ 'test type',
1334
+ true
1335
+ );
992
1336
 
993
- assert.instanceOf(meeting, Meeting, 'createMeeting should eventually resolve to a Meeting Object');
1337
+ assert.instanceOf(
1338
+ meeting,
1339
+ Meeting,
1340
+ 'createMeeting should eventually resolve to a Meeting Object'
1341
+ );
994
1342
  checkCreateWithoutDelay(meeting, FAKE_LOCUS_MEETING, 'test type');
995
1343
  });
1344
+
1345
+ it('creates meeting with the correlationId provided', async () => {
1346
+ const meeting = await webex.meetings.createMeeting('test destination', 'test type', false, {}, 'my-correlationId');
1347
+
1348
+ const expectedMeetingData = {
1349
+ correlationId: 'my-correlationId',
1350
+ };
1351
+
1352
+ checkCreateWithoutDelay(meeting, 'test destination', 'test type', {}, expectedMeetingData);
1353
+ })
996
1354
  });
997
1355
 
998
1356
  describe('rejected MeetingInfo.#fetchMeetingInfo', () => {
999
1357
  beforeEach(() => {
1000
1358
  console.error = sinon.stub().returns(false);
1001
1359
  TriggerProxy.trigger.reset();
1002
- webex.meetings.meetingInfo.fetchMeetingInfo = sinon.stub().returns(Promise.reject(new Error('test')));
1360
+ webex.meetings.meetingInfo.fetchMeetingInfo = sinon
1361
+ .stub()
1362
+ .returns(Promise.reject(new Error('test')));
1003
1363
  });
1004
1364
  it('creates the meeting from a rejected meeting info fetch', async () => {
1005
1365
  const meeting = await webex.meetings.createMeeting('test destination', 'test type');
1006
1366
 
1007
- assert.instanceOf(meeting, Meeting, 'createMeeting should eventually resolve to a Meeting Object');
1367
+ assert.instanceOf(
1368
+ meeting,
1369
+ Meeting,
1370
+ 'createMeeting should eventually resolve to a Meeting Object'
1371
+ );
1008
1372
  assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
1009
1373
  assert.calledOnce(MeetingsUtil.getMeetingAddedType);
1010
1374
  assert.calledTwice(TriggerProxy.trigger);
1011
- assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, 'test destination', 'test type');
1375
+ assert.calledWith(
1376
+ webex.meetings.meetingInfo.fetchMeetingInfo,
1377
+ 'test destination',
1378
+ 'test type'
1379
+ );
1012
1380
  assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
1013
- assert.calledWith(TriggerProxy.trigger, sinon.match.instanceOf(Meetings), {
1014
- file: 'meetings', function: 'createMeeting'
1015
- }, 'meeting:added', {
1016
- meeting: sinon.match.instanceOf(Meeting), type: 'test meeting added type'
1017
- });
1381
+ assert.calledWith(
1382
+ TriggerProxy.trigger,
1383
+ sinon.match.instanceOf(Meetings),
1384
+ {
1385
+ file: 'meetings',
1386
+ function: 'createMeeting',
1387
+ },
1388
+ 'meeting:added',
1389
+ {
1390
+ meeting: sinon.match.instanceOf(Meeting),
1391
+ type: 'test meeting added type',
1392
+ }
1393
+ );
1018
1394
  });
1019
1395
  });
1396
+
1397
+ describe('rejected MeetingInfo.#fetchMeetingInfo - does not log for known Error types', () => {
1398
+ forEach(
1399
+ [
1400
+ {
1401
+ error: new CaptchaError(),
1402
+ debugLogMessage:
1403
+ 'Meetings:index#createMeeting --> Debug CaptchaError: Captcha is required. fetching /meetingInfo for creation.',
1404
+ },
1405
+ {
1406
+ error: new PasswordError(),
1407
+ debugLogMessage:
1408
+ 'Meetings:index#createMeeting --> Debug PasswordError: Password is required, please use verifyPassword() fetching /meetingInfo for creation.',
1409
+ },
1410
+ {
1411
+ error: new PermissionError(),
1412
+ debugLogMessage:
1413
+ '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.',
1414
+ },
1415
+ {
1416
+ error: new Error(),
1417
+ infoLogMessage: true,
1418
+ debugLogMessage:
1419
+ 'Meetings:index#createMeeting --> Debug Error fetching /meetingInfo for creation.',
1420
+ },
1421
+ ],
1422
+ ({error, debugLogMessage, infoLogMessage}) => {
1423
+ it('creates the meeting from a rejected meeting info fetch', async () => {
1424
+ webex.meetings.meetingInfo.fetchMeetingInfo = sinon
1425
+ .stub()
1426
+ .returns(Promise.reject(error));
1427
+
1428
+ LoggerProxy.logger.debug = sinon.stub();
1429
+ LoggerProxy.logger.info = sinon.stub();
1430
+
1431
+ const meeting = await webex.meetings.createMeeting('test destination', 'test type');
1432
+
1433
+ assert.instanceOf(
1434
+ meeting,
1435
+ Meeting,
1436
+ 'createMeeting should eventually resolve to a Meeting Object'
1437
+ );
1438
+
1439
+ assert.calledWith(LoggerProxy.logger.debug, debugLogMessage);
1440
+
1441
+ if (infoLogMessage) {
1442
+ assert.calledWith(
1443
+ LoggerProxy.logger.info,
1444
+ 'Meetings:index#createMeeting --> Info Unable to fetch meeting info for test destination.'
1445
+ );
1446
+ } else {
1447
+ assert.notCalled(LoggerProxy.logger.info);
1448
+ }
1449
+ });
1450
+ }
1451
+ );
1452
+ });
1020
1453
  });
1021
1454
  });
1022
1455
  describe('Public Event Triggers', () => {
@@ -1039,11 +1472,19 @@ describe('plugin-meetings', () => {
1039
1472
 
1040
1473
  assert.calledOnce(webex.meetings.meetingCollection.delete);
1041
1474
  assert.calledWith(webex.meetings.meetingCollection.delete, meeting.id);
1042
- assert.calledWith(TriggerProxy.trigger, sinon.match.instanceOf(Meetings), {
1043
- file: 'meetings', function: 'destroy'
1044
- }, 'meeting:removed', {
1045
- meetingId: meeting.id, reason: test1
1046
- });
1475
+ assert.calledWith(
1476
+ TriggerProxy.trigger,
1477
+ sinon.match.instanceOf(Meetings),
1478
+ {
1479
+ file: 'meetings',
1480
+ function: 'destroy',
1481
+ },
1482
+ 'meeting:removed',
1483
+ {
1484
+ meetingId: meeting.id,
1485
+ reason: test1,
1486
+ }
1487
+ );
1047
1488
  });
1048
1489
  });
1049
1490
 
@@ -1068,7 +1509,8 @@ describe('plugin-meetings', () => {
1068
1509
  it('should trigger event upon mercury disconnect', () => {
1069
1510
  const {meetings} = webex;
1070
1511
  const SCOPE = {
1071
- file: 'meetings/index', function: 'handleMercuryOffline'
1512
+ file: 'meetings/index',
1513
+ function: 'handleMercuryOffline',
1072
1514
  };
1073
1515
  const EVENT = 'network:disconnected';
1074
1516
 
@@ -1086,6 +1528,9 @@ describe('plugin-meetings', () => {
1086
1528
  });
1087
1529
 
1088
1530
  describe('#fetchUserPreferredWebexSite', () => {
1531
+
1532
+ let loggerProxySpy;
1533
+
1089
1534
  it('should call request.getMeetingPreferences to get the preferred webex site ', async () => {
1090
1535
  assert.isDefined(webex.meetings.preferredWebexSite);
1091
1536
  await webex.meetings.fetchUserPreferredWebexSite();
@@ -1093,19 +1538,89 @@ describe('plugin-meetings', () => {
1093
1538
  assert.equal(webex.meetings.preferredWebexSite, 'go.webex.com');
1094
1539
  });
1095
1540
 
1541
+ const setup = ({user} = {}) => {
1542
+ loggerProxySpy = sinon.spy(LoggerProxy.logger, 'error');
1543
+
1544
+ Object.assign(webex.internal, {
1545
+ services: {
1546
+ getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
1547
+ },
1548
+ user: {
1549
+ get: sinon.stub().returns(
1550
+ Promise.resolve(user)
1551
+ ),
1552
+ },
1553
+ });
1554
+ }
1555
+
1096
1556
  it('should not fail if UserPreferred info is not fetched ', async () => {
1557
+ setup();
1558
+
1097
1559
  Object.assign(webex.internal, {
1098
1560
  services: {
1099
1561
  getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
1100
1562
  },
1563
+ });
1101
1564
 
1565
+ await webex.meetings.fetchUserPreferredWebexSite().then(() => {
1566
+ assert.equal(webex.meetings.preferredWebexSite, '');
1102
1567
  });
1568
+ assert.calledOnceWithExactly(
1569
+ loggerProxySpy,
1570
+ 'Failed to fetch preferred site from user - no site will be set'
1571
+ );
1572
+ });
1103
1573
 
1104
- await webex.meetings.fetchUserPreferredWebexSite()
1105
- .then(() => {
1106
- assert.equal(webex.meetings.preferredWebexSite, '');
1107
- });
1574
+ it('should fall back to fetching the site from the user', async () => {
1575
+ setup({
1576
+ user: {
1577
+ userPreferences: {
1578
+ userPreferencesItems: {
1579
+ preferredWebExSite: 'site.webex.com',
1580
+ },
1581
+ },
1582
+ },
1583
+ });
1584
+
1585
+ await webex.meetings.fetchUserPreferredWebexSite();
1586
+
1587
+ assert.equal(webex.meetings.preferredWebexSite, 'site.webex.com');
1588
+ assert.notCalled(loggerProxySpy);
1589
+ });
1590
+
1591
+ forEach([
1592
+ {user: undefined},
1593
+ {user: {userPreferences: {}}},
1594
+ {user: {userPreferences: {userPreferencesItems: {}}}},
1595
+ {user: {userPreferences: {userPreferencesItems: {preferredWebExSite: undefined}}}},
1596
+ ], ({user}) => {
1597
+ it(`should handle invalid user data ${user}`, async () => {
1598
+ setup({user});
1599
+
1600
+ await webex.meetings.fetchUserPreferredWebexSite();
1601
+
1602
+ assert.equal(webex.meetings.preferredWebexSite, '');
1603
+ assert.calledOnceWithExactly(
1604
+ loggerProxySpy,
1605
+ 'Failed to fetch preferred site from user - no site will be set'
1606
+ );
1607
+ });
1108
1608
  });
1609
+
1610
+ it('should handle a get user failure', async () => {
1611
+ setup();
1612
+
1613
+ webex.internal.user.get.rejects(new Error());
1614
+
1615
+ await webex.meetings.fetchUserPreferredWebexSite();
1616
+
1617
+ assert.equal(webex.meetings.preferredWebexSite, '');
1618
+ assert.calledOnceWithExactly(
1619
+ loggerProxySpy,
1620
+ 'Failed to fetch preferred site from user - no site will be set'
1621
+ );
1622
+ });
1623
+
1109
1624
  });
1110
1625
  });
1111
1626
 
@@ -1120,11 +1635,14 @@ describe('plugin-meetings', () => {
1120
1635
  TriggerProxy.trigger.reset();
1121
1636
  // clock = sinon.useFakeTimers();
1122
1637
  // setTimeoutSpy = sinon.spy(clock, 'setTimeout');
1123
- webex.meetings.meetingInfo.fetchMeetingInfo = sinon.stub().returns(Promise.resolve({
1124
- body: {
1125
- permissionToken: 'PT', meetingJoinUrl: 'meetingJoinUrl'
1126
- }
1127
- }));
1638
+ webex.meetings.meetingInfo.fetchMeetingInfo = sinon.stub().returns(
1639
+ Promise.resolve({
1640
+ body: {
1641
+ permissionToken: 'PT',
1642
+ meetingJoinUrl: 'meetingJoinUrl',
1643
+ },
1644
+ })
1645
+ );
1128
1646
 
1129
1647
  meeting = await webex.meetings.createMeeting('test destination', 'test type');
1130
1648
 
@@ -1132,37 +1650,37 @@ describe('plugin-meetings', () => {
1132
1650
  });
1133
1651
 
1134
1652
  it('triggers correct event when CONTROLS_ENTRY_EXIT_TONE_UPDATED emitted', async () => {
1135
- await meeting.locusInfo.emitScoped(
1136
- {},
1137
- LOCUSINFO.EVENTS.CONTROLS_ENTRY_EXIT_TONE_UPDATED,
1138
- {entryExitTone: 'foo'}
1139
- );
1653
+ await meeting.locusInfo.emitScoped({}, LOCUSINFO.EVENTS.CONTROLS_ENTRY_EXIT_TONE_UPDATED, {
1654
+ entryExitTone: 'foo',
1655
+ });
1140
1656
 
1141
1657
  assert.calledOnce(TriggerProxy.trigger);
1142
- assert.calledWith(TriggerProxy.trigger, sinon.match.instanceOf(Meeting),
1658
+ assert.calledWith(
1659
+ TriggerProxy.trigger,
1660
+ sinon.match.instanceOf(Meeting),
1143
1661
  {
1144
1662
  file: 'meeting/index',
1145
- function: 'setupLocusControlsListener'
1663
+ function: 'setupLocusControlsListener',
1146
1664
  },
1147
1665
  EVENT_TRIGGERS.MEETING_ENTRY_EXIT_TONE_UPDATE,
1148
- {entryExitTone: 'foo'});
1666
+ {entryExitTone: 'foo'}
1667
+ );
1149
1668
  });
1150
1669
 
1151
1670
  const checkSelfTrigger = async (inEvent, outEvent) => {
1152
- await meeting.locusInfo.emitScoped(
1153
- {},
1154
- inEvent,
1155
- {foo: 'bar'}
1156
- );
1671
+ await meeting.locusInfo.emitScoped({}, inEvent, {foo: 'bar'});
1157
1672
 
1158
1673
  assert.calledOnce(TriggerProxy.trigger);
1159
- assert.calledWith(TriggerProxy.trigger, sinon.match.instanceOf(Meeting),
1674
+ assert.calledWith(
1675
+ TriggerProxy.trigger,
1676
+ sinon.match.instanceOf(Meeting),
1160
1677
  {
1161
1678
  file: 'meeting/index',
1162
- function: 'setUpLocusInfoSelfListener'
1679
+ function: 'setUpLocusInfoSelfListener',
1163
1680
  },
1164
1681
  outEvent,
1165
- {payload: {foo: 'bar'}});
1682
+ {payload: {foo: 'bar'}}
1683
+ );
1166
1684
  };
1167
1685
 
1168
1686
  it('triggers correct event when SELF_CANNOT_VIEW_PARTICIPANT_LIST_CHANGE emitted', async () => {
@@ -1186,5 +1704,411 @@ describe('plugin-meetings', () => {
1186
1704
  );
1187
1705
  });
1188
1706
  });
1707
+
1708
+ describe('#isNeedHandleMainLocus', () => {
1709
+ let meeting;
1710
+ let newLocus;
1711
+ beforeEach(() => {
1712
+ meeting = {
1713
+ controls: {},
1714
+ self: {},
1715
+ };
1716
+ newLocus = {
1717
+ controls: {},
1718
+ self: {},
1719
+ }
1720
+ });
1721
+ afterEach(() => {
1722
+ sinon.restore();
1723
+ });
1724
+ it('check normal case will return true', () => {
1725
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns(null);
1726
+ LoggerProxy.logger.log = sinon.stub();
1727
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1728
+ assert.equal(result, true);
1729
+ assert.calledWith(
1730
+ LoggerProxy.logger.log,
1731
+ 'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
1732
+ );
1733
+ });
1734
+
1735
+ it('check self joined and joined on this device, return true', () => {
1736
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns(null);
1737
+ newLocus.self.state = 'JOINED';
1738
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
1739
+
1740
+ LoggerProxy.logger.log = sinon.stub();
1741
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1742
+ assert.equal(result, true);
1743
+ assert.calledWith(
1744
+ LoggerProxy.logger.log,
1745
+ 'Meetings:index#isNeedHandleMainLocus --> self this device shown as JOINED in the main session'
1746
+ );
1747
+ });
1748
+
1749
+ it('if newLocus replaceAt time is expired, then return false', () => {
1750
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({joinedWith: {replaces: [{
1751
+ replaceAt: '2023-03-27T02:17:02.506Z',
1752
+ }]}});
1753
+ newLocus.self.state = 'JOINED';
1754
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
1755
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1756
+ replaces: [{
1757
+ replaceAt: '2023-03-27T02:17:01.506Z'
1758
+ }]
1759
+ })
1760
+
1761
+ LoggerProxy.logger.log = sinon.stub();
1762
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1763
+ assert.equal(result, false);
1764
+ assert.calledWith(
1765
+ LoggerProxy.logger.log,
1766
+ `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`
1767
+ );
1768
+ });
1769
+
1770
+ it('check current is in breakout join with this device, return false', () => {
1771
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({
1772
+ joinedWith: {
1773
+ correlationId: '111',
1774
+ },
1775
+ });
1776
+ newLocus.controls.breakout = {url: 'url'};
1777
+ meeting.correlationId = '111';
1778
+
1779
+ LoggerProxy.logger.log = sinon.stub();
1780
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1781
+ assert.equal(result, false);
1782
+ assert.calledWith(
1783
+ LoggerProxy.logger.log,
1784
+ `Meetings:index#isNeedHandleMainLocus --> there is active breakout session and joined on this device, and don't need to handle main session: url`
1785
+ );
1786
+ });
1787
+
1788
+ it('check self is moved and removed, return false', () => {
1789
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1790
+ newLocus.self.state = 'LEFT';
1791
+ newLocus.self.reason = 'MOVED';
1792
+ newLocus.self.removed = true;
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 moved and device resource removed, return false', () => {
1803
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1804
+ newLocus.self.state = 'LEFT';
1805
+ newLocus.self.reason = 'MOVED';
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 moved main locus with self removed status or with device resource moved, not need to handle'
1816
+ );
1817
+ });
1818
+
1819
+ it('check self is joined but device resource removed, return false', () => {
1820
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1821
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(false);
1822
+ newLocus.self.state = 'JOINED';
1823
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1824
+ state: 'LEFT',
1825
+ reason: 'MOVED',
1826
+ });
1827
+ LoggerProxy.logger.log = sinon.stub();
1828
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1829
+ assert.equal(result, false);
1830
+ assert.calledWith(
1831
+ LoggerProxy.logger.log,
1832
+ 'Meetings:index#isNeedHandleMainLocus --> self device left&moved in main locus with self joined status, not need to handle'
1833
+ );
1834
+ });
1835
+ });
1836
+
1837
+ describe('#isNeedHandleLocusDTO', () => {
1838
+ let meeting;
1839
+ let newLocus;
1840
+ beforeEach(() => {
1841
+ meeting = {
1842
+ controls: {},
1843
+ self: {},
1844
+ };
1845
+ newLocus = {
1846
+ controls: {},
1847
+ self: {},
1848
+ }
1849
+ });
1850
+ afterEach(() => {
1851
+ sinon.restore();
1852
+ });
1853
+ it('initial DTO , joined breakout session, return true', () => {
1854
+ newLocus.controls.breakout = {
1855
+ sessionType: 'BREAKOUT',
1856
+ };
1857
+ newLocus.self.state = 'JOINED';
1858
+ newLocus.fullState = {
1859
+ active: true,
1860
+ };
1861
+ LoggerProxy.logger.log = sinon.stub();
1862
+ const result = webex.meetings.isNeedHandleLocusDTO(null, newLocus);
1863
+ assert.equal(result, true);
1864
+ assert.calledWith(
1865
+ LoggerProxy.logger.log,
1866
+ `Meetings:index#isNeedHandleLocusDTO --> the first breakout session locusDTO active status: true`
1867
+ );
1868
+ });
1869
+ it('others go to check isNeedHandleMainLocus', () => {
1870
+ newLocus.controls.breakout = {
1871
+ sessionType: 'MAIN',
1872
+ };
1873
+ newLocus.self.state = 'JOINED';
1874
+
1875
+ LoggerProxy.logger.log = sinon.stub();
1876
+ const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
1877
+ assert.equal(result, true);
1878
+ assert.calledWith(
1879
+ LoggerProxy.logger.log,
1880
+ 'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
1881
+ );
1882
+ });
1883
+ it('joined breakout session, self status is moved, return false', () => {
1884
+ newLocus.controls.breakout = {
1885
+ sessionType: 'BREAKOUT',
1886
+ };
1887
+ newLocus.self.state = 'LEFT';
1888
+ newLocus.self.reason = 'MOVED';
1889
+
1890
+ LoggerProxy.logger.log = sinon.stub();
1891
+ const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
1892
+ assert.equal(result, false);
1893
+ });
1894
+ });
1895
+
1896
+ describe('#getCorrespondingMeetingByLocus', () => {
1897
+ let locus;
1898
+ let mockReturnMeeting = {meeting: 'meeting1'};
1899
+ const mockGetByKey = (keyWillReturnMeeting) => {
1900
+ webex.meetings.meetingCollection.getByKey = sinon.stub().callsFake((key) => {
1901
+ if (key === keyWillReturnMeeting) {
1902
+ return mockReturnMeeting;
1903
+ }
1904
+ return null;
1905
+ });
1906
+ };
1907
+
1908
+ beforeEach(() => {
1909
+ locus = {
1910
+ controls: {},
1911
+ self: {
1912
+ callbackInfo: {
1913
+ callbackAddress: 'address1',
1914
+ }
1915
+ },
1916
+ info: {
1917
+ webExMeetingId: '123456',
1918
+ isUnifiedSpaceMeeting: false,
1919
+ },
1920
+ conversationUrl: 'conversationUrl1'
1921
+ };
1922
+
1923
+ sinon.stub(MeetingsUtil, 'checkForCorrelationId').returns('correlationId1');
1924
+ });
1925
+ afterEach(() => {
1926
+ sinon.restore();
1927
+ });
1928
+ it('check the calls when no meeting found in meetingCollection', () => {
1929
+ mockGetByKey();
1930
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1931
+ assert.isNull(result);
1932
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
1933
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1934
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1935
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1936
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'conversationUrl', 'conversationUrl1');
1937
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', '123456');
1938
+ });
1939
+
1940
+ it('not try getByKey "conversationUrl" when isUnifiedSpaceMeeting is true', () => {
1941
+ mockGetByKey();
1942
+ locus.info.isUnifiedSpaceMeeting = true;
1943
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1944
+ assert.isNull(result);
1945
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
1946
+ })
1947
+
1948
+ it('check the calls when meeting found by key: locusUrl', () => {
1949
+ mockGetByKey('locusUrl');
1950
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1951
+ assert.deepEqual(result, mockReturnMeeting);
1952
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 1);
1953
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1954
+ });
1955
+
1956
+ it('check the calls when meeting found by key: correlationId', () => {
1957
+ mockGetByKey('correlationId');
1958
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1959
+ assert.deepEqual(result, mockReturnMeeting);
1960
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 2);
1961
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1962
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1963
+ });
1964
+
1965
+ it('check the calls when meeting found by key: sipUri', () => {
1966
+ mockGetByKey('sipUri');
1967
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1968
+ assert.deepEqual(result, mockReturnMeeting);
1969
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 3);
1970
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1971
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1972
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1973
+ });
1974
+
1975
+ it('check the calls when meeting found by key: conversationUrl', () => {
1976
+ mockGetByKey('conversationUrl');
1977
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1978
+ assert.deepEqual(result, mockReturnMeeting);
1979
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
1980
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1981
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1982
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1983
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'conversationUrl', 'conversationUrl1');
1984
+ });
1985
+
1986
+ it('check the calls when meeting found by key: meetingNumber', () => {
1987
+ mockGetByKey('meetingNumber');
1988
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
1989
+ assert.deepEqual(result, mockReturnMeeting);
1990
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
1991
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
1992
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'correlationId', 'correlationId1');
1993
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
1994
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'conversationUrl', 'conversationUrl1');
1995
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', '123456');
1996
+ });
1997
+ });
1998
+
1999
+ describe('#sortLocusArrayToUpdate', () => {
2000
+ let lociArray;
2001
+ let mainLocus;
2002
+ let breakoutLocus;
2003
+ beforeEach(() => {
2004
+ mainLocus = {
2005
+ url: 'mainUrl1',
2006
+ controls: {
2007
+ breakout: {
2008
+ sessionType: 'MAIN',
2009
+ url: 'breakoutUnifiedUrl1'
2010
+ }
2011
+ }
2012
+ };
2013
+ breakoutLocus = {
2014
+ url: 'breakoutUrl1',
2015
+ controls: {
2016
+ breakout: {
2017
+ sessionType: 'BREAKOUT',
2018
+ url: 'breakoutUnifiedUrl1'
2019
+ }
2020
+ }
2021
+ };
2022
+ lociArray = [mainLocus, breakoutLocus];
2023
+
2024
+ sinon.stub(MeetingsUtil, 'isValidBreakoutLocus').callsFake((locus) => {
2025
+ return locus.url === 'breakoutUrl1';
2026
+ });
2027
+ });
2028
+ afterEach(() => {
2029
+ sinon.restore();
2030
+ });
2031
+
2032
+ it('if both main and breakout locus is in array for non-exist meeting, return main locus to create first', () => {
2033
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns(undefined);
2034
+ const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
2035
+ assert.deepEqual(result, [mainLocus]);
2036
+ assert.deepEqual(webex.meetings.breakoutLocusForHandleLater, [breakoutLocus]);
2037
+ });
2038
+
2039
+ it('if both main and breakout locus is in array for an exist meeting, return all locus', () => {
2040
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns({});
2041
+ const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
2042
+ assert.deepEqual(result, [mainLocus, breakoutLocus]);
2043
+ assert.deepEqual(webex.meetings.breakoutLocusForHandleLater, []);
2044
+ });
2045
+
2046
+ it('if the breakout locus has no associated main locus, return all', () => {
2047
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns({});
2048
+ breakoutLocus.controls.breakout.url = 'testUrl';
2049
+ const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
2050
+ assert.deepEqual(result, [mainLocus, breakoutLocus]);
2051
+ });
2052
+ });
2053
+
2054
+ describe('#checkHandleBreakoutLocus', () => {
2055
+ let breakoutLocus;
2056
+ beforeEach(() => {
2057
+ breakoutLocus = {
2058
+ url: 'breakoutUrl1',
2059
+ controls: {
2060
+ breakout: {
2061
+ sessionType: 'BREAKOUT',
2062
+ url: 'breakoutUnifiedUrl1',
2063
+ }
2064
+ }
2065
+ };
2066
+
2067
+ webex.meetings.handleLocusEvent = sinon.stub();
2068
+ });
2069
+ afterEach(() => {
2070
+ sinon.restore();
2071
+ });
2072
+ it('do nothing if new created locus is null/no cached breakouts for updating', () => {
2073
+ webex.meetings.checkHandleBreakoutLocus(null);
2074
+ webex.meetings.breakoutLocusForHandleLater = null;
2075
+ webex.meetings.checkHandleBreakoutLocus({});
2076
+ webex.meetings.breakoutLocusForHandleLater = [];
2077
+ webex.meetings.checkHandleBreakoutLocus({});
2078
+ assert.notCalled(webex.meetings.handleLocusEvent);
2079
+ });
2080
+
2081
+ it('do nothing if new created locus is breakout locus', () => {
2082
+ webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
2083
+ webex.meetings.checkHandleBreakoutLocus(breakoutLocus);
2084
+ assert.notCalled(webex.meetings.handleLocusEvent);
2085
+ });
2086
+
2087
+ it('do nothing if no cached locus is associated with the new created locus', () => {
2088
+ webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
2089
+ webex.meetings.checkHandleBreakoutLocus({
2090
+ controls: {
2091
+ breakout: {
2092
+ sessionType: 'MAIN',
2093
+ url: 'breakoutUnifiedUrl2',
2094
+ }
2095
+ }
2096
+ });
2097
+ assert.notCalled(webex.meetings.handleLocusEvent);
2098
+ });
2099
+
2100
+ it('update the cached breakout locus which associate the new created locus', () => {
2101
+ webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
2102
+ webex.meetings.checkHandleBreakoutLocus({
2103
+ controls: {
2104
+ breakout: {
2105
+ sessionType: 'MAIN',
2106
+ url: 'breakoutUnifiedUrl1',
2107
+ }
2108
+ }
2109
+ });
2110
+ assert.calledWith(webex.meetings.handleLocusEvent, {locus: breakoutLocus, locusUrl: breakoutLocus.url});
2111
+ });
2112
+ });
1189
2113
  });
1190
2114
  });