@webex/plugin-meetings 2.14.0 → 2.14.3

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.
@@ -42,6 +42,7 @@ import {
42
42
  } from '@webex/plugin-meetings/src/constants';
43
43
  import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
44
44
 
45
+ import locus from '../fixture/locus';
45
46
  import {
46
47
  UserNotJoinedError,
47
48
  MeetingNotActiveError,
@@ -724,16 +725,12 @@ describe('plugin-meetings', () => {
724
725
  });
725
726
  describe('#isTranscriptionSupported', () => {
726
727
  it('should return false if the feature is not supported for the meeting', () => {
727
- meeting.policy = {
728
- WEBEX_ASSISTANT_STATUS_INACTIVE: true
729
- };
728
+ meeting.locusInfo.controls = {transcribe: {transcribing: false}};
730
729
 
731
730
  assert.equal(meeting.isTranscriptionSupported(), false);
732
731
  });
733
732
  it('should return true if webex assitant is enabled', () => {
734
- meeting.policy = {
735
- WEBEX_ASSISTANT_STATUS_ACTIVE: true
736
- };
733
+ meeting.locusInfo.controls = {transcribe: {transcribing: true}};
737
734
 
738
735
  assert.equal(meeting.isTranscriptionSupported(), true);
739
736
  });
@@ -1332,7 +1329,7 @@ describe('plugin-meetings', () => {
1332
1329
 
1333
1330
  sandbox.stub(meeting.mediaProperties, 'peerConnection').value({shareTransceiver: true});
1334
1331
  sandbox.stub(MeetingUtil, 'getTrack').returns({videoTrack: true});
1335
- sandbox.stub(MeetingUtil, 'validateOptions').resolves(true);
1332
+ MeetingUtil.validateOptions = sinon.stub().returns(Promise.resolve(true));
1336
1333
  sandbox.stub(meeting, 'canUpdateMedia').returns(true);
1337
1334
  sandbox.stub(meeting, 'setLocalShareTrack');
1338
1335
 
@@ -1401,13 +1398,14 @@ describe('plugin-meetings', () => {
1401
1398
  const SENDRECV = 'sendrecv';
1402
1399
  const delay = 1e3;
1403
1400
 
1401
+ MeetingUtil.validateOptions = sinon.stub().returns(Promise.resolve(true));
1402
+ MeetingUtil.updateTransceiver = sinon.stub().returns(Promise.resolve(true));
1404
1403
  sandbox.stub(meeting, 'canUpdateMedia').returns(true);
1405
1404
  sandbox.stub(MeetingUtil, 'getTrack').returns({videoTrack: null});
1406
1405
  sandbox.stub(meeting, 'setLocalShareTrack');
1407
1406
  sandbox.stub(meeting, 'unsetLocalShareTrack');
1408
- sandbox.stub(MeetingUtil, 'validateOptions').resolves(true);
1409
1407
  sandbox.stub(meeting, 'checkForStopShare').returns(false);
1410
- sandbox.stub(MeetingUtil, 'updateTransceiver').resolves(true);
1408
+
1411
1409
  sandbox.stub(meeting, 'isLocalShareLive').value(false);
1412
1410
  sandbox.stub(meeting, 'handleShareTrackEnded');
1413
1411
  sandbox.stub(meeting.mediaProperties, 'peerConnection').value({
@@ -2278,11 +2276,6 @@ describe('plugin-meetings', () => {
2278
2276
  assert.equal(meeting.requiredCaptcha, null);
2279
2277
  assert.calledTwice(TriggerProxy.trigger);
2280
2278
  assert.calledWith(TriggerProxy.trigger, meeting, {file: 'meetings', function: 'fetchMeetingInfo'}, 'meeting:meetingInfoAvailable');
2281
- assert(Metrics.sendBehavioralMetric.calledOnce);
2282
- assert.calledWith(
2283
- Metrics.sendBehavioralMetric,
2284
- BEHAVIORAL_METRICS.VERIFY_PASSWORD_SUCCESS,
2285
- );
2286
2279
  });
2287
2280
 
2288
2281
  it('calls meetingInfoProvider with all the right parameters and parses the result when random delay is applied', async () => {
@@ -2354,11 +2347,6 @@ describe('plugin-meetings', () => {
2354
2347
 
2355
2348
  assert.calledWith(meeting.attrs.meetingInfoProvider.fetchMeetingInfo, FAKE_DESTINATION, FAKE_TYPE, null, null);
2356
2349
 
2357
- assert(Metrics.sendBehavioralMetric.calledOnce);
2358
- assert.calledWith(
2359
- Metrics.sendBehavioralMetric,
2360
- BEHAVIORAL_METRICS.VERIFY_PASSWORD_ERROR,
2361
- );
2362
2350
  assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
2363
2351
  assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD);
2364
2352
  assert.equal(meeting.requiredCaptcha, null);
@@ -2379,11 +2367,7 @@ describe('plugin-meetings', () => {
2379
2367
 
2380
2368
  assert.calledWith(meeting.attrs.meetingInfoProvider.fetchMeetingInfo, FAKE_DESTINATION, FAKE_TYPE, 'aaa', null);
2381
2369
 
2382
- assert(Metrics.sendBehavioralMetric.calledOnce);
2383
- assert.calledWith(
2384
- Metrics.sendBehavioralMetric,
2385
- BEHAVIORAL_METRICS.VERIFY_CAPTCHA_ERROR,
2386
- );
2370
+
2387
2371
  assert.deepEqual(meeting.meetingInfo, {});
2388
2372
  assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD);
2389
2373
  assert.equal(meeting.passwordStatus, PASSWORD_STATUS.REQUIRED);
@@ -2537,6 +2521,11 @@ describe('plugin-meetings', () => {
2537
2521
  meeting.fetchMeetingInfo = sinon.stub().resolves();
2538
2522
  const result = await meeting.verifyPassword('password', 'captcha id');
2539
2523
 
2524
+ assert(Metrics.sendBehavioralMetric.calledOnce);
2525
+ assert.calledWith(
2526
+ Metrics.sendBehavioralMetric,
2527
+ BEHAVIORAL_METRICS.VERIFY_PASSWORD_SUCCESS,
2528
+ );
2540
2529
  assert.equal(result.isPasswordValid, true);
2541
2530
  assert.equal(result.requiredCaptcha, null);
2542
2531
  assert.equal(result.failureReason, MEETING_INFO_FAILURE_REASON.NONE);
@@ -2573,6 +2562,7 @@ describe('plugin-meetings', () => {
2573
2562
  assert.equal(result.failureReason, MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA);
2574
2563
  });
2575
2564
  });
2565
+
2576
2566
  describe('#mediaNegotiatedEvent', () => {
2577
2567
  it('should have #mediaNegotiatedEvent', () => {
2578
2568
  assert.exists(meeting.mediaNegotiatedEvent);
@@ -2650,6 +2640,222 @@ describe('plugin-meetings', () => {
2650
2640
  assert.calledOnce(meeting?.roap?.stop);
2651
2641
  });
2652
2642
  });
2643
+
2644
+ describe('#moveTo', () => {
2645
+ let sandbox;
2646
+
2647
+ beforeEach(() => {
2648
+ sandbox = sinon.createSandbox();
2649
+ sandbox.stub(meeting, 'closeLocalStream');
2650
+ sandbox.stub(meeting, 'closeLocalShare');
2651
+
2652
+ sandbox.stub(meeting.mediaProperties, 'setMediaDirection');
2653
+ sandbox.stub(meeting.mediaProperties, 'unsetMediaTracks');
2654
+
2655
+ sandbox.stub(meeting.reconnectionManager, 'reconnectMedia').returns(Promise.resolve());
2656
+ sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve(MeetingUtil.parseLocusJoin({body: {locus, mediaConnections: []}})));
2657
+ });
2658
+
2659
+ afterEach(() => {
2660
+ sandbox.restore();
2661
+ sandbox = null;
2662
+ });
2663
+
2664
+ it('should throw an error if resourceId not passed', async () => {
2665
+ try {
2666
+ await meeting.moveTo();
2667
+ }
2668
+ catch (err) {
2669
+ assert.instanceOf(err, ParameterError);
2670
+ assert.equal(err.sdkMessage, 'Cannot move call without a resourceId.');
2671
+ }
2672
+ });
2673
+
2674
+ it('should postEvent on moveTo ', async () => {
2675
+ await meeting.moveTo('resourceId');
2676
+ assert.calledWithMatch(Metrics.postEvent, {
2677
+ event: eventType.MEDIA_CAPABILITIES,
2678
+ data: {
2679
+ mediaCapabilities: {
2680
+ rx: {
2681
+ audio: false,
2682
+ share: true,
2683
+ share_audio: false,
2684
+ video: false,
2685
+ whiteboard: false
2686
+ },
2687
+ tx: {
2688
+ audio: false,
2689
+ share: false,
2690
+ share_audio: false,
2691
+ video: false,
2692
+ whiteboard: false
2693
+ }
2694
+ }
2695
+ }
2696
+ });
2697
+ assert.calledWithMatch(Metrics.postEvent, {event: eventType.MOVE_MEDIA});
2698
+ });
2699
+
2700
+ it('should call `MeetingUtil.joinMeetingOptions` with resourceId', async () => {
2701
+ sinon.spy(MeetingUtil, 'joinMeetingOptions');
2702
+ await meeting.moveTo('resourceId');
2703
+
2704
+ assert.calledWith(MeetingUtil.joinMeetingOptions, meeting, {resourceId: 'resourceId', moveToResource: true});
2705
+ });
2706
+
2707
+ it('should reconnectMedia after DX joins after moveTo', async () => {
2708
+ await meeting.moveTo('resourceId');
2709
+
2710
+
2711
+ await meeting.locusInfo.emitScoped(
2712
+ {
2713
+ file: 'locus-info',
2714
+ function: 'updateSelf'
2715
+ },
2716
+ 'SELF_OBSERVING'
2717
+ );
2718
+
2719
+ // beacuse we are calling callback so we need to wait
2720
+
2721
+ assert.called(meeting.closeLocalStream);
2722
+ assert.called(meeting.closeLocalShare);
2723
+
2724
+ // give queued Promise callbacks a chance to run
2725
+ await Promise.resolve();
2726
+
2727
+ assert.called(meeting.mediaProperties.setMediaDirection);
2728
+ assert.called(meeting.mediaProperties.unsetMediaTracks);
2729
+
2730
+ assert.calledWith(meeting.reconnectionManager.reconnectMedia,
2731
+ {
2732
+ mediaDirection: {
2733
+ sendVideo: false,
2734
+ receiveVideo: false,
2735
+ sendAudio: false,
2736
+ receiveAudio: false,
2737
+ sendShare: false,
2738
+ receiveShare: true
2739
+ }
2740
+ });
2741
+ });
2742
+
2743
+ it('should throw an error if moveTo call fails', async () => {
2744
+ MeetingUtil.joinMeeting = sinon.stub().returns(Promise.reject());
2745
+ try {
2746
+ await meeting.moveTo('resourceId');
2747
+ }
2748
+ catch {
2749
+ assert.calledOnce(Metrics.sendBehavioralMetric);
2750
+ assert.calledWith(
2751
+ Metrics.sendBehavioralMetric,
2752
+ BEHAVIORAL_METRICS.MOVE_TO_FAILURE,
2753
+ {
2754
+ correlation_id: meeting.correlationId,
2755
+ locus_id: meeting.locusUrl.split('/').pop(),
2756
+ reason: sinon.match.any,
2757
+ stack: sinon.match.any
2758
+ }
2759
+ );
2760
+ }
2761
+ Metrics.sendBehavioralMetric.reset();
2762
+ meeting.reconnectionManager.reconnectMedia = sinon.stub().returns(Promise.reject());
2763
+ try {
2764
+ await meeting.moveTo('resourceId');
2765
+
2766
+ await meeting.locusInfo.emitScoped(
2767
+ {
2768
+ file: 'locus-info',
2769
+ function: 'updateSelf'
2770
+ },
2771
+ 'SELF_OBSERVING'
2772
+ );
2773
+ }
2774
+ catch {
2775
+ assert.calledOnce(Metrics.sendBehavioralMetric);
2776
+ assert.calledWith(
2777
+ Metrics.sendBehavioralMetric,
2778
+ BEHAVIORAL_METRICS.MOVE_TO_FAILURE,
2779
+ {
2780
+ correlation_id: meeting.correlationId,
2781
+ locus_id: meeting.locusUrl.split('/').pop(),
2782
+ reason: sinon.match.any,
2783
+ stack: sinon.match.any
2784
+ }
2785
+ );
2786
+ }
2787
+ });
2788
+ });
2789
+
2790
+ describe('#moveFrom', () => {
2791
+ let sandbox;
2792
+
2793
+ beforeEach(() => {
2794
+ sandbox = sinon.createSandbox();
2795
+ sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve(MeetingUtil.parseLocusJoin({body: {locus, mediaConnections: []}})));
2796
+ sandbox.stub(MeetingUtil, 'leaveMeeting').returns(Promise.resolve());
2797
+ });
2798
+
2799
+ afterEach(() => {
2800
+ sandbox.restore();
2801
+ sandbox = null;
2802
+ });
2803
+
2804
+ it('should throw an error if resourceId not passed', async () => {
2805
+ try {
2806
+ await meeting.moveFrom();
2807
+ }
2808
+ catch (err) {
2809
+ assert.instanceOf(err, ParameterError);
2810
+
2811
+ assert.equal(err.sdkMessage, 'Cannot move call without a resourceId.');
2812
+ }
2813
+ });
2814
+
2815
+ it('should postEvent on moveFrom ', async () => {
2816
+ await meeting.moveFrom('resourceId');
2817
+
2818
+ assert.calledWithMatch(Metrics.postEvent, {event: eventType.MOVE_MEDIA});
2819
+ });
2820
+
2821
+ it('should call `MeetingUtil.joinMeetingOptions` with resourceId', async () => {
2822
+ sinon.spy(MeetingUtil, 'joinMeetingOptions');
2823
+ await meeting.moveFrom('resourceId');
2824
+
2825
+ assert.calledWith(MeetingUtil.joinMeetingOptions, meeting);
2826
+ assert.calledWith(MeetingUtil.leaveMeeting, meeting, {
2827
+ resourceId: 'resourceId',
2828
+ correlationId: meeting.correlationId,
2829
+ moveMeeting: true
2830
+ });
2831
+
2832
+ assert.calledOnce(Metrics.sendBehavioralMetric);
2833
+ assert.calledWith(
2834
+ Metrics.sendBehavioralMetric,
2835
+ BEHAVIORAL_METRICS.MOVE_FROM_SUCCESS,
2836
+ );
2837
+ });
2838
+
2839
+ it('should throw an error if moveFrom call fails', async () => {
2840
+ MeetingUtil.joinMeeting = sinon.stub().returns(Promise.reject());
2841
+ try {
2842
+ await meeting.moveFrom('resourceId');
2843
+ }
2844
+ catch {
2845
+ assert.calledOnce(Metrics.sendBehavioralMetric);
2846
+ assert.calledWith(
2847
+ Metrics.sendBehavioralMetric,
2848
+ BEHAVIORAL_METRICS.MOVE_FROM_FAILURE,
2849
+ {
2850
+ correlation_id: meeting.correlationId,
2851
+ locus_id: meeting.locusUrl.split('/').pop(),
2852
+ reason: sinon.match.any,
2853
+ stack: sinon.match.any
2854
+ }
2855
+ );
2856
+ }
2857
+ });
2858
+ });
2653
2859
  });
2654
2860
 
2655
2861
  describe('Public Event Triggers', () => {
@@ -177,16 +177,17 @@ describe('plugin-meetings', () => {
177
177
  meetingInfo.createAdhocSpaceMeeting.restore();
178
178
  });
179
179
 
180
+
180
181
  it('should throw an error MeetingInfoV2AdhocMeetingError if not able to start adhoc meeting for a conversation', async () => {
181
182
  webex.config.meetings.experimental.enableAdhocMeetings = true;
182
183
 
183
- webex.request = sinon.stub().rejects({statusCode: 403, body: {code: 400000, message: 'Input is invalid'}});
184
+ webex.request = sinon.stub().rejects({statusCode: 403, body: {code: 400000}});
184
185
  try {
185
186
  await meetingInfo.createAdhocSpaceMeeting('conversationUrl');
186
187
  }
187
188
  catch (err) {
188
189
  assert.instanceOf(err, MeetingInfoV2AdhocMeetingError);
189
- assert.deepEqual(err.message, 'Input is invalid, code=400000');
190
+ assert.deepEqual(err.message, 'Failed starting the adhoc meeting, Please contact support team , code=400000');
190
191
  assert.equal(err.wbxAppApiCode, 400000);
191
192
  }
192
193
  });
@@ -201,6 +202,11 @@ describe('plugin-meetings', () => {
201
202
  assert.fail('fetchMeetingInfo should have thrown, but has not done that');
202
203
  }
203
204
  catch (err) {
205
+ assert(Metrics.sendBehavioralMetric.calledOnce);
206
+ assert.calledWith(
207
+ Metrics.sendBehavioralMetric,
208
+ BEHAVIORAL_METRICS.VERIFY_PASSWORD_ERROR,
209
+ );
204
210
  assert.instanceOf(err, MeetingInfoV2PasswordError);
205
211
  assert.deepEqual(err.meetingInfo, FAKE_MEETING_INFO);
206
212
  assert.equal(err.wbxAppApiCode, 403000);
@@ -226,6 +232,11 @@ describe('plugin-meetings', () => {
226
232
  assert.fail('fetchMeetingInfo should have thrown, but has not done that');
227
233
  }
228
234
  catch (err) {
235
+ assert(Metrics.sendBehavioralMetric.calledOnce);
236
+ assert.calledWith(
237
+ Metrics.sendBehavioralMetric,
238
+ BEHAVIORAL_METRICS.VERIFY_CAPTCHA_ERROR,
239
+ );
229
240
  assert.instanceOf(err, MeetingInfoV2CaptchaError);
230
241
  assert.deepEqual(err.captchaInfo, {
231
242
  captchaId: 'fake_captcha_id',