@webex/plugin-meetings 3.0.0-beta.26 → 3.0.0-beta.261

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 (361) hide show
  1. package/README.md +46 -8
  2. package/dist/annotation/annotation.types.js +7 -0
  3. package/dist/annotation/annotation.types.js.map +1 -0
  4. package/dist/annotation/constants.js +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 +114 -14
  9. package/dist/breakouts/breakout.js.map +1 -1
  10. package/dist/breakouts/edit-lock-error.js +52 -0
  11. package/dist/breakouts/edit-lock-error.js.map +1 -0
  12. package/dist/breakouts/events.js +45 -0
  13. package/dist/breakouts/events.js.map +1 -0
  14. package/dist/breakouts/index.js +841 -19
  15. package/dist/breakouts/index.js.map +1 -1
  16. package/dist/breakouts/request.js +78 -0
  17. package/dist/breakouts/request.js.map +1 -0
  18. package/dist/breakouts/utils.js +67 -0
  19. package/dist/breakouts/utils.js.map +1 -0
  20. package/dist/common/errors/webex-errors.js +28 -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/queue.js +24 -9
  25. package/dist/common/queue.js.map +1 -1
  26. package/dist/config.js +5 -10
  27. package/dist/config.js.map +1 -1
  28. package/dist/constants.js +196 -28
  29. package/dist/constants.js.map +1 -1
  30. package/dist/controls-options-manager/enums.js +14 -2
  31. package/dist/controls-options-manager/enums.js.map +1 -1
  32. package/dist/controls-options-manager/index.js +109 -15
  33. package/dist/controls-options-manager/index.js.map +1 -1
  34. package/dist/controls-options-manager/types.js +7 -0
  35. package/dist/controls-options-manager/types.js.map +1 -0
  36. package/dist/controls-options-manager/util.js +309 -18
  37. package/dist/controls-options-manager/util.js.map +1 -1
  38. package/dist/index.js +112 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/interpretation/collection.js +23 -0
  41. package/dist/interpretation/collection.js.map +1 -0
  42. package/dist/interpretation/index.js +366 -0
  43. package/dist/interpretation/index.js.map +1 -0
  44. package/dist/interpretation/siLanguage.js +25 -0
  45. package/dist/interpretation/siLanguage.js.map +1 -0
  46. package/dist/locus-info/controlsUtils.js +91 -2
  47. package/dist/locus-info/controlsUtils.js.map +1 -1
  48. package/dist/locus-info/index.js +381 -62
  49. package/dist/locus-info/index.js.map +1 -1
  50. package/dist/locus-info/infoUtils.js +7 -1
  51. package/dist/locus-info/infoUtils.js.map +1 -1
  52. package/dist/locus-info/mediaSharesUtils.js +43 -1
  53. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  54. package/dist/locus-info/parser.js +224 -63
  55. package/dist/locus-info/parser.js.map +1 -1
  56. package/dist/locus-info/selfUtils.js +89 -14
  57. package/dist/locus-info/selfUtils.js.map +1 -1
  58. package/dist/media/index.js +58 -116
  59. package/dist/media/index.js.map +1 -1
  60. package/dist/media/properties.js +60 -121
  61. package/dist/media/properties.js.map +1 -1
  62. package/dist/meeting/in-meeting-actions.js +82 -2
  63. package/dist/meeting/in-meeting-actions.js.map +1 -1
  64. package/dist/meeting/index.js +3022 -2795
  65. package/dist/meeting/index.js.map +1 -1
  66. package/dist/meeting/locusMediaRequest.js +292 -0
  67. package/dist/meeting/locusMediaRequest.js.map +1 -0
  68. package/dist/meeting/muteState.js +230 -124
  69. package/dist/meeting/muteState.js.map +1 -1
  70. package/dist/meeting/request.js +256 -196
  71. package/dist/meeting/request.js.map +1 -1
  72. package/dist/meeting/util.js +601 -417
  73. package/dist/meeting/util.js.map +1 -1
  74. package/dist/meeting-info/index.js +70 -7
  75. package/dist/meeting-info/index.js.map +1 -1
  76. package/dist/meeting-info/meeting-info-v2.js +189 -51
  77. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  78. package/dist/meeting-info/util.js +1 -1
  79. package/dist/meeting-info/util.js.map +1 -1
  80. package/dist/meeting-info/utilv2.js +36 -36
  81. package/dist/meeting-info/utilv2.js.map +1 -1
  82. package/dist/meetings/collection.js +22 -0
  83. package/dist/meetings/collection.js.map +1 -1
  84. package/dist/meetings/index.js +372 -90
  85. package/dist/meetings/index.js.map +1 -1
  86. package/dist/meetings/meetings.types.js +7 -0
  87. package/dist/meetings/meetings.types.js.map +1 -0
  88. package/dist/meetings/request.js +2 -0
  89. package/dist/meetings/request.js.map +1 -1
  90. package/dist/meetings/util.js +88 -1
  91. package/dist/meetings/util.js.map +1 -1
  92. package/dist/member/index.js +49 -0
  93. package/dist/member/index.js.map +1 -1
  94. package/dist/member/types.js +25 -0
  95. package/dist/member/types.js.map +1 -0
  96. package/dist/member/util.js +121 -25
  97. package/dist/member/util.js.map +1 -1
  98. package/dist/members/collection.js +10 -0
  99. package/dist/members/collection.js.map +1 -1
  100. package/dist/members/index.js +86 -5
  101. package/dist/members/index.js.map +1 -1
  102. package/dist/members/request.js +106 -38
  103. package/dist/members/request.js.map +1 -1
  104. package/dist/members/types.js +15 -0
  105. package/dist/members/types.js.map +1 -0
  106. package/dist/members/util.js +316 -233
  107. package/dist/members/util.js.map +1 -1
  108. package/dist/metrics/constants.js +10 -5
  109. package/dist/metrics/constants.js.map +1 -1
  110. package/dist/metrics/index.js +1 -468
  111. package/dist/metrics/index.js.map +1 -1
  112. package/dist/multistream/mediaRequestManager.js +238 -49
  113. package/dist/multistream/mediaRequestManager.js.map +1 -1
  114. package/dist/multistream/receiveSlot.js +49 -16
  115. package/dist/multistream/receiveSlot.js.map +1 -1
  116. package/dist/multistream/receiveSlotManager.js +52 -34
  117. package/dist/multistream/receiveSlotManager.js.map +1 -1
  118. package/dist/multistream/remoteMedia.js +44 -18
  119. package/dist/multistream/remoteMedia.js.map +1 -1
  120. package/dist/multistream/remoteMediaGroup.js +60 -3
  121. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  122. package/dist/multistream/remoteMediaManager.js +209 -59
  123. package/dist/multistream/remoteMediaManager.js.map +1 -1
  124. package/dist/multistream/sendSlotManager.js +233 -0
  125. package/dist/multistream/sendSlotManager.js.map +1 -0
  126. package/dist/reachability/index.js +161 -57
  127. package/dist/reachability/index.js.map +1 -1
  128. package/dist/reachability/request.js +17 -8
  129. package/dist/reachability/request.js.map +1 -1
  130. package/dist/reconnection-manager/index.js +199 -154
  131. package/dist/reconnection-manager/index.js.map +1 -1
  132. package/dist/recording-controller/index.js +21 -2
  133. package/dist/recording-controller/index.js.map +1 -1
  134. package/dist/recording-controller/util.js +9 -8
  135. package/dist/recording-controller/util.js.map +1 -1
  136. package/dist/roap/index.js +23 -29
  137. package/dist/roap/index.js.map +1 -1
  138. package/dist/roap/request.js +112 -97
  139. package/dist/roap/request.js.map +1 -1
  140. package/dist/roap/turnDiscovery.js +96 -36
  141. package/dist/roap/turnDiscovery.js.map +1 -1
  142. package/dist/rtcMetrics/constants.js +12 -0
  143. package/dist/rtcMetrics/constants.js.map +1 -0
  144. package/dist/rtcMetrics/index.js +117 -0
  145. package/dist/rtcMetrics/index.js.map +1 -0
  146. package/dist/statsAnalyzer/index.js +51 -34
  147. package/dist/statsAnalyzer/index.js.map +1 -1
  148. package/dist/statsAnalyzer/mqaUtil.js +6 -6
  149. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  150. package/dist/types/annotation/annotation.types.d.ts +42 -0
  151. package/dist/types/annotation/constants.d.ts +31 -0
  152. package/dist/types/annotation/index.d.ts +117 -0
  153. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  154. package/dist/types/breakouts/events.d.ts +8 -0
  155. package/dist/types/breakouts/request.d.ts +22 -0
  156. package/dist/types/breakouts/utils.d.ts +15 -0
  157. package/dist/types/common/errors/webex-errors.d.ts +13 -1
  158. package/dist/types/common/queue.d.ts +9 -7
  159. package/dist/types/config.d.ts +1 -6
  160. package/dist/types/constants.d.ts +155 -21
  161. package/dist/types/controls-options-manager/enums.d.ts +11 -1
  162. package/dist/types/controls-options-manager/index.d.ts +17 -1
  163. package/dist/types/controls-options-manager/types.d.ts +43 -0
  164. package/dist/types/controls-options-manager/util.d.ts +1 -7
  165. package/dist/types/index.d.ts +6 -4
  166. package/dist/types/interpretation/collection.d.ts +5 -0
  167. package/dist/types/interpretation/index.d.ts +5 -0
  168. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  169. package/dist/types/locus-info/index.d.ts +57 -4
  170. package/dist/types/locus-info/parser.d.ts +65 -6
  171. package/dist/types/media/index.d.ts +2 -0
  172. package/dist/types/media/properties.d.ts +34 -48
  173. package/dist/types/meeting/in-meeting-actions.d.ts +82 -2
  174. package/dist/types/meeting/index.d.ts +344 -506
  175. package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
  176. package/dist/types/meeting/muteState.d.ts +99 -23
  177. package/dist/types/meeting/request.d.ts +72 -43
  178. package/dist/types/meeting/util.d.ts +101 -1
  179. package/dist/types/meeting-info/index.d.ts +13 -1
  180. package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
  181. package/dist/types/meetings/collection.d.ts +8 -0
  182. package/dist/types/meetings/index.d.ts +86 -12
  183. package/dist/types/meetings/meetings.types.d.ts +4 -0
  184. package/dist/types/member/index.d.ts +13 -0
  185. package/dist/types/member/types.d.ts +32 -0
  186. package/dist/types/members/collection.d.ts +5 -0
  187. package/dist/types/members/index.d.ts +35 -2
  188. package/dist/types/members/request.d.ts +73 -9
  189. package/dist/types/members/types.d.ts +24 -0
  190. package/dist/types/members/util.d.ts +209 -1
  191. package/dist/types/metrics/constants.d.ts +9 -4
  192. package/dist/types/metrics/index.d.ts +4 -119
  193. package/dist/types/multistream/mediaRequestManager.d.ts +73 -5
  194. package/dist/types/multistream/receiveSlot.d.ts +16 -12
  195. package/dist/types/multistream/receiveSlotManager.d.ts +19 -4
  196. package/dist/types/multistream/remoteMedia.d.ts +8 -29
  197. package/dist/types/multistream/remoteMediaGroup.d.ts +0 -9
  198. package/dist/types/multistream/remoteMediaManager.d.ts +46 -2
  199. package/dist/types/multistream/sendSlotManager.d.ts +61 -0
  200. package/dist/types/reachability/index.d.ts +44 -7
  201. package/dist/types/reachability/request.d.ts +7 -3
  202. package/dist/types/reconnection-manager/index.d.ts +9 -0
  203. package/dist/types/recording-controller/index.d.ts +15 -1
  204. package/dist/types/recording-controller/util.d.ts +5 -4
  205. package/dist/types/roap/request.d.ts +15 -11
  206. package/dist/types/roap/turnDiscovery.d.ts +18 -1
  207. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  208. package/dist/types/rtcMetrics/index.d.ts +47 -0
  209. package/dist/types/statsAnalyzer/index.d.ts +6 -1
  210. package/package.json +23 -20
  211. package/src/annotation/annotation.types.ts +50 -0
  212. package/src/annotation/constants.ts +36 -0
  213. package/src/annotation/index.ts +328 -0
  214. package/src/breakouts/README.md +44 -14
  215. package/src/breakouts/breakout.ts +87 -9
  216. package/src/breakouts/edit-lock-error.ts +25 -0
  217. package/src/breakouts/events.ts +56 -0
  218. package/src/breakouts/index.ts +710 -10
  219. package/src/breakouts/request.ts +55 -0
  220. package/src/breakouts/utils.ts +57 -0
  221. package/src/common/errors/webex-errors.ts +27 -2
  222. package/src/common/logs/logger-proxy.ts +1 -1
  223. package/src/common/queue.ts +22 -8
  224. package/src/config.ts +4 -9
  225. package/src/constants.ts +178 -18
  226. package/src/controls-options-manager/enums.ts +12 -0
  227. package/src/controls-options-manager/index.ts +116 -21
  228. package/src/controls-options-manager/types.ts +59 -0
  229. package/src/controls-options-manager/util.ts +294 -14
  230. package/src/index.ts +40 -0
  231. package/src/interpretation/README.md +60 -0
  232. package/src/interpretation/collection.ts +19 -0
  233. package/src/interpretation/index.ts +332 -0
  234. package/src/interpretation/siLanguage.ts +18 -0
  235. package/src/locus-info/controlsUtils.ts +108 -0
  236. package/src/locus-info/index.ts +412 -59
  237. package/src/locus-info/infoUtils.ts +10 -2
  238. package/src/locus-info/mediaSharesUtils.ts +48 -0
  239. package/src/locus-info/parser.ts +231 -39
  240. package/src/locus-info/selfUtils.ts +81 -5
  241. package/src/media/index.ts +100 -122
  242. package/src/media/properties.ts +70 -108
  243. package/src/meeting/in-meeting-actions.ts +163 -3
  244. package/src/meeting/index.ts +2471 -2306
  245. package/src/meeting/locusMediaRequest.ts +313 -0
  246. package/src/meeting/muteState.ts +229 -131
  247. package/src/meeting/request.ts +172 -121
  248. package/src/meeting/util.ts +588 -394
  249. package/src/meeting-info/index.ts +79 -8
  250. package/src/meeting-info/meeting-info-v2.ts +168 -14
  251. package/src/meeting-info/util.ts +1 -1
  252. package/src/meeting-info/utilv2.ts +23 -23
  253. package/src/meetings/collection.ts +20 -0
  254. package/src/meetings/index.ts +414 -108
  255. package/src/meetings/meetings.types.ts +12 -0
  256. package/src/meetings/request.ts +2 -0
  257. package/src/meetings/util.ts +103 -4
  258. package/src/member/index.ts +49 -0
  259. package/src/member/types.ts +38 -0
  260. package/src/member/util.ts +127 -25
  261. package/src/members/collection.ts +8 -0
  262. package/src/members/index.ts +107 -6
  263. package/src/members/request.ts +97 -17
  264. package/src/members/types.ts +28 -0
  265. package/src/members/util.ts +319 -240
  266. package/src/metrics/constants.ts +9 -4
  267. package/src/metrics/index.ts +1 -490
  268. package/src/multistream/mediaRequestManager.ts +289 -79
  269. package/src/multistream/receiveSlot.ts +55 -18
  270. package/src/multistream/receiveSlotManager.ts +46 -24
  271. package/src/multistream/remoteMedia.ts +27 -2
  272. package/src/multistream/remoteMediaGroup.ts +59 -0
  273. package/src/multistream/remoteMediaManager.ts +148 -30
  274. package/src/multistream/sendSlotManager.ts +170 -0
  275. package/src/reachability/index.ts +165 -37
  276. package/src/reachability/request.ts +17 -8
  277. package/src/reconnection-manager/index.ts +81 -54
  278. package/src/recording-controller/index.ts +20 -3
  279. package/src/recording-controller/util.ts +26 -9
  280. package/src/roap/index.ts +23 -30
  281. package/src/roap/request.ts +100 -104
  282. package/src/roap/turnDiscovery.ts +51 -25
  283. package/src/rtcMetrics/constants.ts +3 -0
  284. package/src/rtcMetrics/index.ts +100 -0
  285. package/src/statsAnalyzer/index.ts +73 -35
  286. package/src/statsAnalyzer/mqaUtil.ts +8 -10
  287. package/test/integration/spec/converged-space-meetings.js +233 -0
  288. package/test/integration/spec/journey.js +320 -261
  289. package/test/integration/spec/space-meeting.js +76 -3
  290. package/test/unit/spec/annotation/index.ts +418 -0
  291. package/test/unit/spec/breakouts/breakout.ts +142 -24
  292. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  293. package/test/unit/spec/breakouts/events.ts +89 -0
  294. package/test/unit/spec/breakouts/index.ts +1545 -48
  295. package/test/unit/spec/breakouts/request.ts +104 -0
  296. package/test/unit/spec/breakouts/utils.js +72 -0
  297. package/test/unit/spec/common/queue.js +31 -2
  298. package/test/unit/spec/controls-options-manager/index.js +163 -0
  299. package/test/unit/spec/controls-options-manager/util.js +576 -60
  300. package/test/unit/spec/fixture/locus.js +1 -0
  301. package/test/unit/spec/interpretation/collection.ts +15 -0
  302. package/test/unit/spec/interpretation/index.ts +589 -0
  303. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  304. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  305. package/test/unit/spec/locus-info/index.js +1283 -33
  306. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  307. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  308. package/test/unit/spec/locus-info/parser.js +62 -22
  309. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  310. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  311. package/test/unit/spec/media/index.ts +104 -37
  312. package/test/unit/spec/meeting/in-meeting-actions.ts +81 -3
  313. package/test/unit/spec/meeting/index.js +4095 -1913
  314. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  315. package/test/unit/spec/meeting/muteState.js +408 -208
  316. package/test/unit/spec/meeting/request.js +440 -45
  317. package/test/unit/spec/meeting/utils.js +679 -64
  318. package/test/unit/spec/meeting-info/index.js +293 -0
  319. package/test/unit/spec/meeting-info/meetinginfov2.js +517 -5
  320. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  321. package/test/unit/spec/meetings/collection.js +14 -0
  322. package/test/unit/spec/meetings/index.js +941 -151
  323. package/test/unit/spec/meetings/utils.js +206 -2
  324. package/test/unit/spec/member/index.js +58 -4
  325. package/test/unit/spec/member/util.js +479 -35
  326. package/test/unit/spec/members/index.js +319 -1
  327. package/test/unit/spec/members/request.js +206 -27
  328. package/test/unit/spec/members/utils.js +184 -0
  329. package/test/unit/spec/metrics/index.js +1 -50
  330. package/test/unit/spec/multistream/mediaRequestManager.ts +803 -162
  331. package/test/unit/spec/multistream/receiveSlot.ts +72 -13
  332. package/test/unit/spec/multistream/receiveSlotManager.ts +58 -28
  333. package/test/unit/spec/multistream/remoteMedia.ts +30 -0
  334. package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
  335. package/test/unit/spec/multistream/remoteMediaManager.ts +326 -0
  336. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  337. package/test/unit/spec/reachability/index.ts +343 -9
  338. package/test/unit/spec/reachability/request.js +68 -0
  339. package/test/unit/spec/reconnection-manager/index.js +84 -9
  340. package/test/unit/spec/recording-controller/index.js +294 -218
  341. package/test/unit/spec/recording-controller/util.js +223 -96
  342. package/test/unit/spec/roap/index.ts +31 -51
  343. package/test/unit/spec/roap/request.ts +203 -85
  344. package/test/unit/spec/roap/turnDiscovery.ts +48 -13
  345. package/test/unit/spec/rtcMetrics/index.ts +68 -0
  346. package/test/unit/spec/stats-analyzer/index.js +29 -2
  347. package/test/utils/constants.js +9 -0
  348. package/test/utils/integrationTestUtils.js +46 -0
  349. package/test/utils/testUtils.js +0 -45
  350. package/test/utils/webex-config.js +4 -0
  351. package/test/utils/webex-test-users.js +6 -3
  352. package/dist/meeting/effectsState.js +0 -262
  353. package/dist/meeting/effectsState.js.map +0 -1
  354. package/dist/metrics/config.js +0 -299
  355. package/dist/metrics/config.js.map +0 -1
  356. package/dist/types/meeting/effectsState.d.ts +0 -42
  357. package/dist/types/metrics/config.d.ts +0 -178
  358. package/src/index.js +0 -16
  359. package/src/meeting/effectsState.ts +0 -211
  360. package/src/metrics/config.ts +0 -495
  361. package/test/unit/spec/meeting/effectsState.js +0 -285
@@ -28,6 +28,7 @@ import {
28
28
  getVideoSenderMqa,
29
29
  getVideoReceiverMqa,
30
30
  } from './mqaUtil';
31
+ import {ReceiveSlot} from '../multistream/receiveSlot';
31
32
 
32
33
  export const EVENTS = {
33
34
  MEDIA_QUALITY: 'MEDIA_QUALITY',
@@ -53,6 +54,8 @@ const emptyReceiver = {
53
54
  meanRoundTripTime: [],
54
55
  };
55
56
 
57
+ type ReceiveSlotCallback = (csi: number) => ReceiveSlot | undefined;
58
+
56
59
  /**
57
60
  * Stats Analyzer class that will emit events based on detected quality
58
61
  *
@@ -74,17 +77,20 @@ export class StatsAnalyzer extends EventsScope {
74
77
  statsInterval: NodeJS.Timeout;
75
78
  statsResults: any;
76
79
  statsStarted: any;
80
+ receiveSlotCallback: ReceiveSlotCallback;
77
81
 
78
82
  /**
79
83
  * Creates a new instance of StatsAnalyzer
80
84
  * @constructor
81
85
  * @public
82
86
  * @param {Object} config SDK Configuration Object
87
+ * @param {Function} receiveSlotCallback Callback used to access receive slots.
83
88
  * @param {Object} networkQualityMonitor class for assessing network characteristics (jitter, packetLoss, latency)
84
89
  * @param {Object} statsResults Default properties for stats
85
90
  */
86
91
  constructor(
87
92
  config: any,
93
+ receiveSlotCallback: ReceiveSlotCallback = () => undefined,
88
94
  networkQualityMonitor: object = {},
89
95
  statsResults: object = defaultStats
90
96
  ) {
@@ -98,6 +104,7 @@ export class StatsAnalyzer extends EventsScope {
98
104
  this.mqaSentCount = -1;
99
105
  this.lastMqaDataSent = {};
100
106
  this.lastEmittedStartStopEvent = {};
107
+ this.receiveSlotCallback = receiveSlotCallback;
101
108
  }
102
109
 
103
110
  /**
@@ -293,7 +300,6 @@ export class StatsAnalyzer extends EventsScope {
293
300
  this.mediaConnection = null;
294
301
  });
295
302
  }
296
- this.mediaConnection = null;
297
303
 
298
304
  return Promise.resolve();
299
305
  }
@@ -492,23 +498,23 @@ export class StatsAnalyzer extends EventsScope {
492
498
  const getCurrentStatsTotals = (keyPrefix: string, value: string): number =>
493
499
  Object.keys(this.statsResults)
494
500
  .filter((key) => key.startsWith(keyPrefix))
495
- .reduce((prev, cur) => prev + (this.statsResults[cur].recv[value] || 0), 0);
501
+ .reduce((prev, cur) => prev + (this.statsResults[cur]?.recv[value] || 0), 0);
496
502
 
497
503
  const getPreviousStatsTotals = (keyPrefix: string, value: string): number =>
498
504
  Object.keys(this.statsResults)
499
505
  .filter((key) => key.startsWith(keyPrefix))
500
- .reduce((prev, cur) => prev + (this.lastStatsResults[cur].recv[value] || 0), 0);
506
+ .reduce((prev, cur) => prev + (this.lastStatsResults[cur]?.recv[value] || 0), 0);
501
507
 
502
508
  const getCurrentResolutionsStatsTotals = (keyPrefix: string, value: string): number =>
503
509
  Object.keys(this.statsResults)
504
510
  .filter((key) => key.startsWith(keyPrefix))
505
- .reduce((prev, cur) => prev + (this.statsResults.resolutions[cur].recv[value] || 0), 0);
511
+ .reduce((prev, cur) => prev + (this.statsResults.resolutions[cur]?.recv[value] || 0), 0);
506
512
 
507
513
  const getPreviousResolutionsStatsTotals = (keyPrefix: string, value: string): number =>
508
514
  Object.keys(this.statsResults)
509
515
  .filter((key) => key.startsWith(keyPrefix))
510
516
  .reduce(
511
- (prev, cur) => prev + (this.lastStatsResults.resolutions[cur].recv[value] || 0),
517
+ (prev, cur) => prev + (this.lastStatsResults.resolutions[cur]?.recv[value] || 0),
512
518
  0
513
519
  );
514
520
 
@@ -523,7 +529,8 @@ export class StatsAnalyzer extends EventsScope {
523
529
  currentStats.totalPacketsSent === 0
524
530
  ) {
525
531
  LoggerProxy.logger.info(
526
- `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent`
532
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent`,
533
+ currentStats.totalPacketsSent
527
534
  );
528
535
  } else {
529
536
  if (
@@ -531,7 +538,8 @@ export class StatsAnalyzer extends EventsScope {
531
538
  currentStats.totalAudioEnergy === 0
532
539
  ) {
533
540
  LoggerProxy.logger.info(
534
- `StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present`
541
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present`,
542
+ currentStats.totalAudioEnergy
535
543
  );
536
544
  }
537
545
 
@@ -565,14 +573,16 @@ export class StatsAnalyzer extends EventsScope {
565
573
 
566
574
  if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
567
575
  LoggerProxy.logger.info(
568
- `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received`
576
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received`,
577
+ currentPacketsReceived
569
578
  );
570
579
  } else if (
571
580
  currentSamplesReceived === previousSamplesReceived ||
572
581
  currentSamplesReceived === 0
573
582
  ) {
574
583
  LoggerProxy.logger.info(
575
- `StatsAnalyzer:index#compareLastStatsResult --> No audio samples received`
584
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio samples received`,
585
+ currentSamplesReceived
576
586
  );
577
587
  }
578
588
 
@@ -589,7 +599,8 @@ export class StatsAnalyzer extends EventsScope {
589
599
  currentStats.totalPacketsSent === 0
590
600
  ) {
591
601
  LoggerProxy.logger.info(
592
- `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent`
602
+ `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent`,
603
+ currentStats.totalPacketsSent
593
604
  );
594
605
  } else {
595
606
  if (
@@ -597,7 +608,8 @@ export class StatsAnalyzer extends EventsScope {
597
608
  currentStats.framesEncoded === 0
598
609
  ) {
599
610
  LoggerProxy.logger.info(
600
- `StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded`
611
+ `StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded`,
612
+ currentStats.framesEncoded
601
613
  );
602
614
  }
603
615
 
@@ -607,7 +619,8 @@ export class StatsAnalyzer extends EventsScope {
607
619
  this.statsResults.resolutions['video-send'].send.framesSent === 0
608
620
  ) {
609
621
  LoggerProxy.logger.info(
610
- `StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent`
622
+ `StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent`,
623
+ this.statsResults.resolutions['video-send'].send.framesSent
611
624
  );
612
625
  }
613
626
  }
@@ -643,24 +656,28 @@ export class StatsAnalyzer extends EventsScope {
643
656
 
644
657
  if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
645
658
  LoggerProxy.logger.info(
646
- `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets received`
659
+ `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets received`,
660
+ currentPacketsReceived
647
661
  );
648
662
  } else {
649
663
  if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {
650
664
  LoggerProxy.logger.info(
651
- `StatsAnalyzer:index#compareLastStatsResult --> No video frames received`
665
+ `StatsAnalyzer:index#compareLastStatsResult --> No video frames received`,
666
+ currentFramesReceived
652
667
  );
653
668
  }
654
669
 
655
670
  if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {
656
671
  LoggerProxy.logger.info(
657
- `StatsAnalyzer:index#compareLastStatsResult --> No video frames decoded`
672
+ `StatsAnalyzer:index#compareLastStatsResult --> No video frames decoded`,
673
+ currentFramesDecoded
658
674
  );
659
675
  }
660
676
 
661
677
  if (currentFramesDropped - previousFramesDropped > 10) {
662
678
  LoggerProxy.logger.info(
663
- `StatsAnalyzer:index#compareLastStatsResult --> video frames are getting dropped`
679
+ `StatsAnalyzer:index#compareLastStatsResult --> video frames are getting dropped`,
680
+ currentFramesDropped - previousFramesDropped
664
681
  );
665
682
  }
666
683
  }
@@ -679,7 +696,8 @@ export class StatsAnalyzer extends EventsScope {
679
696
  currentStats.totalPacketsSent === 0
680
697
  ) {
681
698
  LoggerProxy.logger.info(
682
- `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent`
699
+ `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent`,
700
+ currentStats.totalPacketsSent
683
701
  );
684
702
  } else {
685
703
  if (
@@ -687,7 +705,8 @@ export class StatsAnalyzer extends EventsScope {
687
705
  currentStats.framesEncoded === 0
688
706
  ) {
689
707
  LoggerProxy.logger.info(
690
- `StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded`
708
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded`,
709
+ currentStats.framesEncoded
691
710
  );
692
711
  }
693
712
 
@@ -697,7 +716,8 @@ export class StatsAnalyzer extends EventsScope {
697
716
  this.statsResults.resolutions['video-share-send'].send.framesSent === 0
698
717
  ) {
699
718
  LoggerProxy.logger.info(
700
- `StatsAnalyzer:index#compareLastStatsResult --> No share frames sent`
719
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames sent`,
720
+ this.statsResults.resolutions['video-share-send'].send.framesSent
701
721
  );
702
722
  }
703
723
  }
@@ -735,24 +755,28 @@ export class StatsAnalyzer extends EventsScope {
735
755
 
736
756
  if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
737
757
  LoggerProxy.logger.info(
738
- `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets received`
758
+ `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets received`,
759
+ currentPacketsReceived
739
760
  );
740
761
  } else {
741
762
  if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {
742
763
  LoggerProxy.logger.info(
743
- `StatsAnalyzer:index#compareLastStatsResult --> No share frames received`
764
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames received`,
765
+ currentFramesReceived
744
766
  );
745
767
  }
746
768
 
747
769
  if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {
748
770
  LoggerProxy.logger.info(
749
- `StatsAnalyzer:index#compareLastStatsResult --> No share frames decoded`
771
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames decoded`,
772
+ currentFramesDecoded
750
773
  );
751
774
  }
752
775
 
753
776
  if (currentFramesDropped - previousFramesDropped > 10) {
754
777
  LoggerProxy.logger.info(
755
- `StatsAnalyzer:index#compareLastStatsResult --> share frames are getting dropped`
778
+ `StatsAnalyzer:index#compareLastStatsResult --> share frames are getting dropped`,
779
+ currentFramesDropped - previousFramesDropped
756
780
  );
757
781
  }
758
782
  }
@@ -853,6 +877,14 @@ export class StatsAnalyzer extends EventsScope {
853
877
  if (result.bytesSent) {
854
878
  let kilobytes = 0;
855
879
 
880
+ if (result.frameWidth && result.frameHeight) {
881
+ this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;
882
+ this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;
883
+ this.statsResults.resolutions[mediaType][sendrecvType].framesSent = result.framesSent;
884
+ this.statsResults.resolutions[mediaType][sendrecvType].hugeFramesSent =
885
+ result.hugeFramesSent;
886
+ }
887
+
856
888
  if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesSent) {
857
889
  this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;
858
890
  }
@@ -925,6 +957,17 @@ export class StatsAnalyzer extends EventsScope {
925
957
 
926
958
  if (result.bytesReceived) {
927
959
  let kilobytes = 0;
960
+ const receiveSlot = this.receiveSlotCallback(result.ssrc);
961
+ const idAndCsi = receiveSlot
962
+ ? `id: "${receiveSlot.id || ''}"${receiveSlot.csi ? ` and csi: ${receiveSlot.csi}` : ''}`
963
+ : '';
964
+
965
+ if (result.frameWidth && result.frameHeight) {
966
+ this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;
967
+ this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;
968
+ this.statsResults.resolutions[mediaType][sendrecvType].framesReceived =
969
+ result.framesReceived;
970
+ }
928
971
 
929
972
  if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived) {
930
973
  this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived =
@@ -974,10 +1017,12 @@ export class StatsAnalyzer extends EventsScope {
974
1017
  result.packetsReceived;
975
1018
 
976
1019
  if (this.statsResults[mediaType][sendrecvType].packetsReceived === 0) {
977
- LoggerProxy.logger.info(
978
- `StatsAnalyzer:index#processInboundRTPResult --> No packets received for ${mediaType} `,
979
- this.statsResults[mediaType][sendrecvType].packetsReceived
980
- );
1020
+ if (receiveSlot) {
1021
+ LoggerProxy.logger.info(
1022
+ `StatsAnalyzer:index#processInboundRTPResult --> No packets received for receive slot ${idAndCsi}`,
1023
+ this.statsResults[mediaType][sendrecvType].packetsReceived
1024
+ );
1025
+ }
981
1026
  }
982
1027
 
983
1028
  // Check the over all packet Lost ratio
@@ -989,7 +1034,7 @@ export class StatsAnalyzer extends EventsScope {
989
1034
  : 0;
990
1035
  if (this.statsResults[mediaType][sendrecvType].currentPacketLossRatio > 3) {
991
1036
  LoggerProxy.logger.info(
992
- 'StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver ',
1037
+ `StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver with slot ${idAndCsi}`,
993
1038
  this.statsResults[mediaType][sendrecvType].currentPacketLossRatio
994
1039
  );
995
1040
  }
@@ -1137,13 +1182,6 @@ export class StatsAnalyzer extends EventsScope {
1137
1182
  const sendrecvType =
1138
1183
  result.remoteSource === true ? STATS.RECEIVE_DIRECTION : STATS.SEND_DIRECTION;
1139
1184
 
1140
- if (result.frameWidth && result.frameHeight) {
1141
- this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;
1142
- this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;
1143
- this.statsResults.resolutions[mediaType][sendrecvType].framesSent = result.framesSent;
1144
- this.statsResults.resolutions[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;
1145
- }
1146
-
1147
1185
  if (sendrecvType === STATS.RECEIVE_DIRECTION) {
1148
1186
  this.statsResults.resolutions[mediaType][sendrecvType].framesReceived = result.framesReceived;
1149
1187
  this.statsResults.resolutions[mediaType][sendrecvType].framesDecoded = result.framesDecoded;
@@ -199,12 +199,11 @@ export const getVideoReceiverMqa = ({videoReceiver, statsResults, lastMqaDataSen
199
199
  videoReceiver.streams[0].common.framesDropped =
200
200
  statsResults.resolutions[mediaType][sendrecvType].framesDropped - lastFramesDropped;
201
201
  videoReceiver.streams[0].receivedHeight =
202
- statsResults.resolutions[mediaType][sendrecvType].height;
203
- videoReceiver.streams[0].receivedWidth = statsResults.resolutions[mediaType][sendrecvType].width;
202
+ statsResults.resolutions[mediaType][sendrecvType].height || 0;
203
+ videoReceiver.streams[0].receivedWidth =
204
+ statsResults.resolutions[mediaType][sendrecvType].width || 0;
204
205
  videoReceiver.streams[0].receivedFrameSize =
205
- (statsResults.resolutions[mediaType][sendrecvType].height *
206
- statsResults.resolutions[mediaType][sendrecvType].height) /
207
- 256;
206
+ (videoReceiver.streams[0].receivedHeight * videoReceiver.streams[0].receivedWidth) / 256;
208
207
 
209
208
  videoReceiver.streams[0].receivedKeyFrames =
210
209
  statsResults[mediaType][sendrecvType].keyFramesDecoded - lastKeyFramesDecoded || 0;
@@ -284,10 +283,9 @@ export const getVideoSenderMqa = ({videoSender, statsResults, lastMqaDataSent, m
284
283
  ? (totalFrameSentInaMin * 100) / 60
285
284
  : 0;
286
285
  videoSender.streams[0].transmittedHeight =
287
- statsResults.resolutions[mediaType][sendrecvType].height;
288
- videoSender.streams[0].transmittedWidth = statsResults.resolutions[mediaType][sendrecvType].width;
286
+ statsResults.resolutions[mediaType][sendrecvType].height || 0;
287
+ videoSender.streams[0].transmittedWidth =
288
+ statsResults.resolutions[mediaType][sendrecvType].width || 0;
289
289
  videoSender.streams[0].transmittedFrameSize =
290
- (statsResults.resolutions[mediaType][sendrecvType].height *
291
- statsResults.resolutions[mediaType][sendrecvType].width) /
292
- 254;
290
+ (videoSender.streams[0].transmittedHeight * videoSender.streams[0].transmittedWidth) / 256;
293
291
  };
@@ -0,0 +1,233 @@
1
+ import { config } from 'dotenv';
2
+ import 'jsdom-global/register';
3
+ import {assert} from '@webex/test-helper-chai';
4
+ import {skipInNode} from '@webex/test-helper-mocha';
5
+ import BrowserDetection from '@webex/plugin-meetings/dist/common/browser-detection';
6
+ import {createCameraStream, createMicrophoneStream} from '@webex/plugin-meetings';
7
+
8
+ import {MEDIA_SERVERS} from '../../utils/constants';
9
+ import testUtils from '../../utils/testUtils';
10
+ import integrationTestUtils from '../../utils/integrationTestUtils';
11
+ import webexTestUsers from '../../utils/webex-test-users';
12
+
13
+ config();
14
+
15
+ const localTracks = {
16
+ alice: {
17
+ microphone: undefined,
18
+ camera: undefined,
19
+ },
20
+ bob: {
21
+ microphone: undefined,
22
+ camera: undefined,
23
+ },
24
+ chris: {
25
+ microphone: undefined,
26
+ camera: undefined,
27
+ },
28
+ };
29
+
30
+ skipInNode(describe)('plugin-meetings', () => {
31
+ const {isBrowser} = BrowserDetection();
32
+
33
+ // `addMedia()` fails on FF, this needs to be debuged and fixed in a later change
34
+ if (!isBrowser('firefox')) {
35
+ describe('converged-space-meeting', () => {
36
+ let shouldSkip = false;
37
+ let users, alice, bob, chris;
38
+ let meeting = null;
39
+ let space = null;
40
+ let mediaReadyListener = null;
41
+
42
+ before('setup users', async () => {
43
+ const userSet = await webexTestUsers.generateTestUsers({
44
+ count: 3,
45
+ whistler: process.env.WHISTLER || process.env.JENKINS,
46
+ config
47
+ });
48
+
49
+ users = userSet;
50
+ alice = users[0];
51
+ bob = users[1];
52
+ chris = users[2];
53
+ alice.name = 'alice';
54
+ bob.name = 'bob';
55
+ chris.name = 'chris';
56
+
57
+ const aliceSync = testUtils.syncAndEndMeeting(alice);
58
+ const bobSync = testUtils.syncAndEndMeeting(bob);
59
+ const chrisSync = testUtils.syncAndEndMeeting(chris);
60
+
61
+ await aliceSync;
62
+ await bobSync;
63
+ await chrisSync;
64
+ });
65
+
66
+ // Skip a test in this series if one failed.
67
+ // This beforeEach() instance function must use the `function` declaration to preserve the
68
+ // `this` context. `() => {}` will not generate the correct `this` context
69
+ beforeEach('check if should skip test', function() {
70
+ if (shouldSkip) {
71
+ this.skip();
72
+ }
73
+ });
74
+
75
+ // Store to the describe scope if a test has failed for skipping.
76
+ // This beforeEach() instance function must use the `function` declaration to preserve the
77
+ // `this` context. `() => {}` will not generate the correct `this` context
78
+ afterEach('check if test failed', function() {
79
+ if (this.currentTest.state === 'failed') {
80
+ shouldSkip = true;
81
+ }
82
+ });
83
+
84
+ it('user "alice" starts a space', async () => {
85
+ const conversation = await alice.webex.internal.conversation.create({
86
+ participants: [bob, chris],
87
+ });
88
+
89
+ assert.lengthOf(conversation.participants.items, 3);
90
+ assert.lengthOf(conversation.activities.items, 1);
91
+
92
+ space = conversation;
93
+
94
+ const destinationWithType = await alice.webex.meetings.meetingInfo.fetchMeetingInfo(space.url, 'CONVERSATION_URL');
95
+ const destinationWithoutType = await alice.webex.meetings.meetingInfo.fetchMeetingInfo(space.url);
96
+
97
+ assert.exists(destinationWithoutType);
98
+ assert.exists(destinationWithType);
99
+ assert.exists(destinationWithoutType.body.meetingNumber);
100
+ assert.exists(destinationWithType.body.meetingNumber);
101
+ });
102
+
103
+ it('user "alice" starts a meeting', async () => {
104
+ const wait = testUtils.waitForEvents([{
105
+ scope: alice.webex.meetings,
106
+ event: 'meeting:added',
107
+ user: alice,
108
+ }]);
109
+
110
+ const createdMeeting = await testUtils.delayedPromise(alice.webex.meetings.create(space.url));
111
+
112
+ await wait;
113
+
114
+ assert.exists(createdMeeting);
115
+
116
+ meeting = createdMeeting;
117
+ });
118
+
119
+ it('user "alice" joins the meeting', async () => {
120
+ const wait = testUtils.waitForEvents([
121
+ {scope: bob.webex.meetings, event: 'meeting:added', user: bob},
122
+ {scope: chris.webex.meetings, event: 'meeting:added', user: chris},
123
+ ]);
124
+
125
+ await testUtils.delayedPromise(alice.meeting.join({enableMultistream: true}));
126
+
127
+ await wait;
128
+
129
+ assert.isTrue(!!alice.webex.meetings.meetingCollection.meetings[meeting.id].joinedWith);
130
+ });
131
+
132
+ it('users "bob" and "chris" join the meeting', async () => {
133
+ await testUtils.waitForStateChange(alice.meeting, 'JOINED');
134
+
135
+ const bobIdle = testUtils.waitForStateChange(bob.meeting, 'IDLE');
136
+ const chrisIdle = testUtils.waitForStateChange(chris.meeting, 'IDLE');
137
+
138
+ await bobIdle;
139
+ await chrisIdle;
140
+
141
+ const bobJoined = testUtils.waitForStateChange(bob.meeting, 'JOINED');
142
+ const chrisJoined = testUtils.waitForStateChange(chris.meeting, 'JOINED');
143
+ const bobJoin = bob.meeting.join({enableMultistream: true});
144
+ const chrisJoin = chris.meeting.join({enableMultistream: true});
145
+
146
+ await bobJoin;
147
+ await chrisJoin;
148
+ await bobJoined;
149
+ await chrisJoined;
150
+
151
+ assert.exists(bob.meeting.joinedWith);
152
+ assert.exists(chris.meeting.joinedWith);
153
+ });
154
+
155
+ it('users "alice", "bob", and "chris" create local tracks', async () => {
156
+ localTracks.alice.microphone = await createMicrophoneStream();
157
+ localTracks.alice.camera = await createCameraStream();
158
+
159
+ localTracks.bob.microphone = await createMicrophoneStream();
160
+ localTracks.bob.camera = await createCameraStream();
161
+
162
+ localTracks.chris.microphone = await createMicrophoneStream();
163
+ localTracks.chris.camera = await createCameraStream();
164
+ });
165
+
166
+ it('users "alice", "bob", and "chris" add media', async () => {
167
+ mediaReadyListener = testUtils.waitForEvents([
168
+ {scope: alice.meeting, event: 'media:negotiated'},
169
+ {scope: bob.meeting, event: 'media:negotiated'},
170
+ {scope: chris.meeting, event: 'media:negotiated'},
171
+ ]);
172
+
173
+ const addMediaAlice = integrationTestUtils.addMedia(alice, {multistream: true, microphone: localTracks.alice.microphone, camera: localTracks.alice.camera});
174
+ const addMediaBob = integrationTestUtils.addMedia(bob, {multistream: true, microphone: localTracks.bob.microphone, camera: localTracks.bob.camera});
175
+ const addMediaChris = integrationTestUtils.addMedia(chris, {multistream: true, microphone: localTracks.chris.microphone, camera: localTracks.chris.camera});
176
+
177
+ await addMediaAlice;
178
+ await addMediaBob;
179
+ await addMediaChris;
180
+
181
+ assert.isTrue(alice.meeting.mediaProperties.mediaDirection.sendAudio);
182
+ assert.isTrue(alice.meeting.mediaProperties.mediaDirection.sendVideo);
183
+ assert.isTrue(alice.meeting.mediaProperties.mediaDirection.receiveAudio);
184
+ assert.isTrue(alice.meeting.mediaProperties.mediaDirection.receiveVideo);
185
+ assert.isTrue(bob.meeting.mediaProperties.mediaDirection.sendAudio);
186
+ assert.isTrue(bob.meeting.mediaProperties.mediaDirection.sendVideo);
187
+ assert.isTrue(bob.meeting.mediaProperties.mediaDirection.receiveAudio);
188
+ assert.isTrue(bob.meeting.mediaProperties.mediaDirection.receiveVideo);
189
+ assert.isTrue(chris.meeting.mediaProperties.mediaDirection.sendAudio);
190
+ assert.isTrue(chris.meeting.mediaProperties.mediaDirection.sendVideo);
191
+ assert.isTrue(chris.meeting.mediaProperties.mediaDirection.receiveAudio);
192
+ assert.isTrue(chris.meeting.mediaProperties.mediaDirection.receiveVideo);
193
+ });
194
+
195
+ it(`users "alice", "bob", and "chris" should be using the "${MEDIA_SERVERS.HOMER}" media server`, async () => {
196
+ await mediaReadyListener;
197
+
198
+ assert.equal(alice.meeting.mediaProperties.webrtcMediaConnection.mediaServer, MEDIA_SERVERS.HOMER);
199
+ assert.equal(bob.meeting.mediaProperties.webrtcMediaConnection.mediaServer, MEDIA_SERVERS.HOMER);
200
+ assert.equal(chris.meeting.mediaProperties.webrtcMediaConnection.mediaServer, MEDIA_SERVERS.HOMER);
201
+ });
202
+
203
+ it('users "alice", "bob", and "chris" stop their local tracks', () => {
204
+ if (localTracks.alice.microphone) {
205
+ localTracks.alice.microphone.stop();
206
+ localTracks.alice.microphone = undefined;
207
+ }
208
+ if (localTracks.alice.camera) {
209
+ localTracks.alice.camera.stop();
210
+ localTracks.alice.camera = undefined;
211
+ }
212
+
213
+ if (localTracks.bob.microphone) {
214
+ localTracks.bob.microphone.stop();
215
+ localTracks.bob.microphone = undefined;
216
+ }
217
+ if (localTracks.bob.camera) {
218
+ localTracks.bob.camera.stop();
219
+ localTracks.bob.camera = undefined;
220
+ }
221
+
222
+ if (localTracks.chris.microphone) {
223
+ localTracks.chris.microphone.stop();
224
+ localTracks.chris.microphone = undefined;
225
+ }
226
+ if (localTracks.chris.camera) {
227
+ localTracks.chris.camera.stop();
228
+ localTracks.chris.camera = undefined;
229
+ }
230
+ });
231
+ });
232
+ }
233
+ });