@webex/plugin-meetings 2.14.2 → 2.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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', () => {
@@ -66,6 +66,7 @@ export const self = {
66
66
  ],
67
67
  mediaSessionsExternal: false,
68
68
  state: 'JOINED',
69
+ intent: {type: ''},
69
70
  intents: [
70
71
  null
71
72
  ],
@@ -42,6 +42,7 @@ import {
42
42
  } from '@webex/plugin-meetings/src/constants';
43
43
  import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
44
44
 
45
+ import locus from '../fixture/locus';
45
46
  import {
46
47
  UserNotJoinedError,
47
48
  MeetingNotActiveError,
@@ -2561,6 +2562,7 @@ describe('plugin-meetings', () => {
2561
2562
  assert.equal(result.failureReason, MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA);
2562
2563
  });
2563
2564
  });
2565
+
2564
2566
  describe('#mediaNegotiatedEvent', () => {
2565
2567
  it('should have #mediaNegotiatedEvent', () => {
2566
2568
  assert.exists(meeting.mediaNegotiatedEvent);
@@ -2638,6 +2640,222 @@ describe('plugin-meetings', () => {
2638
2640
  assert.calledOnce(meeting?.roap?.stop);
2639
2641
  });
2640
2642
  });
2643
+
2644
+ describe('#moveTo', () => {
2645
+ let sandbox;
2646
+
2647
+ beforeEach(() => {
2648
+ sandbox = sinon.createSandbox();
2649
+ sandbox.stub(meeting, 'closeLocalStream');
2650
+ sandbox.stub(meeting, 'closeLocalShare');
2651
+
2652
+ sandbox.stub(meeting.mediaProperties, 'setMediaDirection');
2653
+ sandbox.stub(meeting.mediaProperties, 'unsetMediaTracks');
2654
+
2655
+ sandbox.stub(meeting.reconnectionManager, 'reconnectMedia').returns(Promise.resolve());
2656
+ sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve(MeetingUtil.parseLocusJoin({body: {locus, mediaConnections: []}})));
2657
+ });
2658
+
2659
+ afterEach(() => {
2660
+ sandbox.restore();
2661
+ sandbox = null;
2662
+ });
2663
+
2664
+ it('should throw an error if resourceId not passed', async () => {
2665
+ try {
2666
+ await meeting.moveTo();
2667
+ }
2668
+ catch (err) {
2669
+ assert.instanceOf(err, ParameterError);
2670
+ assert.equal(err.sdkMessage, 'Cannot move call without a resourceId.');
2671
+ }
2672
+ });
2673
+
2674
+ it('should postEvent on moveTo ', async () => {
2675
+ await meeting.moveTo('resourceId');
2676
+ assert.calledWithMatch(Metrics.postEvent, {
2677
+ event: eventType.MEDIA_CAPABILITIES,
2678
+ data: {
2679
+ mediaCapabilities: {
2680
+ rx: {
2681
+ audio: false,
2682
+ share: true,
2683
+ share_audio: false,
2684
+ video: false,
2685
+ whiteboard: false
2686
+ },
2687
+ tx: {
2688
+ audio: false,
2689
+ share: false,
2690
+ share_audio: false,
2691
+ video: false,
2692
+ whiteboard: false
2693
+ }
2694
+ }
2695
+ }
2696
+ });
2697
+ assert.calledWithMatch(Metrics.postEvent, {event: eventType.MOVE_MEDIA});
2698
+ });
2699
+
2700
+ it('should call `MeetingUtil.joinMeetingOptions` with resourceId', async () => {
2701
+ sinon.spy(MeetingUtil, 'joinMeetingOptions');
2702
+ await meeting.moveTo('resourceId');
2703
+
2704
+ assert.calledWith(MeetingUtil.joinMeetingOptions, meeting, {resourceId: 'resourceId', moveToResource: true});
2705
+ });
2706
+
2707
+ it('should reconnectMedia after DX joins after moveTo', async () => {
2708
+ await meeting.moveTo('resourceId');
2709
+
2710
+
2711
+ await meeting.locusInfo.emitScoped(
2712
+ {
2713
+ file: 'locus-info',
2714
+ function: 'updateSelf'
2715
+ },
2716
+ 'SELF_OBSERVING'
2717
+ );
2718
+
2719
+ // beacuse we are calling callback so we need to wait
2720
+
2721
+ assert.called(meeting.closeLocalStream);
2722
+ assert.called(meeting.closeLocalShare);
2723
+
2724
+ // give queued Promise callbacks a chance to run
2725
+ await Promise.resolve();
2726
+
2727
+ assert.called(meeting.mediaProperties.setMediaDirection);
2728
+ assert.called(meeting.mediaProperties.unsetMediaTracks);
2729
+
2730
+ assert.calledWith(meeting.reconnectionManager.reconnectMedia,
2731
+ {
2732
+ mediaDirection: {
2733
+ sendVideo: false,
2734
+ receiveVideo: false,
2735
+ sendAudio: false,
2736
+ receiveAudio: false,
2737
+ sendShare: false,
2738
+ receiveShare: true
2739
+ }
2740
+ });
2741
+ });
2742
+
2743
+ it('should throw an error if moveTo call fails', async () => {
2744
+ MeetingUtil.joinMeeting = sinon.stub().returns(Promise.reject());
2745
+ try {
2746
+ await meeting.moveTo('resourceId');
2747
+ }
2748
+ catch {
2749
+ assert.calledOnce(Metrics.sendBehavioralMetric);
2750
+ assert.calledWith(
2751
+ Metrics.sendBehavioralMetric,
2752
+ BEHAVIORAL_METRICS.MOVE_TO_FAILURE,
2753
+ {
2754
+ correlation_id: meeting.correlationId,
2755
+ locus_id: meeting.locusUrl.split('/').pop(),
2756
+ reason: sinon.match.any,
2757
+ stack: sinon.match.any
2758
+ }
2759
+ );
2760
+ }
2761
+ Metrics.sendBehavioralMetric.reset();
2762
+ meeting.reconnectionManager.reconnectMedia = sinon.stub().returns(Promise.reject());
2763
+ try {
2764
+ await meeting.moveTo('resourceId');
2765
+
2766
+ await meeting.locusInfo.emitScoped(
2767
+ {
2768
+ file: 'locus-info',
2769
+ function: 'updateSelf'
2770
+ },
2771
+ 'SELF_OBSERVING'
2772
+ );
2773
+ }
2774
+ catch {
2775
+ assert.calledOnce(Metrics.sendBehavioralMetric);
2776
+ assert.calledWith(
2777
+ Metrics.sendBehavioralMetric,
2778
+ BEHAVIORAL_METRICS.MOVE_TO_FAILURE,
2779
+ {
2780
+ correlation_id: meeting.correlationId,
2781
+ locus_id: meeting.locusUrl.split('/').pop(),
2782
+ reason: sinon.match.any,
2783
+ stack: sinon.match.any
2784
+ }
2785
+ );
2786
+ }
2787
+ });
2788
+ });
2789
+
2790
+ describe('#moveFrom', () => {
2791
+ let sandbox;
2792
+
2793
+ beforeEach(() => {
2794
+ sandbox = sinon.createSandbox();
2795
+ sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve(MeetingUtil.parseLocusJoin({body: {locus, mediaConnections: []}})));
2796
+ sandbox.stub(MeetingUtil, 'leaveMeeting').returns(Promise.resolve());
2797
+ });
2798
+
2799
+ afterEach(() => {
2800
+ sandbox.restore();
2801
+ sandbox = null;
2802
+ });
2803
+
2804
+ it('should throw an error if resourceId not passed', async () => {
2805
+ try {
2806
+ await meeting.moveFrom();
2807
+ }
2808
+ catch (err) {
2809
+ assert.instanceOf(err, ParameterError);
2810
+
2811
+ assert.equal(err.sdkMessage, 'Cannot move call without a resourceId.');
2812
+ }
2813
+ });
2814
+
2815
+ it('should postEvent on moveFrom ', async () => {
2816
+ await meeting.moveFrom('resourceId');
2817
+
2818
+ assert.calledWithMatch(Metrics.postEvent, {event: eventType.MOVE_MEDIA});
2819
+ });
2820
+
2821
+ it('should call `MeetingUtil.joinMeetingOptions` with resourceId', async () => {
2822
+ sinon.spy(MeetingUtil, 'joinMeetingOptions');
2823
+ await meeting.moveFrom('resourceId');
2824
+
2825
+ assert.calledWith(MeetingUtil.joinMeetingOptions, meeting);
2826
+ assert.calledWith(MeetingUtil.leaveMeeting, meeting, {
2827
+ resourceId: 'resourceId',
2828
+ correlationId: meeting.correlationId,
2829
+ moveMeeting: true
2830
+ });
2831
+
2832
+ assert.calledOnce(Metrics.sendBehavioralMetric);
2833
+ assert.calledWith(
2834
+ Metrics.sendBehavioralMetric,
2835
+ BEHAVIORAL_METRICS.MOVE_FROM_SUCCESS,
2836
+ );
2837
+ });
2838
+
2839
+ it('should throw an error if moveFrom call fails', async () => {
2840
+ MeetingUtil.joinMeeting = sinon.stub().returns(Promise.reject());
2841
+ try {
2842
+ await meeting.moveFrom('resourceId');
2843
+ }
2844
+ catch {
2845
+ assert.calledOnce(Metrics.sendBehavioralMetric);
2846
+ assert.calledWith(
2847
+ Metrics.sendBehavioralMetric,
2848
+ BEHAVIORAL_METRICS.MOVE_FROM_FAILURE,
2849
+ {
2850
+ correlation_id: meeting.correlationId,
2851
+ locus_id: meeting.locusUrl.split('/').pop(),
2852
+ reason: sinon.match.any,
2853
+ stack: sinon.match.any
2854
+ }
2855
+ );
2856
+ }
2857
+ });
2858
+ });
2641
2859
  });
2642
2860
 
2643
2861
  describe('Public Event Triggers', () => {