@webex/plugin-meetings 2.60.0 → 2.60.1-next.1

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 (535) hide show
  1. package/README.md +46 -8
  2. package/dist/annotation/annotation.types.d.ts +42 -0
  3. package/dist/annotation/annotation.types.js +7 -0
  4. package/dist/annotation/annotation.types.js.map +1 -0
  5. package/dist/annotation/constants.d.ts +31 -0
  6. package/dist/annotation/constants.js +41 -0
  7. package/dist/annotation/constants.js.map +1 -0
  8. package/dist/annotation/index.d.ts +117 -0
  9. package/dist/annotation/index.js +357 -0
  10. package/dist/annotation/index.js.map +1 -0
  11. package/dist/breakouts/breakout.d.ts +8 -0
  12. package/dist/breakouts/breakout.js +215 -0
  13. package/dist/breakouts/breakout.js.map +1 -0
  14. package/dist/breakouts/collection.d.ts +5 -0
  15. package/dist/breakouts/collection.js +22 -0
  16. package/dist/breakouts/collection.js.map +1 -0
  17. package/dist/breakouts/edit-lock-error.d.ts +15 -0
  18. package/dist/breakouts/edit-lock-error.js +51 -0
  19. package/dist/breakouts/edit-lock-error.js.map +1 -0
  20. package/dist/breakouts/events.d.ts +8 -0
  21. package/dist/breakouts/events.js +44 -0
  22. package/dist/breakouts/events.js.map +1 -0
  23. package/dist/breakouts/index.d.ts +5 -0
  24. package/dist/breakouts/index.js +1047 -0
  25. package/dist/breakouts/index.js.map +1 -0
  26. package/dist/breakouts/request.d.ts +22 -0
  27. package/dist/breakouts/request.js +77 -0
  28. package/dist/breakouts/request.js.map +1 -0
  29. package/dist/breakouts/utils.d.ts +15 -0
  30. package/dist/breakouts/utils.js +64 -0
  31. package/dist/breakouts/utils.js.map +1 -0
  32. package/dist/common/browser-detection.js +2 -3
  33. package/dist/common/browser-detection.js.map +1 -1
  34. package/dist/common/collection.js +3 -4
  35. package/dist/common/collection.js.map +1 -1
  36. package/dist/common/config.js +1 -2
  37. package/dist/common/config.js.map +1 -1
  38. package/dist/common/errors/captcha-error.js +1 -2
  39. package/dist/common/errors/captcha-error.js.map +1 -1
  40. package/dist/common/errors/intent-to-join.js +1 -2
  41. package/dist/common/errors/intent-to-join.js.map +1 -1
  42. package/dist/common/errors/join-meeting.js +1 -2
  43. package/dist/common/errors/join-meeting.js.map +1 -1
  44. package/dist/common/errors/media.js +1 -2
  45. package/dist/common/errors/media.js.map +1 -1
  46. package/dist/common/errors/no-meeting-info.d.ts +14 -0
  47. package/dist/common/errors/no-meeting-info.js +50 -0
  48. package/dist/common/errors/no-meeting-info.js.map +1 -0
  49. package/dist/common/errors/parameter.js +3 -4
  50. package/dist/common/errors/parameter.js.map +1 -1
  51. package/dist/common/errors/password-error.js +1 -2
  52. package/dist/common/errors/password-error.js.map +1 -1
  53. package/dist/common/errors/permission.js +1 -2
  54. package/dist/common/errors/permission.js.map +1 -1
  55. package/dist/common/errors/{reclaim-host-role-error.js → reclaim-host-role-errors.js} +7 -11
  56. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  57. package/dist/common/errors/reconnection-in-progress.js +1 -2
  58. package/dist/common/errors/reconnection-in-progress.js.map +1 -1
  59. package/dist/common/errors/reconnection.js +1 -2
  60. package/dist/common/errors/reconnection.js.map +1 -1
  61. package/dist/common/errors/stats.js +1 -2
  62. package/dist/common/errors/stats.js.map +1 -1
  63. package/dist/common/errors/webex-errors.d.ts +20 -8
  64. package/dist/common/errors/webex-errors.js +48 -28
  65. package/dist/common/errors/webex-errors.js.map +1 -1
  66. package/dist/common/errors/webex-meetings-error.js +1 -2
  67. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  68. package/dist/common/events/events-scope.js +1 -2
  69. package/dist/common/events/events-scope.js.map +1 -1
  70. package/dist/common/events/events.js +1 -2
  71. package/dist/common/events/events.js.map +1 -1
  72. package/dist/common/events/trigger-proxy.js +1 -2
  73. package/dist/common/events/trigger-proxy.js.map +1 -1
  74. package/dist/common/events/util.js +1 -2
  75. package/dist/common/events/util.js.map +1 -1
  76. package/dist/common/logs/logger-config.js +1 -2
  77. package/dist/common/logs/logger-config.js.map +1 -1
  78. package/dist/common/logs/logger-proxy.js +2 -3
  79. package/dist/common/logs/logger-proxy.js.map +1 -1
  80. package/dist/common/logs/request.d.ts +3 -1
  81. package/dist/common/logs/request.js +8 -5
  82. package/dist/common/logs/request.js.map +1 -1
  83. package/dist/common/queue.d.ts +9 -7
  84. package/dist/common/queue.js +22 -9
  85. package/dist/common/queue.js.map +1 -1
  86. package/dist/config.d.ts +6 -7
  87. package/dist/config.js +8 -10
  88. package/dist/config.js.map +1 -1
  89. package/dist/constants.d.ts +217 -97
  90. package/dist/constants.js +416 -441
  91. package/dist/constants.js.map +1 -1
  92. package/dist/controls-options-manager/constants.js +3 -6
  93. package/dist/controls-options-manager/constants.js.map +1 -1
  94. package/dist/controls-options-manager/enums.d.ts +11 -1
  95. package/dist/controls-options-manager/enums.js +15 -6
  96. package/dist/controls-options-manager/enums.js.map +1 -1
  97. package/dist/controls-options-manager/index.d.ts +17 -1
  98. package/dist/controls-options-manager/index.js +127 -38
  99. package/dist/controls-options-manager/index.js.map +1 -1
  100. package/dist/controls-options-manager/types.d.ts +43 -0
  101. package/dist/controls-options-manager/types.js +7 -0
  102. package/dist/controls-options-manager/types.js.map +1 -0
  103. package/dist/controls-options-manager/util.d.ts +1 -7
  104. package/dist/controls-options-manager/util.js +309 -19
  105. package/dist/controls-options-manager/util.js.map +1 -1
  106. package/dist/index.d.ts +6 -3
  107. package/dist/index.js +121 -5
  108. package/dist/index.js.map +1 -1
  109. package/dist/interceptors/index.d.ts +2 -0
  110. package/dist/interceptors/index.js +15 -0
  111. package/dist/interceptors/index.js.map +1 -0
  112. package/dist/interceptors/locusRetry.d.ts +27 -0
  113. package/dist/interceptors/locusRetry.js +94 -0
  114. package/dist/interceptors/locusRetry.js.map +1 -0
  115. package/dist/interpretation/collection.d.ts +5 -0
  116. package/dist/interpretation/collection.js +22 -0
  117. package/dist/interpretation/collection.js.map +1 -0
  118. package/dist/interpretation/index.d.ts +5 -0
  119. package/dist/interpretation/index.js +365 -0
  120. package/dist/interpretation/index.js.map +1 -0
  121. package/dist/interpretation/siLanguage.d.ts +5 -0
  122. package/dist/interpretation/siLanguage.js +24 -0
  123. package/dist/interpretation/siLanguage.js.map +1 -0
  124. package/dist/locus-info/controlsUtils.js +100 -11
  125. package/dist/locus-info/controlsUtils.js.map +1 -1
  126. package/dist/locus-info/embeddedAppsUtils.js +3 -4
  127. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  128. package/dist/locus-info/fullState.js +1 -2
  129. package/dist/locus-info/fullState.js.map +1 -1
  130. package/dist/locus-info/hostUtils.js +1 -2
  131. package/dist/locus-info/hostUtils.js.map +1 -1
  132. package/dist/locus-info/index.d.ts +57 -4
  133. package/dist/locus-info/index.js +425 -84
  134. package/dist/locus-info/index.js.map +1 -1
  135. package/dist/locus-info/infoUtils.js +13 -5
  136. package/dist/locus-info/infoUtils.js.map +1 -1
  137. package/dist/locus-info/mediaSharesUtils.js +58 -3
  138. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  139. package/dist/locus-info/parser.d.ts +66 -6
  140. package/dist/locus-info/parser.js +253 -80
  141. package/dist/locus-info/parser.js.map +1 -1
  142. package/dist/locus-info/selfUtils.js +97 -13
  143. package/dist/locus-info/selfUtils.js.map +1 -1
  144. package/dist/media/index.d.ts +2 -0
  145. package/dist/media/index.js +107 -319
  146. package/dist/media/index.js.map +1 -1
  147. package/dist/media/properties.d.ts +38 -53
  148. package/dist/media/properties.js +96 -153
  149. package/dist/media/properties.js.map +1 -1
  150. package/dist/media/util.js +1 -22
  151. package/dist/media/util.js.map +1 -1
  152. package/dist/mediaQualityMetrics/config.d.ts +234 -230
  153. package/dist/mediaQualityMetrics/config.js +302 -498
  154. package/dist/mediaQualityMetrics/config.js.map +1 -1
  155. package/dist/meeting/in-meeting-actions.d.ts +88 -0
  156. package/dist/meeting/in-meeting-actions.js +94 -3
  157. package/dist/meeting/in-meeting-actions.js.map +1 -1
  158. package/dist/meeting/index.d.ts +591 -494
  159. package/dist/meeting/index.js +4732 -2990
  160. package/dist/meeting/index.js.map +1 -1
  161. package/dist/meeting/locusMediaRequest.d.ts +74 -0
  162. package/dist/meeting/locusMediaRequest.js +291 -0
  163. package/dist/meeting/locusMediaRequest.js.map +1 -0
  164. package/dist/meeting/muteState.d.ts +93 -25
  165. package/dist/meeting/muteState.js +224 -133
  166. package/dist/meeting/muteState.js.map +1 -1
  167. package/dist/meeting/request.d.ts +82 -47
  168. package/dist/meeting/request.js +297 -199
  169. package/dist/meeting/request.js.map +1 -1
  170. package/dist/meeting/request.type.d.ts +11 -0
  171. package/dist/meeting/request.type.js +7 -0
  172. package/dist/meeting/request.type.js.map +1 -0
  173. package/dist/meeting/state.js +1 -2
  174. package/dist/meeting/state.js.map +1 -1
  175. package/dist/meeting/util.d.ts +102 -1
  176. package/dist/meeting/util.js +605 -435
  177. package/dist/meeting/util.js.map +1 -1
  178. package/dist/meeting-info/collection.js +3 -4
  179. package/dist/meeting-info/collection.js.map +1 -1
  180. package/dist/meeting-info/index.d.ts +13 -1
  181. package/dist/meeting-info/index.js +74 -7
  182. package/dist/meeting-info/index.js.map +1 -1
  183. package/dist/meeting-info/meeting-info-v2.d.ts +31 -1
  184. package/dist/meeting-info/meeting-info-v2.js +200 -63
  185. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  186. package/dist/meeting-info/request.js +1 -2
  187. package/dist/meeting-info/request.js.map +1 -1
  188. package/dist/meeting-info/util.js +2 -3
  189. package/dist/meeting-info/util.js.map +1 -1
  190. package/dist/meeting-info/utilv2.js +39 -41
  191. package/dist/meeting-info/utilv2.js.map +1 -1
  192. package/dist/meetings/collection.d.ts +17 -0
  193. package/dist/meetings/collection.js +42 -4
  194. package/dist/meetings/collection.js.map +1 -1
  195. package/dist/meetings/index.d.ts +93 -21
  196. package/dist/meetings/index.js +490 -127
  197. package/dist/meetings/index.js.map +1 -1
  198. package/dist/meetings/meetings.types.d.ts +4 -0
  199. package/dist/meetings/meetings.types.js +7 -0
  200. package/dist/meetings/meetings.types.js.map +1 -0
  201. package/dist/meetings/request.js +4 -3
  202. package/dist/meetings/request.js.map +1 -1
  203. package/dist/meetings/util.js +107 -6
  204. package/dist/meetings/util.js.map +1 -1
  205. package/dist/member/index.d.ts +13 -1
  206. package/dist/member/index.js +45 -2
  207. package/dist/member/index.js.map +1 -1
  208. package/dist/member/member.types.js +3 -4
  209. package/dist/member/member.types.js.map +1 -1
  210. package/dist/member/types.d.ts +32 -0
  211. package/dist/member/types.js +23 -0
  212. package/dist/member/types.js.map +1 -0
  213. package/dist/member/util.js +120 -29
  214. package/dist/member/util.js.map +1 -1
  215. package/dist/members/collection.d.ts +5 -0
  216. package/dist/members/collection.js +11 -2
  217. package/dist/members/collection.js.map +1 -1
  218. package/dist/members/index.d.ts +56 -11
  219. package/dist/members/index.js +174 -47
  220. package/dist/members/index.js.map +1 -1
  221. package/dist/members/request.d.ts +67 -11
  222. package/dist/members/request.js +102 -54
  223. package/dist/members/request.js.map +1 -1
  224. package/dist/members/types.js +3 -4
  225. package/dist/members/types.js.map +1 -1
  226. package/dist/members/util.d.ts +214 -1
  227. package/dist/members/util.js +327 -284
  228. package/dist/members/util.js.map +1 -1
  229. package/dist/metrics/constants.d.ts +15 -6
  230. package/dist/metrics/constants.js +17 -9
  231. package/dist/metrics/constants.js.map +1 -1
  232. package/dist/metrics/index.d.ts +4 -111
  233. package/dist/metrics/index.js +4 -452
  234. package/dist/metrics/index.js.map +1 -1
  235. package/dist/multistream/mediaRequestManager.d.ts +118 -0
  236. package/dist/multistream/mediaRequestManager.js +344 -0
  237. package/dist/multistream/mediaRequestManager.js.map +1 -0
  238. package/dist/multistream/receiveSlot.d.ts +68 -0
  239. package/dist/multistream/receiveSlot.js +200 -0
  240. package/dist/multistream/receiveSlot.js.map +1 -0
  241. package/dist/multistream/receiveSlotManager.d.ts +56 -0
  242. package/dist/multistream/receiveSlotManager.js +174 -0
  243. package/dist/multistream/receiveSlotManager.js.map +1 -0
  244. package/dist/multistream/remoteMedia.d.ts +72 -0
  245. package/dist/multistream/remoteMedia.js +268 -0
  246. package/dist/multistream/remoteMedia.js.map +1 -0
  247. package/dist/multistream/remoteMediaGroup.d.ts +47 -0
  248. package/dist/multistream/remoteMediaGroup.js +267 -0
  249. package/dist/multistream/remoteMediaGroup.js.map +1 -0
  250. package/dist/multistream/remoteMediaManager.d.ts +285 -0
  251. package/dist/multistream/remoteMediaManager.js +1211 -0
  252. package/dist/multistream/remoteMediaManager.js.map +1 -0
  253. package/dist/multistream/sendSlotManager.d.ts +61 -0
  254. package/dist/multistream/sendSlotManager.js +236 -0
  255. package/dist/multistream/sendSlotManager.js.map +1 -0
  256. package/dist/networkQualityMonitor/index.js +5 -4
  257. package/dist/networkQualityMonitor/index.js.map +1 -1
  258. package/dist/personal-meeting-room/index.js +2 -3
  259. package/dist/personal-meeting-room/index.js.map +1 -1
  260. package/dist/personal-meeting-room/request.js +2 -3
  261. package/dist/personal-meeting-room/request.js.map +1 -1
  262. package/dist/personal-meeting-room/util.js +1 -2
  263. package/dist/personal-meeting-room/util.js.map +1 -1
  264. package/dist/reachability/clusterReachability.d.ts +109 -0
  265. package/dist/reachability/clusterReachability.js +357 -0
  266. package/dist/reachability/clusterReachability.js.map +1 -0
  267. package/dist/reachability/index.d.ts +61 -95
  268. package/dist/reachability/index.js +300 -393
  269. package/dist/reachability/index.js.map +1 -1
  270. package/dist/reachability/request.d.ts +7 -3
  271. package/dist/reachability/request.js +18 -10
  272. package/dist/reachability/request.js.map +1 -1
  273. package/dist/reachability/util.d.ts +8 -0
  274. package/dist/reachability/util.js +29 -0
  275. package/dist/reachability/util.js.map +1 -0
  276. package/dist/reactions/constants.d.ts +3 -0
  277. package/dist/reactions/constants.js +12 -0
  278. package/dist/reactions/constants.js.map +1 -0
  279. package/dist/reactions/reactions.d.ts +2 -2
  280. package/dist/reactions/reactions.js +4 -6
  281. package/dist/reactions/reactions.js.map +1 -1
  282. package/dist/reactions/reactions.type.d.ts +23 -3
  283. package/dist/reactions/reactions.type.js +21 -23
  284. package/dist/reactions/reactions.type.js.map +1 -1
  285. package/dist/reconnection-manager/index.d.ts +32 -8
  286. package/dist/reconnection-manager/index.js +282 -231
  287. package/dist/reconnection-manager/index.js.map +1 -1
  288. package/dist/recording-controller/enums.js +4 -5
  289. package/dist/recording-controller/enums.js.map +1 -1
  290. package/dist/recording-controller/index.d.ts +15 -1
  291. package/dist/recording-controller/index.js +57 -46
  292. package/dist/recording-controller/index.js.map +1 -1
  293. package/dist/recording-controller/util.d.ts +5 -4
  294. package/dist/recording-controller/util.js +10 -10
  295. package/dist/recording-controller/util.js.map +1 -1
  296. package/dist/roap/index.d.ts +9 -47
  297. package/dist/roap/index.js +101 -235
  298. package/dist/roap/index.js.map +1 -1
  299. package/dist/roap/request.d.ts +18 -12
  300. package/dist/roap/request.js +126 -180
  301. package/dist/roap/request.js.map +1 -1
  302. package/dist/roap/turnDiscovery.d.ts +27 -16
  303. package/dist/roap/turnDiscovery.js +115 -105
  304. package/dist/roap/turnDiscovery.js.map +1 -1
  305. package/dist/rtcMetrics/constants.d.ts +4 -0
  306. package/dist/rtcMetrics/constants.js +11 -0
  307. package/dist/rtcMetrics/constants.js.map +1 -0
  308. package/dist/rtcMetrics/index.d.ts +54 -0
  309. package/dist/rtcMetrics/index.js +140 -0
  310. package/dist/rtcMetrics/index.js.map +1 -0
  311. package/dist/statsAnalyzer/global.d.ts +1 -83
  312. package/dist/statsAnalyzer/global.js +2 -85
  313. package/dist/statsAnalyzer/global.js.map +1 -1
  314. package/dist/statsAnalyzer/index.d.ts +50 -30
  315. package/dist/statsAnalyzer/index.js +435 -510
  316. package/dist/statsAnalyzer/index.js.map +1 -1
  317. package/dist/statsAnalyzer/mqaUtil.d.ts +8 -6
  318. package/dist/statsAnalyzer/mqaUtil.js +120 -83
  319. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  320. package/dist/transcription/index.js +1 -2
  321. package/dist/transcription/index.js.map +1 -1
  322. package/dist/webinar/collection.d.ts +16 -0
  323. package/dist/webinar/collection.js +43 -0
  324. package/dist/webinar/collection.js.map +1 -0
  325. package/dist/webinar/index.d.ts +5 -0
  326. package/dist/webinar/index.js +68 -0
  327. package/dist/webinar/index.js.map +1 -0
  328. package/package.json +38 -26
  329. package/src/annotation/annotation.types.ts +50 -0
  330. package/src/annotation/constants.ts +36 -0
  331. package/src/annotation/index.ts +328 -0
  332. package/src/breakouts/README.md +220 -0
  333. package/src/breakouts/breakout.ts +188 -0
  334. package/src/breakouts/collection.ts +19 -0
  335. package/src/breakouts/edit-lock-error.ts +25 -0
  336. package/src/breakouts/events.ts +56 -0
  337. package/src/breakouts/index.ts +925 -0
  338. package/src/breakouts/request.ts +55 -0
  339. package/src/breakouts/utils.ts +57 -0
  340. package/src/common/errors/no-meeting-info.ts +24 -0
  341. package/src/common/errors/webex-errors.ts +36 -12
  342. package/src/common/logs/logger-proxy.ts +1 -1
  343. package/src/common/logs/request.ts +5 -1
  344. package/src/common/queue.ts +22 -8
  345. package/src/config.ts +6 -7
  346. package/src/constants.ts +244 -97
  347. package/src/controls-options-manager/enums.ts +12 -0
  348. package/src/controls-options-manager/index.ts +116 -21
  349. package/src/controls-options-manager/types.ts +59 -0
  350. package/src/controls-options-manager/util.ts +294 -14
  351. package/src/index.ts +44 -0
  352. package/src/interceptors/index.ts +3 -0
  353. package/src/interceptors/locusRetry.ts +67 -0
  354. package/src/interpretation/README.md +60 -0
  355. package/src/interpretation/collection.ts +19 -0
  356. package/src/interpretation/index.ts +332 -0
  357. package/src/interpretation/siLanguage.ts +18 -0
  358. package/src/locus-info/controlsUtils.ts +110 -0
  359. package/src/locus-info/index.ts +449 -61
  360. package/src/locus-info/infoUtils.ts +14 -2
  361. package/src/locus-info/mediaSharesUtils.ts +64 -0
  362. package/src/locus-info/parser.ts +258 -47
  363. package/src/locus-info/selfUtils.ts +85 -2
  364. package/src/media/index.ts +153 -370
  365. package/src/media/properties.ts +106 -136
  366. package/src/media/util.ts +0 -21
  367. package/src/mediaQualityMetrics/config.ts +244 -377
  368. package/src/meeting/in-meeting-actions.ts +176 -0
  369. package/src/meeting/index.ts +3944 -2489
  370. package/src/meeting/locusMediaRequest.ts +313 -0
  371. package/src/meeting/muteState.ts +224 -138
  372. package/src/meeting/request.ts +207 -127
  373. package/src/meeting/request.type.ts +13 -0
  374. package/src/meeting/util.ts +590 -423
  375. package/src/meeting-info/index.ts +81 -8
  376. package/src/meeting-info/meeting-info-v2.ts +163 -13
  377. package/src/meeting-info/util.ts +1 -1
  378. package/src/meeting-info/utilv2.ts +28 -28
  379. package/src/meetings/collection.ts +33 -0
  380. package/src/meetings/index.ts +487 -126
  381. package/src/meetings/meetings.types.ts +12 -0
  382. package/src/meetings/request.ts +2 -0
  383. package/src/meetings/util.ts +116 -5
  384. package/src/member/index.ts +43 -1
  385. package/src/member/types.ts +38 -0
  386. package/src/member/util.ts +125 -28
  387. package/src/members/collection.ts +8 -0
  388. package/src/members/index.ts +187 -52
  389. package/src/members/request.ts +87 -27
  390. package/src/members/util.ts +332 -291
  391. package/src/metrics/constants.ts +15 -6
  392. package/src/metrics/index.ts +1 -471
  393. package/src/multistream/mediaRequestManager.ts +440 -0
  394. package/src/multistream/receiveSlot.ts +184 -0
  395. package/src/multistream/receiveSlotManager.ts +166 -0
  396. package/src/multistream/remoteMedia.ts +254 -0
  397. package/src/multistream/remoteMediaGroup.ts +284 -0
  398. package/src/multistream/remoteMediaManager.ts +1145 -0
  399. package/src/multistream/sendSlotManager.ts +170 -0
  400. package/src/networkQualityMonitor/index.ts +6 -6
  401. package/src/reachability/clusterReachability.ts +320 -0
  402. package/src/reachability/index.ts +243 -347
  403. package/src/reachability/request.ts +17 -8
  404. package/src/reachability/util.ts +24 -0
  405. package/src/reactions/constants.ts +4 -0
  406. package/src/reactions/reactions.ts +4 -4
  407. package/src/reactions/reactions.type.ts +30 -4
  408. package/src/reconnection-manager/index.ts +168 -156
  409. package/src/recording-controller/index.ts +20 -3
  410. package/src/recording-controller/util.ts +26 -9
  411. package/src/roap/index.ts +98 -241
  412. package/src/roap/request.ts +74 -148
  413. package/src/roap/turnDiscovery.ts +62 -56
  414. package/src/rtcMetrics/constants.ts +3 -0
  415. package/src/rtcMetrics/index.ts +124 -0
  416. package/src/statsAnalyzer/global.ts +1 -84
  417. package/src/statsAnalyzer/index.ts +477 -643
  418. package/src/statsAnalyzer/mqaUtil.ts +115 -114
  419. package/src/webinar/collection.ts +31 -0
  420. package/src/webinar/index.ts +62 -0
  421. package/test/integration/spec/converged-space-meetings.js +233 -0
  422. package/test/integration/spec/journey.js +320 -264
  423. package/test/integration/spec/space-meeting.js +77 -4
  424. package/test/unit/spec/annotation/index.ts +418 -0
  425. package/test/unit/spec/breakouts/breakout.ts +237 -0
  426. package/test/unit/spec/breakouts/collection.ts +15 -0
  427. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  428. package/test/unit/spec/breakouts/events.ts +89 -0
  429. package/test/unit/spec/breakouts/index.ts +1790 -0
  430. package/test/unit/spec/breakouts/request.ts +104 -0
  431. package/test/unit/spec/breakouts/utils.js +72 -0
  432. package/test/unit/spec/common/queue.js +31 -2
  433. package/test/unit/spec/controls-options-manager/index.js +163 -0
  434. package/test/unit/spec/controls-options-manager/util.js +576 -60
  435. package/test/unit/spec/fixture/locus.js +1 -0
  436. package/test/unit/spec/interceptors/locusRetry.ts +131 -0
  437. package/test/unit/spec/interpretation/collection.ts +15 -0
  438. package/test/unit/spec/interpretation/index.ts +589 -0
  439. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  440. package/test/unit/spec/locus-info/controlsUtils.js +323 -30
  441. package/test/unit/spec/locus-info/index.js +1390 -16
  442. package/test/unit/spec/locus-info/infoUtils.js +54 -16
  443. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  444. package/test/unit/spec/locus-info/lib/selfConstant.js +48 -0
  445. package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
  446. package/test/unit/spec/locus-info/parser.js +116 -35
  447. package/test/unit/spec/locus-info/selfUtils.js +275 -0
  448. package/test/unit/spec/media/index.ts +290 -0
  449. package/test/unit/spec/media/properties.ts +75 -84
  450. package/test/unit/spec/meeting/in-meeting-actions.ts +86 -0
  451. package/test/unit/spec/meeting/index.js +8187 -2769
  452. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  453. package/test/unit/spec/meeting/muteState.js +409 -213
  454. package/test/unit/spec/meeting/request.js +512 -42
  455. package/test/unit/spec/meeting/utils.js +741 -24
  456. package/test/unit/spec/meeting-info/index.js +300 -0
  457. package/test/unit/spec/meeting-info/meetinginfov2.js +527 -5
  458. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  459. package/test/unit/spec/meetings/collection.js +26 -0
  460. package/test/unit/spec/meetings/index.js +1313 -243
  461. package/test/unit/spec/meetings/utils.js +202 -2
  462. package/test/unit/spec/member/index.js +32 -9
  463. package/test/unit/spec/member/util.js +499 -61
  464. package/test/unit/spec/members/index.js +394 -5
  465. package/test/unit/spec/members/request.js +206 -27
  466. package/test/unit/spec/members/utils.js +173 -38
  467. package/test/unit/spec/metrics/index.js +1 -50
  468. package/test/unit/spec/multistream/mediaRequestManager.ts +1418 -0
  469. package/test/unit/spec/multistream/receiveSlot.ts +163 -0
  470. package/test/unit/spec/multistream/receiveSlotManager.ts +203 -0
  471. package/test/unit/spec/multistream/remoteMedia.ts +255 -0
  472. package/test/unit/spec/multistream/remoteMediaGroup.ts +662 -0
  473. package/test/unit/spec/multistream/remoteMediaManager.ts +1924 -0
  474. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  475. package/test/unit/spec/networkQualityMonitor/index.js +4 -4
  476. package/test/unit/spec/reachability/clusterReachability.ts +279 -0
  477. package/test/unit/spec/reachability/index.ts +531 -24
  478. package/test/unit/spec/reachability/request.js +68 -0
  479. package/test/unit/spec/reachability/util.ts +40 -0
  480. package/test/unit/spec/reconnection-manager/index.js +162 -24
  481. package/test/unit/spec/recording-controller/index.js +293 -218
  482. package/test/unit/spec/recording-controller/util.js +223 -96
  483. package/test/unit/spec/roap/index.ts +200 -76
  484. package/test/unit/spec/roap/request.ts +255 -0
  485. package/test/unit/spec/roap/turnDiscovery.ts +86 -48
  486. package/test/unit/spec/rtcMetrics/index.ts +93 -0
  487. package/test/unit/spec/stats-analyzer/index.js +261 -167
  488. package/test/unit/spec/webinar/collection.ts +13 -0
  489. package/test/unit/spec/webinar/index.ts +60 -0
  490. package/test/utils/constants.js +9 -0
  491. package/test/utils/integrationTestUtils.js +46 -0
  492. package/test/utils/testUtils.js +0 -45
  493. package/test/utils/webex-config.js +4 -0
  494. package/test/utils/webex-test-users.js +7 -3
  495. package/dist/common/errors/reclaim-host-role-error.js.map +0 -1
  496. package/dist/meeting/effectsState.d.ts +0 -42
  497. package/dist/meeting/effectsState.js +0 -260
  498. package/dist/meeting/effectsState.js.map +0 -1
  499. package/dist/metrics/config.d.ts +0 -169
  500. package/dist/metrics/config.js +0 -289
  501. package/dist/metrics/config.js.map +0 -1
  502. package/dist/peer-connection-manager/index.d.ts +0 -6
  503. package/dist/peer-connection-manager/index.js +0 -671
  504. package/dist/peer-connection-manager/index.js.map +0 -1
  505. package/dist/peer-connection-manager/util.d.ts +0 -6
  506. package/dist/peer-connection-manager/util.js +0 -110
  507. package/dist/peer-connection-manager/util.js.map +0 -1
  508. package/dist/roap/collection.d.ts +0 -10
  509. package/dist/roap/collection.js +0 -63
  510. package/dist/roap/collection.js.map +0 -1
  511. package/dist/roap/handler.d.ts +0 -47
  512. package/dist/roap/handler.js +0 -279
  513. package/dist/roap/handler.js.map +0 -1
  514. package/dist/roap/state.d.ts +0 -9
  515. package/dist/roap/state.js +0 -127
  516. package/dist/roap/state.js.map +0 -1
  517. package/dist/roap/util.d.ts +0 -2
  518. package/dist/roap/util.js +0 -76
  519. package/dist/roap/util.js.map +0 -1
  520. package/src/index.js +0 -15
  521. package/src/meeting/effectsState.ts +0 -209
  522. package/src/metrics/config.ts +0 -485
  523. package/src/peer-connection-manager/index.ts +0 -847
  524. package/src/peer-connection-manager/util.ts +0 -119
  525. package/src/roap/collection.ts +0 -62
  526. package/src/roap/handler.ts +0 -294
  527. package/src/roap/state.ts +0 -156
  528. package/src/roap/util.ts +0 -100
  529. package/test/unit/spec/meeting/effectsState.js +0 -281
  530. package/test/unit/spec/peerconnection-manager/index.js +0 -218
  531. package/test/unit/spec/peerconnection-manager/utils.js +0 -49
  532. package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -388
  533. package/test/unit/spec/roap/util.js +0 -30
  534. /package/dist/common/errors/{reclaim-host-role-error.d.ts → reclaim-host-role-errors.d.ts} +0 -0
  535. /package/src/common/errors/{reclaim-host-role-error.ts → reclaim-host-role-errors.ts} +0 -0
@@ -1,8 +1,7 @@
1
1
  import sinon from 'sinon';
2
2
  import {assert} from '@webex/test-helper-chai';
3
3
  import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
4
- import createMuteState from '@webex/plugin-meetings/src/meeting/muteState';
5
- import Media from '@webex/plugin-meetings/src/media/index';
4
+ import {createMuteState, MuteState} from '@webex/plugin-meetings/src/meeting/muteState';
6
5
  import PermissionError from '@webex/plugin-meetings/src/common/errors/permission';
7
6
  import {AUDIO, VIDEO} from '@webex/plugin-meetings/src/constants';
8
7
 
@@ -12,277 +11,291 @@ describe('plugin-meetings', () => {
12
11
  let meeting;
13
12
  let audio;
14
13
  let video;
14
+ let originalRemoteUpdateAudioVideo;
15
15
 
16
16
  const fakeLocus = {info: 'this is a fake locus'};
17
17
 
18
- beforeEach(() => {
18
+ const createFakeLocalStream = (id, muted) => {
19
+ return {
20
+ id,
21
+ setServerMuted: sinon.stub(),
22
+ setUnmuteAllowed: sinon.stub(),
23
+ setMuted: sinon.stub(),
24
+ muted,
25
+ };
26
+ };
27
+
28
+ beforeEach(async () => {
19
29
  meeting = {
20
30
  mediaProperties: {
21
- audioTrack: 'fake audio track',
22
- videoTrack: 'fake video track',
31
+ audioStream: createFakeLocalStream('fake audio stream', false),
32
+ videoStream: createFakeLocalStream('fake video stream', false),
23
33
  },
24
34
  remoteMuted: false,
25
35
  unmuteAllowed: true,
36
+ remoteVideoMuted: false,
37
+ unmuteVideoAllowed: true,
38
+
26
39
  locusInfo: {
27
- onFullLocus: sinon.stub(),
40
+ handleLocusDelta: sinon.stub(),
28
41
  },
29
42
  members: {
30
43
  selfId: 'fake self id',
31
44
  muteMember: sinon.stub().resolves(),
32
45
  },
33
46
  };
34
- audio = createMuteState(AUDIO, meeting, {sendAudio: true});
35
- video = createMuteState(VIDEO, meeting, {sendVideo: true});
47
+
48
+ originalRemoteUpdateAudioVideo = MeetingUtil.remoteUpdateAudioVideo;
36
49
 
37
50
  MeetingUtil.remoteUpdateAudioVideo = sinon.stub().resolves(fakeLocus);
38
- Media.setLocalTrack = sinon.stub();
39
- });
40
51
 
41
- describe('mute state library', () => {
42
- it('does not create an audio instance if we are not sending audio', async () => {
43
- assert.isNull(createMuteState(AUDIO, meeting, {sendAudio: false}));
44
- assert.isNull(createMuteState(AUDIO, meeting, {}));
45
- });
52
+ audio = createMuteState(AUDIO, meeting, true);
53
+ video = createMuteState(VIDEO, meeting, true);
46
54
 
47
- it('does not create a video instance if we are not sending video', async () => {
48
- assert.isNull(createMuteState(VIDEO, meeting, {sendVideo: false}));
49
- assert.isNull(createMuteState(VIDEO, meeting, {}));
50
- });
55
+ await testUtils.flushPromises();
56
+ });
51
57
 
58
+ afterEach(() => {
59
+ MeetingUtil.remoteUpdateAudioVideo = originalRemoteUpdateAudioVideo;
60
+ });
61
+
62
+ describe('mute state library', () => {
52
63
  it('takes into account current remote mute status when instantiated', async () => {
53
64
  // simulate being already remote muted
54
65
  meeting.remoteMuted = true;
55
- // create a new MuteState intance
56
- audio = createMuteState(AUDIO, meeting, {sendAudio: true});
66
+
67
+ // create a new MuteState instance
68
+ audio = createMuteState(AUDIO, meeting, true);
69
+
70
+ await testUtils.flushPromises();
57
71
 
58
72
  assert.isTrue(audio.isMuted());
59
- assert.isFalse(audio.isSelf());
73
+ assert.isTrue(audio.isRemotelyMuted());
60
74
 
61
75
  // now check the opposite case
62
76
  meeting.remoteMuted = false;
63
77
 
64
- // create a new MuteState intance
65
- audio = createMuteState(AUDIO, meeting, {sendAudio: true});
78
+ // create a new MuteState instance
79
+ audio = createMuteState(AUDIO, meeting, true);
66
80
 
67
- assert.isFalse(audio.isMuted());
68
- assert.isFalse(audio.isSelf());
81
+ await testUtils.flushPromises();
82
+
83
+ assert.isTrue(audio.isMuted()); // because we start with no stream
84
+ assert.isFalse(audio.isRemotelyMuted());
69
85
  });
70
86
 
71
87
  it('initialises correctly for video', async () => {
72
- // setup fields related to audio remote state
73
- meeting.remoteMuted = true;
74
- meeting.unmuteAllowed = false;
75
- // create a new video MuteState intance
76
- video = createMuteState(VIDEO, meeting, {sendVideo: true});
88
+ // setup fields related to video remote state
89
+ meeting.remoteVideoMuted = false;
90
+ meeting.unmuteVideoAllowed = false;
77
91
 
78
- assert.isFalse(video.isMuted());
92
+ // create a new video MuteState instance
93
+ video = createMuteState(VIDEO, meeting, true);
94
+
95
+ await testUtils.flushPromises();
96
+
97
+ assert.isTrue(video.isMuted()); // because we start with no stream
98
+ assert.isFalse(video.isRemotelyMuted());
79
99
  assert.isFalse(video.state.server.remoteMute);
80
- assert.isTrue(video.state.server.unmuteAllowed);
100
+ assert.isFalse(video.state.server.unmuteAllowed);
81
101
  });
82
102
 
83
103
  it('takes remote mute into account when reporting current state', async () => {
84
- assert.isFalse(audio.isMuted());
104
+ assert.isFalse(audio.isRemotelyMuted());
85
105
 
86
106
  // simulate remote mute
87
- audio.handleServerRemoteMuteUpdate(true, true);
107
+ audio.handleServerRemoteMuteUpdate(meeting, true, true);
88
108
 
89
- assert.isTrue(audio.isMuted());
90
- assert.isFalse(audio.isSelf());
109
+ assert.isTrue(audio.isRemotelyMuted());
91
110
  });
92
111
 
93
112
  it('does local unmute if localAudioUnmuteRequired is received', async () => {
94
- // first we need to mute
95
- await audio.handleClientRequest(meeting, true);
113
+ // first we need to mute have the local stream muted
114
+ meeting.mediaProperties.audioStream.muted = true;
115
+ audio.handleLocalStreamChange(meeting);
96
116
 
97
117
  assert.isTrue(audio.isMuted());
98
- assert.isTrue(audio.isSelf());
99
118
 
100
119
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
101
120
 
102
121
  // now simulate server requiring us to locally unmute
103
122
  audio.handleServerLocalUnmuteRequired(meeting);
123
+
104
124
  await testUtils.flushPromises();
105
125
 
106
- // check that local track was enabled
107
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.audioTrack);
126
+ // check that local stream was unmuted
127
+ assert.calledWith(
128
+ meeting.mediaProperties.audioStream.setServerMuted,
129
+ false,
130
+ 'localUnmuteRequired'
131
+ );
108
132
 
109
133
  // and local unmute was sent to server
110
134
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
111
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, undefined, meeting);
135
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, false, undefined);
112
136
 
113
137
  assert.isFalse(audio.isMuted());
114
- assert.isFalse(audio.isSelf());
115
138
  });
116
139
 
117
- it('rejects client request in progress if localAudioUnmuteRequired is received', async () => {
118
- let clientPromiseResolved = false;
119
- let clientPromiseRejected = false;
120
-
121
- // first we need to mute and make that request last forever
122
- let serverResponseResolve;
123
-
124
- MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(
125
- new Promise((resolve) => {
126
- serverResponseResolve = resolve;
127
- })
128
- );
140
+ it('does local video unmute if localVideoUnmuteRequired is received', async () => {
141
+ // first we need to mute
142
+ meeting.mediaProperties.videoStream.muted = true;
143
+ video.handleLocalStreamChange(meeting);
129
144
 
130
- audio
131
- .handleClientRequest(meeting, true)
132
- .then(() => {
133
- clientPromiseResolved = true;
134
- })
135
- .catch(() => {
136
- clientPromiseRejected = true;
137
- });
145
+ assert.isTrue(video.isMuted());
138
146
 
139
147
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
140
148
 
141
149
  // now simulate server requiring us to locally unmute
142
- audio.handleServerLocalUnmuteRequired(meeting);
150
+ video.handleServerLocalUnmuteRequired(meeting);
143
151
  await testUtils.flushPromises();
144
152
 
145
- // the original client request should have been rejected by now
146
- assert.isTrue(clientPromiseRejected);
147
- assert.isFalse(clientPromiseResolved);
148
-
149
- // now make the server respond to the original mute request
150
- serverResponseResolve();
151
- await testUtils.flushPromises();
153
+ // check that local stream was unmuted
154
+ assert.calledWith(
155
+ meeting.mediaProperties.videoStream.setServerMuted,
156
+ false,
157
+ 'localUnmuteRequired'
158
+ );
152
159
 
153
- // local unmute should be sent to server
160
+ // and local unmute was sent to server
154
161
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
155
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, undefined, meeting);
162
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, false);
156
163
 
157
- // and local track should be enabled
158
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.audioTrack);
159
-
160
- assert.isFalse(audio.isMuted());
161
- assert.isFalse(audio.isSelf());
164
+ assert.isFalse(video.isMuted());
162
165
  });
163
166
 
164
167
  describe('#isLocallyMuted()', () => {
165
168
  it('does not consider remote mute status for audio', async () => {
166
- // simulate being already remote muted
169
+ // simulate being already remote muted and locally unmuted
167
170
  meeting.remoteMuted = true;
168
- // create a new MuteState intance
169
- audio = createMuteState(AUDIO, meeting, {sendAudio: true});
171
+ meeting.mediaProperties.audioStream.muted = false;
172
+
173
+ // create a new MuteState instance
174
+ audio = createMuteState(AUDIO, meeting, true);
175
+ audio.handleLocalStreamChange(meeting);
176
+
177
+ await testUtils.flushPromises();
170
178
 
171
179
  assert.isFalse(audio.isLocallyMuted());
172
180
  });
173
- });
174
181
 
175
- describe('#handleClientRequest', () => {
176
- it('disables/enables the local audio track when audio is muted/unmuted', async () => {
177
- // mute
178
- audio.handleClientRequest(meeting, true);
179
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.audioTrack);
182
+ it('does not consider remote mute status for video', async () => {
183
+ // simulate being already remote muted
184
+ meeting.remoteVideoMuted = true;
185
+ meeting.mediaProperties.videoStream.muted = false;
180
186
 
181
- // even when calling mute when it's already muted should still call setLocalTrack
182
- audio.handleClientRequest(meeting, true);
183
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.audioTrack);
187
+ // create a new MuteState instance
188
+ video = createMuteState(VIDEO, meeting, true);
189
+ video.handleLocalStreamChange(meeting);
184
190
 
185
- // unmute
186
- audio.handleClientRequest(meeting, false);
187
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.audioTrack);
191
+ await testUtils.flushPromises();
188
192
 
189
- // even when calling unmute when it's already unmuted should still call setLocalTrack
190
- audio.handleClientRequest(meeting, false);
191
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.audioTrack);
193
+ assert.isFalse(video.isLocallyMuted());
192
194
  });
195
+ });
193
196
 
194
- it('disables/enables the local video track when video is muted/unmuted', async () => {
195
- // mute
196
- video.handleClientRequest(meeting, true);
197
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.videoTrack);
197
+ describe('handling local stream mute events', () => {
198
+ beforeEach(async () => {
199
+ audio.handleLocalStreamChange(meeting);
200
+ video.handleLocalStreamChange(meeting);
198
201
 
199
- // even when calling mute when it's already muted should still call setLocalTrack
200
- video.handleClientRequest(meeting, false);
201
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.videoTrack);
202
+ await testUtils.flushPromises();
203
+ });
202
204
 
203
- // unmute
204
- video.handleClientRequest(meeting, false);
205
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.videoTrack);
205
+ const simulateAudioMuteChange = async (muteValue) => {
206
+ meeting.mediaProperties.audioStream.muted = muteValue;
207
+ audio.handleLocalStreamMuteStateChange(meeting, muteValue);
206
208
 
207
- // even when calling unmute when it's already unmuted should still call setLocalTrack
208
- video.handleClientRequest(meeting, false);
209
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.videoTrack);
210
- });
209
+ await testUtils.flushPromises();
210
+ };
211
211
 
212
- it('returns correct value in isMuted()/isSelf() methods after client mute/unmute requests', async () => {
213
- // mute
214
- audio.handleClientRequest(meeting, true);
212
+ const simulateVideoMuteChange = async (muteValue) => {
213
+ meeting.mediaProperties.videoStream.muted = muteValue;
214
+ video.handleLocalStreamMuteStateChange(meeting, muteValue);
215
215
 
216
+ await testUtils.flushPromises();
217
+ };
218
+
219
+ it('returns correct value in isMuted() methods after local stream is muted/unmuted', async () => {
220
+ // mute
221
+ await simulateAudioMuteChange(true);
216
222
  assert.isTrue(audio.isMuted());
217
- assert.isTrue(audio.isSelf());
218
223
 
219
224
  // unmute
220
- audio.handleClientRequest(meeting, false);
221
-
225
+ await simulateAudioMuteChange(false);
222
226
  assert.isFalse(audio.isMuted());
223
- assert.isFalse(audio.isSelf());
224
227
  });
225
228
 
226
229
  it('does remote unmute when unmuting and remote mute is on', async () => {
227
230
  // simulate remote mute
228
- audio.handleServerRemoteMuteUpdate(true, true);
231
+ audio.handleServerRemoteMuteUpdate(meeting, true, true);
229
232
 
230
233
  // unmute
231
- await audio.handleClientRequest(meeting, false);
234
+ await simulateAudioMuteChange(false);
232
235
 
233
236
  // check that remote unmute was sent to server
234
237
  assert.calledOnce(meeting.members.muteMember);
235
- assert.calledWith(meeting.members.muteMember, meeting.members.selfId, false);
238
+ assert.calledWith(meeting.members.muteMember, meeting.members.selfId, false, true);
236
239
 
237
240
  assert.isFalse(audio.isMuted());
238
- assert.isFalse(audio.isSelf());
239
241
  });
240
242
 
241
- it('resolves client request promise once the server is updated', async () => {
242
- let clientPromiseResolved = false;
243
+ it('does video remote unmute when unmuting and remote mute is on', async () => {
244
+ // simulate remote mute
245
+ video.handleServerRemoteMuteUpdate(meeting, true, true);
243
246
 
244
- let serverResponseResolve;
247
+ // unmute
248
+ await simulateVideoMuteChange(false);
245
249
 
246
- MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(
247
- new Promise((resolve) => {
248
- serverResponseResolve = resolve;
249
- })
250
- );
250
+ // check that remote unmute was sent to server
251
+ assert.calledOnce(meeting.members.muteMember);
252
+ assert.calledWith(meeting.members.muteMember, meeting.members.selfId, false, false);
251
253
 
252
- audio.handleClientRequest(meeting, true).then(() => {
253
- clientPromiseResolved = true;
254
- });
254
+ assert.isFalse(video.isMuted());
255
+ });
255
256
 
256
- // do a small delay to make sure that the client promise doesn't resolve in that time
257
- await testUtils.waitUntil(200);
258
- assert.isFalse(clientPromiseResolved);
257
+ it('does not video remote unmute when unmuting and remote mute is off', async () => {
258
+ // simulate remote mute
259
+ video.handleServerRemoteMuteUpdate(meeting, false, true);
259
260
 
260
- // now allow the server response to arrive, this should trigger the client promise to get resolved
261
- serverResponseResolve();
262
- await testUtils.flushPromises();
261
+ // unmute
262
+ await simulateVideoMuteChange(false);
263
+
264
+ // check that remote unmute was not sent to server
265
+ assert.notCalled(meeting.members.muteMember);
263
266
 
264
- assert.isTrue(clientPromiseResolved);
267
+ assert.isFalse(video.isMuted());
265
268
  });
266
269
 
267
- it('rejects client request promise if server request for local mute fails', async () => {
268
- MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(
269
- new Promise((resolve, reject) => {
270
- reject();
271
- })
272
- );
270
+ it('calls setServerMuted with "clientRequestFailed" when server request for local mute fails', async () => {
271
+ MeetingUtil.remoteUpdateAudioVideo = sinon.stub().rejects(new Error('fake error'));
273
272
 
274
- assert.isRejected(audio.handleClientRequest(meeting, true));
273
+ await simulateAudioMuteChange(true);
274
+
275
+ assert.calledOnceWithExactly(
276
+ meeting.mediaProperties.audioStream.setServerMuted,
277
+ false,
278
+ 'clientRequestFailed'
279
+ );
275
280
  });
276
281
 
277
- it('rejects client request promise if server request for remote mute fails', async () => {
282
+ it('calls setServerMuted with "clientRequestFailed" if server request for remote mute fails', async () => {
278
283
  // we only send remote mute requests when we're unmuting, so first we need to do a remote mute
279
- audio.handleServerRemoteMuteUpdate(true, true);
284
+ audio.handleServerRemoteMuteUpdate(meeting, true, true);
285
+
286
+ await testUtils.flushPromises();
280
287
 
281
288
  // setup the stub to simulate server error response
282
289
  meeting.members.muteMember = sinon.stub().rejects();
290
+ meeting.mediaProperties.audioStream.setServerMuted.resetHistory();
283
291
 
284
- // try to unmute - it should fail
285
- await assert.isRejected(audio.handleClientRequest(meeting, false));
292
+ await simulateAudioMuteChange(false);
293
+
294
+ assert.calledOnceWithExactly(
295
+ meeting.mediaProperties.audioStream.setServerMuted,
296
+ true,
297
+ 'clientRequestFailed'
298
+ );
286
299
 
287
300
  // even though remote mute update in the server failed, isMuted() should still return true,
288
301
  // because of local mute
@@ -298,12 +311,13 @@ describe('plugin-meetings', () => {
298
311
  })
299
312
  );
300
313
 
301
- // simulate many client requests, with the last one matching the initial one
302
- audio.handleClientRequest(meeting, true);
303
- audio.handleClientRequest(meeting, false);
304
- audio.handleClientRequest(meeting, true);
305
- audio.handleClientRequest(meeting, false);
306
- audio.handleClientRequest(meeting, true);
314
+ // the stream is initially unmuted
315
+ // simulate many mute changes with the last one matching the first one
316
+ await simulateAudioMuteChange(true);
317
+ await simulateAudioMuteChange(false);
318
+ await simulateAudioMuteChange(true);
319
+ await simulateAudioMuteChange(false);
320
+ await simulateAudioMuteChange(true);
307
321
 
308
322
  // so far there should have been only 1 request to server (because our stub hasn't resolved yet
309
323
  // and MuteState sends only 1 server request at a time)
@@ -318,7 +332,7 @@ describe('plugin-meetings', () => {
318
332
  assert.notCalled(MeetingUtil.remoteUpdateAudioVideo);
319
333
  });
320
334
 
321
- it('queues up server requests when multiple client requests are received', async () => {
335
+ it('queues up server requests when multiple mute changes happen to local stream', async () => {
322
336
  let serverResponseResolve;
323
337
 
324
338
  MeetingUtil.remoteUpdateAudioVideo = sinon.stub().returns(
@@ -327,104 +341,286 @@ describe('plugin-meetings', () => {
327
341
  })
328
342
  );
329
343
 
330
- let firstClientPromiseResolved = false;
331
- let secondClientPromiseResolved = false;
332
-
333
344
  // 2 client requests, one after another without waiting for first one to resolve
334
- audio.handleClientRequest(meeting, true).then(() => {
335
- firstClientPromiseResolved = true;
336
- });
337
- audio.handleClientRequest(meeting, false).then(() => {
338
- secondClientPromiseResolved = true;
339
- });
340
-
341
- await testUtils.flushPromises();
345
+ await simulateAudioMuteChange(true);
346
+ await simulateAudioMuteChange(false);
342
347
 
343
348
  assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
344
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, true, undefined, meeting);
349
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, true, undefined);
345
350
 
346
351
  // now allow the first request to complete
347
352
  serverResponseResolve();
348
353
  await testUtils.flushPromises();
349
- assert.isTrue(firstClientPromiseResolved);
350
354
 
351
355
  // that should trigger the second server request to be sent
352
356
  assert.calledTwice(MeetingUtil.remoteUpdateAudioVideo);
353
- assert.strictEqual(false, MeetingUtil.remoteUpdateAudioVideo.getCall(1).args[0]);
354
- assert.strictEqual(undefined, MeetingUtil.remoteUpdateAudioVideo.getCall(1).args[1]);
355
- assert.strictEqual(meeting, MeetingUtil.remoteUpdateAudioVideo.getCall(1).args[2]);
357
+ assert.deepEqual(
358
+ [meeting, false, undefined],
359
+ MeetingUtil.remoteUpdateAudioVideo.getCall(1).args
360
+ );
356
361
 
357
362
  serverResponseResolve();
358
- await testUtils.flushPromises();
359
-
360
- assert.isTrue(secondClientPromiseResolved);
361
- });
362
-
363
- it('rejects client request to unmute if hard mute is used', (done) => {
364
- audio.handleServerRemoteMuteUpdate(true, false);
365
-
366
- audio
367
- .handleClientRequest(meeting, false)
368
- .then(() => {
369
- done(new Error('expected handleClientRequest to fail, but it did not!'));
370
- })
371
- .catch((e) => {
372
- assert.isTrue(e instanceof PermissionError);
373
- done();
374
- });
375
363
  });
376
364
 
377
365
  it('does not send remote mute for video', async () => {
378
366
  // mute
379
- await video.handleClientRequest(meeting, true);
367
+ await simulateVideoMuteChange(true);
380
368
 
381
369
  assert.isTrue(video.isMuted());
382
- assert.isTrue(video.isSelf());
383
370
 
384
371
  // check local mute is done, but not remote one
385
- assert.calledWith(Media.setLocalTrack, false, meeting.mediaProperties.videoTrack);
386
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, undefined, true, meeting);
372
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, true);
387
373
  assert.notCalled(meeting.members.muteMember);
388
374
 
389
- Media.setLocalTrack.resetHistory();
390
375
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
391
376
  meeting.members.muteMember.resetHistory();
392
377
 
393
378
  // unmute
394
- await video.handleClientRequest(meeting, false);
379
+ await simulateVideoMuteChange(false);
395
380
 
396
381
  assert.isFalse(video.isMuted());
397
- assert.isFalse(video.isSelf());
398
382
 
399
- assert.calledWith(Media.setLocalTrack, true, meeting.mediaProperties.videoTrack);
400
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, undefined, false, meeting);
383
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, false);
401
384
  assert.notCalled(meeting.members.muteMember);
402
385
  });
403
386
 
404
- it('sends correct audio value when sending local mute for video', async () => {
387
+ it('sends undefined value for the other media type when sending local mute', async () => {
405
388
  // make sure the meeting object has mute state machines for both audio and video
406
389
  meeting.audio = audio;
407
390
  meeting.video = video;
408
391
 
409
- // mute audio -> request sent to server should have video unmuted
410
- await audio.handleClientRequest(meeting, true);
411
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, true, false, meeting);
392
+ // mute audio -> the call to remoteUpdateAudioVideo should have video undefined
393
+ await simulateAudioMuteChange(true);
394
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, true, undefined);
412
395
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
413
396
 
414
- // now mute video -> request sent to server should have mute for both audio and video
415
- await video.handleClientRequest(meeting, true);
416
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, true, true, meeting);
397
+ // now mute video -> the call to remoteUpdateAudioVideo should have unmute for video and undefined for audio
398
+ await simulateVideoMuteChange(true);
399
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, true);
417
400
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
418
401
 
419
- // now unmute the audio -> request sent to server should still have video muted
420
- await audio.handleClientRequest(meeting, false);
421
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, true, meeting);
402
+ // now unmute the audio -> the call to remoteUpdateAudioVideo should have video undefined
403
+ await simulateAudioMuteChange(false);
404
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, false, undefined);
422
405
  MeetingUtil.remoteUpdateAudioVideo.resetHistory();
423
406
 
424
- // unmute video -> request sent to server should have both audio and video unmuted
425
- await video.handleClientRequest(meeting, false);
426
- assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, false, false, meeting);
407
+ // unmute video -> the call to remoteUpdateAudioVideo should have audio undefined
408
+ await simulateVideoMuteChange(false);
409
+ assert.calledWith(MeetingUtil.remoteUpdateAudioVideo, meeting, undefined, false);
427
410
  });
428
411
  });
412
+
413
+ describe('#init, #handleLocalStreamChange', () => {
414
+ let meeting;
415
+ let muteState;
416
+ let setServerMutedSpy;
417
+ let setMutedSpy, setUnmuteAllowedSpy;
418
+
419
+ const setupMeeting = (
420
+ mediaType,
421
+ remoteMuted = false,
422
+ muted = false,
423
+ defineStreams = true
424
+ ) => {
425
+ const remoteMuteField = mediaType === AUDIO ? 'remoteMuted' : 'remoteVideoMuted';
426
+
427
+ meeting = {
428
+ mediaProperties: {
429
+ audioStream: defineStreams
430
+ ? createFakeLocalStream('fake audio stream', muted)
431
+ : undefined,
432
+ videoStream: defineStreams
433
+ ? createFakeLocalStream('fake video stream', muted)
434
+ : undefined,
435
+ },
436
+ [remoteMuteField]: remoteMuted,
437
+ unmuteAllowed: true,
438
+ unmuteVideoAllowed: true,
439
+
440
+ locusInfo: {
441
+ onFullLocus: sinon.stub(),
442
+ },
443
+ members: {
444
+ selfId: 'fake self id',
445
+ muteMember: sinon.stub().resolves(),
446
+ },
447
+ };
448
+ };
449
+
450
+ const setup = async (mediaType, remoteMuted = false, muted = false, defineStreams = true) => {
451
+ setupMeeting(mediaType, remoteMuted, muted, defineStreams);
452
+
453
+ muteState = createMuteState(mediaType, meeting, true);
454
+ muteState.handleLocalStreamChange(meeting);
455
+
456
+ await testUtils.flushPromises();
457
+
458
+ MeetingUtil.remoteUpdateAudioVideo.resetHistory();
459
+ };
460
+
461
+ const setupSpies = (mediaType) => {
462
+ setUnmuteAllowedSpy =
463
+ mediaType === AUDIO
464
+ ? meeting.mediaProperties.audioStream?.setUnmuteAllowed
465
+ : meeting.mediaProperties.videoStream?.setUnmuteAllowed;
466
+ setServerMutedSpy =
467
+ mediaType === AUDIO
468
+ ? meeting.mediaProperties.audioStream?.setServerMuted
469
+ : meeting.mediaProperties.videoStream?.setServerMuted;
470
+ setMutedSpy =
471
+ mediaType === AUDIO
472
+ ? meeting.mediaProperties.audioStream?.setMuted
473
+ : meeting.mediaProperties.videoStream?.setMuted;
474
+
475
+ clearSpies();
476
+ };
477
+
478
+ const clearSpies = () => {
479
+ setUnmuteAllowedSpy?.resetHistory();
480
+ setServerMutedSpy?.resetHistory();
481
+ setMutedSpy?.resetHistory();
482
+ };
483
+ const tests = [
484
+ {mediaType: AUDIO, title: 'audio'},
485
+ {mediaType: VIDEO, title: 'video'},
486
+ ];
487
+
488
+ tests.forEach(({mediaType, title}) =>
489
+ describe(title, () => {
490
+ let originalRemoteUpdateAudioVideo;
491
+
492
+ beforeEach(() => {
493
+ originalRemoteUpdateAudioVideo = MeetingUtil.remoteUpdateAudioVideo;
494
+ MeetingUtil.remoteUpdateAudioVideo = sinon.stub().resolves({info: 'fake locus'});
495
+ });
496
+
497
+ afterEach(() => {
498
+ MeetingUtil.remoteUpdateAudioVideo = originalRemoteUpdateAudioVideo;
499
+ sinon.restore();
500
+ });
501
+
502
+ describe('#handleLocalStreamChange', () => {
503
+ it('calls init()', async () => {
504
+ await setup(mediaType);
505
+ const spy = sinon.spy(muteState, 'init');
506
+ muteState.handleLocalStreamChange(meeting);
507
+ assert.calledOnceWithExactly(spy, meeting);
508
+ });
509
+ });
510
+
511
+ describe('#init', () => {
512
+ // does the setup by calling new MuteState() so that MuteState.init() doesn't get called
513
+ const setupWithoutInit = async (
514
+ mediaType,
515
+ remoteMuted = false,
516
+ muted = false,
517
+ defineStreams = true
518
+ ) => {
519
+ setupMeeting(mediaType, remoteMuted, muted, defineStreams);
520
+
521
+ muteState = new MuteState(mediaType, meeting, true);
522
+ };
523
+
524
+ it('nothing goes bad when stream is undefined', async () => {
525
+ await setupWithoutInit(mediaType, false, false, false);
526
+ setupSpies(mediaType);
527
+
528
+ muteState.init(meeting);
529
+
530
+ assert.isTrue(muteState.state.client.localMute);
531
+ });
532
+
533
+ it('tests when stream muted is true and remoteMuted is false', async () => {
534
+ await setupWithoutInit(mediaType, false, true);
535
+ setupSpies(mediaType);
536
+
537
+ muteState.init(meeting);
538
+
539
+ assert.calledWith(setUnmuteAllowedSpy, muteState.state.server.unmuteAllowed);
540
+ assert.notCalled(setServerMutedSpy);
541
+ assert.notCalled(MeetingUtil.remoteUpdateAudioVideo);
542
+ assert.isTrue(muteState.state.client.localMute);
543
+ });
544
+
545
+ it('tests when stream muted is false and remoteMuted is false', async () => {
546
+ await setupWithoutInit(mediaType, false, false);
547
+ setupSpies(mediaType);
548
+
549
+ muteState.init(meeting);
550
+
551
+ assert.calledWith(setUnmuteAllowedSpy, muteState.state.server.unmuteAllowed);
552
+ assert.notCalled(setServerMutedSpy);
553
+ assert.calledOnce(MeetingUtil.remoteUpdateAudioVideo);
554
+ assert.isFalse(muteState.state.client.localMute);
555
+ });
556
+
557
+ it('tests when remoteMuted is true', async () => {
558
+ // testing that muteLocalStream is called
559
+ await setupWithoutInit(mediaType, true);
560
+ setupSpies(mediaType);
561
+
562
+ muteState.init(meeting);
563
+
564
+ assert.calledWith(setUnmuteAllowedSpy, muteState.state.server.unmuteAllowed);
565
+ assert.calledOnceWithExactly(setServerMutedSpy, true, 'remotelyMuted');
566
+ });
567
+ });
568
+
569
+ describe('#handleLocalStreamMuteStateChange', () => {
570
+ it('checks when ignoreMuteStateChange is true nothing changes', async () => {
571
+ await setup(mediaType, false, false);
572
+ muteState.ignoreMuteStateChange = true;
573
+
574
+ muteState.handleLocalStreamMuteStateChange(meeting, true);
575
+ assert.notCalled(MeetingUtil.remoteUpdateAudioVideo);
576
+
577
+ assert.isFalse(muteState.state.client.localMute);
578
+ });
579
+
580
+ it('tests localMute - true to false', async () => {
581
+ await setup(mediaType, false, true);
582
+
583
+ muteState.handleLocalStreamMuteStateChange(meeting, false);
584
+ assert.equal(muteState.state.client.localMute, false);
585
+ assert.called(MeetingUtil.remoteUpdateAudioVideo);
586
+ });
587
+
588
+ it('tests localMute - false to true', async () => {
589
+ await setup(mediaType, false, false);
590
+
591
+ muteState.handleLocalStreamMuteStateChange(meeting, true);
592
+ assert.equal(muteState.state.client.localMute, true);
593
+ assert.called(MeetingUtil.remoteUpdateAudioVideo);
594
+ });
595
+ });
596
+
597
+ describe('#applyClientStateLocally', () => {
598
+ afterEach(() => {
599
+ sinon.restore();
600
+ });
601
+
602
+ it('calls setServerMuted on the stream', async () => {
603
+ await setup(mediaType);
604
+ setupSpies(mediaType);
605
+
606
+ muteState.applyClientStateLocally(meeting, 'somereason');
607
+ assert.calledOnceWithExactly(
608
+ setServerMutedSpy,
609
+ muteState.state.client.localMute,
610
+ 'somereason'
611
+ );
612
+ assert.notCalled(setMutedSpy);
613
+ });
614
+
615
+ it('nothing explodes when streams are undefined', async () => {
616
+ await setup(mediaType, false, false, false);
617
+ setupSpies(mediaType);
618
+
619
+ muteState.applyClientStateLocally(meeting, 'somereason');
620
+ });
621
+ });
622
+ })
623
+ );
624
+ });
429
625
  });
430
626
  });