@webex/plugin-meetings 3.8.0-next.34 → 3.8.0-next.35

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.
@@ -450,6 +450,12 @@ export default class Meeting extends StatelessWebexPlugin {
450
450
  allowMediaInLobby: boolean;
451
451
  localShareInstanceId: string;
452
452
  remoteShareInstanceId: string;
453
+ shareCAEventSentStatus: {
454
+ transmitStart: boolean;
455
+ transmitStop: boolean;
456
+ receiveStart: boolean;
457
+ receiveStop: boolean;
458
+ };
453
459
  turnDiscoverySkippedReason: TurnDiscoverySkipReason;
454
460
  turnServerUsed: boolean;
455
461
  areVoiceaEventsSetup: boolean;
@@ -458,7 +458,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
458
458
  }, _callee7);
459
459
  }))();
460
460
  },
461
- version: "3.8.0-next.34"
461
+ version: "3.8.0-next.35"
462
462
  });
463
463
  var _default = exports.default = Webinar;
464
464
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -43,7 +43,7 @@
43
43
  "@webex/eslint-config-legacy": "0.0.0",
44
44
  "@webex/jest-config-legacy": "0.0.0",
45
45
  "@webex/legacy-tools": "0.0.0",
46
- "@webex/plugin-meetings": "3.8.0-next.34",
46
+ "@webex/plugin-meetings": "3.8.0-next.35",
47
47
  "@webex/plugin-rooms": "3.8.0-next.13",
48
48
  "@webex/test-helper-chai": "3.8.0-next.11",
49
49
  "@webex/test-helper-mocha": "3.8.0-next.11",
@@ -71,7 +71,7 @@
71
71
  "@webex/internal-plugin-metrics": "3.8.0-next.11",
72
72
  "@webex/internal-plugin-support": "3.8.0-next.13",
73
73
  "@webex/internal-plugin-user": "3.8.0-next.11",
74
- "@webex/internal-plugin-voicea": "3.8.0-next.34",
74
+ "@webex/internal-plugin-voicea": "3.8.0-next.35",
75
75
  "@webex/media-helpers": "3.8.0-next.12",
76
76
  "@webex/plugin-people": "3.8.0-next.13",
77
77
  "@webex/plugin-rooms": "3.8.0-next.13",
@@ -92,5 +92,5 @@
92
92
  "//": [
93
93
  "TODO: upgrade jwt-decode when moving to node 18"
94
94
  ],
95
- "version": "3.8.0-next.34"
95
+ "version": "3.8.0-next.35"
96
96
  }
@@ -647,6 +647,13 @@ export default class Meeting extends StatelessWebexPlugin {
647
647
  allowMediaInLobby: boolean;
648
648
  localShareInstanceId: string;
649
649
  remoteShareInstanceId: string;
650
+ shareCAEventSentStatus: {
651
+ transmitStart: boolean;
652
+ transmitStop: boolean;
653
+ receiveStart: boolean;
654
+ receiveStop: boolean;
655
+ };
656
+
650
657
  turnDiscoverySkippedReason: TurnDiscoverySkipReason;
651
658
  turnServerUsed: boolean;
652
659
  areVoiceaEventsSetup = false;
@@ -1419,6 +1426,19 @@ export default class Meeting extends StatelessWebexPlugin {
1419
1426
  */
1420
1427
  this.remoteShareInstanceId = null;
1421
1428
 
1429
+ /**
1430
+ * Status used for ensuring we do not oversend metrics
1431
+ * @instance
1432
+ * @private
1433
+ * @memberof Meeting
1434
+ */
1435
+ this.shareCAEventSentStatus = {
1436
+ transmitStart: false,
1437
+ transmitStop: false,
1438
+ receiveStart: false,
1439
+ receiveStop: false,
1440
+ };
1441
+
1422
1442
  /**
1423
1443
  * The class that helps to control recording functions: start, stop, pause, resume, etc
1424
1444
  * @instance
@@ -3023,6 +3043,8 @@ export default class Meeting extends StatelessWebexPlugin {
3023
3043
  case SHARE_STATUS.REMOTE_SHARE_ACTIVE: {
3024
3044
  const sendStartedSharingRemote = () => {
3025
3045
  this.remoteShareInstanceId = contentShare.shareInstanceId;
3046
+ this.shareCAEventSentStatus.receiveStart = false;
3047
+ this.shareCAEventSentStatus.receiveStop = false;
3026
3048
 
3027
3049
  Trigger.trigger(
3028
3050
  this,
@@ -3076,6 +3098,7 @@ export default class Meeting extends StatelessWebexPlugin {
3076
3098
  },
3077
3099
  options: {meetingId: this.id},
3078
3100
  });
3101
+
3079
3102
  break;
3080
3103
 
3081
3104
  case SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE:
@@ -3116,6 +3139,8 @@ export default class Meeting extends StatelessWebexPlugin {
3116
3139
  // if we got here, then some remote participant has stolen
3117
3140
  // the presentation from another remote participant
3118
3141
  this.remoteShareInstanceId = contentShare.shareInstanceId;
3142
+ this.shareCAEventSentStatus.receiveStart = false;
3143
+ this.shareCAEventSentStatus.receiveStop = false;
3119
3144
 
3120
3145
  Trigger.trigger(
3121
3146
  this,
@@ -6771,30 +6796,42 @@ export default class Meeting extends StatelessWebexPlugin {
6771
6796
  EVENT_TRIGGERS.MEETING_MEDIA_LOCAL_STARTED,
6772
6797
  data
6773
6798
  );
6774
- // @ts-ignore
6775
- this.webex.internal.newMetrics.submitClientEvent({
6776
- name: 'client.media.tx.start',
6777
- payload: {
6778
- mediaType: data.mediaType,
6779
- shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
6780
- },
6781
- options: {
6782
- meetingId: this.id,
6783
- },
6784
- });
6799
+ if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.transmitStart) {
6800
+ // @ts-ignore
6801
+ this.webex.internal.newMetrics.submitClientEvent({
6802
+ name: 'client.media.tx.start',
6803
+ payload: {
6804
+ mediaType: data.mediaType,
6805
+ shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
6806
+ },
6807
+ options: {
6808
+ meetingId: this.id,
6809
+ },
6810
+ });
6811
+
6812
+ if (data.mediaType === 'share') {
6813
+ this.shareCAEventSentStatus.transmitStart = true;
6814
+ }
6815
+ }
6785
6816
  });
6786
6817
  this.statsAnalyzer.on(StatsAnalyzerEventNames.LOCAL_MEDIA_STOPPED, (data) => {
6787
- // @ts-ignore
6788
- this.webex.internal.newMetrics.submitClientEvent({
6789
- name: 'client.media.tx.stop',
6790
- payload: {
6791
- mediaType: data.mediaType,
6792
- shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
6793
- },
6794
- options: {
6795
- meetingId: this.id,
6796
- },
6797
- });
6818
+ if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.transmitStop) {
6819
+ // @ts-ignore
6820
+ this.webex.internal.newMetrics.submitClientEvent({
6821
+ name: 'client.media.tx.stop',
6822
+ payload: {
6823
+ mediaType: data.mediaType,
6824
+ shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
6825
+ },
6826
+ options: {
6827
+ meetingId: this.id,
6828
+ },
6829
+ });
6830
+
6831
+ if (data.mediaType === 'share') {
6832
+ this.shareCAEventSentStatus.transmitStop = true;
6833
+ }
6834
+ }
6798
6835
  });
6799
6836
  this.statsAnalyzer.on(StatsAnalyzerEventNames.REMOTE_MEDIA_STARTED, (data) => {
6800
6837
  Trigger.trigger(
@@ -6806,57 +6843,65 @@ export default class Meeting extends StatelessWebexPlugin {
6806
6843
  EVENT_TRIGGERS.MEETING_MEDIA_REMOTE_STARTED,
6807
6844
  data
6808
6845
  );
6809
- // @ts-ignore
6810
- this.webex.internal.newMetrics.submitClientEvent({
6811
- name: 'client.media.rx.start',
6812
- payload: {
6813
- mediaType: data.mediaType,
6814
- shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
6815
- },
6816
- options: {
6817
- meetingId: this.id,
6818
- },
6819
- });
6820
-
6821
- if (data.mediaType === 'share') {
6846
+ if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.receiveStart) {
6822
6847
  // @ts-ignore
6823
6848
  this.webex.internal.newMetrics.submitClientEvent({
6824
- name: 'client.media.render.start',
6849
+ name: 'client.media.rx.start',
6825
6850
  payload: {
6826
- mediaType: 'share',
6827
- shareInstanceId: this.remoteShareInstanceId,
6851
+ mediaType: data.mediaType,
6852
+ shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
6828
6853
  },
6829
6854
  options: {
6830
6855
  meetingId: this.id,
6831
6856
  },
6832
6857
  });
6858
+
6859
+ if (data.mediaType === 'share') {
6860
+ // @ts-ignore
6861
+ this.webex.internal.newMetrics.submitClientEvent({
6862
+ name: 'client.media.render.start',
6863
+ payload: {
6864
+ mediaType: 'share',
6865
+ shareInstanceId: this.remoteShareInstanceId,
6866
+ },
6867
+ options: {
6868
+ meetingId: this.id,
6869
+ },
6870
+ });
6871
+
6872
+ this.shareCAEventSentStatus.receiveStart = true;
6873
+ }
6833
6874
  }
6834
6875
  });
6835
6876
  this.statsAnalyzer.on(StatsAnalyzerEventNames.REMOTE_MEDIA_STOPPED, (data) => {
6836
- // @ts-ignore
6837
- this.webex.internal.newMetrics.submitClientEvent({
6838
- name: 'client.media.rx.stop',
6839
- payload: {
6840
- mediaType: data.mediaType,
6841
- shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
6842
- },
6843
- options: {
6844
- meetingId: this.id,
6845
- },
6846
- });
6847
-
6848
- if (data.mediaType === 'share') {
6877
+ if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.receiveStop) {
6849
6878
  // @ts-ignore
6850
6879
  this.webex.internal.newMetrics.submitClientEvent({
6851
- name: 'client.media.render.stop',
6880
+ name: 'client.media.rx.stop',
6852
6881
  payload: {
6853
- mediaType: 'share',
6854
- shareInstanceId: this.remoteShareInstanceId,
6882
+ mediaType: data.mediaType,
6883
+ shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
6855
6884
  },
6856
6885
  options: {
6857
6886
  meetingId: this.id,
6858
6887
  },
6859
6888
  });
6889
+
6890
+ if (data.mediaType === 'share') {
6891
+ // @ts-ignore
6892
+ this.webex.internal.newMetrics.submitClientEvent({
6893
+ name: 'client.media.render.stop',
6894
+ payload: {
6895
+ mediaType: 'share',
6896
+ shareInstanceId: this.remoteShareInstanceId,
6897
+ },
6898
+ options: {
6899
+ meetingId: this.id,
6900
+ },
6901
+ });
6902
+
6903
+ this.shareCAEventSentStatus.receiveStop = true;
6904
+ }
6860
6905
  }
6861
6906
  });
6862
6907
  };
@@ -7077,6 +7122,12 @@ export default class Meeting extends StatelessWebexPlugin {
7077
7122
  networkQualityMonitor: this.networkQualityMonitor,
7078
7123
  isMultistream: this.isMultistream,
7079
7124
  });
7125
+ this.shareCAEventSentStatus = {
7126
+ transmitStart: false,
7127
+ transmitStop: false,
7128
+ receiveStart: false,
7129
+ receiveStop: false,
7130
+ };
7080
7131
  this.setupStatsAnalyzerEventHandlers();
7081
7132
  this.networkQualityMonitor.on(
7082
7133
  NetworkQualityEventNames.NETWORK_QUALITY,
@@ -9341,6 +9392,8 @@ export default class Meeting extends StatelessWebexPlugin {
9341
9392
 
9342
9393
  if (floorRequestNeeded) {
9343
9394
  this.localShareInstanceId = uuid.v4();
9395
+ this.shareCAEventSentStatus.transmitStart = false;
9396
+ this.shareCAEventSentStatus.transmitStop = false;
9344
9397
 
9345
9398
  // @ts-ignore
9346
9399
  this.webex.internal.newMetrics.submitClientEvent({
@@ -115,9 +115,9 @@ import {ERROR_DESCRIPTIONS} from '@webex/internal-plugin-metrics/src/call-diagno
115
115
  import MeetingCollection from '@webex/plugin-meetings/src/meetings/collection';
116
116
 
117
117
  import {EVENT_TRIGGERS as VOICEAEVENTS} from '@webex/internal-plugin-voicea';
118
- import { createBrbState } from '@webex/plugin-meetings/src/meeting/brbState';
118
+ import {createBrbState} from '@webex/plugin-meetings/src/meeting/brbState';
119
119
  import JoinForbiddenError from '../../../../src/common/errors/join-forbidden-error';
120
- import { EventEmitter } from 'stream';
120
+ import {EventEmitter} from 'stream';
121
121
 
122
122
  describe('plugin-meetings', () => {
123
123
  const logger = {
@@ -282,7 +282,7 @@ describe('plugin-meetings', () => {
282
282
  testDestination = `testDestination-${uuid.v4()}`;
283
283
  correlationId = uuid.v4();
284
284
  uploadEvent = new EventEmitter();
285
- uploadEvent.addListener('progress', () => {})
285
+ uploadEvent.addListener('progress', () => {});
286
286
 
287
287
  meeting = new Meeting(
288
288
  {
@@ -3436,6 +3436,40 @@ describe('plugin-meetings', () => {
3436
3436
  });
3437
3437
  });
3438
3438
 
3439
+ it('LOCAL_MEDIA_STARTED triggers "meeting:media:local:start" event and does not send metric because we already have', async () => {
3440
+ meeting.shareCAEventSentStatus = {
3441
+ transmitStart: true,
3442
+ transmitStop: false,
3443
+ receiveStart: false,
3444
+ receiveStop: false,
3445
+ };
3446
+ statsAnalyzerStub.emit(
3447
+ {file: 'test', function: 'test'},
3448
+ StatsAnalyzerEventNames.LOCAL_MEDIA_STARTED,
3449
+ {mediaType: 'share'}
3450
+ );
3451
+
3452
+ assert.calledWith(
3453
+ TriggerProxy.trigger,
3454
+ sinon.match.instanceOf(Meeting),
3455
+ {
3456
+ file: 'meeting/index',
3457
+ function: 'addMedia',
3458
+ },
3459
+ EVENT_TRIGGERS.MEETING_MEDIA_LOCAL_STARTED,
3460
+ {
3461
+ mediaType: 'share',
3462
+ }
3463
+ );
3464
+ assert.neverCalledWith(webex.internal.newMetrics.submitClientEvent, {
3465
+ name: 'client.media.tx.start',
3466
+ payload: {mediaType: 'share', shareInstanceId: meeting.remoteShareInstanceId},
3467
+ options: {
3468
+ meetingId: meeting.id,
3469
+ },
3470
+ });
3471
+ });
3472
+
3439
3473
  it('LOCAL_MEDIA_STOPPED triggers the right metrics', async () => {
3440
3474
  statsAnalyzerStub.emit(
3441
3475
  {file: 'test', function: 'test'},
@@ -3452,6 +3486,28 @@ describe('plugin-meetings', () => {
3452
3486
  });
3453
3487
  });
3454
3488
 
3489
+ it('LOCAL_MEDIA_STOPPED does not send metric because we already have', async () => {
3490
+ meeting.shareCAEventSentStatus = {
3491
+ transmitStart: false,
3492
+ transmitStop: true,
3493
+ receiveStart: false,
3494
+ receiveStop: false,
3495
+ };
3496
+ statsAnalyzerStub.emit(
3497
+ {file: 'test', function: 'test'},
3498
+ StatsAnalyzerEventNames.LOCAL_MEDIA_STOPPED,
3499
+ {mediaType: 'share'}
3500
+ );
3501
+
3502
+ assert.neverCalledWith(webex.internal.newMetrics.submitClientEvent, {
3503
+ name: 'client.media.tx.stop',
3504
+ payload: {mediaType: 'share', shareInstanceId: meeting.remoteShareInstanceId},
3505
+ options: {
3506
+ meetingId: meeting.id,
3507
+ },
3508
+ });
3509
+ });
3510
+
3455
3511
  it('REMOTE_MEDIA_STARTED triggers "meeting:media:remote:start" event and sends metrics', async () => {
3456
3512
  statsAnalyzerStub.emit(
3457
3513
  {file: 'test', function: 'test'},
@@ -3532,6 +3588,47 @@ describe('plugin-meetings', () => {
3532
3588
  });
3533
3589
  });
3534
3590
 
3591
+ it('REMOTE_MEDIA_STARTED triggers "meeting:media:remote:start" event and does not send metric because we already have', async () => {
3592
+ meeting.shareCAEventSentStatus = {
3593
+ transmitStart: false,
3594
+ transmitStop: false,
3595
+ receiveStart: true,
3596
+ receiveStop: false,
3597
+ };
3598
+ statsAnalyzerStub.emit(
3599
+ {file: 'test', function: 'test'},
3600
+ StatsAnalyzerEventNames.REMOTE_MEDIA_STARTED,
3601
+ {mediaType: 'share'}
3602
+ );
3603
+
3604
+ assert.calledWith(
3605
+ TriggerProxy.trigger,
3606
+ sinon.match.instanceOf(Meeting),
3607
+ {
3608
+ file: 'meeting/index',
3609
+ function: 'addMedia',
3610
+ },
3611
+ EVENT_TRIGGERS.MEETING_MEDIA_REMOTE_STARTED,
3612
+ {
3613
+ mediaType: 'share',
3614
+ }
3615
+ );
3616
+ assert.neverCalledWith(webex.internal.newMetrics.submitClientEvent, {
3617
+ name: 'client.media.render.start',
3618
+ payload: {mediaType: 'share', shareInstanceId: meeting.remoteShareInstanceId},
3619
+ options: {
3620
+ meetingId: meeting.id,
3621
+ },
3622
+ });
3623
+ assert.neverCalledWith(webex.internal.newMetrics.submitClientEvent, {
3624
+ name: 'client.media.rx.start',
3625
+ payload: {mediaType: 'share', shareInstanceId: meeting.remoteShareInstanceId},
3626
+ options: {
3627
+ meetingId: meeting.id,
3628
+ },
3629
+ });
3630
+ });
3631
+
3535
3632
  it('REMOTE_MEDIA_STOPPED triggers the right metrics for share', async () => {
3536
3633
  statsAnalyzerStub.emit(
3537
3634
  {file: 'test', function: 'test'},
@@ -3556,6 +3653,34 @@ describe('plugin-meetings', () => {
3556
3653
  });
3557
3654
  });
3558
3655
 
3656
+ it('REMOTE_MEDIA_STOPPED does not send metric because we already have', async () => {
3657
+ meeting.shareCAEventSentStatus = {
3658
+ transmitStart: false,
3659
+ transmitStop: false,
3660
+ receiveStart: true,
3661
+ receiveStop: true,
3662
+ };
3663
+ statsAnalyzerStub.emit(
3664
+ {file: 'test', function: 'test'},
3665
+ StatsAnalyzerEventNames.REMOTE_MEDIA_STOPPED,
3666
+ {mediaType: 'share'}
3667
+ );
3668
+ assert.neverCalledWith(webex.internal.newMetrics.submitClientEvent, {
3669
+ name: 'client.media.render.stop',
3670
+ payload: {mediaType: 'share', shareInstanceId: meeting.remoteShareInstanceId},
3671
+ options: {
3672
+ meetingId: meeting.id,
3673
+ },
3674
+ });
3675
+ assert.neverCalledWith(webex.internal.newMetrics.submitClientEvent, {
3676
+ name: 'client.media.rx.stop',
3677
+ payload: {mediaType: 'share', shareInstanceId: meeting.remoteShareInstanceId},
3678
+ options: {
3679
+ meetingId: meeting.id,
3680
+ },
3681
+ });
3682
+ });
3683
+
3559
3684
  it('counts the number of members that are in the meeting for MEDIA_QUALITY event', async () => {
3560
3685
  let fakeMembersCollection = {
3561
3686
  members: {
@@ -3884,20 +4009,24 @@ describe('plugin-meetings', () => {
3884
4009
  } catch (err) {
3885
4010
  assert.instanceOf(err, Error);
3886
4011
  assert.equal(err.message, 'setBrb failed');
3887
- assert.isRejected((Promise.reject()));
4012
+ assert.isRejected(Promise.reject());
3888
4013
  }
3889
4014
  });
3890
4015
 
3891
4016
  it('updates remote mute state when brb is enabled', async () => {
3892
- meeting.audio = { handleServerRemoteMuteUpdate: sinon.stub() };
4017
+ meeting.audio = {handleServerRemoteMuteUpdate: sinon.stub()};
3893
4018
 
3894
4019
  await meeting.beRightBack(true);
3895
4020
 
3896
- sinon.assert.calledOnceWithExactly(meeting.audio.handleServerRemoteMuteUpdate, meeting, true);
4021
+ sinon.assert.calledOnceWithExactly(
4022
+ meeting.audio.handleServerRemoteMuteUpdate,
4023
+ meeting,
4024
+ true
4025
+ );
3897
4026
  });
3898
4027
 
3899
4028
  it('does not update remote mute state when brb is disabled', async () => {
3900
- meeting.audio = { handleServerRemoteMuteUpdate: sinon.stub() };
4029
+ meeting.audio = {handleServerRemoteMuteUpdate: sinon.stub()};
3901
4030
 
3902
4031
  await meeting.beRightBack(false);
3903
4032
 
@@ -3956,7 +4085,10 @@ describe('plugin-meetings', () => {
3956
4085
  .resolves({id: 'fake clientMediaPreferences'});
3957
4086
  meeting.roap.doTurnDiscovery = sinon.stub().resolves({
3958
4087
  turnServerInfo: {
3959
- urls: ['turns:turn-server-url1:443?transport=tcp', 'turns:turn-server-url2:443?transport=tcp'],
4088
+ urls: [
4089
+ 'turns:turn-server-url1:443?transport=tcp',
4090
+ 'turns:turn-server-url2:443?transport=tcp',
4091
+ ],
3960
4092
  username: 'turn user',
3961
4093
  password: 'turn password',
3962
4094
  },
@@ -3974,7 +4106,10 @@ describe('plugin-meetings', () => {
3974
4106
  expectedMediaConnectionConfig = {
3975
4107
  iceServers: [
3976
4108
  {
3977
- urls: ['turns:turn-server-url1:443?transport=tcp', 'turns:turn-server-url2:443?transport=tcp'],
4109
+ urls: [
4110
+ 'turns:turn-server-url1:443?transport=tcp',
4111
+ 'turns:turn-server-url2:443?transport=tcp',
4112
+ ],
3978
4113
  username: 'turn user',
3979
4114
  credential: 'turn password',
3980
4115
  },
@@ -4056,9 +4191,11 @@ describe('plugin-meetings', () => {
4056
4191
  .stub(InternalMediaCoreModule, 'MultistreamRoapMediaConnection')
4057
4192
  .returns(fakeMultistreamRoapMediaConnection);
4058
4193
 
4059
- locusMediaRequestStub = sinon
4060
- .stub(WebexPlugin.prototype, 'request')
4061
- .resolves({body: {locus: {fullState: {}}}, upload: sinon.match.instanceOf(EventEmitter), download: sinon.match.instanceOf(EventEmitter)});
4194
+ locusMediaRequestStub = sinon.stub(WebexPlugin.prototype, 'request').resolves({
4195
+ body: {locus: {fullState: {}}},
4196
+ upload: sinon.match.instanceOf(EventEmitter),
4197
+ download: sinon.match.instanceOf(EventEmitter),
4198
+ });
4062
4199
 
4063
4200
  // setup some things and mocks so that the call to join() works
4064
4201
  // (we need to call join() because it creates the LocusMediaRequest instance
@@ -5242,7 +5379,10 @@ describe('plugin-meetings', () => {
5242
5379
  // and check that when we fallback to transcoded we still do another TURN discovery
5243
5380
  await runCheck(
5244
5381
  {
5245
- urls: ['turns:turn-server-url1:443?transport=tcp', 'turns:turn-server-url2:443?transport=tcp'],
5382
+ urls: [
5383
+ 'turns:turn-server-url1:443?transport=tcp',
5384
+ 'turns:turn-server-url2:443?transport=tcp',
5385
+ ],
5246
5386
  username: 'turn user',
5247
5387
  password: 'turn password',
5248
5388
  },
@@ -5256,7 +5396,10 @@ describe('plugin-meetings', () => {
5256
5396
  // but doing it just for completeness
5257
5397
  await runCheck(
5258
5398
  {
5259
- urls: ['turns:turn-server-url1:443?transport=tcp', 'turns:turn-server-url2:443?transport=tcp'],
5399
+ urls: [
5400
+ 'turns:turn-server-url1:443?transport=tcp',
5401
+ 'turns:turn-server-url2:443?transport=tcp',
5402
+ ],
5260
5403
  username: 'turn user',
5261
5404
  password: 'turn password',
5262
5405
  },
@@ -7640,6 +7783,12 @@ describe('plugin-meetings', () => {
7640
7783
  meeting.audio = {handleLocalStreamChange: sinon.stub()};
7641
7784
  meeting.video = {handleLocalStreamChange: sinon.stub()};
7642
7785
  meeting.statsAnalyzer = {updateMediaStatus: sinon.stub()};
7786
+ meeting.shareCAEventSentStatus = {
7787
+ transmitStart: false,
7788
+ transmitStop: false,
7789
+ receiveStart: false,
7790
+ receiveStop: false,
7791
+ };
7643
7792
  fakeMultistreamRoapMediaConnection = {
7644
7793
  createSendSlot: () => {
7645
7794
  return {
@@ -7707,6 +7856,9 @@ describe('plugin-meetings', () => {
7707
7856
  });
7708
7857
  assert.equal(meeting.mediaProperties.mediaDirection.sendShare, true);
7709
7858
 
7859
+ assert.equal(meeting.shareCAEventSentStatus.transmitStart, false);
7860
+ assert.equal(meeting.shareCAEventSentStatus.transmitStop, false);
7861
+
7710
7862
  assert.calledWith(meeting.statsAnalyzer.updateMediaStatus, {
7711
7863
  expected: {sendShare: true},
7712
7864
  });
@@ -7727,18 +7879,23 @@ describe('plugin-meetings', () => {
7727
7879
  assert.equal(meeting.mediaProperties.shareAudioStream, stream);
7728
7880
  assert.equal(meeting.mediaProperties.mediaDirection.sendShare, true);
7729
7881
 
7882
+ assert.equal(meeting.shareCAEventSentStatus.transmitStart, false);
7883
+ assert.equal(meeting.shareCAEventSentStatus.transmitStop, false);
7884
+
7730
7885
  assert.calledWith(meeting.statsAnalyzer.updateMediaStatus, {
7731
7886
  expected: {sendShare: true},
7732
7887
  });
7733
7888
  };
7734
7889
 
7735
7890
  it('requests screen share floor and publishes the screen share video stream', async () => {
7891
+ meeting.shareCAEventSentStatus.transmitStart = true;
7736
7892
  await meeting.publishStreams({screenShare: {video: videoShareStream}});
7737
7893
 
7738
7894
  checkScreenShareVideoPublished(videoShareStream);
7739
7895
  });
7740
7896
 
7741
7897
  it('requests screen share floor and publishes the screen share audio stream', async () => {
7898
+ meeting.shareCAEventSentStatus.transmitStart = true;
7742
7899
  await meeting.publishStreams({screenShare: {audio: audioShareStream}});
7743
7900
 
7744
7901
  checkScreenShareAudioPublished(audioShareStream);
@@ -12032,6 +12189,8 @@ describe('plugin-meetings', () => {
12032
12189
  // Set the webinar attendee flag
12033
12190
  meeting.webinar = {selfIsAttendee: true};
12034
12191
  meeting.locusInfo.info.isWebinar = true;
12192
+ meeting.shareCAEventSentStatus.receiveStart = true;
12193
+ meeting.shareCAEventSentStatus.receiveStop = true;
12035
12194
 
12036
12195
  // Step 1: Start sharing whiteboard A
12037
12196
  const data1 = generateData(
@@ -12055,6 +12214,8 @@ describe('plugin-meetings', () => {
12055
12214
 
12056
12215
  // Specific assertions for webinar attendee status
12057
12216
  assert.equal(meeting.shareStatus, SHARE_STATUS.REMOTE_SHARE_ACTIVE);
12217
+ assert.equal(meeting.shareCAEventSentStatus.receiveStart, false);
12218
+ assert.equal(meeting.shareCAEventSentStatus.receiveStop, false);
12058
12219
  });
12059
12220
  });
12060
12221