@webex/plugin-meetings 1.148.0 → 1.150.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 (37) hide show
  1. package/dist/constants.js +12 -4
  2. package/dist/constants.js.map +1 -1
  3. package/dist/locus-info/mediaSharesUtils.js +88 -11
  4. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  5. package/dist/meeting/index.js +247 -38
  6. package/dist/meeting/index.js.map +1 -1
  7. package/dist/meeting/request.js +17 -41
  8. package/dist/meeting/request.js.map +1 -1
  9. package/dist/meeting-info/index.js +1 -1
  10. package/dist/meeting-info/index.js.map +1 -1
  11. package/dist/meeting-info/util.js +14 -0
  12. package/dist/meeting-info/util.js.map +1 -1
  13. package/dist/meetings/index.js +12 -13
  14. package/dist/meetings/index.js.map +1 -1
  15. package/dist/meetings/util.js +0 -16
  16. package/dist/meetings/util.js.map +1 -1
  17. package/dist/members/index.js +72 -11
  18. package/dist/members/index.js.map +1 -1
  19. package/dist/metrics/config.js +6 -0
  20. package/dist/metrics/config.js.map +1 -1
  21. package/dist/metrics/index.js +6 -0
  22. package/dist/metrics/index.js.map +1 -1
  23. package/package.json +5 -5
  24. package/src/constants.js +9 -2
  25. package/src/locus-info/mediaSharesUtils.js +84 -12
  26. package/src/meeting/index.js +225 -19
  27. package/src/meeting/request.js +50 -29
  28. package/src/meeting-info/index.js +4 -1
  29. package/src/meeting-info/util.js +13 -0
  30. package/src/meetings/index.js +10 -11
  31. package/src/meetings/util.js +0 -14
  32. package/src/members/index.js +80 -11
  33. package/src/metrics/config.js +6 -0
  34. package/src/metrics/index.js +5 -1
  35. package/test/integration/spec/journey.js +141 -5
  36. package/test/integration/spec/space-meeting.js +10 -1
  37. package/test/unit/spec/meeting/index.js +547 -2
@@ -116,15 +116,7 @@ export default class Meetings extends WebexPlugin {
116
116
  */
117
117
  constructor(...args) {
118
118
  super(...args);
119
- /**
120
- * The MeetingInfo object to interact with server
121
- * @instance
122
- * @type {Object}
123
- * @private
124
- * @memberof Meetings
125
- */
126
119
 
127
- this.meetingInfo = null;
128
120
  /**
129
121
  * The Meetings request to interact with server
130
122
  * @instance
@@ -381,6 +373,15 @@ export default class Meetings extends WebexPlugin {
381
373
  LoggerConfig.set(this.config.logging);
382
374
  LoggerProxy.set(this.webex.logger);
383
375
 
376
+ /**
377
+ * The MeetingInfo object to interact with server
378
+ * @instance
379
+ * @type {Object}
380
+ * @private
381
+ * @memberof Meetings
382
+ */
383
+ this.meetingInfo = this.config.experimental.enableUnifiedMeetings ? new MeetingInfoV2(this.webex) : new MeetingInfo(this.webex);
384
+
384
385
  Trigger.trigger(
385
386
  this,
386
387
  {
@@ -407,8 +408,6 @@ export default class Meetings extends WebexPlugin {
407
408
  return Promise.reject(new Error('SDK cannot authorize'));
408
409
  }
409
410
 
410
- this.meetingInfo = this.config.experimental.enableUnifiedMeetings ? new MeetingInfoV2(this.webex) : new MeetingInfo(this.webex);
411
-
412
411
 
413
412
  if (this.registered) {
414
413
  LoggerProxy.logger.info('Meetings:index#register --> INFO, Meetings plugin already registered');
@@ -725,7 +724,7 @@ export default class Meetings extends WebexPlugin {
725
724
  this.meetingCollection.set(meeting);
726
725
 
727
726
  try {
728
- const info = await this.meetingInfo.fetchMeetingInfo(MeetingsUtil.extractDestination(destination, type), type);
727
+ const info = await this.meetingInfo.fetchMeetingInfo(destination, type);
729
728
 
730
729
  meeting.parseMeetingInfo(info);
731
730
  meeting.meetingInfo = info ? info.body : null;
@@ -8,7 +8,6 @@ import {
8
8
  CORRELATION_ID,
9
9
  EVENT_TRIGGERS
10
10
  } from '../constants';
11
- import ParameterError from '../common/errors/parameter';
12
11
  import LoggerProxy from '../common/logs/logger-proxy';
13
12
  import Trigger from '../common/events/trigger-proxy';
14
13
 
@@ -32,19 +31,6 @@ import Trigger from '../common/events/trigger-proxy';
32
31
 
33
32
  const MeetingsUtil = {};
34
33
 
35
- MeetingsUtil.extractDestination = (destination, type) => {
36
- let dest = destination;
37
-
38
- if (type === _LOCUS_ID_) {
39
- if (!(destination && destination.url)) {
40
- throw new ParameterError('You cannot create a meeting by locus without a locus.url defined');
41
- }
42
- dest = destination.url;
43
- }
44
-
45
- return dest;
46
- };
47
-
48
34
  MeetingsUtil.getMeetingAddedType = (type) => (type === _LOCUS_ID_ ? _INCOMING_ : _CREATED_);
49
35
 
50
36
  MeetingsUtil.handleRoapMercury = (envelope, meetingCollection) => {
@@ -4,7 +4,7 @@
4
4
  import {isEmpty} from 'lodash';
5
5
  import {StatelessWebexPlugin} from '@webex/webex-core';
6
6
 
7
- import {MEETINGS, EVENT_TRIGGERS, FLOOR_ACTION, CONTENT} from '../constants';
7
+ import {MEETINGS, EVENT_TRIGGERS, FLOOR_ACTION, CONTENT, WHITEBOARD} from '../constants';
8
8
  import Trigger from '../common/events/trigger-proxy';
9
9
  import Member from '../member';
10
10
  import LoggerProxy from '../common/logs/logger-proxy';
@@ -132,6 +132,14 @@ export default class Members extends StatelessWebexPlugin {
132
132
  * @memberof Members
133
133
  */
134
134
  this.mediaShareContentId = null;
135
+ /**
136
+ * The current mediaShareWhiteboardId for the meeting
137
+ * @instance
138
+ * @type {String}
139
+ * @private
140
+ * @memberof Members
141
+ */
142
+ this.mediaShareWhiteboardId = null;
135
143
  /**
136
144
  * The current recordingId for the meeting, if it exists
137
145
  * @instance
@@ -281,20 +289,49 @@ export default class Members extends StatelessWebexPlugin {
281
289
  * @memberof Members
282
290
  */
283
291
  locusMediaSharesUpdate(payload) {
284
- const currentContent = payload.current;
285
- const previousContent = payload.previous;
292
+ const currentContent = payload.current?.content;
293
+ const previousContent = payload.previous?.content;
294
+ const currentWhiteboard = payload.current?.whiteboard;
295
+ const previousWhiteboard = payload.previous?.whiteboard;
286
296
  let whoSharing = null;
287
297
  let whoStopped = null;
288
298
 
289
- if (currentContent && currentContent.contentId) {
299
+ if (currentContent?.beneficiaryId) {
290
300
  if (currentContent.disposition === FLOOR_ACTION.GRANTED) {
291
- whoSharing = currentContent.contentId;
292
- whoStopped = previousContent && previousContent.contentId;
301
+ whoSharing = currentContent.beneficiaryId;
302
+ this.mediaShareWhiteboardId = null;
303
+ this.mediaShareContentId = whoSharing;
304
+ }
305
+
306
+ if (previousContent?.disposition === FLOOR_ACTION.GRANTED) {
307
+ if (currentContent.disposition === FLOOR_ACTION.RELEASED) {
308
+ whoStopped = currentContent.beneficiaryId;
309
+ this.mediaShareContentId = null;
310
+ }
311
+ else if (currentContent.disposition === FLOOR_ACTION.GRANTED && currentContent.beneficiaryId !== previousContent.beneficiaryId) {
312
+ whoStopped = previousContent.beneficiaryId;
313
+ }
293
314
  }
294
- else if (currentContent.disposition === FLOOR_ACTION.RELEASED) {
295
- whoStopped = currentContent.contentId;
315
+ }
316
+
317
+ if (currentWhiteboard?.beneficiaryId) {
318
+ if (currentWhiteboard.disposition === FLOOR_ACTION.GRANTED) {
319
+ whoSharing = currentWhiteboard.beneficiaryId;
320
+ this.mediaShareContentId = null;
321
+ this.mediaShareWhiteboardId = whoSharing;
322
+ }
323
+
324
+ if (previousWhiteboard?.disposition === FLOOR_ACTION.GRANTED) {
325
+ if (currentWhiteboard.disposition === FLOOR_ACTION.RELEASED) {
326
+ whoStopped = currentWhiteboard.beneficiaryId;
327
+ this.mediaShareWhiteboardId = null;
328
+ }
329
+ else if (currentWhiteboard.disposition === FLOOR_ACTION.GRANTED && currentWhiteboard.beneficiaryId !== previousWhiteboard.beneficiaryId) {
330
+ whoStopped = previousWhiteboard.beneficiaryId;
331
+ }
296
332
  }
297
333
  }
334
+
298
335
  if (whoSharing) {
299
336
  const shareMember = this.membersCollection.get(whoSharing);
300
337
 
@@ -309,7 +346,7 @@ export default class Members extends StatelessWebexPlugin {
309
346
  stopMember.setIsContentSharing(false);
310
347
  }
311
348
  }
312
- this.mediaShareContentId = whoSharing;
349
+
313
350
  Trigger.trigger(
314
351
  this,
315
352
  {
@@ -318,8 +355,8 @@ export default class Members extends StatelessWebexPlugin {
318
355
  },
319
356
  EVENT_TRIGGERS.MEMBERS_CONTENT_UPDATE,
320
357
  {
321
- activeContentSharingId: whoSharing,
322
- endedContentSharingId: whoStopped
358
+ activeSharingId: whoSharing,
359
+ endedSharingId: whoStopped
323
360
  }
324
361
  );
325
362
  }
@@ -524,6 +561,36 @@ export default class Members extends StatelessWebexPlugin {
524
561
  }
525
562
  }
526
563
 
564
+ /**
565
+ * Update the media share whiteboard id
566
+ * @param {Object} locus
567
+ * @param {String} [whiteboardId] optional, takes precedence
568
+ * @throws {Error}
569
+ * @returns {undefined}
570
+ * @memberof Members
571
+ */
572
+ setMediaShareWhiteboardId(locus, whiteboardId) {
573
+ if (whiteboardId) {
574
+ this.mediaShareWhiteboardId = whiteboardId;
575
+ }
576
+ else if (locus) {
577
+ const whiteboardMediaShare =
578
+ locus.mediaShares &&
579
+ locus.mediaShares.length &&
580
+ locus.mediaShares.find((mediaShare) => mediaShare.name === WHITEBOARD);
581
+
582
+ this.mediaShareWhiteboardId =
583
+ (whiteboardMediaShare &&
584
+ whiteboardMediaShare.floor &&
585
+ whiteboardMediaShare.floor.beneficiary &&
586
+ whiteboardMediaShare.floor.beneficiary.id) ||
587
+ null;
588
+ }
589
+ else {
590
+ throw new ParameterError('Setting hostid for the Members module should be done with a locus object or hostId');
591
+ }
592
+ }
593
+
527
594
  /**
528
595
  * Find all the updates, and added members
529
596
  * Removed/left members will end up in updates
@@ -552,6 +619,7 @@ export default class Members extends StatelessWebexPlugin {
552
619
  selfId: this.selfId,
553
620
  hostId: this.hostId,
554
621
  contentSharingId: this.mediaShareContentId,
622
+ whiteboardSharingId: this.mediaShareWhiteboardId,
555
623
  type: this.type
556
624
  })
557
625
  );
@@ -563,6 +631,7 @@ export default class Members extends StatelessWebexPlugin {
563
631
  selfId: this.selfId,
564
632
  hostId: this.hostId,
565
633
  contentSharingId: this.mediaShareContentId,
634
+ whiteboardSharingId: this.mediaShareWhiteboardId,
566
635
  type: this.type
567
636
  })
568
637
  );
@@ -126,6 +126,12 @@ export const eventType = {
126
126
  // Fired when the client changes its local UI/layout to a content sharing view,
127
127
  // because it is expecting to display share media.
128
128
  SHARE_LAYOUT_DISPLAYED: 'client.share.layout.displayed',
129
+ // Fired when the user of the client starts a whiteboard share (e.g. click 'Share Live' button).
130
+ WHITEBOARD_SHARE_INITIATED: 'client.whiteboard.share.initiated',
131
+ // Fired when the meeting floor is released for whiteboard share
132
+ WHITEBOARD_SHARE_STOPPED: 'client.whiteboard.share.stopped',
133
+ // When the client receives a successful response from locus indicating that it has the floor for whiteboard sharing.
134
+ WHITEBOARD_SHARE_FLOOR_GRANTED: 'client.whiteboard.share.floor-granted',
129
135
  MUTED: 'client.muted',
130
136
  UNMUTED: 'client.unmuted',
131
137
  LEAVE: 'client.call.leave',
@@ -51,11 +51,15 @@ const triggerTimers = ({event, meeting, data}) => {
51
51
  case eventType.LOCUS_JOIN_RESPONSE:
52
52
  meeting.setStartSetupDelay(mediaType.AUDIO);
53
53
  meeting.setStartSetupDelay(mediaType.VIDEO);
54
+ meeting.setStartSendingMediaDelay(mediaType.AUDIO);
55
+ meeting.setStartSendingMediaDelay(mediaType.VIDEO);
54
56
  break;
55
57
  case eventType.RECEIVING_MEDIA_START:
56
58
  meeting.setEndSetupDelay(data.mediaType);
57
59
  break;
58
-
60
+ case eventType.SENDING_MEDIA_START:
61
+ meeting.setEndSendingMediaDelay(data.mediaType);
62
+ break;
59
63
  default:
60
64
  break;
61
65
  }
@@ -13,7 +13,7 @@ const webexTestUsers = require('../../utils/webex-test-users');
13
13
 
14
14
  const {isBrowser} = BrowserDetection();
15
15
 
16
- let userSet, alice, bob, chris, enumerateSpy;
16
+ let userSet, alice, bob, chris, enumerateSpy, channelUrlA, channelUrlB;
17
17
 
18
18
  skipInNode(describe)('plugin-meetings', () => {
19
19
  describe('journey', () => {
@@ -32,6 +32,8 @@ skipInNode(describe)('plugin-meetings', () => {
32
32
  alice.webex.meetings.name = 'alice';
33
33
  bob.webex.meetings.name = 'bob';
34
34
  chris.webex.meetings.name = 'chris';
35
+ channelUrlA = 'https://board-a.wbx2.com/board/api/v1/channels/49cfb550-5517-11eb-a2af-1b9e4bc3da13';
36
+ channelUrlB = 'https://board-a.wbx2.com/board/api/v1/channels/977a7330-54f4-11eb-b1ef-91f5eefc7bf3';
35
37
  })
36
38
  .then(() => Promise.all([testUtils.syncAndEndMeeting(alice),
37
39
  testUtils.syncAndEndMeeting(bob)]))
@@ -482,10 +484,7 @@ skipInNode(describe)('plugin-meetings', () => {
482
484
  .then((response) => {
483
485
  assert.equal(response[0].result.memberId, alice.meeting.selfId);
484
486
  }),
485
- testUtils.waitForEvents([{scope: bob.meeting.members, event: 'members:update'}])
486
- .then((response) => {
487
- console.log('SCREEN SHARE RESPONSE ', JSON.stringify(response));
488
- }),
487
+ testUtils.waitForEvents([{scope: bob.meeting.members, event: 'members:update'}]),
489
488
  testUtils.waitForEvents([{scope: alice.meeting, event: 'media:ready'}])
490
489
  .then((response) => {
491
490
  console.log('MEDIA:READY event ', response[0].result);
@@ -553,6 +552,143 @@ skipInNode(describe)('plugin-meetings', () => {
553
552
  assert.equal(alice.meeting.shareStatus, 'no_share');
554
553
  }));
555
554
 
555
+ it('alice shares whiteboard A', () => Promise.all([
556
+ testUtils.delayedPromise(alice.meeting.startWhiteboardShare(channelUrlA)),
557
+ testUtils.waitForEvents([
558
+ {scope: alice.meeting, event: 'meeting:startedSharingWhiteboard'}
559
+ ]),
560
+ testUtils.waitForEvents([{scope: bob.meeting, event: 'meeting:startedSharingWhiteboard'}])
561
+ .then((response) => {
562
+ const {memberId, resourceUrl} = response[0].result;
563
+
564
+ assert.equal(memberId, alice.meeting.selfId);
565
+ assert.equal(resourceUrl, channelUrlA);
566
+ }),
567
+ testUtils.waitForEvents([{scope: bob.meeting.members, event: 'members:update'}])
568
+ .then((response) => {
569
+ console.log('WHITEBOARD SHARE RESPONSE ', JSON.stringify(response));
570
+ })
571
+ ])
572
+ .then(() => {
573
+ assert.equal(alice.meeting.isSharing, false);
574
+ assert.equal(alice.meeting.shareStatus, 'whiteboard_share_active');
575
+ assert.equal(bob.meeting.shareStatus, 'whiteboard_share_active');
576
+ }));
577
+
578
+ it('bob steals share from alice with whiteboard B', () => Promise.all([
579
+ testUtils.delayedPromise(bob.meeting.startWhiteboardShare(channelUrlB)),
580
+ testUtils.waitForEvents([
581
+ {scope: bob.meeting, event: 'meeting:startedSharingWhiteboard'}
582
+ ]),
583
+ testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:startedSharingWhiteboard'}])
584
+ .then((response) => {
585
+ const {memberId, resourceUrl} = response[0].result;
586
+
587
+ assert.equal(memberId, bob.meeting.selfId);
588
+ assert.equal(resourceUrl, channelUrlB);
589
+ }),
590
+ testUtils.waitForEvents([{scope: alice.meeting.members, event: 'members:update'}])
591
+ .then((response) => {
592
+ console.log('WHITEBOARD SHARE RESPONSE ', JSON.stringify(response));
593
+ })
594
+ ])
595
+ .then(() => {
596
+ assert.equal(bob.meeting.isSharing, false);
597
+ assert.equal(alice.meeting.shareStatus, 'whiteboard_share_active');
598
+ assert.equal(bob.meeting.shareStatus, 'whiteboard_share_active');
599
+ }));
600
+
601
+ it('bob stops sharing ', () => Promise.all([
602
+ // Wait for peerConnection to stabalize
603
+ testUtils.waitUntil(20000),
604
+ testUtils.delayedPromise(bob.meeting.stopWhiteboardShare(channelUrlB)),
605
+ testUtils.waitForEvents([{scope: bob.meeting, event: 'meeting:stoppedSharingWhiteboard'}]),
606
+ testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:stoppedSharingWhiteboard'}])
607
+ ])
608
+ .then(() => {
609
+ assert.equal(bob.meeting.isSharing, false);
610
+ assert.equal(bob.meeting.shareStatus, 'no_share');
611
+ assert.equal(alice.meeting.shareStatus, 'no_share');
612
+ }));
613
+
614
+ it('alice shares whiteboard B', () => Promise.all([
615
+ testUtils.delayedPromise(alice.meeting.startWhiteboardShare(channelUrlB)),
616
+ testUtils.waitForEvents([
617
+ {scope: alice.meeting, event: 'meeting:startedSharingWhiteboard'}
618
+ ]),
619
+ testUtils.waitForEvents([{scope: bob.meeting, event: 'meeting:startedSharingWhiteboard'}])
620
+ .then((response) => {
621
+ const {memberId, resourceUrl} = response[0].result;
622
+
623
+ assert.equal(memberId, alice.meeting.selfId);
624
+ assert.equal(resourceUrl, channelUrlB);
625
+ }),
626
+ testUtils.waitForEvents([{scope: bob.meeting.members, event: 'members:update'}])
627
+ .then((response) => {
628
+ console.log('WHITEBOARD SHARE RESPONSE ', JSON.stringify(response));
629
+ })
630
+ ])
631
+ .then(() => {
632
+ assert.equal(alice.meeting.isSharing, false);
633
+ assert.equal(alice.meeting.shareStatus, 'whiteboard_share_active');
634
+ assert.equal(bob.meeting.shareStatus, 'whiteboard_share_active');
635
+ }));
636
+
637
+ it('bob steals the share from alice with desktop share', () => Promise.all([
638
+ testUtils.delayedPromise(bob.meeting.shareScreen()),
639
+ testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:stoppedSharingWhiteboard'}]),
640
+ testUtils.waitForEvents([{scope: bob.meeting, event: 'meeting:startedSharingLocal'}]),
641
+ testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:startedSharingRemote'}])
642
+ .then((response) => {
643
+ assert.equal(response[0].result.memberId, bob.meeting.selfId);
644
+ }),
645
+ testUtils.waitForEvents([{scope: alice.meeting.members, event: 'members:update'}])
646
+ .then((response) => {
647
+ console.log('SCREEN SHARE RESPONSE ', JSON.stringify(response));
648
+ }),
649
+ testUtils.waitForEvents([{scope: bob.meeting, event: 'media:ready'}])
650
+ .then((response) => {
651
+ console.log('MEDIA:READY event ', response[0].result);
652
+ assert.equal(response[0].result.type === 'localShare', true);
653
+ })
654
+ ])
655
+ .then(() => {
656
+ const heightResolution = DEFAULT_RESOLUTIONS.meetings.screenResolution.idealHeight;
657
+
658
+ // TODO: Re-eanable Safari when screensharing issues have been resolved
659
+ if (!isBrowser('safari')) {
660
+ assert.equal(bob.meeting.mediaProperties.shareTrack.getConstraints().height, heightResolution);
661
+ }
662
+ assert.equal(bob.meeting.isSharing, true);
663
+ assert.equal(bob.meeting.shareStatus, 'local_share_active');
664
+ assert.equal(alice.meeting.shareStatus, 'remote_share_active');
665
+
666
+ return testUtils.waitUntil(10000);
667
+ }));
668
+
669
+ it('bob shares whiteboard B', () => Promise.all([
670
+ testUtils.delayedPromise(bob.meeting.startWhiteboardShare(channelUrlB)),
671
+ testUtils.waitForEvents([
672
+ {scope: bob.meeting, event: 'meeting:startedSharingWhiteboard'}
673
+ ]),
674
+ testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:startedSharingWhiteboard'}])
675
+ .then((response) => {
676
+ const {memberId, resourceUrl} = response[0].result;
677
+
678
+ assert.equal(memberId, bob.meeting.selfId);
679
+ assert.equal(resourceUrl, channelUrlB);
680
+ }),
681
+ testUtils.waitForEvents([{scope: alice.meeting.members, event: 'members:update'}])
682
+ .then((response) => {
683
+ console.log('WHITEBOARD SHARE RESPONSE ', JSON.stringify(response));
684
+ })
685
+ ])
686
+ .then(() => {
687
+ assert.equal(bob.meeting.isSharing, false);
688
+ assert.equal(alice.meeting.shareStatus, 'whiteboard_share_active');
689
+ assert.equal(bob.meeting.shareStatus, 'whiteboard_share_active');
690
+ }));
691
+
556
692
  it('alice adds chris as guest to 1:1 meeting', () => Promise.all([
557
693
  testUtils.delayedPromise(alice.meeting.invite({emailAddress: chris.emailAddress})),
558
694
  testUtils.waitForEvents([{scope: chris.webex.meetings, event: 'meeting:added', user: chris}]),
@@ -44,6 +44,15 @@ skipInNode(describe)('plugin-meetings', () => {
44
44
  console.log('CONVERSATION', conversation);
45
45
  space = conversation;
46
46
  })
47
+ .then(async () => {
48
+ const destinationWithType = await alice.webex.meetings.meetingInfo.fetchMeetingInfo(space.url, 'CONVERSATION_URL');
49
+ const destinationNoType = await alice.webex.meetings.meetingInfo.fetchMeetingInfo(space.url);
50
+
51
+ assert.exists(destinationNoType);
52
+ assert.exists(destinationWithType);
53
+ assert.exists(destinationNoType.body.meetingNumber);
54
+ assert.exists(destinationWithType.body.meetingNumber);
55
+ })
47
56
  .then(function aliceStartsMeeting() {
48
57
  return Promise.all([
49
58
  testUtils.delayedPromise(alice.webex.meetings.create(space.url)),
@@ -97,7 +106,7 @@ skipInNode(describe)('plugin-meetings', () => {
97
106
 
98
107
 
99
108
  it('alice adds x user as guest to space meeting', () => Promise.all([
100
- testUtils.delayedPromise(guest.webex.meetings.create(alice.meeting.meetingInfo.uri)),
109
+ testUtils.delayedPromise(guest.webex.meetings.create(alice.meeting.sipUri)),
101
110
  testUtils.waitForEvents([{scope: guest.webex.meetings, event: 'meeting:added', user: guest}])
102
111
  ]).then(() =>
103
112
  Promise.all([