@webex/plugin-meetings 3.0.0-beta.27 → 3.0.0-beta.270

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 (362) 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 +381 -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 +224 -63
  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 +3096 -2823
  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 +70 -7
  77. package/dist/meeting-info/index.js.map +1 -1
  78. package/dist/meeting-info/meeting-info-v2.js +189 -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 -5
  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 +10 -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 +49 -16
  117. package/dist/multistream/receiveSlot.js.map +1 -1
  118. package/dist/multistream/receiveSlotManager.js +52 -34
  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 +51 -34
  149. package/dist/statsAnalyzer/index.js.map +1 -1
  150. package/dist/statsAnalyzer/mqaUtil.js +6 -6
  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 +65 -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 +9 -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 +16 -12
  198. package/dist/types/multistream/receiveSlotManager.d.ts +19 -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 +412 -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 +231 -39
  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 +2495 -2314
  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 +79 -8
  254. package/src/meeting-info/meeting-info-v2.ts +168 -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 +107 -6
  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 +9 -4
  271. package/src/metrics/index.ts +1 -490
  272. package/src/multistream/mediaRequestManager.ts +289 -79
  273. package/src/multistream/receiveSlot.ts +55 -18
  274. package/src/multistream/receiveSlotManager.ts +46 -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 +73 -35
  290. package/src/statsAnalyzer/mqaUtil.ts +8 -10
  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 +1283 -33
  310. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  311. package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
  312. package/test/unit/spec/locus-info/parser.js +62 -22
  313. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  314. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  315. package/test/unit/spec/media/index.ts +104 -37
  316. package/test/unit/spec/meeting/in-meeting-actions.ts +81 -3
  317. package/test/unit/spec/meeting/index.js +4172 -1947
  318. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  319. package/test/unit/spec/meeting/muteState.js +408 -208
  320. package/test/unit/spec/meeting/request.js +440 -45
  321. package/test/unit/spec/meeting/utils.js +679 -64
  322. package/test/unit/spec/meeting-info/index.js +293 -0
  323. package/test/unit/spec/meeting-info/meetinginfov2.js +517 -5
  324. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  325. package/test/unit/spec/meetings/collection.js +14 -0
  326. package/test/unit/spec/meetings/index.js +1007 -177
  327. package/test/unit/spec/meetings/utils.js +206 -2
  328. package/test/unit/spec/member/index.js +58 -4
  329. package/test/unit/spec/member/util.js +479 -35
  330. package/test/unit/spec/members/index.js +319 -1
  331. package/test/unit/spec/members/request.js +206 -27
  332. package/test/unit/spec/members/utils.js +184 -0
  333. package/test/unit/spec/metrics/index.js +1 -50
  334. package/test/unit/spec/multistream/mediaRequestManager.ts +803 -162
  335. package/test/unit/spec/multistream/receiveSlot.ts +72 -13
  336. package/test/unit/spec/multistream/receiveSlotManager.ts +58 -28
  337. package/test/unit/spec/multistream/remoteMedia.ts +30 -0
  338. package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
  339. package/test/unit/spec/multistream/remoteMediaManager.ts +326 -0
  340. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  341. package/test/unit/spec/reachability/index.ts +549 -9
  342. package/test/unit/spec/reachability/request.js +68 -0
  343. package/test/unit/spec/reconnection-manager/index.js +84 -9
  344. package/test/unit/spec/recording-controller/index.js +294 -218
  345. package/test/unit/spec/recording-controller/util.js +223 -96
  346. package/test/unit/spec/roap/index.ts +31 -51
  347. package/test/unit/spec/roap/request.ts +203 -85
  348. package/test/unit/spec/roap/turnDiscovery.ts +48 -13
  349. package/test/unit/spec/rtcMetrics/index.ts +68 -0
  350. package/test/unit/spec/stats-analyzer/index.js +29 -2
  351. package/test/utils/integrationTestUtils.js +46 -0
  352. package/test/utils/testUtils.js +0 -52
  353. package/dist/meeting/effectsState.js +0 -262
  354. package/dist/meeting/effectsState.js.map +0 -1
  355. package/dist/metrics/config.js +0 -299
  356. package/dist/metrics/config.js.map +0 -1
  357. package/dist/types/meeting/effectsState.d.ts +0 -42
  358. package/dist/types/metrics/config.d.ts +0 -178
  359. package/src/index.js +0 -16
  360. package/src/meeting/effectsState.ts +0 -211
  361. package/src/metrics/config.ts +0 -495
  362. 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: {},
@@ -153,6 +159,9 @@ describe('plugin-meetings', () => {
153
159
  type: 'inbound-rtp',
154
160
  framesDecoded: 0,
155
161
  bytesReceived: 1,
162
+ frameHeight: 720,
163
+ frameWidth: 1280,
164
+ framesReceived: 1,
156
165
  },
157
166
  ],
158
167
  },
@@ -184,7 +193,7 @@ describe('plugin-meetings', () => {
184
193
 
185
194
  networkQualityMonitor = new NetworkQualityMonitor(initialConfig);
186
195
 
187
- statsAnalyzer = new StatsAnalyzer(initialConfig, networkQualityMonitor);
196
+ statsAnalyzer = new StatsAnalyzer(initialConfig, () => ({}), networkQualityMonitor);
188
197
 
189
198
  statsAnalyzer.on(EVENTS.LOCAL_MEDIA_STARTED, (data) => {
190
199
  receivedEventsData.local.started = data;
@@ -198,6 +207,9 @@ describe('plugin-meetings', () => {
198
207
  statsAnalyzer.on(EVENTS.REMOTE_MEDIA_STOPPED, (data) => {
199
208
  receivedEventsData.remote.stopped = data;
200
209
  });
210
+ statsAnalyzer.on(EVENTS.MEDIA_QUALITY, ({data}) => {
211
+ mqeData = data;
212
+ });
201
213
  });
202
214
 
203
215
  afterEach(() => {
@@ -224,6 +236,12 @@ describe('plugin-meetings', () => {
224
236
  assert.deepEqual(receivedEventsData.remote.stopped, expected.remote?.stopped);
225
237
  };
226
238
 
239
+ const checkMqeData = () => {
240
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].receivedFrameSize, 3600);
241
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].receivedHeight, 720);
242
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].receivedWidth, 1280);
243
+ };
244
+
227
245
  it('emits LOCAL_MEDIA_STARTED and LOCAL_MEDIA_STOPPED events for audio', async () => {
228
246
  await startStatsAnalyzer({expected: {sendAudio: true}});
229
247
 
@@ -303,6 +321,15 @@ describe('plugin-meetings', () => {
303
321
 
304
322
  checkReceivedEvent({expected: {remote: {stopped: {type: 'video'}}}});
305
323
  });
324
+
325
+ it('emits the correct MEDIA_QUALITY events', async () => {
326
+ await startStatsAnalyzer({expected: {receiveVideo: true}});
327
+
328
+ await progressTime();
329
+
330
+ // Check that the mqe data has been emitted and is correctly computed.
331
+ checkMqeData();
332
+ });
306
333
  });
307
334
  });
308
335
  });
@@ -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
+ };