@webex/plugin-meetings 3.0.0-beta.28 → 3.0.0-beta.280

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 (363) 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 +763 -31
  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/no-meeting-info.js +51 -0
  21. package/dist/common/errors/no-meeting-info.js.map +1 -0
  22. package/dist/common/errors/webex-errors.js +28 -7
  23. package/dist/common/errors/webex-errors.js.map +1 -1
  24. package/dist/common/logs/logger-proxy.js +1 -1
  25. package/dist/common/logs/logger-proxy.js.map +1 -1
  26. package/dist/common/queue.js +24 -9
  27. package/dist/common/queue.js.map +1 -1
  28. package/dist/config.js +5 -10
  29. package/dist/config.js.map +1 -1
  30. package/dist/constants.js +203 -28
  31. package/dist/constants.js.map +1 -1
  32. package/dist/controls-options-manager/enums.js +14 -2
  33. package/dist/controls-options-manager/enums.js.map +1 -1
  34. package/dist/controls-options-manager/index.js +109 -15
  35. package/dist/controls-options-manager/index.js.map +1 -1
  36. package/dist/controls-options-manager/types.js +7 -0
  37. package/dist/controls-options-manager/types.js.map +1 -0
  38. package/dist/controls-options-manager/util.js +309 -18
  39. package/dist/controls-options-manager/util.js.map +1 -1
  40. package/dist/index.js +112 -1
  41. package/dist/index.js.map +1 -1
  42. package/dist/interpretation/collection.js +23 -0
  43. package/dist/interpretation/collection.js.map +1 -0
  44. package/dist/interpretation/index.js +366 -0
  45. package/dist/interpretation/index.js.map +1 -0
  46. package/dist/interpretation/siLanguage.js +25 -0
  47. package/dist/interpretation/siLanguage.js.map +1 -0
  48. package/dist/locus-info/controlsUtils.js +91 -2
  49. package/dist/locus-info/controlsUtils.js.map +1 -1
  50. package/dist/locus-info/index.js +383 -62
  51. package/dist/locus-info/index.js.map +1 -1
  52. package/dist/locus-info/infoUtils.js +7 -1
  53. package/dist/locus-info/infoUtils.js.map +1 -1
  54. package/dist/locus-info/mediaSharesUtils.js +57 -1
  55. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  56. package/dist/locus-info/parser.js +249 -72
  57. package/dist/locus-info/parser.js.map +1 -1
  58. package/dist/locus-info/selfUtils.js +89 -14
  59. package/dist/locus-info/selfUtils.js.map +1 -1
  60. package/dist/media/index.js +58 -116
  61. package/dist/media/index.js.map +1 -1
  62. package/dist/media/properties.js +72 -123
  63. package/dist/media/properties.js.map +1 -1
  64. package/dist/meeting/in-meeting-actions.js +82 -2
  65. package/dist/meeting/in-meeting-actions.js.map +1 -1
  66. package/dist/meeting/index.js +3123 -2814
  67. package/dist/meeting/index.js.map +1 -1
  68. package/dist/meeting/locusMediaRequest.js +292 -0
  69. package/dist/meeting/locusMediaRequest.js.map +1 -0
  70. package/dist/meeting/muteState.js +230 -124
  71. package/dist/meeting/muteState.js.map +1 -1
  72. package/dist/meeting/request.js +256 -196
  73. package/dist/meeting/request.js.map +1 -1
  74. package/dist/meeting/util.js +601 -417
  75. package/dist/meeting/util.js.map +1 -1
  76. package/dist/meeting-info/index.js +73 -7
  77. package/dist/meeting-info/index.js.map +1 -1
  78. package/dist/meeting-info/meeting-info-v2.js +192 -51
  79. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  80. package/dist/meeting-info/util.js +1 -1
  81. package/dist/meeting-info/util.js.map +1 -1
  82. package/dist/meeting-info/utilv2.js +36 -36
  83. package/dist/meeting-info/utilv2.js.map +1 -1
  84. package/dist/meetings/collection.js +22 -0
  85. package/dist/meetings/collection.js.map +1 -1
  86. package/dist/meetings/index.js +394 -94
  87. package/dist/meetings/index.js.map +1 -1
  88. package/dist/meetings/meetings.types.js +7 -0
  89. package/dist/meetings/meetings.types.js.map +1 -0
  90. package/dist/meetings/request.js +2 -0
  91. package/dist/meetings/request.js.map +1 -1
  92. package/dist/meetings/util.js +71 -1
  93. package/dist/meetings/util.js.map +1 -1
  94. package/dist/member/index.js +49 -0
  95. package/dist/member/index.js.map +1 -1
  96. package/dist/member/types.js +25 -0
  97. package/dist/member/types.js.map +1 -0
  98. package/dist/member/util.js +121 -25
  99. package/dist/member/util.js.map +1 -1
  100. package/dist/members/collection.js +10 -0
  101. package/dist/members/collection.js.map +1 -1
  102. package/dist/members/index.js +86 -6
  103. package/dist/members/index.js.map +1 -1
  104. package/dist/members/request.js +106 -38
  105. package/dist/members/request.js.map +1 -1
  106. package/dist/members/types.js +15 -0
  107. package/dist/members/types.js.map +1 -0
  108. package/dist/members/util.js +316 -233
  109. package/dist/members/util.js.map +1 -1
  110. package/dist/metrics/constants.js +12 -5
  111. package/dist/metrics/constants.js.map +1 -1
  112. package/dist/metrics/index.js +1 -468
  113. package/dist/metrics/index.js.map +1 -1
  114. package/dist/multistream/mediaRequestManager.js +238 -49
  115. package/dist/multistream/mediaRequestManager.js.map +1 -1
  116. package/dist/multistream/receiveSlot.js +40 -16
  117. package/dist/multistream/receiveSlot.js.map +1 -1
  118. package/dist/multistream/receiveSlotManager.js +39 -36
  119. package/dist/multistream/receiveSlotManager.js.map +1 -1
  120. package/dist/multistream/remoteMedia.js +44 -18
  121. package/dist/multistream/remoteMedia.js.map +1 -1
  122. package/dist/multistream/remoteMediaGroup.js +60 -3
  123. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  124. package/dist/multistream/remoteMediaManager.js +209 -59
  125. package/dist/multistream/remoteMediaManager.js.map +1 -1
  126. package/dist/multistream/sendSlotManager.js +233 -0
  127. package/dist/multistream/sendSlotManager.js.map +1 -0
  128. package/dist/reachability/index.js +225 -59
  129. package/dist/reachability/index.js.map +1 -1
  130. package/dist/reachability/request.js +17 -8
  131. package/dist/reachability/request.js.map +1 -1
  132. package/dist/reconnection-manager/index.js +199 -154
  133. package/dist/reconnection-manager/index.js.map +1 -1
  134. package/dist/recording-controller/index.js +21 -2
  135. package/dist/recording-controller/index.js.map +1 -1
  136. package/dist/recording-controller/util.js +9 -8
  137. package/dist/recording-controller/util.js.map +1 -1
  138. package/dist/roap/index.js +23 -29
  139. package/dist/roap/index.js.map +1 -1
  140. package/dist/roap/request.js +112 -97
  141. package/dist/roap/request.js.map +1 -1
  142. package/dist/roap/turnDiscovery.js +96 -36
  143. package/dist/roap/turnDiscovery.js.map +1 -1
  144. package/dist/rtcMetrics/constants.js +12 -0
  145. package/dist/rtcMetrics/constants.js.map +1 -0
  146. package/dist/rtcMetrics/index.js +117 -0
  147. package/dist/rtcMetrics/index.js.map +1 -0
  148. package/dist/statsAnalyzer/index.js +67 -73
  149. package/dist/statsAnalyzer/index.js.map +1 -1
  150. package/dist/statsAnalyzer/mqaUtil.js +11 -10
  151. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  152. package/dist/types/annotation/annotation.types.d.ts +42 -0
  153. package/dist/types/annotation/constants.d.ts +31 -0
  154. package/dist/types/annotation/index.d.ts +117 -0
  155. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  156. package/dist/types/breakouts/events.d.ts +8 -0
  157. package/dist/types/breakouts/request.d.ts +22 -0
  158. package/dist/types/breakouts/utils.d.ts +15 -0
  159. package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
  160. package/dist/types/common/errors/webex-errors.d.ts +13 -1
  161. package/dist/types/common/queue.d.ts +9 -7
  162. package/dist/types/config.d.ts +1 -6
  163. package/dist/types/constants.d.ts +161 -21
  164. package/dist/types/controls-options-manager/enums.d.ts +11 -1
  165. package/dist/types/controls-options-manager/index.d.ts +17 -1
  166. package/dist/types/controls-options-manager/types.d.ts +43 -0
  167. package/dist/types/controls-options-manager/util.d.ts +1 -7
  168. package/dist/types/index.d.ts +6 -4
  169. package/dist/types/interpretation/collection.d.ts +5 -0
  170. package/dist/types/interpretation/index.d.ts +5 -0
  171. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  172. package/dist/types/locus-info/index.d.ts +57 -4
  173. package/dist/types/locus-info/parser.d.ts +67 -6
  174. package/dist/types/media/index.d.ts +2 -0
  175. package/dist/types/media/properties.d.ts +34 -48
  176. package/dist/types/meeting/in-meeting-actions.d.ts +82 -2
  177. package/dist/types/meeting/index.d.ts +345 -507
  178. package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
  179. package/dist/types/meeting/muteState.d.ts +99 -23
  180. package/dist/types/meeting/request.d.ts +72 -43
  181. package/dist/types/meeting/util.d.ts +101 -1
  182. package/dist/types/meeting-info/index.d.ts +13 -1
  183. package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
  184. package/dist/types/meetings/collection.d.ts +8 -0
  185. package/dist/types/meetings/index.d.ts +88 -12
  186. package/dist/types/meetings/meetings.types.d.ts +4 -0
  187. package/dist/types/member/index.d.ts +13 -0
  188. package/dist/types/member/types.d.ts +32 -0
  189. package/dist/types/members/collection.d.ts +5 -0
  190. package/dist/types/members/index.d.ts +35 -2
  191. package/dist/types/members/request.d.ts +73 -9
  192. package/dist/types/members/types.d.ts +24 -0
  193. package/dist/types/members/util.d.ts +209 -1
  194. package/dist/types/metrics/constants.d.ts +11 -4
  195. package/dist/types/metrics/index.d.ts +4 -119
  196. package/dist/types/multistream/mediaRequestManager.d.ts +73 -5
  197. package/dist/types/multistream/receiveSlot.d.ts +13 -11
  198. package/dist/types/multistream/receiveSlotManager.d.ts +14 -4
  199. package/dist/types/multistream/remoteMedia.d.ts +8 -29
  200. package/dist/types/multistream/remoteMediaGroup.d.ts +0 -9
  201. package/dist/types/multistream/remoteMediaManager.d.ts +46 -2
  202. package/dist/types/multistream/sendSlotManager.d.ts +61 -0
  203. package/dist/types/reachability/index.d.ts +61 -7
  204. package/dist/types/reachability/request.d.ts +7 -3
  205. package/dist/types/reconnection-manager/index.d.ts +9 -0
  206. package/dist/types/recording-controller/index.d.ts +15 -1
  207. package/dist/types/recording-controller/util.d.ts +5 -4
  208. package/dist/types/roap/request.d.ts +15 -11
  209. package/dist/types/roap/turnDiscovery.d.ts +18 -1
  210. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  211. package/dist/types/rtcMetrics/index.d.ts +47 -0
  212. package/dist/types/statsAnalyzer/index.d.ts +6 -1
  213. package/package.json +23 -20
  214. package/src/annotation/annotation.types.ts +50 -0
  215. package/src/annotation/constants.ts +36 -0
  216. package/src/annotation/index.ts +328 -0
  217. package/src/breakouts/README.md +44 -14
  218. package/src/breakouts/breakout.ts +87 -9
  219. package/src/breakouts/edit-lock-error.ts +25 -0
  220. package/src/breakouts/events.ts +56 -0
  221. package/src/breakouts/index.ts +646 -18
  222. package/src/breakouts/request.ts +55 -0
  223. package/src/breakouts/utils.ts +57 -0
  224. package/src/common/errors/no-meeting-info.ts +24 -0
  225. package/src/common/errors/webex-errors.ts +27 -2
  226. package/src/common/logs/logger-proxy.ts +1 -1
  227. package/src/common/queue.ts +22 -8
  228. package/src/config.ts +4 -9
  229. package/src/constants.ts +184 -18
  230. package/src/controls-options-manager/enums.ts +12 -0
  231. package/src/controls-options-manager/index.ts +116 -21
  232. package/src/controls-options-manager/types.ts +59 -0
  233. package/src/controls-options-manager/util.ts +294 -14
  234. package/src/index.ts +40 -0
  235. package/src/interpretation/README.md +60 -0
  236. package/src/interpretation/collection.ts +19 -0
  237. package/src/interpretation/index.ts +332 -0
  238. package/src/interpretation/siLanguage.ts +18 -0
  239. package/src/locus-info/controlsUtils.ts +108 -0
  240. package/src/locus-info/index.ts +413 -59
  241. package/src/locus-info/infoUtils.ts +10 -2
  242. package/src/locus-info/mediaSharesUtils.ts +64 -0
  243. package/src/locus-info/parser.ts +258 -47
  244. package/src/locus-info/selfUtils.ts +81 -5
  245. package/src/media/index.ts +100 -122
  246. package/src/media/properties.ts +85 -108
  247. package/src/meeting/in-meeting-actions.ts +163 -3
  248. package/src/meeting/index.ts +2541 -2309
  249. package/src/meeting/locusMediaRequest.ts +313 -0
  250. package/src/meeting/muteState.ts +229 -131
  251. package/src/meeting/request.ts +172 -121
  252. package/src/meeting/util.ts +588 -394
  253. package/src/meeting-info/index.ts +81 -8
  254. package/src/meeting-info/meeting-info-v2.ts +170 -14
  255. package/src/meeting-info/util.ts +1 -1
  256. package/src/meeting-info/utilv2.ts +23 -23
  257. package/src/meetings/collection.ts +20 -0
  258. package/src/meetings/index.ts +428 -108
  259. package/src/meetings/meetings.types.ts +12 -0
  260. package/src/meetings/request.ts +2 -0
  261. package/src/meetings/util.ts +79 -4
  262. package/src/member/index.ts +49 -0
  263. package/src/member/types.ts +38 -0
  264. package/src/member/util.ts +127 -25
  265. package/src/members/collection.ts +8 -0
  266. package/src/members/index.ts +106 -7
  267. package/src/members/request.ts +97 -17
  268. package/src/members/types.ts +28 -0
  269. package/src/members/util.ts +319 -240
  270. package/src/metrics/constants.ts +11 -4
  271. package/src/metrics/index.ts +1 -490
  272. package/src/multistream/mediaRequestManager.ts +289 -79
  273. package/src/multistream/receiveSlot.ts +47 -17
  274. package/src/multistream/receiveSlotManager.ts +34 -24
  275. package/src/multistream/remoteMedia.ts +27 -2
  276. package/src/multistream/remoteMediaGroup.ts +59 -0
  277. package/src/multistream/remoteMediaManager.ts +148 -30
  278. package/src/multistream/sendSlotManager.ts +170 -0
  279. package/src/reachability/index.ts +228 -37
  280. package/src/reachability/request.ts +17 -8
  281. package/src/reconnection-manager/index.ts +81 -54
  282. package/src/recording-controller/index.ts +20 -3
  283. package/src/recording-controller/util.ts +26 -9
  284. package/src/roap/index.ts +23 -30
  285. package/src/roap/request.ts +100 -104
  286. package/src/roap/turnDiscovery.ts +51 -25
  287. package/src/rtcMetrics/constants.ts +3 -0
  288. package/src/rtcMetrics/index.ts +100 -0
  289. package/src/statsAnalyzer/index.ts +88 -88
  290. package/src/statsAnalyzer/mqaUtil.ts +13 -14
  291. package/test/integration/spec/converged-space-meetings.js +60 -3
  292. package/test/integration/spec/journey.js +320 -261
  293. package/test/integration/spec/space-meeting.js +76 -3
  294. package/test/unit/spec/annotation/index.ts +418 -0
  295. package/test/unit/spec/breakouts/breakout.ts +142 -24
  296. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  297. package/test/unit/spec/breakouts/events.ts +89 -0
  298. package/test/unit/spec/breakouts/index.ts +1488 -67
  299. package/test/unit/spec/breakouts/request.ts +104 -0
  300. package/test/unit/spec/breakouts/utils.js +72 -0
  301. package/test/unit/spec/common/queue.js +31 -2
  302. package/test/unit/spec/controls-options-manager/index.js +163 -0
  303. package/test/unit/spec/controls-options-manager/util.js +576 -60
  304. package/test/unit/spec/fixture/locus.js +1 -0
  305. package/test/unit/spec/interpretation/collection.ts +15 -0
  306. package/test/unit/spec/interpretation/index.ts +589 -0
  307. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  308. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  309. package/test/unit/spec/locus-info/index.js +1304 -33
  310. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  311. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  312. package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
  313. package/test/unit/spec/locus-info/parser.js +116 -35
  314. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  315. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  316. package/test/unit/spec/media/index.ts +104 -37
  317. package/test/unit/spec/meeting/in-meeting-actions.ts +81 -3
  318. package/test/unit/spec/meeting/index.js +4515 -1932
  319. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  320. package/test/unit/spec/meeting/muteState.js +408 -208
  321. package/test/unit/spec/meeting/request.js +440 -45
  322. package/test/unit/spec/meeting/utils.js +679 -64
  323. package/test/unit/spec/meeting-info/index.js +295 -0
  324. package/test/unit/spec/meeting-info/meetinginfov2.js +521 -5
  325. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  326. package/test/unit/spec/meetings/collection.js +14 -0
  327. package/test/unit/spec/meetings/index.js +1007 -177
  328. package/test/unit/spec/meetings/utils.js +206 -2
  329. package/test/unit/spec/member/index.js +58 -4
  330. package/test/unit/spec/member/util.js +479 -35
  331. package/test/unit/spec/members/index.js +319 -1
  332. package/test/unit/spec/members/request.js +206 -27
  333. package/test/unit/spec/members/utils.js +184 -0
  334. package/test/unit/spec/metrics/index.js +1 -50
  335. package/test/unit/spec/multistream/mediaRequestManager.ts +803 -162
  336. package/test/unit/spec/multistream/receiveSlot.ts +43 -20
  337. package/test/unit/spec/multistream/receiveSlotManager.ts +32 -30
  338. package/test/unit/spec/multistream/remoteMedia.ts +30 -0
  339. package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
  340. package/test/unit/spec/multistream/remoteMediaManager.ts +326 -0
  341. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  342. package/test/unit/spec/reachability/index.ts +549 -9
  343. package/test/unit/spec/reachability/request.js +68 -0
  344. package/test/unit/spec/reconnection-manager/index.js +84 -9
  345. package/test/unit/spec/recording-controller/index.js +294 -218
  346. package/test/unit/spec/recording-controller/util.js +223 -96
  347. package/test/unit/spec/roap/index.ts +31 -51
  348. package/test/unit/spec/roap/request.ts +203 -85
  349. package/test/unit/spec/roap/turnDiscovery.ts +48 -13
  350. package/test/unit/spec/rtcMetrics/index.ts +68 -0
  351. package/test/unit/spec/stats-analyzer/index.js +64 -2
  352. package/test/utils/integrationTestUtils.js +46 -0
  353. package/test/utils/testUtils.js +0 -52
  354. package/dist/meeting/effectsState.js +0 -262
  355. package/dist/meeting/effectsState.js.map +0 -1
  356. package/dist/metrics/config.js +0 -299
  357. package/dist/metrics/config.js.map +0 -1
  358. package/dist/types/meeting/effectsState.d.ts +0 -42
  359. package/dist/types/metrics/config.d.ts +0 -178
  360. package/src/index.js +0 -16
  361. package/src/meeting/effectsState.ts +0 -211
  362. package/src/metrics/config.ts +0 -495
  363. package/test/unit/spec/meeting/effectsState.js +0 -285
@@ -1,114 +1,232 @@
1
- import {assert} from '@webex/test-helper-chai';
2
1
  import sinon from 'sinon';
2
+ import {assert} from '@webex/test-helper-chai';
3
3
  import MockWebex from '@webex/test-helper-mock-webex';
4
- import Metrics from '@webex/plugin-meetings/src/metrics';
5
-
4
+ import Meetings from '@webex/plugin-meetings';
6
5
  import RoapRequest from '@webex/plugin-meetings/src/roap/request';
7
-
8
-
9
- describe('RoapRequest', () => {
10
- describe('attachRechabilityData', () => {
11
- let webex;
12
-
13
- beforeEach(() => {
14
- webex = new MockWebex();
6
+ import {IP_VERSION, REACHABILITY} from '@webex/plugin-meetings/src/constants';
7
+
8
+ describe('plugin-meetings/roap', () => {
9
+ let roapRequest;
10
+ let webex;
11
+ const locusUrl = 'locusUrl';
12
+
13
+ beforeEach(async () => {
14
+ webex = new MockWebex({
15
+ children: {
16
+ meetings: Meetings,
17
+ },
15
18
  });
16
-
17
- it('attaches the reachability data when it exists', async () => {
18
- // @ts-ignore
19
- const roapRequest = new RoapRequest({}, {parent: webex});
20
-
21
- const sdp = {some: 'attribute'};
22
19
 
23
- const reachabilitData = {reachability: 'data'};
20
+ webex.meetings.clientRegion = {
21
+ countryCode: 'US',
22
+ regionCode: 'WEST-COAST',
23
+ };
24
+
25
+ webex.internal = {
26
+ services: {
27
+ get: sinon.mock().returns(locusUrl),
28
+ waitForCatalog: sinon.mock().returns(Promise.resolve({})),
29
+ },
30
+ device: {
31
+ url: 'url',
32
+ },
33
+ newMetrics: {
34
+ submitClientEvent: sinon.stub()
35
+ },
36
+ };
37
+
38
+ // @ts-ignore
39
+ roapRequest = new RoapRequest({webex});
40
+
41
+ roapRequest.request = sinon.mock().returns(
42
+ Promise.resolve({
43
+ body: {
44
+ locus: {
45
+ roapSeq: '',
46
+ id: '',
47
+ url: 'url/path',
48
+ fullState: {
49
+ lastActive: 'lastActive',
50
+ },
51
+ },
52
+ },
53
+ })
54
+ );
24
55
 
25
- await webex.boundedStorage.put(
26
- 'Reachability',
27
- 'reachability.result',
28
- JSON.stringify(reachabilitData)
29
- );
56
+ await webex.boundedStorage.put(
57
+ REACHABILITY.namespace,
58
+ REACHABILITY.localStorageJoinCookie,
59
+ JSON.stringify({
60
+ anycastEntryPoint: 'aws-eu-west-1',
61
+ })
62
+ );
63
+ await webex.boundedStorage.put(
64
+ REACHABILITY.namespace,
65
+ REACHABILITY.localStorageResult,
66
+ JSON.stringify({
67
+ clusterId: {
68
+ udp: 'test',
69
+ isVideoMesh: false,
70
+ },
71
+ })
72
+ );
73
+ });
30
74
 
31
- const newSdp = await roapRequest.attachRechabilityData(sdp);
75
+ describe('#attachReachabilityData', () => {
76
+ it('returns the correct reachability data', async () => {
77
+ const res = await roapRequest.attachReachabilityData({});
32
78
 
33
- assert.deepEqual(newSdp, {
34
- some: 'attribute',
35
- reachability: reachabilitData
36
- })
79
+ assert.deepEqual(res.localSdp, {
80
+ reachability: {
81
+ clusterId: {
82
+ udp: 'test',
83
+ },
84
+ },
85
+ });
86
+ assert.deepEqual(res.joinCookie, {
87
+ anycastEntryPoint: 'aws-eu-west-1',
88
+ });
37
89
  });
38
-
39
- it('handles the case when realiability data does not exist', async () => {
40
- // @ts-ignore
41
- const roapRequest = new RoapRequest({}, {parent: webex});
42
90
 
43
- const sdp = {some: 'attribute'};
91
+ it('handles the case when reachability data does not exist', async () => {
92
+ await webex.boundedStorage.del(REACHABILITY.namespace, REACHABILITY.localStorageJoinCookie);
44
93
 
45
- const newSdp = await roapRequest.attachRechabilityData(sdp);
94
+ await webex.boundedStorage.del(REACHABILITY.namespace, REACHABILITY.localStorageResult);
95
+ const sdp = {
96
+ some: 'attribute',
97
+ };
98
+
99
+ const result = await roapRequest.attachReachabilityData(sdp);
46
100
 
47
- assert.deepEqual(newSdp, sdp);
101
+ assert.deepEqual(result, {
102
+ joinCookie: undefined,
103
+ localSdp: {
104
+ some: 'attribute',
105
+ },
106
+ });
48
107
  });
49
108
  });
50
109
 
51
110
  describe('sendRoap', () => {
52
- let webex;
53
-
54
- beforeEach(() => {
55
- webex = new MockWebex();
56
- });
111
+ it('includes joinCookie in the request correctly', async () => {
112
+ const locusMediaRequest = {send: sinon.stub().resolves({body: {locus: {}}})};
113
+ const ipVersion = IP_VERSION.unknown;
57
114
 
58
- it('calls attachReliabilityData', async () => {
59
- Metrics.postEvent = sinon.stub();
60
-
61
- // @ts-ignore
62
- const roapRequest = new RoapRequest({}, {parent: webex});
115
+ await roapRequest.sendRoap({
116
+ locusSelfUrl: locusUrl,
117
+ ipVersion,
118
+ mediaId: 'mediaId',
119
+ roapMessage: {
120
+ seq: 'seq',
121
+ },
122
+ meetingId: 'meeting-id',
123
+ locusMediaRequest,
124
+ });
63
125
 
64
- const newSdp = {new: 'sdp'}
126
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
127
+ name: 'client.locus.media.request',
128
+ options: {
129
+ meetingId: 'meeting-id',
130
+ },
131
+ });
65
132
 
66
- roapRequest.attachRechabilityData = sinon.stub().returns(Promise.resolve(newSdp));
67
- webex.request.returns(Promise.resolve({
68
- body: {
69
- locus: {}
70
- }
71
- }))
133
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
134
+ name: 'client.locus.media.response',
135
+ options: {
136
+ meetingId: 'meeting-id',
137
+ },
138
+ });
72
139
 
73
- const result = await roapRequest.sendRoap({
74
- roapMessage: {seq: 1},
75
- locusSelfUrl: 'locusSelfUrl',
140
+ const requestParams = locusMediaRequest.send.getCall(0).args[0];
141
+ assert.deepEqual(requestParams, {
142
+ type: 'RoapMessage',
143
+ selfUrl: locusUrl,
144
+ ipVersion,
145
+ joinCookie: {
146
+ anycastEntryPoint: 'aws-eu-west-1',
147
+ },
76
148
  mediaId: 'mediaId',
77
- correlationId: 'correlationId',
78
- audioMuted: true,
79
- videoMuted: true,
80
- meetingId: 'meetingId',
81
- preferTranscoding: true
149
+ roapMessage: {
150
+ seq: 'seq',
151
+ },
152
+ reachability: {clusterId: {udp: 'test'}},
82
153
  });
154
+ });
83
155
 
84
- assert.calledOnceWithExactly(webex.request, {
85
- uri: 'locusSelfUrl/media',
86
- method: 'PUT',
87
- body: {
88
- device: {
89
- url: undefined,
90
- deviceType: undefined,
156
+ it('sends correct client event when fails', async () => {
157
+ const locusMediaRequest = {send: sinon.stub().rejects({code: 300, message: 'error'})};
158
+ try {
159
+ await roapRequest.sendRoap({
160
+ locusSelfUrl: locusUrl,
161
+ mediaId: 'mediaId',
162
+ roapMessage: {
163
+ seq: 'seq',
91
164
  },
92
- correlationId: 'correlationId',
93
- localMedias: [{
94
- localSdp: JSON.stringify(newSdp),
95
- mediaId: 'mediaId'
96
- }],
97
- clientMediaPreferences: {preferTranscoding: true}
98
- },
99
- });
165
+ meetingId: 'meeting-id',
166
+ locusMediaRequest,
167
+ });
168
+ } catch (err) {
169
+ assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
170
+ name: 'client.locus.media.response',
171
+ options: {
172
+ meetingId: 'meeting-id',
173
+ rawError: {code: 300, message: 'error'},
174
+ },
175
+ });
176
+ }
177
+ });
178
+ });
100
179
 
101
- assert.calledOnceWithExactly(roapRequest.attachRechabilityData, {
102
- roapMessage: {seq: 1},
103
- audioMuted: true,
104
- videoMuted: true
180
+ it('calls attachReachabilityData when sendRoap', async () => {
181
+ const locusMediaRequest = { send: sinon.stub().resolves({body: {locus: {}}})};
182
+
183
+ const newSdp = {
184
+ new: 'sdp',
185
+ reachability: { someResult: 'whatever' }
186
+ };
187
+ const ipVersion = IP_VERSION.only_ipv6;
188
+
189
+ roapRequest.attachReachabilityData = sinon.stub().returns(
190
+ Promise.resolve({
191
+ localSdp: newSdp,
192
+ joinCookie: {
193
+ anycastEntryPoint: 'aws-eu-west-1',
194
+ },
105
195
  })
196
+ );
197
+
198
+ await roapRequest.sendRoap({
199
+ roapMessage: {
200
+ seq: 1,
201
+ },
202
+ locusSelfUrl: 'locusSelfUrl',
203
+ ipVersion,
204
+ mediaId: 'mediaId',
205
+ meetingId: 'meetingId',
206
+ preferTranscoding: true,
207
+ locusMediaRequest
208
+ });
106
209
 
107
- assert.deepEqual(result, {
108
- locus: {
109
- roapSeq: 1
110
- }
111
- });
210
+ const requestParams = locusMediaRequest.send.getCall(0).args[0];
211
+
212
+ assert.deepEqual(requestParams, {
213
+ type: 'RoapMessage',
214
+ selfUrl: 'locusSelfUrl',
215
+ ipVersion,
216
+ joinCookie: {
217
+ anycastEntryPoint: 'aws-eu-west-1',
218
+ },
219
+ mediaId: 'mediaId',
220
+ roapMessage: {
221
+ seq: 1,
222
+ },
223
+ reachability: { someResult: 'whatever' },
112
224
  });
113
- })
225
+
226
+ assert.calledOnceWithExactly(roapRequest.attachReachabilityData, {
227
+ roapMessage: {
228
+ seq: 1,
229
+ },
230
+ });
231
+ });
114
232
  });
@@ -5,8 +5,10 @@ import TurnDiscovery from '@webex/plugin-meetings/src/roap/turnDiscovery';
5
5
  import Metrics from '@webex/plugin-meetings/src/metrics';
6
6
  import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
7
7
  import RoapRequest from '@webex/plugin-meetings/src/roap/request';
8
+ import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
8
9
 
9
10
  import testUtils from '../../../utils/testUtils';
11
+ import { IP_VERSION } from '../../../../src/constants';
10
12
 
11
13
  describe('TurnDiscovery', () => {
12
14
  let clock;
@@ -23,6 +25,7 @@ describe('TurnDiscovery', () => {
23
25
  clock = sinon.useFakeTimers();
24
26
 
25
27
  sinon.stub(Metrics, 'sendBehavioralMetric');
28
+ sinon.stub(MeetingUtil, 'getIpVersion').returns(IP_VERSION.unknown);
26
29
 
27
30
  mockRoapRequest = {
28
31
  sendRoap: sinon.fake.resolves({mediaConnections: FAKE_MEDIA_CONNECTIONS_FROM_LOCUS}),
@@ -40,14 +43,21 @@ describe('TurnDiscovery', () => {
40
43
  mediaId: 'fake media id',
41
44
  locusUrl: `https://locus-a.wbx2.com/locus/api/v1/loci/${FAKE_LOCUS_ID}`,
42
45
  roapSeq: -1,
43
- isAudioMuted: () => true,
44
- isVideoMuted: () => false,
46
+ audio:{
47
+ isLocallyMuted: () => true,
48
+ },
49
+ video:{
50
+ isLocallyMuted: () => false,
51
+ },
45
52
  setRoapSeq: sinon.fake((newSeq) => {
46
53
  testMeeting.roapSeq = newSeq;
47
54
  }),
48
55
  updateMediaConnections: sinon.stub(),
49
- webex: {meetings: {reachability: {isAnyClusterReachable: () => Promise.resolve(false)}}},
50
- isMultistream: false
56
+ webex: {meetings: {reachability: {
57
+ isAnyPublicClusterReachable: () => Promise.resolve(false),
58
+ }}},
59
+ isMultistream: false,
60
+ locusMediaRequest: { fake: true },
51
61
  };
52
62
  });
53
63
 
@@ -64,20 +74,24 @@ describe('TurnDiscovery', () => {
64
74
  await testUtils.flushPromises();
65
75
 
66
76
  assert.calledOnce(mockRoapRequest.sendRoap);
67
- assert.calledWith(mockRoapRequest.sendRoap, {
77
+
78
+ const expectedSendRoapArgs: any = {
68
79
  roapMessage: {
69
80
  messageType,
70
81
  version: '2',
71
82
  seq: expectedSeq,
72
83
  },
73
- correlationId: testMeeting.correlationId,
74
84
  locusSelfUrl: testMeeting.selfUrl,
75
85
  mediaId: expectedMediaId,
76
- audioMuted: testMeeting.isAudioMuted(),
77
- videoMuted: testMeeting.isVideoMuted(),
78
86
  meetingId: testMeeting.id,
79
- preferTranscoding: !testMeeting.isMultistream
80
- });
87
+ locusMediaRequest: testMeeting.locusMediaRequest,
88
+ };
89
+
90
+ if (messageType === 'TURN_DISCOVERY_REQUEST') {
91
+ expectedSendRoapArgs.ipVersion = 0;
92
+ }
93
+
94
+ assert.calledWith(mockRoapRequest.sendRoap, expectedSendRoapArgs);
81
95
 
82
96
  if (messageType === 'TURN_DISCOVERY_REQUEST') {
83
97
  // check also that we've applied the media connections from the response
@@ -243,8 +257,8 @@ describe('TurnDiscovery', () => {
243
257
  });
244
258
 
245
259
  it('resolves with undefined when cluster is reachable', async () => {
246
- const prev = testMeeting.webex.meetings.reachability.isAnyClusterReachable;
247
- testMeeting.webex.meetings.reachability.isAnyClusterReachable = () => Promise.resolve(true);
260
+ const prev = testMeeting.webex.meetings.reachability.isAnyPublicClusterReachable;
261
+ testMeeting.webex.meetings.reachability.isAnyPublicClusterReachable = () => Promise.resolve(true);
248
262
  const result = await new TurnDiscovery(mockRoapRequest).doTurnDiscovery(testMeeting);
249
263
 
250
264
  const {turnServerInfo, turnDiscoverySkippedReason} = result;
@@ -253,7 +267,7 @@ describe('TurnDiscovery', () => {
253
267
  assert.equal(turnDiscoverySkippedReason, 'reachability');
254
268
  assert.notCalled(mockRoapRequest.sendRoap);
255
269
  assert.notCalled(Metrics.sendBehavioralMetric);
256
- testMeeting.webex.meetings.reachability.isAnyClusterReachable = prev;
270
+ testMeeting.webex.meetings.reachability.isAnyPublicClusterReachable = prev;
257
271
  });
258
272
 
259
273
  it("resolves with undefined if we don't get a response within 10s", async () => {
@@ -363,6 +377,27 @@ describe('TurnDiscovery', () => {
363
377
  });
364
378
  });
365
379
 
380
+ describe('isSkipped', () => {
381
+ [
382
+ {enabledInConfig: true, isAnyPublicClusterReachable: true, expectedIsSkipped: true},
383
+ {enabledInConfig: true, isAnyPublicClusterReachable: false, expectedIsSkipped: false},
384
+ {enabledInConfig: false, isAnyPublicClusterReachable: true, expectedIsSkipped: true},
385
+ {enabledInConfig: false, isAnyPublicClusterReachable: false, expectedIsSkipped: true},
386
+ ].forEach(({enabledInConfig, isAnyPublicClusterReachable, expectedIsSkipped}) => {
387
+ it(`returns ${expectedIsSkipped} when TURN discovery is ${enabledInConfig ? '' : 'not '} enabled in config and isAnyPublicClusterReachable() returns ${isAnyPublicClusterReachable ? 'true' : 'false'}`, async () => {
388
+ testMeeting.config.experimental.enableTurnDiscovery = enabledInConfig;
389
+
390
+ sinon.stub(testMeeting.webex.meetings.reachability, 'isAnyPublicClusterReachable').resolves(isAnyPublicClusterReachable);
391
+
392
+ const td = new TurnDiscovery(mockRoapRequest);
393
+
394
+ const isSkipped = await td.isSkipped(testMeeting);
395
+
396
+ assert.equal(isSkipped, expectedIsSkipped);
397
+ })
398
+ })
399
+ })
400
+
366
401
  describe('handleTurnDiscoveryResponse', () => {
367
402
  it("doesn't do anything if turn discovery was not started", () => {
368
403
  const td = new TurnDiscovery(mockRoapRequest);
@@ -0,0 +1,68 @@
1
+ import RtcMetrics from '@webex/plugin-meetings/src/rtcMetrics';
2
+ import MockWebex from '@webex/test-helper-mock-webex';
3
+ import {assert} from '@webex/test-helper-chai';
4
+ import sinon from 'sinon';
5
+ import RTC_METRICS from '../../../../src/rtcMetrics/constants';
6
+
7
+ const FAKE_METRICS_ITEM = {payload: ['fake-metrics']};
8
+
9
+ describe('RtcMetrics', () => {
10
+ let metrics: RtcMetrics;
11
+ let webex: MockWebex;
12
+ let clock;
13
+
14
+ beforeEach(() => {
15
+ clock = sinon.useFakeTimers();
16
+ webex = new MockWebex();
17
+ metrics = new RtcMetrics(webex, 'mock-meeting-id', 'mock-correlation-id');
18
+ });
19
+
20
+ it('sendMetrics should send a webex request', () => {
21
+ assert.notCalled(webex.request);
22
+
23
+ metrics.addMetrics(FAKE_METRICS_ITEM);
24
+ (metrics as any).sendMetrics();
25
+
26
+ assert.callCount(webex.request, 1);
27
+ assert.calledWithMatch(webex.request, sinon.match.has('headers', {
28
+ type: 'webrtcMedia',
29
+ appId: RTC_METRICS.APP_ID,
30
+ }));
31
+ assert.calledWithMatch(webex.request, sinon.match.hasNested('body.metrics[0].data[0].payload', FAKE_METRICS_ITEM.payload));
32
+ assert.calledWithMatch(webex.request, sinon.match.hasNested('body.metrics[0].meetingId', 'mock-meeting-id'));
33
+ assert.calledWithMatch(webex.request, sinon.match.hasNested('body.metrics[0].correlationId', 'mock-correlation-id'));
34
+ });
35
+
36
+ it('should send metrics requests over time', () => {
37
+ assert.notCalled(webex.request);
38
+
39
+ metrics.addMetrics(FAKE_METRICS_ITEM);
40
+ assert.deepEqual(metrics.metricsQueue, [FAKE_METRICS_ITEM]);
41
+ clock.tick(60 * 1000);
42
+
43
+ assert.callCount(webex.request, 1);
44
+ });
45
+
46
+ it('should not send requests with no items in the queue', () => {
47
+ clock.tick(60 * 1000);
48
+ assert.notCalled(webex.request);
49
+ });
50
+
51
+ it('checkMetrics should send metrics if any exist in the queue', () => {
52
+ assert.notCalled(webex.request);
53
+
54
+ metrics.addMetrics(FAKE_METRICS_ITEM);
55
+ (metrics as any).checkMetrics();
56
+
57
+ assert.callCount(webex.request, 1);
58
+ });
59
+
60
+ it('should clear out metrics on close', () => {
61
+ assert.notCalled(webex.request);
62
+
63
+ metrics.addMetrics(FAKE_METRICS_ITEM);
64
+ metrics.closeMetrics();
65
+
66
+ assert.callCount(webex.request, 1);
67
+ });
68
+ });
@@ -53,7 +53,12 @@ describe('plugin-meetings', () => {
53
53
  beforeEach(() => {
54
54
  const networkQualityMonitor = new NetworkQualityMonitor(initialConfig);
55
55
 
56
- statsAnalyzer = new StatsAnalyzer(initialConfig, networkQualityMonitor, defaultStats);
56
+ statsAnalyzer = new StatsAnalyzer(
57
+ initialConfig,
58
+ () => ({}),
59
+ networkQualityMonitor,
60
+ defaultStats
61
+ );
57
62
 
58
63
  sandBoxSpy = sandbox.spy(
59
64
  statsAnalyzer.networkQualityMonitor,
@@ -84,6 +89,7 @@ describe('plugin-meetings', () => {
84
89
  let pc;
85
90
  let networkQualityMonitor;
86
91
  let statsAnalyzer;
92
+ let mqeData;
87
93
 
88
94
  let receivedEventsData = {
89
95
  local: {},
@@ -119,6 +125,11 @@ describe('plugin-meetings', () => {
119
125
  packetsSent: 0,
120
126
  bytesSent: 1,
121
127
  },
128
+ {
129
+ type: 'local-candidate',
130
+ id: 'fake-candidate-id',
131
+ protocol: 'tcp'
132
+ },
122
133
  ],
123
134
  },
124
135
  ],
@@ -130,6 +141,11 @@ describe('plugin-meetings', () => {
130
141
  packetsReceived: 0,
131
142
  bytesReceived: 1,
132
143
  },
144
+ {
145
+ type: 'local-candidate',
146
+ id: 'fake-candidate-id',
147
+ protocol: 'tcp'
148
+ },
133
149
  ],
134
150
  },
135
151
  ],
@@ -143,6 +159,11 @@ describe('plugin-meetings', () => {
143
159
  framesSent: 0,
144
160
  bytesSent: 1,
145
161
  },
162
+ {
163
+ type: 'local-candidate',
164
+ id: 'fake-candidate-id',
165
+ protocol: 'tcp'
166
+ },
146
167
  ],
147
168
  },
148
169
  ],
@@ -153,6 +174,14 @@ describe('plugin-meetings', () => {
153
174
  type: 'inbound-rtp',
154
175
  framesDecoded: 0,
155
176
  bytesReceived: 1,
177
+ frameHeight: 720,
178
+ frameWidth: 1280,
179
+ framesReceived: 1,
180
+ },
181
+ {
182
+ type: 'local-candidate',
183
+ id: 'fake-candidate-id',
184
+ protocol: 'tcp'
156
185
  },
157
186
  ],
158
187
  },
@@ -184,7 +213,7 @@ describe('plugin-meetings', () => {
184
213
 
185
214
  networkQualityMonitor = new NetworkQualityMonitor(initialConfig);
186
215
 
187
- statsAnalyzer = new StatsAnalyzer(initialConfig, networkQualityMonitor);
216
+ statsAnalyzer = new StatsAnalyzer(initialConfig, () => ({}), networkQualityMonitor);
188
217
 
189
218
  statsAnalyzer.on(EVENTS.LOCAL_MEDIA_STARTED, (data) => {
190
219
  receivedEventsData.local.started = data;
@@ -198,6 +227,9 @@ describe('plugin-meetings', () => {
198
227
  statsAnalyzer.on(EVENTS.REMOTE_MEDIA_STOPPED, (data) => {
199
228
  receivedEventsData.remote.stopped = data;
200
229
  });
230
+ statsAnalyzer.on(EVENTS.MEDIA_QUALITY, ({data}) => {
231
+ mqeData = data;
232
+ });
201
233
  });
202
234
 
203
235
  afterEach(() => {
@@ -224,6 +256,19 @@ describe('plugin-meetings', () => {
224
256
  assert.deepEqual(receivedEventsData.remote.stopped, expected.remote?.stopped);
225
257
  };
226
258
 
259
+ const checkMqeData = () => {
260
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].receivedFrameSize, 3600);
261
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].receivedHeight, 720);
262
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].receivedWidth, 1280);
263
+ };
264
+
265
+ const checkMqeTransportType = () => {
266
+ console.log(mqeData.audioTransmit[0])
267
+ console.log(mqeData.videoReceive[0])
268
+ assert.strictEqual(mqeData.audioTransmit[0].common.transportType, 'TCP');
269
+ assert.strictEqual(mqeData.videoReceive[0].common.transportType, 'TCP');
270
+ }
271
+
227
272
  it('emits LOCAL_MEDIA_STARTED and LOCAL_MEDIA_STOPPED events for audio', async () => {
228
273
  await startStatsAnalyzer({expected: {sendAudio: true}});
229
274
 
@@ -303,6 +348,23 @@ describe('plugin-meetings', () => {
303
348
 
304
349
  checkReceivedEvent({expected: {remote: {stopped: {type: 'video'}}}});
305
350
  });
351
+
352
+ it('emits the correct MEDIA_QUALITY events', async () => {
353
+ await startStatsAnalyzer({expected: {receiveVideo: true}});
354
+
355
+ await progressTime();
356
+
357
+ // Check that the mqe data has been emitted and is correctly computed.
358
+ checkMqeData();
359
+ });
360
+
361
+ it('emits the correct transportType in MEDIA_QUALITY events', async () => {
362
+ await startStatsAnalyzer({expected: {receiveVideo: true}});
363
+
364
+ await progressTime();
365
+
366
+ checkMqeTransportType();
367
+ });
306
368
  });
307
369
  });
308
370
  });
@@ -0,0 +1,46 @@
1
+ import {assert} from '@webex/test-helper-chai';
2
+ import {Defer} from '@webex/common';
3
+
4
+ const addMedia = async (user, options = {}) => {
5
+
6
+ const {microphone, camera} = options;
7
+
8
+ if (options.multistream) {
9
+ await user.meeting.addMedia({localStreams: {microphone, camera}});
10
+ } else {
11
+ const mediaReadyPromises = Array.isArray(options.expectedMediaReadyTypes)
12
+ ? options.expectedMediaReadyTypes.reduce((output, expectedMediaReadyType) => {
13
+ if (typeof expectedMediaReadyType !== 'string') {
14
+ return output;
15
+ }
16
+
17
+ output[expectedMediaReadyType] = new Defer();
18
+
19
+ return output;
20
+ }, {})
21
+ : {remoteAudio: new Defer(), remoteVideo: new Defer()};
22
+
23
+ const mediaReady = (media) => {
24
+ if (!media) {
25
+ return;
26
+ }
27
+ if (mediaReadyPromises[media.type]) {
28
+ mediaReadyPromises[media.type].resolve();
29
+ }
30
+ };
31
+
32
+ user.meeting.on('media:ready', mediaReady);
33
+
34
+ await user.meeting.addMedia({localStreams: {microphone, camera}});
35
+ await Promise.all(Object.values(mediaReadyPromises).map((defer) => defer.promise));
36
+ };
37
+
38
+
39
+ assert.exists(user.meeting.mediaProperties.audioStream, 'audioStream not present');
40
+ assert.exists(user.meeting.mediaProperties.videoStream, 'videoStream not present');
41
+
42
+ };
43
+
44
+ export default {
45
+ addMedia
46
+ };