@webex/plugin-meetings 3.0.0-stream-classes.5 → 3.0.0-test.1

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 (233) hide show
  1. package/README.md +12 -0
  2. package/dist/breakouts/breakout.js +1 -1
  3. package/dist/breakouts/index.js +1 -1
  4. package/dist/common/errors/no-meeting-info.js +51 -0
  5. package/dist/common/errors/no-meeting-info.js.map +1 -0
  6. package/dist/common/errors/reclaim-host-role-errors.js +158 -0
  7. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  8. package/dist/common/errors/webex-errors.js +23 -3
  9. package/dist/common/errors/webex-errors.js.map +1 -1
  10. package/dist/common/logs/request.js +5 -1
  11. package/dist/common/logs/request.js.map +1 -1
  12. package/dist/config.js +1 -1
  13. package/dist/config.js.map +1 -1
  14. package/dist/constants.js +67 -9
  15. package/dist/constants.js.map +1 -1
  16. package/dist/index.js +11 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/interceptors/index.js +15 -0
  19. package/dist/interceptors/index.js.map +1 -0
  20. package/dist/interceptors/locusRetry.js +93 -0
  21. package/dist/interceptors/locusRetry.js.map +1 -0
  22. package/dist/interpretation/index.js +16 -2
  23. package/dist/interpretation/index.js.map +1 -1
  24. package/dist/interpretation/siLanguage.js +1 -1
  25. package/dist/locus-info/index.js +15 -10
  26. package/dist/locus-info/index.js.map +1 -1
  27. package/dist/locus-info/mediaSharesUtils.js +15 -1
  28. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  29. package/dist/locus-info/parser.js +37 -21
  30. package/dist/locus-info/parser.js.map +1 -1
  31. package/dist/media/index.js +10 -6
  32. package/dist/media/index.js.map +1 -1
  33. package/dist/media/properties.js +13 -3
  34. package/dist/media/properties.js.map +1 -1
  35. package/dist/mediaQualityMetrics/config.js +135 -330
  36. package/dist/mediaQualityMetrics/config.js.map +1 -1
  37. package/dist/meeting/in-meeting-actions.js +4 -0
  38. package/dist/meeting/in-meeting-actions.js.map +1 -1
  39. package/dist/meeting/index.js +2143 -1087
  40. package/dist/meeting/index.js.map +1 -1
  41. package/dist/meeting/muteState.js +37 -25
  42. package/dist/meeting/muteState.js.map +1 -1
  43. package/dist/meeting/request.js +33 -18
  44. package/dist/meeting/request.js.map +1 -1
  45. package/dist/meeting/util.js +71 -0
  46. package/dist/meeting/util.js.map +1 -1
  47. package/dist/meeting-info/index.js +48 -23
  48. package/dist/meeting-info/index.js.map +1 -1
  49. package/dist/meeting-info/meeting-info-v2.js +25 -4
  50. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  51. package/dist/meeting-info/utilv2.js +1 -1
  52. package/dist/meeting-info/utilv2.js.map +1 -1
  53. package/dist/meetings/collection.js +17 -0
  54. package/dist/meetings/collection.js.map +1 -1
  55. package/dist/meetings/index.js +142 -57
  56. package/dist/meetings/index.js.map +1 -1
  57. package/dist/meetings/util.js +2 -6
  58. package/dist/meetings/util.js.map +1 -1
  59. package/dist/member/index.js +9 -0
  60. package/dist/member/index.js.map +1 -1
  61. package/dist/member/util.js +11 -0
  62. package/dist/member/util.js.map +1 -1
  63. package/dist/members/index.js +17 -1
  64. package/dist/members/index.js.map +1 -1
  65. package/dist/members/types.js.map +1 -1
  66. package/dist/members/util.js +15 -4
  67. package/dist/members/util.js.map +1 -1
  68. package/dist/metrics/constants.js +13 -1
  69. package/dist/metrics/constants.js.map +1 -1
  70. package/dist/multistream/mediaRequestManager.js +1 -1
  71. package/dist/multistream/mediaRequestManager.js.map +1 -1
  72. package/dist/multistream/remoteMediaGroup.js +16 -2
  73. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  74. package/dist/multistream/remoteMediaManager.js +177 -65
  75. package/dist/multistream/remoteMediaManager.js.map +1 -1
  76. package/dist/multistream/sendSlotManager.js +22 -0
  77. package/dist/multistream/sendSlotManager.js.map +1 -1
  78. package/dist/reachability/clusterReachability.js +356 -0
  79. package/dist/reachability/clusterReachability.js.map +1 -0
  80. package/dist/reachability/index.js +262 -432
  81. package/dist/reachability/index.js.map +1 -1
  82. package/dist/reachability/request.js +1 -1
  83. package/dist/reachability/request.js.map +1 -1
  84. package/dist/reachability/util.js +29 -0
  85. package/dist/reachability/util.js.map +1 -0
  86. package/dist/reconnection-manager/index.js +113 -96
  87. package/dist/reconnection-manager/index.js.map +1 -1
  88. package/dist/roap/index.js +57 -25
  89. package/dist/roap/index.js.map +1 -1
  90. package/dist/roap/request.js +5 -13
  91. package/dist/roap/request.js.map +1 -1
  92. package/dist/roap/turnDiscovery.js +173 -81
  93. package/dist/roap/turnDiscovery.js.map +1 -1
  94. package/dist/rtcMetrics/index.js +68 -6
  95. package/dist/rtcMetrics/index.js.map +1 -1
  96. package/dist/statsAnalyzer/index.js +338 -289
  97. package/dist/statsAnalyzer/index.js.map +1 -1
  98. package/dist/statsAnalyzer/mqaUtil.js +296 -156
  99. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  100. package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
  101. package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
  102. package/dist/types/common/errors/webex-errors.d.ts +13 -1
  103. package/dist/types/common/logs/request.d.ts +2 -0
  104. package/dist/types/config.d.ts +1 -1
  105. package/dist/types/constants.d.ts +65 -13
  106. package/dist/types/index.d.ts +1 -1
  107. package/dist/types/interceptors/index.d.ts +2 -0
  108. package/dist/types/interceptors/locusRetry.d.ts +27 -0
  109. package/dist/types/locus-info/index.d.ts +1 -1
  110. package/dist/types/locus-info/parser.d.ts +3 -2
  111. package/dist/types/mediaQualityMetrics/config.d.ts +99 -223
  112. package/dist/types/meeting/in-meeting-actions.d.ts +4 -0
  113. package/dist/types/meeting/index.d.ts +272 -35
  114. package/dist/types/meeting/muteState.d.ts +2 -8
  115. package/dist/types/meeting/request.d.ts +2 -0
  116. package/dist/types/meeting/util.d.ts +16 -0
  117. package/dist/types/meeting-info/index.d.ts +7 -0
  118. package/dist/types/meeting-info/meeting-info-v2.d.ts +1 -0
  119. package/dist/types/meetings/collection.d.ts +9 -0
  120. package/dist/types/meetings/index.d.ts +42 -14
  121. package/dist/types/member/index.d.ts +1 -0
  122. package/dist/types/members/types.d.ts +1 -0
  123. package/dist/types/members/util.d.ts +5 -0
  124. package/dist/types/metrics/constants.d.ts +12 -0
  125. package/dist/types/multistream/mediaRequestManager.d.ts +2 -0
  126. package/dist/types/multistream/remoteMediaGroup.d.ts +2 -0
  127. package/dist/types/multistream/remoteMediaManager.d.ts +16 -0
  128. package/dist/types/multistream/sendSlotManager.d.ts +9 -0
  129. package/dist/types/reachability/clusterReachability.d.ts +109 -0
  130. package/dist/types/reachability/index.d.ts +59 -106
  131. package/dist/types/reachability/util.d.ts +8 -0
  132. package/dist/types/reconnection-manager/index.d.ts +10 -0
  133. package/dist/types/roap/index.d.ts +2 -1
  134. package/dist/types/roap/turnDiscovery.d.ts +21 -4
  135. package/dist/types/rtcMetrics/index.d.ts +15 -1
  136. package/dist/types/statsAnalyzer/index.d.ts +28 -11
  137. package/dist/types/statsAnalyzer/mqaUtil.d.ts +28 -4
  138. package/dist/types/webinar/collection.d.ts +16 -0
  139. package/dist/types/webinar/index.d.ts +5 -0
  140. package/dist/webinar/collection.js +44 -0
  141. package/dist/webinar/collection.js.map +1 -0
  142. package/dist/webinar/index.js +69 -0
  143. package/dist/webinar/index.js.map +1 -0
  144. package/package.json +3 -2
  145. package/src/common/errors/no-meeting-info.ts +24 -0
  146. package/src/common/errors/reclaim-host-role-errors.ts +134 -0
  147. package/src/common/errors/webex-errors.ts +19 -2
  148. package/src/common/logs/request.ts +5 -1
  149. package/src/config.ts +1 -1
  150. package/src/constants.ts +70 -6
  151. package/src/index.ts +5 -0
  152. package/src/interceptors/index.ts +3 -0
  153. package/src/interceptors/locusRetry.ts +67 -0
  154. package/src/interpretation/index.ts +18 -1
  155. package/src/locus-info/index.ts +19 -14
  156. package/src/locus-info/mediaSharesUtils.ts +16 -0
  157. package/src/locus-info/parser.ts +40 -21
  158. package/src/media/index.ts +8 -6
  159. package/src/media/properties.ts +17 -2
  160. package/src/mediaQualityMetrics/config.ts +103 -238
  161. package/src/meeting/in-meeting-actions.ts +8 -0
  162. package/src/meeting/index.ts +1471 -533
  163. package/src/meeting/muteState.ts +34 -20
  164. package/src/meeting/request.ts +18 -0
  165. package/src/meeting/util.ts +97 -0
  166. package/src/meeting-info/index.ts +47 -20
  167. package/src/meeting-info/meeting-info-v2.ts +27 -5
  168. package/src/meeting-info/utilv2.ts +1 -1
  169. package/src/meetings/collection.ts +13 -0
  170. package/src/meetings/index.ts +112 -31
  171. package/src/meetings/util.ts +2 -8
  172. package/src/member/index.ts +9 -0
  173. package/src/member/util.ts +14 -0
  174. package/src/members/index.ts +29 -2
  175. package/src/members/types.ts +1 -0
  176. package/src/members/util.ts +15 -1
  177. package/src/metrics/constants.ts +12 -0
  178. package/src/multistream/mediaRequestManager.ts +4 -1
  179. package/src/multistream/remoteMediaGroup.ts +19 -0
  180. package/src/multistream/remoteMediaManager.ts +101 -15
  181. package/src/multistream/sendSlotManager.ts +29 -0
  182. package/src/reachability/clusterReachability.ts +320 -0
  183. package/src/reachability/index.ts +221 -382
  184. package/src/reachability/request.ts +1 -1
  185. package/src/reachability/util.ts +24 -0
  186. package/src/reconnection-manager/index.ts +87 -83
  187. package/src/roap/index.ts +60 -24
  188. package/src/roap/request.ts +3 -16
  189. package/src/roap/turnDiscovery.ts +112 -39
  190. package/src/rtcMetrics/index.ts +71 -5
  191. package/src/statsAnalyzer/index.ts +430 -427
  192. package/src/statsAnalyzer/mqaUtil.ts +317 -168
  193. package/src/webinar/collection.ts +31 -0
  194. package/src/webinar/index.ts +62 -0
  195. package/test/integration/spec/journey.js +22 -22
  196. package/test/unit/spec/interceptors/locusRetry.ts +131 -0
  197. package/test/unit/spec/interpretation/index.ts +36 -3
  198. package/test/unit/spec/locus-info/index.js +87 -11
  199. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  200. package/test/unit/spec/locus-info/mediaSharesUtils.ts +10 -0
  201. package/test/unit/spec/locus-info/parser.js +54 -13
  202. package/test/unit/spec/media/index.ts +20 -4
  203. package/test/unit/spec/media/properties.ts +2 -2
  204. package/test/unit/spec/meeting/in-meeting-actions.ts +4 -0
  205. package/test/unit/spec/meeting/index.js +4178 -1289
  206. package/test/unit/spec/meeting/muteState.js +219 -67
  207. package/test/unit/spec/meeting/request.js +63 -12
  208. package/test/unit/spec/meeting/utils.js +93 -0
  209. package/test/unit/spec/meeting-info/index.js +180 -61
  210. package/test/unit/spec/meeting-info/meetinginfov2.js +196 -53
  211. package/test/unit/spec/meetings/collection.js +12 -0
  212. package/test/unit/spec/meetings/index.js +617 -204
  213. package/test/unit/spec/meetings/utils.js +35 -12
  214. package/test/unit/spec/member/index.js +8 -7
  215. package/test/unit/spec/member/util.js +32 -0
  216. package/test/unit/spec/members/index.js +130 -17
  217. package/test/unit/spec/members/utils.js +26 -0
  218. package/test/unit/spec/multistream/mediaRequestManager.ts +20 -2
  219. package/test/unit/spec/multistream/remoteMediaGroup.ts +80 -1
  220. package/test/unit/spec/multistream/remoteMediaManager.ts +200 -1
  221. package/test/unit/spec/multistream/sendSlotManager.ts +50 -18
  222. package/test/unit/spec/reachability/clusterReachability.ts +279 -0
  223. package/test/unit/spec/reachability/index.ts +505 -135
  224. package/test/unit/spec/reachability/util.ts +40 -0
  225. package/test/unit/spec/reconnection-manager/index.js +74 -17
  226. package/test/unit/spec/roap/index.ts +181 -61
  227. package/test/unit/spec/roap/request.ts +27 -3
  228. package/test/unit/spec/roap/turnDiscovery.ts +362 -101
  229. package/test/unit/spec/rtcMetrics/index.ts +57 -3
  230. package/test/unit/spec/stats-analyzer/index.js +1225 -12
  231. package/test/unit/spec/webinar/collection.ts +13 -0
  232. package/test/unit/spec/webinar/index.ts +60 -0
  233. package/test/utils/webex-test-users.js +12 -4
@@ -0,0 +1,62 @@
1
+ /*!
2
+ * Copyright (c) 2015-2023 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+ import {WebexPlugin} from '@webex/webex-core';
5
+ import {MEETINGS} from '../constants';
6
+
7
+ import WebinarCollection from './collection';
8
+
9
+ /**
10
+ * @class Webinar
11
+ */
12
+ const Webinar = WebexPlugin.extend({
13
+ namespace: MEETINGS,
14
+ collections: {
15
+ webinar: WebinarCollection,
16
+ },
17
+
18
+ props: {
19
+ locusUrl: 'string', // appears current webinar's locus url
20
+ webcastUrl: 'string', // current webinar's webcast url
21
+ webinarAttendeesSearchingUrl: 'string', // current webinarAttendeesSearching url
22
+ canManageWebcast: 'boolean', // appears the ability to manage webcast
23
+ },
24
+
25
+ /**
26
+ * Update the current locus url of the webinar
27
+ * @param {string} locusUrl // locus url
28
+ * @returns {void}
29
+ */
30
+ locusUrlUpdate(locusUrl) {
31
+ this.set('locusUrl', locusUrl);
32
+ },
33
+
34
+ /**
35
+ * Update the current webcast url of the meeting
36
+ * @param {string} webcastUrl // webcast url
37
+ * @returns {void}
38
+ */
39
+ webcastUrlUpdate(webcastUrl) {
40
+ this.set('webcastUrl', webcastUrl);
41
+ },
42
+
43
+ /**
44
+ * Update the current webinarAttendeesSearching url of the meeting
45
+ * @param {string} webinarAttendeesSearchingUrl // webinarAttendeesSearching url
46
+ * @returns {void}
47
+ */
48
+ webinarAttendeesSearchingUrlUpdate(webinarAttendeesSearchingUrl) {
49
+ this.set('webinarAttendeesSearchingUrl', webinarAttendeesSearchingUrl);
50
+ },
51
+
52
+ /**
53
+ * Update whether self has capability to manage start/stop webcast (only host can manage it)
54
+ * @param {boolean} canManageWebcast
55
+ * @returns {void}
56
+ */
57
+ updateCanManageWebcast(canManageWebcast) {
58
+ this.set('canManageWebcast', canManageWebcast);
59
+ },
60
+ });
61
+
62
+ export default Webinar;
@@ -44,14 +44,14 @@ const localStreams = {
44
44
  },
45
45
  };
46
46
 
47
-
47
+ // Updated expectedPublished from a boolean value to an object containing the stream and status properties
48
48
  const waitForPublished = (meeting, expectedPublished, description) => {
49
49
  return testUtils.waitForEvents([{
50
50
  scope: meeting,
51
51
  event: EVENT_TRIGGERS.MEETING_STREAM_PUBLISH_STATE_CHANGED,
52
52
  match: (event) => {
53
53
  console.log(`${description} is now ${event.isPublished ? 'published': 'not published'}`);
54
- return (event.isPublished === expectedPublished);
54
+ return (event.isPublished === expectedPublished.status && event.stream.id === expectedPublished.stream.id) ;
55
55
  }
56
56
  }]);
57
57
  };
@@ -432,11 +432,11 @@ skipInNode(describe)('plugin-meetings', () => {
432
432
  {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
433
433
  ]);
434
434
 
435
- localStreams.alice.microphone.setMuted(true);
435
+ localStreams.alice.microphone.setUserMuted(true);
436
436
 
437
437
  await membersUpdate;
438
438
 
439
- assert.equal(localStreams.alice.microphone.muted, true);
439
+ assert.equal(localStreams.alice.microphone.userMuted, true);
440
440
  });
441
441
 
442
442
  it('alice Audio unMute ', async () => {
@@ -451,11 +451,11 @@ skipInNode(describe)('plugin-meetings', () => {
451
451
  {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
452
452
  ]);
453
453
 
454
- localStreams.alice.microphone.setMuted(false);
454
+ localStreams.alice.microphone.setUserMuted(false);
455
455
 
456
456
  await membersUpdate;
457
457
 
458
- assert.equal(localStreams.alice.microphone.muted, false);
458
+ assert.equal(localStreams.alice.microphone.userMuted, false);
459
459
  });
460
460
 
461
461
  it('alice video mute', async () => {
@@ -470,11 +470,11 @@ skipInNode(describe)('plugin-meetings', () => {
470
470
  {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
471
471
  ]);
472
472
 
473
- localStreams.alice.camera.setMuted(true);
473
+ localStreams.alice.camera.setUserMuted(true);
474
474
 
475
475
  await membersUpdate;
476
476
 
477
- assert.equal(localStreams.alice.camera.muted, true);
477
+ assert.equal(localStreams.alice.camera.userMuted, true);
478
478
  });
479
479
 
480
480
  it('alice video unmute', async () => {
@@ -489,16 +489,16 @@ skipInNode(describe)('plugin-meetings', () => {
489
489
  {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
490
490
  ]);
491
491
 
492
- localStreams.alice.camera.setMuted(false);
492
+ localStreams.alice.camera.setUserMuted(false);
493
493
 
494
494
  await membersUpdate;
495
495
 
496
- assert.equal(localStreams.alice.camera.muted, false);
496
+ assert.equal(localStreams.alice.camera.userMuted, false);
497
497
  });
498
498
 
499
499
  it('alice update Audio', async () => {
500
500
  const newMicrophoneStream = await createMicrophoneStream();
501
- const newStreamPublished = waitForPublished(alice.meeting, true, "Alice AUDIO: new microphone stream");
501
+ const newStreamPublished = waitForPublished(alice.meeting, {stream: newMicrophoneStream, status: true}, "Alice AUDIO: new microphone stream");
502
502
 
503
503
  await testUtils.delayedPromise(
504
504
  alice.meeting
@@ -521,7 +521,7 @@ skipInNode(describe)('plugin-meetings', () => {
521
521
 
522
522
  it('alice update video', async () => {
523
523
  const newCameraStream = await createCameraStream();
524
- const newStreamPublished = waitForPublished(alice.meeting, true, "Alice VIDEO: new camera stream");
524
+ const newStreamPublished = waitForPublished(alice.meeting, {stream: newCameraStream, status: true}, "Alice VIDEO: new camera stream");
525
525
 
526
526
  await testUtils.delayedPromise(
527
527
  alice.meeting
@@ -574,11 +574,11 @@ skipInNode(describe)('plugin-meetings', () => {
574
574
  ]);
575
575
 
576
576
  // first bob mutes himself
577
- localStreams.bob.microphone.setMuted(true);
577
+ localStreams.bob.microphone.setUserMuted(true);
578
578
 
579
579
  await membersUpdate;
580
580
 
581
- assert.equal(localStreams.bob.microphone.muted, true);
581
+ assert.equal(localStreams.bob.microphone.userMuted, true);
582
582
 
583
583
  // now alice tries to unmmute bob
584
584
  await testUtils.delayedPromise(alice.meeting.mute(bob.meeting.members.selfId, false))
@@ -593,7 +593,7 @@ skipInNode(describe)('plugin-meetings', () => {
593
593
  assert.fail('bob received unexpected meeting:self:unmutedByOthers event');
594
594
  })
595
595
  .catch(() => {
596
- assert.equal(localStreams.bob.microphone.muted, true);
596
+ assert.equal(localStreams.bob.microphone.userMuted, true);
597
597
  });
598
598
  });
599
599
 
@@ -607,11 +607,11 @@ skipInNode(describe)('plugin-meetings', () => {
607
607
  {scope: alice.meeting.members, event: 'members:update', match: checkEvent},
608
608
  ]);
609
609
 
610
- localStreams.bob.microphone.setMuted(false);
610
+ localStreams.bob.microphone.setUserMuted(false);
611
611
 
612
612
  await membersUpdate;
613
613
 
614
- assert.equal(localStreams.bob.microphone.muted, false);
614
+ assert.equal(localStreams.bob.microphone.userMuted, false);
615
615
  });
616
616
 
617
617
  it('alice shares the screen with highFrameRate', async () => {
@@ -630,7 +630,7 @@ skipInNode(describe)('plugin-meetings', () => {
630
630
  );
631
631
  });
632
632
 
633
- const screenShareVideoPublished = waitForPublished(alice.meeting, true, "alice's screen share video stream");
633
+ const screenShareVideoPublished = waitForPublished(alice.meeting, {stream: localStreams.alice.screenShare.video, status: true}, "alice's screen share video stream");
634
634
 
635
635
  await testUtils.delayedPromise(alice.meeting.publishStreams({screenShare: {video: localStreams.alice.screenShare.video}}));
636
636
 
@@ -666,8 +666,8 @@ skipInNode(describe)('plugin-meetings', () => {
666
666
  JSON.stringify(response, testUtils.getCircularReplacer())
667
667
  );
668
668
  });
669
- const aliceScreenShareVideoUnpublished = waitForPublished(alice.meeting, false, "alice's screen share video stream");
670
- const bobScreenShareVideoPublished = waitForPublished(bob.meeting, true, "bob's screen share video stream");
669
+ const aliceScreenShareVideoUnpublished = waitForPublished(alice.meeting, {stream: localStreams.alice.screenShare.video, status: false}, "alice's screen share video stream");
670
+ const bobScreenShareVideoPublished = waitForPublished(bob.meeting, {stream: localStreams.bob.screenShare.video, status: true}, "bob's screen share video stream");
671
671
 
672
672
  await testUtils.delayedPromise(bob.meeting.publishStreams({screenShare: {video: localStreams.bob.screenShare.video}}));
673
673
 
@@ -689,7 +689,7 @@ skipInNode(describe)('plugin-meetings', () => {
689
689
  });
690
690
 
691
691
  it('bob stops sharing', async () => {
692
- const screenShareVideoUnpublished = waitForPublished(bob.meeting, false, "bob's screen share video stream");
692
+ const screenShareVideoUnpublished = waitForPublished(bob.meeting, {stream: localStreams.bob.screenShare.video, status: false}, "bob's screen share video stream");
693
693
  const stoppedSharingLocal = testUtils.waitForEvents([{scope: bob.meeting, event: 'meeting:stoppedSharingLocal'}]);
694
694
  const stoppedSharingRemote = testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:stoppedSharingRemote'}]);
695
695
 
@@ -826,7 +826,7 @@ skipInNode(describe)('plugin-meetings', () => {
826
826
  JSON.stringify(response, testUtils.getCircularReplacer())
827
827
  );
828
828
  });
829
- const bobScreenShareVideoPublished = waitForPublished(bob.meeting, true, "bob's screen share video stream");
829
+ const bobScreenShareVideoPublished = waitForPublished(bob.meeting, {stream: localStreams.bob.screenShare.video, status: true}, "bob's screen share video stream");
830
830
 
831
831
  await testUtils.delayedPromise(bob.meeting.publishStreams({screenShare: {video: localStreams.bob.screenShare.video}}));
832
832
 
@@ -0,0 +1,131 @@
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ /* eslint-disable camelcase */
6
+ import {assert} from '@webex/test-helper-chai';
7
+ import { expect } from "@webex/test-helper-chai";
8
+ import MockWebex from '@webex/test-helper-mock-webex';
9
+ import {LocusRetryStatusInterceptor} from "@webex/plugin-meetings/src/interceptors";
10
+ import {WebexHttpError} from '@webex/webex-core';
11
+ import Meetings from '@webex/plugin-meetings';
12
+ import sinon from 'sinon';
13
+
14
+ describe('plugin-meetings', () => {
15
+ describe('Interceptors', () => {
16
+ describe('LocusRetryStatusInterceptor', () => {
17
+ let interceptor, webex;
18
+ beforeEach(() => {
19
+ webex = new MockWebex({
20
+ children: {
21
+ meeting: Meetings,
22
+ },
23
+ });
24
+ interceptor = Reflect.apply(LocusRetryStatusInterceptor.create, {
25
+ sessionId: 'mock-webex_uuid',
26
+ }, []);
27
+ });
28
+ describe('#onResponseError', () => {
29
+ const options = {
30
+ method: 'POST',
31
+ headers: {
32
+ trackingid: 'test',
33
+ 'retry-after': 1000,
34
+ },
35
+ uri: `https://locus-test.webex.com/locus/api/v1/loci/call`,
36
+ body: 'foo'
37
+ };
38
+ const reason1 = new WebexHttpError.MethodNotAllowed({
39
+ statusCode: 403,
40
+ options: {
41
+ headers: {
42
+ trackingid: 'test',
43
+ 'retry-after': 1000,
44
+ },
45
+ uri: `https://locus-test.webex.com/locus/api/v1/loci/call`,
46
+ },
47
+ body: {
48
+ error: 'POST not allwed',
49
+ },
50
+ });
51
+ const reason2 = new WebexHttpError.MethodNotAllowed({
52
+ statusCode: 503,
53
+ options: {
54
+ headers: {
55
+ trackingid: 'test',
56
+ 'retry-after': 1000,
57
+ },
58
+ uri: `https://locus-test.webex.com/locus/api/v1/loci/call`,
59
+ },
60
+ body: {
61
+ error: 'Service Unavailable',
62
+ },
63
+ });
64
+
65
+ it('rejects when not locus service unavailable error', () => {
66
+ return assert.isRejected(interceptor.onResponseError(options, reason1));
67
+ });
68
+
69
+ it('calls handleRetryRequestLocusServiceError with correct retry time when locus service unavailable error', () => {
70
+ interceptor.webex.request = sinon.stub().returns(Promise.resolve());
71
+ const handleRetryStub = sinon.stub(interceptor, 'handleRetryRequestLocusServiceError');
72
+ handleRetryStub.returns(Promise.resolve());
73
+
74
+ return interceptor.onResponseError(options, reason2).then(() => {
75
+ expect(handleRetryStub.calledWith(options, 1000)).to.be.true;
76
+
77
+ });
78
+ });
79
+ });
80
+
81
+ describe('#handleRetryRequestLocusServiceError', () => {
82
+ const options = {
83
+ method: 'POST',
84
+ headers: {
85
+ trackingid: 'test',
86
+ },
87
+ uri: `https://locus-test.webex.com/locus/api/v1/loci/call`,
88
+ body: 'foo'
89
+ };
90
+ const retryAfterTime = 2000;
91
+
92
+ it('returns the correct resolved value when the request is successful', () => {
93
+ const mockResponse = 'mock response'
94
+ interceptor.webex.request = sinon.stub().returns(Promise.resolve(mockResponse));
95
+
96
+ return interceptor.handleRetryRequestLocusServiceError(options, retryAfterTime)
97
+ .then((response) => {
98
+ expect(response).to.equal(mockResponse);
99
+ });
100
+ });
101
+
102
+ it('rejects the promise when the request is unsuccessful', () => {
103
+ const rejectionReason = 'Service Unavaialble after retry';
104
+
105
+ interceptor.webex.request = sinon.stub().returns(Promise.reject(rejectionReason));
106
+
107
+ return interceptor.handleRetryRequestLocusServiceError(options, retryAfterTime)
108
+ .catch((error) => {
109
+ expect(error).to.equal(rejectionReason);
110
+ });
111
+ });
112
+
113
+ it('retries the request after the specified time', () => {
114
+ let clock;
115
+ clock = sinon.useFakeTimers();
116
+ const mockResponse = 'mock response'
117
+
118
+ interceptor.webex.request = sinon.stub().returns(Promise.resolve(mockResponse));
119
+ const promise = interceptor.handleRetryRequestLocusServiceError(options, retryAfterTime);
120
+
121
+ clock.tick(retryAfterTime);
122
+
123
+ return promise.then(() => {
124
+ expect(interceptor.webex.request.calledOnce).to.be.true;
125
+ });
126
+ });
127
+ });
128
+ });
129
+ });
130
+ });
131
+
@@ -1,6 +1,7 @@
1
1
  import {assert, expect} from '@webex/test-helper-chai';
2
2
  import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
3
3
  import SimultaneousInterpretation from '@webex/plugin-meetings/src/interpretation';
4
+ import SILanguage from '@webex/plugin-meetings/src/interpretation/siLanguage';
4
5
  import MockWebex from '@webex/test-helper-mock-webex';
5
6
  import sinon from 'sinon';
6
7
 
@@ -123,7 +124,7 @@ describe('plugin-meetings', () => {
123
124
  receiveLanguage: 'en',
124
125
  order: 0,
125
126
  }, selfParticipantId: '123'};
126
- interpretation.updateSelfInterpretation(sampleData);
127
+ assert.equal(interpretation.updateSelfInterpretation(sampleData), true);
127
128
  assert.equal(interpretation.originalLanguage, 'en');
128
129
  assert.equal(interpretation.sourceLanguage, 'en');
129
130
  assert.equal(interpretation.targetLanguage, 'zh');
@@ -133,12 +134,44 @@ describe('plugin-meetings', () => {
133
134
 
134
135
  sampleData.interpretation = {
135
136
  originalLanguage: 'en',
137
+ targetLanguage: 'zh',
136
138
  order: 0,
137
139
  };
138
- interpretation.updateSelfInterpretation(sampleData);
140
+ assert.equal(interpretation.updateSelfInterpretation(sampleData), false);
139
141
  assert.equal(interpretation.sourceLanguage, undefined);
140
- assert.equal(interpretation.targetLanguage, undefined);
142
+ assert.equal(interpretation.targetLanguage, 'zh');
141
143
  assert.equal(interpretation.receiveLanguage, undefined);
144
+
145
+ sampleData.interpretation = {
146
+ order: 0,
147
+ };
148
+ assert.equal(interpretation.updateSelfInterpretation(sampleData), false);
149
+ assert.equal(interpretation.originalLanguage, undefined);
150
+ assert.equal(interpretation.targetLanguage, undefined);
151
+ });
152
+ });
153
+
154
+ describe('#getTargetLanguageCode', () => {
155
+ it('get target language id if self is interpreter', () => {
156
+ interpretation.siLanguages.set([{
157
+ languageCode: 24,
158
+ languageName: "fr"
159
+ },
160
+ {
161
+ languageCode: 20,
162
+ languageName: "en"
163
+ }]);
164
+ interpretation.selfIsInterpreter = true;
165
+ interpretation.targetLanguage = 'fr';
166
+
167
+ assert.equal(interpretation.getTargetLanguageCode(), 24);
168
+
169
+ interpretation.targetLanguage = 'en';
170
+ assert.equal(interpretation.getTargetLanguageCode(), 20);
171
+
172
+ interpretation.selfIsInterpreter = false;
173
+ assert.equal(interpretation.getTargetLanguageCode(), 0);
174
+
142
175
  });
143
176
  });
144
177
 
@@ -1377,7 +1377,7 @@ describe('plugin-meetings', () => {
1377
1377
  );
1378
1378
  });
1379
1379
 
1380
- const checkMeetingInfoUpdatedCalled = (expected) => {
1380
+ const checkMeetingInfoUpdatedCalled = (expected, payload) => {
1381
1381
  const expectedArgs = [
1382
1382
  locusInfo.emitScoped,
1383
1383
  {
@@ -1385,6 +1385,7 @@ describe('plugin-meetings', () => {
1385
1385
  function: 'updateMeetingInfo',
1386
1386
  },
1387
1387
  LOCUSINFO.EVENTS.MEETING_INFO_UPDATED,
1388
+ payload
1388
1389
  ];
1389
1390
 
1390
1391
  if (expected) {
@@ -1395,7 +1396,7 @@ describe('plugin-meetings', () => {
1395
1396
  locusInfo.emitScoped.resetHistory();
1396
1397
  };
1397
1398
 
1398
- const checkMeetingInfoUpdatedCalledForRoles = (expected) => {
1399
+ const checkMeetingInfoUpdatedCalledForRoles = (expected, payload) => {
1399
1400
  const expectedArgs = [
1400
1401
  locusInfo.emitScoped,
1401
1402
  {
@@ -1403,6 +1404,7 @@ describe('plugin-meetings', () => {
1403
1404
  function: 'updateMeetingInfo',
1404
1405
  },
1405
1406
  LOCUSINFO.EVENTS.MEETING_INFO_UPDATED,
1407
+ payload
1406
1408
  ];
1407
1409
 
1408
1410
  if (expected) {
@@ -1447,7 +1449,7 @@ describe('plugin-meetings', () => {
1447
1449
 
1448
1450
  // since it was initially undefined, this should trigger the event
1449
1451
 
1450
- checkMeetingInfoUpdatedCalled(true);
1452
+ checkMeetingInfoUpdatedCalled(true, {isInitializing: false});
1451
1453
 
1452
1454
  const newInfo = cloneDeep(meetingInfo);
1453
1455
 
@@ -1472,7 +1474,7 @@ describe('plugin-meetings', () => {
1472
1474
  };
1473
1475
  locusInfo.updateMeetingInfo(newInfo, self);
1474
1476
 
1475
- checkMeetingInfoUpdatedCalled(true);
1477
+ checkMeetingInfoUpdatedCalled(true, {isInitializing: false});
1476
1478
 
1477
1479
  // update it with the same info
1478
1480
  expectedMeeting = {
@@ -1494,7 +1496,7 @@ describe('plugin-meetings', () => {
1494
1496
  locusInfo.updateMeetingInfo(newInfo, self);
1495
1497
 
1496
1498
  // since the info is the same it should not call trigger the event
1497
- checkMeetingInfoUpdatedCalled(false);
1499
+ checkMeetingInfoUpdatedCalled(false, {isInitializing: false});
1498
1500
 
1499
1501
  // update it with the same info, but roles changed
1500
1502
  const updateSelf = cloneDeep(self);
@@ -1525,7 +1527,7 @@ describe('plugin-meetings', () => {
1525
1527
  };
1526
1528
  locusInfo.updateMeetingInfo(newInfo, updateSelf);
1527
1529
  // since the info is the same but roles changed, it should call trigger the event
1528
- checkMeetingInfoUpdatedCalledForRoles(true);
1530
+ checkMeetingInfoUpdatedCalledForRoles(true, {isInitializing: false});
1529
1531
  });
1530
1532
 
1531
1533
  it('gets roles from self if available', () => {
@@ -1546,12 +1548,17 @@ describe('plugin-meetings', () => {
1546
1548
  roles: ['MODERATOR', 'COHOST'],
1547
1549
  };
1548
1550
 
1551
+ sinon.stub(locusInfo, 'emitScoped');
1552
+
1549
1553
  const parsedLocusInfo = cloneDeep(locusInfo.parsedLocus.info);
1550
1554
 
1551
1555
  locusInfo.updateMeetingInfo(initialInfo);
1552
1556
  assert.calledWith(isJoinedSpy, locusInfo.parsedLocus.self);
1553
1557
  assert.neverCalledWith(getRolesSpy, self);
1554
1558
  assert.calledWith(getInfosSpy, parsedLocusInfo, initialInfo, ['MODERATOR', 'COHOST']);
1559
+
1560
+ // since self is not passed to updateMeetingInfo, MEETING_INFO_UPDATED should be triggered with isIntializing: true
1561
+ checkMeetingInfoUpdatedCalledForRoles(true, {isInitializing: true});
1555
1562
  });
1556
1563
  });
1557
1564
 
@@ -1884,6 +1891,27 @@ describe('plugin-meetings', () => {
1884
1891
  });
1885
1892
  });
1886
1893
 
1894
+ it('applyLocusDeltaData handles LOCUS_URL_CHANGED action correctly', () => {
1895
+ const {LOCUS_URL_CHANGED} = LocusDeltaParser.loci;
1896
+ const fakeDeltaLocus = {id: 'fake delta locus'};
1897
+ const meeting = {
1898
+ meetingRequest: {
1899
+ getLocusDTO: sandbox.stub().resolves({body: fakeDeltaLocus}),
1900
+ },
1901
+ locusInfo: {
1902
+ handleLocusDelta: sandbox.stub(),
1903
+ },
1904
+ locusUrl: 'current locus url',
1905
+ };
1906
+
1907
+ locusInfo.locusParser.workingCopy = {
1908
+ syncUrl: 'current sync url',
1909
+ };
1910
+
1911
+ locusInfo.applyLocusDeltaData(LOCUS_URL_CHANGED, fakeLocus, meeting);
1912
+ assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {url: 'current sync url'});
1913
+ });
1914
+
1887
1915
  describe('edge cases for sync failing', () => {
1888
1916
  const {DESYNC} = LocusDeltaParser.loci;
1889
1917
  const fakeFullLocusDto = {id: 'fake full locus dto'};
@@ -2037,7 +2065,7 @@ describe('plugin-meetings', () => {
2037
2065
  });
2038
2066
 
2039
2067
  describe('#getTheLocusToUpdate', () => {
2040
- it('return the cache locus if return to main session', () => {
2068
+ it('return the cache locus if return to main session and do not clear main session cache', () => {
2041
2069
  locusInfo.mainSessionLocusCache = {url: 'url'};
2042
2070
  locusInfo.controls = {
2043
2071
  breakout: {
@@ -2053,9 +2081,13 @@ describe('plugin-meetings', () => {
2053
2081
  };
2054
2082
 
2055
2083
  assert.deepEqual(locusInfo.getTheLocusToUpdate(newLocus), {url: 'url'});
2084
+
2085
+ locusInfo.clearMainSessionLocusCache = sinon.stub();
2086
+ locusInfo.getTheLocusToUpdate(newLocus);
2087
+ assert.notCalled(locusInfo.clearMainSessionLocusCache)
2056
2088
  });
2057
2089
 
2058
- it('return the new locus if return to main session but no cache', () => {
2090
+ it('return the new locus if return to main session but no cache and do not clear main session cache', () => {
2059
2091
  locusInfo.mainSessionLocusCache = null;
2060
2092
  locusInfo.controls = {
2061
2093
  breakout: {
@@ -2071,10 +2103,22 @@ describe('plugin-meetings', () => {
2071
2103
  };
2072
2104
 
2073
2105
  assert.deepEqual(locusInfo.getTheLocusToUpdate(newLocus), newLocus);
2106
+
2107
+ locusInfo.clearMainSessionLocusCache = sinon.stub();
2108
+ locusInfo.getTheLocusToUpdate(newLocus);
2109
+ assert.notCalled(locusInfo.clearMainSessionLocusCache)
2074
2110
  });
2075
2111
 
2076
- it('return the new locus if not return to main session', () => {
2077
- locusInfo.mainSessionLocusCache = {url: 'url'};
2112
+ it('return the new locus if not return to main session and clear main session cache', () => {
2113
+ locusInfo.mainSessionLocusCache = {
2114
+ controls: {
2115
+ breakout: {
2116
+ sessionType: 'MAIN',
2117
+ },
2118
+ },
2119
+ self: {removed: true}
2120
+ };
2121
+ locusInfo.fullState = {state: 'ACTIVE'}
2078
2122
  locusInfo.controls = {
2079
2123
  breakout: {
2080
2124
  sessionType: 'MAIN',
@@ -2088,7 +2132,39 @@ describe('plugin-meetings', () => {
2088
2132
  },
2089
2133
  };
2090
2134
 
2091
- assert.deepEqual(locusInfo.getTheLocusToUpdate(newLocus), newLocus);
2135
+ locusInfo.clearMainSessionLocusCache = sinon.stub();
2136
+ const result = locusInfo.getTheLocusToUpdate(newLocus);
2137
+ assert.calledOnce(locusInfo.clearMainSessionLocusCache)
2138
+
2139
+ assert.deepEqual(result, newLocus);
2140
+ });
2141
+
2142
+ it('do not clear main session cache when "mainSessionLocusCache?.self?.removed" is not true', () => {
2143
+ locusInfo.mainSessionLocusCache = {
2144
+ controls: {
2145
+ breakout: {
2146
+ sessionType: 'MAIN',
2147
+ },
2148
+ },
2149
+ self: {removed: undefined}
2150
+ };
2151
+ locusInfo.fullState = {state: 'ACTIVE'}
2152
+ locusInfo.controls = {
2153
+ breakout: {
2154
+ sessionType: 'MAIN',
2155
+ },
2156
+ };
2157
+ const newLocus = {
2158
+ controls: {
2159
+ breakout: {
2160
+ sessionType: 'BREAKOUT',
2161
+ },
2162
+ },
2163
+ };
2164
+
2165
+ locusInfo.clearMainSessionLocusCache = sinon.stub();
2166
+ locusInfo.getTheLocusToUpdate(newLocus);
2167
+ assert.notCalled(locusInfo.clearMainSessionLocusCache)
2092
2168
  });
2093
2169
  });
2094
2170
 
@@ -517,6 +517,22 @@
517
517
  "new": "seq4g",
518
518
  "result": "DESYNC",
519
519
  "description": "New seq is greater than current, but both current and new base have some unique entries."
520
+ },
521
+ "updt25": {
522
+ "current": "seq4",
523
+ "newbase": "seq5c",
524
+ "new": "seq5b",
525
+ "result": "WAIT",
526
+ "description": "Both new seq and new base are newer than current but are not equal"
527
+ },
528
+ "updt26": {
529
+ "current": "seq4",
530
+ "currentUrl": "locus url 1",
531
+ "newbase": "seq5c",
532
+ "new": "seq5b",
533
+ "newUrl": "locus url 2",
534
+ "result": "LOCUS_URL_CHANGED",
535
+ "description": "Locus url changes in incoming"
520
536
  }
521
537
  }
522
538
  }
@@ -20,3 +20,13 @@ describe('getContentUrl', () => {
20
20
  });
21
21
  });
22
22
 
23
+ describe('getContentBeneficiaryDeviceUrl', () => {
24
+ it('getContentBeneficiaryDeviceUrl return correct deviceUrl value', () => {
25
+ const mockContentBeneficiaryDeviceUrl = "https://wdm-a.wbx2.com/wdm/api/v1/devices/e9ffd8a1-1fae-42d1-afbe-013e951f93ab"
26
+ const stub = Sinon.stub(MediaSharesUtils, 'extractContentFloor').returns({ beneficiary: {deviceUrl : mockContentBeneficiaryDeviceUrl}});
27
+ const contentBeneficiaryDeviceUrl = MediaSharesUtils.getContentBeneficiaryDeviceUrl();
28
+ assert.equal(contentBeneficiaryDeviceUrl, mockContentBeneficiaryDeviceUrl);
29
+ stub.restore();
30
+ });
31
+ });
32
+