@webex/plugin-meetings 3.0.0-beta.41 → 3.0.0-beta.410

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 (398) hide show
  1. package/README.md +58 -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 +49 -0
  5. package/dist/annotation/constants.js.map +1 -0
  6. package/dist/annotation/index.js +342 -0
  7. package/dist/annotation/index.js.map +1 -0
  8. package/dist/breakouts/breakout.js +94 -15
  9. package/dist/breakouts/breakout.js.map +1 -1
  10. package/dist/breakouts/events.js +45 -0
  11. package/dist/breakouts/events.js.map +1 -0
  12. package/dist/breakouts/index.js +625 -123
  13. package/dist/breakouts/index.js.map +1 -1
  14. package/dist/breakouts/utils.js +27 -8
  15. package/dist/breakouts/utils.js.map +1 -1
  16. package/dist/common/errors/no-meeting-info.js +51 -0
  17. package/dist/common/errors/no-meeting-info.js.map +1 -0
  18. package/dist/common/errors/reclaim-host-role-errors.js +158 -0
  19. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  20. package/dist/common/errors/webex-errors.js +48 -7
  21. package/dist/common/errors/webex-errors.js.map +1 -1
  22. package/dist/common/logs/logger-proxy.js +1 -1
  23. package/dist/common/logs/logger-proxy.js.map +1 -1
  24. package/dist/common/logs/request.js +5 -1
  25. package/dist/common/logs/request.js.map +1 -1
  26. package/dist/common/queue.js +24 -9
  27. package/dist/common/queue.js.map +1 -1
  28. package/dist/config.js +6 -10
  29. package/dist/config.js.map +1 -1
  30. package/dist/constants.js +247 -34
  31. package/dist/constants.js.map +1 -1
  32. package/dist/controls-options-manager/enums.js +14 -2
  33. package/dist/controls-options-manager/enums.js.map +1 -1
  34. package/dist/controls-options-manager/index.js +109 -15
  35. package/dist/controls-options-manager/index.js.map +1 -1
  36. package/dist/controls-options-manager/types.js +7 -0
  37. package/dist/controls-options-manager/types.js.map +1 -0
  38. package/dist/controls-options-manager/util.js +309 -18
  39. package/dist/controls-options-manager/util.js.map +1 -1
  40. package/dist/index.js +116 -2
  41. package/dist/index.js.map +1 -1
  42. package/dist/interceptors/index.js +15 -0
  43. package/dist/interceptors/index.js.map +1 -0
  44. package/dist/interceptors/locusRetry.js +93 -0
  45. package/dist/interceptors/locusRetry.js.map +1 -0
  46. package/dist/interpretation/collection.js +23 -0
  47. package/dist/interpretation/collection.js.map +1 -0
  48. package/dist/interpretation/index.js +380 -0
  49. package/dist/interpretation/index.js.map +1 -0
  50. package/dist/interpretation/siLanguage.js +25 -0
  51. package/dist/interpretation/siLanguage.js.map +1 -0
  52. package/dist/locus-info/controlsUtils.js +91 -2
  53. package/dist/locus-info/controlsUtils.js.map +1 -1
  54. package/dist/locus-info/index.js +386 -62
  55. package/dist/locus-info/index.js.map +1 -1
  56. package/dist/locus-info/infoUtils.js +7 -1
  57. package/dist/locus-info/infoUtils.js.map +1 -1
  58. package/dist/locus-info/mediaSharesUtils.js +71 -1
  59. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  60. package/dist/locus-info/parser.js +249 -72
  61. package/dist/locus-info/parser.js.map +1 -1
  62. package/dist/locus-info/selfUtils.js +89 -14
  63. package/dist/locus-info/selfUtils.js.map +1 -1
  64. package/dist/media/index.js +65 -102
  65. package/dist/media/index.js.map +1 -1
  66. package/dist/media/properties.js +73 -124
  67. package/dist/media/properties.js.map +1 -1
  68. package/dist/mediaQualityMetrics/config.js +135 -330
  69. package/dist/mediaQualityMetrics/config.js.map +1 -1
  70. package/dist/meeting/in-meeting-actions.js +86 -2
  71. package/dist/meeting/in-meeting-actions.js.map +1 -1
  72. package/dist/meeting/index.js +4531 -2994
  73. package/dist/meeting/index.js.map +1 -1
  74. package/dist/meeting/locusMediaRequest.js +292 -0
  75. package/dist/meeting/locusMediaRequest.js.map +1 -0
  76. package/dist/meeting/muteState.js +236 -136
  77. package/dist/meeting/muteState.js.map +1 -1
  78. package/dist/meeting/request.js +189 -155
  79. package/dist/meeting/request.js.map +1 -1
  80. package/dist/meeting/util.js +676 -417
  81. package/dist/meeting/util.js.map +1 -1
  82. package/dist/meeting/voicea-meeting.js +172 -0
  83. package/dist/meeting/voicea-meeting.js.map +1 -0
  84. package/dist/meeting-info/index.js +73 -7
  85. package/dist/meeting-info/index.js.map +1 -1
  86. package/dist/meeting-info/meeting-info-v2.js +201 -57
  87. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  88. package/dist/meeting-info/util.js +8 -7
  89. package/dist/meeting-info/util.js.map +1 -1
  90. package/dist/meeting-info/utilv2.js +44 -40
  91. package/dist/meeting-info/utilv2.js.map +1 -1
  92. package/dist/meetings/collection.js +39 -0
  93. package/dist/meetings/collection.js.map +1 -1
  94. package/dist/meetings/index.js +484 -119
  95. package/dist/meetings/index.js.map +1 -1
  96. package/dist/meetings/meetings.types.js +7 -0
  97. package/dist/meetings/meetings.types.js.map +1 -0
  98. package/dist/meetings/request.js +2 -0
  99. package/dist/meetings/request.js.map +1 -1
  100. package/dist/meetings/util.js +73 -7
  101. package/dist/meetings/util.js.map +1 -1
  102. package/dist/member/index.js +57 -0
  103. package/dist/member/index.js.map +1 -1
  104. package/dist/member/types.js +25 -0
  105. package/dist/member/types.js.map +1 -0
  106. package/dist/member/util.js +132 -25
  107. package/dist/member/util.js.map +1 -1
  108. package/dist/members/collection.js +10 -0
  109. package/dist/members/collection.js.map +1 -1
  110. package/dist/members/index.js +100 -5
  111. package/dist/members/index.js.map +1 -1
  112. package/dist/members/request.js +106 -38
  113. package/dist/members/request.js.map +1 -1
  114. package/dist/members/types.js +15 -0
  115. package/dist/members/types.js.map +1 -0
  116. package/dist/members/util.js +326 -232
  117. package/dist/members/util.js.map +1 -1
  118. package/dist/metrics/constants.js +18 -1
  119. package/dist/metrics/constants.js.map +1 -1
  120. package/dist/metrics/index.js +1 -446
  121. package/dist/metrics/index.js.map +1 -1
  122. package/dist/multistream/mediaRequestManager.js +223 -32
  123. package/dist/multistream/mediaRequestManager.js.map +1 -1
  124. package/dist/multistream/receiveSlot.js +10 -0
  125. package/dist/multistream/receiveSlot.js.map +1 -1
  126. package/dist/multistream/receiveSlotManager.js +39 -36
  127. package/dist/multistream/receiveSlotManager.js.map +1 -1
  128. package/dist/multistream/remoteMedia.js +3 -1
  129. package/dist/multistream/remoteMedia.js.map +1 -1
  130. package/dist/multistream/remoteMediaGroup.js +76 -5
  131. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  132. package/dist/multistream/remoteMediaManager.js +366 -104
  133. package/dist/multistream/remoteMediaManager.js.map +1 -1
  134. package/dist/multistream/sendSlotManager.js +255 -0
  135. package/dist/multistream/sendSlotManager.js.map +1 -0
  136. package/dist/reachability/clusterReachability.js +356 -0
  137. package/dist/reachability/clusterReachability.js.map +1 -0
  138. package/dist/reachability/index.js +263 -390
  139. package/dist/reachability/index.js.map +1 -1
  140. package/dist/reachability/request.js +6 -4
  141. package/dist/reachability/request.js.map +1 -1
  142. package/dist/reachability/util.js +29 -0
  143. package/dist/reachability/util.js.map +1 -0
  144. package/dist/reconnection-manager/index.js +266 -202
  145. package/dist/reconnection-manager/index.js.map +1 -1
  146. package/dist/recording-controller/index.js +21 -2
  147. package/dist/recording-controller/index.js.map +1 -1
  148. package/dist/recording-controller/util.js +9 -8
  149. package/dist/recording-controller/util.js.map +1 -1
  150. package/dist/roap/index.js +66 -28
  151. package/dist/roap/index.js.map +1 -1
  152. package/dist/roap/request.js +48 -64
  153. package/dist/roap/request.js.map +1 -1
  154. package/dist/roap/turnDiscovery.js +407 -79
  155. package/dist/roap/turnDiscovery.js.map +1 -1
  156. package/dist/rtcMetrics/constants.js +12 -0
  157. package/dist/rtcMetrics/constants.js.map +1 -0
  158. package/dist/rtcMetrics/index.js +179 -0
  159. package/dist/rtcMetrics/index.js.map +1 -0
  160. package/dist/statsAnalyzer/index.js +389 -304
  161. package/dist/statsAnalyzer/index.js.map +1 -1
  162. package/dist/statsAnalyzer/mqaUtil.js +296 -156
  163. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  164. package/dist/types/annotation/annotation.types.d.ts +42 -0
  165. package/dist/types/annotation/constants.d.ts +31 -0
  166. package/dist/types/annotation/index.d.ts +117 -0
  167. package/dist/types/breakouts/events.d.ts +8 -0
  168. package/dist/types/breakouts/utils.d.ts +9 -2
  169. package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
  170. package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
  171. package/dist/types/common/errors/webex-errors.d.ts +25 -1
  172. package/dist/types/common/logs/request.d.ts +2 -0
  173. package/dist/types/common/queue.d.ts +9 -7
  174. package/dist/types/config.d.ts +2 -7
  175. package/dist/types/constants.d.ts +204 -32
  176. package/dist/types/controls-options-manager/enums.d.ts +11 -1
  177. package/dist/types/controls-options-manager/index.d.ts +17 -1
  178. package/dist/types/controls-options-manager/types.d.ts +43 -0
  179. package/dist/types/controls-options-manager/util.d.ts +1 -7
  180. package/dist/types/index.d.ts +6 -5
  181. package/dist/types/interceptors/index.d.ts +2 -0
  182. package/dist/types/interceptors/locusRetry.d.ts +27 -0
  183. package/dist/types/interpretation/collection.d.ts +5 -0
  184. package/dist/types/interpretation/index.d.ts +5 -0
  185. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  186. package/dist/types/locus-info/index.d.ts +57 -4
  187. package/dist/types/locus-info/parser.d.ts +66 -6
  188. package/dist/types/media/index.d.ts +2 -0
  189. package/dist/types/media/properties.d.ts +34 -49
  190. package/dist/types/mediaQualityMetrics/config.d.ts +99 -223
  191. package/dist/types/meeting/in-meeting-actions.d.ts +86 -2
  192. package/dist/types/meeting/index.d.ts +630 -505
  193. package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
  194. package/dist/types/meeting/muteState.d.ts +88 -26
  195. package/dist/types/meeting/request.d.ts +67 -43
  196. package/dist/types/meeting/util.d.ts +117 -1
  197. package/dist/types/meeting/voicea-meeting.d.ts +16 -0
  198. package/dist/types/meeting-info/index.d.ts +13 -1
  199. package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
  200. package/dist/types/meetings/collection.d.ts +17 -0
  201. package/dist/types/meetings/index.d.ts +113 -21
  202. package/dist/types/meetings/meetings.types.d.ts +4 -0
  203. package/dist/types/member/index.d.ts +14 -0
  204. package/dist/types/member/types.d.ts +32 -0
  205. package/dist/types/members/collection.d.ts +5 -0
  206. package/dist/types/members/index.d.ts +35 -2
  207. package/dist/types/members/request.d.ts +73 -9
  208. package/dist/types/members/types.d.ts +25 -0
  209. package/dist/types/members/util.d.ts +214 -1
  210. package/dist/types/metrics/constants.d.ts +17 -0
  211. package/dist/types/metrics/index.d.ts +4 -111
  212. package/dist/types/multistream/mediaRequestManager.d.ts +71 -3
  213. package/dist/types/multistream/receiveSlot.d.ts +7 -3
  214. package/dist/types/multistream/receiveSlotManager.d.ts +14 -4
  215. package/dist/types/multistream/remoteMedia.d.ts +3 -31
  216. package/dist/types/multistream/remoteMediaGroup.d.ts +2 -9
  217. package/dist/types/multistream/remoteMediaManager.d.ts +61 -2
  218. package/dist/types/multistream/sendSlotManager.d.ts +69 -0
  219. package/dist/types/reachability/clusterReachability.d.ts +109 -0
  220. package/dist/types/reachability/index.d.ts +60 -95
  221. package/dist/types/reachability/request.d.ts +3 -1
  222. package/dist/types/reachability/util.d.ts +8 -0
  223. package/dist/types/reconnection-manager/index.d.ts +19 -0
  224. package/dist/types/recording-controller/index.d.ts +15 -1
  225. package/dist/types/recording-controller/util.d.ts +5 -4
  226. package/dist/types/roap/index.d.ts +11 -2
  227. package/dist/types/roap/request.d.ts +9 -8
  228. package/dist/types/roap/turnDiscovery.d.ts +90 -9
  229. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  230. package/dist/types/rtcMetrics/index.d.ts +61 -0
  231. package/dist/types/statsAnalyzer/index.d.ts +34 -12
  232. package/dist/types/statsAnalyzer/mqaUtil.d.ts +28 -4
  233. package/dist/types/webinar/collection.d.ts +16 -0
  234. package/dist/types/webinar/index.d.ts +5 -0
  235. package/dist/webinar/collection.js +44 -0
  236. package/dist/webinar/collection.js.map +1 -0
  237. package/dist/webinar/index.js +69 -0
  238. package/dist/webinar/index.js.map +1 -0
  239. package/package.json +22 -19
  240. package/src/annotation/annotation.types.ts +50 -0
  241. package/src/annotation/constants.ts +36 -0
  242. package/src/annotation/index.ts +328 -0
  243. package/src/breakouts/README.md +27 -6
  244. package/src/breakouts/breakout.ts +67 -9
  245. package/src/breakouts/events.ts +56 -0
  246. package/src/breakouts/index.ts +494 -73
  247. package/src/breakouts/utils.ts +26 -8
  248. package/src/common/errors/no-meeting-info.ts +24 -0
  249. package/src/common/errors/reclaim-host-role-errors.ts +134 -0
  250. package/src/common/errors/webex-errors.ts +44 -2
  251. package/src/common/logs/logger-proxy.ts +1 -1
  252. package/src/common/logs/request.ts +5 -1
  253. package/src/common/queue.ts +22 -8
  254. package/src/config.ts +6 -13
  255. package/src/constants.ts +234 -22
  256. package/src/controls-options-manager/enums.ts +12 -0
  257. package/src/controls-options-manager/index.ts +116 -21
  258. package/src/controls-options-manager/types.ts +59 -0
  259. package/src/controls-options-manager/util.ts +294 -14
  260. package/src/index.ts +45 -0
  261. package/src/interceptors/index.ts +3 -0
  262. package/src/interceptors/locusRetry.ts +67 -0
  263. package/src/interpretation/README.md +60 -0
  264. package/src/interpretation/collection.ts +19 -0
  265. package/src/interpretation/index.ts +349 -0
  266. package/src/interpretation/siLanguage.ts +18 -0
  267. package/src/locus-info/controlsUtils.ts +108 -0
  268. package/src/locus-info/index.ts +417 -59
  269. package/src/locus-info/infoUtils.ts +10 -2
  270. package/src/locus-info/mediaSharesUtils.ts +80 -0
  271. package/src/locus-info/parser.ts +258 -47
  272. package/src/locus-info/selfUtils.ts +81 -5
  273. package/src/media/index.ts +100 -108
  274. package/src/media/properties.ts +88 -117
  275. package/src/mediaQualityMetrics/config.ts +103 -238
  276. package/src/meeting/in-meeting-actions.ts +171 -3
  277. package/src/meeting/index.ts +3929 -2622
  278. package/src/meeting/locusMediaRequest.ts +313 -0
  279. package/src/meeting/muteState.ts +237 -136
  280. package/src/meeting/request.ts +173 -122
  281. package/src/meeting/util.ts +690 -395
  282. package/src/meeting/voicea-meeting.ts +122 -0
  283. package/src/meeting-info/index.ts +81 -8
  284. package/src/meeting-info/meeting-info-v2.ts +166 -16
  285. package/src/meeting-info/util.ts +13 -10
  286. package/src/meeting-info/utilv2.ts +47 -37
  287. package/src/meetings/collection.ts +33 -0
  288. package/src/meetings/index.ts +507 -127
  289. package/src/meetings/meetings.types.ts +12 -0
  290. package/src/meetings/request.ts +2 -0
  291. package/src/meetings/util.ts +81 -12
  292. package/src/member/index.ts +57 -0
  293. package/src/member/types.ts +38 -0
  294. package/src/member/util.ts +141 -25
  295. package/src/members/collection.ts +8 -0
  296. package/src/members/index.ts +133 -7
  297. package/src/members/request.ts +97 -17
  298. package/src/members/types.ts +29 -0
  299. package/src/members/util.ts +333 -240
  300. package/src/metrics/constants.ts +17 -0
  301. package/src/metrics/index.ts +1 -469
  302. package/src/multistream/mediaRequestManager.ts +271 -56
  303. package/src/multistream/receiveSlot.ts +11 -4
  304. package/src/multistream/receiveSlotManager.ts +34 -24
  305. package/src/multistream/remoteMedia.ts +5 -3
  306. package/src/multistream/remoteMediaGroup.ts +78 -0
  307. package/src/multistream/remoteMediaManager.ts +248 -45
  308. package/src/multistream/sendSlotManager.ts +198 -0
  309. package/src/reachability/clusterReachability.ts +320 -0
  310. package/src/reachability/index.ts +229 -346
  311. package/src/reachability/request.ts +8 -4
  312. package/src/reachability/util.ts +24 -0
  313. package/src/reconnection-manager/index.ts +128 -97
  314. package/src/recording-controller/index.ts +20 -3
  315. package/src/recording-controller/util.ts +26 -9
  316. package/src/roap/index.ts +76 -25
  317. package/src/roap/request.ts +48 -67
  318. package/src/roap/turnDiscovery.ts +331 -67
  319. package/src/rtcMetrics/constants.ts +3 -0
  320. package/src/rtcMetrics/index.ts +166 -0
  321. package/src/statsAnalyzer/index.ts +496 -419
  322. package/src/statsAnalyzer/mqaUtil.ts +317 -170
  323. package/src/webinar/collection.ts +31 -0
  324. package/src/webinar/index.ts +62 -0
  325. package/test/integration/spec/converged-space-meetings.js +60 -3
  326. package/test/integration/spec/journey.js +321 -262
  327. package/test/integration/spec/space-meeting.js +76 -3
  328. package/test/unit/spec/annotation/index.ts +418 -0
  329. package/test/unit/spec/breakouts/breakout.ts +119 -28
  330. package/test/unit/spec/breakouts/events.ts +89 -0
  331. package/test/unit/spec/breakouts/index.ts +1204 -118
  332. package/test/unit/spec/breakouts/utils.js +27 -2
  333. package/test/unit/spec/common/queue.js +31 -2
  334. package/test/unit/spec/controls-options-manager/index.js +163 -0
  335. package/test/unit/spec/controls-options-manager/util.js +576 -60
  336. package/test/unit/spec/fixture/locus.js +1 -0
  337. package/test/unit/spec/interceptors/locusRetry.ts +131 -0
  338. package/test/unit/spec/interpretation/collection.ts +15 -0
  339. package/test/unit/spec/interpretation/index.ts +625 -0
  340. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  341. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  342. package/test/unit/spec/locus-info/index.js +1372 -37
  343. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  344. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  345. package/test/unit/spec/locus-info/mediaSharesUtils.ts +41 -0
  346. package/test/unit/spec/locus-info/parser.js +116 -35
  347. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  348. package/test/unit/spec/locus-info/selfUtils.js +203 -17
  349. package/test/unit/spec/media/index.ts +178 -81
  350. package/test/unit/spec/media/properties.ts +2 -2
  351. package/test/unit/spec/meeting/in-meeting-actions.ts +85 -3
  352. package/test/unit/spec/meeting/index.js +7835 -2501
  353. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  354. package/test/unit/spec/meeting/muteState.js +549 -207
  355. package/test/unit/spec/meeting/request.js +494 -54
  356. package/test/unit/spec/meeting/utils.js +827 -74
  357. package/test/unit/spec/meeting/voicea-meeting.ts +266 -0
  358. package/test/unit/spec/meeting-info/index.js +300 -0
  359. package/test/unit/spec/meeting-info/meetinginfov2.js +535 -9
  360. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  361. package/test/unit/spec/meetings/collection.js +26 -0
  362. package/test/unit/spec/meetings/index.js +1489 -219
  363. package/test/unit/spec/meetings/utils.js +229 -2
  364. package/test/unit/spec/member/index.js +61 -6
  365. package/test/unit/spec/member/util.js +510 -34
  366. package/test/unit/spec/members/index.js +432 -1
  367. package/test/unit/spec/members/request.js +206 -27
  368. package/test/unit/spec/members/utils.js +210 -0
  369. package/test/unit/spec/metrics/index.js +2 -52
  370. package/test/unit/spec/multistream/mediaRequestManager.ts +782 -114
  371. package/test/unit/spec/multistream/receiveSlot.ts +9 -1
  372. package/test/unit/spec/multistream/receiveSlotManager.ts +32 -30
  373. package/test/unit/spec/multistream/remoteMedia.ts +2 -0
  374. package/test/unit/spec/multistream/remoteMediaGroup.ts +344 -0
  375. package/test/unit/spec/multistream/remoteMediaManager.ts +524 -0
  376. package/test/unit/spec/multistream/sendSlotManager.ts +274 -0
  377. package/test/unit/spec/reachability/clusterReachability.ts +279 -0
  378. package/test/unit/spec/reachability/index.ts +551 -14
  379. package/test/unit/spec/reachability/request.js +3 -1
  380. package/test/unit/spec/reachability/util.ts +40 -0
  381. package/test/unit/spec/reconnection-manager/index.js +171 -11
  382. package/test/unit/spec/recording-controller/index.js +293 -218
  383. package/test/unit/spec/recording-controller/util.js +223 -96
  384. package/test/unit/spec/roap/index.ts +233 -81
  385. package/test/unit/spec/roap/request.ts +100 -62
  386. package/test/unit/spec/roap/turnDiscovery.ts +682 -108
  387. package/test/unit/spec/rtcMetrics/index.ts +122 -0
  388. package/test/unit/spec/stats-analyzer/index.js +1431 -12
  389. package/test/unit/spec/webinar/collection.ts +13 -0
  390. package/test/unit/spec/webinar/index.ts +60 -0
  391. package/test/utils/integrationTestUtils.js +46 -0
  392. package/test/utils/testUtils.js +0 -57
  393. package/test/utils/webex-test-users.js +12 -4
  394. package/dist/metrics/config.js +0 -289
  395. package/dist/metrics/config.js.map +0 -1
  396. package/dist/types/metrics/config.d.ts +0 -169
  397. package/src/index.js +0 -18
  398. package/src/metrics/config.ts +0 -485
@@ -5,7 +5,8 @@ import {BREAKOUTS} from '@webex/plugin-meetings/src/constants';
5
5
  import sinon from 'sinon';
6
6
  import MockWebex from '@webex/test-helper-mock-webex';
7
7
  import testUtils from '../../../utils/testUtils';
8
- import BreakoutEditLockedError from "@webex/plugin-meetings/src/breakouts/edit-lock-error";
8
+ import BreakoutEditLockedError from '@webex/plugin-meetings/src/breakouts/edit-lock-error';
9
+ import breakoutEvent from '../../../../src/breakouts/events';
9
10
 
10
11
  const getBOResponse = (status: string) => {
11
12
  return {
@@ -47,6 +48,36 @@ const getBOResponse = (status: string) => {
47
48
  };
48
49
  };
49
50
 
51
+ const getBOResponseWithEditLockInfo = (status: string, withOutToken?: boolean) => {
52
+ return {
53
+ url: 'url',
54
+ locusUrl: 'locusUrl',
55
+ mainGroupId: 'mainGroupId',
56
+ mainSessionId: 'mainSessionId',
57
+ editlock: {
58
+ state: 'LOCKED',
59
+ ttl: 30,
60
+ userId: 'cc5d452f-04b6-4876-a4c3-28ca21982c6a',
61
+ token: withOutToken ? '' : 'token1',
62
+ },
63
+ groups: [
64
+ {
65
+ sessions: [
66
+ {
67
+ name: 'Breakout Session 1',
68
+ subConfId: 1,
69
+ anyoneCanJoin: false,
70
+ locusUrl: 'locusUrl',
71
+ venueUrl: 'venueUrl',
72
+ allowed: ['allowed id1', 'allowed id2'],
73
+ id: 'sessionId1',
74
+ },
75
+ ],
76
+ },
77
+ ],
78
+ };
79
+ };
80
+
50
81
  describe('plugin-meetings', () => {
51
82
  describe('Breakouts', () => {
52
83
  let webex;
@@ -64,6 +95,8 @@ describe('plugin-meetings', () => {
64
95
  breakouts.locusUrl = 'locusUrl';
65
96
  breakouts.breakoutServiceUrl = 'breakoutServiceUrl';
66
97
  webex.request = sinon.stub().returns(Promise.resolve('REQUEST_RETURN_VALUE'));
98
+ webex.meetings = {};
99
+ webex.meetings.getMeetingByType = sinon.stub();
67
100
  });
68
101
 
69
102
  describe('#initialize', () => {
@@ -71,19 +104,59 @@ describe('plugin-meetings', () => {
71
104
  assert.equal(breakouts.namespace, 'Meetings');
72
105
  });
73
106
 
74
- it('emits BREAKOUTS_CLOSING event when the status is CLOSING', () => {
75
- let called = false;
76
- breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.BREAKOUTS_CLOSING, () => {
77
- called = true;
107
+ it('emits BREAKOUTS_CLOSING event when the breakoutStatus is CLOSING', () => {
108
+ const checkIsCalled = (prev, deps) => {
109
+ breakouts.set(prev);
110
+ const breakoutClosingHandler = sinon.stub();
111
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.BREAKOUTS_CLOSING, breakoutClosingHandler);
112
+ assert.notCalled(breakoutClosingHandler);
113
+ breakouts.set(deps);
114
+ assert.calledOnce(breakoutClosingHandler);
115
+ }
116
+
117
+ checkIsCalled({sessionType: BREAKOUTS.SESSION_TYPES.MAIN, groups: undefined, status: undefined}, {
118
+ sessionType: BREAKOUTS.SESSION_TYPES.MAIN,
119
+ groups: [{status: BREAKOUTS.STATUS.CLOSING}],
120
+ status: undefined
78
121
  });
79
122
 
80
- breakouts.set('status', 'something');
123
+ checkIsCalled({sessionType: BREAKOUTS.SESSION_TYPES.MAIN, groups: [{status: BREAKOUTS.STATUS.OPEN}], status: undefined}, {
124
+ sessionType: BREAKOUTS.SESSION_TYPES.MAIN,
125
+ groups: [{status: BREAKOUTS.STATUS.CLOSING}],
126
+ status: undefined
127
+ });
81
128
 
82
- assert.isFalse(called);
129
+ checkIsCalled({sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT, groups: undefined, status: undefined}, {
130
+ sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT,
131
+ groups: undefined,
132
+ status: BREAKOUTS.STATUS.CLOSING
133
+ });
83
134
 
84
- breakouts.set({status: BREAKOUTS.STATUS.CLOSING});
135
+ checkIsCalled({sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT, groups: undefined, status: BREAKOUTS.STATUS.OPEN}, {
136
+ sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT,
137
+ groups: undefined,
138
+ status: BREAKOUTS.STATUS.CLOSING
139
+ });
85
140
 
86
- assert.isTrue(called);
141
+ });
142
+
143
+ it('should not emits BREAKOUTS_CLOSING event when just sessionType changed from BREAKOUT to MAIN', () => {
144
+ breakouts.set({
145
+ sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT,
146
+ groups: undefined,
147
+ status: BREAKOUTS.STATUS.CLOSING
148
+ });
149
+
150
+ const breakoutClosingHandler = sinon.stub();
151
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.BREAKOUTS_CLOSING, breakoutClosingHandler);
152
+
153
+ breakouts.set({
154
+ sessionType: BREAKOUTS.SESSION_TYPES.MAIN,
155
+ groups: [{status: BREAKOUTS.STATUS.CLOSING}],
156
+ status: undefined
157
+ });
158
+
159
+ assert.notCalled(breakoutClosingHandler);
87
160
  });
88
161
 
89
162
  it('debounces querying rosters on add', () => {
@@ -92,6 +165,64 @@ describe('plugin-meetings', () => {
92
165
 
93
166
  assert.calledOnceWithExactly(breakouts.debouncedQueryRosters);
94
167
  });
168
+
169
+ it('call triggerReturnToMainEvent correctly when requested breakout add', () => {
170
+ breakouts.triggerReturnToMainEvent = sinon.stub();
171
+ breakouts.breakouts.add({sessionId: 'session1', sessionType: 'MAIN'});
172
+ assert.calledOnceWithExactly(breakouts.triggerReturnToMainEvent, breakouts.breakouts.get('session1'));
173
+ });
174
+
175
+ it('call triggerReturnToMainEvent correctly when breakout requestedLastModifiedTime change', () => {
176
+ breakouts.breakouts.add({sessionId: 'session1', sessionType: 'MAIN'});
177
+ breakouts.triggerReturnToMainEvent = sinon.stub();
178
+ breakouts.breakouts.get('session1').set({requestedLastModifiedTime: "2023-05-09T17:16:01.000Z"});
179
+ assert.calledOnceWithExactly(breakouts.triggerReturnToMainEvent, breakouts.breakouts.get('session1'));
180
+ });
181
+
182
+ it('call queryPreAssignments correctly when should query preAssignments is true', () => {
183
+ breakouts.queryPreAssignments = sinon.stub();
184
+ breakouts.set({
185
+ canManageBreakouts: true,
186
+ enableBreakoutSession: true,
187
+ hasBreakoutPreAssignments: true,
188
+ });
189
+ assert.calledThrice(breakouts.queryPreAssignments);
190
+ });
191
+ });
192
+
193
+ describe('#listenToCurrentSessionTypeChange', () => {
194
+ it('triggers leave breakout event when sessionType changed from SESSION to MAIN', () => {
195
+ const handler = sinon.stub();
196
+ breakouts.currentBreakoutSession.set({sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT})
197
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
198
+ breakouts.currentBreakoutSession.set({sessionType: BREAKOUTS.SESSION_TYPES.MAIN});
199
+
200
+ assert.calledOnceWithExactly(handler);
201
+
202
+ breakouts.stopListening(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
203
+ });
204
+
205
+ it('should not triggers leave breakout event when sessionType changed from undefined to MAIN', () => {
206
+ const handler = sinon.stub();
207
+ breakouts.currentBreakoutSession.set({sessionType: undefined})
208
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
209
+ breakouts.currentBreakoutSession.set({sessionType: BREAKOUTS.SESSION_TYPES.MAIN});
210
+
211
+ assert.notCalled(handler);
212
+
213
+ breakouts.stopListening(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
214
+ });
215
+
216
+ it('should not triggers leave breakout event when sessionType changed from MAIN to SESSION', () => {
217
+ const handler = sinon.stub();
218
+ breakouts.currentBreakoutSession.set({sessionType: BREAKOUTS.SESSION_TYPES.MAIN})
219
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
220
+ breakouts.currentBreakoutSession.set({sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT});
221
+
222
+ assert.notCalled(handler);
223
+
224
+ breakouts.stopListening(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
225
+ });
95
226
  });
96
227
 
97
228
  describe('#listenToBroadcastMessages', () => {
@@ -151,6 +282,33 @@ describe('plugin-meetings', () => {
151
282
  });
152
283
  });
153
284
 
285
+ describe('#listenToBreakoutHelp', () => {
286
+ it('triggers ask for help event when a help received', () => {
287
+ const call = webex.internal.mercury.on.getCall(1);
288
+ const callback = call.args[1];
289
+
290
+ assert.equal(call.args[0], 'event:breakout.help');
291
+
292
+ let data;
293
+
294
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.ASK_FOR_HELP, (eventData) => {
295
+ data = eventData;
296
+ });
297
+
298
+ callback({
299
+ data: {
300
+ participant: 'participant',
301
+ sessionId: 'sessionId'
302
+ },
303
+ });
304
+
305
+ assert.deepEqual(data, {
306
+ participant: 'participant',
307
+ sessionId: 'sessionId',
308
+ });
309
+ });
310
+ });
311
+
154
312
  describe('#updateBreakout', () => {
155
313
  it('updates the current breakout session', () => {
156
314
  breakouts.updateBreakout({
@@ -190,6 +348,90 @@ describe('plugin-meetings', () => {
190
348
  assert.equal(breakouts.currentBreakoutSession.assignedCurrent, false);
191
349
  assert.equal(breakouts.currentBreakoutSession.requested, false);
192
350
  });
351
+
352
+ it('update the startTime correctly when no attribute startTime exists on params', () => {
353
+ breakouts.updateBreakout({
354
+ startTime: "startTime"
355
+ })
356
+ assert.equal(breakouts.startTime, 'startTime');
357
+
358
+ breakouts.updateBreakout({})
359
+ assert.equal(breakouts.startTime, undefined);
360
+ });
361
+
362
+ it('update the status correctly when no attribute status exists on params', () => {
363
+ breakouts.updateBreakout({
364
+ status: 'CLOSING'
365
+ })
366
+ assert.equal(breakouts.status, 'CLOSING');
367
+
368
+ breakouts.updateBreakout({})
369
+ assert.equal(breakouts.status, undefined);
370
+ });
371
+
372
+ it('call clearBreakouts if current breakout is not in-progress', () => {
373
+ breakouts.clearBreakouts = sinon.stub();
374
+ breakouts.updateBreakout({status: 'CLOSED'})
375
+ assert.calledOnce(breakouts.clearBreakouts);
376
+ });
377
+
378
+ it('updates the current breakout session, call onBreakoutJoinResponse when session changed', () => {
379
+ breakouts.webex.meetings = {
380
+ getMeetingByType: sinon.stub().returns({
381
+ id: 'meeting-id'
382
+ })
383
+ };
384
+ const onBreakoutJoinResponseSpy = sinon.stub(breakoutEvent,'onBreakoutJoinResponse')
385
+ breakouts.currentBreakoutSession.sessionId = "sessionId-old";
386
+ breakouts.updateBreakout({
387
+ sessionId: 'sessionId-new',
388
+ groupId: 'groupId',
389
+ sessionType: 'sessionType',
390
+ url: 'url',
391
+ name: 'name',
392
+ allowBackToMain: true,
393
+ delayCloseTime: 10,
394
+ enableBreakoutSession: true,
395
+ startTime: 'startTime',
396
+ status: 'active',
397
+ locusUrl: 'locusUrl',
398
+ breakoutMoveId: 'breakoutMoveId',
399
+ });
400
+
401
+ assert.calledOnce(onBreakoutJoinResponseSpy);
402
+
403
+ onBreakoutJoinResponseSpy.restore()
404
+
405
+ });
406
+
407
+ it('updates the current breakout session, not call onBreakoutJoinResponse when session no changed', () => {
408
+ breakouts.webex.meetings = {
409
+ getMeetingByType: sinon.stub().returns({
410
+ id: 'meeting-id'
411
+ })
412
+ };
413
+ const onBreakoutJoinResponseSpy = sinon.stub(breakoutEvent, 'onBreakoutJoinResponse');
414
+ breakouts.currentBreakoutSession.sessionId = "sessionId";
415
+ breakouts.currentBreakoutSession.groupId = "groupId";
416
+ breakouts.updateBreakout({
417
+ sessionId: 'sessionId',
418
+ groupId: 'groupId',
419
+ sessionType: 'sessionType',
420
+ url: 'url',
421
+ name: 'name',
422
+ allowBackToMain: true,
423
+ delayCloseTime: 10,
424
+ enableBreakoutSession: true,
425
+ startTime: 'startTime',
426
+ status: 'active',
427
+ locusUrl: 'locusUrl',
428
+ breakoutMoveId: 'breakoutMoveId',
429
+ });
430
+
431
+ assert.notCalled(onBreakoutJoinResponseSpy);
432
+ onBreakoutJoinResponseSpy.restore()
433
+
434
+ });
193
435
  });
194
436
 
195
437
  describe('#updateBreakoutSessions', () => {
@@ -210,7 +452,7 @@ describe('plugin-meetings', () => {
210
452
 
211
453
  it('works', () => {
212
454
  breakouts.set('url', 'url');
213
-
455
+ breakouts.set('sessionType', BREAKOUTS.SESSION_TYPES.MAIN);
214
456
  const payload = {
215
457
  breakoutSessions: {
216
458
  active: [{sessionId: 'sessionId1'}],
@@ -229,6 +471,26 @@ describe('plugin-meetings', () => {
229
471
  checkBreakout(breakouts.breakouts.get('sessionId4'), 'sessionId4', 'assignedCurrent');
230
472
  checkBreakout(breakouts.breakouts.get('sessionId5'), 'sessionId5', 'requested');
231
473
  });
474
+
475
+ it('set requestedLastModifiedTime correctly', () => {
476
+ const payload = {
477
+ breakoutSessions: {
478
+ assigned: [{sessionId: 'sessionId1'}],
479
+ requested: [{sessionId: 'sessionId2', modifiedAt: "2023-05-09T17:16:01.000Z"}],
480
+ },
481
+ };
482
+
483
+ breakouts.updateBreakoutSessions(payload);
484
+ assert.equal(breakouts.breakouts.get('sessionId1').requestedLastModifiedTime, undefined)
485
+ assert.equal(breakouts.breakouts.get('sessionId2').requestedLastModifiedTime, "2023-05-09T17:16:01.000Z")
486
+ });
487
+
488
+ it('not update breakout sessions when breakouts is closing', () => {
489
+ breakouts.set('status', 'CLOSING');
490
+ breakouts.breakouts.set = sinon.stub();
491
+ breakouts.updateBreakoutSessions({breakoutSessions: {}});
492
+ assert.notCalled(breakouts.breakouts.set);
493
+ });
232
494
  });
233
495
 
234
496
  describe('#locusUrlUpdate', () => {
@@ -239,6 +501,18 @@ describe('plugin-meetings', () => {
239
501
  });
240
502
  });
241
503
 
504
+ describe('#updateCanManageBreakouts', () => {
505
+ it('update canManageBreakouts', () => {
506
+ breakouts.updateCanManageBreakouts(true);
507
+
508
+ assert.equal(breakouts.canManageBreakouts, true);
509
+
510
+ breakouts.updateCanManageBreakouts(false);
511
+
512
+ assert.equal(breakouts.canManageBreakouts, false);
513
+ });
514
+ });
515
+
242
516
  describe('#cleanUp', () => {
243
517
  it('stops listening', () => {
244
518
  breakouts.stopListening = sinon.stub();
@@ -267,6 +541,122 @@ describe('plugin-meetings', () => {
267
541
  });
268
542
  });
269
543
 
544
+ describe('#isActiveBreakout', () => {
545
+ it('return is current is breakout with active status', () => {
546
+ assert.equal(breakouts.isActiveBreakout, false);
547
+ breakouts.set('sessionType', BREAKOUTS.SESSION_TYPES.BREAKOUT);
548
+ assert.equal(breakouts.isActiveBreakout, false);
549
+ breakouts.set('status', BREAKOUTS.STATUS.OPEN);
550
+ assert.equal(breakouts.isActiveBreakout, true);
551
+ });
552
+ });
553
+
554
+ describe('#breakoutGroupId', () => {
555
+ it('return empty breakout group id for managing breakouts if no data', () => {
556
+ assert.equal(breakouts.breakoutGroupId, '');
557
+ breakouts.set('manageGroups', []);
558
+ assert.equal(breakouts.breakoutGroupId, '');
559
+ breakouts.set('manageGroups', [{name: 'test'}]);
560
+ assert.equal(breakouts.breakoutGroupId, undefined);
561
+ });
562
+ it('return the group id if has id in manageGroups', () => {
563
+ breakouts.set('manageGroups', [{id: 'groupId1'}]);
564
+ assert.equal(breakouts.breakoutGroupId, 'groupId1');
565
+ });
566
+ it('return empty group id if group status is CLOSED', () => {
567
+ breakouts.set('manageGroups', [{id: 'groupId1', status: 'CLOSED'}]);
568
+ assert.equal(breakouts.breakoutGroupId, '');
569
+ });
570
+ });
571
+
572
+ describe('#shouldQueryPreAssignments', () => {
573
+ it('returns should query preAssignments depends on status', () => {
574
+ assert.equal(breakouts.shouldQueryPreAssignments, false);
575
+ breakouts.set('canManageBreakouts', true);
576
+ assert.equal(breakouts.shouldQueryPreAssignments, false);
577
+ breakouts.set('enableBreakoutSession', true);
578
+ assert.equal(breakouts.shouldQueryPreAssignments, false);
579
+ breakouts.set('hasBreakoutPreAssignments', true);
580
+ assert.equal(breakouts.shouldQueryPreAssignments, true);
581
+ });
582
+ });
583
+
584
+ describe('#breakoutStatus', () => {
585
+ it('return status from groups with session type', () => {
586
+ breakouts.set('groups', [{status: "OPEN"}]);
587
+ breakouts.set('status', "CLOSED");
588
+ breakouts.set('sessionType', BREAKOUTS.SESSION_TYPES.MAIN);
589
+
590
+ assert.equal(breakouts.breakoutStatus, "OPEN")
591
+
592
+ breakouts.set('sessionType', BREAKOUTS.SESSION_TYPES.BREAKOUT);
593
+
594
+ assert.equal(breakouts.breakoutStatus, "CLOSED")
595
+ });
596
+ });
597
+
598
+ describe('#_setManageGroups', () => {
599
+ it('do nothing if breakout info is empty', () => {
600
+ breakouts._setManageGroups();
601
+ assert.equal(breakouts.manageGroups, undefined);
602
+ breakouts._setManageGroups({body: null});
603
+ assert.equal(breakouts.manageGroups, undefined);
604
+ breakouts._setManageGroups({body: {groups: null}});
605
+ assert.equal(breakouts.manageGroups, undefined);
606
+ });
607
+ it('set the groups into manageGroups if has groups in side breakout info', () => {
608
+ breakouts._setManageGroups({body: {groups: [{id: 'groupId1'}]}});
609
+ assert.deepEqual(breakouts.manageGroups, [{id: 'groupId1'}]);
610
+ });
611
+ });
612
+
613
+ describe('#isBreakoutInProgress', () => {
614
+ it('return breakout is in progress depends on the status(groups/breakouts)', () => {
615
+ breakouts.set('groups', [{status: 'CLOSING'}]);
616
+
617
+ assert.equal(breakouts.isBreakoutInProgress(), true)
618
+
619
+ breakouts.set('groups', undefined);
620
+ breakouts.set('status', 'OPEN');
621
+
622
+ assert.equal(breakouts.isBreakoutInProgress(), true);
623
+
624
+ breakouts.set('groups', [{status: 'CLOSED'}]);
625
+
626
+ assert.equal(breakouts.isBreakoutInProgress(), false);
627
+
628
+ breakouts.set('groups', undefined);
629
+ breakouts.set('status', 'CLOSED');
630
+
631
+ assert.equal(breakouts.isBreakoutInProgress(), false);
632
+
633
+ breakouts.set('status', undefined);
634
+
635
+ assert.equal(breakouts.isBreakoutInProgress(), false);
636
+ });
637
+ });
638
+
639
+ describe('#isBreakoutIClosing', () => {
640
+ it('return breakout is closing depends the status(groups/breakouts)', () => {
641
+ breakouts.set('groups', [{status: 'CLOSING'}]);
642
+
643
+ assert.equal(breakouts.isBreakoutIClosing(), true);
644
+
645
+ breakouts.set('groups', undefined);
646
+ breakouts.set('status', 'CLOSING');
647
+
648
+ assert.equal(breakouts.isBreakoutIClosing(), true);
649
+
650
+ breakouts.set('status', undefined);
651
+
652
+ assert.equal(breakouts.isBreakoutIClosing(), false);
653
+
654
+ breakouts.set('groups', [{status: 'OPEN'}]);
655
+
656
+ assert.equal(breakouts.isBreakoutIClosing(), false);
657
+ });
658
+ });
659
+
270
660
  describe('#queryRosters', () => {
271
661
  it('makes the expected query', async () => {
272
662
  webex.request.returns(
@@ -334,6 +724,22 @@ describe('plugin-meetings', () => {
334
724
  });
335
725
  });
336
726
 
727
+ describe('#clearBreakouts', () => {
728
+ it('call reset to clear breakouts', () => {
729
+ breakouts.set('breakouts', [{id: 'session1'}]);
730
+ breakouts.breakouts.reset = sinon.stub();
731
+ breakouts.clearBreakouts();
732
+ assert.calledWith(breakouts.breakouts.reset);
733
+ });
734
+
735
+ it('do nothing if breakouts already is empty', () => {
736
+ breakouts.set('breakouts', []);
737
+ breakouts.breakouts.reset = sinon.stub();
738
+ breakouts.clearBreakouts();
739
+ assert.notCalled(breakouts.breakouts.reset);
740
+ });
741
+ });
742
+
337
743
  describe('#getMainSession', () => {
338
744
  it('returns main session as expect', () => {
339
745
  breakouts.updateBreakout({
@@ -347,24 +753,24 @@ describe('plugin-meetings', () => {
347
753
  enableBreakoutSession: true,
348
754
  startTime: 'startTime',
349
755
  status: 'active',
350
- locusUrl: 'locusUrl'
756
+ locusUrl: 'locusUrl',
351
757
  });
352
758
  const payload = {
353
759
  breakoutSessions: {
354
760
  active: [{sessionId: 'sessionId1'}],
355
- }
356
- }
357
- breakouts.updateBreakoutSessions(payload);
761
+ },
762
+ };
358
763
 
359
764
  breakouts.set('sessionType', BREAKOUTS.SESSION_TYPES.MAIN);
765
+ breakouts.updateBreakoutSessions(payload);
360
766
  let result = breakouts.getMainSession();
361
767
  assert.equal(result.sessionId, 'sessionId');
362
768
 
363
769
  const payload2 = {
364
770
  breakoutSessions: {
365
771
  active: [{sessionId: 'sessionId1', sessionType: BREAKOUTS.SESSION_TYPES.MAIN}],
366
- }
367
- }
772
+ },
773
+ };
368
774
  breakouts.updateBreakoutSessions(payload2);
369
775
  breakouts.set('sessionType', 'BREAKOUT');
370
776
  result = breakouts.getMainSession();
@@ -373,12 +779,12 @@ describe('plugin-meetings', () => {
373
779
  it('throw error if cannot find main session', () => {
374
780
  const fn = () => {
375
781
  breakouts.getMainSession();
376
- }
782
+ };
377
783
  expect(fn).to.throw(/no main session found/);
378
784
  });
379
785
  });
380
786
 
381
- describe('#askAllToReturn', () => {
787
+ describe('#askAllToReturn', () => {
382
788
  it('makes the request as expected', async () => {
383
789
  breakouts.set('sessionType', BREAKOUTS.SESSION_TYPES.MAIN);
384
790
  breakouts.currentBreakoutSession.sessionId = 'sessionId';
@@ -389,8 +795,8 @@ describe('plugin-meetings', () => {
389
795
  uri: 'url/requestMove',
390
796
  body: {
391
797
  groupId: 'groupId',
392
- sessionId: 'sessionId'
393
- }
798
+ sessionId: 'sessionId',
799
+ },
394
800
  });
395
801
  });
396
802
  });
@@ -403,16 +809,19 @@ describe('plugin-meetings', () => {
403
809
  });
404
810
 
405
811
  describe('#toggleBreakout', () => {
406
- it('enableBreakoutSession is undefined, run enableBreakouts then toggleBreakout', async() => {
407
- breakouts.enableBreakoutSession = undefined;
408
- breakouts.enableBreakouts = sinon.stub().resolves(({body: {
812
+ const mockEnableResponse = {
813
+ body: {
409
814
  sessionId: 'sessionId',
410
815
  groupId: 'groupId',
411
816
  name: 'name',
412
817
  current: true,
413
818
  sessionType: 'sessionType',
414
- url: 'url'
415
- }}))
819
+ url: 'url',
820
+ },
821
+ };
822
+ it('enableBreakoutSession is undefined, run enableBreakouts then toggleBreakout', async () => {
823
+ breakouts.enableBreakoutSession = undefined;
824
+ breakouts.enableBreakouts = sinon.stub().resolves(mockEnableResponse);
416
825
  breakouts.updateBreakout = sinon.stub().resolves();
417
826
  breakouts.doToggleBreakout = sinon.stub().resolves();
418
827
 
@@ -424,12 +833,31 @@ describe('plugin-meetings', () => {
424
833
  name: 'name',
425
834
  current: true,
426
835
  sessionType: 'sessionType',
427
- url: 'url'
836
+ url: 'url',
428
837
  });
429
838
  assert.calledOnceWithExactly(breakouts.doToggleBreakout, false);
430
839
  });
431
840
 
432
- it('enableBreakoutSession is exist, run toggleBreakout', async() => {
841
+ it('first time enable breakouts, call updateBreakout to set initial params', async () => {
842
+ breakouts.enableBreakoutSession = undefined;
843
+ breakouts.enableBreakouts = sinon.stub().resolves(mockEnableResponse);
844
+ breakouts.updateBreakout = sinon.stub().resolves();
845
+ breakouts.doToggleBreakout = sinon.stub();
846
+
847
+ await breakouts.toggleBreakout(true);
848
+ assert.calledOnceWithExactly(breakouts.updateBreakout, {
849
+ sessionId: 'sessionId',
850
+ groupId: 'groupId',
851
+ name: 'name',
852
+ current: true,
853
+ sessionType: 'sessionType',
854
+ url: 'url',
855
+ });
856
+
857
+ assert.notCalled(breakouts.doToggleBreakout);
858
+ });
859
+
860
+ it('enableBreakoutSession is exist, run toggleBreakout', async () => {
433
861
  breakouts.enableBreakoutSession = true;
434
862
  breakouts.doToggleBreakout = sinon.stub().resolves();
435
863
  await breakouts.toggleBreakout(true);
@@ -445,17 +873,19 @@ describe('plugin-meetings', () => {
445
873
  method: 'POST',
446
874
  uri: 'breakoutServiceUrl',
447
875
  body: {
448
- locusUrl: 'locusUrl'
449
- }
876
+ locusUrl: 'locusUrl',
877
+ },
450
878
  });
451
879
 
452
880
  assert.equal(result, 'REQUEST_RETURN_VALUE');
453
881
  });
454
882
  });
455
883
 
456
- describe('#broadcast', () => {
884
+ describe('#broadcast', () => {
457
885
  it('makes the request as expected', async () => {
458
- breakouts.breakoutRequest.broadcast = sinon.stub().returns(Promise.resolve('REQUEST_RETURN_VALUE'));
886
+ breakouts.breakoutRequest.broadcast = sinon
887
+ .stub()
888
+ .returns(Promise.resolve('REQUEST_RETURN_VALUE'));
459
889
  webex.request.returns(
460
890
  Promise.resolve({
461
891
  body: getBOResponse('OPEN'),
@@ -467,7 +897,7 @@ describe('plugin-meetings', () => {
467
897
  url: 'url',
468
898
  message: 'hello',
469
899
  options: undefined,
470
- groupId: 'groupId'
900
+ groupId: 'groupId',
471
901
  });
472
902
 
473
903
  assert.equal(result, 'REQUEST_RETURN_VALUE');
@@ -477,59 +907,204 @@ describe('plugin-meetings', () => {
477
907
  url: 'url',
478
908
  groupId: 'groupId',
479
909
  message: 'hello',
480
- options: {presenters: true, cohosts: true}
910
+ options: {presenters: true, cohosts: true},
481
911
  });
482
- assert.equal(result, 'REQUEST_RETURN_VALUE')
912
+ assert.equal(result, 'REQUEST_RETURN_VALUE');
483
913
  });
484
914
 
485
915
  it('throw error if no breakout group id found', () => {
486
916
  breakouts.set('sessionType', BREAKOUTS.SESSION_TYPES.MAIN);
487
917
  const fn = () => {
488
918
  breakouts.broadcast('hello');
489
- }
919
+ };
490
920
  expect(fn).to.throw(/no breakout session found/);
491
921
  });
492
922
  });
493
923
 
494
- describe('#start', () => {
495
- it('should start breakout sessions', async () => {
924
+ describe('#update', () => {
925
+ it('makes the request as expected', async () => {
926
+ const mockedReturnBody = getBOResponse('OPEN');
496
927
  webex.request.returns(
497
928
  Promise.resolve({
498
- body: getBOResponse('OPEN'),
929
+ body: mockedReturnBody,
499
930
  })
500
931
  );
501
-
502
- breakouts.set('url', 'url');
503
- await breakouts.getBreakout();
504
-
505
- const result = await breakouts.start();
506
- await breakouts.start({id: 'id', someOtherParam: 'someOtherParam'});
507
-
508
- const arg = webex.request.getCall(1).args[0];
509
- const argObj1 = arg.body.groups[0];
510
- const argObj2 = webex.request.getCall(2).args[0].body.groups[0];
511
-
512
- assert.equal(arg.uri, 'url');
513
- assert.equal(arg.method, 'PUT');
514
- assert.deepEqual(argObj1, {id:'groupId', action: 'START', allowBackToMain: false, allowToJoinLater: false});
515
- assert.deepEqual(argObj2, {id:'id', action: 'START', allowBackToMain: false, allowToJoinLater: false, someOtherParam: 'someOtherParam'});
516
- assert.deepEqual(result, {body: getBOResponse('OPEN')});
517
- });
518
-
519
- it('rejects when edit lock token mismatch', async () => {
520
- webex.request.returns(Promise.reject({
521
- body: {
522
- "errorCode":BREAKOUTS.ERROR_CODE.EDIT_LOCK_TOKEN_MISMATCH,
523
- "message":"Edit lock token mismatch"
524
- }
525
- }));
932
+ breakouts.editLock = {
933
+ token: 'token1',
934
+ };
935
+ const params = {
936
+ id: 'groupId',
937
+ sessions: [{name: 'Session 1'}],
938
+ };
939
+ breakouts._setManageGroups = sinon.stub();
940
+ const result = await breakouts.update(params);
941
+ assert.calledOnceWithExactly(webex.request, {
942
+ method: 'PUT',
943
+ uri: 'url',
944
+ body: {
945
+ editlock: {token: 'token1', refresh: true},
946
+ groups: [params],
947
+ },
948
+ });
949
+ assert.calledOnceWithExactly(breakouts._setManageGroups, {
950
+ body: mockedReturnBody,
951
+ });
952
+ });
953
+ it('makes the request as expected when unlockEdit is true', async () => {
954
+ breakouts.editLock = {
955
+ token: 'token1',
956
+ };
957
+ const params = {
958
+ id: 'groupId',
959
+ sessions: [{name: 'Session 1'}],
960
+ };
961
+ breakouts._clearEditLockInfo = sinon.stub();
962
+ const result = await breakouts.update(params, true);
963
+ assert.calledOnceWithExactly(webex.request, {
964
+ method: 'PUT',
965
+ uri: 'url',
966
+ body: {
967
+ editlock: {token: 'token1', refresh: false},
968
+ groups: [params],
969
+ },
970
+ });
971
+ assert.calledOnceWithExactly(breakouts._clearEditLockInfo);
972
+ });
973
+ it('throw error if missing id in params', async () => {
974
+ const params = {
975
+ sessions: [{name: 'Session 1'}],
976
+ };
977
+ await breakouts.update(params).catch((error) => {
978
+ assert.equal(error.toString(), 'Error: Missing breakout group id');
979
+ });
980
+ });
981
+ it('rejects when edit lock token mismatch', async () => {
982
+ webex.request.returns(
983
+ Promise.reject({
984
+ body: {
985
+ errorCode: BREAKOUTS.ERROR_CODE.EDIT_LOCK_TOKEN_MISMATCH,
986
+ message: 'Edit lock token mismatch',
987
+ },
988
+ })
989
+ );
990
+ LoggerProxy.logger.info = sinon.stub();
991
+
992
+ const params = {
993
+ id: 'groupId',
994
+ sessions: [{name: 'Session 1'}],
995
+ };
526
996
 
527
997
  await assert.isRejected(
528
- breakouts.start(),
998
+ breakouts.update(params),
529
999
  BreakoutEditLockedError,
530
1000
  'Edit lock token mismatch'
531
1001
  );
1002
+ assert.calledOnceWithExactly(
1003
+ LoggerProxy.logger.info,
1004
+ 'Breakouts#update --> Edit lock token mismatch'
1005
+ );
1006
+ });
1007
+
1008
+ it('rejects when edit not authorized', async () => {
1009
+ webex.request.returns(
1010
+ Promise.reject({
1011
+ body: {
1012
+ errorCode: BREAKOUTS.ERROR_CODE.EDIT_NOT_AUTHORIZED,
1013
+ },
1014
+ })
1015
+ );
1016
+ LoggerProxy.logger.info = sinon.stub();
1017
+
1018
+ const params = {
1019
+ id: 'groupId',
1020
+ sessions: [{name: 'Session 1'}],
1021
+ };
1022
+
1023
+ await assert.isRejected(
1024
+ breakouts.update(params),
1025
+ BreakoutEditLockedError,
1026
+ 'Not authorized to interact with edit lock'
1027
+ );
532
1028
 
1029
+ assert.calledOnceWithExactly(
1030
+ LoggerProxy.logger.info,
1031
+ 'Breakouts#update --> Not authorized to interact with edit lock'
1032
+ );
1033
+ });
1034
+
1035
+ it('rejects when other unknow error', async () => {
1036
+ const mockError = new Error('something wrong');
1037
+ webex.request.returns(Promise.reject(mockError));
1038
+ LoggerProxy.logger.info = sinon.stub();
1039
+
1040
+ const params = {
1041
+ id: 'groupId',
1042
+ sessions: [{name: 'Session 1'}],
1043
+ };
1044
+
1045
+ await assert.isRejected(breakouts.update(params), mockError, 'something wrong');
1046
+
1047
+ assert.calledOnceWithExactly(
1048
+ LoggerProxy.logger.info,
1049
+ 'Breakouts#update --> something wrong'
1050
+ );
1051
+ });
1052
+ });
1053
+
1054
+ describe('#start', () => {
1055
+ it('should start breakout sessions', async () => {
1056
+ const mockedReturnBody = getBOResponse('OPEN');
1057
+ webex.request.returns(
1058
+ Promise.resolve({
1059
+ body: mockedReturnBody,
1060
+ })
1061
+ );
1062
+
1063
+ breakouts.set('url', 'url');
1064
+ await breakouts.getBreakout();
1065
+
1066
+ const result = await breakouts.start();
1067
+ breakouts._setManageGroups = sinon.stub();
1068
+ await breakouts.start({id: 'id', someOtherParam: 'someOtherParam'});
1069
+
1070
+ const arg = webex.request.getCall(1).args[0];
1071
+ const argObj1 = arg.body.groups[0];
1072
+ const argObj2 = webex.request.getCall(2).args[0].body.groups[0];
1073
+
1074
+ assert.equal(arg.uri, 'url');
1075
+ assert.equal(arg.method, 'PUT');
1076
+ assert.deepEqual(argObj1, {
1077
+ id: 'groupId',
1078
+ action: 'START',
1079
+ allowBackToMain: false,
1080
+ allowToJoinLater: false,
1081
+ });
1082
+ assert.deepEqual(argObj2, {
1083
+ id: 'id',
1084
+ action: 'START',
1085
+ allowBackToMain: false,
1086
+ allowToJoinLater: false,
1087
+ someOtherParam: 'someOtherParam',
1088
+ });
1089
+ assert.deepEqual(result, {body: mockedReturnBody});
1090
+ assert.calledWithExactly(breakouts._setManageGroups, {body: mockedReturnBody})
1091
+ });
1092
+
1093
+ it('rejects when edit lock token mismatch', async () => {
1094
+ webex.request.returns(
1095
+ Promise.reject({
1096
+ body: {
1097
+ errorCode: BREAKOUTS.ERROR_CODE.EDIT_LOCK_TOKEN_MISMATCH,
1098
+ message: 'Edit lock token mismatch',
1099
+ },
1100
+ })
1101
+ );
1102
+
1103
+ await assert.isRejected(
1104
+ breakouts.start(),
1105
+ BreakoutEditLockedError,
1106
+ 'Edit lock token mismatch'
1107
+ );
533
1108
  });
534
1109
  });
535
1110
 
@@ -546,6 +1121,8 @@ describe('plugin-meetings', () => {
546
1121
  await breakouts.getBreakout();
547
1122
 
548
1123
  const result = await breakouts.end();
1124
+
1125
+ breakouts._setManageGroups = sinon.stub();
549
1126
  await breakouts.end({id: 'id', someOtherParam: 'someOtherParam'});
550
1127
  const arg = webex.request.getCall(1).args[0];
551
1128
  const argObj1 = arg.body.groups[0];
@@ -553,25 +1130,32 @@ describe('plugin-meetings', () => {
553
1130
 
554
1131
  assert.equal(arg.uri, 'url');
555
1132
  assert.equal(arg.method, 'PUT');
556
- assert.deepEqual(argObj1, {id:'groupId', action: 'CLOSE', delayCloseTime: 60});
557
- assert.deepEqual(argObj2, {id:'id', action: 'CLOSE', delayCloseTime: 60, someOtherParam: 'someOtherParam'});
1133
+ assert.deepEqual(argObj1, {id: 'groupId', action: 'CLOSE', delayCloseTime: 60});
1134
+ assert.deepEqual(argObj2, {
1135
+ id: 'id',
1136
+ action: 'CLOSE',
1137
+ delayCloseTime: 60,
1138
+ someOtherParam: 'someOtherParam',
1139
+ });
558
1140
  assert.deepEqual(result, {body: getBOResponse('CLOSING')});
1141
+ assert.calledOnceWithExactly(breakouts._setManageGroups, {body: getBOResponse('CLOSING')});
559
1142
  });
560
1143
 
561
1144
  it('rejects when edit lock token mismatch', async () => {
562
- webex.request.returns(Promise.reject({
563
- body: {
564
- "errorCode":BREAKOUTS.ERROR_CODE.EDIT_LOCK_TOKEN_MISMATCH,
565
- "message":"Edit lock token mismatch"
566
- }
567
- }));
1145
+ webex.request.returns(
1146
+ Promise.reject({
1147
+ body: {
1148
+ errorCode: BREAKOUTS.ERROR_CODE.EDIT_LOCK_TOKEN_MISMATCH,
1149
+ message: 'Edit lock token mismatch',
1150
+ },
1151
+ })
1152
+ );
568
1153
 
569
1154
  await assert.isRejected(
570
1155
  breakouts.end(),
571
1156
  BreakoutEditLockedError,
572
1157
  'Edit lock token mismatch'
573
1158
  );
574
-
575
1159
  });
576
1160
  });
577
1161
 
@@ -585,6 +1169,8 @@ describe('plugin-meetings', () => {
585
1169
 
586
1170
  breakouts.set('url', 'url');
587
1171
  const result = await breakouts.getBreakout();
1172
+
1173
+ breakouts._setManageGroups = sinon.stub();
588
1174
  await breakouts.getBreakout(true);
589
1175
  const arg1 = webex.request.getCall(0).args[0];
590
1176
  const arg2 = webex.request.getCall(1).args[0];
@@ -593,20 +1179,71 @@ describe('plugin-meetings', () => {
593
1179
  assert.equal(arg2.uri, 'url?editlock=true');
594
1180
  assert.equal(arg1.method, 'GET');
595
1181
  assert.deepEqual(result, {body: getBOResponse('PENDING')});
596
- assert.deepEqual(breakouts.groups, result.body.groups);
1182
+ assert.deepEqual(breakouts.manageGroups, result.body.groups);
597
1183
  assert.equal(breakouts.breakoutGroupId, 'groupId');
1184
+ assert.calledOnceWithExactly(breakouts._setManageGroups, {body: getBOResponse('PENDING')});
1185
+ });
1186
+
1187
+ it('breakoutGroupId should be empty if it is CLOSED group', async () => {
1188
+ webex.request.returns(
1189
+ Promise.resolve({
1190
+ body: getBOResponse('CLOSED'),
1191
+ })
1192
+ );
1193
+
1194
+ breakouts.set('url', 'url');
1195
+ await breakouts.getBreakout();
1196
+
1197
+ assert.equal(breakouts.breakoutGroupId, '');
1198
+ });
1199
+
1200
+ it('should call keep alive when response with edit lock info', async () => {
1201
+ webex.request.returns(
1202
+ Promise.resolve({
1203
+ body: getBOResponseWithEditLockInfo('PENDING'),
1204
+ })
1205
+ );
1206
+
1207
+ breakouts.set('url', 'url');
1208
+ breakouts.keepEditLockAlive = sinon.stub().resolves();
1209
+ const result = await breakouts.getBreakout();
1210
+ await breakouts.getBreakout(true);
1211
+
1212
+ assert.calledOnceWithExactly(breakouts.keepEditLockAlive);
1213
+ });
1214
+ it('not call keep alive when response with no edit lock token', async () => {
1215
+ webex.request.returns(
1216
+ Promise.resolve({
1217
+ body: getBOResponseWithEditLockInfo('PENDING', true),
1218
+ })
1219
+ );
1220
+
1221
+ breakouts.set('url', 'url');
1222
+ breakouts.keepEditLockAlive = sinon.stub().resolves();
1223
+ const result = await breakouts.getBreakout();
1224
+ await breakouts.getBreakout(true);
1225
+
1226
+ assert.notCalled(breakouts.keepEditLockAlive);
598
1227
  });
599
1228
  });
600
1229
 
601
1230
  describe('doToggleBreakout', () => {
602
1231
  it('makes the request as expected', async () => {
1232
+ breakouts.set('editLock', {
1233
+ ttl: 30,
1234
+ token: 'editToken',
1235
+ state: 'UNLOCKED',
1236
+ });
603
1237
  const result = await breakouts.doToggleBreakout(true);
604
1238
  assert.calledOnceWithExactly(webex.request, {
605
1239
  method: 'PUT',
606
1240
  uri: 'url',
607
1241
  body: {
608
- enableBreakoutSession: true
609
- }
1242
+ editlock: {
1243
+ token: 'editToken',
1244
+ },
1245
+ enableBreakoutSession: true,
1246
+ },
610
1247
  });
611
1248
 
612
1249
  assert.equal(result, 'REQUEST_RETURN_VALUE');
@@ -615,16 +1252,21 @@ describe('plugin-meetings', () => {
615
1252
 
616
1253
  describe('delete', () => {
617
1254
  it('makes the request as expected', async () => {
618
- webex.request.returns(Promise.resolve({
619
- body: {
620
- groups: [{
621
- id : "455556a4-37cd-4baa-89bc-8730581a1cc0",
622
- status : "CLOSE",
623
- type : "BREAKOUT",
624
- }]
625
- }
626
- }));
1255
+ webex.request.returns(
1256
+ Promise.resolve({
1257
+ body: {
1258
+ groups: [
1259
+ {
1260
+ id: '455556a4-37cd-4baa-89bc-8730581a1cc0',
1261
+ status: 'CLOSE',
1262
+ type: 'BREAKOUT',
1263
+ },
1264
+ ],
1265
+ },
1266
+ })
1267
+ );
627
1268
 
1269
+ breakouts._setManageGroups = sinon.stub();
628
1270
  const result = await breakouts.clearSessions();
629
1271
  assert.calledOnceWithExactly(webex.request, {
630
1272
  method: 'PUT',
@@ -635,73 +1277,517 @@ describe('plugin-meetings', () => {
635
1277
  action: BREAKOUTS.ACTION.DELETE,
636
1278
  },
637
1279
  ],
638
- }
1280
+ },
639
1281
  });
640
1282
 
641
- assert.equal(breakouts.groups[0].status, "CLOSE")
1283
+ assert.calledOnceWithExactly(breakouts._setManageGroups, {
1284
+ body: {
1285
+ groups: [
1286
+ {
1287
+ id: '455556a4-37cd-4baa-89bc-8730581a1cc0',
1288
+ status: 'CLOSE',
1289
+ type: 'BREAKOUT',
1290
+ },
1291
+ ],
1292
+ },
1293
+ });
642
1294
  });
643
1295
 
644
1296
  it('rejects when edit lock token mismatch', async () => {
645
- webex.request.returns(Promise.reject({
646
- body: {
647
- "errorCode":BREAKOUTS.ERROR_CODE.EDIT_LOCK_TOKEN_MISMATCH,
648
- "message":"Edit lock token mismatch"
649
- }
650
- }));
1297
+ webex.request.returns(
1298
+ Promise.reject({
1299
+ body: {
1300
+ errorCode: BREAKOUTS.ERROR_CODE.EDIT_LOCK_TOKEN_MISMATCH,
1301
+ message: 'Edit lock token mismatch',
1302
+ },
1303
+ })
1304
+ );
651
1305
 
652
1306
  await assert.isRejected(
653
1307
  breakouts.clearSessions(),
654
1308
  BreakoutEditLockedError,
655
1309
  'Edit lock token mismatch'
656
1310
  );
657
-
658
1311
  });
659
1312
  });
660
1313
 
661
1314
  describe('create', () => {
662
1315
  it('response not include groups info', async () => {
663
- const sessions = [{'name':'session1', "anyoneCanJoin" : true}];
664
- const result = await breakouts.create(sessions);
1316
+ const sessions = [{name: 'session1', anyoneCanJoin: true}];
1317
+ const result = await breakouts.create({sessions});
665
1318
 
666
1319
  assert.equal(result, 'REQUEST_RETURN_VALUE');
667
-
668
1320
  });
669
1321
 
670
1322
  it('response include groups info', async () => {
671
- const sessions = [{'name':'session1', "anyoneCanJoin" : true}];
672
-
673
- webex.request.returns(Promise.resolve({
674
- body: {
675
- groups: [{
676
- id : "455556a4-37cd-4baa-89bc-8730581a1cc0",
677
- status : "PENDING",
678
- type : "BREAKOUT",
679
- }]
680
- }
681
- }));
1323
+ const sessions = [{name: 'session1', anyoneCanJoin: true}];
682
1324
 
683
- const result = await breakouts.create(sessions);
1325
+ webex.request.returns(
1326
+ Promise.resolve({
1327
+ body: {
1328
+ groups: [
1329
+ {
1330
+ id: '455556a4-37cd-4baa-89bc-8730581a1cc0',
1331
+ status: 'PENDING',
1332
+ type: 'BREAKOUT',
1333
+ },
1334
+ ],
1335
+ },
1336
+ })
1337
+ );
684
1338
 
685
- assert.equal(breakouts.groups[0].id, "455556a4-37cd-4baa-89bc-8730581a1cc0")
1339
+ const result = await breakouts.create({sessions});
686
1340
 
1341
+ assert.equal(breakouts.manageGroups[0].id, '455556a4-37cd-4baa-89bc-8730581a1cc0');
687
1342
  });
688
1343
 
689
1344
  it('rejects when edit lock token mismatch', async () => {
690
- const sessions = [{'name':'session1', "anyoneCanJoin" : true}];
1345
+ const sessions = [{name: 'session1', anyoneCanJoin: true}];
691
1346
 
692
- webex.request.returns(Promise.reject({
693
- body: {
694
- "errorCode":BREAKOUTS.ERROR_CODE.EDIT_LOCK_TOKEN_MISMATCH,
695
- "message":"Edit lock token mismatch"
696
- }
697
- }));
1347
+ webex.request.returns(
1348
+ Promise.reject({
1349
+ body: {
1350
+ errorCode: BREAKOUTS.ERROR_CODE.EDIT_LOCK_TOKEN_MISMATCH,
1351
+ message: 'Edit lock token mismatch',
1352
+ },
1353
+ })
1354
+ );
698
1355
 
699
1356
  await assert.isRejected(
700
- breakouts.create(sessions),
1357
+ breakouts.create({sessions}),
701
1358
  BreakoutEditLockedError,
702
1359
  'Edit lock token mismatch'
703
1360
  );
704
1361
  });
705
1362
  });
1363
+
1364
+ describe('enableAndLockBreakout', () => {
1365
+ it('enableBreakoutSession is true', async () => {
1366
+ breakouts.enableBreakoutSession = true;
1367
+
1368
+ breakouts.lockBreakout = sinon.stub().resolves();
1369
+
1370
+ breakouts.enableAndLockBreakout();
1371
+
1372
+ assert.calledOnceWithExactly(breakouts.lockBreakout);
1373
+ });
1374
+
1375
+ it('enableBreakoutSession is false', async () => {
1376
+ breakouts.enableBreakoutSession = false;
1377
+
1378
+ breakouts.enableBreakouts = sinon.stub().resolves();
1379
+
1380
+ breakouts.enableAndLockBreakout();
1381
+
1382
+ assert.calledOnceWithExactly(breakouts.enableBreakouts);
1383
+ });
1384
+ });
1385
+
1386
+ describe('hasBreakoutLocked', () => {
1387
+ it('has breakout locked is true', async () => {
1388
+ breakouts.editLock = {
1389
+ ttl: 30,
1390
+ token: 'token',
1391
+ state: 'LOCKED',
1392
+ };
1393
+
1394
+ assert.equal(breakouts.hasBreakoutLocked(), true);
1395
+ });
1396
+
1397
+ it('breakout locked by others', async () => {
1398
+ breakouts.editLock = {
1399
+ ttl: 30,
1400
+ token: '',
1401
+ state: 'LOCKED',
1402
+ };
1403
+
1404
+ assert.equal(breakouts.hasBreakoutLocked(), false);
1405
+ });
1406
+
1407
+ it('breakout not locked', async () => {
1408
+ breakouts.editLock = {
1409
+ ttl: 30,
1410
+ token: '',
1411
+ state: 'UNLOCKED',
1412
+ };
1413
+
1414
+ assert.equal(breakouts.hasBreakoutLocked(), false);
1415
+ });
1416
+ });
1417
+
1418
+ describe('lockBreakout', () => {
1419
+ it('lock breakout is true', async () => {
1420
+ breakouts.editLock = {
1421
+ ttl: 30,
1422
+ token: 'token',
1423
+ state: 'UNLOCKED',
1424
+ };
1425
+
1426
+ breakouts.keepEditLockAlive = sinon.stub().resolves();
1427
+
1428
+ breakouts.lockBreakout();
1429
+
1430
+ assert.calledOnceWithExactly(breakouts.keepEditLockAlive);
1431
+ });
1432
+
1433
+ it('lock breakout throw error', async () => {
1434
+ breakouts.editLock = {
1435
+ ttl: 30,
1436
+ token: '2ad57140-01b5-4bd0-a5a7-4dccdc06904c',
1437
+ state: 'LOCKED',
1438
+ };
1439
+
1440
+ await expect(breakouts.lockBreakout()).to.be.rejectedWith('Breakout already locked');
1441
+ });
1442
+
1443
+ it('lock breakout without editLock', async () => {
1444
+ breakouts.getBreakout = sinon.stub().resolves();
1445
+
1446
+ breakouts.lockBreakout();
1447
+
1448
+ assert.calledOnceWithExactly(breakouts.getBreakout, true);
1449
+ });
1450
+ });
1451
+
1452
+ describe('unLockEditBreakout', () => {
1453
+ it('unLock edit breakout request as expected', async () => {
1454
+ breakouts.set('editLock', {
1455
+ ttl: 30,
1456
+ token: '2ad57140-01b5-4bd0-a5a7-4dccdc06904c',
1457
+ state: 'LOCKED',
1458
+ });
1459
+
1460
+ breakouts.unLockEditBreakout();
1461
+ assert.calledOnceWithExactly(webex.request, {
1462
+ method: 'DELETE',
1463
+ uri: 'url/editlock/2ad57140-01b5-4bd0-a5a7-4dccdc06904c',
1464
+ });
1465
+ });
1466
+
1467
+ it('do not call unLock if edit lock info not exist ', async () => {
1468
+ breakouts.unLockEditBreakout();
1469
+ assert.notCalled(webex.request);
1470
+ });
1471
+ });
1472
+
1473
+ describe('keepEditLockAlive', () => {
1474
+ it('keep edit lock', () => {
1475
+ const clock = sinon.useFakeTimers();
1476
+
1477
+ breakouts.set('editLock', {
1478
+ ttl: 30,
1479
+ token: 'token',
1480
+ state: 'UNLOCKED',
1481
+ });
1482
+
1483
+ breakouts.keepEditLockAlive();
1484
+ clock.tick(15001);
1485
+
1486
+ assert.calledOnceWithExactly(webex.request, {
1487
+ method: 'PUT',
1488
+ uri: 'url/editlock/token',
1489
+ });
1490
+
1491
+ clock.restore();
1492
+ });
1493
+
1494
+ it('keep edit lock, ttl < 30, also using 30', () => {
1495
+ const clock = sinon.useFakeTimers();
1496
+
1497
+ breakouts.set('editLock', {
1498
+ ttl: 20,
1499
+ token: 'token',
1500
+ state: 'UNLOCKED',
1501
+ });
1502
+
1503
+ breakouts.keepEditLockAlive();
1504
+ clock.tick(15001);
1505
+
1506
+ assert.calledOnceWithExactly(webex.request, {
1507
+ method: 'PUT',
1508
+ uri: 'url/editlock/token',
1509
+ });
1510
+
1511
+ clock.restore();
1512
+ });
1513
+
1514
+ it('keep edit lock, ttl > 30, using the ttl', () => {
1515
+ const clock = sinon.useFakeTimers();
1516
+
1517
+ breakouts.set('editLock', {
1518
+ ttl: 50,
1519
+ token: 'token',
1520
+ state: 'UNLOCKED',
1521
+ });
1522
+
1523
+ breakouts.keepEditLockAlive();
1524
+ clock.tick(24099);
1525
+
1526
+ assert.notCalled(webex.request);
1527
+
1528
+ clock.restore();
1529
+ });
1530
+
1531
+ it('keep edit lock, throw error, clearInterval', async () => {
1532
+ breakouts._clearEditLockInfo = sinon.stub();
1533
+
1534
+ const error = new Error('something went wrong');
1535
+ webex.request.rejects(error);
1536
+
1537
+ const clock = sinon.useFakeTimers();
1538
+
1539
+ breakouts.set('editLock', {
1540
+ ttl: 30,
1541
+ token: 'token',
1542
+ state: 'UNLOCKED',
1543
+ });
1544
+
1545
+ breakouts.keepEditLockAlive();
1546
+ clock.tick(15001);
1547
+
1548
+ await testUtils.flushPromises();
1549
+
1550
+ assert.calledOnceWithExactly(breakouts._clearEditLockInfo);
1551
+
1552
+ clock.restore();
1553
+ });
1554
+
1555
+ it('keep edit lock, do not call until reached ttl', () => {
1556
+ const clock = sinon.useFakeTimers();
1557
+
1558
+ breakouts.set('editLock', {
1559
+ ttl: 30,
1560
+ token: 'token',
1561
+ state: 'UNLOCKED',
1562
+ });
1563
+
1564
+ breakouts.keepEditLockAlive();
1565
+ clock.tick(14999);
1566
+
1567
+ assert.notCalled(webex.request);
1568
+
1569
+ clock.tick(1);
1570
+ assert.calledOnceWithExactly(webex.request, {
1571
+ method: 'PUT',
1572
+ uri: 'url/editlock/token',
1573
+ });
1574
+
1575
+ clock.restore();
1576
+ });
1577
+
1578
+ it('clear interval first if previous one is in work', () => {
1579
+ breakouts.set('editLock', {
1580
+ ttl: 30,
1581
+ token: 'token',
1582
+ });
1583
+ const clock = sinon.useFakeTimers();
1584
+ window.clearInterval = sinon.stub();
1585
+ breakouts.keepEditLockAlive();
1586
+ const firstIntervalID = breakouts.intervalID;
1587
+ breakouts.keepEditLockAlive();
1588
+
1589
+ assert.calledWithExactly(window.clearInterval, firstIntervalID);
1590
+ clock.restore();
1591
+ });
1592
+ });
1593
+
1594
+ describe('#assign', () => {
1595
+ it('assign members and emails to a breakout session', async () => {
1596
+ breakouts.assign = sinon.stub().returns(Promise.resolve('ASSIGN_RETURN_VALUE'));
1597
+ const params = [
1598
+ {id: 'sessionId', memberIds: ['111'], emails: ['111@cisco.com'], anyone: true},
1599
+ ];
1600
+ const result = await breakouts.assign(params);
1601
+ assert.calledOnceWithExactly(breakouts.assign, params);
1602
+ assert.equal(result, 'ASSIGN_RETURN_VALUE');
1603
+ });
1604
+ it('assign only members to a breakout session', async () => {
1605
+ breakouts.assign = sinon.stub().returns(Promise.resolve('ASSIGN_RETURN_VALUE'));
1606
+ const params = [{id: 'sessionId', memberIds: ['111']}];
1607
+ const result = await breakouts.assign(params);
1608
+ assert.calledOnceWithExactly(breakouts.assign, params);
1609
+ assert.equal(result, 'ASSIGN_RETURN_VALUE');
1610
+ });
1611
+ it('assign only emails to a breakout session', async () => {
1612
+ breakouts.assign = sinon.stub().returns(Promise.resolve('ASSIGN_RETURN_VALUE'));
1613
+ const params = [{id: 'sessionId', emails: ['111@cisco.com']}];
1614
+ const result = await breakouts.assign(params);
1615
+ assert.calledOnceWithExactly(breakouts.assign, params);
1616
+ assert.equal(result, 'ASSIGN_RETURN_VALUE');
1617
+ });
1618
+
1619
+ it('called with editlock', async () => {
1620
+ breakouts.request = sinon.stub().returns(Promise.resolve('ASSIGN_RETURN_VALUE'));
1621
+ breakouts.editLock = {
1622
+ token: 'token1',
1623
+ };
1624
+ const params = [{id: 'sessionId', emails: ['111@cisco.com'], memberIds: []}];
1625
+ await breakouts.assign(params);
1626
+ const args = breakouts.request.getCall(0).args[0];
1627
+ expect(args).to.be.an('object', {
1628
+ method: 'PUT',
1629
+ uri: 'url',
1630
+ body: {
1631
+ editlock: {token: 'token1', refresh: true},
1632
+ groups: {
1633
+ id: 'sessionId',
1634
+ sessions: [
1635
+ {
1636
+ id: 'sessionId',
1637
+ assigned: [],
1638
+ assignedEmails: ['111@cisco.com'],
1639
+ anyoneCanJoin: false,
1640
+ },
1641
+ ],
1642
+ },
1643
+ },
1644
+ });
1645
+ });
1646
+ });
1647
+
1648
+ describe('#queryPreAssignments', () => {
1649
+ it('makes the expected query', async () => {
1650
+ const mockPreAssignments = [
1651
+ {
1652
+ sessions: [
1653
+ {
1654
+ name: 'Breakout session 1',
1655
+ assignedEmails: ['aa@aa.com', 'bb@bb.com', 'cc@cc.com'],
1656
+ anyoneCanJoin: false,
1657
+ },
1658
+ {
1659
+ name: 'Breakout session 2',
1660
+ anyoneCanJoin: false,
1661
+ },
1662
+ {
1663
+ name: 'Breakout session 3',
1664
+ assignedEmails: ['cc@cc.com'],
1665
+ anyoneCanJoin: false,
1666
+ },
1667
+ ],
1668
+ unassignedInvitees: {
1669
+ emails: ['dd@dd.com'],
1670
+ },
1671
+ type: 'BREAKOUT',
1672
+ },
1673
+ ];
1674
+ webex.request.returns(
1675
+ Promise.resolve({
1676
+ body: {
1677
+ groups: mockPreAssignments,
1678
+ },
1679
+ })
1680
+ );
1681
+ breakouts.set('locusUrl', 'test');
1682
+
1683
+ await breakouts.queryPreAssignments();
1684
+ assert.calledOnceWithExactly(webex.request, {
1685
+ uri: 'url/preassignments',
1686
+ qs: {
1687
+ locusUrl: 'dGVzdA==',
1688
+ }
1689
+ });
1690
+
1691
+ assert.deepEqual(breakouts.preAssignments, mockPreAssignments);
1692
+ });
1693
+
1694
+ it('rejects when no pre-assignments created for this meeting', async () => {
1695
+ const response = {
1696
+ statusCode: 404,
1697
+ body: {
1698
+ errorCode: 201404004,
1699
+ message: 'No pre-assignments created for this meeting',
1700
+ },
1701
+ };
1702
+ webex.request.rejects(response);
1703
+ LoggerProxy.logger.error = sinon.stub();
1704
+ const result = await breakouts.queryPreAssignments({enableBreakoutSession: true, hasBreakoutPreAssignments: true});
1705
+ await testUtils.flushPromises();
1706
+ assert.calledOnceWithExactly(
1707
+ LoggerProxy.logger.error,
1708
+ 'Meeting:breakouts#queryPreAssignments failed',
1709
+ response
1710
+ );
1711
+ });
1712
+
1713
+ it('fail when no correct params', () => {
1714
+
1715
+ assert.deepEqual(breakouts.queryPreAssignments(undefined), undefined);
1716
+
1717
+ assert.deepEqual(breakouts.queryPreAssignments({}), undefined);
1718
+
1719
+ assert.deepEqual(breakouts.queryPreAssignments({ enableBreakoutSession: true, hasBreakoutPreAssignments: false }), undefined);
1720
+
1721
+ assert.deepEqual(breakouts.queryPreAssignments({ enableBreakoutSession: false, hasBreakoutPreAssignments: true }), undefined);
1722
+
1723
+ assert.deepEqual(breakouts.queryPreAssignments({ enableBreakoutSession: false, hasBreakoutPreAssignments: false }), undefined);
1724
+
1725
+ });
1726
+
1727
+ });
1728
+
1729
+ describe('#dynamicAssign', () => {
1730
+ it('should make a PUT request with correct body and return the result', async () => {
1731
+ breakouts.dynamicAssign = sinon.stub().returns(Promise.resolve('REQUEST_RETURN_VALUE'));
1732
+
1733
+ const expectedBody = {
1734
+ groups: [
1735
+ {
1736
+ id: 'breakoutGroup1',
1737
+ sessions: [
1738
+ {
1739
+ id: 'session1',
1740
+ participants: ['participant1', 'participant2'],
1741
+ targetState: 'JOINED',
1742
+ },
1743
+ ],
1744
+ },
1745
+ ],
1746
+ editlock: {
1747
+ token: 'abcdefg',
1748
+ },
1749
+ };
1750
+
1751
+ const result = await breakouts.dynamicAssign(expectedBody);
1752
+
1753
+ assert.calledOnceWithExactly(breakouts.dynamicAssign, expectedBody);
1754
+ assert.equal(result, 'REQUEST_RETURN_VALUE');
1755
+ });
1756
+ });
1757
+
1758
+ describe('#triggerReturnToMainEvent', () => {
1759
+ const checkTrigger = ({breakout, shouldTrigger}) => {
1760
+ breakouts.trigger = sinon.stub();
1761
+ breakouts.triggerReturnToMainEvent(breakout);
1762
+ if (shouldTrigger) {
1763
+ assert.calledOnceWithExactly(breakouts.trigger, BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN);
1764
+ } else {
1765
+ assert.notCalled(breakouts.trigger);
1766
+ }
1767
+ }
1768
+ it('should trigger ASK_RETURN_TO_MAIN event correctly', () => {
1769
+ const breakout = {
1770
+ isMain: true,
1771
+ requested: true
1772
+ };
1773
+ checkTrigger({breakout, shouldTrigger: true})
1774
+ });
1775
+
1776
+ it('should not trigger ASK_RETURN_TO_MAIN event when sessionType is not MAIN', () => {
1777
+ const breakout = {
1778
+ isMain: false,
1779
+ requested: true
1780
+ };
1781
+ checkTrigger({breakout, shouldTrigger: false});
1782
+ });
1783
+
1784
+ it('should not trigger ASK_RETURN_TO_MAIN event when session is not requested', () => {
1785
+ const breakout = {
1786
+ isMain: true,
1787
+ requested: false
1788
+ };
1789
+ checkTrigger({breakout, shouldTrigger: false})
1790
+ });
1791
+ });
706
1792
  });
707
1793
  });