@webex/plugin-meetings 2.14.2 → 2.15.0

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 (36) hide show
  1. package/README.md +2 -0
  2. package/dist/common/errors/parameter.js +1 -1
  3. package/dist/common/errors/parameter.js.map +1 -1
  4. package/dist/constants.js +8 -4
  5. package/dist/constants.js.map +1 -1
  6. package/dist/locus-info/index.js +7 -0
  7. package/dist/locus-info/index.js.map +1 -1
  8. package/dist/locus-info/infoUtils.js +4 -2
  9. package/dist/locus-info/infoUtils.js.map +1 -1
  10. package/dist/locus-info/selfUtils.js +14 -0
  11. package/dist/locus-info/selfUtils.js.map +1 -1
  12. package/dist/meeting/in-meeting-actions.js +3 -1
  13. package/dist/meeting/in-meeting-actions.js.map +1 -1
  14. package/dist/meeting/index.js +164 -118
  15. package/dist/meeting/index.js.map +1 -1
  16. package/dist/meeting/util.js +4 -0
  17. package/dist/meeting/util.js.map +1 -1
  18. package/dist/metrics/constants.js +5 -1
  19. package/dist/metrics/constants.js.map +1 -1
  20. package/package.json +6 -6
  21. package/src/common/errors/parameter.js +1 -1
  22. package/src/constants.js +3 -0
  23. package/src/locus-info/index.js +10 -0
  24. package/src/locus-info/infoUtils.js +11 -3
  25. package/src/locus-info/selfUtils.js +12 -0
  26. package/src/meeting/in-meeting-actions.js +2 -0
  27. package/src/meeting/index.js +106 -52
  28. package/src/meeting/util.js +2 -0
  29. package/src/metrics/constants.js +5 -1
  30. package/test/unit/spec/fixture/locus.js +404 -0
  31. package/test/unit/spec/locus-info/index.js +27 -0
  32. package/test/unit/spec/locus-info/infoUtils.js +17 -10
  33. package/test/unit/spec/locus-info/selfConstant.js +1 -0
  34. package/test/unit/spec/meeting/in-meeting-actions.js +2 -0
  35. package/test/unit/spec/meeting/index.js +230 -0
  36. package/test/unit/spec/meeting/utils.js +7 -0
@@ -1908,6 +1908,7 @@ export default class Meeting extends StatelessWebexPlugin {
1908
1908
  canResumeRecording: MeetingUtil.canUserResume(payload.info.userDisplayHints),
1909
1909
  canRaiseHand: MeetingUtil.canUserRaiseHand(payload.info.userDisplayHints),
1910
1910
  canLowerAllHands: MeetingUtil.canUserLowerAllHands(payload.info.userDisplayHints),
1911
+ canLowerSomeoneElsesHand: MeetingUtil.canUserLowerSomeoneElsesHand(payload.info.userDisplayHints),
1911
1912
  });
1912
1913
 
1913
1914
  if (changed) {
@@ -2903,7 +2904,8 @@ export default class Meeting extends StatelessWebexPlugin {
2903
2904
  const audioStopped = audioTrack && audioTrack.readyState === ENDED;
2904
2905
  const videoStopped = videoTrack && videoTrack.readyState === ENDED;
2905
2906
 
2906
- if (audioStopped && videoStopped) {
2907
+ // triggers event for audio and video stop , sometime either audio or video one of them exists
2908
+ if (audioStopped || videoStopped) {
2907
2909
  Trigger.trigger(
2908
2910
  this,
2909
2911
  {
@@ -2916,7 +2918,7 @@ export default class Meeting extends StatelessWebexPlugin {
2916
2918
  );
2917
2919
  }
2918
2920
  else if (audioTrack || videoTrack) {
2919
- LoggerProxy.logger.warn('Meeting:index#closeLocalStream --> Error: MediaStreamTrack.readyState is incorrect.');
2921
+ LoggerProxy.logger.warn('Meeting:index#closeLocalStream --> Warning: track might already been ended or unavaliable.');
2920
2922
  }
2921
2923
  });
2922
2924
  }
@@ -3574,6 +3576,15 @@ export default class Meeting extends StatelessWebexPlugin {
3574
3576
  * Scenario D: Joining any other way (sip, pstn, conversationUrl, link just need to specify resourceId)
3575
3577
  */
3576
3578
  join(options = {}) {
3579
+ if (!this.webex.meetings.registered) {
3580
+ const errorMessage = 'Meeting:index#join --> Device not registered';
3581
+ const error = new Error(errorMessage);
3582
+
3583
+ LoggerProxy.logger.error(errorMessage);
3584
+
3585
+ return Promise.reject(error);
3586
+ }
3587
+
3577
3588
  // If a join request is being processed, refer to the deferred promise.
3578
3589
  if (this.deferJoin) {
3579
3590
  return this.deferJoin;
@@ -3886,7 +3897,7 @@ export default class Meeting extends StatelessWebexPlugin {
3886
3897
  mediaCapabilities: {
3887
3898
  rx: {
3888
3899
  audio: false,
3889
- share: false,
3900
+ share: true,
3890
3901
  share_audio: false,
3891
3902
  video: false,
3892
3903
  whiteboard: false
@@ -3904,16 +3915,73 @@ export default class Meeting extends StatelessWebexPlugin {
3904
3915
 
3905
3916
  Metrics.postEvent({event: eventType.MOVE_MEDIA, meeting: this});
3906
3917
 
3907
- return MeetingUtil.joinMeetingOptions(this, {resourceId, moveToResource: true}).then(() => {
3908
- this.meetingFiniteStateMachine.join();
3918
+ this.locusInfo.once(LOCUSINFO.EVENTS.SELF_OBSERVING, async () => {
3919
+ // Clean up the camera , microphone track and re initiate it
3909
3920
 
3910
- return this.updateMedia({
3911
- mediaSettings: {
3912
- sendVideo: false, receiveVideo: false, sendAudio: false, receiveAudio: false, sendShare: false, receiveShare: false
3921
+ try {
3922
+ if (this.isSharing) {
3923
+ await this.stopFloorRequest();
3913
3924
  }
3914
- }).then(() => Promise.resolve(this));
3925
+ const mediaSettings = {
3926
+ mediaDirection: {
3927
+ sendVideo: false,
3928
+ receiveVideo: false,
3929
+ sendAudio: false,
3930
+ receiveAudio: false,
3931
+ sendShare: false,
3932
+ receiveShare: true
3933
+ }
3934
+ };
3935
+
3936
+ // clean up the local tracks
3937
+ this.mediaProperties.setMediaDirection(mediaSettings.mediaDirection);
3938
+
3939
+ // close the existing local tracks
3940
+ await this.closeLocalStream();
3941
+ await this.closeLocalShare();
3942
+
3943
+ this.mediaProperties.unsetMediaTracks();
3944
+
3945
+
3946
+ // when a move to is intiated by the client , Locus delets the existing media node from the server as soon the DX answers the meeting
3947
+ // once the DX answers we establish connection back the media server with only receiveShare enabled
3948
+ await this.reconnectionManager.reconnectMedia(mediaSettings)
3949
+ .then(() => {
3950
+ Metrics.sendBehavioralMetric(
3951
+ BEHAVIORAL_METRICS.MOVE_TO_SUCCESS,
3952
+ );
3953
+ });
3954
+ }
3955
+ catch (error) {
3956
+ LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
3957
+ Metrics.sendBehavioralMetric(
3958
+ BEHAVIORAL_METRICS.MOVE_TO_FAILURE,
3959
+ {
3960
+ correlation_id: this.correlationId,
3961
+ locus_id: this.locusUrl.split('/').pop(),
3962
+ reason: error.message,
3963
+ stack: error.stack
3964
+ }
3965
+ );
3966
+ }
3967
+ });
3968
+
3969
+ LoggerProxy.logger.info('Meeting:index#moveTo --> Initated moved to using resourceId', resourceId);
3970
+
3971
+ return MeetingUtil.joinMeetingOptions(this, {resourceId, moveToResource: true}).then(() => {
3972
+ this.meetingFiniteStateMachine.join();
3915
3973
  }).catch((error) => {
3916
3974
  this.meetingFiniteStateMachine.fail(error);
3975
+ Metrics.sendBehavioralMetric(
3976
+ BEHAVIORAL_METRICS.MOVE_TO_FAILURE,
3977
+ {
3978
+ correlation_id: this.correlationId,
3979
+ locus_id: this.locusUrl.split('/').pop(),
3980
+ reason: error.message,
3981
+ stack: error.stack
3982
+ }
3983
+ );
3984
+ LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
3917
3985
 
3918
3986
  return Promise.reject(error);
3919
3987
  });
@@ -3927,54 +3995,38 @@ export default class Meeting extends StatelessWebexPlugin {
3927
3995
  * @memberof Meeting
3928
3996
  */
3929
3997
  moveFrom(resourceId) {
3998
+ // On moveFrom ask the developer to re capture it moveFrom then updateMedia
3930
3999
  if (!resourceId) {
3931
4000
  throw new ParameterError('Cannot move call without a resourceId.');
3932
4001
  }
3933
4002
  const oldCorrelationId = this.correlationId;
3934
4003
 
3935
- this.id = uuid.v4();
3936
-
3937
- this.webex.meetings.meetingCollection.set(this);
3938
-
3939
- Metrics.postEvent({
3940
- event: eventType.MEDIA_CAPABILITIES,
3941
- meeting: this,
3942
- data: {
3943
- mediaCapabilities: {
3944
- rx: {
3945
- audio: true,
3946
- share: true,
3947
- share_audio: true,
3948
- video: true,
3949
- whiteboard: true
3950
- },
3951
- tx: {
3952
- audio: true,
3953
- share: true,
3954
- share_audio: true,
3955
- video: true,
3956
- whiteboard: true
3957
- }
3958
- }
3959
- }
3960
- });
3961
4004
  Metrics.postEvent({event: eventType.MOVE_MEDIA, meeting: this});
3962
4005
 
3963
- return MeetingUtil.joinMeetingOptions(this).then((join) => this.getMediaStreams({sendAudio: true, sendVideo: true, sendShare: false})
3964
- .then(([localStream, localShare]) =>
3965
- this.updateMedia({
3966
- mediaSettings: {
3967
- sendAudio: true, receiveAudio: true, sendVideo: true, receiveVideo: true, sendShare: false, receiveShare: false
3968
- },
3969
- localStream,
3970
- localShare
3971
- })
3972
- .then(() => Promise.resolve(join)))
3973
- .then(() => MeetingUtil.leaveMeeting(this, {resourceId, correlationId: oldCorrelationId, moveMeeting: true})))
3974
- .then(() => {
3975
- this.webex.meetings.meetingCollection.delete(this.id);
4006
+ return MeetingUtil.joinMeetingOptions(this)
4007
+ .then(() => MeetingUtil.leaveMeeting(this, {
4008
+ resourceId,
4009
+ correlationId: oldCorrelationId,
4010
+ moveMeeting: true
4011
+ }).then(() => {
4012
+ this.resourceId = '';
4013
+ Metrics.sendBehavioralMetric(
4014
+ BEHAVIORAL_METRICS.MOVE_FROM_SUCCESS,
4015
+ );
4016
+ })).catch((error) => {
4017
+ this.meetingFiniteStateMachine.fail(error);
4018
+ Metrics.sendBehavioralMetric(
4019
+ BEHAVIORAL_METRICS.MOVE_FROM_FAILURE,
4020
+ {
4021
+ correlation_id: this.correlationId,
4022
+ locus_id: this.locusUrl.split('/').pop(),
4023
+ reason: error.message,
4024
+ stack: error.stack
4025
+ }
4026
+ );
4027
+ LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
3976
4028
 
3977
- return Promise.resolve();
4029
+ return Promise.reject(error);
3978
4030
  });
3979
4031
  }
3980
4032
 
@@ -4441,7 +4493,9 @@ export default class Meeting extends StatelessWebexPlugin {
4441
4493
  if (!this.canUpdateMedia()) {
4442
4494
  return this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.ALL, options);
4443
4495
  }
4444
- const {localStream, localShare, mediaSettings} = options;
4496
+ const {
4497
+ localStream, localShare, mediaSettings
4498
+ } = options;
4445
4499
 
4446
4500
  const previousSendShareStatus = this.mediaProperties.mediaDirection.sendShare;
4447
4501
 
@@ -4451,7 +4505,7 @@ export default class Meeting extends StatelessWebexPlugin {
4451
4505
  meetingId: this.id,
4452
4506
  remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
4453
4507
  enableRtx: this.config.enableRtx,
4454
- enableExtmap: this.config.enableExtmap
4508
+ enableExtmap: this.config.enableExtmap,
4455
4509
  })
4456
4510
  .then((peerConnection) => {
4457
4511
  LoggerProxy.logger.info(`${LOG_HEADER} PeerConnection received from updateMedia, ${peerConnection}`);
@@ -4480,7 +4534,7 @@ export default class Meeting extends StatelessWebexPlugin {
4480
4534
  .sendRoapMediaRequest({
4481
4535
  sdp: this.mediaProperties.peerConnection.sdp,
4482
4536
  roapSeq: this.roapSeq,
4483
- meeting: this // or can pass meeting ID
4537
+ meeting: this, // or can pass meeting ID
4484
4538
  }),
4485
4539
  {
4486
4540
  header: `${LOG_HEADER} sendRoapMediaRequest being sent`,
@@ -445,6 +445,8 @@ MeetingUtil.canUserRaiseHand = (displayHints) => displayHints.includes(DISPLAY_H
445
445
 
446
446
  MeetingUtil.canUserLowerAllHands = (displayHints) => displayHints.includes(DISPLAY_HINTS.LOWER_ALL_HANDS);
447
447
 
448
+ MeetingUtil.canUserLowerSomeoneElsesHand = (displayHints) => displayHints.includes(DISPLAY_HINTS.LOWER_SOMEONE_ELSES_HAND);
449
+
448
450
  MeetingUtil.lockMeeting = (actions, request, locusUrl) => {
449
451
  if (actions && actions.canLock) {
450
452
  return request.lockMeeting({locusUrl, lock: true});
@@ -51,7 +51,11 @@ const BEHAVIORAL_METRICS = {
51
51
  ADHOC_MEETING_FAILURE: 'js_sdk_adhoc_meeting_failure',
52
52
  VERIFY_PASSWORD_SUCCESS: 'js_sdk_verify_password_success',
53
53
  VERIFY_PASSWORD_ERROR: 'js_sdk_verify_password_error',
54
- VERIFY_CAPTCHA_ERROR: 'js_sdk_verify_captcha_error'
54
+ VERIFY_CAPTCHA_ERROR: 'js_sdk_verify_captcha_error',
55
+ MOVE_TO_SUCCESS: 'js_sdk_move_to_success',
56
+ MOVE_TO_FAILURE: 'js_sdk_move_to_failure',
57
+ MOVE_FROM_SUCCESS: 'js_sdk_move_from_success',
58
+ MOVE_FROM_FAILURE: 'js_sdk_move_from_failure'
55
59
  };
56
60
 
57
61
 
@@ -0,0 +1,404 @@
1
+ export default {
2
+ url: 'https://locus-a.wbx2.com/locus/api/v1/loci/aca0015b',
3
+ created: '2018-06-21T02:06:32.207Z',
4
+ info: {
5
+ topic: '',
6
+ sipUri: 'arun@cisco.webex.com',
7
+ maxParticipants: 1000,
8
+ webExRosterSyncEnabled: true,
9
+ webExMeetingId: '20519228',
10
+ globalMeetingId: '632D9CB5908CF13BE05FC0ABA26',
11
+ webExSite: 'cisco.webex.com',
12
+ webExMeetingName: 'ARUN Personal Room',
13
+ isPmr: true,
14
+ webexServiceType: 'MEETING_CENTER',
15
+ meetingAvatarUrl: 'https://cisco.webex.com/webappng/images/avatars/ag.png?type=initials&initials=ag',
16
+ owner: '344ea183-9d5d-4e77-aed2-c4f004afd',
17
+ siteOrgId: '1eb65fdf-9643-417f-9974-ad72ca',
18
+ callInTollNumber: '+1-408-525-6',
19
+ callInNumbers: [
20
+ {
21
+ number: '+1-408-525-',
22
+ tollfree: false,
23
+ label: 'Call-in toll number (US/Canada)'
24
+ }
25
+ ],
26
+ isSparkPstnEnabled: true,
27
+ isCallInEnabled: true,
28
+ isGlobalCallInEnabled: true,
29
+ isCallOutEnabled: true,
30
+ isGlobalCallOutEnabled: true,
31
+ displayHints: {
32
+ joined: [
33
+ 'WAITING_FOR_OTHERS',
34
+ 'RECORDING_STATUS_STOPPED',
35
+ 'LOCK_STATUS_UNLOCKED',
36
+ 'ROSTER_IN_MEETING',
37
+ 'SHARE_WHITEBOARD',
38
+ 'SHARE_WHITEBOARD_POLICY',
39
+ 'WEBEX_ASSISTANT_STATUS_INACTIVE',
40
+ 'CAPTION_START',
41
+ 'DISPLAY_REAL_TIME_TRANSLATION',
42
+ 'ENABLE_CAPTION_PANEL',
43
+ 'RAISE_HAND',
44
+ 'REACTIONS_ACTIVE',
45
+ 'REACTIONS_ACTIVE_SHOW_DISPLAY_NAME',
46
+ 'UCF_SUPPRESS_BREAKOUTS_SUPPORT',
47
+ 'UCF_SUPPRESS_MOBILE_BREAKOUTS_SUPPORT',
48
+ 'DISABLE_ASK_FOR_HELP',
49
+ 'STAGE_VIEW_INACTIVE',
50
+ 'IMMERSIVE_PRESENTER_SUPPORTED_FOR_MTG'
51
+ ],
52
+ moderator: [
53
+ 'RECORDING_CONTROL_START',
54
+ 'TRANSCRIPTION_CONTROL_START',
55
+ 'DISPLAY_NON_ENGLISH_ASR',
56
+ 'PRESENTER_CONTROL',
57
+ 'MUTE_ALL',
58
+ 'UNMUTE_ALL',
59
+ 'MUTE_OTHER',
60
+ 'MUTE_VIDEO_OTHER',
61
+ 'LOCK_CONTROL_LOCK',
62
+ 'MODERATOR_ASSIGNMENT_CONTROL',
63
+ 'ENABLE_MUTE_ON_ENTRY',
64
+ 'DISABLE_REACTIONS',
65
+ 'ENABLE_HARD_MUTE',
66
+ 'ADD_GUEST',
67
+ 'EXPEL',
68
+ 'ENABLE_STAGE_VIEW'
69
+ ],
70
+ coHost: [
71
+ 'LOCK_CONTROL_LOCK',
72
+ 'ENABLE_HARD_MUTE',
73
+ 'ENABLE_MUTE_ON_ENTRY',
74
+ 'MUTE_ALL',
75
+ 'UNMUTE_ALL',
76
+ 'DISABLE_REACTIONS',
77
+ 'MUTE_OTHER',
78
+ 'MUTE_VIDEO_OTHER',
79
+ 'TRANSCRIPTION_CONTROL_START',
80
+ 'DISPLAY_NON_ENGLISH_ASR',
81
+ 'PRESENTER_CONTROL',
82
+ 'ENABLE_STAGE_VIEW',
83
+ 'EXPEL',
84
+ 'ADD_GUEST'
85
+ ]
86
+ },
87
+ venueUrl: 'https://calliope-a.wbx2.com/calliope/api/v1/venues/b84e1830-74f7-11e8-',
88
+ datachannelUrl: 'https://board-a.wbx2.com/datachannel/api/v1/locus/aHR0cHM6Ly9sb2N1cy1hsb2NpL2FjYTAwMTViLTQ1ODctMzNiZi05NGRjLTE2NTBmZDMyY2Q4NQ==/registrations',
89
+ embeddedAppsListUrl: 'https://hecate-a.wbx2.com/apps/api/v1/locus/aca0015b-4587-33bf-94dc-/embeddedApps/allowed?sessionInfo=eyJhbGci.',
90
+ embeddedAppsLaunchUrl: 'https://hecate-a.wbx2.com/apps/api/v1/locus/aca0015b-4587-33bf-94dc/embeddedApps?sessionInfo=eyJhbGciOiJub25lIn0.eyJza.',
91
+ meetingInstanceId: '632D9CB5908CF13BE053D107FC0ABA26_I_2331',
92
+ webexSiteUuid: '4C675B882686B136'
93
+ },
94
+ host: {
95
+ id: '344ea183-9d5d-4e77-aed2-c4f',
96
+ name: 'Arun Ganeshan',
97
+ isExternal: false,
98
+ orgId: '1eb65fdf-9643-417f-997',
99
+ incomingCallProtocols: []
100
+ },
101
+ fullState: {
102
+ active: true,
103
+ count: 1,
104
+ locked: false,
105
+ state: 'ACTIVE',
106
+ type: 'MEETING',
107
+ lastActive: '2022-07-26T20:32:22.964Z',
108
+ sessionIds: [],
109
+ sessionId: '3762f03e-598a-29dd-1ae7'
110
+ },
111
+ meetings: [],
112
+ controls: {
113
+ lock: {
114
+ locked: false,
115
+ meta: {}
116
+ },
117
+ record: {
118
+ recording: false,
119
+ meta: {
120
+ readOnly: false
121
+ }
122
+ },
123
+ transcribe: {
124
+ transcribing: false,
125
+ postMeetingTranscribing: false,
126
+ caption: false,
127
+ meta: {}
128
+ },
129
+ meetingFull: {
130
+ meetingFull: false,
131
+ meta: {}
132
+ },
133
+ muteOnEntry: {
134
+ enabled: false,
135
+ meta: {}
136
+ },
137
+ shareControl: {
138
+ control: 'ANYONE',
139
+ meta: {}
140
+ },
141
+ disallowUnmute: {
142
+ enabled: false,
143
+ meta: {}
144
+ },
145
+ videoLayout: {
146
+ layoutName: {
147
+ defaultName: 'Equal',
148
+ singleScreenDefaultName: 'ActivePresence'
149
+ }
150
+ },
151
+ reactions: {
152
+ enabled: true,
153
+ meta: {
154
+ modifiedBy: '344ea183-9d5d-4e77-aed2',
155
+ lastModified: '2022-07-26T20:32:22.964Z'
156
+ },
157
+ reactionChannelUrl: 'https://media-encryption-a.wbx2.com/reaction/api/v1/channels/e0b7b747-67f0-4b89',
158
+ showDisplayNameWithReactions: true
159
+ },
160
+ viewTheParticipantList: {
161
+ enabled: true,
162
+ meta: {
163
+ lastModified: '2022-07-26T20:32:22.964Z'
164
+ }
165
+ }
166
+ },
167
+ participants: [
168
+ {
169
+ isCreator: true,
170
+ identity: '344ea183-9d5d-4e77',
171
+ url: 'https://locus-a.wbx2.com/locus/api/v1/loci/aca0015b-4587-33bf-94dc/participant/e0d54e94-226c-3290-b75a-83cc1dbf1554',
172
+ state: 'JOINED',
173
+ type: 'USER',
174
+ isSiteInternal: true,
175
+ person: {
176
+ id: '344ea183-9d5d-4e77-aed2',
177
+ name: 'Arun Ganeshan',
178
+ isExternal: false,
179
+ orgId: '1eb65fdf-9643-417f-9974-ad72cae0e10f',
180
+ incomingCallProtocols: []
181
+ },
182
+ devices: [
183
+ {
184
+ url: 'https://wdm-a.wbx2.com/wdm/api/v1/devices/85e6e2a0-2514-4fc2-a175',
185
+ deviceType: 'WEB',
186
+ state: 'JOINED',
187
+ intents: [
188
+ null
189
+ ],
190
+ correlationId: 'b05b4263-8fe3-427e-9995-e6f0a13302',
191
+ isVideoCallback: false,
192
+ csis: [],
193
+ replaces: []
194
+ }
195
+ ],
196
+ status: {
197
+ audioStatus: 'UNKNOWN',
198
+ videoStatus: 'UNKNOWN',
199
+ csis: []
200
+ },
201
+ controls: {
202
+ audio: {
203
+ muted: false,
204
+ requestedToUnmute: false,
205
+ disallowUnmute: false,
206
+ meta: {}
207
+ },
208
+ video: {
209
+ muted: false,
210
+ meta: {}
211
+ },
212
+ role: {
213
+ roles: [
214
+ {
215
+ type: 'COHOST',
216
+ hasRole: true,
217
+ meta: {
218
+ lastModified: '2022-07-26T20:32:22.964Z'
219
+ }
220
+ },
221
+ {
222
+ type: 'MODERATOR',
223
+ hasRole: true,
224
+ meta: {
225
+ lastModified: '2022-07-26T20:32:22.964Z'
226
+ }
227
+ },
228
+ {
229
+ type: 'ATTENDEE',
230
+ hasRole: true,
231
+ meta: {
232
+ lastModified: '2022-07-26T20:32:22.964Z',
233
+ readOnly: true
234
+ }
235
+ }
236
+ ]
237
+ }
238
+ },
239
+ doesNotSupportBreakouts: true,
240
+ identityTrustLevel: 'INTERNAL',
241
+ id: 'e0d54e94-226c-3290-b75a-83cc1dbf',
242
+ guest: false,
243
+ resourceGuest: false,
244
+ moderator: true,
245
+ panelist: false,
246
+ moveToLobbyNotAllowed: true,
247
+ cmrHost: true,
248
+ deviceUrl: 'https://wdm-a.wbx2.com/wdm/api/v1/devices/85e6e2a0-2514-4fc2-a175'
249
+ }
250
+ ],
251
+ self: {
252
+ deviceUrl: 'https://wdm-a.wbx2.com/wdm/api/v1/devices/85e6e2a0-2514-4fc2-a175',
253
+ alertHint: {
254
+ action: 'NONE'
255
+ },
256
+ alertType: {
257
+ action: 'NONE'
258
+ },
259
+ callbackInfo: {
260
+ callbackAddress: 'arungane@cisco.webex.com',
261
+ callbackType: 'SIPURI'
262
+ },
263
+ lookUpInfo: {
264
+ lookupLink: 'https://locus-a.wbx2.com/locus/api/v1/loci/meetingInfo/aca0015b-4587-33bf-94dc?type=LOCUS_ID&useUriLookup=false',
265
+ type: 'MEETING'
266
+ },
267
+ isCreator: true,
268
+ identity: '344ea183-9d5d-4e77-aed2-c4f004afd915',
269
+ url: 'https://locus-a.wbx2.com/locus/api/v1/loci/aca0015b-4587-33bf-94dc/participant/e0d54e94-226c-3290-b75a',
270
+ state: 'JOINED',
271
+ type: 'USER',
272
+ person: {
273
+ id: '344ea183-9d5d-4e77-aed2',
274
+ name: 'Arun Ganeshan',
275
+ isExternal: false,
276
+ orgId: '1eb65fdf-9643-417f-9974',
277
+ incomingCallProtocols: []
278
+ },
279
+ devices: [
280
+ {
281
+ url: 'https://wdm-a.wbx2.com/wdm/api/v1/devices/85e6e2a0-2514-4fc2-a175',
282
+ deviceType: 'WEB',
283
+ state: 'JOINED',
284
+ intents: [
285
+ null
286
+ ],
287
+ keepAliveUrl: 'https://locus-a.wbx2.com/locus/api/v1/loci/aca0015b-4587-33bf',
288
+ keepAliveSecs: 300,
289
+ callLegId: '80f5e939-1149-4f13-9535',
290
+ correlationId: 'b05b4263-8fe3-427e-9995',
291
+ isVideoCallback: false,
292
+ csis: [],
293
+ serverTranscoded: false,
294
+ serverComposed: false,
295
+ replaces: []
296
+ }
297
+ ],
298
+ status: {
299
+ audioStatus: 'UNKNOWN',
300
+ videoStatus: 'UNKNOWN',
301
+ csis: []
302
+ },
303
+ suggestedMedia: [
304
+ {
305
+ mediaType: 'audio',
306
+ mediaContent: 'main',
307
+ direction: 'sendrecv'
308
+ },
309
+ {
310
+ mediaType: 'video',
311
+ mediaContent: 'main',
312
+ direction: 'sendrecv'
313
+ },
314
+ {
315
+ mediaType: 'video',
316
+ mediaContent: 'slides',
317
+ direction: 'sendrecv'
318
+ }
319
+ ],
320
+ controls: {
321
+ audio: {
322
+ muted: false,
323
+ requestedToUnmute: false,
324
+ disallowUnmute: false,
325
+ meta: {}
326
+ },
327
+ video: {
328
+ muted: false,
329
+ meta: {}
330
+ },
331
+ role: {
332
+ roles: [
333
+ {
334
+ type: 'COHOST',
335
+ hasRole: true,
336
+ meta: {
337
+ lastModified: '2022-07-26T20:32:22.964Z'
338
+ }
339
+ },
340
+ {
341
+ type: 'MODERATOR',
342
+ hasRole: true,
343
+ meta: {
344
+ lastModified: '2022-07-26T20:32:22.964Z'
345
+ }
346
+ },
347
+ {
348
+ type: 'ATTENDEE',
349
+ hasRole: true,
350
+ meta: {
351
+ lastModified: '2022-07-26T20:32:22.964Z',
352
+ readOnly: true
353
+ }
354
+ }
355
+ ]
356
+ }
357
+ },
358
+ enableDTMF: true,
359
+ id: 'e0d54e94-226c-3290-b75a',
360
+ guest: false,
361
+ resourceGuest: false,
362
+ moderator: true,
363
+ panelist: false,
364
+ moveToLobbyNotAllowed: true,
365
+ cmrHost: true,
366
+ mediaBaseUrl: 'https://locus-a.wbx2.com/locus/api/v1/loci/aca0015b-4587-33bf-94dc/participant/e0d54e94-226c-3290-b75a-83cc1dbf1554/media'
367
+ },
368
+ mediaShares: [
369
+ {
370
+ name: 'content',
371
+ url: 'https://locus-a.wbx2.com/locus/api/v1/loci/aca0015b-4587-33bf-94dc/mediashares/337f77f9-2f27-3cb3-ba55'
372
+ },
373
+ {
374
+ name: 'whiteboardview',
375
+ url: 'https://locus-a.wbx2.com/locus/api/v1/loci/aca0015b-4587-33bf-94dc/mediashares/98891810-efb6-3aa3-b600-8654539abf46'
376
+ },
377
+ {
378
+ name: 'whiteboard',
379
+ url: 'https://locus-a.wbx2.com/locus/api/v1/loci/aca0015b-4587-33bf-94dc/mediashares/b8f1742b-5dc5-3d7a-b97f-39ae11f8a051'
380
+ }
381
+ ],
382
+ embeddedApps: [],
383
+ replaces: [],
384
+ sequence: {
385
+ entries: [
386
+ 138781603429640000
387
+ ],
388
+ rangeStart: 0,
389
+ rangeEnd: 0,
390
+ since: '138781603429640000',
391
+ sequenceHash: 42,
392
+ dataCenter: 'achm3',
393
+ totalParticipants: 1,
394
+ dirtyParticipants: 0
395
+ },
396
+ syncUrl: 'https://locus-a.wbx2.com/locus/api/v1/loci/aca0015b-4587-33bf-94dc/sync?since=138781603429640000&sequenceHash=42',
397
+ links: {
398
+ services: {
399
+ breakout: {
400
+ url: 'https://breakout-a.wbx2.com/breakout/api/v1'
401
+ }
402
+ }
403
+ }
404
+ };
@@ -619,6 +619,33 @@ describe('plugin-meetings', () => {
619
619
  LOCUSINFO.EVENTS.LOCAL_UNMUTE_REQUESTED,
620
620
  {});
621
621
  });
622
+
623
+
624
+ it('should trigger SELF_OBSERVING when moving meeting to DX', () => {
625
+ locusInfo.self = self;
626
+ const selfInitiatedMove = cloneDeep(self);
627
+
628
+ // Inital move meeting is iniated
629
+ selfInitiatedMove.devices[0].intent.type = 'MOVE_MEDIA';
630
+
631
+ locusInfo.webex.internal.device.url = self.deviceUrl;
632
+
633
+ locusInfo.updateSelf(selfInitiatedMove, []);
634
+
635
+ locusInfo.emitScoped = sinon.stub();
636
+ // When dx joined the meeting after move
637
+ const selfAfterDxJoins = cloneDeep(self);
638
+
639
+ selfAfterDxJoins.devices[0].intent.type = 'OBSERVE';
640
+
641
+ locusInfo.updateSelf(selfAfterDxJoins, []);
642
+
643
+ assert.calledWith(locusInfo.emitScoped, {
644
+ file: 'locus-info',
645
+ function: 'updateSelf'
646
+ },
647
+ LOCUSINFO.EVENTS.SELF_OBSERVING);
648
+ });
622
649
  });
623
650
 
624
651
  describe('#updateMeetingInfo', () => {