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

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 (539) hide show
  1. package/README.md +58 -8
  2. package/dist/annotation/annotation.types.d.ts +42 -0
  3. package/dist/annotation/annotation.types.js +7 -0
  4. package/dist/annotation/annotation.types.js.map +1 -0
  5. package/dist/annotation/constants.d.ts +31 -0
  6. package/dist/annotation/constants.js +41 -0
  7. package/dist/annotation/constants.js.map +1 -0
  8. package/dist/annotation/index.d.ts +117 -0
  9. package/dist/annotation/index.js +357 -0
  10. package/dist/annotation/index.js.map +1 -0
  11. package/dist/breakouts/breakout.d.ts +8 -0
  12. package/dist/breakouts/breakout.js +215 -0
  13. package/dist/breakouts/breakout.js.map +1 -0
  14. package/dist/breakouts/collection.d.ts +5 -0
  15. package/dist/breakouts/collection.js +22 -0
  16. package/dist/breakouts/collection.js.map +1 -0
  17. package/dist/breakouts/edit-lock-error.d.ts +15 -0
  18. package/dist/breakouts/edit-lock-error.js +51 -0
  19. package/dist/breakouts/edit-lock-error.js.map +1 -0
  20. package/dist/breakouts/events.d.ts +8 -0
  21. package/dist/breakouts/events.js +44 -0
  22. package/dist/breakouts/events.js.map +1 -0
  23. package/dist/breakouts/index.d.ts +5 -0
  24. package/dist/breakouts/index.js +1047 -0
  25. package/dist/breakouts/index.js.map +1 -0
  26. package/dist/breakouts/request.d.ts +22 -0
  27. package/dist/breakouts/request.js +77 -0
  28. package/dist/breakouts/request.js.map +1 -0
  29. package/dist/breakouts/utils.d.ts +15 -0
  30. package/dist/breakouts/utils.js +64 -0
  31. package/dist/breakouts/utils.js.map +1 -0
  32. package/dist/common/browser-detection.js +2 -3
  33. package/dist/common/browser-detection.js.map +1 -1
  34. package/dist/common/collection.js +3 -4
  35. package/dist/common/collection.js.map +1 -1
  36. package/dist/common/config.js +1 -2
  37. package/dist/common/config.js.map +1 -1
  38. package/dist/common/errors/captcha-error.js +1 -2
  39. package/dist/common/errors/captcha-error.js.map +1 -1
  40. package/dist/common/errors/intent-to-join.js +1 -2
  41. package/dist/common/errors/intent-to-join.js.map +1 -1
  42. package/dist/common/errors/join-meeting.js +1 -2
  43. package/dist/common/errors/join-meeting.js.map +1 -1
  44. package/dist/common/errors/media.js +1 -2
  45. package/dist/common/errors/media.js.map +1 -1
  46. package/dist/common/errors/no-meeting-info.d.ts +14 -0
  47. package/dist/common/errors/no-meeting-info.js +50 -0
  48. package/dist/common/errors/no-meeting-info.js.map +1 -0
  49. package/dist/common/errors/parameter.js +3 -4
  50. package/dist/common/errors/parameter.js.map +1 -1
  51. package/dist/common/errors/password-error.js +1 -2
  52. package/dist/common/errors/password-error.js.map +1 -1
  53. package/dist/common/errors/permission.js +1 -2
  54. package/dist/common/errors/permission.js.map +1 -1
  55. package/dist/common/errors/{reclaim-host-role-error.js → reclaim-host-role-errors.js} +7 -11
  56. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  57. package/dist/common/errors/reconnection-in-progress.js +1 -2
  58. package/dist/common/errors/reconnection-in-progress.js.map +1 -1
  59. package/dist/common/errors/reconnection.js +1 -2
  60. package/dist/common/errors/reconnection.js.map +1 -1
  61. package/dist/common/errors/stats.js +1 -2
  62. package/dist/common/errors/stats.js.map +1 -1
  63. package/dist/common/errors/webex-errors.d.ts +20 -8
  64. package/dist/common/errors/webex-errors.js +48 -28
  65. package/dist/common/errors/webex-errors.js.map +1 -1
  66. package/dist/common/errors/webex-meetings-error.js +1 -2
  67. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  68. package/dist/common/events/events-scope.js +1 -2
  69. package/dist/common/events/events-scope.js.map +1 -1
  70. package/dist/common/events/events.js +1 -2
  71. package/dist/common/events/events.js.map +1 -1
  72. package/dist/common/events/trigger-proxy.js +1 -2
  73. package/dist/common/events/trigger-proxy.js.map +1 -1
  74. package/dist/common/events/util.js +1 -2
  75. package/dist/common/events/util.js.map +1 -1
  76. package/dist/common/logs/logger-config.js +1 -2
  77. package/dist/common/logs/logger-config.js.map +1 -1
  78. package/dist/common/logs/logger-proxy.js +2 -3
  79. package/dist/common/logs/logger-proxy.js.map +1 -1
  80. package/dist/common/logs/request.d.ts +3 -1
  81. package/dist/common/logs/request.js +8 -5
  82. package/dist/common/logs/request.js.map +1 -1
  83. package/dist/common/queue.d.ts +9 -7
  84. package/dist/common/queue.js +22 -9
  85. package/dist/common/queue.js.map +1 -1
  86. package/dist/config.d.ts +6 -7
  87. package/dist/config.js +8 -10
  88. package/dist/config.js.map +1 -1
  89. package/dist/constants.d.ts +234 -100
  90. package/dist/constants.js +433 -444
  91. package/dist/constants.js.map +1 -1
  92. package/dist/controls-options-manager/constants.js +3 -6
  93. package/dist/controls-options-manager/constants.js.map +1 -1
  94. package/dist/controls-options-manager/enums.d.ts +11 -1
  95. package/dist/controls-options-manager/enums.js +15 -6
  96. package/dist/controls-options-manager/enums.js.map +1 -1
  97. package/dist/controls-options-manager/index.d.ts +17 -1
  98. package/dist/controls-options-manager/index.js +127 -38
  99. package/dist/controls-options-manager/index.js.map +1 -1
  100. package/dist/controls-options-manager/types.d.ts +43 -0
  101. package/dist/controls-options-manager/types.js +7 -0
  102. package/dist/controls-options-manager/types.js.map +1 -0
  103. package/dist/controls-options-manager/util.d.ts +1 -7
  104. package/dist/controls-options-manager/util.js +309 -19
  105. package/dist/controls-options-manager/util.js.map +1 -1
  106. package/dist/index.d.ts +6 -3
  107. package/dist/index.js +121 -5
  108. package/dist/index.js.map +1 -1
  109. package/dist/interceptors/index.d.ts +2 -0
  110. package/dist/interceptors/index.js +15 -0
  111. package/dist/interceptors/index.js.map +1 -0
  112. package/dist/interceptors/locusRetry.d.ts +27 -0
  113. package/dist/interceptors/locusRetry.js +94 -0
  114. package/dist/interceptors/locusRetry.js.map +1 -0
  115. package/dist/interpretation/collection.d.ts +5 -0
  116. package/dist/interpretation/collection.js +22 -0
  117. package/dist/interpretation/collection.js.map +1 -0
  118. package/dist/interpretation/index.d.ts +5 -0
  119. package/dist/interpretation/index.js +365 -0
  120. package/dist/interpretation/index.js.map +1 -0
  121. package/dist/interpretation/siLanguage.d.ts +5 -0
  122. package/dist/interpretation/siLanguage.js +24 -0
  123. package/dist/interpretation/siLanguage.js.map +1 -0
  124. package/dist/locus-info/controlsUtils.js +100 -11
  125. package/dist/locus-info/controlsUtils.js.map +1 -1
  126. package/dist/locus-info/embeddedAppsUtils.js +3 -4
  127. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  128. package/dist/locus-info/fullState.js +1 -2
  129. package/dist/locus-info/fullState.js.map +1 -1
  130. package/dist/locus-info/hostUtils.js +1 -2
  131. package/dist/locus-info/hostUtils.js.map +1 -1
  132. package/dist/locus-info/index.d.ts +57 -4
  133. package/dist/locus-info/index.js +425 -84
  134. package/dist/locus-info/index.js.map +1 -1
  135. package/dist/locus-info/infoUtils.js +13 -5
  136. package/dist/locus-info/infoUtils.js.map +1 -1
  137. package/dist/locus-info/mediaSharesUtils.js +58 -3
  138. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  139. package/dist/locus-info/parser.d.ts +66 -6
  140. package/dist/locus-info/parser.js +253 -80
  141. package/dist/locus-info/parser.js.map +1 -1
  142. package/dist/locus-info/selfUtils.js +97 -13
  143. package/dist/locus-info/selfUtils.js.map +1 -1
  144. package/dist/media/index.d.ts +2 -0
  145. package/dist/media/index.js +107 -319
  146. package/dist/media/index.js.map +1 -1
  147. package/dist/media/properties.d.ts +38 -53
  148. package/dist/media/properties.js +96 -153
  149. package/dist/media/properties.js.map +1 -1
  150. package/dist/media/util.js +1 -22
  151. package/dist/media/util.js.map +1 -1
  152. package/dist/mediaQualityMetrics/config.d.ts +234 -230
  153. package/dist/mediaQualityMetrics/config.js +302 -498
  154. package/dist/mediaQualityMetrics/config.js.map +1 -1
  155. package/dist/meeting/in-meeting-actions.d.ts +88 -0
  156. package/dist/meeting/in-meeting-actions.js +94 -3
  157. package/dist/meeting/in-meeting-actions.js.map +1 -1
  158. package/dist/meeting/index.d.ts +705 -520
  159. package/dist/meeting/index.js +5047 -3089
  160. package/dist/meeting/index.js.map +1 -1
  161. package/dist/meeting/locusMediaRequest.d.ts +74 -0
  162. package/dist/meeting/locusMediaRequest.js +291 -0
  163. package/dist/meeting/locusMediaRequest.js.map +1 -0
  164. package/dist/meeting/muteState.d.ts +93 -25
  165. package/dist/meeting/muteState.js +224 -133
  166. package/dist/meeting/muteState.js.map +1 -1
  167. package/dist/meeting/request.d.ts +82 -47
  168. package/dist/meeting/request.js +304 -199
  169. package/dist/meeting/request.js.map +1 -1
  170. package/dist/meeting/request.type.d.ts +11 -0
  171. package/dist/meeting/request.type.js +7 -0
  172. package/dist/meeting/request.type.js.map +1 -0
  173. package/dist/meeting/state.js +1 -2
  174. package/dist/meeting/state.js.map +1 -1
  175. package/dist/meeting/util.d.ts +118 -1
  176. package/dist/meeting/util.js +676 -435
  177. package/dist/meeting/util.js.map +1 -1
  178. package/dist/meeting/voicea-meeting.d.ts +20 -0
  179. package/dist/meeting/voicea-meeting.js +201 -0
  180. package/dist/meeting/voicea-meeting.js.map +1 -0
  181. package/dist/meeting-info/collection.js +3 -4
  182. package/dist/meeting-info/collection.js.map +1 -1
  183. package/dist/meeting-info/index.d.ts +13 -1
  184. package/dist/meeting-info/index.js +74 -7
  185. package/dist/meeting-info/index.js.map +1 -1
  186. package/dist/meeting-info/meeting-info-v2.d.ts +31 -1
  187. package/dist/meeting-info/meeting-info-v2.js +200 -63
  188. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  189. package/dist/meeting-info/request.js +1 -2
  190. package/dist/meeting-info/request.js.map +1 -1
  191. package/dist/meeting-info/util.js +2 -3
  192. package/dist/meeting-info/util.js.map +1 -1
  193. package/dist/meeting-info/utilv2.js +39 -41
  194. package/dist/meeting-info/utilv2.js.map +1 -1
  195. package/dist/meetings/collection.d.ts +17 -0
  196. package/dist/meetings/collection.js +42 -4
  197. package/dist/meetings/collection.js.map +1 -1
  198. package/dist/meetings/index.d.ts +114 -20
  199. package/dist/meetings/index.js +540 -126
  200. package/dist/meetings/index.js.map +1 -1
  201. package/dist/meetings/meetings.types.d.ts +4 -0
  202. package/dist/meetings/meetings.types.js +7 -0
  203. package/dist/meetings/meetings.types.js.map +1 -0
  204. package/dist/meetings/request.js +4 -3
  205. package/dist/meetings/request.js.map +1 -1
  206. package/dist/meetings/util.js +107 -6
  207. package/dist/meetings/util.js.map +1 -1
  208. package/dist/member/index.d.ts +13 -1
  209. package/dist/member/index.js +45 -2
  210. package/dist/member/index.js.map +1 -1
  211. package/dist/member/member.types.js +3 -4
  212. package/dist/member/member.types.js.map +1 -1
  213. package/dist/member/types.d.ts +32 -0
  214. package/dist/member/types.js +23 -0
  215. package/dist/member/types.js.map +1 -0
  216. package/dist/member/util.js +120 -29
  217. package/dist/member/util.js.map +1 -1
  218. package/dist/members/collection.d.ts +5 -0
  219. package/dist/members/collection.js +11 -2
  220. package/dist/members/collection.js.map +1 -1
  221. package/dist/members/index.d.ts +56 -11
  222. package/dist/members/index.js +174 -47
  223. package/dist/members/index.js.map +1 -1
  224. package/dist/members/request.d.ts +67 -11
  225. package/dist/members/request.js +102 -54
  226. package/dist/members/request.js.map +1 -1
  227. package/dist/members/types.js +3 -4
  228. package/dist/members/types.js.map +1 -1
  229. package/dist/members/util.d.ts +214 -1
  230. package/dist/members/util.js +327 -284
  231. package/dist/members/util.js.map +1 -1
  232. package/dist/metrics/constants.d.ts +15 -6
  233. package/dist/metrics/constants.js +17 -9
  234. package/dist/metrics/constants.js.map +1 -1
  235. package/dist/metrics/index.d.ts +4 -111
  236. package/dist/metrics/index.js +4 -452
  237. package/dist/metrics/index.js.map +1 -1
  238. package/dist/multistream/mediaRequestManager.d.ts +118 -0
  239. package/dist/multistream/mediaRequestManager.js +344 -0
  240. package/dist/multistream/mediaRequestManager.js.map +1 -0
  241. package/dist/multistream/receiveSlot.d.ts +68 -0
  242. package/dist/multistream/receiveSlot.js +200 -0
  243. package/dist/multistream/receiveSlot.js.map +1 -0
  244. package/dist/multistream/receiveSlotManager.d.ts +56 -0
  245. package/dist/multistream/receiveSlotManager.js +174 -0
  246. package/dist/multistream/receiveSlotManager.js.map +1 -0
  247. package/dist/multistream/remoteMedia.d.ts +72 -0
  248. package/dist/multistream/remoteMedia.js +268 -0
  249. package/dist/multistream/remoteMedia.js.map +1 -0
  250. package/dist/multistream/remoteMediaGroup.d.ts +47 -0
  251. package/dist/multistream/remoteMediaGroup.js +267 -0
  252. package/dist/multistream/remoteMediaGroup.js.map +1 -0
  253. package/dist/multistream/remoteMediaManager.d.ts +285 -0
  254. package/dist/multistream/remoteMediaManager.js +1211 -0
  255. package/dist/multistream/remoteMediaManager.js.map +1 -0
  256. package/dist/multistream/sendSlotManager.d.ts +61 -0
  257. package/dist/multistream/sendSlotManager.js +236 -0
  258. package/dist/multistream/sendSlotManager.js.map +1 -0
  259. package/dist/networkQualityMonitor/index.js +5 -4
  260. package/dist/networkQualityMonitor/index.js.map +1 -1
  261. package/dist/personal-meeting-room/index.js +2 -3
  262. package/dist/personal-meeting-room/index.js.map +1 -1
  263. package/dist/personal-meeting-room/request.js +2 -3
  264. package/dist/personal-meeting-room/request.js.map +1 -1
  265. package/dist/personal-meeting-room/util.js +1 -2
  266. package/dist/personal-meeting-room/util.js.map +1 -1
  267. package/dist/reachability/clusterReachability.d.ts +109 -0
  268. package/dist/reachability/clusterReachability.js +357 -0
  269. package/dist/reachability/clusterReachability.js.map +1 -0
  270. package/dist/reachability/index.d.ts +61 -95
  271. package/dist/reachability/index.js +304 -392
  272. package/dist/reachability/index.js.map +1 -1
  273. package/dist/reachability/request.d.ts +7 -3
  274. package/dist/reachability/request.js +18 -10
  275. package/dist/reachability/request.js.map +1 -1
  276. package/dist/reachability/util.d.ts +8 -0
  277. package/dist/reachability/util.js +29 -0
  278. package/dist/reachability/util.js.map +1 -0
  279. package/dist/reactions/constants.d.ts +3 -0
  280. package/dist/reactions/constants.js +12 -0
  281. package/dist/reactions/constants.js.map +1 -0
  282. package/dist/reactions/reactions.d.ts +2 -2
  283. package/dist/reactions/reactions.js +4 -6
  284. package/dist/reactions/reactions.js.map +1 -1
  285. package/dist/reactions/reactions.type.d.ts +23 -3
  286. package/dist/reactions/reactions.type.js +21 -23
  287. package/dist/reactions/reactions.type.js.map +1 -1
  288. package/dist/reconnection-manager/index.d.ts +32 -8
  289. package/dist/reconnection-manager/index.js +285 -232
  290. package/dist/reconnection-manager/index.js.map +1 -1
  291. package/dist/recording-controller/enums.js +4 -5
  292. package/dist/recording-controller/enums.js.map +1 -1
  293. package/dist/recording-controller/index.d.ts +15 -1
  294. package/dist/recording-controller/index.js +57 -46
  295. package/dist/recording-controller/index.js.map +1 -1
  296. package/dist/recording-controller/util.d.ts +5 -4
  297. package/dist/recording-controller/util.js +10 -10
  298. package/dist/recording-controller/util.js.map +1 -1
  299. package/dist/roap/index.d.ts +9 -47
  300. package/dist/roap/index.js +100 -238
  301. package/dist/roap/index.js.map +1 -1
  302. package/dist/roap/request.d.ts +18 -12
  303. package/dist/roap/request.js +126 -180
  304. package/dist/roap/request.js.map +1 -1
  305. package/dist/roap/turnDiscovery.d.ts +27 -16
  306. package/dist/roap/turnDiscovery.js +115 -105
  307. package/dist/roap/turnDiscovery.js.map +1 -1
  308. package/dist/rtcMetrics/constants.d.ts +4 -0
  309. package/dist/rtcMetrics/constants.js +11 -0
  310. package/dist/rtcMetrics/constants.js.map +1 -0
  311. package/dist/rtcMetrics/index.d.ts +54 -0
  312. package/dist/rtcMetrics/index.js +140 -0
  313. package/dist/rtcMetrics/index.js.map +1 -0
  314. package/dist/statsAnalyzer/global.d.ts +1 -83
  315. package/dist/statsAnalyzer/global.js +2 -85
  316. package/dist/statsAnalyzer/global.js.map +1 -1
  317. package/dist/statsAnalyzer/index.d.ts +50 -30
  318. package/dist/statsAnalyzer/index.js +436 -511
  319. package/dist/statsAnalyzer/index.js.map +1 -1
  320. package/dist/statsAnalyzer/mqaUtil.d.ts +8 -6
  321. package/dist/statsAnalyzer/mqaUtil.js +130 -90
  322. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  323. package/dist/transcription/index.js +1 -2
  324. package/dist/transcription/index.js.map +1 -1
  325. package/dist/webinar/collection.d.ts +16 -0
  326. package/dist/webinar/collection.js +43 -0
  327. package/dist/webinar/collection.js.map +1 -0
  328. package/dist/webinar/index.d.ts +5 -0
  329. package/dist/webinar/index.js +68 -0
  330. package/dist/webinar/index.js.map +1 -0
  331. package/package.json +39 -26
  332. package/src/annotation/annotation.types.ts +50 -0
  333. package/src/annotation/constants.ts +36 -0
  334. package/src/annotation/index.ts +328 -0
  335. package/src/breakouts/README.md +220 -0
  336. package/src/breakouts/breakout.ts +188 -0
  337. package/src/breakouts/collection.ts +19 -0
  338. package/src/breakouts/edit-lock-error.ts +25 -0
  339. package/src/breakouts/events.ts +56 -0
  340. package/src/breakouts/index.ts +925 -0
  341. package/src/breakouts/request.ts +55 -0
  342. package/src/breakouts/utils.ts +57 -0
  343. package/src/common/errors/no-meeting-info.ts +24 -0
  344. package/src/common/errors/webex-errors.ts +36 -12
  345. package/src/common/logs/logger-proxy.ts +1 -1
  346. package/src/common/logs/request.ts +5 -1
  347. package/src/common/queue.ts +22 -8
  348. package/src/config.ts +6 -7
  349. package/src/constants.ts +265 -100
  350. package/src/controls-options-manager/enums.ts +12 -0
  351. package/src/controls-options-manager/index.ts +116 -21
  352. package/src/controls-options-manager/types.ts +59 -0
  353. package/src/controls-options-manager/util.ts +294 -14
  354. package/src/index.ts +44 -0
  355. package/src/interceptors/index.ts +3 -0
  356. package/src/interceptors/locusRetry.ts +67 -0
  357. package/src/interpretation/README.md +60 -0
  358. package/src/interpretation/collection.ts +19 -0
  359. package/src/interpretation/index.ts +332 -0
  360. package/src/interpretation/siLanguage.ts +18 -0
  361. package/src/locus-info/controlsUtils.ts +110 -0
  362. package/src/locus-info/index.ts +450 -61
  363. package/src/locus-info/infoUtils.ts +14 -2
  364. package/src/locus-info/mediaSharesUtils.ts +64 -0
  365. package/src/locus-info/parser.ts +258 -47
  366. package/src/locus-info/selfUtils.ts +85 -2
  367. package/src/media/index.ts +153 -370
  368. package/src/media/properties.ts +106 -136
  369. package/src/media/util.ts +0 -21
  370. package/src/mediaQualityMetrics/config.ts +244 -377
  371. package/src/meeting/in-meeting-actions.ts +176 -0
  372. package/src/meeting/index.ts +4306 -2581
  373. package/src/meeting/locusMediaRequest.ts +313 -0
  374. package/src/meeting/muteState.ts +224 -138
  375. package/src/meeting/request.ts +214 -127
  376. package/src/meeting/request.type.ts +13 -0
  377. package/src/meeting/util.ts +687 -423
  378. package/src/meeting/voicea-meeting.ts +161 -0
  379. package/src/meeting-info/index.ts +81 -8
  380. package/src/meeting-info/meeting-info-v2.ts +163 -13
  381. package/src/meeting-info/util.ts +1 -1
  382. package/src/meeting-info/utilv2.ts +28 -28
  383. package/src/meetings/collection.ts +33 -0
  384. package/src/meetings/index.ts +529 -127
  385. package/src/meetings/meetings.types.ts +12 -0
  386. package/src/meetings/request.ts +2 -0
  387. package/src/meetings/util.ts +116 -5
  388. package/src/member/index.ts +43 -1
  389. package/src/member/types.ts +38 -0
  390. package/src/member/util.ts +125 -28
  391. package/src/members/collection.ts +8 -0
  392. package/src/members/index.ts +187 -52
  393. package/src/members/request.ts +87 -27
  394. package/src/members/util.ts +332 -291
  395. package/src/metrics/constants.ts +15 -6
  396. package/src/metrics/index.ts +1 -471
  397. package/src/multistream/mediaRequestManager.ts +440 -0
  398. package/src/multistream/receiveSlot.ts +184 -0
  399. package/src/multistream/receiveSlotManager.ts +166 -0
  400. package/src/multistream/remoteMedia.ts +254 -0
  401. package/src/multistream/remoteMediaGroup.ts +284 -0
  402. package/src/multistream/remoteMediaManager.ts +1145 -0
  403. package/src/multistream/sendSlotManager.ts +170 -0
  404. package/src/networkQualityMonitor/index.ts +6 -6
  405. package/src/reachability/clusterReachability.ts +320 -0
  406. package/src/reachability/index.ts +246 -347
  407. package/src/reachability/request.ts +17 -8
  408. package/src/reachability/util.ts +24 -0
  409. package/src/reactions/constants.ts +4 -0
  410. package/src/reactions/reactions.ts +4 -4
  411. package/src/reactions/reactions.type.ts +30 -4
  412. package/src/reconnection-manager/index.ts +168 -156
  413. package/src/recording-controller/index.ts +20 -3
  414. package/src/recording-controller/util.ts +26 -9
  415. package/src/roap/index.ts +96 -241
  416. package/src/roap/request.ts +74 -148
  417. package/src/roap/turnDiscovery.ts +62 -56
  418. package/src/rtcMetrics/constants.ts +3 -0
  419. package/src/rtcMetrics/index.ts +124 -0
  420. package/src/statsAnalyzer/global.ts +1 -84
  421. package/src/statsAnalyzer/index.ts +479 -645
  422. package/src/statsAnalyzer/mqaUtil.ts +128 -126
  423. package/src/webinar/collection.ts +31 -0
  424. package/src/webinar/index.ts +62 -0
  425. package/test/integration/spec/converged-space-meetings.js +233 -0
  426. package/test/integration/spec/journey.js +320 -264
  427. package/test/integration/spec/space-meeting.js +77 -4
  428. package/test/unit/spec/annotation/index.ts +418 -0
  429. package/test/unit/spec/breakouts/breakout.ts +237 -0
  430. package/test/unit/spec/breakouts/collection.ts +15 -0
  431. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  432. package/test/unit/spec/breakouts/events.ts +89 -0
  433. package/test/unit/spec/breakouts/index.ts +1790 -0
  434. package/test/unit/spec/breakouts/request.ts +104 -0
  435. package/test/unit/spec/breakouts/utils.js +72 -0
  436. package/test/unit/spec/common/queue.js +31 -2
  437. package/test/unit/spec/controls-options-manager/index.js +163 -0
  438. package/test/unit/spec/controls-options-manager/util.js +576 -60
  439. package/test/unit/spec/fixture/locus.js +1 -0
  440. package/test/unit/spec/interceptors/locusRetry.ts +131 -0
  441. package/test/unit/spec/interpretation/collection.ts +15 -0
  442. package/test/unit/spec/interpretation/index.ts +589 -0
  443. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  444. package/test/unit/spec/locus-info/controlsUtils.js +323 -30
  445. package/test/unit/spec/locus-info/index.js +1438 -16
  446. package/test/unit/spec/locus-info/infoUtils.js +54 -16
  447. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  448. package/test/unit/spec/locus-info/lib/selfConstant.js +48 -0
  449. package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
  450. package/test/unit/spec/locus-info/parser.js +116 -35
  451. package/test/unit/spec/locus-info/selfUtils.js +275 -0
  452. package/test/unit/spec/media/index.ts +290 -0
  453. package/test/unit/spec/media/properties.ts +75 -84
  454. package/test/unit/spec/meeting/in-meeting-actions.ts +86 -0
  455. package/test/unit/spec/meeting/index.js +8886 -2815
  456. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  457. package/test/unit/spec/meeting/muteState.js +409 -213
  458. package/test/unit/spec/meeting/request.js +523 -43
  459. package/test/unit/spec/meeting/utils.js +834 -24
  460. package/test/unit/spec/meeting-info/index.js +300 -0
  461. package/test/unit/spec/meeting-info/meetinginfov2.js +527 -5
  462. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  463. package/test/unit/spec/meetings/collection.js +26 -0
  464. package/test/unit/spec/meetings/index.js +1446 -217
  465. package/test/unit/spec/meetings/utils.js +202 -2
  466. package/test/unit/spec/member/index.js +32 -9
  467. package/test/unit/spec/member/util.js +499 -61
  468. package/test/unit/spec/members/index.js +394 -5
  469. package/test/unit/spec/members/request.js +206 -27
  470. package/test/unit/spec/members/utils.js +173 -38
  471. package/test/unit/spec/metrics/index.js +1 -50
  472. package/test/unit/spec/multistream/mediaRequestManager.ts +1418 -0
  473. package/test/unit/spec/multistream/receiveSlot.ts +163 -0
  474. package/test/unit/spec/multistream/receiveSlotManager.ts +203 -0
  475. package/test/unit/spec/multistream/remoteMedia.ts +255 -0
  476. package/test/unit/spec/multistream/remoteMediaGroup.ts +662 -0
  477. package/test/unit/spec/multistream/remoteMediaManager.ts +1924 -0
  478. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  479. package/test/unit/spec/networkQualityMonitor/index.js +4 -4
  480. package/test/unit/spec/reachability/clusterReachability.ts +279 -0
  481. package/test/unit/spec/reachability/index.ts +532 -24
  482. package/test/unit/spec/reachability/request.js +68 -0
  483. package/test/unit/spec/reachability/util.ts +40 -0
  484. package/test/unit/spec/reconnection-manager/index.js +163 -24
  485. package/test/unit/spec/recording-controller/index.js +293 -218
  486. package/test/unit/spec/recording-controller/util.js +223 -96
  487. package/test/unit/spec/roap/index.ts +187 -77
  488. package/test/unit/spec/roap/request.ts +255 -0
  489. package/test/unit/spec/roap/turnDiscovery.ts +86 -48
  490. package/test/unit/spec/rtcMetrics/index.ts +93 -0
  491. package/test/unit/spec/stats-analyzer/index.js +644 -165
  492. package/test/unit/spec/webinar/collection.ts +13 -0
  493. package/test/unit/spec/webinar/index.ts +60 -0
  494. package/test/utils/constants.js +9 -0
  495. package/test/utils/integrationTestUtils.js +46 -0
  496. package/test/utils/testUtils.js +0 -45
  497. package/test/utils/webex-config.js +4 -0
  498. package/test/utils/webex-test-users.js +7 -3
  499. package/dist/common/errors/reclaim-host-role-error.js.map +0 -1
  500. package/dist/meeting/effectsState.d.ts +0 -42
  501. package/dist/meeting/effectsState.js +0 -260
  502. package/dist/meeting/effectsState.js.map +0 -1
  503. package/dist/metrics/config.d.ts +0 -169
  504. package/dist/metrics/config.js +0 -289
  505. package/dist/metrics/config.js.map +0 -1
  506. package/dist/peer-connection-manager/index.d.ts +0 -6
  507. package/dist/peer-connection-manager/index.js +0 -671
  508. package/dist/peer-connection-manager/index.js.map +0 -1
  509. package/dist/peer-connection-manager/util.d.ts +0 -6
  510. package/dist/peer-connection-manager/util.js +0 -110
  511. package/dist/peer-connection-manager/util.js.map +0 -1
  512. package/dist/roap/collection.d.ts +0 -10
  513. package/dist/roap/collection.js +0 -63
  514. package/dist/roap/collection.js.map +0 -1
  515. package/dist/roap/handler.d.ts +0 -47
  516. package/dist/roap/handler.js +0 -279
  517. package/dist/roap/handler.js.map +0 -1
  518. package/dist/roap/state.d.ts +0 -9
  519. package/dist/roap/state.js +0 -127
  520. package/dist/roap/state.js.map +0 -1
  521. package/dist/roap/util.d.ts +0 -2
  522. package/dist/roap/util.js +0 -76
  523. package/dist/roap/util.js.map +0 -1
  524. package/src/index.js +0 -15
  525. package/src/meeting/effectsState.ts +0 -209
  526. package/src/metrics/config.ts +0 -485
  527. package/src/peer-connection-manager/index.ts +0 -847
  528. package/src/peer-connection-manager/util.ts +0 -119
  529. package/src/roap/collection.ts +0 -62
  530. package/src/roap/handler.ts +0 -294
  531. package/src/roap/state.ts +0 -156
  532. package/src/roap/util.ts +0 -100
  533. package/test/unit/spec/meeting/effectsState.js +0 -281
  534. package/test/unit/spec/peerconnection-manager/index.js +0 -218
  535. package/test/unit/spec/peerconnection-manager/utils.js +0 -49
  536. package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -388
  537. package/test/unit/spec/roap/util.js +0 -30
  538. /package/dist/common/errors/{reclaim-host-role-error.d.ts → reclaim-host-role-errors.d.ts} +0 -0
  539. /package/src/common/errors/{reclaim-host-role-error.ts → reclaim-host-role-errors.ts} +0 -0
@@ -2,10 +2,14 @@ import 'jsdom-global/register';
2
2
  import chai from 'chai';
3
3
  import chaiAsPromised from 'chai-as-promised';
4
4
  import sinon from 'sinon';
5
+ import {ConnectionState} from '@webex/internal-media-core';
5
6
 
6
7
  import {StatsAnalyzer, EVENTS} from '../../../../src/statsAnalyzer';
7
8
  import NetworkQualityMonitor from '../../../../src/networkQualityMonitor';
8
9
  import testUtils from '../../../utils/testUtils';
10
+ import {MEDIA_DEVICES, MQA_INTERVAL, _UNKNOWN_} from '@webex/plugin-meetings/src/constants';
11
+ import LoggerProxy from '../../../../src/common/logs/logger-proxy';
12
+ import LoggerConfig from '../../../../src/common/logs/logger-config';
9
13
 
10
14
  const {assert} = chai;
11
15
 
@@ -14,6 +18,156 @@ sinon.assert.expose(chai.assert, {prefix: ''});
14
18
 
15
19
  describe('plugin-meetings', () => {
16
20
  describe('StatsAnalyzer', () => {
21
+ describe('parseStatsResult', () => {
22
+ const sandbox = sinon.createSandbox();
23
+ let statsAnalyzer;
24
+
25
+ const initialConfig = {};
26
+ const defaultStats = {};
27
+
28
+ beforeEach(() => {
29
+ const networkQualityMonitor = new NetworkQualityMonitor(initialConfig);
30
+
31
+ statsAnalyzer = new StatsAnalyzer(
32
+ initialConfig,
33
+ () => ({}),
34
+ networkQualityMonitor,
35
+ defaultStats
36
+ );
37
+ });
38
+
39
+ afterEach(() => {
40
+ sandbox.reset();
41
+ });
42
+
43
+ it('should call processOutboundRTPResult', () => {
44
+ const calledSpy = sandbox.spy(statsAnalyzer, 'processOutboundRTPResult');
45
+ statsAnalyzer.parseGetStatsResult({ type: 'outbound-rtp' }, 'video-send');
46
+ assert(calledSpy.calledOnce);
47
+ });
48
+
49
+ it('should call processInboundRTPResult', () => {
50
+ const calledSpy = sandbox.spy(statsAnalyzer, 'processInboundRTPResult');
51
+ statsAnalyzer.parseGetStatsResult({ type: 'inbound-rtp' }, 'video-recv');
52
+ assert(calledSpy.calledOnce);
53
+ });
54
+
55
+ it('should call compareSentAndReceived', () => {
56
+ const calledSpy = sandbox.spy(statsAnalyzer, 'compareSentAndReceived');
57
+ statsAnalyzer.parseGetStatsResult({ type: 'remote-outbound-rtp' }, 'video-send');
58
+ assert(calledSpy.calledOnce);
59
+ });
60
+
61
+ it('should call parseCandidate', () => {
62
+ const calledSpy = sandbox.spy(statsAnalyzer, 'parseCandidate');
63
+ statsAnalyzer.parseGetStatsResult({ type: 'local-candidate' }, 'video-send');
64
+ assert(calledSpy.calledOnce);
65
+ });
66
+
67
+ it('processOutboundRTPResult should create the correct stats results', () => {
68
+ // establish the `statsResults` object.
69
+ statsAnalyzer.parseGetStatsResult({ type: 'none' }, 'audio-send', true);
70
+
71
+ statsAnalyzer.processOutboundRTPResult({
72
+ bytesSent: 50000,
73
+ codecId: "RTCCodec_1_Outbound_111",
74
+ headerBytesSent: 25000,
75
+ id: "RTCOutboundRTPAudioStream_123456789",
76
+ kind: "audio",
77
+ mediaSourceId: "RTCAudioSource_2",
78
+ mediaType: "audio",
79
+ nackCount: 1,
80
+ packetsSent: 3600,
81
+ remoteId: "RTCRemoteInboundRtpAudioStream_123456789",
82
+ retransmittedBytesSent: 100,
83
+ retransmittedPacketsSent: 2,
84
+ ssrc: 123456789,
85
+ targetBitrate: 256000,
86
+ timestamp: 1707341489336,
87
+ trackId: "RTCMediaStreamTrack_sender_2",
88
+ transportId: "RTCTransport_0_1",
89
+ type: "outbound-rtp",
90
+ }, 'audio-send', true);
91
+
92
+ assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.headerBytesSent, 25000);
93
+ assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.totalBytesSent, 50000);
94
+ assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.totalNackCount, 1);
95
+ assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.totalPacketsSent, 3600)
96
+ assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.retransmittedPacketsSent, 2);
97
+ assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.retransmittedBytesSent, 100);
98
+ });
99
+
100
+ it('processInboundRTPResult should create the correct stats results', () => {
101
+ // establish the `statsResults` object.
102
+ statsAnalyzer.parseGetStatsResult({ type: 'none' }, 'audio-recv-1', false);
103
+
104
+ statsAnalyzer.processInboundRTPResult({
105
+ audioLevel: 0,
106
+ bytesReceived: 509,
107
+ codecId: "RTCCodec_6_Inbound_111",
108
+ concealedSamples: 200000,
109
+ concealmentEvents: 13,
110
+ fecPacketsDiscarded: 1,
111
+ fecPacketsReceived: 1,
112
+ headerBytesReceived: 250,
113
+ id: "RTCInboundRTPAudioStream_123456789",
114
+ insertedSamplesForDeceleration: 0,
115
+ jitter: 0.012,
116
+ jitterBufferDelay: 1000,
117
+ jitterBufferEmittedCount: 10000,
118
+ kind: "audio",
119
+ lastPacketReceivedTimestamp: 1707341488529,
120
+ mediaType: "audio",
121
+ packetsDiscarded: 0,
122
+ packetsLost: 0,
123
+ packetsReceived: 12,
124
+ remoteId: "RTCRemoteOutboundRTPAudioStream_123456789",
125
+ removedSamplesForAcceleration: 0,
126
+ silentConcealedSamples: 200000,
127
+ ssrc: 123456789,
128
+ timestamp: 1707341489419,
129
+ totalAudioEnergy: 133,
130
+ totalSamplesDuration: 7,
131
+ totalSamplesReceived: 300000,
132
+ trackId: "RTCMediaStreamTrack_receiver_76",
133
+ transportId: "RTCTransport_0_1",
134
+ type: "inbound-rtp",
135
+ }, 'audio-recv-1', false);
136
+
137
+ assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.totalPacketsReceived, 12);
138
+ assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.fecPacketsDiscarded, 1);
139
+ assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.fecPacketsReceived, 1);
140
+ assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.totalBytesReceived, 509);
141
+ assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.headerBytesReceived, 250);
142
+ assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.audioLevel, 0);
143
+ assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.totalAudioEnergy, 133);
144
+ assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.totalSamplesReceived, 300000);
145
+ assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.totalSamplesDecoded, 0);
146
+ assert.strictEqual(statsAnalyzer.statsResults['audio-recv-1'].recv.concealedSamples, 200000);
147
+ });
148
+
149
+ it('parseAudioSource should create the correct stats results', () => {
150
+ // establish the `statsResults` object.
151
+ statsAnalyzer.parseGetStatsResult({ type: 'none' }, 'audio-send', true);
152
+
153
+ statsAnalyzer.parseAudioSource({
154
+ audioLevel: 0.03,
155
+ echoReturnLoss: -30,
156
+ echoReturnLossEnhancement: 0.17,
157
+ id: "RTCAudioSource_2",
158
+ kind: "audio",
159
+ timestamp: 1707341488160.012,
160
+ totalAudioEnergy: 0.001,
161
+ totalSamplesDuration: 4.5,
162
+ trackIdentifier: "2207e5bf-c595-4301-93f7-283994d8143f",
163
+ type: "media-source",
164
+ }, 'audio-send', true);
165
+
166
+ assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.audioLevel, 0.03);
167
+ assert.strictEqual(statsAnalyzer.statsResults['audio-send'].send.totalAudioEnergy, 0.001);
168
+ });
169
+ });
170
+
17
171
  describe('compareSentAndReceived()', () => {
18
172
  let statsAnalyzer;
19
173
  let sandBoxSpy;
@@ -23,14 +177,15 @@ describe('plugin-meetings', () => {
23
177
  };
24
178
 
25
179
  const defaultStats = {
180
+ resolutions: {},
26
181
  internal: {
27
- video: {
182
+ 'video-send-1': {
28
183
  send: {
29
184
  totalPacketsLostOnReceiver: 10,
30
185
  },
31
186
  },
32
187
  },
33
- video: {
188
+ 'video-send-1': {
34
189
  send: {
35
190
  packetsSent: 2,
36
191
  meanRemoteJitter: [],
@@ -51,7 +206,12 @@ describe('plugin-meetings', () => {
51
206
  beforeEach(() => {
52
207
  const networkQualityMonitor = new NetworkQualityMonitor(initialConfig);
53
208
 
54
- statsAnalyzer = new StatsAnalyzer(initialConfig, networkQualityMonitor, defaultStats);
209
+ statsAnalyzer = new StatsAnalyzer(
210
+ initialConfig,
211
+ () => ({}),
212
+ networkQualityMonitor,
213
+ defaultStats
214
+ );
55
215
 
56
216
  sandBoxSpy = sandbox.spy(
57
217
  statsAnalyzer.networkQualityMonitor,
@@ -64,12 +224,12 @@ describe('plugin-meetings', () => {
64
224
  });
65
225
 
66
226
  it('should trigger determineUplinkNetworkQuality with specific arguments', async () => {
67
- await statsAnalyzer.parseGetStatsResult(statusResult, 'video');
227
+ await statsAnalyzer.parseGetStatsResult(statusResult, 'video-send-1', true);
68
228
 
69
229
  assert.calledOnce(statsAnalyzer.networkQualityMonitor.determineUplinkNetworkQuality);
70
230
  assert(
71
231
  sandBoxSpy.calledWith({
72
- mediaType: 'video',
232
+ mediaType: 'video-send-1',
73
233
  remoteRtpResults: statusResult,
74
234
  statsAnalyzerCurrentStats: statsAnalyzer.statsResults,
75
235
  })
@@ -82,22 +242,8 @@ describe('plugin-meetings', () => {
82
242
  let pc;
83
243
  let networkQualityMonitor;
84
244
  let statsAnalyzer;
85
- const statusResultOutboundRTP = {
86
- type: 'outbound-rtp',
87
- frameHeight: 720,
88
- frameWidth: 1280,
89
- packetsLost: 11,
90
- framesSent: 105,
91
- hugeFramesSent: 1,
92
- framesEncoded: 102,
93
- rttThreshold: 501,
94
- jitterThreshold: 501,
95
- jitterBufferDelay: 288.131459,
96
- jitterBufferEmittedCount: 4013,
97
- trackIdentifier: '6bbf5506-6a7e-4397-951c-c05b72ab0ace',
98
- bytesSent: 1233,
99
- totalPacketsSent: 100,
100
- };
245
+ let mqeData;
246
+ let loggerSpy;
101
247
 
102
248
  let receivedEventsData = {
103
249
  local: {},
@@ -110,6 +256,8 @@ describe('plugin-meetings', () => {
110
256
 
111
257
  let fakeStats;
112
258
 
259
+ const sandbox = sinon.createSandbox();
260
+
113
261
  const resetReceivedEvents = () => {
114
262
  receivedEventsData = {
115
263
  local: {},
@@ -117,6 +265,12 @@ describe('plugin-meetings', () => {
117
265
  };
118
266
  };
119
267
 
268
+ before(() => {
269
+ LoggerConfig.set({ enable: false });
270
+ LoggerProxy.set();
271
+ loggerSpy = sandbox.spy(LoggerProxy.logger, 'info');
272
+ });
273
+
120
274
  beforeEach(() => {
121
275
  clock = sinon.useFakeTimers();
122
276
 
@@ -125,61 +279,165 @@ describe('plugin-meetings', () => {
125
279
  // bytesReceived and bytesSent need to be non-zero in order for StatsAnalyzer to parse any other values
126
280
  fakeStats = {
127
281
  audio: {
128
- receiver: {
129
- type: 'inbound-rtp',
130
- packetsReceived: 0,
131
- bytesReceived: 1,
132
- },
133
- sender: {
134
- type: 'outbound-rtp',
135
- packetsSent: 0,
136
- bytesSent: 1,
137
- },
282
+ senders: [
283
+ {
284
+ localTrackLabel: 'fake-microphone',
285
+ report: [
286
+ {
287
+ type: 'outbound-rtp',
288
+ bytesSent: 1,
289
+ packetsSent: 0,
290
+ },
291
+ {
292
+ type: 'remote-inbound-rtp',
293
+ packetsLost: 0,
294
+ },
295
+ {
296
+ type: 'candidate-pair',
297
+ state: 'succeeded',
298
+ localCandidateId: 'fake-candidate-id',
299
+ },
300
+ {
301
+ type: 'candidate-pair',
302
+ state: 'failed',
303
+ localCandidateId: 'bad-candidate-id',
304
+ },
305
+ {
306
+ type: 'local-candidate',
307
+ id: 'fake-candidate-id',
308
+ protocol: 'tcp',
309
+ },
310
+ ],
311
+ },
312
+ ],
313
+ receivers: [
314
+ {
315
+ report: [
316
+ {
317
+ type: 'inbound-rtp',
318
+ bytesReceived: 1,
319
+ fecPacketsDiscarded: 0,
320
+ fecPacketsReceived: 0,
321
+ packetsLost: 0,
322
+ packetsReceived: 0,
323
+ },
324
+ {
325
+ type: 'remote-outbound-rtp',
326
+ },
327
+ {
328
+ type: 'candidate-pair',
329
+ state: 'succeeded',
330
+ localCandidateId: 'fake-candidate-id',
331
+ },
332
+ {
333
+ type: 'candidate-pair',
334
+ state: 'failed',
335
+ localCandidateId: 'bad-candidate-id',
336
+ },
337
+ {
338
+ type: 'local-candidate',
339
+ id: 'fake-candidate-id',
340
+ protocol: 'tcp',
341
+ },
342
+ ],
343
+ },
344
+ ],
138
345
  },
139
346
  video: {
140
- receiver: {
141
- type: 'inbound-rtp',
142
- framesDecoded: 0,
143
- bytesReceived: 1,
144
- },
145
- sender: {
146
- type: 'outbound-rtp',
147
- framesSent: 0,
148
- bytesSent: 1,
149
- },
347
+ senders: [
348
+ {
349
+ localTrackLabel: 'fake-camera',
350
+ report: [
351
+ {
352
+ type: 'outbound-rtp',
353
+ bytesSent: 1,
354
+ framesSent: 0,
355
+ packetsSent: 0,
356
+ },
357
+ {
358
+ type: 'remote-inbound-rtp',
359
+ packetsLost: 0,
360
+ },
361
+ {
362
+ type: 'candidate-pair',
363
+ state: 'succeeded',
364
+ localCandidateId: 'fake-candidate-id',
365
+ },
366
+ {
367
+ type: 'candidate-pair',
368
+ state: 'failed',
369
+ localCandidateId: 'bad-candidate-id',
370
+ },
371
+ {
372
+ type: 'local-candidate',
373
+ id: 'fake-candidate-id',
374
+ protocol: 'tcp',
375
+ },
376
+ ],
377
+ },
378
+ ],
379
+ receivers: [
380
+ {
381
+ report: [
382
+ {
383
+ type: 'inbound-rtp',
384
+ bytesReceived: 1,
385
+ frameHeight: 720,
386
+ frameWidth: 1280,
387
+ framesDecoded: 0,
388
+ framesReceived: 0,
389
+ packetsLost: 0,
390
+ packetsReceived: 0,
391
+ },
392
+ {
393
+ type: 'remote-outbound-rtp',
394
+ },
395
+ {
396
+ type: 'candidate-pair',
397
+ state: 'succeeded',
398
+ localCandidateId: 'fake-candidate-id',
399
+ },
400
+ {
401
+ type: 'candidate-pair',
402
+ state: 'failed',
403
+ localCandidateId: 'bad-candidate-id',
404
+ },
405
+ {
406
+ type: 'local-candidate',
407
+ id: 'fake-candidate-id',
408
+ protocol: 'tcp',
409
+ },
410
+ ],
411
+ },
412
+ ],
150
413
  },
151
414
  };
152
415
 
153
416
  pc = {
154
- audioTransceiver: {
155
- sender: {
156
- getStats: sinon.stub().resolves([fakeStats.audio.sender]),
157
- },
158
- receiver: {
159
- getStats: sinon.stub().resolves([fakeStats.audio.receiver]),
417
+ getConnectionState: sinon.stub().returns(ConnectionState.Connected),
418
+ getTransceiverStats: sinon.stub().resolves({
419
+ audio: {
420
+ senders: [fakeStats.audio.senders[0]],
421
+ receivers: [fakeStats.audio.receivers[0]],
160
422
  },
161
- },
162
- videoTransceiver: {
163
- sender: {
164
- getStats: sinon.stub().resolves([fakeStats.video.sender]),
165
- },
166
- receiver: {
167
- getStats: sinon.stub().resolves([fakeStats.video.receiver]),
423
+ video: {
424
+ senders: [fakeStats.video.senders[0]],
425
+ receivers: [fakeStats.video.receivers[0]],
168
426
  },
169
- },
170
- shareTransceiver: {
171
- sender: {
172
- getStats: sinon.stub().resolves([]),
427
+ screenShareAudio: {
428
+ senders: [fakeStats.audio.senders[0]],
429
+ receivers: [fakeStats.audio.receivers[0]],
173
430
  },
174
- receiver: {
175
- getStats: sinon.stub().resolves([]),
431
+ screenShareVideo: {
432
+ senders: [fakeStats.video.senders[0]],
433
+ receivers: [fakeStats.video.receivers[0]],
176
434
  },
177
- },
435
+ }),
178
436
  };
179
437
 
180
438
  networkQualityMonitor = new NetworkQualityMonitor(initialConfig);
181
439
 
182
- statsAnalyzer = new StatsAnalyzer(initialConfig, networkQualityMonitor);
440
+ statsAnalyzer = new StatsAnalyzer(initialConfig, () => ({}), networkQualityMonitor);
183
441
 
184
442
  statsAnalyzer.on(EVENTS.LOCAL_MEDIA_STARTED, (data) => {
185
443
  receivedEventsData.local.started = data;
@@ -193,15 +451,13 @@ describe('plugin-meetings', () => {
193
451
  statsAnalyzer.on(EVENTS.REMOTE_MEDIA_STOPPED, (data) => {
194
452
  receivedEventsData.remote.stopped = data;
195
453
  });
196
- statsAnalyzer.on(EVENTS.NO_FRAMES_SENT, (data) => {
197
- receivedEventsData.noFramesSent = data;
198
- });
199
- statsAnalyzer.on(EVENTS.NO_VIDEO_ENCODED, (data) => {
200
- receivedEventsData.noVideoEncoded = data;
454
+ statsAnalyzer.on(EVENTS.MEDIA_QUALITY, ({data}) => {
455
+ mqeData = data;
201
456
  });
202
457
  });
203
458
 
204
459
  afterEach(() => {
460
+ sandbox.reset();
205
461
  clock.restore();
206
462
  });
207
463
 
@@ -212,8 +468,27 @@ describe('plugin-meetings', () => {
212
468
  await testUtils.flushPromises();
213
469
  };
214
470
 
215
- const progressTime = async () => {
216
- await clock.tickAsync(initialConfig.analyzerInterval);
471
+ const mergeProperties = (
472
+ target,
473
+ properties,
474
+ keyValue = 'fake-candidate-id',
475
+ matchKey = 'type',
476
+ matchValue = 'local-candidate'
477
+ ) => {
478
+ for (let key in target) {
479
+ if (target.hasOwnProperty(key)) {
480
+ if (typeof target[key] === 'object') {
481
+ mergeProperties(target[key], properties, keyValue, matchKey, matchValue);
482
+ }
483
+ if (key === 'id' && target[key] === keyValue && target[matchKey] === matchValue) {
484
+ Object.assign(target, properties);
485
+ }
486
+ }
487
+ }
488
+ };
489
+
490
+ const progressTime = async (time = initialConfig.analyzerInterval) => {
491
+ await clock.tickAsync(time);
217
492
  await testUtils.flushPromises();
218
493
  };
219
494
 
@@ -225,6 +500,23 @@ describe('plugin-meetings', () => {
225
500
  assert.deepEqual(receivedEventsData.remote.stopped, expected.remote?.stopped);
226
501
  };
227
502
 
503
+ const checkMqeData = () => {
504
+ for (const data of [
505
+ mqeData.audioTransmit,
506
+ mqeData.audioReceive,
507
+ mqeData.videoTransmit,
508
+ mqeData.videoReceive,
509
+ ]) {
510
+ assert.strictEqual(data.length, 2);
511
+ assert.strictEqual(data[0].common.common.isMain, true);
512
+ assert.strictEqual(data[1].common.common.isMain, false);
513
+ }
514
+
515
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].receivedFrameSize, 3600);
516
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].receivedHeight, 720);
517
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].receivedWidth, 1280);
518
+ };
519
+
228
520
  it('emits LOCAL_MEDIA_STARTED and LOCAL_MEDIA_STOPPED events for audio', async () => {
229
521
  await startStatsAnalyzer({expected: {sendAudio: true}});
230
522
 
@@ -232,7 +524,7 @@ describe('plugin-meetings', () => {
232
524
  checkReceivedEvent({expected: {}});
233
525
 
234
526
  // setup a mock to return some values higher the previous ones
235
- fakeStats.audio.sender.packetsSent += 10;
527
+ fakeStats.audio.senders[0].report[0].packetsSent += 10;
236
528
 
237
529
  await progressTime();
238
530
 
@@ -252,7 +544,7 @@ describe('plugin-meetings', () => {
252
544
  checkReceivedEvent({expected: {}});
253
545
 
254
546
  // setup a mock to return some values higher the previous ones
255
- fakeStats.video.sender.framesSent += 1;
547
+ fakeStats.video.senders[0].report[0].framesSent += 1;
256
548
 
257
549
  await progressTime();
258
550
 
@@ -272,7 +564,7 @@ describe('plugin-meetings', () => {
272
564
  checkReceivedEvent({expected: {}});
273
565
 
274
566
  // setup a mock to return some values higher the previous ones
275
- fakeStats.audio.receiver.packetsReceived += 5;
567
+ fakeStats.audio.receivers[0].report[0].packetsReceived += 5;
276
568
 
277
569
  await progressTime();
278
570
  // check that we got the REMOTE_MEDIA_STARTED event for audio
@@ -292,7 +584,7 @@ describe('plugin-meetings', () => {
292
584
  checkReceivedEvent({expected: {}});
293
585
 
294
586
  // setup a mock to return some values higher the previous ones
295
- fakeStats.video.receiver.framesDecoded += 1;
587
+ fakeStats.video.receivers[0].report[0].framesDecoded += 1;
296
588
 
297
589
  await progressTime();
298
590
  // check that we got the REMOTE_MEDIA_STARTED event for video
@@ -305,133 +597,320 @@ describe('plugin-meetings', () => {
305
597
  checkReceivedEvent({expected: {remote: {stopped: {type: 'video'}}}});
306
598
  });
307
599
 
308
- const checkStats = (type) => {
309
- const statsResult = {
310
- height: 720,
311
- width: 1280,
312
- jitterBufferDelay: 288.131459,
313
- jitterBufferEmittedCount: 4013,
314
- trackIdentifier: '6bbf5506-6a7e-4397-951c-c05b72ab0ace',
315
- avgJitterDelay: 0.07179951632195365,
316
- };
317
- if (type === 'inbound-rtp') {
318
- statsResult.framesDecoded = 4013;
319
- statsResult.framesDropped = 0;
320
- statsResult.framesReceived = 4016;
321
- assert.deepEqual(statsAnalyzer.statsResults.resolutions.video.recv, statsResult);
322
- } else if (type === 'outbound-rtp') {
323
- statsResult.framesSent = 105;
324
- statsResult.hugeFramesSent = 1;
325
- assert.deepEqual(statsAnalyzer.statsResults.resolutions.video.send, statsResult);
326
- }
327
- };
600
+ it('emits the correct MEDIA_QUALITY events', async () => {
601
+ await startStatsAnalyzer({expected: {receiveVideo: true}});
328
602
 
329
- it('processes track results and populate statsResults.resolutions object when type is inbound-rtp with video', async () => {
603
+ await progressTime();
604
+
605
+ // Check that the mqe data has been emitted and is correctly computed.
606
+ checkMqeData();
607
+ });
608
+
609
+ it('emits the correct transportType in MEDIA_QUALITY events', async () => {
330
610
  await startStatsAnalyzer({expected: {receiveVideo: true}});
331
- const statusResultInboundRTP = {
332
- type: 'inbound-rtp',
333
- frameHeight: 720,
334
- frameWidth: 1280,
335
- packetsLost: 11,
336
- rttThreshold: 501,
337
- jitterThreshold: 501,
338
- framesDecoded: 4013,
339
- framesDropped: 0,
340
- framesReceived: 4016,
341
- jitterBufferDelay: 288.131459,
342
- jitterBufferEmittedCount: 4013,
343
- trackIdentifier: '6bbf5506-6a7e-4397-951c-c05b72ab0ace',
344
- };
345
- await statsAnalyzer.parseGetStatsResult(statusResultInboundRTP, 'video');
346
- checkStats('inbound-rtp');
611
+
612
+ await progressTime();
613
+
614
+ assert.strictEqual(mqeData.audioTransmit[0].common.transportType, 'TCP');
615
+ assert.strictEqual(mqeData.videoReceive[0].common.transportType, 'TCP');
347
616
  });
348
- it('processes track results and populate statsResults.resolutions object when type is outbound-rtp with video', async () => {
617
+
618
+ it('emits the correct transportType in MEDIA_QUALITY events when using a TURN server', async () => {
619
+ fakeStats.audio.senders[0].report[4].relayProtocol = 'tls';
620
+ fakeStats.video.senders[0].report[4].relayProtocol = 'tls';
621
+ fakeStats.audio.receivers[0].report[4].relayProtocol = 'tls';
622
+ fakeStats.video.receivers[0].report[4].relayProtocol = 'tls';
623
+
349
624
  await startStatsAnalyzer({expected: {receiveVideo: true}});
350
625
 
351
- await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'video');
352
- checkStats('outbound-rtp');
626
+ await progressTime();
627
+
628
+ assert.strictEqual(mqeData.audioTransmit[0].common.transportType, 'TLS');
629
+ assert.strictEqual(mqeData.videoReceive[0].common.transportType, 'TLS');
353
630
  });
354
631
 
355
- it('doesnot processes track results with audio', async () => {
356
- await startStatsAnalyzer({expected: {receiveAudio: true}});
357
- await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'audio');
358
- assert.deepEqual(statsAnalyzer.statsResults.resolutions.audio, undefined);
632
+ it('emits the correct peripherals in MEDIA_QUALITY events', async () => {
633
+ await startStatsAnalyzer({expected: {receiveVideo: true}});
634
+
635
+ await progressTime();
636
+
637
+ assert.strictEqual(
638
+ mqeData.intervalMetadata.peripherals.find((val) => val.name === MEDIA_DEVICES.MICROPHONE)
639
+ .information,
640
+ 'fake-microphone'
641
+ );
642
+ assert.strictEqual(
643
+ mqeData.intervalMetadata.peripherals.find((val) => val.name === MEDIA_DEVICES.CAMERA)
644
+ .information,
645
+ 'fake-camera'
646
+ );
359
647
  });
360
648
 
361
- it('emits NO_FRAMES_ENCODED when frames are not being encoded', async () => {
362
- const expected = {mediaType: 'video'};
363
- await startStatsAnalyzer({expected: {sendVideo: true}});
649
+ it('emits the correct peripherals in MEDIA_QUALITY events when localTrackLabel is undefined', async () => {
650
+ fakeStats.audio.senders[0].localTrackLabel = undefined;
651
+ fakeStats.video.senders[0].localTrackLabel = undefined;
364
652
 
365
- statsAnalyzer.lastStatsResults.video.send = {framesEncoded: 102, totalPacketsSent: 106};
653
+ await startStatsAnalyzer({expected: {receiveVideo: true}});
366
654
 
367
- await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'video');
655
+ await progressTime();
368
656
 
369
- statsAnalyzer.compareLastStatsResult();
370
- assert.deepEqual(receivedEventsData.noVideoEncoded, expected);
657
+ assert.strictEqual(
658
+ mqeData.intervalMetadata.peripherals.find((val) => val.name === MEDIA_DEVICES.MICROPHONE)
659
+ .information,
660
+ _UNKNOWN_
661
+ );
662
+ assert.strictEqual(
663
+ mqeData.intervalMetadata.peripherals.find((val) => val.name === MEDIA_DEVICES.CAMERA)
664
+ .information,
665
+ _UNKNOWN_
666
+ );
371
667
  });
372
668
 
373
- it('emits NO_FRAMES_SENT when frames are not being sent but frames are being encoded', async () => {
374
- await startStatsAnalyzer({expected: {sendVideo: true}});
669
+ it('emits the correct transmittedFrameRate/receivedFrameRate', async () => {
670
+ it('at the start of the stats analyzer', async () => {
671
+ await startStatsAnalyzer();
672
+ assert.strictEqual(mqeData.videoTransmit[0].streams[0].common.transmittedFrameRate, 0);
673
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].common.receivedFrameRate, 0);
674
+ });
375
675
 
376
- const expected = {mediaType: 'video'};
676
+ it('after frames are sent and received', async () => {
677
+ fakeStats.video.senders[0].report[0].framesSent += 300;
678
+ fakeStats.video.receivers[0].report[0].framesReceived += 300;
679
+ await progressTime(MQA_INTERVAL);
377
680
 
378
- statsAnalyzer.lastStatsResults.video.send = {
379
- framesEncoded: 10,
380
- framesSent: 105,
381
- totalPacketsSent: 106,
382
- };
383
- await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'video');
681
+ // 300 frames in 60 seconds = 5 frames per second
682
+ assert.strictEqual(mqeData.videoTransmit[0].streams[0].common.transmittedFrameRate, 5);
683
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].common.receivedFrameRate, 5);
684
+ });
685
+ });
686
+
687
+ it('emits the correct rtpPackets', async () => {
688
+ it('at the start of the stats analyzer', async () => {
689
+ await startStatsAnalyzer();
690
+ assert.strictEqual(mqeData.audioTransmit[0].common.rtpPackets, 0);
691
+ assert.strictEqual(mqeData.audioTransmit[0].streams[0].common.rtpPackets, 0);
692
+ assert.strictEqual(mqeData.audioReceive[0].common.rtpPackets, 0);
693
+ assert.strictEqual(mqeData.audioReceive[0].streams[0].common.rtpPackets, 0);
694
+ assert.strictEqual(mqeData.videoTransmit[0].common.rtpPackets, 0);
695
+ assert.strictEqual(mqeData.videoTransmit[0].streams[0].common.rtpPackets, 0);
696
+ assert.strictEqual(mqeData.videoReceive[0].common.rtpPackets, 0);
697
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].common.rtpPackets, 0);
698
+ });
699
+
700
+ it('after packets are sent', async () => {
701
+ fakeStats.audio.senders[0].report[0].packetsSent += 5;
702
+ fakeStats.video.senders[0].report[0].packetsSent += 5;
703
+ await progressTime(MQA_INTERVAL);
384
704
 
385
- statsAnalyzer.compareLastStatsResult();
386
- assert.deepEqual(receivedEventsData.noFramesSent, expected);
705
+ assert.strictEqual(mqeData.audioTransmit[0].common.rtpPackets, 5);
706
+ assert.strictEqual(mqeData.audioTransmit[0].streams[0].common.rtpPackets, 5);
707
+ assert.strictEqual(mqeData.videoTransmit[0].common.rtpPackets, 5);
708
+ assert.strictEqual(mqeData.videoTransmit[0].streams[0].common.rtpPackets, 5);
709
+ });
710
+
711
+ it('after packets are received', async () => {
712
+ fakeStats.audio.senders[0].report[0].packetsSent += 10;
713
+ fakeStats.video.senders[0].report[0].packetsSent += 10;
714
+ fakeStats.audio.receivers[0].report[0].packetsReceived += 10;
715
+ fakeStats.video.receivers[0].report[0].packetsReceived += 10;
716
+ await progressTime(MQA_INTERVAL);
717
+
718
+ assert.strictEqual(mqeData.audioReceive[0].common.rtpPackets, 10);
719
+ assert.strictEqual(mqeData.audioReceive[0].streams[0].common.rtpPackets, 10);
720
+ assert.strictEqual(mqeData.videoReceive[0].common.rtpPackets, 10);
721
+ assert.strictEqual(mqeData.videoReceive[0].streams[0].common.rtpPackets, 10);
722
+ });
387
723
  });
388
724
 
389
- it('doesnot emits NO_FRAMES_SENT when last emitted event is LOCAL_MEDIA_STOPPED', async () => {
390
- statsAnalyzer.lastEmittedStartStopEvent.video.local = EVENTS.LOCAL_MEDIA_STOPPED;
725
+ it('emits the correct fecPackets', async () => {
726
+ it('at the start of the stats analyzer', async () => {
727
+ await startStatsAnalyzer();
728
+ assert.strictEqual(mqeData.audioReceive[0].common.fecPackets, 0);
729
+ });
391
730
 
392
- await startStatsAnalyzer({expected: {sendVideo: true}});
393
- await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'video');
731
+ it('after FEC packets are received', async () => {
732
+ fakeStats.audio.receivers[0].report[0].fecPacketsReceived += 5;
733
+ await progressTime(MQA_INTERVAL);
734
+
735
+ assert.strictEqual(mqeData.audioReceive[0].common.fecPackets, 5);
736
+ });
737
+
738
+ it('after FEC packets are received and some FEC packets are discarded', async () => {
739
+ fakeStats.audio.receivers[0].report[0].fecPacketsReceived += 15;
740
+ fakeStats.audio.receivers[0].report[0].fecPacketsDiscarded += 5;
741
+ await progressTime(MQA_INTERVAL);
394
742
 
395
- statsAnalyzer.compareLastStatsResult();
396
- assert.deepEqual(receivedEventsData.noFramesSent, undefined);
743
+ assert.strictEqual(mqeData.audioReceive[0].common.fecPackets, 10);
744
+ });
397
745
  });
398
746
 
399
- it('emits NO_FRAMES_ENCODED when frames are not being encoded for share', async () => {
400
- const expected = {mediaType: 'share'};
401
- await startStatsAnalyzer({expected: {sendShare: true}});
747
+ it('emits the correct mediaHopByHopLost/rtpHopByHopLost', async () => {
748
+ it('at the start of the stats analyzer', async () => {
749
+ await startStatsAnalyzer();
750
+ assert.strictEqual(mqeData.audioReceive[0].common.mediaHopByHopLost, 0);
751
+ assert.strictEqual(mqeData.audioReceive[0].common.rtpHopByHopLost, 0);
752
+ assert.strictEqual(mqeData.videoReceive[0].common.mediaHopByHopLost, 0);
753
+ assert.strictEqual(mqeData.videoReceive[0].common.rtpHopByHopLost, 0);
754
+ });
402
755
 
403
- statsAnalyzer.lastStatsResults.share.send = {framesEncoded: 102, totalPacketsSent: 106};
756
+ it('after packets are lost', async () => {
757
+ fakeStats.audio.receivers[0].report[0].packetsLost += 5;
758
+ fakeStats.video.receivers[0].report[0].packetsLost += 5;
759
+ await progressTime(MQA_INTERVAL);
404
760
 
405
- await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'share');
761
+ assert.strictEqual(mqeData.audioReceive[0].common.mediaHopByHopLost, 5);
762
+ assert.strictEqual(mqeData.audioReceive[0].common.rtpHopByHopLost, 5);
763
+ assert.strictEqual(mqeData.videoReceive[0].common.mediaHopByHopLost, 5);
764
+ assert.strictEqual(mqeData.videoReceive[0].common.rtpHopByHopLost, 5);
765
+ });
766
+ });
767
+
768
+ it('emits the correct remoteLossRate', async () => {
769
+ it('at the start of the stats analyzer', async () => {
770
+ await startStatsAnalyzer();
771
+ assert.strictEqual(mqeData.audioTransmit[0].common.remoteLossRate, 0);
772
+ assert.strictEqual(mqeData.videoTransmit[0].common.remoteLossRate, 0);
773
+ });
774
+
775
+ it('after packets are sent', async () => {
776
+ fakeStats.audio.senders[0].report[0].packetsSent += 100;
777
+ fakeStats.video.senders[0].report[0].packetsSent += 100;
778
+ await progressTime(MQA_INTERVAL);
779
+
780
+ assert.strictEqual(mqeData.audioTransmit[0].common.remoteLossRate, 0);
781
+ assert.strictEqual(mqeData.videoTransmit[0].common.remoteLossRate, 0);
782
+ });
406
783
 
407
- statsAnalyzer.compareLastStatsResult();
408
- assert.deepEqual(receivedEventsData.noVideoEncoded, expected);
784
+ it('after packets are sent and some packets are lost', async () => {
785
+ fakeStats.audio.senders[0].report[0].packetsSent += 200;
786
+ fakeStats.audio.senders[0].report[1].packetsLost += 10;
787
+ fakeStats.video.senders[0].report[0].packetsSent += 200;
788
+ fakeStats.video.senders[0].report[1].packetsLost += 10;
789
+ await progressTime(MQA_INTERVAL);
790
+
791
+ assert.strictEqual(mqeData.audioTransmit[0].common.remoteLossRate, 5);
792
+ assert.strictEqual(mqeData.videoTransmit[0].common.remoteLossRate, 5);
793
+ });
409
794
  });
410
795
 
411
- it('emits NO_FRAMES_SENT when frames are not being sent but frames are being encoded for share', async () => {
412
- const expected = {mediaType: 'share'};
413
- await startStatsAnalyzer({expected: {sendShare: true}});
796
+ it('has the correct localIpAddress set when the candidateType is host', async () => {
797
+ await startStatsAnalyzer();
414
798
 
415
- statsAnalyzer.lastStatsResults.share.send = {
416
- framesEncoded: 10,
417
- framesSent: 105,
418
- totalPacketsSent: 106,
419
- };
799
+ await progressTime();
800
+ assert.strictEqual(statsAnalyzer.getLocalIpAddress(), '');
801
+ mergeProperties(fakeStats, {address: 'test', candidateType: 'host'});
802
+ await progressTime();
803
+ assert.strictEqual(statsAnalyzer.getLocalIpAddress(), 'test');
804
+ });
805
+
806
+ it('has the correct localIpAddress set when the candidateType is prflx and relayProtocol is set', async () => {
807
+ await startStatsAnalyzer();
808
+
809
+ await progressTime();
810
+ assert.strictEqual(statsAnalyzer.getLocalIpAddress(), '');
811
+ mergeProperties(fakeStats, {
812
+ relayProtocol: 'test',
813
+ address: 'test2',
814
+ candidateType: 'prflx',
815
+ });
816
+ await progressTime();
817
+ assert.strictEqual(statsAnalyzer.getLocalIpAddress(), 'test2');
818
+ });
819
+
820
+ it('has the correct localIpAddress set when the candidateType is prflx and relayProtocol is not set', async () => {
821
+ await startStatsAnalyzer();
822
+
823
+ await progressTime();
824
+ assert.strictEqual(statsAnalyzer.getLocalIpAddress(), '');
825
+ mergeProperties(fakeStats, {
826
+ relatedAddress: 'relatedAddress',
827
+ address: 'test2',
828
+ candidateType: 'prflx',
829
+ });
830
+ await progressTime();
831
+ assert.strictEqual(statsAnalyzer.getLocalIpAddress(), 'relatedAddress');
832
+ });
833
+
834
+ it('has no localIpAddress set when the candidateType is invalid', async () => {
835
+ await startStatsAnalyzer();
836
+
837
+ await progressTime();
838
+ assert.strictEqual(statsAnalyzer.getLocalIpAddress(), '');
839
+ mergeProperties(fakeStats, {candidateType: 'invalid'});
840
+ await progressTime();
841
+ assert.strictEqual(statsAnalyzer.getLocalIpAddress(), '');
842
+ });
843
+
844
+ it('logs a message when audio send packets do not increase', async () => {
845
+ await startStatsAnalyzer({expected: {sendAudio: true}});
846
+
847
+ // don't increase the packets when time progresses.
848
+ await progressTime();
849
+
850
+ assert(loggerSpy.calledWith('StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent'));
851
+ });
852
+
853
+ it('does not log a message when audio send packets increase', async () => {
854
+ await startStatsAnalyzer({expected: {sendAudio: true}});
855
+
856
+ fakeStats.audio.senders[0].report[0].packetsSent += 5;
857
+ await progressTime();
858
+
859
+ assert(loggerSpy.neverCalledWith('StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent'));
860
+ });
420
861
 
421
- await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'share');
862
+ it('logs a message when audio receive packets do not increase', async () => {
863
+ await startStatsAnalyzer({expected: {receiveAudio: true}});
864
+
865
+ // don't increase the packets when time progresses.
866
+ await progressTime();
422
867
 
423
- statsAnalyzer.compareLastStatsResult();
424
- assert.deepEqual(receivedEventsData.noFramesSent, expected);
868
+ assert(loggerSpy.calledWith('StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received'));
425
869
  });
426
870
 
427
- it('doesnot emits NO_FRAMES_SENT when last emitted event is LOCAL_MEDIA_STOPPED for share', async () => {
428
- statsAnalyzer.lastEmittedStartStopEvent.video.local = EVENTS.LOCAL_MEDIA_STOPPED;
871
+ it('does not log a message when audio receive packets increase', async () => {
872
+ await startStatsAnalyzer({expected: {receiveAudio: true}});
873
+
874
+ fakeStats.audio.receivers[0].report[0].packetsReceived += 5;
875
+ await progressTime();
876
+
877
+ assert(loggerSpy.neverCalledWith('StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received'));
878
+ });
429
879
 
430
- await startStatsAnalyzer({expected: {sendShare: true}});
431
- await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'share');
880
+ it('logs a message when video send packets do not increase', async () => {
881
+ await startStatsAnalyzer({expected: {sendVideo: true}});
882
+
883
+ // don't increase the packets when time progresses.
884
+ await progressTime();
885
+
886
+ assert(loggerSpy.calledWith('StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent'));
887
+ });
888
+
889
+ it('does not log a message when video send packets increase', async () => {
890
+ await startStatsAnalyzer({expected: {sendVideo: true}});
891
+
892
+ fakeStats.video.senders[0].report[0].packetsSent += 5;
893
+ await progressTime();
894
+
895
+ assert(loggerSpy.neverCalledWith('StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent'));
896
+ });
897
+
898
+ it('logs a message when video receive packets do not increase', async () => {
899
+ await startStatsAnalyzer({expected: {receiveVideo: true}});
900
+
901
+ // don't increase the packets when time progresses.
902
+ await progressTime();
903
+
904
+ assert(loggerSpy.calledWith('StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets received'));
905
+ });
906
+
907
+ it('does not log a message when video receive packets increase', async () => {
908
+ await startStatsAnalyzer({expected: {receiveVideo: true}});
909
+
910
+ fakeStats.video.receivers[0].report[0].packetsReceived += 5;
911
+ await progressTime();
432
912
 
433
- statsAnalyzer.compareLastStatsResult();
434
- assert.deepEqual(receivedEventsData.noFramesSent, undefined);
913
+ assert(loggerSpy.neverCalledWith('StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received'));
435
914
  });
436
915
  });
437
916
  });