@webex/plugin-meetings 2.60.0-next.2 → 2.60.0-next.4

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.
@@ -308,6 +308,7 @@ describe('plugin-meetings', () => {
308
308
  assert.equal(meeting.resource, uuid2);
309
309
  assert.equal(meeting.deviceUrl, uuid3);
310
310
  assert.equal(meeting.correlationId, correlationId);
311
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId});
311
312
  assert.deepEqual(meeting.meetingInfo, {});
312
313
  assert.instanceOf(meeting.members, Members);
313
314
  assert.calledOnceWithExactly(
@@ -375,6 +376,34 @@ describe('plugin-meetings', () => {
375
376
  }
376
377
  );
377
378
  assert.equal(newMeeting.correlationId, newMeeting.id);
379
+ assert.deepEqual(newMeeting.callStateForMetrics, {correlationId: newMeeting.id});
380
+ });
381
+
382
+ it('correlationId can be provided in callStateForMetrics', () => {
383
+ const newMeeting = new Meeting(
384
+ {
385
+ userId: uuid1,
386
+ resource: uuid2,
387
+ deviceUrl: uuid3,
388
+ locus: {url: url1},
389
+ destination: testDestination,
390
+ destinationType: _MEETING_ID_,
391
+ callStateForMetrics: {
392
+ correlationId: uuid4,
393
+ joinTrigger: 'fake-join-trigger',
394
+ loginType: 'fake-login-type',
395
+ }
396
+ },
397
+ {
398
+ parent: webex,
399
+ }
400
+ );
401
+ assert.equal(newMeeting.correlationId, uuid4);
402
+ assert.deepEqual(newMeeting.callStateForMetrics, {
403
+ correlationId: uuid4,
404
+ joinTrigger: 'fake-join-trigger',
405
+ loginType: 'fake-login-type',
406
+ });
378
407
  });
379
408
 
380
409
  describe('creates ReceiveSlot manager instance', () => {
@@ -851,6 +880,17 @@ describe('plugin-meetings', () => {
851
880
  assert.calledOnce(meeting.startTranscription);
852
881
  });
853
882
 
883
+ it('should take trigger from meeting joinTrigger if available', () => {
884
+ meeting.updateCallStateForMetrics({joinTrigger: 'fake-join-trigger'});
885
+ const join = meeting.join();
886
+
887
+ assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
888
+ name: 'client.call.initiated',
889
+ payload: {trigger: 'fake-join-trigger', isRoapCallEnabled: true},
890
+ options: {meetingId: meeting.id},
891
+ });
892
+ });
893
+
854
894
  it('should not create new correlation ID on join immediately after create', async () => {
855
895
  await meeting.join();
856
896
  sinon.assert.notCalled(setCorrelationIdSpy);
@@ -1173,8 +1213,8 @@ describe('plugin-meetings', () => {
1173
1213
  assert.exists(meeting.addMedia);
1174
1214
  });
1175
1215
 
1176
- it('should reject promise if meeting is not active', async () => {
1177
- const result = await assert.isRejected(meeting.addMedia());
1216
+ it('should reject promise if meeting is not active and the meeting in lobby is not enabled', async () => {
1217
+ const result = await assert.isRejected(meeting.addMedia({allowMediaInLobby: false}));
1178
1218
 
1179
1219
  assert.instanceOf(result, MeetingNotActiveError);
1180
1220
  });
@@ -2583,8 +2623,12 @@ describe('plugin-meetings', () => {
2583
2623
  setUnmuteAllowed: sinon.stub(),
2584
2624
  setMuted: sinon.stub(),
2585
2625
  setServerMuted: sinon.stub(),
2586
- outputTrack: {
2587
- id: 'fake mic'
2626
+ outputStream: {
2627
+ getTracks: () => {
2628
+ return [{
2629
+ id: 'fake mic'
2630
+ }];
2631
+ }
2588
2632
  }
2589
2633
  }
2590
2634
 
@@ -2795,10 +2839,10 @@ describe('plugin-meetings', () => {
2795
2839
  assert.calledOnceWithExactly(roapMediaConnectionConstructorStub, mediaConnectionConfig,
2796
2840
  {
2797
2841
  localTracks: {
2798
- audio: localStreams.audio?.outputTrack,
2799
- video: localStreams.video?.outputTrack,
2800
- screenShareVideo: localStreams.screenShareVideo?.outputTrack,
2801
- screenShareAudio: localStreams.screenShareAudio?.outputTrack,
2842
+ audio: localStreams.audio?.outputStream?.getTracks()[0],
2843
+ video: localStreams.video?.outputStream?.getTracks()[0],
2844
+ screenShareVideo: localStreams.screenShareVideo?.outputStream?.getTracks()[0],
2845
+ screenShareAudio: localStreams.screenShareAudio?.outputStream?.getTracks()[0],
2802
2846
  },
2803
2847
  direction: {audio: direction.audio, video: direction.video, screenShareVideo: direction.screenShare},
2804
2848
  remoteQualityLevel,
@@ -3073,7 +3117,7 @@ describe('plugin-meetings', () => {
3073
3117
  assert.calledOnceWithExactly(meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream, fakeMicrophoneStream);
3074
3118
  } else {
3075
3119
  assert.calledOnceWithExactly(fakeRoapMediaConnection.update, {
3076
- localTracks: { audio: fakeMicrophoneStream.outputTrack, video: null, screenShareVideo: null, screenShareAudio: null },
3120
+ localTracks: { audio: fakeMicrophoneStream.outputStream.getTracks()[0], video: null, screenShareVideo: null, screenShareAudio: null },
3077
3121
  direction: {
3078
3122
  audio: expected.direction,
3079
3123
  video: 'sendrecv',
@@ -3099,8 +3143,12 @@ describe('plugin-meetings', () => {
3099
3143
  muted: false,
3100
3144
  setUnmuteAllowed: sinon.stub(),
3101
3145
  setMuted: sinon.stub(),
3102
- outputTrack:{
3103
- id: 'fake mic 2',
3146
+ outputStream: {
3147
+ getTracks: () => {
3148
+ return [{
3149
+ id: 'fake mic 2',
3150
+ }];
3151
+ }
3104
3152
  }
3105
3153
  }
3106
3154
 
@@ -3112,7 +3160,7 @@ describe('plugin-meetings', () => {
3112
3160
  assert.calledOnceWithExactly(meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream, fakeMicrophoneStream2);
3113
3161
  } else {
3114
3162
  assert.calledOnceWithExactly(fakeRoapMediaConnection.update, {
3115
- localTracks: { audio: fakeMicrophoneStream2.outputTrack, video: null, screenShareVideo: null, screenShareAudio: null },
3163
+ localTracks: { audio: fakeMicrophoneStream2.outputStream.getTracks()[0], video: null, screenShareVideo: null, screenShareAudio: null },
3116
3164
  direction: {
3117
3165
  audio: expected.direction,
3118
3166
  video: 'sendrecv',
@@ -3183,7 +3231,7 @@ describe('plugin-meetings', () => {
3183
3231
  assert.equal(meeting.sendSlotManager.getSlot(MediaType.AudioMain).active, expectedDirection !== 'inactive');
3184
3232
  } else {
3185
3233
  assert.calledOnceWithExactly(fakeRoapMediaConnection.update, {
3186
- localTracks: { audio: expectedStream?.outputTrack ?? null, video: null, screenShareVideo: null, screenShareAudio: null },
3234
+ localTracks: { audio: expectedStream?.outputStream.getTracks()[0] ?? null, video: null, screenShareVideo: null, screenShareAudio: null },
3187
3235
  direction: {
3188
3236
  audio: expectedDirection,
3189
3237
  video: 'sendrecv',
@@ -3633,7 +3681,11 @@ describe('plugin-meetings', () => {
3633
3681
  let sandbox;
3634
3682
 
3635
3683
  const createFakeLocalStream = () => ({
3636
- outputTrack: {id: 'fake underlying track'},
3684
+ outputStream: {
3685
+ getTracks: () => {
3686
+ return [{id: 'fake underlying track'}];
3687
+ }
3688
+ }
3637
3689
  });
3638
3690
  beforeEach(() => {
3639
3691
  sandbox = sinon.createSandbox();
@@ -3716,10 +3768,10 @@ describe('plugin-meetings', () => {
3716
3768
  meeting.mediaProperties.webrtcMediaConnection.update,
3717
3769
  {
3718
3770
  localTracks: {
3719
- audio: meeting.mediaProperties.audioStream.outputTrack,
3720
- video: meeting.mediaProperties.videoStream.outputTrack,
3721
- screenShareVideo: meeting.mediaProperties.shareVideoStream.outputTrack,
3722
- screenShareAudio: meeting.mediaProperties.shareVideoStream.outputTrack,
3771
+ audio: meeting.mediaProperties.audioStream.outputStream.getTracks()[0],
3772
+ video: meeting.mediaProperties.videoStream.outputStream.getTracks()[0],
3773
+ screenShareVideo: meeting.mediaProperties.shareVideoStream.outputStream.getTracks()[0],
3774
+ screenShareAudio: meeting.mediaProperties.shareVideoStream.outputStream.getTracks()[0],
3723
3775
  },
3724
3776
  direction: {
3725
3777
  audio: 'inactive',
@@ -3748,7 +3800,13 @@ describe('plugin-meetings', () => {
3748
3800
  meeting.mediaProperties.mediaDirection = mediaDirection;
3749
3801
  meeting.mediaProperties.remoteVideoStream = sinon
3750
3802
  .stub()
3751
- .returns({outputTrack: {id: 'some mock id'}});
3803
+ .returns({
3804
+ outputStream: {
3805
+ getTracks: () => {
3806
+ id: 'some mock id'
3807
+ }
3808
+ }
3809
+ });
3752
3810
 
3753
3811
  meeting.meetingRequest.changeVideoLayoutDebounced = sinon
3754
3812
  .stub()
@@ -4573,7 +4631,7 @@ describe('plugin-meetings', () => {
4573
4631
  };
4574
4632
  const FAKE_MEETING_INFO_LOOKUP_URL = 'meetingLookupUrl';
4575
4633
  const FAKE_PERMISSION_TOKEN = {someField: 'some value'};
4576
- const FAKE_TTL = 13;
4634
+ const FAKE_TIMESTAMPS = {timeLeft: 13, expiryTime: 123456, currentTime: 123478};
4577
4635
 
4578
4636
  beforeEach(() => {
4579
4637
  meeting.locusId = 'locus-id';
@@ -4583,7 +4641,7 @@ describe('plugin-meetings', () => {
4583
4641
  meeting.destination = 'meeting-destination';
4584
4642
  meeting.destinationType = 'meeting-destination-type';
4585
4643
  meeting.updateMeetingActions = sinon.stub().returns(undefined);
4586
- meeting.getPermissionTokenTimeLeftInSec = sinon.stub().returns(FAKE_TTL);
4644
+
4587
4645
  meeting.meetingInfoExtraParams = {
4588
4646
  extraParam1: 'value1'
4589
4647
  };
@@ -4604,6 +4662,50 @@ describe('plugin-meetings', () => {
4604
4662
  });
4605
4663
 
4606
4664
  it('calls meetingInfoProvider.fetchMeetingInfo() with the right params', async () => {
4665
+ meeting.getPermissionTokenExpiryInfo = sinon.stub().returns(FAKE_TIMESTAMPS);
4666
+ await meeting.refreshPermissionToken('fake reason');
4667
+
4668
+ assert.calledOnceWithExactly(
4669
+ meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
4670
+ 'meeting-destination',
4671
+ 'meeting-destination-type',
4672
+ null,
4673
+ null,
4674
+ 'fake-installed-org-id',
4675
+ 'locus-id',
4676
+ {extraParam1: 'value1', permissionToken: FAKE_PERMISSION_TOKEN},
4677
+ {meetingId: meeting.id, sendCAevents: true}
4678
+ );
4679
+ assert.deepEqual(meeting.meetingInfo, {
4680
+ ...FAKE_MEETING_INFO,
4681
+ meetingLookupUrl: FAKE_MEETING_INFO_LOOKUP_URL
4682
+ });
4683
+ assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.NONE);
4684
+ assert.equal(meeting.requiredCaptcha, null);
4685
+ assert.equal(meeting.passwordStatus, PASSWORD_STATUS.NOT_REQUIRED);
4686
+
4687
+ assert.calledWith(
4688
+ TriggerProxy.trigger,
4689
+ meeting,
4690
+ {file: 'meetings', function: 'fetchMeetingInfo'},
4691
+ 'meeting:meetingInfoAvailable'
4692
+ );
4693
+ assert.calledWith(meeting.updateMeetingActions);
4694
+
4695
+ assert.calledWith(
4696
+ Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH, {
4697
+ correlationId: meeting.correlationId,
4698
+ timeLeft: FAKE_TIMESTAMPS.timeLeft,
4699
+ expiryTime: FAKE_TIMESTAMPS.expiryTime,
4700
+ currentTime: FAKE_TIMESTAMPS.currentTime,
4701
+ reason: 'fake reason',
4702
+ destinationType: 'meeting-destination-type',
4703
+ }
4704
+ );
4705
+ });
4706
+
4707
+ it('calls meetingInfoProvider.fetchMeetingInfo() with the right params when getPermissionTokenExpiryInfo returns undefined', async () => {
4708
+ meeting.getPermissionTokenExpiryInfo = sinon.stub().returns(undefined);
4607
4709
  await meeting.refreshPermissionToken('fake reason');
4608
4710
 
4609
4711
  assert.calledOnceWithExactly(
@@ -4636,7 +4738,9 @@ describe('plugin-meetings', () => {
4636
4738
  assert.calledWith(
4637
4739
  Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH, {
4638
4740
  correlationId: meeting.correlationId,
4639
- timeLeft: FAKE_TTL,
4741
+ timeLeft: undefined,
4742
+ expiryTime: undefined,
4743
+ currentTime: undefined,
4640
4744
  reason: 'fake reason',
4641
4745
  destinationType: 'meeting-destination-type',
4642
4746
  }
@@ -4644,6 +4748,7 @@ describe('plugin-meetings', () => {
4644
4748
  });
4645
4749
 
4646
4750
  it('calls meetingInfoProvider.fetchMeetingInfo() with the right params when we are starting an instant space meeting', async () => {
4751
+ meeting.getPermissionTokenExpiryInfo = sinon.stub().returns(FAKE_TIMESTAMPS);
4647
4752
  meeting.destination = 'some-convo-url';
4648
4753
  meeting.destinationType = 'CONVERSATION_URL';
4649
4754
  meeting.config.experimental = {enableAdhocMeetings: true};
@@ -4685,7 +4790,9 @@ describe('plugin-meetings', () => {
4685
4790
  assert.calledWith(
4686
4791
  Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH, {
4687
4792
  correlationId: meeting.correlationId,
4688
- timeLeft: FAKE_TTL,
4793
+ timeLeft: FAKE_TIMESTAMPS.timeLeft,
4794
+ expiryTime: FAKE_TIMESTAMPS.expiryTime,
4795
+ currentTime: FAKE_TIMESTAMPS.currentTime,
4689
4796
  reason: 'some reason',
4690
4797
  destinationType: 'MEETING_LINK',
4691
4798
  }
@@ -5178,6 +5285,31 @@ describe('plugin-meetings', () => {
5178
5285
  }
5179
5286
  });
5180
5287
  });
5288
+
5289
+ describe('#setCorrelationId', () => {
5290
+ it('should set the correlationId and return undefined', () => {
5291
+ assert.equal(meeting.correlationId, correlationId);
5292
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId});
5293
+ meeting.setCorrelationId(uuid1);
5294
+ assert.equal(meeting.correlationId, uuid1);
5295
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1});
5296
+ });
5297
+ });
5298
+
5299
+ describe('#updateCallStateForMetrics', () => {
5300
+ it('should update the callState, overriding existing values', () => {
5301
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId});
5302
+ meeting.updateCallStateForMetrics({correlationId: uuid1, joinTrigger: 'jt', loginType: 'lt'});
5303
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1, joinTrigger: 'jt', loginType: 'lt'});
5304
+ });
5305
+
5306
+ it('should update the callState, keeping non-supplied values', () => {
5307
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId});
5308
+ meeting.updateCallStateForMetrics({joinTrigger: 'jt', loginType: 'lt'});
5309
+ assert.deepEqual(meeting.callStateForMetrics, {correlationId, joinTrigger: 'jt', loginType: 'lt'});
5310
+ });
5311
+ });
5312
+
5181
5313
  describe('Local tracks publishing', () => {
5182
5314
  let audioStream;
5183
5315
  let videoStream;
@@ -5577,6 +5709,16 @@ describe('plugin-meetings', () => {
5577
5709
  });
5578
5710
  });
5579
5711
 
5712
+ it('should reconnect successfully if reconnectionManager.cleanUp is called before reconnection attempt', async () => {
5713
+ meeting.reconnectionManager.cleanUp();
5714
+
5715
+ try {
5716
+ await meeting.reconnect();
5717
+ } catch (err) {
5718
+ assert.fail('reconnect should not error after clean up');
5719
+ }
5720
+ })
5721
+
5580
5722
  it('should trigger reconnection success and send CA metric', async () => {
5581
5723
  await meeting.reconnect();
5582
5724
 
@@ -5662,7 +5804,7 @@ describe('plugin-meetings', () => {
5662
5804
  it('should stop remote tracks, and trigger a media:stopped event when the remote tracks are stopped', async () => {
5663
5805
  await meeting.closeRemoteStreams();
5664
5806
 
5665
- assert.equal(TriggerProxy.trigger.callCount, 6);
5807
+ assert.equal(TriggerProxy.trigger.callCount, 5);
5666
5808
  assert.calledWith(
5667
5809
  TriggerProxy.trigger,
5668
5810
  sinon.match.instanceOf(Meeting),
@@ -7249,12 +7391,18 @@ describe('plugin-meetings', () => {
7249
7391
  it('sets correctly when policy data is present in token', () => {
7250
7392
  assert.notOk(meeting.selfUserPolicies);
7251
7393
 
7252
- const policyData = {permission: {userPolicies: {a: true}}};
7394
+ const testUrl = 'https://example.com';
7395
+
7396
+ const policyData = {permission: {
7397
+ userPolicies: {a: true},
7398
+ enforceVBGImagesURL: testUrl
7399
+ }};
7253
7400
  meeting.permissionTokenPayload = policyData;
7254
7401
 
7255
7402
  meeting.setSelfUserPolicies();
7256
7403
 
7257
7404
  assert.deepEqual(meeting.selfUserPolicies, policyData.permission.userPolicies);
7405
+ assert.equal(meeting.enforceVBGImagesURL, testUrl);
7258
7406
  });
7259
7407
 
7260
7408
  it('handles missing permission data', () => {
@@ -7522,14 +7670,6 @@ describe('plugin-meetings', () => {
7522
7670
  });
7523
7671
  });
7524
7672
 
7525
- describe('#setCorrelationId', () => {
7526
- it('should set the correlationId and return undefined', () => {
7527
- assert.ok(meeting.correlationId);
7528
- meeting.setCorrelationId(uuid1);
7529
- assert.equal(meeting.correlationId, uuid1);
7530
- });
7531
- });
7532
-
7533
7673
  describe('#setUpLocusInfoAssignHostListener', () => {
7534
7674
  let locusInfoOnSpy;
7535
7675
  let inMeetingActionsSetSpy;
@@ -7958,6 +8098,60 @@ describe('plugin-meetings', () => {
7958
8098
  }
7959
8099
  );
7960
8100
 
8101
+ forEach(
8102
+ [
8103
+ // policies supported and enforce is true
8104
+ {
8105
+ meetingInfo: {video: {}},
8106
+ selfUserPolicies: {
8107
+ [SELF_POLICY.ENFORCE_VIRTUAL_BACKGROUND]: true,
8108
+ },
8109
+ expectedActions: {
8110
+ enforceVirtualBackground: true,
8111
+ },
8112
+ },
8113
+ // policies supported and enforce is false
8114
+ {
8115
+ meetingInfo: {video: {}},
8116
+ selfUserPolicies: {
8117
+ [SELF_POLICY.ENFORCE_VIRTUAL_BACKGROUND]: false,
8118
+ },
8119
+ expectedActions: {
8120
+ enforceVirtualBackground: false,
8121
+ },
8122
+ },
8123
+ // policies not supported but enforce is true
8124
+ {
8125
+ meetingInfo: undefined,
8126
+ selfUserPolicies: {
8127
+ [SELF_POLICY.ENFORCE_VIRTUAL_BACKGROUND]: true,
8128
+ },
8129
+ expectedActions: {
8130
+ enforceVirtualBackground: false,
8131
+ },
8132
+ },
8133
+ ],
8134
+ ({meetingInfo, selfUserPolicies, expectedActions}) => {
8135
+ it(`expectedActions are ${JSON.stringify(
8136
+ expectedActions
8137
+ )} when policies are ${JSON.stringify(
8138
+ selfUserPolicies
8139
+ )} and meetingInfo is ${JSON.stringify(meetingInfo)}`, () => {
8140
+ meeting.meetingInfo = meetingInfo;
8141
+ meeting.selfUserPolicies = selfUserPolicies;
8142
+
8143
+ meeting.updateMeetingActions();
8144
+
8145
+ assert.deepEqual(
8146
+ {
8147
+ enforceVirtualBackground: meeting.inMeetingActions.enforceVirtualBackground,
8148
+ },
8149
+ expectedActions
8150
+ );
8151
+ });
8152
+ }
8153
+ );
8154
+
7961
8155
  it('canUseVoip is disabled when the required policies are missing', () => {
7962
8156
  meeting.userDisplayHints = [DISPLAY_HINTS.VOIP_IS_ENABLED];
7963
8157
  meeting.selfUserPolicies = {};
@@ -10365,7 +10559,7 @@ describe('plugin-meetings', () => {
10365
10559
  });
10366
10560
  });
10367
10561
 
10368
- describe('#getPermissionTokenTimeLeftInSec', () => {
10562
+ describe('#getPermissionTokenExpiryInfo', () => {
10369
10563
  let now;
10370
10564
  let clock;
10371
10565
 
@@ -10381,63 +10575,65 @@ describe('plugin-meetings', () => {
10381
10575
  })
10382
10576
 
10383
10577
  it('should return undefined if exp is undefined', () => {
10384
- assert.equal(meeting.getPermissionTokenTimeLeftInSec(), undefined)
10578
+ assert.equal(meeting.getPermissionTokenExpiryInfo(), undefined)
10385
10579
  });
10386
10580
 
10387
10581
  it('should return the expected positive exp', () => {
10388
10582
  // set permission token as now + 1 sec
10389
- meeting.permissionTokenPayload = {exp: (now + 1000).toString()};
10390
- assert.equal(meeting.getPermissionTokenTimeLeftInSec(), 1);
10583
+ const expiryTime = now + 1000;
10584
+ meeting.permissionTokenPayload = {exp: (expiryTime).toString()};
10585
+ assert.deepEqual(meeting.getPermissionTokenExpiryInfo(), {timeLeft: 1, expiryTime: Number(expiryTime), currentTime: now});
10391
10586
  });
10392
10587
 
10393
10588
  it('should return the expected negative exp', () => {
10394
10589
  // set permission token as now - 1 sec
10395
- meeting.permissionTokenPayload = {exp: (now - 1000).toString()};
10396
- assert.equal(meeting.getPermissionTokenTimeLeftInSec(), -1);
10590
+ const expiryTime = now - 1000;
10591
+ meeting.permissionTokenPayload = {exp: (expiryTime).toString()};
10592
+ assert.deepEqual(meeting.getPermissionTokenExpiryInfo(), {timeLeft: -1, expiryTime: Number(expiryTime), currentTime: now});
10397
10593
  });
10398
10594
  });
10399
10595
 
10400
10596
  describe('#checkAndRefreshPermissionToken', () => {
10401
10597
  it('should not fire refreshPermissionToken if permissionToken is not defined', async() => {
10402
- meeting.getPermissionTokenTimeLeftInSec = sinon.stub().returns(undefined)
10598
+ meeting.getPermissionTokenExpiryInfo = sinon.stub().returns(undefined)
10403
10599
  meeting.refreshPermissionToken = sinon.stub().returns(Promise.resolve('test return value'));
10404
10600
 
10405
10601
  const returnValue = await meeting.checkAndRefreshPermissionToken(10, 'ttl-join');
10406
10602
 
10407
- assert.calledOnce(meeting.getPermissionTokenTimeLeftInSec);
10603
+ assert.calledOnce(meeting.getPermissionTokenExpiryInfo);
10408
10604
  assert.notCalled(meeting.refreshPermissionToken);
10409
10605
  assert.equal(returnValue, undefined);
10410
10606
  });
10411
10607
 
10412
10608
  it('should fire refreshPermissionToken if time left is below 10sec', async() => {
10413
- meeting.getPermissionTokenTimeLeftInSec = sinon.stub().returns(9)
10609
+ meeting.getPermissionTokenExpiryInfo = sinon.stub().returns({timeLeft: 9, expiryTime: 122132, currentTime: Date.now()})
10414
10610
  meeting.refreshPermissionToken = sinon.stub().returns(Promise.resolve('test return value'));
10415
10611
 
10416
10612
  const returnValue = await meeting.checkAndRefreshPermissionToken(10, 'ttl-join');
10417
10613
 
10418
- assert.calledOnce(meeting.getPermissionTokenTimeLeftInSec);
10614
+ assert.calledOnce(meeting.getPermissionTokenExpiryInfo);
10419
10615
  assert.calledOnceWithExactly(meeting.refreshPermissionToken, 'ttl-join');
10420
10616
  assert.equal(returnValue, 'test return value');
10421
10617
  });
10422
10618
 
10423
10619
  it('should fire refreshPermissionToken if time left is equal 10sec', async () => {
10424
- meeting.getPermissionTokenTimeLeftInSec = sinon.stub().returns(10)
10620
+ meeting.getPermissionTokenExpiryInfo = sinon.stub().returns({timeLeft: 10, expiryTime: 122132, currentTime: Date.now()})
10425
10621
  meeting.refreshPermissionToken = sinon.stub().returns(Promise.resolve('test return value'));
10426
10622
 
10427
10623
  const returnValue = await meeting.checkAndRefreshPermissionToken(10, 'ttl-join');
10428
10624
 
10429
- assert.calledOnce(meeting.getPermissionTokenTimeLeftInSec);
10625
+ assert.calledOnce(meeting.getPermissionTokenExpiryInfo);
10430
10626
  assert.calledOnceWithExactly(meeting.refreshPermissionToken, 'ttl-join');
10431
10627
  assert.equal(returnValue, 'test return value');
10432
10628
  });
10433
10629
 
10434
10630
  it('should not fire refreshPermissionToken if time left is higher than 10sec', async () => {
10435
- meeting.getPermissionTokenTimeLeftInSec = sinon.stub().returns(11)
10631
+ meeting.getPermissionTokenExpiryInfo = sinon.stub().returns({timeLeft: 11, expiryTime: 122132, currentTime: Date.now()})
10436
10632
  meeting.refreshPermissionToken = sinon.stub().returns(Promise.resolve('test return value'));
10437
10633
 
10438
10634
  const returnValue = await meeting.checkAndRefreshPermissionToken(10, 'ttl-join');
10439
10635
 
10440
- assert.calledOnce(meeting.getPermissionTokenTimeLeftInSec);
10636
+ assert.calledOnce(meeting.getPermissionTokenExpiryInfo);
10441
10637
  assert.notCalled(meeting.refreshPermissionToken);
10442
10638
  assert.equal(returnValue, undefined);
10443
10639
  });
@@ -637,6 +637,29 @@ describe('plugin-meetings', () => {
637
637
 
638
638
  const FAKE_USE_RANDOM_DELAY = true;
639
639
  const correlationId = 'my-correlationId';
640
+ const callStateForMetrics = {
641
+ correlationId: 'my-correlationId2',
642
+ joinTrigger: 'my-join-trigger',
643
+ loginType: 'my-login-type',
644
+ };
645
+
646
+ it('should call setCallStateForMetrics on any pre-existing meeting', async () => {
647
+ const fakeMeeting = {setCallStateForMetrics: sinon.mock()};
648
+ webex.meetings.meetingCollection.getByKey = sinon.stub().returns(fakeMeeting);
649
+ await webex.meetings.create(
650
+ test1,
651
+ test2,
652
+ FAKE_USE_RANDOM_DELAY,
653
+ {},
654
+ correlationId,
655
+ true,
656
+ callStateForMetrics
657
+ );
658
+ assert.calledOnceWithExactly(fakeMeeting.setCallStateForMetrics, {
659
+ ...callStateForMetrics,
660
+ correlationId,
661
+ });
662
+ });
640
663
 
641
664
  const checkCallCreateMeeting = async (createParameters, createMeetingParameters) => {
642
665
  const create = webex.meetings.create(...createParameters);
@@ -648,23 +671,37 @@ describe('plugin-meetings', () => {
648
671
  };
649
672
 
650
673
  it('calls createMeeting and returns its promise', async () => {
651
- checkCallCreateMeeting(
674
+ await checkCallCreateMeeting(
652
675
  [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, true],
653
- [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, true]
676
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, {correlationId}, true]
654
677
  );
655
678
  });
656
679
 
657
680
  it('calls createMeeting when failOnMissingMeetinginfo is undefined and returns its promise', async () => {
658
- checkCallCreateMeeting(
681
+ await checkCallCreateMeeting(
659
682
  [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, undefined],
660
- [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, false]
683
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, {correlationId}, false]
661
684
  );
662
685
  });
663
686
 
664
687
  it('calls createMeeting when failOnMissingMeetinginfo is false and returns its promise', async () => {
665
- checkCallCreateMeeting(
688
+ await checkCallCreateMeeting(
666
689
  [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, false],
667
- [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, false]
690
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, {correlationId}, false]
691
+ );
692
+ });
693
+
694
+ it('calls createMeeting with callStateForMetrics and returns its promise', async () => {
695
+ await checkCallCreateMeeting(
696
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, undefined, true, callStateForMetrics],
697
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, callStateForMetrics, true]
698
+ );
699
+ });
700
+
701
+ it('calls createMeeting with callStateForMetrics overwritten with correlationId and returns its promise', async () => {
702
+ await checkCallCreateMeeting(
703
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, true, callStateForMetrics],
704
+ [test1, test2, FAKE_USE_RANDOM_DELAY, {}, {...callStateForMetrics, correlationId}, true]
668
705
  );
669
706
  });
670
707
 
@@ -693,7 +730,8 @@ describe('plugin-meetings', () => {
693
730
  test2,
694
731
  FAKE_USE_RANDOM_DELAY,
695
732
  FAKE_INFO_EXTRA_PARAMS,
696
- correlationId
733
+ {correlationId},
734
+ false
697
735
  );
698
736
  });
699
737
 
@@ -1122,6 +1160,12 @@ describe('plugin-meetings', () => {
1122
1160
  if (expectedMeetingData.correlationId) {
1123
1161
  assert.equal(meeting.correlationId, expectedMeetingData.correlationId);
1124
1162
  }
1163
+ if (expectedMeetingData.callStateForMetrics) {
1164
+ assert.deepEqual(
1165
+ meeting.callStateForMetrics,
1166
+ expectedMeetingData.callStateForMetrics
1167
+ );
1168
+ }
1125
1169
  assert.equal(meeting.destination, destination);
1126
1170
  assert.equal(meeting.destinationType, type);
1127
1171
  assert.calledWith(
@@ -1390,7 +1434,7 @@ describe('plugin-meetings', () => {
1390
1434
  'test type',
1391
1435
  false,
1392
1436
  {},
1393
- 'my-correlationId'
1437
+ {correlationId: 'my-correlationId'}
1394
1438
  );
1395
1439
 
1396
1440
  const expectedMeetingData = {
@@ -1406,6 +1450,38 @@ describe('plugin-meetings', () => {
1406
1450
  true
1407
1451
  );
1408
1452
  });
1453
+
1454
+ it('creates meeting with the callStateForMetrics provided', async () => {
1455
+ const meeting = await webex.meetings.createMeeting(
1456
+ 'test destination',
1457
+ 'test type',
1458
+ false,
1459
+ {},
1460
+ {
1461
+ correlationId: 'my-correlationId',
1462
+ joinTrigger: 'my-join-trigger',
1463
+ loginType: 'my-login-type',
1464
+ }
1465
+ );
1466
+
1467
+ const expectedMeetingData = {
1468
+ correlationId: 'my-correlationId',
1469
+ callStateForMetrics: {
1470
+ correlationId: 'my-correlationId',
1471
+ joinTrigger: 'my-join-trigger',
1472
+ loginType: 'my-login-type',
1473
+ },
1474
+ };
1475
+
1476
+ checkCreateWithoutDelay(
1477
+ meeting,
1478
+ 'test destination',
1479
+ 'test type',
1480
+ {},
1481
+ expectedMeetingData,
1482
+ true
1483
+ );
1484
+ });
1409
1485
  });
1410
1486
 
1411
1487
  describe('rejected MeetingInfo.#fetchMeetingInfo', () => {