@webex/plugin-meetings 3.8.1-web-workers-keepalive.1 → 3.9.0-webinar5k.1

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 (87) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +1 -1
  3. package/dist/constants.js +8 -2
  4. package/dist/constants.js.map +1 -1
  5. package/dist/hashTree/constants.js +23 -0
  6. package/dist/hashTree/constants.js.map +1 -0
  7. package/dist/hashTree/hashTree.js +516 -0
  8. package/dist/hashTree/hashTree.js.map +1 -0
  9. package/dist/hashTree/hashTreeParser.js +521 -0
  10. package/dist/hashTree/hashTreeParser.js.map +1 -0
  11. package/dist/interpretation/index.js +1 -1
  12. package/dist/interpretation/siLanguage.js +1 -1
  13. package/dist/locus-info/index.js +301 -59
  14. package/dist/locus-info/index.js.map +1 -1
  15. package/dist/meeting/brbState.js +14 -12
  16. package/dist/meeting/brbState.js.map +1 -1
  17. package/dist/meeting/index.js +110 -12
  18. package/dist/meeting/index.js.map +1 -1
  19. package/dist/meeting/muteState.js +2 -5
  20. package/dist/meeting/muteState.js.map +1 -1
  21. package/dist/meeting/request.js +19 -0
  22. package/dist/meeting/request.js.map +1 -1
  23. package/dist/meeting/request.type.js.map +1 -1
  24. package/dist/meeting/util.js +8 -11
  25. package/dist/meeting/util.js.map +1 -1
  26. package/dist/meetings/index.js +6 -2
  27. package/dist/meetings/index.js.map +1 -1
  28. package/dist/member/index.js.map +1 -1
  29. package/dist/member/types.js.map +1 -1
  30. package/dist/members/collection.js +13 -0
  31. package/dist/members/collection.js.map +1 -1
  32. package/dist/members/index.js +44 -23
  33. package/dist/members/index.js.map +1 -1
  34. package/dist/members/request.js +3 -3
  35. package/dist/members/request.js.map +1 -1
  36. package/dist/members/util.js +18 -6
  37. package/dist/members/util.js.map +1 -1
  38. package/dist/multistream/sendSlotManager.js +32 -2
  39. package/dist/multistream/sendSlotManager.js.map +1 -1
  40. package/dist/types/constants.d.ts +6 -0
  41. package/dist/types/hashTree/constants.d.ts +8 -0
  42. package/dist/types/hashTree/hashTree.d.ts +128 -0
  43. package/dist/types/hashTree/hashTreeParser.d.ts +152 -0
  44. package/dist/types/locus-info/index.d.ts +93 -3
  45. package/dist/types/meeting/brbState.d.ts +0 -1
  46. package/dist/types/meeting/index.d.ts +29 -3
  47. package/dist/types/meeting/request.d.ts +9 -1
  48. package/dist/types/meeting/request.type.d.ts +74 -0
  49. package/dist/types/meeting/util.d.ts +3 -3
  50. package/dist/types/member/types.d.ts +1 -0
  51. package/dist/types/members/collection.d.ts +6 -0
  52. package/dist/types/members/index.d.ts +15 -3
  53. package/dist/types/members/request.d.ts +1 -1
  54. package/dist/types/members/util.d.ts +5 -2
  55. package/dist/types/multistream/sendSlotManager.d.ts +16 -0
  56. package/dist/webinar/index.js +1 -1
  57. package/package.json +24 -23
  58. package/src/constants.ts +7 -0
  59. package/src/hashTree/constants.ts +12 -0
  60. package/src/hashTree/hashTree.ts +460 -0
  61. package/src/hashTree/hashTreeParser.ts +556 -0
  62. package/src/locus-info/index.ts +393 -58
  63. package/src/meeting/brbState.ts +9 -7
  64. package/src/meeting/index.ts +104 -6
  65. package/src/meeting/muteState.ts +2 -6
  66. package/src/meeting/request.ts +16 -0
  67. package/src/meeting/request.type.ts +64 -0
  68. package/src/meeting/util.ts +17 -20
  69. package/src/meetings/index.ts +17 -3
  70. package/src/member/index.ts +1 -0
  71. package/src/member/types.ts +1 -0
  72. package/src/members/collection.ts +11 -0
  73. package/src/members/index.ts +33 -7
  74. package/src/members/request.ts +2 -2
  75. package/src/members/util.ts +14 -3
  76. package/src/multistream/sendSlotManager.ts +34 -2
  77. package/test/unit/spec/hashTree/hashTree.ts +394 -0
  78. package/test/unit/spec/hashTree/hashTreeParser.ts +156 -0
  79. package/test/unit/spec/locus-info/index.js +506 -55
  80. package/test/unit/spec/meeting/brbState.ts +9 -9
  81. package/test/unit/spec/meeting/index.js +475 -42
  82. package/test/unit/spec/meeting/request.js +71 -0
  83. package/test/unit/spec/members/index.js +33 -10
  84. package/test/unit/spec/members/request.js +2 -2
  85. package/test/unit/spec/members/utils.js +27 -7
  86. package/test/unit/spec/multistream/sendSlotManager.ts +59 -0
  87. package/test/unit/spec/reachability/index.ts +3 -1
@@ -826,4 +826,75 @@ describe('plugin-meetings', () => {
826
826
  });
827
827
  });
828
828
  });
829
+
830
+ describe('#synchronizeStage', () => {
831
+ [
832
+ ['an unset stage', {overrideDefault: false}],
833
+ [
834
+ 'a minimally set stage',
835
+ {
836
+ overrideDefault: true,
837
+ lockAttendeeViewOnStageOnly: false,
838
+ stageParameters: {
839
+ activeSpeakerProportion: 0.5,
840
+ showActiveSpeaker: {show: false, order: 0},
841
+ stageManagerType: 0,
842
+ },
843
+ },
844
+ ],
845
+ [
846
+ 'a fully set stage',
847
+ {
848
+ overrideDefault: true,
849
+ lockAttendeeViewOnStageOnly: true,
850
+ stageParameters: {
851
+ activeSpeakerProportion: 0.6,
852
+ importantParticipants: [
853
+ {mainCsi: 11111111, participantId: uuidv4(), order: 1},
854
+ {mainCsi: 22222222, participantId: uuidv4(), order: 2},
855
+ {mainCsi: 33333333, participantId: uuidv4(), order: 3},
856
+ {mainCsi: 44444444, participantId: uuidv4(), order: 4},
857
+ {mainCsi: 55555555, participantId: uuidv4(), order: 5},
858
+ {mainCsi: 66666666, participantId: uuidv4(), order: 6},
859
+ {mainCsi: 77777777, participantId: uuidv4(), order: 7},
860
+ {mainCsi: 88888888, participantId: uuidv4(), order: 8},
861
+ ],
862
+ showActiveSpeaker: {show: true, order: 0},
863
+ stageManagerType: 7,
864
+ },
865
+ customLayouts: {
866
+ background: {url: `https://test.wbx2.com/background/${uuidv4()}.jpg`},
867
+ logo: {url: `https://test.wbx2.com/logo/${uuidv4()}.png`, position: 'UpperMiddle'},
868
+ },
869
+ nameLabelStyle: {
870
+ accentColor: '#00A3FF',
871
+ background: {color: 'rgba(0, 163, 255, 1)'},
872
+ border: {color: 'rgba(0, 163, 255, 1)'},
873
+ content: {
874
+ displayName: {color: 'rgba(255, 255, 255, 0.95)'},
875
+ subtitle: {color: 'rgba(255, 255, 255, 0.7)'},
876
+ },
877
+ decoration: {color: 'rgba(255, 255, 255, 0.95)'},
878
+ fadeOut: {delay: 15},
879
+ type: 'PrimaryInverted',
880
+ },
881
+ },
882
+ ],
883
+ ].forEach(([description, videoLayout]) => {
884
+ it(`sends request to synchronize the stage with ${description} video layout`, async () => {
885
+ const locusUrl = `https://locus-test.wbx2.com/locus/api/v1/loci/${uuidv4()}`;
886
+
887
+ const synchronizePromise = meetingsRequest.synchronizeStage(locusUrl, videoLayout);
888
+
889
+ assert.exists(synchronizePromise.then);
890
+ await synchronizePromise;
891
+
892
+ checkRequest({
893
+ method: 'PATCH',
894
+ uri: `${locusUrl}/controls`,
895
+ body: {videoLayout},
896
+ });
897
+ });
898
+ });
899
+ });
829
900
  });
@@ -176,6 +176,20 @@ describe('plugin-meetings', () => {
176
176
  assert.calledOnce(MembersUtil.isInvalidInvitee);
177
177
  assert.isFalse(MembersUtil.isInvalidInvitee({email: 'sip:test@cisco.com'}), 'SIP email should be valid');
178
178
  });
179
+
180
+ it('should accept valid phone with isInternalNumber', async () => {
181
+ sandbox.spy(MembersUtil, 'isInvalidInvitee');
182
+
183
+ const members = createMembers({url: true});
184
+
185
+ await members.addMember({phoneNumber: '+8618578675309', isInternalNumber: false});
186
+
187
+ assert.calledOnce(MembersUtil.isInvalidInvitee);
188
+ assert.isFalse(MembersUtil.isInvalidInvitee({ phoneNumber: '+8618578675309', isInternalNumber: false }));
189
+ assert.isTrue(MembersUtil.isInvalidInvitee({ phoneNumber: '18578675309', isInternalNumber: false }));
190
+ assert.isFalse(MembersUtil.isInvalidInvitee({phoneNumber: '18578675309', isInternalNumber: true}));
191
+ assert.isTrue(MembersUtil.isInvalidInvitee({phoneNumber: '+8618578675309', isInternalNumber: true}));
192
+ });
179
193
  });
180
194
 
181
195
  describe('#admitMembers', () => {
@@ -293,7 +307,7 @@ describe('plugin-meetings', () => {
293
307
  },
294
308
  EVENT_TRIGGERS.MEMBERS_UPDATE,
295
309
  {
296
- delta: {added: [], updated: []},
310
+ delta: {added: [], updated: [], removedIds: []},
297
311
  full: {},
298
312
  isReplace: true,
299
313
  }
@@ -465,29 +479,38 @@ describe('plugin-meetings', () => {
465
479
  });
466
480
  });
467
481
 
468
- describe('#cancelSIPInvite', () => {
482
+ describe('#cancelInviteByMemberId', () => {
469
483
  const memberId = uuid.v4();
470
- it('should invoke cancelSIPInviteOptions from MembersUtil when cancelSIPInvite is called with valid params', async () => {
471
- sandbox.spy(MembersUtil, 'cancelSIPInviteOptions');
484
+ it('should invoke cancelInviteByMemberIdOptions from MembersUtil when cancelInviteByMemberId is called with valid params', async () => {
485
+ sandbox.spy(MembersUtil, 'cancelInviteByMemberIdOptions');
486
+
487
+ const members = createMembers({url: url1});
488
+
489
+ await members.cancelInviteByMemberId({memberId});
490
+ assert.calledOnce(MembersUtil.cancelInviteByMemberIdOptions);
491
+ });
492
+
493
+ it('should invoke cancelInviteByMemberIdOptions from MembersUtil when cancelInviteByMemberId is called with isInternalNumber', async () => {
494
+ sandbox.spy(MembersUtil, 'cancelInviteByMemberIdOptions');
472
495
 
473
496
  const members = createMembers({url: url1});
474
497
 
475
- await members.cancelSIPInvite({memberId});
476
- assert.calledOnce(MembersUtil.cancelSIPInviteOptions);
498
+ await members.cancelInviteByMemberId({memberId, isInternalNumber: true});
499
+ assert.calledOnce(MembersUtil.cancelInviteByMemberIdOptions);
477
500
  });
478
501
 
479
502
  it('should throw a rejection if there is no locus url', async () => {
480
503
  const members = createMembers({url: false});
481
504
 
482
- assert.isRejected(members.cancelSIPInvite({memberId}));
505
+ assert.isRejected(members.cancelInviteByMemberId({memberId}));
483
506
  });
484
507
 
485
508
  it('should throw a rejection if memberId is not provided', async () => {
486
509
  const members = createMembers({url: url1});
487
510
 
488
- assert.isRejected(members.cancelSIPInvite({}));
489
- assert.isRejected(members.cancelSIPInvite({memberId: null}));
490
- assert.isRejected(members.cancelSIPInvite({memberId: undefined}));
511
+ assert.isRejected(members.cancelInviteByMemberId({}));
512
+ assert.isRejected(members.cancelInviteByMemberId({memberId: null}));
513
+ assert.isRejected(members.cancelInviteByMemberId({memberId: undefined}));
491
514
  });
492
515
  });
493
516
 
@@ -221,7 +221,7 @@ describe('plugin-meetings', () => {
221
221
  });
222
222
  });
223
223
 
224
- describe('#cancelSIPInvite', () => {
224
+ describe('#cancelInviteByMemberId', () => {
225
225
  const memberId = uuid.v4();
226
226
  it('sends a PUT to the locus endpoint', async () => {
227
227
  const options = {
@@ -231,7 +231,7 @@ describe('plugin-meetings', () => {
231
231
  locusUrl: url1,
232
232
  };
233
233
 
234
- await membersRequest.cancelSIPInvite(options);
234
+ await membersRequest.cancelInviteByMemberId(options);
235
235
 
236
236
  checkRequest({
237
237
  method: 'PUT',
@@ -302,6 +302,26 @@ describe('plugin-meetings', () => {
302
302
  });
303
303
  });
304
304
 
305
+ it('returns the correct body with phone number and isInternalNumber', () => {
306
+ const options = {
307
+ invitee: {
308
+ phoneNumber: '1234567890',
309
+ isInternalNumber: false
310
+ },
311
+ alertIfActive: false,
312
+ };
313
+
314
+ assert.deepEqual(MembersUtil.getAddMemberBody(options), {
315
+ invitees: [
316
+ {
317
+ address: '1234567890',
318
+ isInternalNumber: false
319
+ },
320
+ ],
321
+ alertIfActive: false,
322
+ });
323
+ });
324
+
305
325
  it('returns the correct body with fallback to email', () => {
306
326
  const options = {
307
327
  invitee: {
@@ -391,14 +411,14 @@ describe('plugin-meetings', () => {
391
411
  });
392
412
  });
393
413
 
394
- describe('#cancelSIPInviteOptions', () => {
414
+ describe('#cancelInviteByMemberIdOptions', () => {
395
415
  it('returns the correct options', () => {
396
416
  const locusUrl = 'TestLocusUrl';
397
417
  const memberId = 'test';
398
- const invitee = {memberId};
418
+ const invitee = {memberId, isInternalNumber: false};
399
419
 
400
420
  assert.deepEqual(
401
- MembersUtil.cancelSIPInviteOptions(
421
+ MembersUtil.cancelInviteByMemberIdOptions(
402
422
  invitee,
403
423
  locusUrl
404
424
  ),
@@ -410,22 +430,22 @@ describe('plugin-meetings', () => {
410
430
  });
411
431
  });
412
432
 
413
- describe('#generateCancelSIPInviteRequestParams', () => {
433
+ describe('#generateCancelInviteByMemberIdRequestParams', () => {
414
434
  it('returns the correct params', () => {
415
435
  const locusUrl = 'TestLocusUrl';
416
436
  const memberId = 'test';
417
437
  const options = {
418
438
  locusUrl,
419
- invitee: {memberId}
439
+ invitee: {memberId, isInternalNumber: false}
420
440
  };
421
441
  const body = {
422
442
  actionType: 'REMOVE',
423
- invitees: [{address: options.invitee.memberId}],
443
+ invitees: [{address: options.invitee.memberId, isInternalNumber: false}],
424
444
  };
425
445
 
426
446
  const uri = options.locusUrl;
427
447
 
428
- assert.deepEqual(MembersUtil.generateCancelSIPInviteRequestParams(options), {
448
+ assert.deepEqual(MembersUtil.generateCancelInviteByMemberIdRequestParams(options), {
429
449
  method: HTTP_VERBS.PUT,
430
450
  uri,
431
451
  body,
@@ -272,4 +272,63 @@ describe('SendSlotsManager', () => {
272
272
  expect(() => sendSlotsManager.getSlot(MediaType.VideoSlides)).to.throw();
273
273
  });
274
274
  });
275
+
276
+ describe('sourceStateOverride', () => {
277
+ let mediaConnection: MultistreamRoapMediaConnection;
278
+ beforeEach(() => {
279
+ mediaConnection = {
280
+ createSendSlot: sinon.stub().returns({
281
+ setSourceStateOverride: sinon.stub().resolves(),
282
+ clearSourceStateOverride: sinon.stub().resolves(),
283
+ }),
284
+ } as MultistreamRoapMediaConnection;
285
+ });
286
+
287
+ it(`can set source state override for ${MediaType.VideoMain}`, () => {
288
+ const slot: any = sendSlotsManager.createSlot(mediaConnection, MediaType.VideoMain);
289
+
290
+ const set = () => sendSlotsManager.setSourceStateOverride(MediaType.VideoMain, 'away');
291
+
292
+ expect(set).not.to.throw();
293
+ expect(slot.setSourceStateOverride.calledWith('away')).to.be.true;
294
+ });
295
+
296
+ [MediaType.VideoSlides, MediaType.AudioMain, MediaType.AudioSlides].forEach((mediaType) => {
297
+ it(`can't set source state override for ${mediaType}`, () => {
298
+ const slot: any = sendSlotsManager.createSlot(mediaConnection, mediaType);
299
+
300
+ const set = () => sendSlotsManager.setSourceStateOverride(mediaType, 'away');
301
+
302
+ expect(set).to.throw();
303
+ expect(slot.setSourceStateOverride.called).to.be.false;
304
+ });
305
+ });
306
+
307
+ it("can't set source state override for non-existing slot", () => {
308
+ const set = () => sendSlotsManager.setSourceStateOverride(MediaType.VideoMain, 'away');
309
+ expect(set).to.throw(`Slot for ${MediaType.VideoMain} does not exist`);
310
+ });
311
+
312
+ it('can clear source state override', () => {
313
+ const slot: any = sendSlotsManager.createSlot(mediaConnection, MediaType.VideoMain);
314
+ sendSlotsManager.setSourceStateOverride(MediaType.VideoMain, 'away');
315
+
316
+ expect(slot.setSourceStateOverride.calledWith('away')).to.be.true;
317
+ expect(slot.clearSourceStateOverride.called).to.be.false;
318
+
319
+ sendSlotsManager.setSourceStateOverride(MediaType.VideoMain, null);
320
+ expect(slot.clearSourceStateOverride.called).to.be.true;
321
+ });
322
+
323
+ it("won't set source state override if it didn't change", () => {
324
+ const slot: any = sendSlotsManager.createSlot(mediaConnection, MediaType.VideoMain);
325
+ sendSlotsManager.setSourceStateOverride(MediaType.VideoMain, 'away');
326
+
327
+ expect(slot.setSourceStateOverride.calledWith('away')).to.be.true;
328
+ slot.setSourceStateOverride.resetHistory();
329
+
330
+ sendSlotsManager.setSourceStateOverride(MediaType.VideoMain, 'away');
331
+ expect(slot.setSourceStateOverride.called).to.be.false;
332
+ });
333
+ });
275
334
  });
@@ -3,7 +3,9 @@ import MockWebex from '@webex/test-helper-mock-webex';
3
3
  import sinon from 'sinon';
4
4
  import EventEmitter from 'events';
5
5
  import testUtils from '../../../utils/testUtils';
6
- import Reachability, {ReachabilityResultsForBackend} from '@webex/plugin-meetings/src/reachability/';
6
+ import Reachability, {
7
+ ReachabilityResultsForBackend,
8
+ } from '@webex/plugin-meetings/src/reachability/';
7
9
  import {ClusterNode} from '../../../../src/reachability/request';
8
10
  import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
9
11
  import * as ClusterReachabilityModule from '@webex/plugin-meetings/src/reachability/clusterReachability';