@webex/plugin-meetings 3.0.0-beta.174 → 3.0.0-beta.176

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.
@@ -12,6 +12,7 @@ describe('plugin-meetings', () => {
12
12
  beforeEach(() => {
13
13
  // @ts-ignore
14
14
  webex = new MockWebex({});
15
+ webex.internal.mercury.on = sinon.stub();
15
16
  interpretation = new SimultaneousInterpretation({}, {parent: webex});
16
17
  interpretation.locusUrl = 'locusUrl';
17
18
  webex.request = sinon.stub().returns(Promise.resolve('REQUEST_RETURN_VALUE'));
@@ -50,6 +51,14 @@ describe('plugin-meetings', () => {
50
51
  });
51
52
  });
52
53
 
54
+ describe('#approvalUrlUpdate', () => {
55
+ it('sets the approval url', () => {
56
+ interpretation.approvalUrlUpdate('newUrl');
57
+
58
+ assert.equal(interpretation.approvalUrl, 'newUrl');
59
+ });
60
+ });
61
+
53
62
  describe('#updateCanManageInterpreters', () => {
54
63
  it('update canManageInterpreters', () => {
55
64
  interpretation.updateCanManageInterpreters(true);
@@ -62,6 +71,18 @@ describe('plugin-meetings', () => {
62
71
  });
63
72
  });
64
73
 
74
+ describe('#updateHostSIEnabled', () => {
75
+ it('update hostSI feature is on or off', () => {
76
+ interpretation.updateHostSIEnabled(true);
77
+
78
+ assert.equal(interpretation.hostSIEnabled, true);
79
+
80
+ interpretation.updateHostSIEnabled(false);
81
+
82
+ assert.equal(interpretation.hostSIEnabled, false);
83
+ });
84
+ });
85
+
65
86
  describe('#updateInterpretation', () => {
66
87
  const checkSILanguage = (siLanguage, expectResult) => {
67
88
  return siLanguage?.languageCode === expectResult.languageCode && siLanguage?.languageName === expectResult.languageName
@@ -69,15 +90,6 @@ describe('plugin-meetings', () => {
69
90
  it('update interpretation correctly', () => {
70
91
  interpretation.updateInterpretation({siLanguages: [{languageName: 'en', languageCode: 1}]});
71
92
  checkSILanguage(interpretation.siLanguages.en, {languageName: 'en', languageCode: 1});
72
- assert.equal(interpretation.siEnabled, true);
73
- });
74
-
75
- it('check siEnable as false if input param interpretation is null/undefined', () => {
76
- interpretation.updateInterpretation(null);
77
- assert.equal(interpretation.siEnabled, false);
78
-
79
- interpretation.updateInterpretation(undefined);
80
- assert.equal(interpretation.siEnabled, false);
81
93
  });
82
94
  });
83
95
 
@@ -325,5 +337,234 @@ describe('plugin-meetings', () => {
325
337
  });
326
338
  });
327
339
  });
340
+
341
+ describe('#listenToHandoffRequests', () => {
342
+ it('triggers handoff update event when the approval is related with self', () => {
343
+ const call = webex.internal.mercury.on.getCall(0);
344
+ const callback = call.args[1];
345
+
346
+ assert.equal(call.args[0], 'event:locus.approval_request');
347
+ interpretation.set('selfParticipantId', 'p123');
348
+
349
+ let called = false;
350
+ const triggerSpy = sinon.spy(interpretation, 'trigger');
351
+
352
+ interpretation.listenTo(interpretation, 'HANDOFF_REQUESTS_ARRIVED', () => {
353
+ called = true;
354
+ });
355
+
356
+ callback({
357
+ data: {
358
+ approval: {
359
+ actionType: 'OFFERED',
360
+ resourceType: 'SiHandover',
361
+ receivers: [{
362
+ participantId: 'p123',
363
+ }],
364
+ initiator: {participantId: 'p123'},
365
+ url: 'testUrl',
366
+ },
367
+ }
368
+ });
369
+
370
+ assert.isTrue(called);
371
+ assert.calledWithExactly(triggerSpy, 'HANDOFF_REQUESTS_ARRIVED', {
372
+ actionType: 'OFFERED',
373
+ isReceiver: true,
374
+ isSender: true,
375
+ senderId: 'p123',
376
+ receiverId: 'p123',
377
+ url: 'testUrl',
378
+ });
379
+ });
380
+
381
+ it('not triggers handoff update event when the approval is not related with self', () => {
382
+ const call = webex.internal.mercury.on.getCall(0);
383
+ const callback = call.args[1];
384
+
385
+ interpretation.set('selfParticipantId', 'p123');
386
+
387
+ let called = false;
388
+
389
+ interpretation.listenTo(interpretation, 'HANDOFF_REQUESTS_ARRIVED', () => {
390
+ called = true;
391
+ });
392
+
393
+ callback({
394
+ data: {
395
+ approval: {
396
+ actionType: 'OFFERED',
397
+ resourceType: 'SiHandover',
398
+ receivers: [{
399
+ participantId: 'p444',
400
+ }],
401
+ initiator: {participantId: 'p444'},
402
+ url: 'testUrl',
403
+ },
404
+ }
405
+ });
406
+
407
+ assert.isFalse(called);
408
+ });
409
+ });
410
+
411
+ describe('#handoffInterpreter', () => {
412
+ it('makes the request as expected', async () => {
413
+ interpretation.approvalUrlUpdate('approvalUrl');
414
+ await interpretation.handoffInterpreter('participant2');
415
+ assert.calledOnceWithExactly(webex.request, {
416
+ method: 'POST',
417
+ uri: 'approvalUrl',
418
+ body: {
419
+ actionType: 'OFFERED',
420
+ resourceType: 'SiHandover',
421
+ receivers: [
422
+ {
423
+ participantId: 'participant2',
424
+ },
425
+ ],
426
+ },
427
+ });
428
+ });
429
+
430
+ it('rejects with error', async () => {
431
+ const mockError = new Error('something wrong');
432
+ webex.request.returns(Promise.reject(mockError));
433
+ LoggerProxy.logger.error = sinon.stub();
434
+ interpretation.approvalUrlUpdate('approvalUrl');
435
+
436
+ await assert.isRejected(interpretation.handoffInterpreter('p2'), mockError, 'something wrong');
437
+
438
+ assert.calledOnceWithExactly(
439
+ LoggerProxy.logger.error,
440
+ 'Meeting:interpretation#handoffInterpreter failed',
441
+ mockError
442
+ );
443
+ });
444
+
445
+ it('rejects error when no target participant id', async () => {
446
+ LoggerProxy.logger.error = sinon.stub();
447
+
448
+ await interpretation.handoffInterpreter().catch((error) => {
449
+ assert.equal(error.toString(), 'Error: Missing target participant id');
450
+ });
451
+ });
452
+
453
+ it('rejects error when no approval url', async () => {
454
+ LoggerProxy.logger.error = sinon.stub();
455
+
456
+ await interpretation.handoffInterpreter('p2').catch((error) => {
457
+ assert.equal(error.toString(), 'Error: Missing approval url');
458
+ });
459
+ });
460
+ });
461
+
462
+ describe('#requestHandoff', () => {
463
+ it('makes the request as expected', async () => {
464
+ interpretation.approvalUrlUpdate('approvalUrl');
465
+ await interpretation.requestHandoff();
466
+ assert.calledOnceWithExactly(webex.request, {
467
+ method: 'POST',
468
+ uri: 'approvalUrl',
469
+ body: {
470
+ actionType: 'REQUESTED',
471
+ resourceType: 'SiHandover',
472
+ },
473
+ });
474
+ });
475
+
476
+ it('rejects with error', async () => {
477
+ const mockError = new Error('something wrong');
478
+ webex.request.returns(Promise.reject(mockError));
479
+ LoggerProxy.logger.error = sinon.stub();
480
+ interpretation.approvalUrlUpdate('approvalUrl');
481
+
482
+ await assert.isRejected(interpretation.requestHandoff(), mockError, 'something wrong');
483
+
484
+ assert.calledOnceWithExactly(
485
+ LoggerProxy.logger.error,
486
+ 'Meeting:interpretation#requestHandoff failed',
487
+ mockError
488
+ );
489
+ });
490
+
491
+ it('rejects error when no approval url', async () => {
492
+ LoggerProxy.logger.error = sinon.stub();
493
+
494
+ await interpretation.requestHandoff().catch((error) => {
495
+ assert.equal(error.toString(), 'Error: Missing approval url');
496
+ });
497
+ });
498
+ });
499
+
500
+ describe('#acceptRequest', () => {
501
+ it('makes the request as expected', async () => {
502
+ await interpretation.acceptRequest('testUrl');
503
+ assert.calledOnceWithExactly(webex.request, {
504
+ method: 'PUT',
505
+ uri: 'testUrl',
506
+ body: {
507
+ actionType: 'ACCEPTED',
508
+ },
509
+ });
510
+ });
511
+
512
+ it('rejects with error', async () => {
513
+ const mockError = new Error('something wrong');
514
+ webex.request.returns(Promise.reject(mockError));
515
+ LoggerProxy.logger.error = sinon.stub();
516
+
517
+ await assert.isRejected(interpretation.acceptRequest('testUrl'), mockError, 'something wrong');
518
+
519
+ assert.calledOnceWithExactly(
520
+ LoggerProxy.logger.error,
521
+ 'Meeting:interpretation#acceptRequest failed',
522
+ mockError
523
+ );
524
+ });
525
+
526
+ it('rejects error when no url passed', async () => {
527
+ LoggerProxy.logger.error = sinon.stub();
528
+
529
+ await interpretation.acceptRequest().catch((error) => {
530
+ assert.equal(error.toString(), 'Error: Missing the url to accept');
531
+ });
532
+ });
533
+ });
534
+
535
+ describe('#declineRequest', () => {
536
+ it('makes the request as expected', async () => {
537
+ await interpretation.declineRequest('testUrl');
538
+ assert.calledOnceWithExactly(webex.request, {
539
+ method: 'PUT',
540
+ uri: 'testUrl',
541
+ body: {
542
+ actionType: 'DECLINED',
543
+ },
544
+ });
545
+ });
546
+
547
+ it('rejects with error', async () => {
548
+ const mockError = new Error('something wrong');
549
+ webex.request.returns(Promise.reject(mockError));
550
+ LoggerProxy.logger.error = sinon.stub();
551
+
552
+ await assert.isRejected(interpretation.declineRequest('testUrl'), mockError, 'something wrong');
553
+
554
+ assert.calledOnceWithExactly(
555
+ LoggerProxy.logger.error,
556
+ 'Meeting:interpretation#declineRequest failed',
557
+ mockError
558
+ );
559
+ });
560
+
561
+ it('rejects error when no url passed', async () => {
562
+ LoggerProxy.logger.error = sinon.stub();
563
+
564
+ await interpretation.declineRequest().catch((error) => {
565
+ assert.equal(error.toString(), 'Error: Missing the url to decline');
566
+ });
567
+ });
568
+ });
328
569
  });
329
570
  });
@@ -2,6 +2,7 @@ import {assert} from '@webex/test-helper-chai';
2
2
  import SILanguage from '@webex/plugin-meetings/src/interpretation/siLanguage';
3
3
  import SimultaneousInterpretation from '@webex/plugin-meetings/src/interpretation';
4
4
  import MockWebex from '@webex/test-helper-mock-webex';
5
+ import sinon from 'sinon';
5
6
 
6
7
  describe('plugin-meetings', () => {
7
8
  describe('SILanguage', () => {
@@ -11,6 +12,7 @@ describe('plugin-meetings', () => {
11
12
  beforeEach(() => {
12
13
  // @ts-ignore
13
14
  webex = new MockWebex({});
15
+ webex.internal.mercury.on = sinon.stub();
14
16
  interpretation = new SimultaneousInterpretation({}, {parent: webex});
15
17
  siLanguage = new SILanguage({}, {parent: interpretation});
16
18
  });
@@ -1335,7 +1335,7 @@ describe('plugin-meetings', () => {
1335
1335
  icePhase: 'JOIN_MEETING_FINAL',
1336
1336
  errors: [{}],
1337
1337
  },
1338
- options: {
1338
+ options: {
1339
1339
  meetingId: meeting.id,
1340
1340
  },
1341
1341
  });
@@ -3831,7 +3831,7 @@ describe('plugin-meetings', () => {
3831
3831
  assert.equal(meeting.mediaProperties.shareVideoTrack, track);
3832
3832
  assert.equal(meeting.mediaProperties.mediaDirection.sendShare, true);
3833
3833
  };
3834
-
3834
+
3835
3835
  const checkScreenShareAudioPublished = (track) => {
3836
3836
  assert.calledOnce(meeting.requestScreenShareFloor);
3837
3837
 
@@ -3849,27 +3849,27 @@ describe('plugin-meetings', () => {
3849
3849
  assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.publishTrack);
3850
3850
  checkScreenShareVideoPublished(videoShareTrack);
3851
3851
  });
3852
-
3852
+
3853
3853
  it('requests screen share floor and publishes the screen share audio track', async () => {
3854
3854
  await meeting.publishTracks({screenShare: {audio: audioShareTrack}});
3855
-
3855
+
3856
3856
  assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.publishTrack);
3857
3857
  checkScreenShareAudioPublished(audioShareTrack);
3858
3858
  });
3859
-
3859
+
3860
3860
  it('does not request screen share floor when publishing video share track if already sharing audio', async () => {
3861
3861
  await meeting.publishTracks({screenShare: {audio: audioShareTrack}});
3862
3862
  assert.calledOnce(meeting.requestScreenShareFloor);
3863
-
3863
+
3864
3864
  meeting.requestScreenShareFloor.reset();
3865
3865
  await meeting.publishTracks({screenShare: {video: videoShareTrack}});
3866
3866
  assert.notCalled(meeting.requestScreenShareFloor);
3867
3867
  })
3868
-
3868
+
3869
3869
  it('does not request screen share floor when publishing audio share track if already sharing video', async () => {
3870
3870
  await meeting.publishTracks({screenShare: {video: videoShareTrack}});
3871
3871
  assert.calledOnce(meeting.requestScreenShareFloor);
3872
-
3872
+
3873
3873
  meeting.requestScreenShareFloor.reset();
3874
3874
  await meeting.publishTracks({screenShare: {audio: audioShareTrack}});
3875
3875
  assert.notCalled(meeting.requestScreenShareFloor);
@@ -4007,26 +4007,26 @@ describe('plugin-meetings', () => {
4007
4007
  assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack);
4008
4008
  checkScreenShareVideoUnpublished();
4009
4009
  });
4010
-
4010
+
4011
4011
  it('un-publishes the screen share audio track correctly', async () => {
4012
4012
  await meeting.unpublishTracks([audioShareTrack]);
4013
-
4013
+
4014
4014
  assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack);
4015
4015
  checkScreenShareAudioUnpublished();
4016
4016
  });
4017
-
4017
+
4018
4018
  it('releases share floor and sets send direction to false when both screen share tracks are undefined', async () => {
4019
4019
  await meeting.unpublishTracks([videoShareTrack, audioShareTrack]);
4020
-
4020
+
4021
4021
  assert.calledOnce(meeting.releaseScreenShareFloor);
4022
4022
  assert.equal(meeting.mediaProperties.mediaDirection.sendShare, false);
4023
4023
  });
4024
-
4024
+
4025
4025
  it('does not release share floor when audio is released and video still exists', async () => {
4026
4026
  await meeting.unpublishTracks([audioShareTrack]);
4027
4027
  assert.notCalled(meeting.releaseScreenShareFloor);
4028
4028
  });
4029
-
4029
+
4030
4030
  it('does not release share floor when video is released and audio still exists', async () => {
4031
4031
  await meeting.unpublishTracks([videoShareTrack]);
4032
4032
  assert.notCalled(meeting.releaseScreenShareFloor);
@@ -4287,7 +4287,7 @@ describe('plugin-meetings', () => {
4287
4287
  icePhase: 'IN_MEETING',
4288
4288
  errors: [{}],
4289
4289
  },
4290
- options: {
4290
+ options: {
4291
4291
  meetingId: meeting.id,
4292
4292
  },
4293
4293
  });
@@ -5108,6 +5108,9 @@ describe('plugin-meetings', () => {
5108
5108
  meeting.annotation = {
5109
5109
  approvalUrlUpdate: sinon.stub().returns(undefined),
5110
5110
  };
5111
+ meeting.simultaneousInterpretation = {
5112
+ approvalUrlUpdate: sinon.stub().returns(undefined),
5113
+ };
5111
5114
 
5112
5115
  meeting.locusInfo.emit(
5113
5116
  {function: 'test', file: 'test'},
@@ -5123,6 +5126,10 @@ describe('plugin-meetings', () => {
5123
5126
  meeting.annotation.approvalUrlUpdate,
5124
5127
  newLocusServices.services.approval.url,
5125
5128
  );
5129
+ assert.calledWith(
5130
+ meeting.simultaneousInterpretation.approvalUrlUpdate,
5131
+ newLocusServices.services.approval.url,
5132
+ );
5126
5133
  assert.calledOnce(meeting.recordingController.setSessionId);
5127
5134
  done();
5128
5135
  });
@@ -5226,6 +5233,20 @@ describe('plugin-meetings', () => {
5226
5233
  EVENT_TRIGGERS.MEETING_INTERPRETATION_SUPPORT_LANGUAGES_UPDATE
5227
5234
  );
5228
5235
  });
5236
+
5237
+ it('listens to the handoff request event from interpretation and triggers the update event', () => {
5238
+ TriggerProxy.trigger.reset();
5239
+ const payload = {};
5240
+ meeting.simultaneousInterpretation.trigger('HANDOFF_REQUESTS_ARRIVED', payload);
5241
+
5242
+ assert.calledWith(
5243
+ TriggerProxy.trigger,
5244
+ meeting,
5245
+ {file: 'meeting/index', function: 'setUpInterpretationListener'},
5246
+ EVENT_TRIGGERS.MEETING_INTERPRETATION_HANDOFF_REQUESTS_ARRIVED,
5247
+ payload
5248
+ );
5249
+ });
5229
5250
  });
5230
5251
  });
5231
5252
  describe('Private Detailed API and Helpers', () => {
@@ -5508,6 +5529,26 @@ describe('plugin-meetings', () => {
5508
5529
 
5509
5530
  checkParseMeetingInfo(expectedInfoToParse);
5510
5531
  });
5532
+ it('should set hostSIEnabled correctly depend on the toggle statue in site setting', () => {
5533
+ const updateHostSIEnabledSpy = sinon.spy(meeting.simultaneousInterpretation, 'updateHostSIEnabled');
5534
+ const mockToggleOnData = {
5535
+ body: {
5536
+ meetingSiteSetting: {
5537
+ enableHostInterpreterControlSI: true,
5538
+ }
5539
+ }
5540
+ };
5541
+ meeting.parseMeetingInfo(mockToggleOnData);
5542
+ assert.calledWith(updateHostSIEnabledSpy, true);
5543
+
5544
+ const mockToggleOffData = {
5545
+ body: {
5546
+ meetingSiteSetting: {}
5547
+ }
5548
+ };
5549
+ meeting.parseMeetingInfo(mockToggleOffData);
5550
+ assert.calledWith(updateHostSIEnabledSpy, false);
5551
+ });
5511
5552
  });
5512
5553
 
5513
5554
  describe('#setCorrelationId', () => {
@@ -6178,7 +6219,7 @@ describe('plugin-meetings', () => {
6178
6219
  eventTrigger.share.push({
6179
6220
  eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
6180
6221
  functionName: 'remoteShare',
6181
- eventPayload: {memberId: beneficiaryId, url, shareInstanceId},
6222
+ eventPayload: {memberId: beneficiaryId, url, shareInstanceId , annotationInfo:undefined},
6182
6223
  });
6183
6224
  }
6184
6225
  }