@webex/plugin-meetings 3.8.1 → 3.9.0

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 (290) hide show
  1. package/README.md +26 -13
  2. package/dist/breakouts/breakout.js +1 -1
  3. package/dist/breakouts/index.js +1 -1
  4. package/dist/constants.js +32 -3
  5. package/dist/constants.js.map +1 -1
  6. package/dist/controls-options-manager/enums.js +1 -0
  7. package/dist/controls-options-manager/enums.js.map +1 -1
  8. package/dist/controls-options-manager/types.js.map +1 -1
  9. package/dist/controls-options-manager/util.js +26 -0
  10. package/dist/controls-options-manager/util.js.map +1 -1
  11. package/dist/interpretation/index.js +1 -1
  12. package/dist/interpretation/siLanguage.js +1 -1
  13. package/dist/locus-info/controlsUtils.js +11 -3
  14. package/dist/locus-info/controlsUtils.js.map +1 -1
  15. package/dist/locus-info/index.js +68 -84
  16. package/dist/locus-info/index.js.map +1 -1
  17. package/dist/media/index.js +2 -2
  18. package/dist/media/index.js.map +1 -1
  19. package/dist/meeting/brbState.js +17 -14
  20. package/dist/meeting/brbState.js.map +1 -1
  21. package/dist/meeting/in-meeting-actions.js +11 -1
  22. package/dist/meeting/in-meeting-actions.js.map +1 -1
  23. package/dist/meeting/index.js +428 -253
  24. package/dist/meeting/index.js.map +1 -1
  25. package/dist/meeting/request.js +19 -0
  26. package/dist/meeting/request.js.map +1 -1
  27. package/dist/meeting/request.type.js.map +1 -1
  28. package/dist/{rtcMetrics/constants.js → meeting/type.js} +1 -5
  29. package/dist/meeting/type.js.map +1 -0
  30. package/dist/meeting/util.js +68 -2
  31. package/dist/meeting/util.js.map +1 -1
  32. package/dist/meetings/index.js +35 -33
  33. package/dist/meetings/index.js.map +1 -1
  34. package/dist/members/index.js +11 -9
  35. package/dist/members/index.js.map +1 -1
  36. package/dist/members/request.js +3 -3
  37. package/dist/members/request.js.map +1 -1
  38. package/dist/members/util.js +18 -6
  39. package/dist/members/util.js.map +1 -1
  40. package/dist/metrics/constants.js +1 -0
  41. package/dist/metrics/constants.js.map +1 -1
  42. package/dist/multistream/mediaRequestManager.js +1 -1
  43. package/dist/multistream/mediaRequestManager.js.map +1 -1
  44. package/dist/multistream/remoteMedia.js +34 -5
  45. package/dist/multistream/remoteMedia.js.map +1 -1
  46. package/dist/multistream/remoteMediaGroup.js +42 -2
  47. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  48. package/dist/multistream/sendSlotManager.js +32 -2
  49. package/dist/multistream/sendSlotManager.js.map +1 -1
  50. package/dist/reachability/index.js +5 -10
  51. package/dist/reachability/index.js.map +1 -1
  52. package/dist/types/constants.d.ts +28 -0
  53. package/dist/types/controls-options-manager/enums.d.ts +2 -1
  54. package/dist/types/controls-options-manager/types.d.ts +4 -1
  55. package/dist/types/locus-info/index.d.ts +0 -9
  56. package/dist/types/meeting/brbState.d.ts +0 -1
  57. package/dist/types/meeting/in-meeting-actions.d.ts +10 -0
  58. package/dist/types/meeting/index.d.ts +47 -19
  59. package/dist/types/meeting/request.d.ts +9 -1
  60. package/dist/types/meeting/request.type.d.ts +74 -0
  61. package/dist/types/meeting/type.d.ts +9 -0
  62. package/dist/types/meeting/util.d.ts +3 -0
  63. package/dist/types/members/index.d.ts +10 -7
  64. package/dist/types/members/request.d.ts +1 -1
  65. package/dist/types/members/util.d.ts +7 -3
  66. package/dist/types/metrics/constants.d.ts +1 -0
  67. package/dist/types/multistream/remoteMedia.d.ts +20 -1
  68. package/dist/types/multistream/remoteMediaGroup.d.ts +11 -0
  69. package/dist/types/multistream/sendSlotManager.d.ts +16 -0
  70. package/dist/types/reachability/index.d.ts +2 -2
  71. package/dist/webinar/index.js +1 -1
  72. package/package.json +24 -25
  73. package/src/constants.ts +32 -2
  74. package/src/controls-options-manager/enums.ts +1 -0
  75. package/src/controls-options-manager/types.ts +6 -1
  76. package/src/controls-options-manager/util.ts +31 -0
  77. package/src/locus-info/controlsUtils.ts +15 -0
  78. package/src/locus-info/index.ts +88 -82
  79. package/src/media/index.ts +2 -2
  80. package/src/meeting/brbState.ts +13 -9
  81. package/src/meeting/in-meeting-actions.ts +21 -0
  82. package/src/meeting/index.ts +254 -71
  83. package/src/meeting/request.ts +16 -0
  84. package/src/meeting/request.type.ts +64 -0
  85. package/src/meeting/type.ts +9 -0
  86. package/src/meeting/util.ts +73 -2
  87. package/src/meetings/index.ts +3 -2
  88. package/src/members/index.ts +13 -10
  89. package/src/members/request.ts +2 -2
  90. package/src/members/util.ts +16 -4
  91. package/src/metrics/constants.ts +1 -0
  92. package/src/multistream/mediaRequestManager.ts +7 -7
  93. package/src/multistream/remoteMedia.ts +34 -4
  94. package/src/multistream/remoteMediaGroup.ts +37 -2
  95. package/src/multistream/sendSlotManager.ts +34 -2
  96. package/src/reachability/index.ts +5 -13
  97. package/test/unit/spec/controls-options-manager/util.js +58 -0
  98. package/test/unit/spec/locus-info/controlsUtils.js +52 -0
  99. package/test/unit/spec/locus-info/index.js +218 -82
  100. package/test/unit/spec/media/index.ts +107 -0
  101. package/test/unit/spec/meeting/brbState.ts +23 -4
  102. package/test/unit/spec/meeting/in-meeting-actions.ts +10 -0
  103. package/test/unit/spec/meeting/index.js +901 -84
  104. package/test/unit/spec/meeting/request.js +71 -0
  105. package/test/unit/spec/meeting/utils.js +122 -1
  106. package/test/unit/spec/meetings/index.js +2 -0
  107. package/test/unit/spec/members/index.js +68 -9
  108. package/test/unit/spec/members/request.js +2 -2
  109. package/test/unit/spec/members/utils.js +27 -7
  110. package/test/unit/spec/multistream/mediaRequestManager.ts +19 -6
  111. package/test/unit/spec/multistream/remoteMedia.ts +66 -2
  112. package/test/unit/spec/multistream/sendSlotManager.ts +59 -0
  113. package/test/unit/spec/reachability/index.ts +2 -6
  114. package/dist/annotation/annotation.types.d.ts +0 -42
  115. package/dist/annotation/constants.d.ts +0 -31
  116. package/dist/annotation/index.d.ts +0 -117
  117. package/dist/breakouts/breakout.d.ts +0 -8
  118. package/dist/breakouts/collection.d.ts +0 -5
  119. package/dist/breakouts/edit-lock-error.d.ts +0 -15
  120. package/dist/breakouts/events.d.ts +0 -8
  121. package/dist/breakouts/index.d.ts +0 -5
  122. package/dist/breakouts/request.d.ts +0 -22
  123. package/dist/breakouts/utils.d.ts +0 -15
  124. package/dist/common/browser-detection.d.ts +0 -9
  125. package/dist/common/collection.d.ts +0 -48
  126. package/dist/common/config.d.ts +0 -2
  127. package/dist/common/errors/captcha-error.d.ts +0 -15
  128. package/dist/common/errors/intent-to-join.d.ts +0 -16
  129. package/dist/common/errors/join-meeting.d.ts +0 -17
  130. package/dist/common/errors/media.d.ts +0 -15
  131. package/dist/common/errors/no-meeting-info.d.ts +0 -14
  132. package/dist/common/errors/parameter.d.ts +0 -15
  133. package/dist/common/errors/password-error.d.ts +0 -15
  134. package/dist/common/errors/permission.d.ts +0 -14
  135. package/dist/common/errors/reclaim-host-role-error.d.ts +0 -60
  136. package/dist/common/errors/reclaim-host-role-error.js +0 -158
  137. package/dist/common/errors/reclaim-host-role-error.js.map +0 -1
  138. package/dist/common/errors/reclaim-host-role-errors.d.ts +0 -60
  139. package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
  140. package/dist/common/errors/reconnection-in-progress.js +0 -35
  141. package/dist/common/errors/reconnection-in-progress.js.map +0 -1
  142. package/dist/common/errors/reconnection.d.ts +0 -15
  143. package/dist/common/errors/stats.d.ts +0 -15
  144. package/dist/common/errors/webex-errors.d.ts +0 -81
  145. package/dist/common/errors/webex-meetings-error.d.ts +0 -20
  146. package/dist/common/events/events-scope.d.ts +0 -17
  147. package/dist/common/events/events.d.ts +0 -12
  148. package/dist/common/events/trigger-proxy.d.ts +0 -2
  149. package/dist/common/events/util.d.ts +0 -2
  150. package/dist/common/logs/logger-config.d.ts +0 -2
  151. package/dist/common/logs/logger-proxy.d.ts +0 -2
  152. package/dist/common/logs/request.d.ts +0 -34
  153. package/dist/common/queue.d.ts +0 -32
  154. package/dist/config.d.ts +0 -73
  155. package/dist/constants.d.ts +0 -952
  156. package/dist/controls-options-manager/constants.d.ts +0 -4
  157. package/dist/controls-options-manager/enums.d.ts +0 -5
  158. package/dist/controls-options-manager/index.d.ts +0 -120
  159. package/dist/controls-options-manager/types.d.ts +0 -43
  160. package/dist/controls-options-manager/util.d.ts +0 -7
  161. package/dist/index.d.ts +0 -4
  162. package/dist/interceptors/index.d.ts +0 -2
  163. package/dist/interceptors/locusRetry.d.ts +0 -27
  164. package/dist/interpretation/collection.d.ts +0 -5
  165. package/dist/interpretation/index.d.ts +0 -5
  166. package/dist/interpretation/siLanguage.d.ts +0 -5
  167. package/dist/locus-info/controlsUtils.d.ts +0 -2
  168. package/dist/locus-info/embeddedAppsUtils.d.ts +0 -2
  169. package/dist/locus-info/fullState.d.ts +0 -2
  170. package/dist/locus-info/hostUtils.d.ts +0 -2
  171. package/dist/locus-info/index.d.ts +0 -269
  172. package/dist/locus-info/infoUtils.d.ts +0 -2
  173. package/dist/locus-info/mediaSharesUtils.d.ts +0 -2
  174. package/dist/locus-info/parser.d.ts +0 -212
  175. package/dist/locus-info/selfUtils.d.ts +0 -2
  176. package/dist/media/index.d.ts +0 -32
  177. package/dist/media/properties.d.ts +0 -108
  178. package/dist/media/util.d.ts +0 -2
  179. package/dist/mediaQualityMetrics/config.d.ts +0 -233
  180. package/dist/mediaQualityMetrics/config.js +0 -513
  181. package/dist/mediaQualityMetrics/config.js.map +0 -1
  182. package/dist/meeting/effectsState.d.ts +0 -42
  183. package/dist/meeting/effectsState.js +0 -260
  184. package/dist/meeting/effectsState.js.map +0 -1
  185. package/dist/meeting/in-meeting-actions.d.ts +0 -79
  186. package/dist/meeting/index.d.ts +0 -1622
  187. package/dist/meeting/locusMediaRequest.d.ts +0 -74
  188. package/dist/meeting/muteState.d.ts +0 -116
  189. package/dist/meeting/request.d.ts +0 -257
  190. package/dist/meeting/request.type.d.ts +0 -11
  191. package/dist/meeting/state.d.ts +0 -9
  192. package/dist/meeting/util.d.ts +0 -2
  193. package/dist/meeting/voicea-meeting.d.ts +0 -16
  194. package/dist/meeting-info/collection.d.ts +0 -20
  195. package/dist/meeting-info/index.d.ts +0 -57
  196. package/dist/meeting-info/meeting-info-v2.d.ts +0 -93
  197. package/dist/meeting-info/request.d.ts +0 -22
  198. package/dist/meeting-info/util.d.ts +0 -2
  199. package/dist/meeting-info/utilv2.d.ts +0 -2
  200. package/dist/meetings/collection.d.ts +0 -23
  201. package/dist/meetings/index.d.ts +0 -296
  202. package/dist/meetings/meetings.types.d.ts +0 -4
  203. package/dist/meetings/request.d.ts +0 -27
  204. package/dist/meetings/util.d.ts +0 -18
  205. package/dist/member/index.d.ts +0 -148
  206. package/dist/member/member.types.d.ts +0 -11
  207. package/dist/member/member.types.js +0 -18
  208. package/dist/member/member.types.js.map +0 -1
  209. package/dist/member/types.d.ts +0 -32
  210. package/dist/member/util.d.ts +0 -2
  211. package/dist/members/collection.d.ts +0 -24
  212. package/dist/members/index.d.ts +0 -308
  213. package/dist/members/request.d.ts +0 -58
  214. package/dist/members/types.d.ts +0 -25
  215. package/dist/members/util.d.ts +0 -2
  216. package/dist/metrics/config.d.ts +0 -169
  217. package/dist/metrics/config.js +0 -289
  218. package/dist/metrics/config.js.map +0 -1
  219. package/dist/metrics/constants.d.ts +0 -59
  220. package/dist/metrics/index.d.ts +0 -152
  221. package/dist/multistream/mediaRequestManager.d.ts +0 -119
  222. package/dist/multistream/receiveSlot.d.ts +0 -68
  223. package/dist/multistream/receiveSlotManager.d.ts +0 -56
  224. package/dist/multistream/remoteMedia.d.ts +0 -72
  225. package/dist/multistream/remoteMediaGroup.d.ts +0 -49
  226. package/dist/multistream/remoteMediaManager.d.ts +0 -300
  227. package/dist/multistream/sendSlotManager.d.ts +0 -69
  228. package/dist/networkQualityMonitor/index.d.ts +0 -70
  229. package/dist/networkQualityMonitor/index.js +0 -226
  230. package/dist/networkQualityMonitor/index.js.map +0 -1
  231. package/dist/peer-connection-manager/index.d.ts +0 -6
  232. package/dist/peer-connection-manager/index.js +0 -671
  233. package/dist/peer-connection-manager/index.js.map +0 -1
  234. package/dist/peer-connection-manager/util.d.ts +0 -6
  235. package/dist/peer-connection-manager/util.js +0 -110
  236. package/dist/peer-connection-manager/util.js.map +0 -1
  237. package/dist/personal-meeting-room/index.d.ts +0 -47
  238. package/dist/personal-meeting-room/request.d.ts +0 -14
  239. package/dist/personal-meeting-room/util.d.ts +0 -2
  240. package/dist/reachability/clusterReachability.d.ts +0 -109
  241. package/dist/reachability/index.d.ts +0 -139
  242. package/dist/reachability/request.d.ts +0 -35
  243. package/dist/reachability/util.d.ts +0 -8
  244. package/dist/reactions/constants.d.ts +0 -3
  245. package/dist/reactions/reactions.d.ts +0 -4
  246. package/dist/reactions/reactions.type.d.ts +0 -32
  247. package/dist/reconnection-manager/index.d.ts +0 -112
  248. package/dist/recording-controller/enums.d.ts +0 -7
  249. package/dist/recording-controller/index.d.ts +0 -193
  250. package/dist/recording-controller/util.d.ts +0 -13
  251. package/dist/roap/collection.d.ts +0 -10
  252. package/dist/roap/collection.js +0 -63
  253. package/dist/roap/collection.js.map +0 -1
  254. package/dist/roap/handler.d.ts +0 -47
  255. package/dist/roap/handler.js +0 -279
  256. package/dist/roap/handler.js.map +0 -1
  257. package/dist/roap/index.d.ts +0 -116
  258. package/dist/roap/request.d.ts +0 -35
  259. package/dist/roap/state.d.ts +0 -9
  260. package/dist/roap/state.js +0 -127
  261. package/dist/roap/state.js.map +0 -1
  262. package/dist/roap/turnDiscovery.d.ts +0 -81
  263. package/dist/roap/util.d.ts +0 -2
  264. package/dist/roap/util.js +0 -76
  265. package/dist/roap/util.js.map +0 -1
  266. package/dist/rtcMetrics/constants.d.ts +0 -4
  267. package/dist/rtcMetrics/constants.js.map +0 -1
  268. package/dist/rtcMetrics/index.d.ts +0 -61
  269. package/dist/rtcMetrics/index.js +0 -197
  270. package/dist/rtcMetrics/index.js.map +0 -1
  271. package/dist/statsAnalyzer/global.d.ts +0 -118
  272. package/dist/statsAnalyzer/global.js +0 -127
  273. package/dist/statsAnalyzer/global.js.map +0 -1
  274. package/dist/statsAnalyzer/index.d.ts +0 -193
  275. package/dist/statsAnalyzer/index.js +0 -1019
  276. package/dist/statsAnalyzer/index.js.map +0 -1
  277. package/dist/statsAnalyzer/mqaUtil.d.ts +0 -22
  278. package/dist/statsAnalyzer/mqaUtil.js +0 -181
  279. package/dist/statsAnalyzer/mqaUtil.js.map +0 -1
  280. package/dist/transcription/index.d.ts +0 -64
  281. package/dist/types/common/errors/reconnection-in-progress.d.ts +0 -9
  282. package/dist/types/mediaQualityMetrics/config.d.ts +0 -241
  283. package/dist/types/networkQualityMonitor/index.d.ts +0 -70
  284. package/dist/types/rtcMetrics/constants.d.ts +0 -4
  285. package/dist/types/rtcMetrics/index.d.ts +0 -71
  286. package/dist/types/statsAnalyzer/global.d.ts +0 -36
  287. package/dist/types/statsAnalyzer/index.d.ts +0 -217
  288. package/dist/types/statsAnalyzer/mqaUtil.d.ts +0 -48
  289. package/dist/webinar/collection.d.ts +0 -16
  290. package/dist/webinar/index.d.ts +0 -5
@@ -473,6 +473,40 @@ describe('plugin-meetings', () => {
473
473
  assert.equal(results, expected);
474
474
  });
475
475
  });
476
+
477
+ describe('canUpdatePollingQA()', () => {
478
+ beforeEach(() => {
479
+ sinon.stub(ControlsOptionsUtil, 'hasHints').returns(true);
480
+ });
481
+
482
+ it('should call hasHints() with proper hints when `enabled` is true', () => {
483
+ ControlsOptionsUtil.canUpdatePollingQA({properties: {enabled: true}}, []);
484
+
485
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
486
+ requiredHints: [DISPLAY_HINTS.ENABLE_ATTENDEE_START_POLLING_QA],
487
+ displayHints: [],
488
+ });
489
+ });
490
+
491
+ it('should call hasHints() with proper hints when `enabled` is false', () => {
492
+ ControlsOptionsUtil.canUpdatePollingQA({properties: {enabled: false}}, []);
493
+
494
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
495
+ requiredHints: [DISPLAY_HINTS.DISABLE_ATTENDEE_START_POLLING_QA],
496
+ displayHints: [],
497
+ });
498
+ });
499
+
500
+ it('should return the resolution of hasHints()', () => {
501
+ const expected = 'example-return-value';
502
+ ControlsOptionsUtil.hasHints.returns(expected);
503
+
504
+ const results = ControlsOptionsUtil.canUpdatePollingQA({properties: {}}, []);
505
+
506
+ assert.calledOnce(ControlsOptionsUtil.hasHints);
507
+ assert.equal(results, expected);
508
+ });
509
+ });
476
510
 
477
511
  describe('canUpdate()', () => {
478
512
  const displayHints = [];
@@ -486,6 +520,7 @@ describe('plugin-meetings', () => {
486
520
  ControlsOptionsUtil.canUpdateViewTheParticipantsList = sinon.stub().returns(true);
487
521
  ControlsOptionsUtil.canUpdateAnnotation = sinon.stub().returns(true);
488
522
  ControlsOptionsUtil.canUpdateRemoteDesktopControl = sinon.stub().returns(true);
523
+ ControlsOptionsUtil.canUpdatePollingQA = sinon.stub().returns(true);
489
524
  });
490
525
 
491
526
  it('should only call canUpdateAudio() if the scope is audio', () => {
@@ -621,6 +656,28 @@ describe('plugin-meetings', () => {
621
656
  control,
622
657
  displayHints
623
658
  );
659
+ assert.callCount(ControlsOptionsUtil.canUpdatePollingQA, 0);
660
+ assert.isTrue(results);
661
+ });
662
+
663
+ it('should only call canUpdatePollingQA() if the scope is pollingQA', () => {
664
+ const control = {scope: 'pollingQA'};
665
+
666
+ const results = ControlsOptionsUtil.canUpdate(control, displayHints);
667
+
668
+ assert.callCount(ControlsOptionsUtil.canUpdateAudio, 0);
669
+ assert.callCount(ControlsOptionsUtil.canUpdateRaiseHand, 0);
670
+ assert.callCount(ControlsOptionsUtil.canUpdateReactions, 0);
671
+ assert.callCount(ControlsOptionsUtil.canUpdateShareControl, 0);
672
+ assert.callCount(ControlsOptionsUtil.canUpdateVideo, 0);
673
+ assert.callCount(ControlsOptionsUtil.canUpdateViewTheParticipantsList, 0);
674
+ assert.callCount(ControlsOptionsUtil.canUpdateAnnotation, 0);
675
+ assert.callCount(ControlsOptionsUtil.canUpdateRemoteDesktopControl, 0);
676
+ assert.calledWith(
677
+ ControlsOptionsUtil.canUpdatePollingQA,
678
+ control,
679
+ displayHints
680
+ );
624
681
  assert.isTrue(results);
625
682
  });
626
683
 
@@ -637,6 +694,7 @@ describe('plugin-meetings', () => {
637
694
  assert.callCount(ControlsOptionsUtil.canUpdateViewTheParticipantsList, 0);
638
695
  assert.callCount(ControlsOptionsUtil.canUpdateAnnotation, 0);
639
696
  assert.callCount(ControlsOptionsUtil.canUpdateRemoteDesktopControl, 0);
697
+ assert.callCount(ControlsOptionsUtil.canUpdatePollingQA, 0);
640
698
  assert.isFalse(results);
641
699
  });
642
700
  });
@@ -164,6 +164,14 @@ describe('plugin-meetings', () => {
164
164
 
165
165
  assert.equal(parsedControls.rdcControl.enabled, newControls.rdcControl.enabled);
166
166
  });
167
+
168
+ it('should parse the pollingQAControl control', () => {
169
+ const newControls = {pollingQAControl: {enabled: true}};
170
+
171
+ const parsedControls = ControlsUtils.parse(newControls);
172
+
173
+ assert.equal(parsedControls.pollingQAControl.enabled, newControls.pollingQAControl.enabled);
174
+ });
167
175
 
168
176
  describe('videoEnabled', () => {
169
177
  it('returns expected', () => {
@@ -411,6 +419,50 @@ describe('plugin-meetings', () => {
411
419
  assert.equal(updates.hasRemoteDesktopControlChanged, true);
412
420
  });
413
421
 
422
+ it('returns hasPollingQAControlChanged = true when changed', () => {
423
+ const newControls = {pollingQAControl: {enabled: true}};
424
+
425
+ const {updates} = ControlsUtils.getControls(defaultControls, newControls);
426
+
427
+ assert.equal(updates.hasPollingQAControlChanged, true);
428
+ });
429
+
430
+ it('returns false when previous spoken language is undefined and current is a invalid value', () => {
431
+ const previous = { transcribe: undefined };
432
+ const current = { transcribe: { spokenLanguage: null } };
433
+
434
+ const {updates} = ControlsUtils.getControls(previous, current);
435
+
436
+ assert.equal(updates.hasTranscribeSpokenLanguageChanged, false);
437
+ });
438
+
439
+ it('detects spoken language change when previous is undefined and current is a valid value', () => {
440
+ const previous = { transcribe: undefined };
441
+ const current = { transcribe: { spokenLanguage: 'en-US' } };
442
+
443
+ const {updates} = ControlsUtils.getControls(previous, current);
444
+
445
+ assert.equal(updates.hasTranscribeSpokenLanguageChanged, true);
446
+ });
447
+
448
+ it('returns false when spoken language changes to a same value', () => {
449
+ const previous = { transcribe: {caption: true, spokenLanguage: 'en-US' } };
450
+ const current = { transcribe: {caption: true, spokenLanguage: 'en-US' } };
451
+
452
+ const {updates} = ControlsUtils.getControls(previous, current);
453
+
454
+ assert.equal(updates.hasTranscribeSpokenLanguageChanged, false);
455
+ });
456
+
457
+ it('returns true when spoken language changes to a different value', () => {
458
+ const previous = { transcribe: {caption: true, spokenLanguage: 'en-US' } };
459
+ const current = { transcribe: {caption: true, spokenLanguage: 'fr-FR' } };
460
+
461
+ const {updates} = ControlsUtils.getControls(previous, current);
462
+
463
+ assert.equal(updates.hasTranscribeSpokenLanguageChanged, true);
464
+ });
465
+
414
466
  describe('videoEnabled', () => {
415
467
  const testVideoEnabled = (oldControls, newControls, updatedProperty) => {
416
468
  const result = ControlsUtils.getControls(oldControls, newControls);
@@ -306,6 +306,20 @@ describe('plugin-meetings', () => {
306
306
  );
307
307
  });
308
308
 
309
+ it('should trigger the CONTROLS_POLLING_QA_CHANGED event when necessary', () => {
310
+ locusInfo.controls = {};
311
+ locusInfo.emitScoped = sinon.stub();
312
+ newControls.pollingQAControl = { enabled: true };
313
+ locusInfo.updateControls(newControls);
314
+
315
+ assert.calledWith(
316
+ locusInfo.emitScoped,
317
+ {file: 'locus-info', function: 'updateControls'},
318
+ LOCUSINFO.EVENTS.CONTROLS_POLLING_QA_CHANGED,
319
+ {state: newControls.pollingQAControl}
320
+ );
321
+ });
322
+
309
323
  it('should keep the recording state to `IDLE`', () => {
310
324
  locusInfo.controls = {
311
325
  record: {
@@ -557,6 +571,34 @@ describe('plugin-meetings', () => {
557
571
  );
558
572
  });
559
573
 
574
+ it('should update the transcribe spoken language', () => {
575
+ locusInfo.emitScoped = sinon.stub();
576
+ locusInfo.controls = {
577
+ transcribe: {
578
+ transcribing: false,
579
+ caption: true,
580
+ spokenLanguage: 'en-US',
581
+ },
582
+ };
583
+ newControls.transcribe.transcribing = false;
584
+ newControls.transcribe.caption = true;
585
+ newControls.transcribe.spokenLanguage = 'fr';
586
+
587
+ locusInfo.updateControls(newControls);
588
+
589
+ assert.calledWith(
590
+ locusInfo.emitScoped,
591
+ {
592
+ file: 'locus-info',
593
+ function: 'updateControls',
594
+ },
595
+ LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
596
+ {
597
+ spokenLanguage: 'fr',
598
+ }
599
+ );
600
+ });
601
+
560
602
  it('should update the manual caption state', () => {
561
603
  locusInfo.emitScoped = sinon.stub();
562
604
  locusInfo.controls = {
@@ -792,39 +834,6 @@ describe('plugin-meetings', () => {
792
834
  );
793
835
  });
794
836
 
795
- it('should update the deltaParticipants object', () => {
796
- const prev = locusInfo.deltaParticipants;
797
-
798
- locusInfo.updateParticipantDeltas(newParticipants);
799
-
800
- assert.notEqual(locusInfo.deltaParticipants, prev);
801
- });
802
-
803
- it('should update the delta property on all changed states', () => {
804
- locusInfo.updateParticipantDeltas(newParticipants);
805
-
806
- const [exampleParticipant] = locusInfo.deltaParticipants;
807
-
808
- assert.isTrue(exampleParticipant.delta.audioStatus);
809
- assert.isTrue(exampleParticipant.delta.videoSlidesStatus);
810
- assert.isTrue(exampleParticipant.delta.videoStatus);
811
- });
812
-
813
- it('should include the person details of the changed participant', () => {
814
- locusInfo.updateParticipantDeltas(newParticipants);
815
-
816
- const [exampleParticipant] = locusInfo.deltaParticipants;
817
-
818
- assert.equal(exampleParticipant.person, newParticipants[0].person);
819
- });
820
-
821
- it('should clear deltaParticipants when no changes occured', () => {
822
- locusInfo.participants = [...newParticipants];
823
-
824
- locusInfo.updateParticipantDeltas(locusInfo.participants);
825
-
826
- assert.isTrue(locusInfo.deltaParticipants.length === 0);
827
- });
828
837
 
829
838
  it('should call with participant display name', () => {
830
839
  const failureParticipant = [
@@ -2066,6 +2075,38 @@ describe('plugin-meetings', () => {
2066
2075
  assert.isFunction(locusParser.onDeltaAction);
2067
2076
  });
2068
2077
 
2078
+ it("#updateLocusInfo invokes updateLocusUrl before updateMeetingInfo", () => {
2079
+ const callOrder = [];
2080
+ sinon.stub(locusInfo, "updateControls");
2081
+ sinon.stub(locusInfo, "updateConversationUrl");
2082
+ sinon.stub(locusInfo, "updateCreated");
2083
+ sinon.stub(locusInfo, "updateFullState");
2084
+ sinon.stub(locusInfo, "updateHostInfo");
2085
+ sinon.stub(locusInfo, "updateMeetingInfo").callsFake(() => {
2086
+ callOrder.push("updateMeetingInfo");
2087
+ });
2088
+ sinon.stub(locusInfo, "updateMediaShares");
2089
+ sinon.stub(locusInfo, "updateParticipantsUrl");
2090
+ sinon.stub(locusInfo, "updateReplace");
2091
+ sinon.stub(locusInfo, "updateSelf");
2092
+ sinon.stub(locusInfo, "updateLocusUrl").callsFake(() => {
2093
+ callOrder.push("updateLocusUrl");
2094
+ });
2095
+ sinon.stub(locusInfo, "updateAclUrl");
2096
+ sinon.stub(locusInfo, "updateBasequence");
2097
+ sinon.stub(locusInfo, "updateSequence");
2098
+ sinon.stub(locusInfo, "updateMemberShip");
2099
+ sinon.stub(locusInfo, "updateIdentifiers");
2100
+ sinon.stub(locusInfo, "updateEmbeddedApps");
2101
+ sinon.stub(locusInfo, "updateResources");
2102
+ sinon.stub(locusInfo, "compareAndUpdate");
2103
+
2104
+ locusInfo.updateLocusInfo(locus);
2105
+
2106
+ // Ensure updateLocusUrl is called before updateMeetingInfo if both are called
2107
+ assert.deepEqual(callOrder, ['updateLocusUrl', 'updateMeetingInfo']);
2108
+ });
2109
+
2069
2110
  it('#updateLocusInfo ignores breakout LEFT message', () => {
2070
2111
  const newLocus = {
2071
2112
  self: {
@@ -2117,10 +2158,11 @@ describe('plugin-meetings', () => {
2117
2158
  assert.notCalled(locusInfo.compareAndUpdate);
2118
2159
  });
2119
2160
 
2161
+
2162
+
2120
2163
  it('onFullLocus() updates the working-copy of locus parser', () => {
2121
2164
  const eventType = 'fakeEvent';
2122
2165
 
2123
- sandbox.stub(locusInfo, 'updateParticipantDeltas');
2124
2166
  sandbox.stub(locusInfo, 'updateLocusInfo');
2125
2167
  sandbox.stub(locusInfo, 'updateParticipants');
2126
2168
  sandbox.stub(locusInfo, 'isMeetingActive');
@@ -2140,7 +2182,6 @@ describe('plugin-meetings', () => {
2140
2182
  const oldWorkingCopy = locusParser.workingCopy;
2141
2183
 
2142
2184
  const spies = [
2143
- sandbox.stub(locusInfo, 'updateParticipantDeltas'),
2144
2185
  sandbox.stub(locusInfo, 'updateLocusInfo'),
2145
2186
  sandbox.stub(locusInfo, 'updateParticipants'),
2146
2187
  sandbox.stub(locusInfo, 'isMeetingActive'),
@@ -2215,7 +2256,7 @@ describe('plugin-meetings', () => {
2215
2256
 
2216
2257
  it('applyLocusDeltaData gets delta locus on DESYNC action if we have a syncUrl', () => {
2217
2258
  const {DESYNC} = LocusDeltaParser.loci;
2218
- const fakeDeltaLocus = {id: 'fake delta locus'};
2259
+ const fakeDeltaLocus = {baseSequence: {}, id: 'fake delta locus'};
2219
2260
  const meeting = {
2220
2261
  meetingRequest: {
2221
2262
  getLocusDTO: sandbox.stub().resolves({body: fakeDeltaLocus}),
@@ -2350,25 +2391,22 @@ describe('plugin-meetings', () => {
2350
2391
  };
2351
2392
  });
2352
2393
 
2353
- it('applyLocusDeltaData gets full locus on DESYNC action if we do not have a syncUrl and destroys the meeting if that fails', () => {
2394
+ it('applyLocusDeltaData gets full locus on DESYNC action if we do not have a syncUrl and destroys the meeting if that fails', async () => {
2354
2395
  meeting.meetingRequest.getLocusDTO.rejects(new Error('fake error'));
2355
2396
 
2356
2397
  locusInfo.locusParser.workingCopy = {}; // no syncUrl
2357
2398
 
2358
- // Since we have a promise inside a function we want to test that's not returned,
2359
- // we will wait and stub it's last function to resolve this waiting promise.
2360
- return new Promise((resolve) => {
2361
- webex.meetings.destroy.callsFake(() => resolve());
2362
- locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
2363
- }).then(() => {
2364
- assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {url: 'fullSyncUrl'});
2399
+ locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
2365
2400
 
2366
- assert.notCalled(meeting.locusInfo.handleLocusDelta);
2367
- assert.notCalled(meeting.locusInfo.onFullLocus);
2368
- assert.notCalled(locusInfo.locusParser.resume);
2401
+ await testUtils.flushPromises();
2369
2402
 
2370
- assert.calledOnceWithExactly(webex.meetings.destroy, meeting, 'LOCUS_DTO_SYNC_FAILED');
2371
- });
2403
+ assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {url: 'fullSyncUrl'});
2404
+
2405
+ assert.notCalled(meeting.locusInfo.handleLocusDelta);
2406
+ assert.notCalled(meeting.locusInfo.onFullLocus);
2407
+ assert.notCalled(locusInfo.locusParser.resume);
2408
+
2409
+ assert.calledOnceWithExactly(webex.meetings.destroy, meeting, 'LOCUS_DTO_SYNC_FAILED');
2372
2410
  });
2373
2411
 
2374
2412
  it('applyLocusDeltaData first tries a delta sync on DESYNC action and if that fails, does a full locus sync', () => {
@@ -2405,39 +2443,62 @@ describe('plugin-meetings', () => {
2405
2443
  });
2406
2444
  });
2407
2445
 
2408
- it('applyLocusDeltaData destroys the meeting if both delta sync and full sync fail', () => {
2446
+ it('applyLocusDeltaData first tries a delta sync on DESYNC action and if that fails with 403, it does not do a full locus sync', async () => {
2447
+ const fake403Error = new Error('fake error');
2448
+ fake403Error.statusCode = 403;
2449
+
2450
+ meeting.meetingRequest.getLocusDTO.onCall(0).rejects(fake403Error);
2451
+
2452
+ locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
2453
+
2454
+ await testUtils.flushPromises();
2455
+
2456
+ assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {url: 'deltaSyncUrl'});
2457
+
2458
+ assert.calledWith(sendBehavioralMetricStub, 'js_sdk_locus_delta_sync_failed', {
2459
+ correlationId: meeting.correlationId,
2460
+ url: 'deltaSyncUrl',
2461
+ reason: 'fake error',
2462
+ errorName: 'Error',
2463
+ stack: sinon.match.any,
2464
+ code: sinon.match.any,
2465
+ });
2466
+
2467
+ assert.notCalled(meeting.locusInfo.handleLocusDelta);
2468
+ assert.notCalled(meeting.locusInfo.onFullLocus);
2469
+ assert.notCalled(locusInfo.locusParser.resume);
2470
+ });
2471
+
2472
+ it('applyLocusDeltaData destroys the meeting if both delta sync and full sync fail', async () => {
2409
2473
  meeting.meetingRequest.getLocusDTO.rejects(new Error('fake error'));
2410
2474
 
2411
- // Since we have a promise inside a function we want to test that's not returned,
2412
- // we will wait and stub it's last function to resolve this waiting promise.
2413
- return new Promise((resolve) => {
2414
- webex.meetings.destroy.callsFake(() => resolve());
2415
- locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
2416
- }).then(() => {
2417
- assert.calledTwice(meeting.meetingRequest.getLocusDTO);
2475
+ locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
2418
2476
 
2419
- assert.deepEqual(meeting.meetingRequest.getLocusDTO.getCalls()[0].args, [
2420
- {url: 'deltaSyncUrl'},
2421
- ]);
2422
- assert.deepEqual(meeting.meetingRequest.getLocusDTO.getCalls()[1].args, [
2423
- {url: 'fullSyncUrl'},
2424
- ]);
2477
+ await testUtils.flushPromises();
2425
2478
 
2426
- assert.calledWith(sendBehavioralMetricStub, 'js_sdk_locus_delta_sync_failed', {
2427
- correlationId: meeting.correlationId,
2428
- url: 'deltaSyncUrl',
2429
- reason: 'fake error',
2430
- errorName: 'Error',
2431
- stack: sinon.match.any,
2432
- code: sinon.match.any,
2433
- });
2479
+ assert.calledTwice(meeting.meetingRequest.getLocusDTO);
2434
2480
 
2435
- assert.notCalled(meeting.locusInfo.handleLocusDelta);
2436
- assert.notCalled(meeting.locusInfo.onFullLocus);
2437
- assert.notCalled(locusInfo.locusParser.resume);
2481
+ assert.deepEqual(meeting.meetingRequest.getLocusDTO.getCalls()[0].args, [
2482
+ {url: 'deltaSyncUrl'},
2483
+ ]);
2484
+ assert.deepEqual(meeting.meetingRequest.getLocusDTO.getCalls()[1].args, [
2485
+ {url: 'fullSyncUrl'},
2486
+ ]);
2438
2487
 
2439
- assert.calledOnceWithExactly(webex.meetings.destroy, meeting, 'LOCUS_DTO_SYNC_FAILED');
2488
+ assert.calledWith(sendBehavioralMetricStub, 'js_sdk_locus_delta_sync_failed', {
2489
+ correlationId: meeting.correlationId,
2490
+ url: 'deltaSyncUrl',
2491
+ reason: 'fake error',
2492
+ errorName: 'Error',
2493
+ stack: sinon.match.any,
2494
+ code: sinon.match.any,
2440
2495
  });
2496
+
2497
+ assert.notCalled(meeting.locusInfo.handleLocusDelta);
2498
+ assert.notCalled(meeting.locusInfo.onFullLocus);
2499
+ assert.notCalled(locusInfo.locusParser.resume);
2500
+
2501
+ assert.calledOnceWithExactly(webex.meetings.destroy, meeting, 'LOCUS_DTO_SYNC_FAILED');
2441
2502
  });
2442
2503
  });
2443
2504
 
@@ -2467,9 +2528,7 @@ describe('plugin-meetings', () => {
2467
2528
  });
2468
2529
 
2469
2530
  it('onDeltaLocus merges delta participants with existing participants', () => {
2470
- const FAKE_DELTA_PARTICIPANTS = [
2471
- {id: '1111'}, {id: '2222'}
2472
- ]
2531
+ const FAKE_DELTA_PARTICIPANTS = [{id: '1111'}, {id: '2222'}];
2473
2532
  fakeLocus.participants = FAKE_DELTA_PARTICIPANTS;
2474
2533
 
2475
2534
  sinon.spy(locusInfo, 'mergeParticipants');
@@ -2477,9 +2536,87 @@ describe('plugin-meetings', () => {
2477
2536
  const existingParticipants = locusInfo.participants;
2478
2537
 
2479
2538
  locusInfo.onDeltaLocus(fakeLocus);
2480
- assert.calledOnceWithExactly(locusInfo.mergeParticipants, existingParticipants, FAKE_DELTA_PARTICIPANTS);
2539
+ assert.calledOnceWithExactly(
2540
+ locusInfo.mergeParticipants,
2541
+ existingParticipants,
2542
+ FAKE_DELTA_PARTICIPANTS
2543
+ );
2481
2544
  assert.calledWith(locusInfo.updateParticipants, FAKE_DELTA_PARTICIPANTS, false);
2482
2545
  });
2546
+
2547
+ [true, false].forEach((isDelta) =>
2548
+ it(`applyLocusDeltaData - handles empty ${
2549
+ isDelta ? 'delta' : 'full'
2550
+ } DTO in response`, async () => {
2551
+ const {DESYNC} = LocusDeltaParser.loci;
2552
+ const fakeFullLocusDto = {};
2553
+ const meeting = {
2554
+ meetingRequest: {
2555
+ getLocusDTO: sandbox.stub().resolves({body: fakeFullLocusDto}),
2556
+ },
2557
+ locusInfo: {
2558
+ onFullLocus: sandbox.stub(),
2559
+ handleLocusDelta: sandbox.stub(),
2560
+ },
2561
+ locusUrl: 'fake locus FULL url',
2562
+ };
2563
+
2564
+ sinon.stub(locusInfo.locusParser, 'resume').resolves();
2565
+
2566
+ if (isDelta) {
2567
+ locusInfo.locusParser.workingCopy = {syncUrl: 'fake locus DELTA url'};
2568
+ } else {
2569
+ locusInfo.locusParser.workingCopy = {}; // no syncUrl (to trigger FULL DTO request)
2570
+ }
2571
+
2572
+ await locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
2573
+
2574
+ await testUtils.flushPromises();
2575
+
2576
+ if (isDelta) {
2577
+ assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {
2578
+ url: 'fake locus DELTA url',
2579
+ });
2580
+ } else {
2581
+ assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {
2582
+ url: 'fake locus FULL url',
2583
+ });
2584
+ }
2585
+ assert.notCalled(meeting.locusInfo.handleLocusDelta);
2586
+ assert.notCalled(meeting.locusInfo.onFullLocus);
2587
+ assert.calledOnce(locusInfo.locusParser.resume);
2588
+ })
2589
+ );
2590
+
2591
+ it(`applyLocusDeltaData - handles the case when we get FULL DTO when we asked for DELTA DTO`, async () => {
2592
+ const {DESYNC} = LocusDeltaParser.loci;
2593
+ const fakeFullLocusDto = {someStuff: 'data'}; // non-empty DTO, without baseSequence
2594
+ const meeting = {
2595
+ meetingRequest: {
2596
+ getLocusDTO: sandbox.stub().resolves({body: fakeFullLocusDto}),
2597
+ },
2598
+ locusInfo: {
2599
+ onFullLocus: sandbox.stub(),
2600
+ handleLocusDelta: sandbox.stub(),
2601
+ },
2602
+ locusUrl: 'fake locus FULL url',
2603
+ };
2604
+
2605
+ sinon.stub(locusInfo.locusParser, 'resume').resolves();
2606
+
2607
+ locusInfo.locusParser.workingCopy = {syncUrl: 'fake locus DELTA url'};
2608
+
2609
+ await locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
2610
+
2611
+ await testUtils.flushPromises();
2612
+
2613
+ assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {
2614
+ url: 'fake locus DELTA url',
2615
+ });
2616
+ assert.notCalled(meeting.locusInfo.handleLocusDelta);
2617
+ assert.calledOnceWithExactly(meeting.locusInfo.onFullLocus, fakeFullLocusDto);
2618
+ assert.calledOnce(locusInfo.locusParser.resume);
2619
+ });
2483
2620
  });
2484
2621
 
2485
2622
  describe('#updateLocusCache', () => {
@@ -2892,10 +3029,9 @@ describe('plugin-meetings', () => {
2892
3029
  beforeEach(() => {
2893
3030
  clock = sinon.useFakeTimers();
2894
3031
 
2895
- sinon.stub(locusInfo, 'updateParticipantDeltas');
2896
3032
  sinon.stub(locusInfo, 'updateParticipants');
2897
- sinon.stub(locusInfo, 'isMeetingActive'),
2898
- sinon.stub(locusInfo, 'handleOneOnOneEvent'),
3033
+ sinon.stub(locusInfo, 'isMeetingActive');
3034
+ sinon.stub(locusInfo, 'handleOneOnOneEvent');
2899
3035
  (updateLocusInfoStub = sinon.stub(locusInfo, 'updateLocusInfo'));
2900
3036
  syncRequestStub = sinon.stub().resolves({body: {}});
2901
3037
 
@@ -137,6 +137,113 @@ describe('createMediaConnection', () => {
137
137
  );
138
138
  });
139
139
 
140
+ it('should set direction to sendonly for both audio and video when only send flags are true', () => {
141
+ const roapMediaConnectionConstructorStub = sinon
142
+ .stub(InternalMediaCoreModule, 'RoapMediaConnection')
143
+ .returns(fakeRoapMediaConnection);
144
+
145
+ StaticConfig.set({bandwidth: {audio: 123, video: 456, startBitrate: 999}});
146
+
147
+ const ENABLE_EXTMAP = false;
148
+ const ENABLE_RTX = true;
149
+
150
+ Media.createMediaConnection(false, 'sendonly-debug-id', 'meetingId', {
151
+ mediaProperties: {
152
+ mediaDirection: {
153
+ sendAudio: true,
154
+ receiveAudio: false,
155
+ sendVideo: true,
156
+ receiveVideo: false,
157
+ sendShare: false,
158
+ receiveShare: false,
159
+ },
160
+ audioStream: fakeAudioStream,
161
+ videoStream: fakeVideoStream,
162
+ shareVideoTrack: null,
163
+ shareAudioTrack: null,
164
+ },
165
+ remoteQualityLevel: 'HIGH',
166
+ enableRtx: ENABLE_RTX,
167
+ enableExtmap: ENABLE_EXTMAP,
168
+ turnServerInfo: undefined,
169
+ iceCandidatesTimeout: undefined,
170
+ });
171
+
172
+ assert.calledWith(
173
+ roapMediaConnectionConstructorStub,
174
+ sinon.match.any,
175
+ {
176
+ localTracks: {
177
+ audio: fakeTrack,
178
+ video: fakeTrack,
179
+ screenShareVideo: undefined,
180
+ screenShareAudio: undefined,
181
+ },
182
+ direction: {
183
+ audio: 'sendonly',
184
+ video: 'sendonly',
185
+ screenShareVideo: 'inactive',
186
+ },
187
+ remoteQualityLevel: 'HIGH',
188
+ },
189
+ 'sendonly-debug-id'
190
+ );
191
+ });
192
+
193
+ it('should set direction to recvonly for both audio and video when only receive flags are true', () => {
194
+ const roapMediaConnectionConstructorStub = sinon
195
+ .stub(InternalMediaCoreModule, 'RoapMediaConnection')
196
+ .returns(fakeRoapMediaConnection);
197
+
198
+ StaticConfig.set({bandwidth: {audio: 123, video: 456, startBitrate: 999}});
199
+
200
+ const ENABLE_EXTMAP = true;
201
+ const ENABLE_RTX = false;
202
+
203
+ Media.createMediaConnection(false, 'recvonly-debug-id', 'meetingId', {
204
+ mediaProperties: {
205
+ mediaDirection: {
206
+ sendAudio: false,
207
+ receiveAudio: true,
208
+ sendVideo: false,
209
+ receiveVideo: true,
210
+ sendShare: false,
211
+ receiveShare: false,
212
+ },
213
+ audioStream: fakeAudioStream,
214
+ videoStream: fakeVideoStream,
215
+ shareVideoTrack: null,
216
+ shareAudioTrack: null,
217
+ },
218
+ remoteQualityLevel: 'HIGH',
219
+ enableRtx: ENABLE_RTX,
220
+ enableExtmap: ENABLE_EXTMAP,
221
+ turnServerInfo: undefined,
222
+ iceCandidatesTimeout: undefined,
223
+ });
224
+
225
+ assert.calledWith(
226
+ roapMediaConnectionConstructorStub,
227
+ sinon.match.any,
228
+ {
229
+ localTracks: {
230
+ audio: fakeTrack,
231
+ video: fakeTrack,
232
+ screenShareVideo: undefined,
233
+ screenShareAudio: undefined,
234
+ },
235
+ direction: {
236
+ audio: 'recvonly',
237
+ video: 'recvonly',
238
+ screenShareVideo: 'inactive',
239
+ },
240
+ remoteQualityLevel: 'HIGH',
241
+ },
242
+ 'recvonly-debug-id'
243
+ );
244
+ });
245
+
246
+
140
247
  it('creates a MultistreamRoapMediaConnection when multistream is enabled', () => {
141
248
  const multistreamRoapMediaConnectionConstructorStub = sinon
142
249
  .stub(InternalMediaCoreModule, 'MultistreamRoapMediaConnection')