@webex/plugin-meetings 3.0.0-beta.145 → 3.0.0-beta.147

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 (68) hide show
  1. package/dist/annotation/annotation.types.js.map +1 -1
  2. package/dist/annotation/constants.js +6 -5
  3. package/dist/annotation/constants.js.map +1 -1
  4. package/dist/breakouts/breakout.js +1 -1
  5. package/dist/breakouts/index.js +1 -1
  6. package/dist/common/errors/webex-errors.js +3 -2
  7. package/dist/common/errors/webex-errors.js.map +1 -1
  8. package/dist/config.js +1 -7
  9. package/dist/config.js.map +1 -1
  10. package/dist/constants.js +7 -15
  11. package/dist/constants.js.map +1 -1
  12. package/dist/index.js +6 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/media/index.js +5 -56
  15. package/dist/media/index.js.map +1 -1
  16. package/dist/media/properties.js +15 -93
  17. package/dist/media/properties.js.map +1 -1
  18. package/dist/meeting/index.js +1106 -1876
  19. package/dist/meeting/index.js.map +1 -1
  20. package/dist/meeting/muteState.js +88 -184
  21. package/dist/meeting/muteState.js.map +1 -1
  22. package/dist/meeting/request.js +2 -2
  23. package/dist/meeting/request.js.map +1 -1
  24. package/dist/meeting/util.js +1 -23
  25. package/dist/meeting/util.js.map +1 -1
  26. package/dist/meetings/index.js +1 -2
  27. package/dist/meetings/index.js.map +1 -1
  28. package/dist/reconnection-manager/index.js +153 -134
  29. package/dist/reconnection-manager/index.js.map +1 -1
  30. package/dist/roap/index.js +8 -7
  31. package/dist/roap/index.js.map +1 -1
  32. package/dist/types/annotation/annotation.types.d.ts +9 -1
  33. package/dist/types/annotation/constants.d.ts +5 -5
  34. package/dist/types/common/errors/webex-errors.d.ts +1 -1
  35. package/dist/types/config.d.ts +0 -6
  36. package/dist/types/constants.d.ts +1 -18
  37. package/dist/types/index.d.ts +1 -1
  38. package/dist/types/media/properties.d.ts +16 -38
  39. package/dist/types/meeting/index.d.ts +92 -352
  40. package/dist/types/meeting/muteState.d.ts +36 -38
  41. package/dist/types/meeting/request.d.ts +2 -1
  42. package/dist/types/meeting/util.d.ts +2 -4
  43. package/package.json +19 -19
  44. package/src/annotation/annotation.types.ts +10 -1
  45. package/src/annotation/constants.ts +5 -5
  46. package/src/common/errors/webex-errors.ts +6 -2
  47. package/src/config.ts +0 -6
  48. package/src/constants.ts +1 -14
  49. package/src/index.ts +1 -0
  50. package/src/media/index.ts +10 -53
  51. package/src/media/properties.ts +32 -92
  52. package/src/meeting/index.ts +532 -1564
  53. package/src/meeting/muteState.ts +87 -178
  54. package/src/meeting/request.ts +4 -3
  55. package/src/meeting/util.ts +3 -24
  56. package/src/meetings/index.ts +0 -1
  57. package/src/reconnection-manager/index.ts +4 -9
  58. package/src/roap/index.ts +13 -14
  59. package/test/integration/spec/converged-space-meetings.js +59 -3
  60. package/test/integration/spec/journey.js +330 -256
  61. package/test/integration/spec/space-meeting.js +75 -3
  62. package/test/unit/spec/meeting/index.js +776 -1344
  63. package/test/unit/spec/meeting/muteState.js +238 -394
  64. package/test/unit/spec/meeting/request.js +4 -4
  65. package/test/unit/spec/meeting/utils.js +2 -9
  66. package/test/unit/spec/multistream/receiveSlot.ts +1 -1
  67. package/test/unit/spec/roap/index.ts +2 -2
  68. package/test/utils/integrationTestUtils.js +5 -23
@@ -6,8 +6,8 @@ import {skipInNode} from '@webex/test-helper-mocha';
6
6
  import sinon from 'sinon';
7
7
 
8
8
  import BrowserDetection from '@webex/plugin-meetings/dist/common/browser-detection';
9
+ import {createCameraTrack, createDisplayTrack, createMicrophoneTrack, LocalTrackEvents} from '@webex/plugin-meetings';
9
10
 
10
- import DEFAULT_RESOLUTIONS from '../../../src/config';
11
11
  import testUtils from '../../utils/testUtils';
12
12
  import integrationTestUtils from '../../utils/integrationTestUtils';
13
13
 
@@ -19,6 +19,42 @@ const {isBrowser} = BrowserDetection();
19
19
 
20
20
  let userSet, alice, bob, chris, enumerateSpy, channelUrlA, channelUrlB;
21
21
 
22
+ const localTracks = {
23
+ alice: {
24
+ microphone: undefined,
25
+ camera: undefined,
26
+ screenShare: {
27
+ video: undefined,
28
+ }
29
+ },
30
+ bob: {
31
+ microphone: undefined,
32
+ camera: undefined,
33
+ screenShare: {
34
+ video: undefined,
35
+ }
36
+ },
37
+ chris: {
38
+ microphone: undefined,
39
+ camera: undefined,
40
+ screenShare: {
41
+ video: undefined,
42
+ }
43
+ },
44
+ };
45
+
46
+
47
+ const waitForPublished = (track, expectedPublished, description) => {
48
+ return testUtils.waitForEvents([{
49
+ scope: track,
50
+ event: LocalTrackEvents.PublishedStateUpdate,
51
+ match: ({isPublished}) => {
52
+ console.log(`${description} is now ${isPublished ? 'published': 'not published'}`);
53
+ return (isPublished === expectedPublished);
54
+ }
55
+ }]);
56
+ };
57
+
22
58
  skipInNode(describe)('plugin-meetings', () => {
23
59
  describe('journey', () => {
24
60
  before(() =>
@@ -275,6 +311,11 @@ skipInNode(describe)('plugin-meetings', () => {
275
311
  );
276
312
  });
277
313
 
314
+ it('alice creates local microphone and camera tracks', async () => {
315
+ localTracks.alice.microphone = await createMicrophoneTrack();
316
+ localTracks.alice.camera = await createCameraTrack();
317
+ });
318
+
278
319
  it('alice dials bob and adds media', () =>
279
320
  Promise.all([
280
321
  testUtils.delayedPromise(alice.webex.meetings.create(bob.emailAddress)),
@@ -302,7 +343,7 @@ skipInNode(describe)('plugin-meetings', () => {
302
343
  })
303
344
  .then(() =>
304
345
  Promise.all([
305
- integrationTestUtils.addMedia(alice),
346
+ integrationTestUtils.addMedia(alice, {microphone: localTracks.alice.microphone, camera: localTracks.alice.camera}),
306
347
  testUtils.waitForEvents([
307
348
  {scope: alice.meeting, event: 'meeting:media:local:start', user: alice},
308
349
  ]),
@@ -329,9 +370,14 @@ skipInNode(describe)('plugin-meetings', () => {
329
370
  ]);
330
371
  });
331
372
 
373
+ it('bob creates local microphone and camera tracks', async () => {
374
+ localTracks.bob.microphone = await createMicrophoneTrack();
375
+ localTracks.bob.camera = await createCameraTrack();
376
+ });
377
+
332
378
  it('bob adds media to the meeting', () =>
333
379
  Promise.all([
334
- integrationTestUtils.addMedia(bob),
380
+ integrationTestUtils.addMedia(bob, {microphone: localTracks.bob.microphone, camera: localTracks.bob.camera}),
335
381
  testUtils
336
382
  .waitForEvents([
337
383
  {scope: bob.meeting, event: 'meeting:media:local:start', user: bob},
@@ -373,135 +419,146 @@ skipInNode(describe)('plugin-meetings', () => {
373
419
  assert.exists(alice.meeting.members.selfId, 'selfId not present');
374
420
  });
375
421
 
376
- it('alice Audio Mute ', () => {
422
+ it('alice Audio Mute ', async () => {
377
423
  const checkEvent = (event) =>
378
424
  !!event.delta.updated.find(
379
425
  (member) => alice.meeting.members.selfId === member.id && member.isAudioMuted === true
380
426
  );
381
427
 
382
- return Promise.all([
383
- testUtils.delayedPromise(alice.meeting.muteAudio()),
384
- testUtils.waitForEvents([
385
- {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
386
- ]),
387
- ]).then(() => {
388
- assert.equal(alice.meeting.audio.muted, true);
389
- assert.equal(alice.meeting.isAudioMuted(), true);
390
- });
428
+ await testUtils.waitUntil(2000);
429
+
430
+ const membersUpdate = testUtils.waitForEvents([
431
+ {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
432
+ ]);
433
+
434
+ localTracks.alice.microphone.setMuted(true);
435
+
436
+ await membersUpdate;
437
+
438
+ assert.equal(localTracks.alice.microphone.muted, true);
391
439
  });
392
440
 
393
- it('alice Audio unMute ', () => {
441
+ it('alice Audio unMute ', async () => {
394
442
  const checkEvent = (event) =>
395
443
  !!event.delta.updated.find(
396
444
  (member) => alice.meeting.members.selfId === member.id && member.isAudioMuted === false
397
445
  );
398
446
 
399
- return Promise.all([
400
- testUtils.delayedPromise(alice.meeting.unmuteAudio()),
401
- testUtils.waitForEvents([
402
- {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
403
- ]),
404
- ]).then(() => {
405
- assert.equal(alice.meeting.audio.muted, false);
406
- assert.equal(alice.meeting.isAudioMuted(), false);
407
- });
447
+ await testUtils.waitUntil(2000);
448
+
449
+ const membersUpdate = testUtils.waitForEvents([
450
+ {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
451
+ ]);
452
+
453
+ localTracks.alice.microphone.setMuted(false);
454
+
455
+ await membersUpdate;
456
+
457
+ assert.equal(localTracks.alice.microphone.muted, false);
408
458
  });
409
459
 
410
- // skipped for now, because it fails intermittently, it will be rewritten and re-enabled in SPARK-399695
411
- it.skip('alice Video Mute', () => {
460
+ it('alice video mute', async () => {
412
461
  const checkEvent = (event) =>
413
462
  !!event.delta.updated.find(
414
463
  (member) => alice.meeting.members.selfId === member.id && member.isVideoMuted === true
415
464
  );
416
465
 
417
- return Promise.all([
418
- testUtils.delayedPromise(alice.meeting.muteVideo()),
419
- testUtils.waitForEvents([
420
- {scope: alice.meeting.members, event: 'members:update', match: checkEvent},
421
- ]),
422
- ]).then(() => {
423
- assert.equal(alice.meeting.video.muted, true);
424
- assert.equal(alice.meeting.isVideoMuted(), true);
425
- });
466
+ await testUtils.waitUntil(2000);
467
+
468
+ const membersUpdate = testUtils.waitForEvents([
469
+ {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
470
+ ]);
471
+
472
+ localTracks.alice.camera.setMuted(true);
473
+
474
+ await membersUpdate;
475
+
476
+ assert.equal(localTracks.alice.camera.muted, true);
426
477
  });
427
478
 
428
- // skipped for now, because it fails intermittently, it will be rewritten and re-enabled in SPARK-399695
429
- it.skip('alice video unMute', () => {
479
+ it('alice video unmute', async () => {
430
480
  const checkEvent = (event) =>
431
481
  !!event.delta.updated.find(
432
482
  (member) => alice.meeting.members.selfId === member.id && member.isVideoMuted === false
433
483
  );
434
484
 
435
- return Promise.all([
436
- testUtils.delayedPromise(alice.meeting.unmuteVideo()),
437
- testUtils.waitForEvents([
438
- {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
439
- ]),
440
- ]).then(() => {
441
- assert.equal(alice.meeting.video.muted, false);
442
- assert.equal(alice.meeting.isVideoMuted(), false);
443
- });
485
+ await testUtils.waitUntil(2000);
486
+
487
+ const membersUpdate = testUtils.waitForEvents([
488
+ {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
489
+ ]);
490
+
491
+ localTracks.alice.camera.setMuted(false);
492
+
493
+ await membersUpdate;
494
+
495
+ assert.equal(localTracks.alice.camera.muted, false);
444
496
  });
445
497
 
446
- it('alice update Audio', () => {
498
+ it('alice update Audio', async () => {
447
499
  const oldVideoTrackId = alice.meeting.mediaProperties.videoTrack.id;
448
500
 
449
- return alice.meeting.getMediaStreams({sendAudio: true}).then((response) =>
450
- Promise.all([
451
- testUtils.delayedPromise(
452
- alice.meeting
453
- .updateAudio({
454
- sendAudio: true,
455
- receiveAudio: true,
456
- stream: response[0],
457
- })
458
- .then(() => {
459
- console.log('AUDIO ', alice.meeting.mediaProperties.audioTrack);
460
- assert.equal(
461
- alice.meeting.mediaProperties.audioTrack.id,
462
- response[0].getAudioTracks()[0].id
463
- );
464
- assert.equal(alice.meeting.mediaProperties.videoTrack.id, oldVideoTrackId);
465
- })
466
- ),
467
- testUtils
468
- .waitForEvents([{scope: alice.meeting, event: 'media:ready'}])
469
- .then((response) => {
470
- console.log('MEDIA:READY event ', response[0].result);
471
- assert.equal(response[0].result.type === 'local', true);
472
- }),
473
- ])
474
- );
501
+ const oldMicrophoneTrack = localTracks.alice.microphone;
502
+ const newMicrophoneTrack = await createMicrophoneTrack();
503
+
504
+ assert.equal(oldMicrophoneTrack.published, true);
505
+ assert.notEqual(oldMicrophoneTrack.id, newMicrophoneTrack.id);
506
+
507
+ const oldTrackUnpublished = waitForPublished(oldMicrophoneTrack, false, "Alice AUDIO: old microphone track");
508
+ const newTrackPublished = waitForPublished(newMicrophoneTrack, true, "Alice AUDIO: new microphone track");
509
+
510
+ await testUtils.delayedPromise(
511
+ alice.meeting
512
+ .publishTracks({
513
+ microphone: newMicrophoneTrack,
514
+ })
515
+ .then(() => {
516
+ console.log('Alice AUDIO: new track on meeting object:', alice.meeting.mediaProperties.audioTrack);
517
+ assert.equal(
518
+ alice.meeting.mediaProperties.audioTrack.id,
519
+ newMicrophoneTrack.id
520
+ );
521
+ assert.equal(alice.meeting.mediaProperties.videoTrack.id, oldVideoTrackId);
522
+ })
523
+ );
524
+
525
+ await oldTrackUnpublished;
526
+ await newTrackPublished;
527
+
528
+ localTracks.alice.microphone = newMicrophoneTrack;
475
529
  });
476
530
 
477
- it('alice update video', () => {
531
+ it('alice update video', async () => {
478
532
  const oldAudioTrackId = alice.meeting.mediaProperties.audioTrack.id;
479
533
 
480
- return alice.meeting.getMediaStreams({sendVideo: true}).then((response) =>
481
- Promise.all([
482
- testUtils.delayedPromise(
483
- alice.meeting
484
- .updateVideo({
485
- sendVideo: true,
486
- receiveVideo: true,
487
- stream: response[0],
488
- })
489
- .then(() => {
490
- assert.equal(
491
- alice.meeting.mediaProperties.videoTrack.id,
492
- response[0].getVideoTracks()[0].id
493
- );
494
- assert.equal(alice.meeting.mediaProperties.audioTrack.id, oldAudioTrackId);
495
- })
496
- ),
497
- testUtils
498
- .waitForEvents([{scope: alice.meeting, event: 'media:ready'}])
499
- .then((response) => {
500
- console.log('MEDIA:READY event ', response[0].result);
501
- assert.equal(response[0].result.type === 'local', true);
502
- }),
503
- ])
504
- );
534
+ const oldCameraTrack = localTracks.alice.camera;
535
+ const newCameraTrack = await createCameraTrack();
536
+
537
+ assert.equal(oldCameraTrack.published, true);
538
+ assert.notEqual(oldCameraTrack.id, newCameraTrack.id);
539
+
540
+ const oldTrackUnpublished = waitForPublished(oldCameraTrack, false, "Alice VIDEO: old camera track");
541
+ const newTrackPublished = waitForPublished(newCameraTrack, true, "Alice VIDEO: new camera track");
542
+
543
+ await testUtils.delayedPromise(
544
+ alice.meeting
545
+ .publishTracks({
546
+ camera: newCameraTrack,
547
+ })
548
+ .then(() => {
549
+ console.log('Alice VIDEO: new track on meeting:', alice.meeting.mediaProperties.videoTrack);
550
+ assert.equal(
551
+ alice.meeting.mediaProperties.videoTrack.id,
552
+ newCameraTrack.id
553
+ );
554
+ assert.equal(alice.meeting.mediaProperties.audioTrack.id, oldAudioTrackId);
555
+ })
556
+ );
557
+
558
+ await oldTrackUnpublished;
559
+ await newTrackPublished;
560
+
561
+ localTracks.alice.camera = newCameraTrack;
505
562
  });
506
563
 
507
564
  it('alice mutes bob', () =>
@@ -525,27 +582,25 @@ skipInNode(describe)('plugin-meetings', () => {
525
582
  }),
526
583
  ]));
527
584
 
528
- it('bob audio mute, so alice cannot unmute bob', (done) => {
585
+ it('bob audio mute, so alice cannot unmute bob', async () => {
529
586
  const checkEvent = (event) =>
530
587
  !!event.delta.updated.find(
531
588
  (member) => bob.meeting.members.selfId === member.id && member.isAudioMuted === true
532
589
  );
533
590
 
591
+ const membersUpdate = testUtils.waitForEvents([
592
+ {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
593
+ ]);
594
+
534
595
  // first bob mutes himself
535
- Promise.all([
536
- testUtils.delayedPromise(bob.meeting.muteAudio()),
537
- testUtils.waitForEvents([
538
- {scope: bob.meeting.members, event: 'members:update', match: checkEvent},
539
- ]),
540
- ])
541
- .then(() => {
542
- assert.equal(bob.meeting.audio.muted, true);
543
- assert.equal(bob.meeting.isAudioMuted(), true);
544
- })
545
- // now alice tries to unmmut bob
546
- .then(() =>
547
- testUtils.delayedPromise(alice.meeting.mute(bob.meeting.members.selfId, false))
548
- )
596
+ localTracks.bob.microphone.setMuted(true);
597
+
598
+ await membersUpdate;
599
+
600
+ assert.equal(localTracks.bob.microphone.muted, true);
601
+
602
+ // now alice tries to unmmute bob
603
+ await testUtils.delayedPromise(alice.meeting.mute(bob.meeting.members.selfId, false))
549
604
  // expect the waitForEvents to timeout
550
605
  .then(() =>
551
606
  testUtils.waitForEvents(
@@ -557,126 +612,120 @@ skipInNode(describe)('plugin-meetings', () => {
557
612
  assert.fail('bob received unexpected meeting:self:unmutedByOthers event');
558
613
  })
559
614
  .catch(() => {
560
- assert.equal(bob.meeting.audio.muted, true);
561
- assert.equal(bob.meeting.isAudioMuted(), true);
562
- done();
615
+ assert.equal(localTracks.bob.microphone.muted, true);
563
616
  });
564
617
  });
565
618
 
566
- it('bob audio unmute ', () => {
619
+ it('bob audio unmute ', async () => {
567
620
  const checkEvent = (event) =>
568
621
  !!event.delta.updated.find(
569
622
  (member) => bob.meeting.members.selfId === member.id && member.isAudioMuted === false
570
623
  );
571
624
 
572
- return Promise.all([
573
- testUtils.delayedPromise(bob.meeting.unmuteAudio()),
574
- testUtils.waitForEvents([
575
- {scope: alice.meeting.members, event: 'members:update', match: checkEvent},
576
- ]),
577
- ]).then(() => {
578
- assert.equal(bob.meeting.audio.muted, false);
579
- assert.equal(bob.meeting.isAudioMuted(), false);
580
- });
625
+ const membersUpdate = testUtils.waitForEvents([
626
+ {scope: alice.meeting.members, event: 'members:update', match: checkEvent},
627
+ ]);
628
+
629
+ localTracks.bob.microphone.setMuted(false);
630
+
631
+ await membersUpdate;
632
+
633
+ assert.equal(localTracks.bob.microphone.muted, false);
581
634
  });
582
635
 
583
- it('alice shares the screen with highFrameRate', () =>
584
- Promise.all([
585
- testUtils.delayedPromise(
586
- alice.meeting.shareScreen({sharePreferences: {highFrameRate: true}})
587
- ),
588
- testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:startedSharingLocal'}]),
589
- testUtils
590
- .waitForEvents([{scope: bob.meeting, event: 'meeting:startedSharingRemote'}])
591
- .then((response) => {
592
- assert.equal(response[0].result.memberId, alice.meeting.selfId);
593
- }),
594
- testUtils
595
- .waitForEvents([{scope: bob.meeting.members, event: 'members:update'}])
596
- .then((response) => {
597
- console.log(
598
- 'SCREEN SHARE RESPONSE ',
599
- JSON.stringify(response, testUtils.getCircularReplacer())
600
- );
601
- }),
602
- testUtils
603
- .waitForEvents([{scope: alice.meeting, event: 'media:ready'}])
604
- .then((response) => {
605
- console.log('MEDIA:READY event ', response[0].result);
606
- assert.equal(response[0].result.type === 'localShare', true);
607
- }),
608
- ]).then(() => {
609
- // TODO: Re-eanable Safari when screensharing issues have been resolved
610
- if (!isBrowser('safari')) {
611
- assert.equal(alice.meeting.mediaProperties.shareTrack.underlyingTrack.getConstraints().height, 720);
612
- }
613
- assert.equal(alice.meeting.isSharing, true);
614
- assert.equal(alice.meeting.shareStatus, 'local_share_active');
615
- assert.equal(bob.meeting.shareStatus, 'remote_share_active');
616
- console.log(
617
- 'SCREEN SHARE PARTICIPANTS ',
618
- JSON.stringify(alice.meeting.locusInfo.participants)
619
- );
636
+ it('alice shares the screen with highFrameRate', async () => {
637
+ localTracks.alice.screenShare.video = await createDisplayTrack();
620
638
 
621
- return testUtils.waitUntil(10000);
622
- }));
639
+ const startedSharingLocal = testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:startedSharingLocal'}]);
640
+ const startedSharingRemote = testUtils.waitForEvents([{scope: bob.meeting, event: 'meeting:startedSharingRemote'}])
641
+ .then((response) => {
642
+ assert.equal(response[0].result.memberId, alice.meeting.selfId);
643
+ });
644
+ const bobReceivesMembersUpdate = testUtils.waitForEvents([{scope: bob.meeting.members, event: 'members:update'}])
645
+ .then((response) => {
646
+ console.log(
647
+ 'SCREEN SHARE RESPONSE ',
648
+ JSON.stringify(response, testUtils.getCircularReplacer())
649
+ );
650
+ });
651
+ const screenShareVideoPublished = waitForPublished(localTracks.alice.screenShare.video, true, "alice's screen share video track");
623
652
 
624
- it('bob steals the screen share from alice', () =>
625
- Promise.all([
626
- testUtils.delayedPromise(bob.meeting.shareScreen()),
627
- testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:stoppedSharingLocal'}]),
628
- testUtils.waitForEvents([{scope: bob.meeting, event: 'meeting:startedSharingLocal'}]),
629
- testUtils
630
- .waitForEvents([{scope: alice.meeting, event: 'meeting:startedSharingRemote'}])
631
- .then((response) => {
632
- assert.equal(response[0].result.memberId, bob.meeting.selfId);
633
- }),
634
- testUtils
635
- .waitForEvents([{scope: alice.meeting.members, event: 'members:update'}])
636
- .then((response) => {
637
- console.log(
638
- 'SCREEN SHARE RESPONSE ',
639
- JSON.stringify(response, testUtils.getCircularReplacer())
640
- );
641
- }),
642
- testUtils.waitForEvents([{scope: bob.meeting, event: 'media:ready'}]).then((response) => {
643
- console.log('MEDIA:READY event ', response[0].result);
644
- assert.equal(response[0].result.type === 'localShare', true);
645
- }),
646
- ]).then(() => {
647
- const heightResolution = DEFAULT_RESOLUTIONS.meetings.screenResolution.idealHeight;
653
+ await testUtils.delayedPromise(alice.meeting.publishTracks({screenShare: {video: localTracks.alice.screenShare.video}}));
654
+
655
+ await screenShareVideoPublished;
656
+ await startedSharingLocal;
657
+ await startedSharingRemote;
658
+ await bobReceivesMembersUpdate;
648
659
 
649
- // TODO: Re-eanable Safari when screensharing issues have been resolved
650
- if (!isBrowser('safari')) {
651
- assert.equal(
652
- bob.meeting.mediaProperties.shareTrack.underlyingTrack.getConstraints().height,
653
- heightResolution
660
+ assert.equal(alice.meeting.isSharing, true);
661
+ assert.equal(alice.meeting.shareStatus, 'local_share_active');
662
+ assert.equal(bob.meeting.shareStatus, 'remote_share_active');
663
+ console.log(
664
+ 'SCREEN SHARE PARTICIPANTS ',
665
+ JSON.stringify(alice.meeting.locusInfo.participants)
666
+ );
667
+
668
+ await testUtils.waitUntil(10000);
669
+ });
670
+
671
+ it('bob steals the screen share from alice', async () => {
672
+ localTracks.bob.screenShare.video = await createDisplayTrack();
673
+
674
+ const stoppedSharingLocal = testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:stoppedSharingLocal'}]);
675
+ const startedSharingLocal = testUtils.waitForEvents([{scope: bob.meeting, event: 'meeting:startedSharingLocal'}]);
676
+ const startedSharingRemote = testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:startedSharingRemote'}])
677
+ .then((response) => {
678
+ assert.equal(response[0].result.memberId, bob.meeting.selfId);
679
+ });
680
+ const aliceReceivesMembersUpdate = testUtils.waitForEvents([{scope: alice.meeting.members, event: 'members:update'}])
681
+ .then((response) => {
682
+ console.log(
683
+ 'SCREEN SHARE RESPONSE ',
684
+ JSON.stringify(response, testUtils.getCircularReplacer())
654
685
  );
655
- }
656
- assert.equal(bob.meeting.isSharing, true);
657
- assert.equal(bob.meeting.shareStatus, 'local_share_active');
658
- assert.equal(alice.meeting.shareStatus, 'remote_share_active');
686
+ });
687
+ const aliceScreenShareVideoUnpublished = waitForPublished(localTracks.alice.screenShare.video, false, "alice's screen share video track");
688
+ const bobScreenShareVideoPublished = waitForPublished(localTracks.bob.screenShare.video, true, "bob's screen share video track");
659
689
 
660
- return testUtils.waitUntil(10000);
661
- }));
690
+ await testUtils.delayedPromise(bob.meeting.publishTracks({screenShare: {video: localTracks.bob.screenShare.video}}));
662
691
 
663
- it('bob stops sharing ', () =>
664
- Promise.all([
665
- // Wait for peerConnection to stabalize
666
- testUtils.waitUntil(20000),
667
- testUtils.delayedPromise(
668
- bob.meeting.updateShare({
669
- sendShare: false,
670
- receiveShare: true,
671
- })
672
- ),
673
- testUtils.waitForEvents([{scope: bob.meeting, event: 'meeting:stoppedSharingLocal'}]),
674
- testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:stoppedSharingRemote'}]),
675
- ]).then(() => {
676
- assert.equal(bob.meeting.isSharing, false);
677
- assert.equal(bob.meeting.shareStatus, 'no_share');
678
- assert.equal(alice.meeting.shareStatus, 'no_share');
679
- }));
692
+ await bobScreenShareVideoPublished;
693
+ await aliceScreenShareVideoUnpublished;
694
+ await stoppedSharingLocal;
695
+ await startedSharingLocal;
696
+ await startedSharingRemote;
697
+ await aliceReceivesMembersUpdate;
698
+
699
+ localTracks.alice.screenShare.video.stop();
700
+ localTracks.alice.screenShare.video = undefined;
701
+
702
+ assert.equal(bob.meeting.isSharing, true);
703
+ assert.equal(bob.meeting.shareStatus, 'local_share_active');
704
+ assert.equal(alice.meeting.shareStatus, 'remote_share_active');
705
+
706
+ await testUtils.waitUntil(10000);
707
+ });
708
+
709
+ it('bob stops sharing', async () => {
710
+ const screenShareVideoUnpublished = waitForPublished(localTracks.bob.screenShare.video, false, "bob's screen share video track");
711
+ const stoppedSharingLocal = testUtils.waitForEvents([{scope: bob.meeting, event: 'meeting:stoppedSharingLocal'}]);
712
+ const stoppedSharingRemote = testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:stoppedSharingRemote'}]);
713
+
714
+ await testUtils.delayedPromise(bob.meeting.unpublishTracks([localTracks.bob.screenShare.video]));
715
+
716
+ await screenShareVideoUnpublished;
717
+ await stoppedSharingLocal;
718
+ await stoppedSharingRemote;
719
+
720
+ localTracks.bob.screenShare.video.stop();
721
+ localTracks.bob.screenShare.video = undefined;
722
+
723
+ assert.equal(bob.meeting.isSharing, false);
724
+ assert.equal(bob.meeting.shareStatus, 'no_share');
725
+ assert.equal(alice.meeting.shareStatus, 'no_share');
726
+
727
+ await testUtils.waitUntil(10000);
728
+ });
680
729
 
681
730
  it('alice shares whiteboard A', () =>
682
731
  Promise.all([
@@ -734,7 +783,7 @@ skipInNode(describe)('plugin-meetings', () => {
734
783
  assert.equal(bob.meeting.shareStatus, 'whiteboard_share_active');
735
784
  }));
736
785
 
737
- it('bob stops sharing ', () =>
786
+ it('bob stops sharing again', () =>
738
787
  Promise.all([
739
788
  // Wait for peerConnection to stabalize
740
789
  testUtils.waitUntil(20000),
@@ -779,46 +828,38 @@ skipInNode(describe)('plugin-meetings', () => {
779
828
  assert.equal(bob.meeting.shareStatus, 'whiteboard_share_active');
780
829
  }));
781
830
 
782
- it('bob steals the share from alice with desktop share', () =>
783
- Promise.all([
784
- testUtils.delayedPromise(bob.meeting.shareScreen()),
785
- testUtils.waitForEvents([
786
- {scope: alice.meeting, event: 'meeting:stoppedSharingWhiteboard'},
787
- ]),
788
- testUtils.waitForEvents([{scope: bob.meeting, event: 'meeting:startedSharingLocal'}]),
789
- testUtils
790
- .waitForEvents([{scope: alice.meeting, event: 'meeting:startedSharingRemote'}])
791
- .then((response) => {
792
- assert.equal(response[0].result.memberId, bob.meeting.selfId);
793
- }),
794
- testUtils
795
- .waitForEvents([{scope: alice.meeting.members, event: 'members:update'}])
796
- .then((response) => {
797
- console.log(
798
- 'SCREEN SHARE RESPONSE ',
799
- JSON.stringify(response, testUtils.getCircularReplacer())
800
- );
801
- }),
802
- testUtils.waitForEvents([{scope: bob.meeting, event: 'media:ready'}]).then((response) => {
803
- console.log('MEDIA:READY event ', response[0].result);
804
- assert.equal(response[0].result.type === 'localShare', true);
805
- }),
806
- ]).then(() => {
807
- const heightResolution = DEFAULT_RESOLUTIONS.meetings.screenResolution.idealHeight;
831
+ it('bob steals the share from alice with desktop share', async () => {
832
+ localTracks.bob.screenShare.video = await createDisplayTrack();
808
833
 
809
- // TODO: Re-eanable Safari when screensharing issues have been resolved
810
- if (!isBrowser('safari')) {
811
- assert.equal(
812
- bob.meeting.mediaProperties.shareTrack.underlyingTrack.getConstraints().height,
813
- heightResolution
834
+ const stoppedSharingWhiteboard = testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:stoppedSharingWhiteboard'}]);
835
+ const startedSharingLocal = testUtils.waitForEvents([{scope: bob.meeting, event: 'meeting:startedSharingLocal'}]);
836
+ const startedSharingRemote = testUtils.waitForEvents([{scope: alice.meeting, event: 'meeting:startedSharingRemote'}])
837
+ .then((response) => {
838
+ assert.equal(response[0].result.memberId, bob.meeting.selfId);
839
+ });
840
+ const aliceReceivesMembersUpdate = testUtils.waitForEvents([{scope: alice.meeting.members, event: 'members:update'}])
841
+ .then((response) => {
842
+ console.log(
843
+ 'SCREEN SHARE RESPONSE ',
844
+ JSON.stringify(response, testUtils.getCircularReplacer())
814
845
  );
815
- }
816
- assert.equal(bob.meeting.isSharing, true);
817
- assert.equal(bob.meeting.shareStatus, 'local_share_active');
818
- assert.equal(alice.meeting.shareStatus, 'remote_share_active');
846
+ });
847
+ const bobScreenShareVideoPublished = waitForPublished(localTracks.bob.screenShare.video, true, "bob's screen share video track");
819
848
 
820
- return testUtils.waitUntil(10000);
821
- }));
849
+ await testUtils.delayedPromise(bob.meeting.publishTracks({screenShare: {video: localTracks.bob.screenShare.video}}));
850
+
851
+ await bobScreenShareVideoPublished;
852
+ await stoppedSharingWhiteboard;
853
+ await startedSharingLocal;
854
+ await startedSharingRemote;
855
+ await aliceReceivesMembersUpdate;
856
+
857
+ assert.equal(bob.meeting.isSharing, true);
858
+ assert.equal(bob.meeting.shareStatus, 'local_share_active');
859
+ assert.equal(alice.meeting.shareStatus, 'remote_share_active');
860
+
861
+ await testUtils.waitUntil(10000);
862
+ });
822
863
 
823
864
  it('bob shares whiteboard B', () =>
824
865
  Promise.all([
@@ -889,7 +930,11 @@ skipInNode(describe)('plugin-meetings', () => {
889
930
  );
890
931
  })
891
932
  .then(() => testUtils.waitForStateChange(chris.meeting, 'JOINED'))
892
- .then(() => integrationTestUtils.addMedia(chris))
933
+ .then(async () => {
934
+ localTracks.chris.microphone = await createMicrophoneTrack();
935
+ localTracks.chris.camera = await createCameraTrack();
936
+ })
937
+ .then(() => integrationTestUtils.addMedia(chris, {microphone: localTracks.chris.microphone, camera: localTracks.chris.camera}))
893
938
  .then(() => assert(enumerateSpy.called));
894
939
  })
895
940
  .then(() =>
@@ -936,6 +981,35 @@ skipInNode(describe)('plugin-meetings', () => {
936
981
  assert.equal(bob.webex.meetings.getMeetingByType('sipUri', alice.emailAddress), null);
937
982
  });
938
983
  });
984
+
985
+ it('stop all local tracks', () => {
986
+ if (localTracks.alice.microphone) {
987
+ localTracks.alice.microphone.stop();
988
+ localTracks.alice.microphone = undefined;
989
+ }
990
+ if (localTracks.alice.camera) {
991
+ localTracks.alice.camera.stop();
992
+ localTracks.alice.camera = undefined;
993
+ }
994
+
995
+ if (localTracks.bob.microphone) {
996
+ localTracks.bob.microphone.stop();
997
+ localTracks.bob.microphone = undefined;
998
+ }
999
+ if (localTracks.bob.camera) {
1000
+ localTracks.bob.camera.stop();
1001
+ localTracks.bob.camera = undefined;
1002
+ }
1003
+
1004
+ if (localTracks.chris.microphone) {
1005
+ localTracks.chris.microphone.stop();
1006
+ localTracks.chris.microphone = undefined;
1007
+ }
1008
+ if (localTracks.chris.camera) {
1009
+ localTracks.chris.camera.stop();
1010
+ localTracks.chris.camera = undefined;
1011
+ }
1012
+ });
939
1013
  });
940
1014
  });
941
1015
  });