@webex/plugin-meetings 2.59.8 → 2.60.0-next.2

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 (528) hide show
  1. package/README.md +46 -8
  2. package/dist/annotation/annotation.types.js +7 -0
  3. package/dist/annotation/annotation.types.js.map +1 -0
  4. package/dist/annotation/constants.js +41 -0
  5. package/dist/annotation/constants.js.map +1 -0
  6. package/dist/annotation/index.js +357 -0
  7. package/dist/annotation/index.js.map +1 -0
  8. package/dist/breakouts/breakout.js +215 -0
  9. package/dist/breakouts/breakout.js.map +1 -0
  10. package/dist/breakouts/collection.js +22 -0
  11. package/dist/breakouts/collection.js.map +1 -0
  12. package/dist/breakouts/edit-lock-error.js +51 -0
  13. package/dist/breakouts/edit-lock-error.js.map +1 -0
  14. package/dist/breakouts/events.js +44 -0
  15. package/dist/breakouts/events.js.map +1 -0
  16. package/dist/breakouts/index.js +1047 -0
  17. package/dist/breakouts/index.js.map +1 -0
  18. package/dist/breakouts/request.js +77 -0
  19. package/dist/breakouts/request.js.map +1 -0
  20. package/dist/breakouts/utils.js +64 -0
  21. package/dist/breakouts/utils.js.map +1 -0
  22. package/dist/common/browser-detection.js +2 -3
  23. package/dist/common/browser-detection.js.map +1 -1
  24. package/dist/common/collection.js +3 -4
  25. package/dist/common/collection.js.map +1 -1
  26. package/dist/common/config.js +1 -2
  27. package/dist/common/config.js.map +1 -1
  28. package/dist/common/errors/captcha-error.js +1 -2
  29. package/dist/common/errors/captcha-error.js.map +1 -1
  30. package/dist/common/errors/intent-to-join.js +1 -2
  31. package/dist/common/errors/intent-to-join.js.map +1 -1
  32. package/dist/common/errors/join-meeting.js +1 -2
  33. package/dist/common/errors/join-meeting.js.map +1 -1
  34. package/dist/common/errors/media.js +1 -2
  35. package/dist/common/errors/media.js.map +1 -1
  36. package/dist/common/errors/no-meeting-info.js +50 -0
  37. package/dist/common/errors/no-meeting-info.js.map +1 -0
  38. package/dist/common/errors/parameter.js +3 -4
  39. package/dist/common/errors/parameter.js.map +1 -1
  40. package/dist/common/errors/password-error.js +1 -2
  41. package/dist/common/errors/password-error.js.map +1 -1
  42. package/dist/common/errors/permission.js +1 -2
  43. package/dist/common/errors/permission.js.map +1 -1
  44. package/dist/common/errors/reclaim-host-role-errors.js +154 -0
  45. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  46. package/dist/common/errors/reconnection-in-progress.js +1 -2
  47. package/dist/common/errors/reconnection-in-progress.js.map +1 -1
  48. package/dist/common/errors/reconnection.js +1 -2
  49. package/dist/common/errors/reconnection.js.map +1 -1
  50. package/dist/common/errors/stats.js +1 -2
  51. package/dist/common/errors/stats.js.map +1 -1
  52. package/dist/common/errors/webex-errors.js +48 -28
  53. package/dist/common/errors/webex-errors.js.map +1 -1
  54. package/dist/common/errors/webex-meetings-error.js +1 -2
  55. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  56. package/dist/common/events/events-scope.js +1 -2
  57. package/dist/common/events/events-scope.js.map +1 -1
  58. package/dist/common/events/events.js +1 -2
  59. package/dist/common/events/events.js.map +1 -1
  60. package/dist/common/events/trigger-proxy.js +1 -2
  61. package/dist/common/events/trigger-proxy.js.map +1 -1
  62. package/dist/common/events/util.js +1 -2
  63. package/dist/common/events/util.js.map +1 -1
  64. package/dist/common/logs/logger-config.js +1 -2
  65. package/dist/common/logs/logger-config.js.map +1 -1
  66. package/dist/common/logs/logger-proxy.js +2 -3
  67. package/dist/common/logs/logger-proxy.js.map +1 -1
  68. package/dist/common/logs/request.js +8 -5
  69. package/dist/common/logs/request.js.map +1 -1
  70. package/dist/common/queue.js +22 -9
  71. package/dist/common/queue.js.map +1 -1
  72. package/dist/config.js +8 -11
  73. package/dist/config.js.map +1 -1
  74. package/dist/constants.js +437 -435
  75. package/dist/constants.js.map +1 -1
  76. package/dist/controls-options-manager/constants.js +3 -6
  77. package/dist/controls-options-manager/constants.js.map +1 -1
  78. package/dist/controls-options-manager/enums.js +15 -6
  79. package/dist/controls-options-manager/enums.js.map +1 -1
  80. package/dist/controls-options-manager/index.js +127 -38
  81. package/dist/controls-options-manager/index.js.map +1 -1
  82. package/dist/controls-options-manager/types.js +7 -0
  83. package/dist/controls-options-manager/types.js.map +1 -0
  84. package/dist/controls-options-manager/util.js +309 -19
  85. package/dist/controls-options-manager/util.js.map +1 -1
  86. package/dist/index.js +116 -4
  87. package/dist/index.js.map +1 -1
  88. package/dist/interpretation/collection.js +22 -0
  89. package/dist/interpretation/collection.js.map +1 -0
  90. package/dist/interpretation/index.js +365 -0
  91. package/dist/interpretation/index.js.map +1 -0
  92. package/dist/interpretation/siLanguage.js +24 -0
  93. package/dist/interpretation/siLanguage.js.map +1 -0
  94. package/dist/locus-info/controlsUtils.js +100 -11
  95. package/dist/locus-info/controlsUtils.js.map +1 -1
  96. package/dist/locus-info/embeddedAppsUtils.js +3 -4
  97. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  98. package/dist/locus-info/fullState.js +1 -2
  99. package/dist/locus-info/fullState.js.map +1 -1
  100. package/dist/locus-info/hostUtils.js +1 -2
  101. package/dist/locus-info/hostUtils.js.map +1 -1
  102. package/dist/locus-info/index.js +425 -84
  103. package/dist/locus-info/index.js.map +1 -1
  104. package/dist/locus-info/infoUtils.js +13 -5
  105. package/dist/locus-info/infoUtils.js.map +1 -1
  106. package/dist/locus-info/mediaSharesUtils.js +58 -3
  107. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  108. package/dist/locus-info/parser.js +253 -80
  109. package/dist/locus-info/parser.js.map +1 -1
  110. package/dist/locus-info/selfUtils.js +97 -13
  111. package/dist/locus-info/selfUtils.js.map +1 -1
  112. package/dist/media/index.js +106 -319
  113. package/dist/media/index.js.map +1 -1
  114. package/dist/media/properties.js +96 -153
  115. package/dist/media/properties.js.map +1 -1
  116. package/dist/media/util.js +1 -22
  117. package/dist/media/util.js.map +1 -1
  118. package/dist/mediaQualityMetrics/config.js +498 -493
  119. package/dist/mediaQualityMetrics/config.js.map +1 -1
  120. package/dist/meeting/in-meeting-actions.js +92 -3
  121. package/dist/meeting/in-meeting-actions.js.map +1 -1
  122. package/dist/meeting/index.js +4628 -2971
  123. package/dist/meeting/index.js.map +1 -1
  124. package/dist/meeting/locusMediaRequest.js +291 -0
  125. package/dist/meeting/locusMediaRequest.js.map +1 -0
  126. package/dist/meeting/muteState.js +224 -133
  127. package/dist/meeting/muteState.js.map +1 -1
  128. package/dist/meeting/request.js +297 -199
  129. package/dist/meeting/request.js.map +1 -1
  130. package/dist/meeting/request.type.js +7 -0
  131. package/dist/meeting/request.type.js.map +1 -0
  132. package/dist/meeting/state.js +1 -2
  133. package/dist/meeting/state.js.map +1 -1
  134. package/dist/meeting/util.js +605 -435
  135. package/dist/meeting/util.js.map +1 -1
  136. package/dist/meeting-info/collection.js +3 -4
  137. package/dist/meeting-info/collection.js.map +1 -1
  138. package/dist/meeting-info/index.js +74 -7
  139. package/dist/meeting-info/index.js.map +1 -1
  140. package/dist/meeting-info/meeting-info-v2.js +200 -63
  141. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  142. package/dist/meeting-info/request.js +1 -2
  143. package/dist/meeting-info/request.js.map +1 -1
  144. package/dist/meeting-info/util.js +2 -3
  145. package/dist/meeting-info/util.js.map +1 -1
  146. package/dist/meeting-info/utilv2.js +39 -41
  147. package/dist/meeting-info/utilv2.js.map +1 -1
  148. package/dist/meetings/collection.js +42 -4
  149. package/dist/meetings/collection.js.map +1 -1
  150. package/dist/meetings/index.js +477 -123
  151. package/dist/meetings/index.js.map +1 -1
  152. package/dist/meetings/meetings.types.js +7 -0
  153. package/dist/meetings/meetings.types.js.map +1 -0
  154. package/dist/meetings/request.js +4 -3
  155. package/dist/meetings/request.js.map +1 -1
  156. package/dist/meetings/util.js +107 -6
  157. package/dist/meetings/util.js.map +1 -1
  158. package/dist/member/index.js +54 -2
  159. package/dist/member/index.js.map +1 -1
  160. package/dist/member/member.types.js +3 -4
  161. package/dist/member/member.types.js.map +1 -1
  162. package/dist/member/types.js +23 -0
  163. package/dist/member/types.js.map +1 -0
  164. package/dist/member/util.js +131 -29
  165. package/dist/member/util.js.map +1 -1
  166. package/dist/members/collection.js +11 -2
  167. package/dist/members/collection.js.map +1 -1
  168. package/dist/members/index.js +174 -10
  169. package/dist/members/index.js.map +1 -1
  170. package/dist/members/request.js +108 -41
  171. package/dist/members/request.js.map +1 -1
  172. package/dist/members/types.js +14 -0
  173. package/dist/members/types.js.map +1 -0
  174. package/dist/members/util.js +327 -234
  175. package/dist/members/util.js.map +1 -1
  176. package/dist/metrics/constants.js +15 -9
  177. package/dist/metrics/constants.js.map +1 -1
  178. package/dist/metrics/index.js +4 -452
  179. package/dist/metrics/index.js.map +1 -1
  180. package/dist/multistream/mediaRequestManager.js +344 -0
  181. package/dist/multistream/mediaRequestManager.js.map +1 -0
  182. package/dist/multistream/receiveSlot.js +200 -0
  183. package/dist/multistream/receiveSlot.js.map +1 -0
  184. package/dist/multistream/receiveSlotManager.js +174 -0
  185. package/dist/multistream/receiveSlotManager.js.map +1 -0
  186. package/dist/multistream/remoteMedia.js +268 -0
  187. package/dist/multistream/remoteMedia.js.map +1 -0
  188. package/dist/multistream/remoteMediaGroup.js +267 -0
  189. package/dist/multistream/remoteMediaGroup.js.map +1 -0
  190. package/dist/multistream/remoteMediaManager.js +1211 -0
  191. package/dist/multistream/remoteMediaManager.js.map +1 -0
  192. package/dist/multistream/sendSlotManager.js +236 -0
  193. package/dist/multistream/sendSlotManager.js.map +1 -0
  194. package/dist/networkQualityMonitor/index.js +5 -4
  195. package/dist/networkQualityMonitor/index.js.map +1 -1
  196. package/dist/personal-meeting-room/index.js +2 -3
  197. package/dist/personal-meeting-room/index.js.map +1 -1
  198. package/dist/personal-meeting-room/request.js +2 -3
  199. package/dist/personal-meeting-room/request.js.map +1 -1
  200. package/dist/personal-meeting-room/util.js +1 -2
  201. package/dist/personal-meeting-room/util.js.map +1 -1
  202. package/dist/reachability/index.js +265 -72
  203. package/dist/reachability/index.js.map +1 -1
  204. package/dist/reachability/request.js +18 -10
  205. package/dist/reachability/request.js.map +1 -1
  206. package/dist/reactions/constants.js +12 -0
  207. package/dist/reactions/constants.js.map +1 -0
  208. package/dist/reactions/reactions.js +4 -6
  209. package/dist/reactions/reactions.js.map +1 -1
  210. package/dist/reactions/reactions.type.js +21 -23
  211. package/dist/reactions/reactions.type.js.map +1 -1
  212. package/dist/reconnection-manager/index.js +281 -229
  213. package/dist/reconnection-manager/index.js.map +1 -1
  214. package/dist/recording-controller/enums.js +4 -5
  215. package/dist/recording-controller/enums.js.map +1 -1
  216. package/dist/recording-controller/index.js +57 -46
  217. package/dist/recording-controller/index.js.map +1 -1
  218. package/dist/recording-controller/util.js +10 -10
  219. package/dist/recording-controller/util.js.map +1 -1
  220. package/dist/roap/index.js +101 -235
  221. package/dist/roap/index.js.map +1 -1
  222. package/dist/roap/request.js +126 -180
  223. package/dist/roap/request.js.map +1 -1
  224. package/dist/roap/turnDiscovery.js +115 -105
  225. package/dist/roap/turnDiscovery.js.map +1 -1
  226. package/dist/rtcMetrics/constants.js +11 -0
  227. package/dist/rtcMetrics/constants.js.map +1 -0
  228. package/dist/rtcMetrics/index.js +140 -0
  229. package/dist/rtcMetrics/index.js.map +1 -0
  230. package/dist/statsAnalyzer/global.js +2 -85
  231. package/dist/statsAnalyzer/global.js.map +1 -1
  232. package/dist/statsAnalyzer/index.js +402 -424
  233. package/dist/statsAnalyzer/index.js.map +1 -1
  234. package/dist/statsAnalyzer/mqaUtil.js +117 -83
  235. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  236. package/dist/transcription/index.js +1 -2
  237. package/dist/transcription/index.js.map +1 -1
  238. package/dist/webinar/collection.js +43 -0
  239. package/dist/webinar/collection.js.map +1 -0
  240. package/dist/webinar/index.js +68 -0
  241. package/dist/webinar/index.js.map +1 -0
  242. package/package.json +34 -25
  243. package/src/annotation/annotation.types.ts +50 -0
  244. package/src/annotation/constants.ts +36 -0
  245. package/src/annotation/index.ts +328 -0
  246. package/src/breakouts/README.md +220 -0
  247. package/src/breakouts/breakout.ts +188 -0
  248. package/src/breakouts/collection.ts +19 -0
  249. package/src/breakouts/edit-lock-error.ts +25 -0
  250. package/src/breakouts/events.ts +56 -0
  251. package/src/breakouts/index.ts +925 -0
  252. package/src/breakouts/request.ts +55 -0
  253. package/src/breakouts/utils.ts +57 -0
  254. package/src/common/errors/no-meeting-info.ts +24 -0
  255. package/src/common/errors/reclaim-host-role-errors.ts +134 -0
  256. package/src/common/errors/webex-errors.ts +36 -12
  257. package/src/common/logs/logger-proxy.ts +1 -1
  258. package/src/common/logs/request.ts +5 -1
  259. package/src/common/queue.ts +22 -8
  260. package/src/config.ts +5 -7
  261. package/src/constants.ts +271 -93
  262. package/src/controls-options-manager/enums.ts +12 -0
  263. package/src/controls-options-manager/index.ts +116 -21
  264. package/src/controls-options-manager/types.ts +59 -0
  265. package/src/controls-options-manager/util.ts +294 -14
  266. package/src/index.ts +40 -0
  267. package/src/interpretation/README.md +60 -0
  268. package/src/interpretation/collection.ts +19 -0
  269. package/src/interpretation/index.ts +332 -0
  270. package/src/interpretation/siLanguage.ts +18 -0
  271. package/src/locus-info/controlsUtils.ts +110 -0
  272. package/src/locus-info/index.ts +449 -61
  273. package/src/locus-info/infoUtils.ts +14 -2
  274. package/src/locus-info/mediaSharesUtils.ts +64 -0
  275. package/src/locus-info/parser.ts +258 -47
  276. package/src/locus-info/selfUtils.ts +85 -2
  277. package/src/media/index.ts +153 -370
  278. package/src/media/properties.ts +106 -136
  279. package/src/media/util.ts +0 -21
  280. package/src/mediaQualityMetrics/config.ts +379 -377
  281. package/src/meeting/in-meeting-actions.ts +172 -0
  282. package/src/meeting/index.ts +3861 -2504
  283. package/src/meeting/locusMediaRequest.ts +313 -0
  284. package/src/meeting/muteState.ts +224 -138
  285. package/src/meeting/request.ts +207 -127
  286. package/src/meeting/request.type.ts +13 -0
  287. package/src/meeting/util.ts +590 -423
  288. package/src/meeting-info/index.ts +81 -8
  289. package/src/meeting-info/meeting-info-v2.ts +163 -13
  290. package/src/meeting-info/util.ts +1 -1
  291. package/src/meeting-info/utilv2.ts +28 -28
  292. package/src/meetings/collection.ts +33 -0
  293. package/src/meetings/index.ts +477 -124
  294. package/src/meetings/meetings.types.ts +12 -0
  295. package/src/meetings/request.ts +2 -0
  296. package/src/meetings/util.ts +116 -5
  297. package/src/member/index.ts +52 -1
  298. package/src/member/types.ts +38 -0
  299. package/src/member/util.ts +139 -28
  300. package/src/members/collection.ts +8 -0
  301. package/src/members/index.ts +196 -7
  302. package/src/members/request.ts +97 -17
  303. package/src/members/types.ts +29 -0
  304. package/src/members/util.ts +333 -240
  305. package/src/metrics/constants.ts +13 -6
  306. package/src/metrics/index.ts +1 -471
  307. package/src/multistream/mediaRequestManager.ts +440 -0
  308. package/src/multistream/receiveSlot.ts +184 -0
  309. package/src/multistream/receiveSlotManager.ts +166 -0
  310. package/src/multistream/remoteMedia.ts +254 -0
  311. package/src/multistream/remoteMediaGroup.ts +284 -0
  312. package/src/multistream/remoteMediaManager.ts +1145 -0
  313. package/src/multistream/sendSlotManager.ts +170 -0
  314. package/src/networkQualityMonitor/index.ts +6 -6
  315. package/src/reachability/index.ts +238 -45
  316. package/src/reachability/request.ts +17 -8
  317. package/src/reactions/constants.ts +4 -0
  318. package/src/reactions/reactions.ts +4 -4
  319. package/src/reactions/reactions.type.ts +30 -4
  320. package/src/reconnection-manager/index.ts +167 -154
  321. package/src/recording-controller/index.ts +20 -3
  322. package/src/recording-controller/util.ts +26 -9
  323. package/src/roap/index.ts +98 -241
  324. package/src/roap/request.ts +74 -148
  325. package/src/roap/turnDiscovery.ts +62 -56
  326. package/src/rtcMetrics/constants.ts +3 -0
  327. package/src/rtcMetrics/index.ts +124 -0
  328. package/src/statsAnalyzer/global.ts +1 -84
  329. package/src/statsAnalyzer/index.ts +470 -522
  330. package/src/statsAnalyzer/mqaUtil.ts +117 -112
  331. package/src/webinar/collection.ts +31 -0
  332. package/src/webinar/index.ts +62 -0
  333. package/test/integration/spec/converged-space-meetings.js +233 -0
  334. package/test/integration/spec/journey.js +320 -264
  335. package/test/integration/spec/space-meeting.js +77 -4
  336. package/test/unit/spec/annotation/index.ts +418 -0
  337. package/test/unit/spec/breakouts/breakout.ts +237 -0
  338. package/test/unit/spec/breakouts/collection.ts +15 -0
  339. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  340. package/test/unit/spec/breakouts/events.ts +89 -0
  341. package/test/unit/spec/breakouts/index.ts +1790 -0
  342. package/test/unit/spec/breakouts/request.ts +104 -0
  343. package/test/unit/spec/breakouts/utils.js +72 -0
  344. package/test/unit/spec/common/queue.js +31 -2
  345. package/test/unit/spec/controls-options-manager/index.js +163 -0
  346. package/test/unit/spec/controls-options-manager/util.js +576 -60
  347. package/test/unit/spec/fixture/locus.js +1 -0
  348. package/test/unit/spec/interpretation/collection.ts +15 -0
  349. package/test/unit/spec/interpretation/index.ts +589 -0
  350. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  351. package/test/unit/spec/locus-info/controlsUtils.js +323 -30
  352. package/test/unit/spec/locus-info/index.js +1390 -16
  353. package/test/unit/spec/locus-info/infoUtils.js +54 -16
  354. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  355. package/test/unit/spec/locus-info/lib/selfConstant.js +48 -0
  356. package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
  357. package/test/unit/spec/locus-info/parser.js +116 -35
  358. package/test/unit/spec/locus-info/selfUtils.js +275 -0
  359. package/test/unit/spec/media/index.ts +274 -0
  360. package/test/unit/spec/media/properties.ts +75 -84
  361. package/test/unit/spec/meeting/in-meeting-actions.ts +84 -0
  362. package/test/unit/spec/meeting/index.js +8269 -3145
  363. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  364. package/test/unit/spec/meeting/muteState.js +409 -213
  365. package/test/unit/spec/meeting/request.js +512 -42
  366. package/test/unit/spec/meeting/utils.js +741 -24
  367. package/test/unit/spec/meeting-info/index.js +300 -0
  368. package/test/unit/spec/meeting-info/meetinginfov2.js +527 -5
  369. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  370. package/test/unit/spec/meetings/collection.js +26 -0
  371. package/test/unit/spec/meetings/index.js +1201 -210
  372. package/test/unit/spec/meetings/utils.js +202 -2
  373. package/test/unit/spec/member/index.js +38 -8
  374. package/test/unit/spec/member/util.js +499 -29
  375. package/test/unit/spec/members/index.js +597 -3
  376. package/test/unit/spec/members/request.js +206 -27
  377. package/test/unit/spec/members/utils.js +210 -0
  378. package/test/unit/spec/metrics/index.js +1 -50
  379. package/test/unit/spec/multistream/mediaRequestManager.ts +1418 -0
  380. package/test/unit/spec/multistream/receiveSlot.ts +163 -0
  381. package/test/unit/spec/multistream/receiveSlotManager.ts +203 -0
  382. package/test/unit/spec/multistream/remoteMedia.ts +255 -0
  383. package/test/unit/spec/multistream/remoteMediaGroup.ts +662 -0
  384. package/test/unit/spec/multistream/remoteMediaManager.ts +1924 -0
  385. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  386. package/test/unit/spec/networkQualityMonitor/index.js +4 -4
  387. package/test/unit/spec/reachability/index.ts +598 -24
  388. package/test/unit/spec/reachability/request.js +68 -0
  389. package/test/unit/spec/reconnection-manager/index.js +145 -22
  390. package/test/unit/spec/recording-controller/index.js +293 -218
  391. package/test/unit/spec/recording-controller/util.js +223 -96
  392. package/test/unit/spec/roap/index.ts +200 -76
  393. package/test/unit/spec/roap/request.ts +232 -0
  394. package/test/unit/spec/roap/turnDiscovery.ts +86 -48
  395. package/test/unit/spec/rtcMetrics/index.ts +93 -0
  396. package/test/unit/spec/stats-analyzer/index.js +188 -174
  397. package/test/unit/spec/webinar/collection.ts +13 -0
  398. package/test/unit/spec/webinar/index.ts +60 -0
  399. package/test/utils/constants.js +9 -0
  400. package/test/utils/integrationTestUtils.js +46 -0
  401. package/test/utils/testUtils.js +0 -45
  402. package/test/utils/webex-config.js +4 -0
  403. package/test/utils/webex-test-users.js +7 -3
  404. package/dist/common/browser-detection.d.ts +0 -9
  405. package/dist/common/collection.d.ts +0 -48
  406. package/dist/common/config.d.ts +0 -2
  407. package/dist/common/errors/captcha-error.d.ts +0 -15
  408. package/dist/common/errors/intent-to-join.d.ts +0 -16
  409. package/dist/common/errors/join-meeting.d.ts +0 -17
  410. package/dist/common/errors/media.d.ts +0 -15
  411. package/dist/common/errors/parameter.d.ts +0 -15
  412. package/dist/common/errors/password-error.d.ts +0 -15
  413. package/dist/common/errors/permission.d.ts +0 -14
  414. package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
  415. package/dist/common/errors/reconnection.d.ts +0 -15
  416. package/dist/common/errors/stats.d.ts +0 -15
  417. package/dist/common/errors/webex-errors.d.ts +0 -81
  418. package/dist/common/errors/webex-meetings-error.d.ts +0 -20
  419. package/dist/common/events/events-scope.d.ts +0 -17
  420. package/dist/common/events/events.d.ts +0 -12
  421. package/dist/common/events/trigger-proxy.d.ts +0 -2
  422. package/dist/common/events/util.d.ts +0 -2
  423. package/dist/common/logs/logger-config.d.ts +0 -2
  424. package/dist/common/logs/logger-proxy.d.ts +0 -2
  425. package/dist/common/logs/request.d.ts +0 -34
  426. package/dist/common/queue.d.ts +0 -32
  427. package/dist/config.d.ts +0 -73
  428. package/dist/constants.d.ts +0 -926
  429. package/dist/controls-options-manager/constants.d.ts +0 -4
  430. package/dist/controls-options-manager/enums.d.ts +0 -5
  431. package/dist/controls-options-manager/index.d.ts +0 -120
  432. package/dist/controls-options-manager/util.d.ts +0 -7
  433. package/dist/index.d.ts +0 -4
  434. package/dist/locus-info/controlsUtils.d.ts +0 -2
  435. package/dist/locus-info/embeddedAppsUtils.d.ts +0 -2
  436. package/dist/locus-info/fullState.d.ts +0 -2
  437. package/dist/locus-info/hostUtils.d.ts +0 -2
  438. package/dist/locus-info/index.d.ts +0 -269
  439. package/dist/locus-info/infoUtils.d.ts +0 -2
  440. package/dist/locus-info/mediaSharesUtils.d.ts +0 -2
  441. package/dist/locus-info/parser.d.ts +0 -212
  442. package/dist/locus-info/selfUtils.d.ts +0 -2
  443. package/dist/media/index.d.ts +0 -32
  444. package/dist/media/properties.d.ts +0 -108
  445. package/dist/media/util.d.ts +0 -2
  446. package/dist/mediaQualityMetrics/config.d.ts +0 -233
  447. package/dist/meeting/effectsState.d.ts +0 -42
  448. package/dist/meeting/effectsState.js +0 -260
  449. package/dist/meeting/effectsState.js.map +0 -1
  450. package/dist/meeting/in-meeting-actions.d.ts +0 -79
  451. package/dist/meeting/index.d.ts +0 -1622
  452. package/dist/meeting/muteState.d.ts +0 -116
  453. package/dist/meeting/request.d.ts +0 -255
  454. package/dist/meeting/state.d.ts +0 -9
  455. package/dist/meeting/util.d.ts +0 -2
  456. package/dist/meeting-info/collection.d.ts +0 -20
  457. package/dist/meeting-info/index.d.ts +0 -57
  458. package/dist/meeting-info/meeting-info-v2.d.ts +0 -93
  459. package/dist/meeting-info/request.d.ts +0 -22
  460. package/dist/meeting-info/util.d.ts +0 -2
  461. package/dist/meeting-info/utilv2.d.ts +0 -2
  462. package/dist/meetings/collection.d.ts +0 -23
  463. package/dist/meetings/index.d.ts +0 -296
  464. package/dist/meetings/request.d.ts +0 -27
  465. package/dist/meetings/util.d.ts +0 -18
  466. package/dist/member/index.d.ts +0 -147
  467. package/dist/member/member.types.d.ts +0 -11
  468. package/dist/member/util.d.ts +0 -2
  469. package/dist/members/collection.d.ts +0 -24
  470. package/dist/members/index.d.ts +0 -298
  471. package/dist/members/request.d.ts +0 -50
  472. package/dist/members/util.d.ts +0 -2
  473. package/dist/metrics/config.d.ts +0 -169
  474. package/dist/metrics/config.js +0 -289
  475. package/dist/metrics/config.js.map +0 -1
  476. package/dist/metrics/constants.d.ts +0 -59
  477. package/dist/metrics/index.d.ts +0 -152
  478. package/dist/networkQualityMonitor/index.d.ts +0 -70
  479. package/dist/peer-connection-manager/index.d.ts +0 -6
  480. package/dist/peer-connection-manager/index.js +0 -671
  481. package/dist/peer-connection-manager/index.js.map +0 -1
  482. package/dist/peer-connection-manager/util.d.ts +0 -6
  483. package/dist/peer-connection-manager/util.js +0 -110
  484. package/dist/peer-connection-manager/util.js.map +0 -1
  485. package/dist/personal-meeting-room/index.d.ts +0 -47
  486. package/dist/personal-meeting-room/request.d.ts +0 -14
  487. package/dist/personal-meeting-room/util.d.ts +0 -2
  488. package/dist/reachability/index.d.ts +0 -139
  489. package/dist/reachability/request.d.ts +0 -35
  490. package/dist/reactions/reactions.d.ts +0 -4
  491. package/dist/reactions/reactions.type.d.ts +0 -32
  492. package/dist/reconnection-manager/index.d.ts +0 -112
  493. package/dist/recording-controller/enums.d.ts +0 -7
  494. package/dist/recording-controller/index.d.ts +0 -193
  495. package/dist/recording-controller/util.d.ts +0 -13
  496. package/dist/roap/collection.d.ts +0 -10
  497. package/dist/roap/collection.js +0 -63
  498. package/dist/roap/collection.js.map +0 -1
  499. package/dist/roap/handler.d.ts +0 -47
  500. package/dist/roap/handler.js +0 -279
  501. package/dist/roap/handler.js.map +0 -1
  502. package/dist/roap/index.d.ts +0 -116
  503. package/dist/roap/request.d.ts +0 -35
  504. package/dist/roap/state.d.ts +0 -9
  505. package/dist/roap/state.js +0 -127
  506. package/dist/roap/state.js.map +0 -1
  507. package/dist/roap/turnDiscovery.d.ts +0 -81
  508. package/dist/roap/util.d.ts +0 -2
  509. package/dist/roap/util.js +0 -76
  510. package/dist/roap/util.js.map +0 -1
  511. package/dist/statsAnalyzer/global.d.ts +0 -118
  512. package/dist/statsAnalyzer/index.d.ts +0 -193
  513. package/dist/statsAnalyzer/mqaUtil.d.ts +0 -22
  514. package/dist/transcription/index.d.ts +0 -64
  515. package/src/index.js +0 -15
  516. package/src/meeting/effectsState.ts +0 -209
  517. package/src/metrics/config.ts +0 -485
  518. package/src/peer-connection-manager/index.ts +0 -847
  519. package/src/peer-connection-manager/util.ts +0 -119
  520. package/src/roap/collection.ts +0 -62
  521. package/src/roap/handler.ts +0 -294
  522. package/src/roap/state.ts +0 -156
  523. package/src/roap/util.ts +0 -100
  524. package/test/unit/spec/meeting/effectsState.js +0 -281
  525. package/test/unit/spec/peerconnection-manager/index.js +0 -218
  526. package/test/unit/spec/peerconnection-manager/utils.js +0 -49
  527. package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -388
  528. package/test/unit/spec/roap/util.js +0 -30
@@ -3,6 +3,10 @@
3
3
  */
4
4
  import 'jsdom-global/register';
5
5
 
6
+ // Polyfill for crypto: https://github.com/jsdom/jsdom/issues/1612#issuecomment-663210638
7
+ import {Crypto} from '@peculiar/webcrypto';
8
+ global.crypto = new Crypto();
9
+
6
10
  import Device from '@webex/internal-plugin-device';
7
11
  import Mercury from '@webex/internal-plugin-mercury';
8
12
  import {assert} from '@webex/test-helper-chai';
@@ -11,8 +15,8 @@ import sinon from 'sinon';
11
15
  import uuid from 'uuid';
12
16
  import StaticConfig from '@webex/plugin-meetings/src/common/config';
13
17
  import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
18
+ import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
14
19
  import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
15
- import MediaUtil from '@webex/plugin-meetings/src/media/util';
16
20
  import Meeting from '@webex/plugin-meetings/src/meeting';
17
21
  import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
18
22
  import Meetings from '@webex/plugin-meetings/src/meetings';
@@ -20,6 +24,7 @@ import MeetingCollection from '@webex/plugin-meetings/src/meetings/collection';
20
24
  import MeetingsUtil from '@webex/plugin-meetings/src/meetings/util';
21
25
  import PersonalMeetingRoom from '@webex/plugin-meetings/src/personal-meeting-room';
22
26
  import Reachability from '@webex/plugin-meetings/src/reachability';
27
+ import Metrics from '@webex/plugin-meetings/src/metrics';
23
28
 
24
29
  import testUtils from '../../../utils/testUtils';
25
30
  import {
@@ -30,6 +35,12 @@ import {
30
35
  LOCUSINFO,
31
36
  EVENT_TRIGGERS,
32
37
  } from '../../../../src/constants';
38
+ import CaptchaError from '@webex/plugin-meetings/src/common/errors/captcha-error';
39
+ import {forEach} from 'lodash';
40
+ import PasswordError from '@webex/plugin-meetings/src/common/errors/password-error';
41
+ import PermissionError from '@webex/plugin-meetings/src/common/errors/permission';
42
+ import {NoiseReductionEffect, VirtualBackgroundEffect} from '@webex/media-helpers';
43
+ import NoMeetingInfoError from '../../../../src/common/errors/no-meeting-info';
33
44
 
34
45
  describe('plugin-meetings', () => {
35
46
  const logger = {
@@ -41,6 +52,8 @@ describe('plugin-meetings', () => {
41
52
  debug: () => {},
42
53
  };
43
54
 
55
+ let triggerProxyStub;
56
+
44
57
  beforeEach(() => {
45
58
  StaticConfig.set({
46
59
  bandwidth: {
@@ -52,7 +65,7 @@ describe('plugin-meetings', () => {
52
65
  verboseEvents: true,
53
66
  enable: false,
54
67
  });
55
- TriggerProxy.trigger = sinon.stub().returns(true);
68
+ triggerProxyStub = sinon.stub(TriggerProxy, 'trigger').returns(true);
56
69
  });
57
70
 
58
71
  let webex;
@@ -61,15 +74,20 @@ describe('plugin-meetings', () => {
61
74
  let url1;
62
75
  let test1;
63
76
  let test2;
77
+ let locusInfo;
64
78
 
65
79
  describe('meetings index', () => {
66
80
  beforeEach(() => {
67
81
  MeetingsUtil.checkH264Support = sinon.stub();
68
- uuid1 = uuid.v4();
82
+ uuid1 = uuid.v4();
69
83
  url1 = `https://example.com/${uuid.v4()}`;
70
84
  uri1 = `test-${uuid.v4()}@example.com`;
71
85
  test1 = `test-${uuid.v4()}`;
72
86
  test2 = `test2-${uuid.v4()}`;
87
+ locusInfo = {
88
+ parse: sinon.stub().returns(true),
89
+ updateMainSessionLocusCache: sinon.stub(),
90
+ };
73
91
  webex = new MockWebex({
74
92
  children: {
75
93
  device: Device,
@@ -108,6 +126,7 @@ describe('plugin-meetings', () => {
108
126
  });
109
127
 
110
128
  Object.assign(webex.internal, {
129
+ llm: {on: sinon.stub()},
111
130
  device: {
112
131
  deviceType: 'FAKE_DEVICE',
113
132
  register: sinon.stub().returns(Promise.resolve()),
@@ -151,6 +170,10 @@ describe('plugin-meetings', () => {
151
170
  webex.emit('ready');
152
171
  });
153
172
 
173
+ afterEach(() => {
174
+ sinon.restore();
175
+ });
176
+
154
177
  it('has a webex instance with a meetings property', () => {
155
178
  assert.exists(webex, 'webex was initialized with children');
156
179
  assert.exists(webex.meetings, 'meetings child was set up on the webex instance');
@@ -217,34 +240,6 @@ describe('plugin-meetings', () => {
217
240
  });
218
241
  });
219
242
 
220
- describe('#_toggleTurnDiscovery', () => {
221
- it('should have toggleAdhocMeetings', () => {
222
- assert.equal(typeof webex.meetings._toggleTurnDiscovery, 'function');
223
- });
224
-
225
- describe('success', () => {
226
- it('should update meetings to do TURN discovery', () => {
227
- webex.meetings._toggleTurnDiscovery(true);
228
- assert.equal(webex.meetings.config.experimental.enableTurnDiscovery, true);
229
-
230
- webex.meetings._toggleTurnDiscovery(false);
231
- assert.equal(webex.meetings.config.experimental.enableTurnDiscovery, false);
232
- });
233
- });
234
-
235
- describe('failure', () => {
236
- it('should not accept non boolean input', () => {
237
- const currentEnableTurnDiscovery = webex.meetings.config.experimental.enableTurnDiscovery;
238
-
239
- webex.meetings._toggleTurnDiscovery('test');
240
- assert.equal(
241
- webex.meetings.config.experimental.enableAdhocMeetings,
242
- currentEnableTurnDiscovery
243
- );
244
- });
245
- });
246
- });
247
-
248
243
  describe('Public API Contracts', () => {
249
244
  describe('#register', () => {
250
245
  it('emits an event and resolves when register succeeds', async () => {
@@ -338,37 +333,110 @@ describe('plugin-meetings', () => {
338
333
  });
339
334
  });
340
335
 
336
+ describe('virtual background effect', () => {
337
+ beforeEach(() => {
338
+ webex.credentials = {
339
+ supertoken: {
340
+ access_token: 'fake_token',
341
+ },
342
+ };
343
+ });
344
+
345
+ it('creates background effect', async () => {
346
+ const result = await webex.meetings.createVirtualBackgroundEffect();
347
+
348
+ assert.exists(result);
349
+ assert.instanceOf(result, VirtualBackgroundEffect);
350
+ assert.containsAllKeys(result, ['loadModel', 'isEnabled', 'options']);
351
+ assert.deepEqual(result.options, {
352
+ mode: 'BLUR',
353
+ blurStrength: 'STRONG',
354
+ generator: 'worker',
355
+ quality: 'LOW',
356
+ authToken: 'fake_token',
357
+ mirror: false,
358
+ });
359
+ assert.exists(result.enable);
360
+ assert.exists(result.disable);
361
+ assert.exists(result.dispose);
362
+ });
363
+
364
+ it('creates background effect with custom options passed', async () => {
365
+ const effectOptions = {
366
+ generator: 'local',
367
+ frameRate: 45,
368
+ mode: 'IMAGE',
369
+ mirror: false,
370
+ quality: 'HIGH',
371
+ blurStrength: 'STRONG',
372
+ bgImageUrl: 'https://test.webex.com/landscape.5a535788.jpg',
373
+ };
374
+
375
+ const result = await webex.meetings.createVirtualBackgroundEffect(effectOptions);
376
+
377
+ assert.exists(result);
378
+ assert.instanceOf(result, VirtualBackgroundEffect);
379
+ assert.containsAllKeys(result, ['loadModel', 'isEnabled', 'options']);
380
+ assert.deepEqual(result.options, {...effectOptions, authToken: 'fake_token'});
381
+ assert.exists(result.enable);
382
+ assert.exists(result.disable);
383
+ assert.exists(result.dispose);
384
+ });
385
+ });
386
+
387
+ describe('noise reduction effect', () => {
388
+ beforeEach(() => {
389
+ webex.credentials = {
390
+ supertoken: {
391
+ access_token: 'fake_token',
392
+ },
393
+ };
394
+ });
395
+
396
+ it('creates noise reduction effect', async () => {
397
+ const result = await webex.meetings.createNoiseReductionEffect({audioContext: {}});
398
+
399
+ assert.exists(result);
400
+ assert.instanceOf(result, NoiseReductionEffect);
401
+ assert.containsAllKeys(result, ['audioContext', 'isEnabled', 'isReady', 'options']);
402
+ assert.deepEqual(result.options, {
403
+ authToken: 'fake_token',
404
+ audioContext: {},
405
+ });
406
+ assert.exists(result.enable);
407
+ assert.exists(result.disable);
408
+ assert.exists(result.dispose);
409
+ });
410
+
411
+ it('creates noise reduction effect with custom options passed', async () => {
412
+ const effectOptions = {
413
+ audioContext: {},
414
+ mode: 'WORKLET',
415
+ env: 'prod',
416
+ };
417
+
418
+ const result = await webex.meetings.createNoiseReductionEffect(effectOptions);
419
+
420
+ assert.exists(result);
421
+ assert.instanceOf(result, NoiseReductionEffect);
422
+ assert.containsAllKeys(result, ['audioContext', 'isEnabled', 'isReady', 'options']);
423
+ assert.deepEqual(result.options, {...effectOptions, authToken: 'fake_token'});
424
+ assert.exists(result.enable);
425
+ assert.exists(result.disable);
426
+ assert.exists(result.dispose);
427
+ });
428
+ });
429
+
341
430
  describe('gets', () => {
342
431
  describe('#getReachability', () => {
343
432
  it('should have #getReachability', () => {
344
433
  assert.exists(webex.meetings.getReachability);
345
434
  });
346
- describe('before #setReachability', () => {
347
- it('does not get a reachability instance', () => {
348
- const reachability = webex.meetings.getReachability();
349
-
350
- assert.notExists(
351
- reachability,
352
- 'reachability is undefined because #setReachability has not been called'
353
- );
354
- });
355
- });
356
- describe('after #setReachability', () => {
357
- beforeEach(() => {
358
- webex.meetings.setReachability();
359
- const reachabilityMocker = webex.meetings.getReachability();
360
-
361
- sinon.stub(reachabilityMocker, 'gatherReachability').returns(true);
362
- });
363
- it('gets the reachability data instance from webex.meetings', () => {
364
- const reachability = webex.meetings.getReachability();
435
+ it('gets the reachability data instance from webex.meetings', () => {
436
+ const reachability = webex.meetings.getReachability();
365
437
 
366
- assert.exists(
367
- reachability,
368
- 'reachability is defined because #setReachability has been called'
369
- );
370
- assert.instanceOf(reachability, Reachability, 'should be a reachability instance');
371
- });
438
+ assert.exists(reachability, 'reachability is defined');
439
+ assert.instanceOf(reachability, Reachability, 'should be a reachability instance');
372
440
  });
373
441
  });
374
442
  describe('#getPersonalMeetingRoom', () => {
@@ -443,21 +511,16 @@ describe('plugin-meetings', () => {
443
511
  );
444
512
  });
445
513
  describe('when meeting is returned', () => {
446
- let parse;
447
-
448
514
  beforeEach(() => {
449
- parse = sinon.stub().returns(true);
450
515
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
451
- locusInfo: {
452
- parse,
453
- },
516
+ locusInfo,
454
517
  });
455
518
  });
456
519
  it('tests the sync meeting calls for existing meeting', async () => {
457
520
  await webex.meetings.syncMeetings();
458
521
  assert.calledOnce(webex.meetings.request.getActiveMeetings);
459
522
  assert.calledOnce(webex.meetings.meetingCollection.getByKey);
460
- assert.calledOnce(parse);
523
+ assert.calledOnce(locusInfo.parse);
461
524
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
462
525
  });
463
526
  });
@@ -470,6 +533,7 @@ describe('plugin-meetings', () => {
470
533
  webex.meetings.create = sinon.stub().returns(
471
534
  Promise.resolve({
472
535
  locusInfo: {
536
+ ...locusInfo,
473
537
  initialSetup,
474
538
  },
475
539
  })
@@ -478,7 +542,7 @@ describe('plugin-meetings', () => {
478
542
  it('tests the sync meeting calls for not existing meeting', async () => {
479
543
  await webex.meetings.syncMeetings();
480
544
  assert.calledOnce(webex.meetings.request.getActiveMeetings);
481
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
545
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
482
546
  assert.calledOnce(initialSetup);
483
547
  assert.calledOnce(webex.meetings.create);
484
548
  assert.calledWith(webex.meetings.request.getActiveMeetings);
@@ -502,12 +566,9 @@ describe('plugin-meetings', () => {
502
566
 
503
567
  beforeEach(() => {
504
568
  destroySpy = sinon.spy(webex.meetings, 'destroy');
505
- parse = sinon.stub().returns(true);
506
569
  initialSetup = sinon.stub().returns(true);
507
570
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
508
- locusInfo: {
509
- parse,
510
- },
571
+ locusInfo,
511
572
  sendCallAnalyzerMetrics: sinon.stub(),
512
573
  });
513
574
  webex.meetings.meetingCollection.getAll = sinon.stub().returns({
@@ -574,14 +635,66 @@ describe('plugin-meetings', () => {
574
635
  });
575
636
  });
576
637
 
638
+ const FAKE_USE_RANDOM_DELAY = true;
639
+ const correlationId = 'my-correlationId';
640
+
641
+ const checkCallCreateMeeting = async (createParameters, createMeetingParameters) => {
642
+ const create = webex.meetings.create(...createParameters);
643
+
644
+ assert.exists(create.then);
645
+ await create;
646
+ assert.calledOnce(webex.meetings.createMeeting);
647
+ assert.calledWith(webex.meetings.createMeeting, ...createMeetingParameters);
648
+ };
649
+
577
650
  it('calls createMeeting and returns its promise', async () => {
578
- const FAKE_USE_RANDOM_DELAY = true;
579
- const create = webex.meetings.create(test1, test2, FAKE_USE_RANDOM_DELAY);
651
+ checkCallCreateMeeting(
652
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, true],
653
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, true]
654
+ );
655
+ });
656
+
657
+ it('calls createMeeting when failOnMissingMeetinginfo is undefined and returns its promise', async () => {
658
+ checkCallCreateMeeting(
659
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, undefined],
660
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, false]
661
+ );
662
+ });
663
+
664
+ it('calls createMeeting when failOnMissingMeetinginfo is false and returns its promise', async () => {
665
+ checkCallCreateMeeting(
666
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, false],
667
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, false]
668
+ );
669
+ });
670
+
671
+ it('calls createMeeting with extra info params and returns its promise', async () => {
672
+ const FAKE_USE_RANDOM_DELAY = false;
673
+ const correlationId = 'my-correlationId';
674
+
675
+ const FAKE_INFO_EXTRA_PARAMS = {
676
+ mtid: 'm9fe0afd8c435e892afcce9ea25b97046',
677
+ joinTXId: 'TSmrX61wNF',
678
+ };
679
+ const create = webex.meetings.create(
680
+ test1,
681
+ test2,
682
+ FAKE_USE_RANDOM_DELAY,
683
+ FAKE_INFO_EXTRA_PARAMS,
684
+ correlationId
685
+ );
580
686
 
581
687
  assert.exists(create.then);
582
688
  await create;
583
689
  assert.calledOnce(webex.meetings.createMeeting);
584
- assert.calledWith(webex.meetings.createMeeting, test1, test2, FAKE_USE_RANDOM_DELAY);
690
+ assert.calledWith(
691
+ webex.meetings.createMeeting,
692
+ test1,
693
+ test2,
694
+ FAKE_USE_RANDOM_DELAY,
695
+ FAKE_INFO_EXTRA_PARAMS,
696
+ correlationId
697
+ );
585
698
  });
586
699
 
587
700
  it('creates a new meeting when a scheduled meeting exists in the conversation', async () => {
@@ -677,45 +790,51 @@ describe('plugin-meetings', () => {
677
790
  });
678
791
  describe('#handleLocusEvent', () => {
679
792
  describe('there was a meeting', () => {
680
- let parse;
681
-
682
793
  beforeEach(() => {
683
- parse = sinon.stub().returns(true);
684
794
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
685
- locusInfo: {
686
- parse,
687
- },
795
+ locusInfo,
688
796
  });
689
797
  });
690
- it('should parse the meeting info', () => {
798
+ it('should parse the meeting info and update main session locus cache', () => {
799
+ sinon.stub(MeetingsUtil, 'isBreakoutLocusDTO').returns(false);
691
800
  webex.meetings.handleLocusEvent({
692
801
  locusUrl: url1,
693
802
  });
694
803
  assert.calledOnce(webex.meetings.meetingCollection.getByKey);
695
804
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
696
- assert.calledOnce(parse);
805
+ assert.calledOnce(locusInfo.parse);
806
+ assert.calledOnce(locusInfo.updateMainSessionLocusCache);
697
807
  assert.calledWith(
698
- parse,
808
+ locusInfo.parse,
699
809
  {
700
- locusInfo: {
701
- parse,
702
- },
810
+ locusInfo,
703
811
  },
704
812
  {
705
813
  locusUrl: url1,
706
814
  }
707
815
  );
708
816
  });
817
+
818
+ it('should not update main session locus cache', () => {
819
+ sinon.stub(MeetingsUtil, 'isBreakoutLocusDTO').returns(true);
820
+ webex.meetings.handleLocusEvent({
821
+ locusUrl: url1,
822
+ });
823
+ assert.notCalled(locusInfo.updateMainSessionLocusCache);
824
+ });
709
825
  });
710
826
  describe('there was not a meeting', () => {
711
827
  let initialSetup;
828
+ const webExMeetingId = '123456';
712
829
 
713
830
  beforeEach(() => {
714
831
  initialSetup = sinon.stub().returns(true);
715
832
  webex.meetings.meetingCollection.getByKey = sinon.stub().returns(undefined);
716
833
  webex.meetings.create = sinon.stub().returns(
717
834
  Promise.resolve({
835
+ id: 'meeting-id',
718
836
  locusInfo: {
837
+ ...locusInfo,
719
838
  initialSetup,
720
839
  },
721
840
  })
@@ -735,12 +854,20 @@ describe('plugin-meetings', () => {
735
854
  callbackAddress: uri1,
736
855
  },
737
856
  },
857
+ info: {
858
+ webExMeetingId,
859
+ },
738
860
  },
739
861
  eventType: 'locus.difference',
740
862
  locusUrl: url1,
741
863
  });
742
- assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
864
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 6);
743
865
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
866
+ assert.calledWith(
867
+ webex.meetings.meetingCollection.getByKey,
868
+ 'meetingNumber',
869
+ webExMeetingId
870
+ );
744
871
  assert.calledOnce(initialSetup);
745
872
  assert.calledWith(initialSetup, {
746
873
  id: uuid1,
@@ -754,6 +881,9 @@ describe('plugin-meetings', () => {
754
881
  callbackAddress: uri1,
755
882
  },
756
883
  },
884
+ info: {
885
+ webExMeetingId,
886
+ },
757
887
  });
758
888
  });
759
889
  it('should setup the meeting by difference event without replaces', async () => {
@@ -765,12 +895,20 @@ describe('plugin-meetings', () => {
765
895
  callbackAddress: uri1,
766
896
  },
767
897
  },
898
+ info: {
899
+ webExMeetingId,
900
+ },
768
901
  },
769
902
  eventType: 'locus.difference',
770
903
  locusUrl: url1,
771
904
  });
772
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
905
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
773
906
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
907
+ assert.calledWith(
908
+ webex.meetings.meetingCollection.getByKey,
909
+ 'meetingNumber',
910
+ webExMeetingId
911
+ );
774
912
  assert.calledOnce(initialSetup);
775
913
  assert.calledWith(initialSetup, {
776
914
  id: uuid1,
@@ -779,8 +917,44 @@ describe('plugin-meetings', () => {
779
917
  callbackAddress: uri1,
780
918
  },
781
919
  },
920
+ info: {
921
+ webExMeetingId,
922
+ },
923
+ });
924
+ });
925
+
926
+ it('sends client event correctly on finally', async () => {
927
+ webex.meetings.getMeetingByType = sinon.stub().returns(true);
928
+
929
+ await webex.meetings.handleLocusEvent({
930
+ locus: {
931
+ id: uuid1,
932
+ self: {
933
+ callBackInfo: {
934
+ callbackAddress: uri1,
935
+ },
936
+ },
937
+ info: {
938
+ webExMeetingId,
939
+ },
940
+ },
941
+ eventType: 'locus.difference',
942
+ locusUrl: url1,
943
+ });
944
+
945
+ await testUtils.flushPromises();
946
+
947
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
948
+ name: 'client.call.remote-started',
949
+ payload: {
950
+ trigger: 'mercury-event',
951
+ },
952
+ options: {
953
+ meetingId: 'meeting-id',
954
+ },
782
955
  });
783
956
  });
957
+
784
958
  it('should setup the meeting by a not difference event', async () => {
785
959
  await webex.meetings.handleLocusEvent({
786
960
  locus: {
@@ -790,12 +964,20 @@ describe('plugin-meetings', () => {
790
964
  callbackAddress: uri1,
791
965
  },
792
966
  },
967
+ info: {
968
+ webExMeetingId,
969
+ },
793
970
  },
794
971
  eventType: test1,
795
972
  locusUrl: url1,
796
973
  });
797
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
974
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
798
975
  assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
976
+ assert.calledWith(
977
+ webex.meetings.meetingCollection.getByKey,
978
+ 'meetingNumber',
979
+ webExMeetingId
980
+ );
799
981
  assert.calledOnce(initialSetup);
800
982
  assert.calledWith(initialSetup, {
801
983
  id: uuid1,
@@ -804,6 +986,9 @@ describe('plugin-meetings', () => {
804
986
  callbackAddress: uri1,
805
987
  },
806
988
  },
989
+ info: {
990
+ webExMeetingId,
991
+ },
807
992
  });
808
993
  });
809
994
 
@@ -826,7 +1011,7 @@ describe('plugin-meetings', () => {
826
1011
 
827
1012
  it('should not try to match USM meetings by conversation url', async () => {
828
1013
  await webex.meetings.handleLocusEvent(generateFakeLocusData(true));
829
- assert.callCount(webex.meetings.meetingCollection.getByKey, 3);
1014
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
830
1015
  assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, [
831
1016
  'locusUrl',
832
1017
  url1,
@@ -843,7 +1028,7 @@ describe('plugin-meetings', () => {
843
1028
  });
844
1029
  it('should try to match non-USM meetings by conversation url', async () => {
845
1030
  await webex.meetings.handleLocusEvent(generateFakeLocusData(false));
846
- assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
1031
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
847
1032
  assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, [
848
1033
  'locusUrl',
849
1034
  url1,
@@ -866,7 +1051,6 @@ describe('plugin-meetings', () => {
866
1051
  });
867
1052
  describe('#createMeeting', () => {
868
1053
  beforeEach(() => {
869
- MediaUtil.createPeerConnection = sinon.stub().returns(true);
870
1054
  webex.internal.device.userId = uuid1;
871
1055
  webex.internal.device.url = url1;
872
1056
  MeetingCollection.set = sinon.stub().returns(true);
@@ -875,6 +1059,10 @@ describe('plugin-meetings', () => {
875
1059
  });
876
1060
  describe('successful MeetingInfo.#fetchMeetingInfo', () => {
877
1061
  let clock, setTimeoutSpy, fakeMeetingStartTimeString, FAKE_TIME_TO_START;
1062
+ const FAKE_INFO_EXTRA_PARAMS = {
1063
+ mtid: 'm9fe0afd8c435e892afcce9ea25b97046',
1064
+ joinTXId: 'TSmrX61wNF',
1065
+ };
878
1066
 
879
1067
  beforeEach(() => {
880
1068
  clock = sinon.useFakeTimers();
@@ -904,13 +1092,25 @@ describe('plugin-meetings', () => {
904
1092
  meeting,
905
1093
  destination,
906
1094
  type,
907
- expectedMeetingData = {}
1095
+ extraParams = {},
1096
+ expectedMeetingData = {},
1097
+ sendCAevents = false
908
1098
  ) => {
909
1099
  assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
910
1100
  assert.calledOnce(MeetingsUtil.getMeetingAddedType);
911
1101
  assert.notCalled(setTimeoutSpy);
912
- assert.calledThrice(TriggerProxy.trigger);
913
- assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, destination, type);
1102
+ assert.callCount(TriggerProxy.trigger, 5);
1103
+ assert.calledWith(
1104
+ webex.meetings.meetingInfo.fetchMeetingInfo,
1105
+ destination,
1106
+ type,
1107
+ null,
1108
+ null,
1109
+ undefined,
1110
+ undefined,
1111
+ extraParams,
1112
+ {meetingId: meeting.id, sendCAevents}
1113
+ );
914
1114
  assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
915
1115
 
916
1116
  if (expectedMeetingData.permissionToken) {
@@ -919,6 +1119,9 @@ describe('plugin-meetings', () => {
919
1119
  if (expectedMeetingData.meetingJoinUrl) {
920
1120
  assert.equal(meeting.meetingJoinUrl, expectedMeetingData.meetingJoinUrl);
921
1121
  }
1122
+ if (expectedMeetingData.correlationId) {
1123
+ assert.equal(meeting.correlationId, expectedMeetingData.correlationId);
1124
+ }
922
1125
  assert.equal(meeting.destination, destination);
923
1126
  assert.equal(meeting.destinationType, type);
924
1127
  assert.calledWith(
@@ -948,107 +1151,139 @@ describe('plugin-meetings', () => {
948
1151
  const expectedMeetingData = {
949
1152
  permissionToken: 'PT',
950
1153
  meetingJoinUrl: 'meetingJoinUrl',
1154
+ correlationId: meeting.id,
951
1155
  };
952
1156
 
953
- checkCreateWithoutDelay(meeting, 'test destination', 'test type', expectedMeetingData);
954
- });
955
-
956
- it('creates the meeting from a successful meeting info fetch meeting resolve testing', async () => {
957
- const meeting = await webex.meetings.createMeeting('test destination', 'test type');
958
- const expectedMeetingData = {
959
- permissionToken: 'PT',
960
- meetingJoinUrl: 'meetingJoinUrl',
961
- };
962
-
963
- assert.instanceOf(
1157
+ checkCreateWithoutDelay(
964
1158
  meeting,
965
- Meeting,
966
- 'createMeeting should eventually resolve to a Meeting Object'
1159
+ 'test destination',
1160
+ 'test type',
1161
+ {},
1162
+ expectedMeetingData
967
1163
  );
968
- checkCreateWithoutDelay(meeting, 'test destination', 'test type', expectedMeetingData);
969
1164
  });
970
1165
 
971
- it('creates the meeting from a successful meeting info fetch with random delay', async () => {
972
- const FAKE_LOCUS_MEETING = {
973
- conversationUrl: 'locusConvURL',
974
- url: 'locusUrl',
975
- info: {
976
- webExMeetingId: 'locusMeetingId',
977
- sipUri: 'locusSipUri',
978
- owner: 'locusOwner',
979
- },
980
- meeting: {
981
- startTime: fakeMeetingStartTimeString,
982
- },
983
- fullState: {
984
- active: false,
985
- },
986
- };
1166
+ [undefined, FAKE_INFO_EXTRA_PARAMS].forEach((infoExtraParams) => {
1167
+ const infoExtraParamsProvided = infoExtraParams !== undefined;
1168
+
1169
+ it(`creates the meeting from a successful meeting info fetch meeting resolve testing${
1170
+ infoExtraParamsProvided ? ' with infoExtraParams' : ''
1171
+ }`, async () => {
1172
+ const meeting = await webex.meetings.createMeeting(
1173
+ 'test destination',
1174
+ 'test type',
1175
+ false,
1176
+ infoExtraParams
1177
+ );
1178
+ const expectedMeetingData = {
1179
+ permissionToken: 'PT',
1180
+ meetingJoinUrl: 'meetingJoinUrl',
1181
+ };
1182
+
1183
+ assert.instanceOf(
1184
+ meeting,
1185
+ Meeting,
1186
+ 'createMeeting should eventually resolve to a Meeting Object'
1187
+ );
1188
+ checkCreateWithoutDelay(
1189
+ meeting,
1190
+ 'test destination',
1191
+ 'test type',
1192
+ infoExtraParamsProvided ? infoExtraParams : {},
1193
+ expectedMeetingData
1194
+ );
1195
+ });
987
1196
 
988
- const meeting = await webex.meetings.createMeeting(
989
- FAKE_LOCUS_MEETING,
990
- 'test type',
991
- true
992
- );
1197
+ it(`creates the meeting from a successful meeting info fetch with random delay${
1198
+ infoExtraParamsProvided ? ' with infoExtraParams' : ''
1199
+ }`, async () => {
1200
+ const FAKE_LOCUS_MEETING = {
1201
+ conversationUrl: 'locusConvURL',
1202
+ url: 'locusUrl',
1203
+ info: {
1204
+ webExMeetingId: 'locusMeetingId',
1205
+ sipUri: 'locusSipUri',
1206
+ owner: 'locusOwner',
1207
+ },
1208
+ meeting: {
1209
+ startTime: fakeMeetingStartTimeString,
1210
+ },
1211
+ fullState: {
1212
+ active: false,
1213
+ },
1214
+ };
993
1215
 
994
- assert.instanceOf(
995
- meeting,
996
- Meeting,
997
- 'createMeeting should eventually resolve to a Meeting Object'
998
- );
999
- assert.notCalled(webex.meetings.meetingInfo.fetchMeetingInfo);
1000
- assert.calledOnce(setTimeoutSpy);
1001
-
1002
- // Parse meeting info with locus object
1003
- assert.equal(meeting.conversationUrl, 'locusConvURL');
1004
- assert.equal(meeting.locusUrl, 'locusUrl');
1005
- assert.equal(meeting.sipUri, 'locusSipUri');
1006
- assert.equal(meeting.meetingNumber, 'locusMeetingId');
1007
- assert.isUndefined(meeting.meetingJoinUrl);
1008
- assert.equal(meeting.owner, 'locusOwner');
1009
- assert.isUndefined(meeting.permissionToken);
1010
-
1011
- // Add meeting and send trigger
1012
- assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
1013
- assert.calledTwice(TriggerProxy.trigger);
1014
- assert.calledWith(
1015
- TriggerProxy.trigger,
1016
- sinon.match.instanceOf(Meetings),
1017
- {
1018
- file: 'meetings',
1019
- function: 'createMeeting',
1020
- },
1021
- 'meeting:added',
1022
- {
1023
- meeting: sinon.match.instanceOf(Meeting),
1024
- type: 'test meeting added type',
1025
- }
1026
- );
1216
+ const meeting = await webex.meetings.createMeeting(
1217
+ FAKE_LOCUS_MEETING,
1218
+ 'test type',
1219
+ true,
1220
+ infoExtraParams
1221
+ );
1027
1222
 
1028
- // When timer expires
1029
- clock.tick(FAKE_TIME_TO_START);
1030
- assert.calledWith(
1031
- webex.meetings.meetingInfo.fetchMeetingInfo,
1032
- FAKE_LOCUS_MEETING,
1033
- 'test type'
1034
- );
1223
+ assert.instanceOf(
1224
+ meeting,
1225
+ Meeting,
1226
+ 'createMeeting should eventually resolve to a Meeting Object'
1227
+ );
1228
+ assert.notCalled(webex.meetings.meetingInfo.fetchMeetingInfo);
1229
+ assert.calledOnce(setTimeoutSpy);
1230
+
1231
+ // Parse meeting info with locus object
1232
+ assert.equal(meeting.conversationUrl, 'locusConvURL');
1233
+ assert.equal(meeting.locusUrl, 'locusUrl');
1234
+ assert.equal(meeting.sipUri, 'locusSipUri');
1235
+ assert.equal(meeting.meetingNumber, 'locusMeetingId');
1236
+ assert.isUndefined(meeting.meetingJoinUrl);
1237
+ assert.equal(meeting.owner, 'locusOwner');
1238
+ assert.isUndefined(meeting.permissionToken);
1239
+
1240
+ // Add meeting and send trigger
1241
+ assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
1242
+ assert.calledTwice(TriggerProxy.trigger);
1243
+ assert.calledWith(
1244
+ TriggerProxy.trigger,
1245
+ sinon.match.instanceOf(Meetings),
1246
+ {
1247
+ file: 'meetings',
1248
+ function: 'createMeeting',
1249
+ },
1250
+ 'meeting:added',
1251
+ {
1252
+ meeting: sinon.match.instanceOf(Meeting),
1253
+ type: 'test meeting added type',
1254
+ }
1255
+ );
1035
1256
 
1036
- // Parse meeting info is called again with new meeting info
1037
- await testUtils.flushPromises();
1038
- assert.equal(meeting.conversationUrl, 'locusConvURL');
1039
- assert.equal(meeting.locusUrl, 'locusUrl');
1040
- assert.equal(meeting.sipUri, 'locusSipUri');
1041
- assert.equal(meeting.meetingNumber, 'locusMeetingId');
1042
- assert.equal(meeting.meetingJoinUrl, 'meetingJoinUrl');
1043
- assert.equal(meeting.owner, 'locusOwner');
1044
- assert.equal(meeting.permissionToken, 'PT');
1257
+ // When timer expires
1258
+ clock.tick(FAKE_TIME_TO_START);
1259
+ assert.calledWith(
1260
+ webex.meetings.meetingInfo.fetchMeetingInfo,
1261
+ FAKE_LOCUS_MEETING,
1262
+ 'test type',
1263
+ null,
1264
+ null,
1265
+ undefined,
1266
+ undefined,
1267
+ infoExtraParamsProvided ? infoExtraParams : {}
1268
+ );
1045
1269
 
1046
- assert.calledWith(
1047
- TriggerProxy.trigger,
1048
- meeting,
1049
- {file: 'meetings', function: 'fetchMeetingInfo'},
1050
- 'meeting:meetingInfoAvailable'
1051
- );
1270
+ // Parse meeting info is called again with new meeting info
1271
+ await testUtils.flushPromises();
1272
+ assert.equal(meeting.conversationUrl, 'locusConvURL');
1273
+ assert.equal(meeting.locusUrl, 'locusUrl');
1274
+ assert.equal(meeting.sipUri, 'locusSipUri');
1275
+ assert.equal(meeting.meetingNumber, 'locusMeetingId');
1276
+ assert.equal(meeting.meetingJoinUrl, 'meetingJoinUrl');
1277
+ assert.equal(meeting.owner, 'locusOwner');
1278
+ assert.equal(meeting.permissionToken, 'PT');
1279
+
1280
+ assert.calledWith(
1281
+ TriggerProxy.trigger,
1282
+ meeting,
1283
+ {file: 'meetings', function: 'fetchMeetingInfo'},
1284
+ 'meeting:meetingInfoAvailable'
1285
+ );
1286
+ });
1052
1287
  });
1053
1288
 
1054
1289
  it('creates the meeting from a successful meeting info fetch that has no random delay because it is active', async () => {
@@ -1148,6 +1383,29 @@ describe('plugin-meetings', () => {
1148
1383
  );
1149
1384
  checkCreateWithoutDelay(meeting, FAKE_LOCUS_MEETING, 'test type');
1150
1385
  });
1386
+
1387
+ it('creates meeting with the correlationId provided', async () => {
1388
+ const meeting = await webex.meetings.createMeeting(
1389
+ 'test destination',
1390
+ 'test type',
1391
+ false,
1392
+ {},
1393
+ 'my-correlationId'
1394
+ );
1395
+
1396
+ const expectedMeetingData = {
1397
+ correlationId: 'my-correlationId',
1398
+ };
1399
+
1400
+ checkCreateWithoutDelay(
1401
+ meeting,
1402
+ 'test destination',
1403
+ 'test type',
1404
+ {},
1405
+ expectedMeetingData,
1406
+ true
1407
+ );
1408
+ });
1151
1409
  });
1152
1410
 
1153
1411
  describe('rejected MeetingInfo.#fetchMeetingInfo', () => {
@@ -1157,45 +1415,136 @@ describe('plugin-meetings', () => {
1157
1415
  webex.meetings.meetingInfo.fetchMeetingInfo = sinon
1158
1416
  .stub()
1159
1417
  .returns(Promise.reject(new Error('test')));
1418
+ webex.meetings.destroy = sinon.stub().returns(Promise.resolve());
1419
+ webex.meetings.createMeeting = sinon.spy(webex.meetings.createMeeting);
1160
1420
  });
1421
+
1422
+ const checkCreateMeetingWithNoMeetingInfo = async (failOnMissingMeetingInfo, destroy) => {
1423
+ try {
1424
+ const meeting = await webex.meetings.createMeeting(
1425
+ 'test destination',
1426
+ 'test type',
1427
+ undefined,
1428
+ undefined,
1429
+ undefined,
1430
+ failOnMissingMeetingInfo
1431
+ );
1432
+
1433
+ assert.instanceOf(
1434
+ meeting,
1435
+ Meeting,
1436
+ 'createMeeting should eventually resolve to a Meeting Object'
1437
+ );
1438
+ assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
1439
+ assert.calledOnce(MeetingsUtil.getMeetingAddedType);
1440
+ assert.calledThrice(TriggerProxy.trigger);
1441
+ assert.calledWith(
1442
+ webex.meetings.meetingInfo.fetchMeetingInfo,
1443
+ 'test destination',
1444
+ 'test type'
1445
+ );
1446
+
1447
+ if (destroy) {
1448
+ assert.calledWith(
1449
+ webex.meetings.destroy,
1450
+ sinon.match.instanceOf(Meeting),
1451
+ 'MISSING_MEETING_INFO'
1452
+ );
1453
+ assert.notCalled(MeetingsUtil.getMeetingAddedType);
1454
+ assert.notCalled(TriggerProxy.trigger);
1455
+ assert.throw(webex.meetings.createMeeting, 'meeting information not found');
1456
+ } else {
1457
+ assert.notCalled(webex.meetings.destroy);
1458
+ assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
1459
+ assert.calledWith(
1460
+ TriggerProxy.trigger,
1461
+ sinon.match.instanceOf(Meetings),
1462
+ {
1463
+ file: 'meetings',
1464
+ function: 'createMeeting',
1465
+ },
1466
+ 'meeting:added',
1467
+ {
1468
+ meeting: sinon.match.instanceOf(Meeting),
1469
+ type: 'test meeting added type',
1470
+ }
1471
+ );
1472
+ }
1473
+ } catch (err) {
1474
+ assert.instanceOf(err, NoMeetingInfoError);
1475
+ }
1476
+ };
1477
+
1161
1478
  it('creates the meeting from a rejected meeting info fetch', async () => {
1162
- const meeting = await webex.meetings.createMeeting('test destination', 'test type');
1479
+ checkCreateMeetingWithNoMeetingInfo(false, false);
1480
+ });
1163
1481
 
1164
- assert.instanceOf(
1165
- meeting,
1166
- Meeting,
1167
- 'createMeeting should eventually resolve to a Meeting Object'
1168
- );
1169
- assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
1170
- assert.calledOnce(MeetingsUtil.getMeetingAddedType);
1171
- assert.calledTwice(TriggerProxy.trigger);
1172
- assert.calledWith(
1173
- webex.meetings.meetingInfo.fetchMeetingInfo,
1174
- 'test destination',
1175
- 'test type'
1176
- );
1177
- assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
1178
- assert.calledWith(
1179
- TriggerProxy.trigger,
1180
- sinon.match.instanceOf(Meetings),
1482
+ it('creates the meeting from a rejected meeting info fetch and destroys it if failOnMissingMeetingInfo', async () => {
1483
+ checkCreateMeetingWithNoMeetingInfo(true, true);
1484
+ });
1485
+ });
1486
+
1487
+ describe('rejected MeetingInfo.#fetchMeetingInfo - does not log for known Error types', () => {
1488
+ forEach(
1489
+ [
1181
1490
  {
1182
- file: 'meetings',
1183
- function: 'createMeeting',
1491
+ error: new CaptchaError(),
1492
+ debugLogMessage:
1493
+ 'Meetings:index#createMeeting --> Debug CaptchaError: Captcha is required. fetching /meetingInfo for creation.',
1184
1494
  },
1185
- 'meeting:added',
1186
1495
  {
1187
- meeting: sinon.match.instanceOf(Meeting),
1188
- type: 'test meeting added type',
1189
- }
1190
- );
1191
- });
1496
+ error: new PasswordError(),
1497
+ debugLogMessage:
1498
+ 'Meetings:index#createMeeting --> Debug PasswordError: Password is required, please use verifyPassword() fetching /meetingInfo for creation.',
1499
+ },
1500
+ {
1501
+ error: new PermissionError(),
1502
+ debugLogMessage:
1503
+ '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.',
1504
+ },
1505
+ {
1506
+ error: new Error(),
1507
+ infoLogMessage: true,
1508
+ debugLogMessage:
1509
+ 'Meetings:index#createMeeting --> Debug Error fetching /meetingInfo for creation.',
1510
+ },
1511
+ ],
1512
+ ({error, debugLogMessage, infoLogMessage}) => {
1513
+ it('creates the meeting from a rejected meeting info fetch', async () => {
1514
+ webex.meetings.meetingInfo.fetchMeetingInfo = sinon
1515
+ .stub()
1516
+ .returns(Promise.reject(error));
1517
+
1518
+ LoggerProxy.logger.debug = sinon.stub();
1519
+ LoggerProxy.logger.info = sinon.stub();
1520
+
1521
+ const meeting = await webex.meetings.createMeeting('test destination', 'test type');
1522
+
1523
+ assert.instanceOf(
1524
+ meeting,
1525
+ Meeting,
1526
+ 'createMeeting should eventually resolve to a Meeting Object'
1527
+ );
1528
+
1529
+ assert.calledWith(LoggerProxy.logger.debug, debugLogMessage);
1530
+
1531
+ if (infoLogMessage) {
1532
+ assert.calledWith(
1533
+ LoggerProxy.logger.info,
1534
+ 'Meetings:index#createMeeting --> Info Unable to fetch meeting info for test destination.'
1535
+ );
1536
+ } else {
1537
+ assert.notCalled(LoggerProxy.logger.info);
1538
+ }
1539
+ });
1540
+ }
1541
+ );
1192
1542
  });
1193
1543
  });
1194
1544
  });
1195
1545
  describe('Public Event Triggers', () => {
1196
1546
  describe('#destroy', () => {
1197
1547
  beforeEach(() => {
1198
- MediaUtil.createPeerConnection = sinon.stub().returns(true);
1199
1548
  MeetingUtil.cleanUp = sinon.stub();
1200
1549
  });
1201
1550
  it('should have #destroy', () => {
@@ -1269,6 +1618,8 @@ describe('plugin-meetings', () => {
1269
1618
  });
1270
1619
 
1271
1620
  describe('#fetchUserPreferredWebexSite', () => {
1621
+ let loggerProxySpy;
1622
+
1272
1623
  it('should call request.getMeetingPreferences to get the preferred webex site ', async () => {
1273
1624
  assert.isDefined(webex.meetings.preferredWebexSite);
1274
1625
  await webex.meetings.fetchUserPreferredWebexSite();
@@ -1276,7 +1627,22 @@ describe('plugin-meetings', () => {
1276
1627
  assert.equal(webex.meetings.preferredWebexSite, 'go.webex.com');
1277
1628
  });
1278
1629
 
1630
+ const setup = ({user} = {}) => {
1631
+ loggerProxySpy = sinon.spy(LoggerProxy.logger, 'error');
1632
+
1633
+ Object.assign(webex.internal, {
1634
+ services: {
1635
+ getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
1636
+ },
1637
+ user: {
1638
+ get: sinon.stub().returns(Promise.resolve(user)),
1639
+ },
1640
+ });
1641
+ };
1642
+
1279
1643
  it('should not fail if UserPreferred info is not fetched ', async () => {
1644
+ setup();
1645
+
1280
1646
  Object.assign(webex.internal, {
1281
1647
  services: {
1282
1648
  getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
@@ -1286,7 +1652,115 @@ describe('plugin-meetings', () => {
1286
1652
  await webex.meetings.fetchUserPreferredWebexSite().then(() => {
1287
1653
  assert.equal(webex.meetings.preferredWebexSite, '');
1288
1654
  });
1655
+ assert.calledOnceWithExactly(
1656
+ loggerProxySpy,
1657
+ 'Failed to fetch preferred site from user - no site will be set'
1658
+ );
1659
+ });
1660
+
1661
+ it('should fall back to fetching the site from the user', async () => {
1662
+ setup({
1663
+ user: {
1664
+ userPreferences: {
1665
+ userPreferencesItems: {
1666
+ preferredWebExSite: 'site.webex.com',
1667
+ },
1668
+ },
1669
+ },
1670
+ });
1671
+
1672
+ await webex.meetings.fetchUserPreferredWebexSite();
1673
+
1674
+ assert.equal(webex.meetings.preferredWebexSite, 'site.webex.com');
1675
+ assert.notCalled(loggerProxySpy);
1289
1676
  });
1677
+
1678
+ forEach(
1679
+ [
1680
+ {user: undefined},
1681
+ {user: {userPreferences: {}}},
1682
+ {user: {userPreferences: {userPreferencesItems: {}}}},
1683
+ {user: {userPreferences: {userPreferencesItems: {preferredWebExSite: undefined}}}},
1684
+ ],
1685
+ ({user}) => {
1686
+ it(`should handle invalid user data ${user}`, async () => {
1687
+ setup({user});
1688
+
1689
+ await webex.meetings.fetchUserPreferredWebexSite();
1690
+
1691
+ assert.equal(webex.meetings.preferredWebexSite, '');
1692
+ assert.calledOnceWithExactly(
1693
+ loggerProxySpy,
1694
+ 'Failed to fetch preferred site from user - no site will be set'
1695
+ );
1696
+ });
1697
+ }
1698
+ );
1699
+
1700
+ it('should handle a get user failure', async () => {
1701
+ setup();
1702
+
1703
+ webex.internal.user.get.rejects(new Error());
1704
+
1705
+ await webex.meetings.fetchUserPreferredWebexSite();
1706
+
1707
+ assert.equal(webex.meetings.preferredWebexSite, '');
1708
+ assert.calledOnceWithExactly(
1709
+ loggerProxySpy,
1710
+ 'Failed to fetch preferred site from user - no site will be set'
1711
+ );
1712
+ });
1713
+
1714
+ it('should fall back to fetching the site from the user', async () => {
1715
+ setup({
1716
+ user: {
1717
+ userPreferences: {
1718
+ userPreferencesItems: {
1719
+ preferredWebExSite: 'site.webex.com',
1720
+ },
1721
+ },
1722
+ },
1723
+ });
1724
+
1725
+ await webex.meetings.fetchUserPreferredWebexSite();
1726
+
1727
+ assert.equal(webex.meetings.preferredWebexSite, 'site.webex.com');
1728
+ assert.notCalled(loggerProxySpy);
1729
+ });
1730
+
1731
+ forEach([
1732
+ {user: undefined},
1733
+ {user: {userPreferences: {}}},
1734
+ {user: {userPreferences: {userPreferencesItems: {}}}},
1735
+ {user: {userPreferences: {userPreferencesItems: {preferredWebExSite: undefined}}}},
1736
+ ], ({user}) => {
1737
+ it(`should handle invalid user data ${user}`, async () => {
1738
+ setup({user});
1739
+
1740
+ await webex.meetings.fetchUserPreferredWebexSite();
1741
+
1742
+ assert.equal(webex.meetings.preferredWebexSite, '');
1743
+ assert.calledOnceWithExactly(
1744
+ loggerProxySpy,
1745
+ 'Failed to fetch preferred site from user - no site will be set'
1746
+ );
1747
+ });
1748
+ });
1749
+
1750
+ it('should handle a get user failure', async () => {
1751
+ setup();
1752
+
1753
+ webex.internal.user.get.rejects(new Error());
1754
+
1755
+ await webex.meetings.fetchUserPreferredWebexSite();
1756
+
1757
+ assert.equal(webex.meetings.preferredWebexSite, '');
1758
+ assert.calledOnceWithExactly(
1759
+ loggerProxySpy,
1760
+ 'Failed to fetch preferred site from user - no site will be set'
1761
+ );
1762
+ });
1763
+
1290
1764
  });
1291
1765
  });
1292
1766
 
@@ -1294,7 +1768,6 @@ describe('plugin-meetings', () => {
1294
1768
  let meeting;
1295
1769
 
1296
1770
  beforeEach(async () => {
1297
- MediaUtil.createPeerConnection = sinon.stub().returns(true);
1298
1771
  webex.internal.device.userId = uuid1;
1299
1772
  webex.internal.device.url = url1;
1300
1773
  MeetingCollection.set = sinon.stub().returns(true);
@@ -1371,5 +1844,523 @@ describe('plugin-meetings', () => {
1371
1844
  );
1372
1845
  });
1373
1846
  });
1847
+
1848
+ describe('#isNeedHandleMainLocus', () => {
1849
+ let meeting;
1850
+ let newLocus;
1851
+ beforeEach(() => {
1852
+ meeting = {
1853
+ controls: {},
1854
+ self: {},
1855
+ };
1856
+ newLocus = {
1857
+ controls: {},
1858
+ self: {},
1859
+ };
1860
+ });
1861
+ afterEach(() => {
1862
+ sinon.restore();
1863
+ });
1864
+ it('check normal case will return true', () => {
1865
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns(null);
1866
+ LoggerProxy.logger.log = sinon.stub();
1867
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1868
+ assert.equal(result, true);
1869
+ assert.calledWith(
1870
+ LoggerProxy.logger.log,
1871
+ 'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
1872
+ );
1873
+ });
1874
+
1875
+ it('check self joined and joined on this device, return true', () => {
1876
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns(null);
1877
+ newLocus.self.state = 'JOINED';
1878
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
1879
+
1880
+ LoggerProxy.logger.log = sinon.stub();
1881
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1882
+ assert.equal(result, true);
1883
+ assert.calledWith(
1884
+ LoggerProxy.logger.log,
1885
+ 'Meetings:index#isNeedHandleMainLocus --> self this device shown as JOINED in the main session'
1886
+ );
1887
+ });
1888
+
1889
+ it('if newLocus replaceAt time is expired, then return false', () => {
1890
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({
1891
+ joinedWith: {
1892
+ replaces: [
1893
+ {
1894
+ replaceAt: '2023-03-27T02:17:02.506Z',
1895
+ },
1896
+ ],
1897
+ },
1898
+ });
1899
+ newLocus.self.state = 'JOINED';
1900
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
1901
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1902
+ replaces: [
1903
+ {
1904
+ replaceAt: '2023-03-27T02:17:01.506Z',
1905
+ },
1906
+ ],
1907
+ });
1908
+
1909
+ LoggerProxy.logger.log = sinon.stub();
1910
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1911
+ assert.equal(result, false);
1912
+ assert.calledWith(
1913
+ LoggerProxy.logger.log,
1914
+ `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`
1915
+ );
1916
+ });
1917
+
1918
+ it('check current is in breakout join with this device, return false', () => {
1919
+ sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({
1920
+ joinedWith: {
1921
+ correlationId: '111',
1922
+ },
1923
+ });
1924
+ newLocus.controls.breakout = {url: 'url'};
1925
+ meeting.correlationId = '111';
1926
+
1927
+ LoggerProxy.logger.log = sinon.stub();
1928
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1929
+ assert.equal(result, false);
1930
+ assert.calledWith(
1931
+ LoggerProxy.logger.log,
1932
+ `Meetings:index#isNeedHandleMainLocus --> there is active breakout session and joined on this device, and don't need to handle main session: url`
1933
+ );
1934
+ });
1935
+
1936
+ it('check self is moved and removed, return false', () => {
1937
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1938
+ newLocus.self.state = 'LEFT';
1939
+ newLocus.self.reason = 'MOVED';
1940
+ newLocus.self.removed = true;
1941
+ LoggerProxy.logger.log = sinon.stub();
1942
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1943
+ assert.equal(result, false);
1944
+ assert.calledWith(
1945
+ LoggerProxy.logger.log,
1946
+ 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
1947
+ );
1948
+ });
1949
+
1950
+ it('check self is moved and device resource removed, return false', () => {
1951
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1952
+ newLocus.self.state = 'LEFT';
1953
+ newLocus.self.reason = 'MOVED';
1954
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1955
+ state: 'LEFT',
1956
+ reason: 'MOVED',
1957
+ });
1958
+ LoggerProxy.logger.log = sinon.stub();
1959
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1960
+ assert.equal(result, false);
1961
+ assert.calledWith(
1962
+ LoggerProxy.logger.log,
1963
+ 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
1964
+ );
1965
+ });
1966
+
1967
+ it('check self is joined but device resource removed, return false', () => {
1968
+ webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
1969
+ sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(false);
1970
+ newLocus.self.state = 'JOINED';
1971
+ sinon.stub(MeetingsUtil, 'getThisDevice').returns({
1972
+ state: 'LEFT',
1973
+ reason: 'MOVED',
1974
+ });
1975
+ LoggerProxy.logger.log = sinon.stub();
1976
+ const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
1977
+ assert.equal(result, false);
1978
+ assert.calledWith(
1979
+ LoggerProxy.logger.log,
1980
+ 'Meetings:index#isNeedHandleMainLocus --> self device left&moved in main locus with self joined status, not need to handle'
1981
+ );
1982
+ });
1983
+ });
1984
+
1985
+ describe('#isNeedHandleLocusDTO', () => {
1986
+ let meeting;
1987
+ let newLocus;
1988
+ beforeEach(() => {
1989
+ meeting = {
1990
+ controls: {},
1991
+ self: {},
1992
+ };
1993
+ newLocus = {
1994
+ controls: {},
1995
+ self: {},
1996
+ };
1997
+ });
1998
+ afterEach(() => {
1999
+ sinon.restore();
2000
+ });
2001
+ it('initial DTO , joined breakout session, return true', () => {
2002
+ newLocus.controls.breakout = {
2003
+ sessionType: 'BREAKOUT',
2004
+ };
2005
+ newLocus.self.state = 'JOINED';
2006
+ newLocus.fullState = {
2007
+ active: true,
2008
+ };
2009
+ LoggerProxy.logger.log = sinon.stub();
2010
+ const result = webex.meetings.isNeedHandleLocusDTO(null, newLocus);
2011
+ assert.equal(result, true);
2012
+ assert.calledWith(
2013
+ LoggerProxy.logger.log,
2014
+ `Meetings:index#isNeedHandleLocusDTO --> the first breakout session locusDTO active status: true`
2015
+ );
2016
+ });
2017
+ it('others go to check isNeedHandleMainLocus', () => {
2018
+ newLocus.controls.breakout = {
2019
+ sessionType: 'MAIN',
2020
+ };
2021
+ newLocus.self.state = 'JOINED';
2022
+
2023
+ LoggerProxy.logger.log = sinon.stub();
2024
+ const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
2025
+ assert.equal(result, true);
2026
+ assert.calledWith(
2027
+ LoggerProxy.logger.log,
2028
+ 'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
2029
+ );
2030
+ });
2031
+ it('joined breakout session, self status is moved, return false', () => {
2032
+ newLocus.controls.breakout = {
2033
+ sessionType: 'BREAKOUT',
2034
+ };
2035
+ newLocus.self.state = 'LEFT';
2036
+ newLocus.self.reason = 'MOVED';
2037
+
2038
+ LoggerProxy.logger.log = sinon.stub();
2039
+ const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
2040
+ assert.equal(result, false);
2041
+ });
2042
+ });
2043
+
2044
+ describe('#getCorrespondingMeetingByLocus', () => {
2045
+ let locus;
2046
+ let mockReturnMeeting = {meeting: 'meeting1'};
2047
+ const mockGetByKey = (keyWillReturnMeeting) => {
2048
+ webex.meetings.meetingCollection.getByKey = sinon.stub().callsFake((key) => {
2049
+ if (key === keyWillReturnMeeting) {
2050
+ return mockReturnMeeting;
2051
+ }
2052
+ return null;
2053
+ });
2054
+ };
2055
+
2056
+ beforeEach(() => {
2057
+ locus = {
2058
+ controls: {},
2059
+ self: {
2060
+ callbackInfo: {
2061
+ callbackAddress: 'address1',
2062
+ },
2063
+ },
2064
+ info: {
2065
+ webExMeetingId: '123456',
2066
+ isUnifiedSpaceMeeting: false,
2067
+ },
2068
+ conversationUrl: 'conversationUrl1',
2069
+ };
2070
+
2071
+ sinon.stub(MeetingsUtil, 'checkForCorrelationId').returns('correlationId1');
2072
+ });
2073
+ afterEach(() => {
2074
+ sinon.restore();
2075
+ });
2076
+ it('check the calls when no meeting found in meetingCollection', () => {
2077
+ mockGetByKey();
2078
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
2079
+ assert.isNull(result);
2080
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
2081
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
2082
+ assert.calledWith(
2083
+ webex.meetings.meetingCollection.getByKey,
2084
+ 'correlationId',
2085
+ 'correlationId1'
2086
+ );
2087
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
2088
+ assert.calledWith(
2089
+ webex.meetings.meetingCollection.getByKey,
2090
+ 'conversationUrl',
2091
+ 'conversationUrl1'
2092
+ );
2093
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', '123456');
2094
+ });
2095
+
2096
+ it('not try getByKey "conversationUrl" when isUnifiedSpaceMeeting is true', () => {
2097
+ mockGetByKey();
2098
+ locus.info.isUnifiedSpaceMeeting = true;
2099
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
2100
+ assert.isNull(result);
2101
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
2102
+ });
2103
+
2104
+ it('check the calls when meeting found by key: locusUrl', () => {
2105
+ mockGetByKey('locusUrl');
2106
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
2107
+ assert.deepEqual(result, mockReturnMeeting);
2108
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 1);
2109
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
2110
+ });
2111
+
2112
+ it('check the calls when meeting found by key: correlationId', () => {
2113
+ mockGetByKey('correlationId');
2114
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
2115
+ assert.deepEqual(result, mockReturnMeeting);
2116
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 2);
2117
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
2118
+ assert.calledWith(
2119
+ webex.meetings.meetingCollection.getByKey,
2120
+ 'correlationId',
2121
+ 'correlationId1'
2122
+ );
2123
+ });
2124
+
2125
+ it('check the calls when meeting found by key: sipUri', () => {
2126
+ mockGetByKey('sipUri');
2127
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
2128
+ assert.deepEqual(result, mockReturnMeeting);
2129
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 3);
2130
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
2131
+ assert.calledWith(
2132
+ webex.meetings.meetingCollection.getByKey,
2133
+ 'correlationId',
2134
+ 'correlationId1'
2135
+ );
2136
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
2137
+ });
2138
+
2139
+ it('check the calls when meeting found by key: conversationUrl', () => {
2140
+ mockGetByKey('conversationUrl');
2141
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
2142
+ assert.deepEqual(result, mockReturnMeeting);
2143
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
2144
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
2145
+ assert.calledWith(
2146
+ webex.meetings.meetingCollection.getByKey,
2147
+ 'correlationId',
2148
+ 'correlationId1'
2149
+ );
2150
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
2151
+ assert.calledWith(
2152
+ webex.meetings.meetingCollection.getByKey,
2153
+ 'conversationUrl',
2154
+ 'conversationUrl1'
2155
+ );
2156
+ });
2157
+
2158
+ it('check the calls when meeting found by key: meetingNumber', () => {
2159
+ mockGetByKey('meetingNumber');
2160
+ const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
2161
+ assert.deepEqual(result, mockReturnMeeting);
2162
+ assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
2163
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
2164
+ assert.calledWith(
2165
+ webex.meetings.meetingCollection.getByKey,
2166
+ 'correlationId',
2167
+ 'correlationId1'
2168
+ );
2169
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
2170
+ assert.calledWith(
2171
+ webex.meetings.meetingCollection.getByKey,
2172
+ 'conversationUrl',
2173
+ 'conversationUrl1'
2174
+ );
2175
+ assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', '123456');
2176
+ });
2177
+ });
2178
+
2179
+ describe('#sortLocusArrayToUpdate', () => {
2180
+ let lociArray;
2181
+ let mainLocus;
2182
+ let breakoutLocus;
2183
+ beforeEach(() => {
2184
+ mainLocus = {
2185
+ url: 'mainUrl1',
2186
+ controls: {
2187
+ breakout: {
2188
+ sessionType: 'MAIN',
2189
+ url: 'breakoutUnifiedUrl1',
2190
+ },
2191
+ },
2192
+ };
2193
+ breakoutLocus = {
2194
+ url: 'breakoutUrl1',
2195
+ controls: {
2196
+ breakout: {
2197
+ sessionType: 'BREAKOUT',
2198
+ url: 'breakoutUnifiedUrl1',
2199
+ },
2200
+ },
2201
+ };
2202
+ lociArray = [mainLocus, breakoutLocus];
2203
+
2204
+ sinon.stub(MeetingsUtil, 'isValidBreakoutLocus').callsFake((locus) => {
2205
+ return locus.url === 'breakoutUrl1';
2206
+ });
2207
+ });
2208
+ afterEach(() => {
2209
+ sinon.restore();
2210
+ });
2211
+
2212
+ it('if both main and breakout locus is in array for non-exist meeting, return main locus to create first', () => {
2213
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns(undefined);
2214
+ const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
2215
+ assert.deepEqual(result, [mainLocus]);
2216
+ assert.deepEqual(webex.meetings.breakoutLocusForHandleLater, [breakoutLocus]);
2217
+ });
2218
+
2219
+ it('if both main and breakout locus is in array for an exist meeting, return all locus', () => {
2220
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns({});
2221
+ const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
2222
+ assert.deepEqual(result, [mainLocus, breakoutLocus]);
2223
+ assert.deepEqual(webex.meetings.breakoutLocusForHandleLater, []);
2224
+ });
2225
+
2226
+ it('if the breakout locus has no associated main locus, return all', () => {
2227
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns({});
2228
+ breakoutLocus.controls.breakout.url = 'testUrl';
2229
+ const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
2230
+ assert.deepEqual(result, [mainLocus, breakoutLocus]);
2231
+ });
2232
+ });
2233
+
2234
+ describe('#checkHandleBreakoutLocus', () => {
2235
+ let breakoutLocus;
2236
+ beforeEach(() => {
2237
+ breakoutLocus = {
2238
+ url: 'breakoutUrl1',
2239
+ controls: {
2240
+ breakout: {
2241
+ sessionType: 'BREAKOUT',
2242
+ url: 'breakoutUnifiedUrl1',
2243
+ },
2244
+ },
2245
+ };
2246
+
2247
+ webex.meetings.handleLocusEvent = sinon.stub();
2248
+ });
2249
+ afterEach(() => {
2250
+ sinon.restore();
2251
+ });
2252
+ it('do nothing if new created locus is null/no cached breakouts for updating', () => {
2253
+ webex.meetings.checkHandleBreakoutLocus(null);
2254
+ webex.meetings.breakoutLocusForHandleLater = null;
2255
+ webex.meetings.checkHandleBreakoutLocus({});
2256
+ webex.meetings.breakoutLocusForHandleLater = [];
2257
+ webex.meetings.checkHandleBreakoutLocus({});
2258
+ assert.notCalled(webex.meetings.handleLocusEvent);
2259
+ });
2260
+
2261
+ it('do nothing if new created locus is breakout locus', () => {
2262
+ webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
2263
+ webex.meetings.checkHandleBreakoutLocus(breakoutLocus);
2264
+ assert.notCalled(webex.meetings.handleLocusEvent);
2265
+ });
2266
+
2267
+ it('do nothing if no cached locus is associated with the new created locus', () => {
2268
+ webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
2269
+ webex.meetings.checkHandleBreakoutLocus({
2270
+ controls: {
2271
+ breakout: {
2272
+ sessionType: 'MAIN',
2273
+ url: 'breakoutUnifiedUrl2',
2274
+ },
2275
+ },
2276
+ });
2277
+ assert.notCalled(webex.meetings.handleLocusEvent);
2278
+ });
2279
+
2280
+ it('update the cached breakout locus which associate the new created locus', () => {
2281
+ webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
2282
+ webex.meetings.checkHandleBreakoutLocus({
2283
+ controls: {
2284
+ breakout: {
2285
+ sessionType: 'MAIN',
2286
+ url: 'breakoutUnifiedUrl1',
2287
+ },
2288
+ },
2289
+ });
2290
+ assert.calledWith(webex.meetings.handleLocusEvent, {
2291
+ locus: breakoutLocus,
2292
+ locusUrl: breakoutLocus.url,
2293
+ });
2294
+ });
2295
+ });
2296
+
2297
+ describe('uploading of logs', () => {
2298
+ let metricsSpy;
2299
+ let meeting;
2300
+
2301
+ beforeEach(async () => {
2302
+ webex.meetings.config.autoUploadLogs = true;
2303
+ webex.meetings.loggerRequest.uploadLogs = sinon.stub().resolves();
2304
+
2305
+ sinon.stub(webex.meetings.meetingInfo, 'fetchInfoOptions').resolves({});
2306
+ sinon.stub(webex.meetings.meetingInfo, 'fetchMeetingInfo').resolves({});
2307
+
2308
+ triggerProxyStub.restore();
2309
+
2310
+ metricsSpy = sinon.stub(Metrics, 'sendBehavioralMetric');
2311
+
2312
+ meeting = await webex.meetings.create('test');
2313
+
2314
+ meeting.locusId = 'locus id';
2315
+ meeting.correlationId = 'correlation id';
2316
+ meeting.locusInfo = {
2317
+ fullState: {lastActive: 'last active', sessionId: 'locus session id'},
2318
+ info: {webExMeetingId: 'meeting id'},
2319
+ };
2320
+ });
2321
+
2322
+ afterEach(() => {
2323
+ sinon.restore();
2324
+ });
2325
+
2326
+ it('sends metrics on success', async () => {
2327
+ await meeting.uploadLogs();
2328
+
2329
+ await testUtils.flushPromises();
2330
+
2331
+ assert.calledOnceWithExactly(metricsSpy, 'js_sdk_upload_logs_success', {
2332
+ callStart: 'last active',
2333
+ correlationId: 'correlation id',
2334
+ feedbackId: 'correlation id',
2335
+ locusId: 'locus id',
2336
+ meetingId: 'meeting id',
2337
+ autoupload: true,
2338
+ locussessionid: 'locus session id',
2339
+ });
2340
+ });
2341
+
2342
+ it('sends metrics on failure', async () => {
2343
+ webex.meetings.loggerRequest.uploadLogs.rejects(new Error('fake error'));
2344
+
2345
+ await meeting.uploadLogs();
2346
+
2347
+ await testUtils.flushPromises();
2348
+
2349
+ assert.calledOnceWithExactly(
2350
+ metricsSpy,
2351
+ 'js_sdk_upload_logs_failure',
2352
+ sinon.match({
2353
+ callStart: 'last active',
2354
+ correlationId: 'correlation id',
2355
+ feedbackId: 'correlation id',
2356
+ locusId: 'locus id',
2357
+ meetingId: 'meeting id',
2358
+ reason: 'fake error',
2359
+ autoupload: true,
2360
+ locussessionid: 'locus session id',
2361
+ })
2362
+ );
2363
+ });
2364
+ });
1374
2365
  });
1375
2366
  });