@webex/plugin-meetings 3.0.0-beta.39 → 3.0.0-beta.391

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 (393) 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 +671 -81
  13. package/dist/breakouts/index.js.map +1 -1
  14. package/dist/breakouts/utils.js +45 -1
  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 +5 -10
  29. package/dist/config.js.map +1 -1
  30. package/dist/constants.js +242 -33
  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 +110 -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 +4075 -2827
  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 +224 -136
  77. package/dist/meeting/muteState.js.map +1 -1
  78. package/dist/meeting/request.js +177 -152
  79. package/dist/meeting/request.js.map +1 -1
  80. package/dist/meeting/util.js +672 -417
  81. package/dist/meeting/util.js.map +1 -1
  82. package/dist/meeting-info/index.js +73 -7
  83. package/dist/meeting-info/index.js.map +1 -1
  84. package/dist/meeting-info/meeting-info-v2.js +192 -51
  85. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  86. package/dist/meeting-info/util.js +1 -1
  87. package/dist/meeting-info/util.js.map +1 -1
  88. package/dist/meeting-info/utilv2.js +36 -36
  89. package/dist/meeting-info/utilv2.js.map +1 -1
  90. package/dist/meetings/collection.js +39 -0
  91. package/dist/meetings/collection.js.map +1 -1
  92. package/dist/meetings/index.js +484 -119
  93. package/dist/meetings/index.js.map +1 -1
  94. package/dist/meetings/meetings.types.js +7 -0
  95. package/dist/meetings/meetings.types.js.map +1 -0
  96. package/dist/meetings/request.js +2 -0
  97. package/dist/meetings/request.js.map +1 -1
  98. package/dist/meetings/util.js +73 -7
  99. package/dist/meetings/util.js.map +1 -1
  100. package/dist/member/index.js +58 -0
  101. package/dist/member/index.js.map +1 -1
  102. package/dist/member/types.js +25 -0
  103. package/dist/member/types.js.map +1 -0
  104. package/dist/member/util.js +132 -25
  105. package/dist/member/util.js.map +1 -1
  106. package/dist/members/collection.js +10 -0
  107. package/dist/members/collection.js.map +1 -1
  108. package/dist/members/index.js +102 -6
  109. package/dist/members/index.js.map +1 -1
  110. package/dist/members/request.js +106 -38
  111. package/dist/members/request.js.map +1 -1
  112. package/dist/members/types.js +15 -0
  113. package/dist/members/types.js.map +1 -0
  114. package/dist/members/util.js +326 -232
  115. package/dist/members/util.js.map +1 -1
  116. package/dist/metrics/constants.js +18 -1
  117. package/dist/metrics/constants.js.map +1 -1
  118. package/dist/metrics/index.js +1 -446
  119. package/dist/metrics/index.js.map +1 -1
  120. package/dist/multistream/mediaRequestManager.js +223 -32
  121. package/dist/multistream/mediaRequestManager.js.map +1 -1
  122. package/dist/multistream/receiveSlot.js +10 -0
  123. package/dist/multistream/receiveSlot.js.map +1 -1
  124. package/dist/multistream/receiveSlotManager.js +39 -36
  125. package/dist/multistream/receiveSlotManager.js.map +1 -1
  126. package/dist/multistream/remoteMedia.js +3 -1
  127. package/dist/multistream/remoteMedia.js.map +1 -1
  128. package/dist/multistream/remoteMediaGroup.js +76 -5
  129. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  130. package/dist/multistream/remoteMediaManager.js +366 -104
  131. package/dist/multistream/remoteMediaManager.js.map +1 -1
  132. package/dist/multistream/sendSlotManager.js +255 -0
  133. package/dist/multistream/sendSlotManager.js.map +1 -0
  134. package/dist/reachability/clusterReachability.js +356 -0
  135. package/dist/reachability/clusterReachability.js.map +1 -0
  136. package/dist/reachability/index.js +263 -390
  137. package/dist/reachability/index.js.map +1 -1
  138. package/dist/reachability/request.js +6 -4
  139. package/dist/reachability/request.js.map +1 -1
  140. package/dist/reachability/util.js +29 -0
  141. package/dist/reachability/util.js.map +1 -0
  142. package/dist/reconnection-manager/index.js +266 -202
  143. package/dist/reconnection-manager/index.js.map +1 -1
  144. package/dist/recording-controller/index.js +21 -2
  145. package/dist/recording-controller/index.js.map +1 -1
  146. package/dist/recording-controller/util.js +9 -8
  147. package/dist/recording-controller/util.js.map +1 -1
  148. package/dist/roap/index.js +51 -28
  149. package/dist/roap/index.js.map +1 -1
  150. package/dist/roap/request.js +48 -64
  151. package/dist/roap/request.js.map +1 -1
  152. package/dist/roap/turnDiscovery.js +220 -70
  153. package/dist/roap/turnDiscovery.js.map +1 -1
  154. package/dist/rtcMetrics/constants.js +12 -0
  155. package/dist/rtcMetrics/constants.js.map +1 -0
  156. package/dist/rtcMetrics/index.js +179 -0
  157. package/dist/rtcMetrics/index.js.map +1 -0
  158. package/dist/statsAnalyzer/index.js +357 -295
  159. package/dist/statsAnalyzer/index.js.map +1 -1
  160. package/dist/statsAnalyzer/mqaUtil.js +296 -156
  161. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  162. package/dist/types/annotation/annotation.types.d.ts +42 -0
  163. package/dist/types/annotation/constants.d.ts +31 -0
  164. package/dist/types/annotation/index.d.ts +117 -0
  165. package/dist/types/breakouts/events.d.ts +8 -0
  166. package/dist/types/breakouts/utils.d.ts +14 -0
  167. package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
  168. package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
  169. package/dist/types/common/errors/webex-errors.d.ts +25 -1
  170. package/dist/types/common/logs/request.d.ts +2 -0
  171. package/dist/types/common/queue.d.ts +9 -7
  172. package/dist/types/config.d.ts +2 -7
  173. package/dist/types/constants.d.ts +203 -31
  174. package/dist/types/controls-options-manager/enums.d.ts +11 -1
  175. package/dist/types/controls-options-manager/index.d.ts +17 -1
  176. package/dist/types/controls-options-manager/types.d.ts +43 -0
  177. package/dist/types/controls-options-manager/util.d.ts +1 -7
  178. package/dist/types/index.d.ts +6 -5
  179. package/dist/types/interceptors/index.d.ts +2 -0
  180. package/dist/types/interceptors/locusRetry.d.ts +27 -0
  181. package/dist/types/interpretation/collection.d.ts +5 -0
  182. package/dist/types/interpretation/index.d.ts +5 -0
  183. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  184. package/dist/types/locus-info/index.d.ts +57 -4
  185. package/dist/types/locus-info/parser.d.ts +66 -6
  186. package/dist/types/media/index.d.ts +2 -0
  187. package/dist/types/media/properties.d.ts +34 -49
  188. package/dist/types/mediaQualityMetrics/config.d.ts +99 -223
  189. package/dist/types/meeting/in-meeting-actions.d.ts +86 -2
  190. package/dist/types/meeting/index.d.ts +567 -496
  191. package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
  192. package/dist/types/meeting/muteState.d.ts +93 -25
  193. package/dist/types/meeting/request.d.ts +64 -43
  194. package/dist/types/meeting/util.d.ts +117 -1
  195. package/dist/types/meeting-info/index.d.ts +13 -1
  196. package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
  197. package/dist/types/meetings/collection.d.ts +17 -0
  198. package/dist/types/meetings/index.d.ts +113 -21
  199. package/dist/types/meetings/meetings.types.d.ts +4 -0
  200. package/dist/types/member/index.d.ts +14 -0
  201. package/dist/types/member/types.d.ts +32 -0
  202. package/dist/types/members/collection.d.ts +5 -0
  203. package/dist/types/members/index.d.ts +35 -2
  204. package/dist/types/members/request.d.ts +73 -9
  205. package/dist/types/members/types.d.ts +25 -0
  206. package/dist/types/members/util.d.ts +214 -1
  207. package/dist/types/metrics/constants.d.ts +17 -0
  208. package/dist/types/metrics/index.d.ts +4 -111
  209. package/dist/types/multistream/mediaRequestManager.d.ts +72 -3
  210. package/dist/types/multistream/receiveSlot.d.ts +7 -3
  211. package/dist/types/multistream/receiveSlotManager.d.ts +14 -4
  212. package/dist/types/multistream/remoteMedia.d.ts +3 -31
  213. package/dist/types/multistream/remoteMediaGroup.d.ts +2 -9
  214. package/dist/types/multistream/remoteMediaManager.d.ts +62 -2
  215. package/dist/types/multistream/sendSlotManager.d.ts +70 -0
  216. package/dist/types/reachability/clusterReachability.d.ts +109 -0
  217. package/dist/types/reachability/index.d.ts +60 -95
  218. package/dist/types/reachability/request.d.ts +3 -1
  219. package/dist/types/reachability/util.d.ts +8 -0
  220. package/dist/types/reconnection-manager/index.d.ts +19 -0
  221. package/dist/types/recording-controller/index.d.ts +15 -1
  222. package/dist/types/recording-controller/util.d.ts +5 -4
  223. package/dist/types/roap/index.d.ts +2 -1
  224. package/dist/types/roap/request.d.ts +9 -8
  225. package/dist/types/roap/turnDiscovery.d.ts +39 -5
  226. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  227. package/dist/types/rtcMetrics/index.d.ts +61 -0
  228. package/dist/types/statsAnalyzer/index.d.ts +34 -12
  229. package/dist/types/statsAnalyzer/mqaUtil.d.ts +28 -4
  230. package/dist/types/webinar/collection.d.ts +16 -0
  231. package/dist/types/webinar/index.d.ts +5 -0
  232. package/dist/webinar/collection.js +44 -0
  233. package/dist/webinar/collection.js.map +1 -0
  234. package/dist/webinar/index.js +69 -0
  235. package/dist/webinar/index.js.map +1 -0
  236. package/package.json +22 -19
  237. package/src/annotation/annotation.types.ts +50 -0
  238. package/src/annotation/constants.ts +36 -0
  239. package/src/annotation/index.ts +328 -0
  240. package/src/breakouts/README.md +35 -11
  241. package/src/breakouts/breakout.ts +67 -9
  242. package/src/breakouts/events.ts +56 -0
  243. package/src/breakouts/index.ts +558 -59
  244. package/src/breakouts/utils.ts +42 -0
  245. package/src/common/errors/no-meeting-info.ts +24 -0
  246. package/src/common/errors/reclaim-host-role-errors.ts +134 -0
  247. package/src/common/errors/webex-errors.ts +44 -2
  248. package/src/common/logs/logger-proxy.ts +1 -1
  249. package/src/common/logs/request.ts +5 -1
  250. package/src/common/queue.ts +22 -8
  251. package/src/config.ts +4 -9
  252. package/src/constants.ts +229 -21
  253. package/src/controls-options-manager/enums.ts +12 -0
  254. package/src/controls-options-manager/index.ts +116 -21
  255. package/src/controls-options-manager/types.ts +59 -0
  256. package/src/controls-options-manager/util.ts +294 -14
  257. package/src/index.ts +44 -0
  258. package/src/interceptors/index.ts +3 -0
  259. package/src/interceptors/locusRetry.ts +67 -0
  260. package/src/interpretation/README.md +60 -0
  261. package/src/interpretation/collection.ts +19 -0
  262. package/src/interpretation/index.ts +349 -0
  263. package/src/interpretation/siLanguage.ts +18 -0
  264. package/src/locus-info/controlsUtils.ts +108 -0
  265. package/src/locus-info/index.ts +417 -59
  266. package/src/locus-info/infoUtils.ts +10 -2
  267. package/src/locus-info/mediaSharesUtils.ts +80 -0
  268. package/src/locus-info/parser.ts +258 -47
  269. package/src/locus-info/selfUtils.ts +81 -5
  270. package/src/media/index.ts +100 -108
  271. package/src/media/properties.ts +88 -117
  272. package/src/mediaQualityMetrics/config.ts +103 -238
  273. package/src/meeting/in-meeting-actions.ts +171 -3
  274. package/src/meeting/index.ts +3411 -2435
  275. package/src/meeting/locusMediaRequest.ts +313 -0
  276. package/src/meeting/muteState.ts +223 -136
  277. package/src/meeting/request.ts +155 -120
  278. package/src/meeting/util.ts +685 -395
  279. package/src/meeting-info/index.ts +81 -8
  280. package/src/meeting-info/meeting-info-v2.ts +170 -14
  281. package/src/meeting-info/util.ts +1 -1
  282. package/src/meeting-info/utilv2.ts +23 -23
  283. package/src/meetings/collection.ts +33 -0
  284. package/src/meetings/index.ts +507 -127
  285. package/src/meetings/meetings.types.ts +12 -0
  286. package/src/meetings/request.ts +2 -0
  287. package/src/meetings/util.ts +81 -12
  288. package/src/member/index.ts +58 -0
  289. package/src/member/types.ts +38 -0
  290. package/src/member/util.ts +141 -25
  291. package/src/members/collection.ts +8 -0
  292. package/src/members/index.ts +134 -8
  293. package/src/members/request.ts +97 -17
  294. package/src/members/types.ts +29 -0
  295. package/src/members/util.ts +333 -240
  296. package/src/metrics/constants.ts +17 -0
  297. package/src/metrics/index.ts +1 -469
  298. package/src/multistream/mediaRequestManager.ts +271 -56
  299. package/src/multistream/receiveSlot.ts +11 -4
  300. package/src/multistream/receiveSlotManager.ts +34 -24
  301. package/src/multistream/remoteMedia.ts +5 -3
  302. package/src/multistream/remoteMediaGroup.ts +78 -0
  303. package/src/multistream/remoteMediaManager.ts +248 -44
  304. package/src/multistream/sendSlotManager.ts +199 -0
  305. package/src/reachability/clusterReachability.ts +320 -0
  306. package/src/reachability/index.ts +229 -346
  307. package/src/reachability/request.ts +8 -4
  308. package/src/reachability/util.ts +24 -0
  309. package/src/reconnection-manager/index.ts +128 -97
  310. package/src/recording-controller/index.ts +20 -3
  311. package/src/recording-controller/util.ts +26 -9
  312. package/src/roap/index.ts +52 -23
  313. package/src/roap/request.ts +48 -67
  314. package/src/roap/turnDiscovery.ts +147 -49
  315. package/src/rtcMetrics/constants.ts +3 -0
  316. package/src/rtcMetrics/index.ts +166 -0
  317. package/src/statsAnalyzer/index.ts +457 -416
  318. package/src/statsAnalyzer/mqaUtil.ts +317 -170
  319. package/src/webinar/collection.ts +31 -0
  320. package/src/webinar/index.ts +62 -0
  321. package/test/integration/spec/converged-space-meetings.js +60 -3
  322. package/test/integration/spec/journey.js +320 -261
  323. package/test/integration/spec/space-meeting.js +76 -3
  324. package/test/unit/spec/annotation/index.ts +418 -0
  325. package/test/unit/spec/breakouts/breakout.ts +118 -28
  326. package/test/unit/spec/breakouts/events.ts +89 -0
  327. package/test/unit/spec/breakouts/index.ts +1349 -114
  328. package/test/unit/spec/breakouts/utils.js +52 -1
  329. package/test/unit/spec/common/queue.js +31 -2
  330. package/test/unit/spec/controls-options-manager/index.js +163 -0
  331. package/test/unit/spec/controls-options-manager/util.js +576 -60
  332. package/test/unit/spec/fixture/locus.js +1 -0
  333. package/test/unit/spec/interceptors/locusRetry.ts +131 -0
  334. package/test/unit/spec/interpretation/collection.ts +15 -0
  335. package/test/unit/spec/interpretation/index.ts +625 -0
  336. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  337. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  338. package/test/unit/spec/locus-info/index.js +1363 -37
  339. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  340. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  341. package/test/unit/spec/locus-info/mediaSharesUtils.ts +41 -0
  342. package/test/unit/spec/locus-info/parser.js +116 -35
  343. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  344. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  345. package/test/unit/spec/media/index.ts +173 -81
  346. package/test/unit/spec/media/properties.ts +2 -2
  347. package/test/unit/spec/meeting/in-meeting-actions.ts +85 -3
  348. package/test/unit/spec/meeting/index.js +6821 -2172
  349. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  350. package/test/unit/spec/meeting/muteState.js +402 -212
  351. package/test/unit/spec/meeting/request.js +473 -54
  352. package/test/unit/spec/meeting/utils.js +773 -67
  353. package/test/unit/spec/meeting-info/index.js +300 -0
  354. package/test/unit/spec/meeting-info/meetinginfov2.js +526 -5
  355. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  356. package/test/unit/spec/meetings/collection.js +26 -0
  357. package/test/unit/spec/meetings/index.js +1415 -213
  358. package/test/unit/spec/meetings/utils.js +229 -2
  359. package/test/unit/spec/member/index.js +61 -6
  360. package/test/unit/spec/member/util.js +510 -34
  361. package/test/unit/spec/members/index.js +432 -1
  362. package/test/unit/spec/members/request.js +206 -27
  363. package/test/unit/spec/members/utils.js +210 -0
  364. package/test/unit/spec/metrics/index.js +1 -50
  365. package/test/unit/spec/multistream/mediaRequestManager.ts +781 -114
  366. package/test/unit/spec/multistream/receiveSlot.ts +9 -1
  367. package/test/unit/spec/multistream/receiveSlotManager.ts +32 -30
  368. package/test/unit/spec/multistream/remoteMedia.ts +2 -0
  369. package/test/unit/spec/multistream/remoteMediaGroup.ts +345 -0
  370. package/test/unit/spec/multistream/remoteMediaManager.ts +525 -0
  371. package/test/unit/spec/multistream/sendSlotManager.ts +274 -0
  372. package/test/unit/spec/reachability/clusterReachability.ts +279 -0
  373. package/test/unit/spec/reachability/index.ts +551 -14
  374. package/test/unit/spec/reachability/request.js +3 -1
  375. package/test/unit/spec/reachability/util.ts +40 -0
  376. package/test/unit/spec/reconnection-manager/index.js +171 -11
  377. package/test/unit/spec/recording-controller/index.js +294 -218
  378. package/test/unit/spec/recording-controller/util.js +223 -96
  379. package/test/unit/spec/roap/index.ts +180 -83
  380. package/test/unit/spec/roap/request.ts +100 -62
  381. package/test/unit/spec/roap/turnDiscovery.ts +388 -96
  382. package/test/unit/spec/rtcMetrics/index.ts +122 -0
  383. package/test/unit/spec/stats-analyzer/index.js +1252 -12
  384. package/test/unit/spec/webinar/collection.ts +13 -0
  385. package/test/unit/spec/webinar/index.ts +60 -0
  386. package/test/utils/integrationTestUtils.js +46 -0
  387. package/test/utils/testUtils.js +0 -57
  388. package/test/utils/webex-test-users.js +12 -4
  389. package/dist/metrics/config.js +0 -289
  390. package/dist/metrics/config.js.map +0 -1
  391. package/dist/types/metrics/config.d.ts +0 -169
  392. package/src/index.js +0 -18
  393. package/src/metrics/config.ts +0 -485
@@ -15,6 +15,10 @@ import {cloneDeep} from 'lodash';
15
15
  import {MediaRequest} from '@webex/plugin-meetings/src/multistream/mediaRequestManager';
16
16
  import {CSI, ReceiveSlotId} from '@webex/plugin-meetings/src/multistream/receiveSlot';
17
17
  import testUtils from '../../../utils/testUtils';
18
+ import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
19
+ import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
20
+ import { expect } from 'chai';
21
+ import { NamedMediaGroup } from "@webex/json-multistream";
18
22
 
19
23
  class FakeSlot extends EventEmitter {
20
24
  public mediaType: MediaType;
@@ -32,6 +36,10 @@ class FakeSlot extends EventEmitter {
32
36
  // Calling setMaxListeners() fixes the warning.
33
37
  this.setMaxListeners(50);
34
38
  }
39
+
40
+ public get logString() {
41
+ return this.id;
42
+ }
35
43
  }
36
44
 
37
45
  const DefaultTestConfiguration: Configuration = {
@@ -120,7 +128,23 @@ describe('RemoteMediaManager', () => {
120
128
  let fakeScreenShareAudioSlot;
121
129
  let fakeScreenShareVideoSlot;
122
130
 
131
+ const logger = {
132
+ log: sinon.fake(),
133
+ error: () => {},
134
+ warn: () => {},
135
+ trace: () => {},
136
+ debug: () => {},
137
+ };
138
+
139
+ afterEach(() => {
140
+ LoggerConfig.set({enable: false});
141
+ LoggerProxy.set();
142
+ });
143
+
123
144
  beforeEach(() => {
145
+ LoggerConfig.set({enable: true});
146
+ LoggerProxy.set(logger);
147
+
124
148
  fakeAudioSlot = new FakeSlot(MediaType.AudioMain, 'fake audio slot');
125
149
  fakeVideoSlot = new FakeSlot(MediaType.VideoMain, 'fake video slot');
126
150
  fakeScreenShareAudioSlot = new FakeSlot(
@@ -191,6 +215,7 @@ describe('RemoteMediaManager', () => {
191
215
  fakeMediaRequestManagers.video.commit.resetHistory();
192
216
  fakeMediaRequestManagers.screenShareVideo.commit.resetHistory();
193
217
  fakeMediaRequestManagers.screenShareAudio.commit.resetHistory();
218
+ logger.log.resetHistory();
194
219
  };
195
220
 
196
221
  describe('start', () => {
@@ -275,6 +300,204 @@ describe('RemoteMediaManager', () => {
275
300
  );
276
301
  });
277
302
 
303
+ it('creates a RemoteMediaGroup for named media group audio correctly', async () => {
304
+ let createdInterpretationAudioGroup: RemoteMediaGroup | null = null;
305
+ // create a config with just audio, no video at all and no screen share
306
+ const config: Configuration = {
307
+ audio: {
308
+ numOfActiveSpeakerStreams: 3,
309
+ numOfScreenShareStreams: 0,
310
+ },
311
+ video: {
312
+ preferLiveVideo: false,
313
+ initialLayoutId: 'empty',
314
+ layouts: {
315
+ empty: {},
316
+ },
317
+ },
318
+ namedMediaGroup: {type: 1, value: 20},
319
+ };
320
+
321
+ remoteMediaManager = new RemoteMediaManager(
322
+ fakeReceiveSlotManager,
323
+ fakeMediaRequestManagers,
324
+ config
325
+ );
326
+
327
+ remoteMediaManager.on(Event.InterpretationAudioCreated, (audio: RemoteMediaGroup) => {
328
+ createdInterpretationAudioGroup = audio;
329
+ });
330
+
331
+ remoteMediaManager.start();
332
+
333
+ await testUtils.flushPromises();
334
+
335
+ assert.callCount(fakeReceiveSlotManager.allocateSlot, 4);
336
+ assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.AudioMain);
337
+
338
+ assert.isNotNull(createdInterpretationAudioGroup);
339
+ if (createdInterpretationAudioGroup) {
340
+ assert.strictEqual(createdInterpretationAudioGroup.getRemoteMedia().length, 1);
341
+ assert.isTrue(
342
+ createdInterpretationAudioGroup
343
+ .getRemoteMedia()
344
+ .every((remoteMedia) => remoteMedia.mediaType === MediaType.AudioMain)
345
+ );
346
+ assert.strictEqual(createdInterpretationAudioGroup.getRemoteMedia('pinned').length, 0);
347
+ assert.calledTwice(fakeMediaRequestManagers.audio.addRequest);
348
+ assert.calledWith(
349
+ fakeMediaRequestManagers.audio.addRequest,
350
+ sinon.match({
351
+ policyInfo: sinon.match({
352
+ policy: 'active-speaker',
353
+ priority: 255,
354
+ namedMediaGroups: sinon.match([{type: 1, value: 20}]),
355
+ }),
356
+ receiveSlots: Array(1).fill(fakeAudioSlot),
357
+ codecInfo: undefined,
358
+ }),
359
+ false,
360
+ );
361
+ }
362
+ });
363
+
364
+ it('creates new media request when call setReceiveNamedMediaGroup', async () => {
365
+ let createdInterpretationAudioGroup: RemoteMediaGroup | null = null;
366
+ // create a config with just audio, no video at all and no screen share
367
+ const config: Configuration = {
368
+ audio: {
369
+ numOfActiveSpeakerStreams: 3,
370
+ numOfScreenShareStreams: 0,
371
+ },
372
+ video: {
373
+ preferLiveVideo: false,
374
+ initialLayoutId: 'empty',
375
+ layouts: {
376
+ empty: {},
377
+ },
378
+ },
379
+ namedMediaGroup: {type: 1, value: 24},
380
+ };
381
+
382
+ remoteMediaManager = new RemoteMediaManager(
383
+ fakeReceiveSlotManager,
384
+ fakeMediaRequestManagers,
385
+ config
386
+ );
387
+
388
+ remoteMediaManager.on(Event.InterpretationAudioCreated, (audio: RemoteMediaGroup) => {
389
+ createdInterpretationAudioGroup = audio;
390
+ createdInterpretationAudioGroup.setNamedMediaGroup = sinon.stub();
391
+ });
392
+
393
+ await remoteMediaManager.start();
394
+
395
+ // requires 3 main audio slots and one interpretation audio slot
396
+ assert.callCount(fakeReceiveSlotManager.allocateSlot, 4);
397
+
398
+
399
+ resetHistory();
400
+
401
+
402
+ remoteMediaManager.setReceiveNamedMediaGroup(MediaType.AudioMain, 28);
403
+
404
+ // check that setNamedMediaGroup has been called
405
+ assert.calledOnce(createdInterpretationAudioGroup.setNamedMediaGroup);
406
+ assert.calledWith(
407
+ createdInterpretationAudioGroup.setNamedMediaGroup,
408
+ {type: 1, value: 28},
409
+ true,
410
+ );
411
+
412
+ });
413
+
414
+ it('ignore duplicated group when call setReceiveNamedMediaGroup', async () => {
415
+ let createdAudioGroup: RemoteMediaGroup | null = null;
416
+ let audioStopStub;
417
+ // create a config with just audio, no video at all and no screen share
418
+ const config: Configuration = {
419
+ audio: {
420
+ numOfActiveSpeakerStreams: 3,
421
+ numOfScreenShareStreams: 0,
422
+ },
423
+ video: {
424
+ preferLiveVideo: false,
425
+ initialLayoutId: 'empty',
426
+ layouts: {
427
+ empty: {},
428
+ },
429
+ },
430
+ namedMediaGroup: {type: 1, value: 24},
431
+ };
432
+
433
+ remoteMediaManager = new RemoteMediaManager(
434
+ fakeReceiveSlotManager,
435
+ fakeMediaRequestManagers,
436
+ config
437
+ );
438
+
439
+ remoteMediaManager.on(Event.AudioCreated, (audio: RemoteMediaGroup) => {
440
+ audioStopStub = sinon.stub(audio, 'stop');
441
+ });
442
+
443
+ await remoteMediaManager.start();
444
+
445
+ // we're using the default config that requires 3 main audio slots
446
+ assert.callCount(fakeReceiveSlotManager.allocateSlot, 4);
447
+
448
+
449
+ resetHistory();
450
+
451
+ remoteMediaManager.setReceiveNamedMediaGroup(MediaType.AudioMain, 24);
452
+
453
+ assert.notCalled(audioStopStub);
454
+ assert.callCount(fakeReceiveSlotManager.releaseSlot, 0);
455
+
456
+ await testUtils.flushPromises();
457
+ assert.callCount(fakeReceiveSlotManager.allocateSlot, 0);
458
+ assert.notCalled(fakeReceiveSlotManager.allocateSlot);
459
+
460
+ });
461
+
462
+
463
+ it('should throw error if set receive named media group which type is not audio', async () => {
464
+ let createdAudioGroup: RemoteMediaGroup | null = null;
465
+ let audioStopStub;
466
+ // create a config with just audio, no video at all and no screen share
467
+ const config: Configuration = {
468
+ audio: {
469
+ numOfActiveSpeakerStreams: 3,
470
+ numOfScreenShareStreams: 0,
471
+ },
472
+ video: {
473
+ preferLiveVideo: false,
474
+ initialLayoutId: 'empty',
475
+ layouts: {
476
+ empty: {},
477
+ },
478
+ },
479
+ namedMediaGroup: {type: 1, value: 24},
480
+ };
481
+
482
+ remoteMediaManager = new RemoteMediaManager(
483
+ fakeReceiveSlotManager,
484
+ fakeMediaRequestManagers,
485
+ config
486
+ );
487
+
488
+ // Assuming setReceiveNamedMediaGroup returns a promise
489
+ it('should throw error when media type is not audio-main', async () => {
490
+ try {
491
+ await remoteMediaManager.setReceiveNamedMediaGroup(MediaType.VideoMain, 0);
492
+ // If the promise resolves successfully, we should fail the test
493
+ throw new Error('Expected an error but none was thrown');
494
+ } catch (error) {
495
+ // Check if the error message matches the expected one
496
+ expect(error.message).to.equal('cannot set receive named media group which media type is not audio-main');
497
+ }
498
+ });
499
+ });
500
+
278
501
  it('pre-allocates receive slots based on the biggest layout', async () => {
279
502
  const config = cloneDeep(DefaultTestConfiguration);
280
503
 
@@ -639,6 +862,41 @@ describe('RemoteMediaManager', () => {
639
862
  remoteMediaManager.stop();
640
863
  });
641
864
  });
865
+
866
+ describe('setPreferLiveVideo', () => {
867
+
868
+ it('sets preferLiveVideo', async () => {
869
+ const config = cloneDeep(DefaultTestConfiguration);
870
+ let stubs = [];
871
+
872
+ config.video.initialLayoutId = 'OnePlusFive';
873
+
874
+ remoteMediaManager = new RemoteMediaManager(
875
+ fakeReceiveSlotManager,
876
+ fakeMediaRequestManagers,
877
+ config
878
+ );
879
+
880
+ remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
881
+ Object.values(layoutInfo.activeSpeakerVideoPanes).forEach((group) => stubs.push(sinon.stub(group, 'setPreferLiveVideo')));
882
+ });
883
+
884
+ await remoteMediaManager.start();
885
+ resetHistory();
886
+ assert(stubs.length > 0);
887
+ await remoteMediaManager.setPreferLiveVideo(true);
888
+
889
+
890
+ stubs.forEach((stub) => {
891
+ assert.calledWith(stub, true, false)
892
+ });
893
+
894
+ expect(config.video.preferLiveVideo).to.equal(true);
895
+
896
+ assert.calledOnce(fakeMediaRequestManagers.video.commit);
897
+ });
898
+ });
899
+
642
900
  describe('setLayout', () => {
643
901
  it('rejects if called with invalid layoutId', async () => {
644
902
  await assert.isRejected(remoteMediaManager.setLayout('invalid value'));
@@ -671,6 +929,58 @@ describe('RemoteMediaManager', () => {
671
929
  assert.alwaysCalledWith(fakeReceiveSlotManager.allocateSlot, MediaType.VideoMain);
672
930
  });
673
931
 
932
+ it('logs layout changes - receiver selected', async () => {
933
+ const config = cloneDeep(DefaultTestConfiguration);
934
+
935
+ remoteMediaManager = new RemoteMediaManager(
936
+ fakeReceiveSlotManager,
937
+ fakeMediaRequestManagers,
938
+ config
939
+ );
940
+
941
+ await remoteMediaManager.start();
942
+
943
+ resetHistory();
944
+
945
+ await remoteMediaManager.setLayout('Stage');
946
+
947
+ assert.calledWith(
948
+ logger.log,
949
+ 'RemoteMediaManager#setLayout --> new layout selected: Stage'
950
+ );
951
+ assert.calledWith(
952
+ logger.log,
953
+ 'RemoteMediaManager#logMainVideoReceiveSlots --> MAIN VIDEO receive slots: unused=0, activeSpeaker=6, receiverSelected=4\ngroup: thumbnails\nfake video slot, fake video slot, fake video slot, fake video slot, fake video slot, fake video slot\nreceiverSelected:\n stage-1: fake video slot\n stage-2: fake video slot\n stage-3: fake video slot\n stage-4: fake video slot\n'
954
+ );
955
+ });
956
+
957
+ it('logs layout changes - active speaker', async () => {
958
+ const config = cloneDeep(DefaultTestConfiguration);
959
+ config.video.initialLayoutId = 'OnePlusFive'
960
+
961
+ remoteMediaManager = new RemoteMediaManager(
962
+ fakeReceiveSlotManager,
963
+ fakeMediaRequestManagers,
964
+ config
965
+ );
966
+
967
+ await remoteMediaManager.start();
968
+
969
+ resetHistory();
970
+
971
+ await remoteMediaManager.setLayout('AllEqual');
972
+
973
+ assert.calledWith(
974
+ logger.log,
975
+ 'RemoteMediaManager#setLayout --> new layout selected: AllEqual'
976
+ );
977
+ assert.calledWith(
978
+ logger.log,
979
+ 'RemoteMediaManager#logMainVideoReceiveSlots --> MAIN VIDEO receive slots: unused=0, activeSpeaker=9, receiverSelected=0\ngroup: main\nfake video slot, fake video slot, fake video slot, fake video slot, fake video slot, fake video slot, fake video slot, fake video slot, fake video slot\nreceiverSelected:\n'
980
+ );
981
+ });
982
+
983
+
674
984
  it('releases slots when switching to layout that requires less active speaker slots', async () => {
675
985
  // start with "AllEqual" layout that needs just 9 video slots
676
986
  const config = cloneDeep(DefaultTestConfiguration);
@@ -699,6 +1009,133 @@ describe('RemoteMediaManager', () => {
699
1009
  });
700
1010
  });
701
1011
 
1012
+ it('releases slots and reallocates slots when switching to layouts in correct order', async () => {
1013
+
1014
+ const config = cloneDeep(DefaultTestConfiguration);
1015
+ let count = 0;
1016
+
1017
+ fakeReceiveSlotManager.allocateSlot = sinon.stub().callsFake((mediaType) => {
1018
+ switch (mediaType) {
1019
+ case MediaType.AudioMain:
1020
+ return Promise.resolve(fakeAudioSlot);
1021
+ case MediaType.VideoMain:
1022
+ return Promise.resolve(new FakeSlot(MediaType.VideoMain, `fake video ${count++}`));
1023
+ case MediaType.AudioSlides:
1024
+ return Promise.resolve(fakeScreenShareAudioSlot);
1025
+ case MediaType.VideoSlides:
1026
+ return Promise.resolve(fakeScreenShareVideoSlot);
1027
+ }
1028
+ throw new Error(`invalid mediaType: ${mediaType}`);
1029
+ })
1030
+
1031
+ remoteMediaManager = new RemoteMediaManager(
1032
+ fakeReceiveSlotManager,
1033
+ fakeMediaRequestManagers,
1034
+ config
1035
+ );
1036
+
1037
+ await remoteMediaManager.start();
1038
+
1039
+ resetHistory();
1040
+
1041
+ assert.deepEqual(remoteMediaManager.slots.video.activeSpeaker.map((slot: any) => slot.id), [
1042
+ "fake video 0",
1043
+ "fake video 1",
1044
+ "fake video 2",
1045
+ "fake video 3",
1046
+ "fake video 4",
1047
+ "fake video 5",
1048
+ "fake video 6",
1049
+ "fake video 7",
1050
+ "fake video 8",
1051
+ ]);
1052
+
1053
+ assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["main"].slots.map((slot: any) => slot.id), [
1054
+ "fake video 0",
1055
+ "fake video 1",
1056
+ "fake video 2",
1057
+ "fake video 3",
1058
+ "fake video 4",
1059
+ "fake video 5",
1060
+ "fake video 6",
1061
+ "fake video 7",
1062
+ "fake video 8",
1063
+ ])
1064
+
1065
+ // switch to "OnePlusFive" layout that requires 3 less video slots (6)
1066
+ await remoteMediaManager.setLayout('OnePlusFive');
1067
+
1068
+ assert.deepEqual(remoteMediaManager.slots.video.unused, []);
1069
+
1070
+ assert.deepEqual(remoteMediaManager.slots.video.activeSpeaker.map((slot: any) => slot.id), [
1071
+ "fake video 0",
1072
+ "fake video 1",
1073
+ "fake video 2",
1074
+ "fake video 3",
1075
+ "fake video 4",
1076
+ "fake video 5"
1077
+ ]);
1078
+
1079
+ // we're checking that the slots are in the same order as in the previous layout
1080
+ // first one goes into main
1081
+ assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["mainBigOne"].slots.map((slot: any) => slot.id), [
1082
+ "fake video 0",
1083
+ ])
1084
+ // and rest go in the pips
1085
+ assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["secondarySetOfSmallPanes"].slots.map((slot: any) => slot.id), [
1086
+ "fake video 1",
1087
+ "fake video 2",
1088
+ "fake video 3",
1089
+ "fake video 4",
1090
+ "fake video 5"
1091
+ ])
1092
+
1093
+ // verify that 3 main video slots were released
1094
+ assert.callCount(fakeReceiveSlotManager.releaseSlot, 3);
1095
+ fakeReceiveSlotManager.releaseSlot.getCalls().forEach((call) => {
1096
+ const slot = call.args[0];
1097
+
1098
+ assert.strictEqual(slot.mediaType, MediaType.VideoMain);
1099
+ });
1100
+
1101
+ await remoteMediaManager.setLayout('AllEqual');
1102
+
1103
+ assert.deepEqual(remoteMediaManager.slots.video.unused, []);
1104
+
1105
+ // checking that slots are in the same order as in previous layout + 3 new ones
1106
+ assert.deepEqual(remoteMediaManager.slots.video.activeSpeaker.map((slot: any) => slot.id), [
1107
+ "fake video 0",
1108
+ "fake video 1",
1109
+ "fake video 2",
1110
+ "fake video 3",
1111
+ "fake video 4",
1112
+ "fake video 5",
1113
+ "fake video 10",
1114
+ "fake video 11",
1115
+ "fake video 12",
1116
+ ]);
1117
+
1118
+ assert.deepEqual(remoteMediaManager.receiveSlotAllocations.activeSpeaker["main"].slots.map((slot: any) => slot.id), [
1119
+ "fake video 0",
1120
+ "fake video 1",
1121
+ "fake video 2",
1122
+ "fake video 3",
1123
+ "fake video 4",
1124
+ "fake video 5",
1125
+ "fake video 10",
1126
+ "fake video 11",
1127
+ "fake video 12"
1128
+ ])
1129
+
1130
+ // verify that 3 main video slots were allocated
1131
+ assert.callCount(fakeReceiveSlotManager.allocateSlot, 3);
1132
+ fakeReceiveSlotManager.allocateSlot.getCalls().forEach((call) => {
1133
+ const mediaType = call.args[0];
1134
+
1135
+ assert.strictEqual(mediaType, MediaType.VideoMain);
1136
+ });
1137
+ });
1138
+
702
1139
  it('stops all current video remoteMedia instances when switching to new layout', async () => {
703
1140
  const audioStopStubs = [];
704
1141
  const videoStopStubs = [];
@@ -1494,6 +1931,94 @@ describe('RemoteMediaManager', () => {
1494
1931
  });
1495
1932
  });
1496
1933
 
1934
+ describe('setActiveSpeakerCsis', () => {
1935
+ it('calls setActiveSpeakerCsis on the correct remote media group', async () => {
1936
+ let currentLayoutInfo: VideoLayoutChangedEventData | null = null;
1937
+ let setCsisStub;
1938
+
1939
+ remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
1940
+ currentLayoutInfo = layoutInfo;
1941
+ setCsisStub = sinon.stub(layoutInfo.activeSpeakerVideoPanes.main, 'setActiveSpeakerCsis');
1942
+ });
1943
+
1944
+ await remoteMediaManager.start();
1945
+ resetHistory();
1946
+
1947
+ assert.isNotNull(currentLayoutInfo);
1948
+
1949
+ if (currentLayoutInfo) {
1950
+ const remoteVideo = currentLayoutInfo.activeSpeakerVideoPanes.main.getRemoteMedia()[0];
1951
+
1952
+ remoteMediaManager.setActiveSpeakerCsis([{remoteMedia: remoteVideo}]);
1953
+
1954
+ assert.calledOnce(setCsisStub);
1955
+ assert.calledWith(setCsisStub, [{remoteMedia: remoteVideo}], false);
1956
+ assert.calledOnce(fakeMediaRequestManagers.video.commit);
1957
+ }
1958
+ });
1959
+
1960
+ it('does not call setActiveSpeakerCsis on the incorrect media group', async () => {
1961
+ let currentLayoutInfo: VideoLayoutChangedEventData | null = null;
1962
+ let setCsisStub;
1963
+
1964
+ remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
1965
+ currentLayoutInfo = layoutInfo;
1966
+ setCsisStub = sinon.stub(layoutInfo.activeSpeakerVideoPanes.main, 'setActiveSpeakerCsis');
1967
+ });
1968
+
1969
+ await remoteMediaManager.start();
1970
+ resetHistory();
1971
+
1972
+ assert.isNotNull(currentLayoutInfo);
1973
+
1974
+ if (currentLayoutInfo) {
1975
+ remoteMediaManager.setActiveSpeakerCsis([{remoteMedia: {}}]);
1976
+
1977
+ assert.notCalled(setCsisStub);
1978
+ assert.calledOnce(fakeMediaRequestManagers.video.commit);
1979
+ }
1980
+ });
1981
+
1982
+ it('checking when there is more than one group', async () => {
1983
+ let currentLayoutInfo: VideoLayoutChangedEventData | null = null;
1984
+ const config = cloneDeep(DefaultTestConfiguration);
1985
+ let stubs = [];
1986
+
1987
+ config.video.initialLayoutId = 'OnePlusFive';
1988
+
1989
+ remoteMediaManager = new RemoteMediaManager(
1990
+ fakeReceiveSlotManager,
1991
+ fakeMediaRequestManagers,
1992
+ config
1993
+ );
1994
+
1995
+ remoteMediaManager.on(Event.VideoLayoutChanged, (layoutInfo: VideoLayoutChangedEventData) => {
1996
+ currentLayoutInfo = layoutInfo;
1997
+ Object.values(layoutInfo.activeSpeakerVideoPanes).forEach((group) => stubs.push(sinon.stub(group, 'setActiveSpeakerCsis')));
1998
+ });
1999
+
2000
+ await remoteMediaManager.start();
2001
+ resetHistory();
2002
+
2003
+ assert.isNotNull(currentLayoutInfo);
2004
+
2005
+ if (currentLayoutInfo) {
2006
+
2007
+ const remoteMedia1 = currentLayoutInfo.activeSpeakerVideoPanes.mainBigOne.getRemoteMedia()[0];
2008
+ const remoteMedia2 = currentLayoutInfo.activeSpeakerVideoPanes.secondarySetOfSmallPanes.getRemoteMedia()[0];
2009
+
2010
+ const remoteMediaCsis = [{remoteMedia: remoteMedia1}, {remoteMedia: remoteMedia2}];
2011
+
2012
+ remoteMediaManager.setActiveSpeakerCsis([{remoteMedia: remoteMedia1}, {remoteMedia: remoteMedia2}]);
2013
+
2014
+ stubs.forEach((stub, index) => {
2015
+ assert.calledWith(stub, [remoteMediaCsis[index]], false)
2016
+ });
2017
+ assert.calledOnce(fakeMediaRequestManagers.video.commit);
2018
+ }
2019
+ });
2020
+ });
2021
+
1497
2022
  describe('pinActiveSpeakerVideoPane() and isPinned()', () => {
1498
2023
  it('throws if called on a pane not belonging to an active speaker group', async () => {
1499
2024
  let currentLayoutInfo: VideoLayoutChangedEventData | null = null;