@webex/plugin-meetings 3.0.0-beta.133 → 3.0.0-beta.135

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 (41) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +46 -35
  3. package/dist/breakouts/index.js.map +1 -1
  4. package/dist/common/logs/logger-proxy.js +1 -1
  5. package/dist/common/logs/logger-proxy.js.map +1 -1
  6. package/dist/constants.js +4 -3
  7. package/dist/constants.js.map +1 -1
  8. package/dist/controls-options-manager/util.js +17 -11
  9. package/dist/controls-options-manager/util.js.map +1 -1
  10. package/dist/locus-info/index.js +0 -8
  11. package/dist/locus-info/index.js.map +1 -1
  12. package/dist/locus-info/parser.js +1 -1
  13. package/dist/locus-info/parser.js.map +1 -1
  14. package/dist/locus-info/selfUtils.js +6 -18
  15. package/dist/locus-info/selfUtils.js.map +1 -1
  16. package/dist/meeting/index.js +9 -7
  17. package/dist/meeting/index.js.map +1 -1
  18. package/dist/meetings/index.js.map +1 -1
  19. package/dist/multistream/remoteMediaManager.js +1 -0
  20. package/dist/multistream/remoteMediaManager.js.map +1 -1
  21. package/dist/reconnection-manager/index.js.map +1 -1
  22. package/dist/roap/request.js.map +1 -1
  23. package/dist/types/constants.d.ts +2 -1
  24. package/package.json +19 -19
  25. package/src/breakouts/index.ts +44 -28
  26. package/src/common/logs/logger-proxy.ts +1 -1
  27. package/src/constants.ts +2 -1
  28. package/src/controls-options-manager/util.ts +16 -11
  29. package/src/locus-info/index.ts +2 -13
  30. package/src/locus-info/parser.ts +1 -1
  31. package/src/locus-info/selfUtils.ts +6 -26
  32. package/src/meeting/index.ts +16 -7
  33. package/src/meetings/index.ts +0 -1
  34. package/src/multistream/remoteMediaManager.ts +1 -0
  35. package/src/reconnection-manager/index.ts +0 -1
  36. package/src/roap/request.ts +0 -1
  37. package/test/unit/spec/breakouts/index.ts +72 -48
  38. package/test/unit/spec/controls-options-manager/util.js +16 -2
  39. package/test/unit/spec/locus-info/index.js +0 -21
  40. package/test/unit/spec/locus-info/selfUtils.js +6 -37
  41. package/test/unit/spec/meeting/index.js +15 -14
@@ -41,10 +41,10 @@ const Breakouts = WebexPlugin.extend({
41
41
  groups: 'array', // appears when create breakouts
42
42
  manageGroups: 'array', // appears when manage breakouts
43
43
  preAssignments: 'array', // appears when getPreAssignments info hasBreakoutPreAssignments = true
44
- shouldFetchPreassignments: 'boolean', // Controlling the lifecycle of the pre-assign API
45
44
  editLock: 'object', // appears when getBreakout info editlock = true
46
45
  intervalID: 'number',
47
46
  meetingId: 'string',
47
+ canManageBreakouts: 'boolean', // appear the ability to manage breakouts
48
48
  },
49
49
  children: {
50
50
  currentBreakoutSession: Breakout,
@@ -80,7 +80,7 @@ const Breakouts = WebexPlugin.extend({
80
80
  cache: false,
81
81
  deps: ['manageGroups'],
82
82
  /**
83
- * Returns the actived group id
83
+ * Returns the active group id
84
84
  * @returns {boolean}
85
85
  */
86
86
  fn() {
@@ -104,6 +104,21 @@ const Breakouts = WebexPlugin.extend({
104
104
  return this.isInMainSession ? this.groups?.[0]?.status : this.status;
105
105
  },
106
106
  },
107
+ shouldQueryPreAssignments: {
108
+ cache: false,
109
+ deps: ['canManageBreakouts', 'enableBreakoutSession', 'hasBreakoutPreAssignments'],
110
+ /**
111
+ * Returns should query preAssignments or not
112
+ * @returns {boolean}
113
+ */
114
+ fn() {
115
+ return !!(
116
+ this.canManageBreakouts &&
117
+ this.enableBreakoutSession &&
118
+ this.hasBreakoutPreAssignments
119
+ );
120
+ },
121
+ },
107
122
  },
108
123
 
109
124
  /**
@@ -116,6 +131,11 @@ const Breakouts = WebexPlugin.extend({
116
131
  this.trigger(BREAKOUTS.EVENTS.BREAKOUTS_CLOSING);
117
132
  }
118
133
  });
134
+ this.listenTo(this, 'change:shouldQueryPreAssignments', () => {
135
+ if (this.shouldQueryPreAssignments && !this.preAssignments) {
136
+ this.queryPreAssignments();
137
+ }
138
+ });
119
139
  this.debouncedQueryRosters = debounce(this.queryRosters, 10, {
120
140
  leading: true,
121
141
  trailing: false,
@@ -156,6 +176,15 @@ const Breakouts = WebexPlugin.extend({
156
176
  }
157
177
  },
158
178
 
179
+ /**
180
+ * Update whether self is moderator/cohost or not
181
+ * @param {boolean} canManageBreakouts
182
+ * @returns {void}
183
+ */
184
+ updateCanManageBreakouts(canManageBreakouts) {
185
+ this.set('canManageBreakouts', canManageBreakouts);
186
+ },
187
+
159
188
  /**
160
189
  * Update the current breakout resource url
161
190
  * @param {string} breakoutServiceUrl
@@ -273,7 +302,6 @@ const Breakouts = WebexPlugin.extend({
273
302
  * @returns {void}
274
303
  */
275
304
  updateBreakout(params) {
276
- const preEnableBreakoutSession = this.get('enableBreakoutSession');
277
305
  this.set(params);
278
306
 
279
307
  // These values are set manually so they are unset when they are not included in params
@@ -295,11 +323,6 @@ const Breakouts = WebexPlugin.extend({
295
323
  [BREAKOUTS.SESSION_STATES.REQUESTED]: false,
296
324
  });
297
325
 
298
- // We need to call queryPreAssignments when enableBreakoutSession become true
299
- if (preEnableBreakoutSession !== params.enableBreakoutSession) {
300
- this.queryPreAssignments(params);
301
- }
302
-
303
326
  if (
304
327
  this.currentBreakoutSession.previous('sessionId') !== this.currentBreakoutSession.sessionId ||
305
328
  this.currentBreakoutSession.previous('groupId') !== this.currentBreakoutSession.groupId
@@ -529,7 +552,6 @@ const Breakouts = WebexPlugin.extend({
529
552
  });
530
553
 
531
554
  this._setManageGroups(breakoutInfo);
532
- this.shouldFetchPreassignments = false;
533
555
 
534
556
  return breakoutInfo;
535
557
  },
@@ -788,27 +810,21 @@ const Breakouts = WebexPlugin.extend({
788
810
  },
789
811
 
790
812
  /**
791
- * The pre-assignments need to be queried when "hasBreakoutPreAssignments" is true
792
- * @param {Object} params
813
+ * query preAssignments
793
814
  * @returns {void}
794
815
  */
795
- queryPreAssignments(params) {
796
- if (!params || !params.enableBreakoutSession || !params.hasBreakoutPreAssignments) {
797
- return;
798
- }
799
- if (!this.shouldFetchPreassignments) {
800
- this.webex
801
- .request({uri: `${this.url}/preassignments`, qs: {locusUrl: btoa(this.locusUrl)}})
802
- .then((result) => {
803
- if (result.body?.groups) {
804
- this.set('preAssignments', result.body.groups);
805
- }
806
- })
807
- .catch((error) => {
808
- LoggerProxy.logger.error('Meeting:breakouts#queryPreAssignments failed', error);
809
- });
810
- this.shouldFetchPreassignments = true;
811
- }
816
+ queryPreAssignments() {
817
+ this.webex
818
+ .request({uri: `${this.url}/preassignments`, qs: {locusUrl: btoa(this.locusUrl)}})
819
+ .then((result) => {
820
+ if (result.body?.groups) {
821
+ this.set('preAssignments', result.body.groups);
822
+ this.trigger(BREAKOUTS.EVENTS.PRE_ASSIGNMENTS_UPDATE);
823
+ }
824
+ })
825
+ .catch((error) => {
826
+ LoggerProxy.logger.error('Meeting:breakouts#queryPreAssignments failed', error);
827
+ });
812
828
  },
813
829
  /**
814
830
  * assign participants dynamically after breakout sessions started,
@@ -1,4 +1,4 @@
1
- /* eslint-disable no-unused-vars */
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
2
  import LoggerConfig from './logger-config';
3
3
 
4
4
  const LoggerProxy: any = {
package/src/constants.ts CHANGED
@@ -318,6 +318,7 @@ export const EVENT_TRIGGERS = {
318
318
  MEETING_BREAKOUTS_ASK_RETURN_TO_MAIN: 'meeting:breakouts:askReturnToMain',
319
319
  MEETING_BREAKOUTS_LEAVE: 'meeting:breakouts:leave',
320
320
  MEETING_BREAKOUTS_ASK_FOR_HELP: 'meeting:breakouts:askForHelp',
321
+ MEETING_BREAKOUTS_PRE_ASSIGNMENTS_UPDATE: 'meeting:breakouts:preAssignmentsUpdate',
321
322
  MEMBERS_UPDATE: 'members:update',
322
323
  MEMBERS_CLEAR: 'members:clear',
323
324
  MEMBERS_CONTENT_UPDATE: 'members:content:update',
@@ -563,6 +564,7 @@ export const BREAKOUTS = {
563
564
  ASK_RETURN_TO_MAIN: 'ASK_RETURN_TO_MAIN',
564
565
  LEAVE_BREAKOUT: 'LEAVE_BREAKOUT',
565
566
  ASK_FOR_HELP: 'ASK_FOR_HELP',
567
+ PRE_ASSIGNMENTS_UPDATE: 'PRE_ASSIGNMENTS_UPDATE',
566
568
  },
567
569
  SESSION_TYPES: {
568
570
  MAIN: 'MAIN',
@@ -633,7 +635,6 @@ export const LOCUSINFO = {
633
635
  SELF_MEETING_BREAKOUTS_CHANGED: 'SELF_MEETING_BREAKOUTS_CHANGED',
634
636
  MEDIA_INACTIVITY: 'MEDIA_INACTIVITY',
635
637
  LINKS_SERVICES: 'LINKS_SERVICES',
636
- SELF_MODERATOR_OR_COHOST_UPGRADE: 'SELF_MODERATOR_OR_COHOST_UPGRADE',
637
638
  },
638
639
  };
639
640
 
@@ -153,17 +153,22 @@ class Utils {
153
153
  ) {
154
154
  const requiredHints = [];
155
155
 
156
- if (control.properties.enabled === true) {
157
- requiredHints.push(DISPLAY_HINTS.ENABLE_REACTIONS);
158
- }
159
- if (control.properties.enabled === false) {
160
- requiredHints.push(DISPLAY_HINTS.DISABLE_REACTIONS);
161
- }
162
- if (control.properties.showDisplayNameWithReactions === true) {
163
- requiredHints.push(DISPLAY_HINTS.ENABLE_SHOW_DISPLAY_NAME);
164
- }
165
- if (control.properties.showDisplayNameWithReactions === false) {
166
- requiredHints.push(DISPLAY_HINTS.DISABLE_SHOW_DISPLAY_NAME);
156
+ // This additional if statement avoids the display hint discrepency due to
157
+ // the service blocking partial requests with this property only.
158
+ if (control.properties.showDisplayNameWithReactions !== undefined) {
159
+ if (control.properties.showDisplayNameWithReactions === true) {
160
+ requiredHints.push(DISPLAY_HINTS.ENABLE_SHOW_DISPLAY_NAME);
161
+ }
162
+ if (control.properties.showDisplayNameWithReactions === false) {
163
+ requiredHints.push(DISPLAY_HINTS.DISABLE_SHOW_DISPLAY_NAME);
164
+ }
165
+ } else {
166
+ if (control.properties.enabled === true) {
167
+ requiredHints.push(DISPLAY_HINTS.ENABLE_REACTIONS);
168
+ }
169
+ if (control.properties.enabled === false) {
170
+ requiredHints.push(DISPLAY_HINTS.DISABLE_REACTIONS);
171
+ }
167
172
  }
168
173
 
169
174
  return Utils.hasHints({requiredHints, displayHints});
@@ -1,4 +1,4 @@
1
- import {isArray, isEqual, assignWith, cloneDeep} from 'lodash';
1
+ import {isEqual, assignWith, cloneDeep} from 'lodash';
2
2
 
3
3
  import LoggerProxy from '../common/logs/logger-proxy';
4
4
  import EventsScope from '../common/events/events-scope';
@@ -1237,18 +1237,7 @@ export default class LocusInfo extends EventsScope {
1237
1237
  {oldRoles: parsedSelves.previous?.roles, newRoles: parsedSelves.current?.roles}
1238
1238
  );
1239
1239
  }
1240
- // When the user upgrades to moderator or cohost
1241
- if (parsedSelves.updates.isUpgradeToModeratorOrCohost) {
1242
- this.emitScoped(
1243
- {
1244
- file: 'locus-info',
1245
- function: 'updateSelf',
1246
- },
1247
- LOCUSINFO.EVENTS.SELF_MODERATOR_OR_COHOST_UPGRADE,
1248
- self
1249
- );
1250
- }
1251
- //
1240
+
1252
1241
  if (parsedSelves.updates.isVideoMutedByOthersChanged) {
1253
1242
  this.emitScoped(
1254
1243
  {
@@ -478,7 +478,7 @@ export default class Parser {
478
478
  * @param {Types~Locus} locus Locus delta
479
479
  * @returns {undefined}
480
480
  */
481
- // eslint-disable-next-line no-unused-vars
481
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
482
482
  onDeltaAction(action: string, locus) {}
483
483
 
484
484
  /**
@@ -14,7 +14,6 @@ import {
14
14
  AUDIO,
15
15
  VIDEO,
16
16
  MediaContent,
17
- SELF_ROLES,
18
17
  } from '../constants';
19
18
  import ParameterError from '../common/errors/parameter';
20
19
 
@@ -109,7 +108,6 @@ SelfUtils.getSelves = (oldSelf, newSelf, deviceId) => {
109
108
  );
110
109
  updates.moderatorChanged = SelfUtils.moderatorChanged(previous, current);
111
110
  updates.isRolesChanged = SelfUtils.isRolesChanged(previous, current);
112
- updates.isUpgradeToModeratorOrCohost = SelfUtils.isUpgradeToModeratorOrCohost(previous, current);
113
111
  updates.isMediaInactiveOrReleased = SelfUtils.wasMediaInactiveOrReleased(previous, current);
114
112
  updates.isUserObserving = SelfUtils.isDeviceObserving(previous, current);
115
113
  updates.layoutChanged = SelfUtils.layoutChanged(previous, current);
@@ -340,38 +338,20 @@ SelfUtils.moderatorChanged = (oldSelf, changedSelf) => {
340
338
  return oldSelf.moderator !== changedSelf.moderator;
341
339
  };
342
340
 
343
- SelfUtils.isRolesChanged = (oldSelf, changedSelf) => {
344
- if (!oldSelf || !changedSelf) {
345
- return false;
346
- }
347
-
348
- return !isEqual(oldSelf.roles, changedSelf.roles);
349
- };
350
341
  /**
342
+ * determine whether the roles of self is changed or not
351
343
  * @param {Object} oldSelf
352
344
  * @param {Object} changedSelf
353
345
  * @returns {Boolean}
354
- * @throws {Error} if changed self was undefined
355
346
  */
356
- SelfUtils.isUpgradeToModeratorOrCohost = (oldSelf, changedSelf) => {
357
- if (!oldSelf) {
358
- return false;
359
- }
347
+ SelfUtils.isRolesChanged = (oldSelf, changedSelf) => {
360
348
  if (!changedSelf) {
361
- throw new ParameterError(
362
- 'New self must be defined to determine if self transitioned moderator or cohost status.'
363
- );
349
+ // no new self means no change
350
+ return false;
364
351
  }
365
- const isAttendeeOnly =
366
- oldSelf.roles.includes(SELF_ROLES.ATTENDEE) &&
367
- !oldSelf.roles.includes(SELF_ROLES.COHOST) &&
368
- !oldSelf.roles.includes(SELF_ROLES.MODERATOR);
369
- const isCohost = changedSelf.roles.includes(SELF_ROLES.COHOST);
370
- const isModerator = changedSelf.roles.includes(SELF_ROLES.MODERATOR);
371
-
372
- return isAttendeeOnly && (isCohost || isModerator);
373
- };
374
352
 
353
+ return !isEqual(oldSelf?.roles, changedSelf?.roles);
354
+ };
375
355
  /**
376
356
  * @param {Object} oldSelf
377
357
  * @param {Object} changedSelf
@@ -2,7 +2,6 @@ import uuid from 'uuid';
2
2
  import {cloneDeep, isEqual, pick, isString, defer, isEmpty} from 'lodash';
3
3
  // @ts-ignore - Fix this
4
4
  import {StatelessWebexPlugin} from '@webex/webex-core';
5
- import {base64} from '@webex/common';
6
5
  import {
7
6
  ConnectionState,
8
7
  Errors,
@@ -1524,6 +1523,17 @@ export default class Meeting extends StatelessWebexPlugin {
1524
1523
  helpEvent
1525
1524
  );
1526
1525
  });
1526
+
1527
+ this.breakouts.on(BREAKOUTS.EVENTS.PRE_ASSIGNMENTS_UPDATE, () => {
1528
+ Trigger.trigger(
1529
+ this,
1530
+ {
1531
+ file: 'meeting/index',
1532
+ function: 'setUpBreakoutsListener',
1533
+ },
1534
+ EVENT_TRIGGERS.MEETING_BREAKOUTS_PRE_ASSIGNMENTS_UPDATE
1535
+ );
1536
+ });
1527
1537
  }
1528
1538
 
1529
1539
  /**
@@ -2923,6 +2933,11 @@ export default class Meeting extends StatelessWebexPlugin {
2923
2933
  });
2924
2934
 
2925
2935
  this.locusInfo.on(LOCUSINFO.EVENTS.SELF_ROLES_CHANGED, (payload) => {
2936
+ const isModeratorOrCohost =
2937
+ payload.newRoles?.includes(SELF_ROLES.MODERATOR) ||
2938
+ payload.newRoles?.includes(SELF_ROLES.COHOST);
2939
+ this.breakouts.updateCanManageBreakouts(isModeratorOrCohost);
2940
+
2926
2941
  Trigger.trigger(
2927
2942
  this,
2928
2943
  {
@@ -2936,12 +2951,6 @@ export default class Meeting extends StatelessWebexPlugin {
2936
2951
  );
2937
2952
  });
2938
2953
 
2939
- // We need to reinitialize when user upgrades to host or cohost
2940
- this.locusInfo.on(LOCUSINFO.EVENTS.SELF_MODERATOR_OR_COHOST_UPGRADE, (payload) => {
2941
- this.breakouts.queryPreAssignments(payload);
2942
- // ...
2943
- });
2944
-
2945
2954
  this.locusInfo.on(LOCUSINFO.EVENTS.SELF_IS_SHARING_BLOCKED_CHANGE, (payload) => {
2946
2955
  Trigger.trigger(
2947
2956
  this,
@@ -43,7 +43,6 @@ import {
43
43
  _CONVERSATION_URL_,
44
44
  CONVERSATION_URL,
45
45
  MEETINGNUMBER,
46
- BREAKOUTS,
47
46
  _JOINED_,
48
47
  _MOVED_,
49
48
  } from '../constants';
@@ -96,6 +96,7 @@ const OnePlusFiveLayout: VideoLayout = {
96
96
  };
97
97
 
98
98
  // A layout with 2 big panes for 2 main active speakers and a strip of 6 small panes for other active speakers:
99
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
99
100
  const TwoMainPlusSixSmallLayout: VideoLayout = {
100
101
  activeSpeakerVideoPaneGroups: [
101
102
  {
@@ -19,7 +19,6 @@ import BEHAVIORAL_METRICS from '../metrics/constants';
19
19
  import ReconnectionError from '../common/errors/reconnection';
20
20
  import ReconnectInProgress from '../common/errors/reconnection-in-progress';
21
21
  import {eventType, reconnection, errorObjects} from '../metrics/config';
22
- import Media from '../media';
23
22
  import Metrics from '../metrics';
24
23
  import Meeting from '../meeting';
25
24
  import {MediaRequestManager} from '../multistream/mediaRequestManager';
@@ -1,4 +1,3 @@
1
- /* global window */
2
1
  // @ts-ignore
3
2
  import {StatelessWebexPlugin} from '@webex/webex-core';
4
3
 
@@ -6,9 +6,7 @@ import sinon from 'sinon';
6
6
  import MockWebex from '@webex/test-helper-mock-webex';
7
7
  import testUtils from '../../../utils/testUtils';
8
8
  import BreakoutEditLockedError from '@webex/plugin-meetings/src/breakouts/edit-lock-error';
9
- import breakoutEvent from "../../../../src/breakouts/events";
10
- import SelfUtils from "../../../../src/locus-info/selfUtils";
11
- import { self } from "../locus-info/selfConstant";
9
+ import breakoutEvent from '../../../../src/breakouts/events';
12
10
 
13
11
  const getBOResponse = (status: string) => {
14
12
  return {
@@ -150,6 +148,16 @@ describe('plugin-meetings', () => {
150
148
  breakouts.breakouts.get('session1').set({requestedLastModifiedTime: "2023-05-09T17:16:01.000Z"});
151
149
  assert.calledOnceWithExactly(breakouts.triggerReturnToMainEvent, breakouts.breakouts.get('session1'));
152
150
  });
151
+
152
+ it('call queryPreAssignments correctly when should query preAssignments is true', () => {
153
+ breakouts.queryPreAssignments = sinon.stub();
154
+ breakouts.set({
155
+ canManageBreakouts: true,
156
+ enableBreakoutSession: true,
157
+ hasBreakoutPreAssignments: true,
158
+ });
159
+ assert.calledThrice(breakouts.queryPreAssignments);
160
+ });
153
161
  });
154
162
 
155
163
  describe('#listenToCurrentSessionTypeChange', () => {
@@ -448,6 +456,18 @@ describe('plugin-meetings', () => {
448
456
  });
449
457
  });
450
458
 
459
+ describe('#updateCanManageBreakouts', () => {
460
+ it('update canManageBreakouts', () => {
461
+ breakouts.updateCanManageBreakouts(true);
462
+
463
+ assert.equal(breakouts.canManageBreakouts, true);
464
+
465
+ breakouts.updateCanManageBreakouts(false);
466
+
467
+ assert.equal(breakouts.canManageBreakouts, false);
468
+ });
469
+ });
470
+
451
471
  describe('#cleanUp', () => {
452
472
  it('stops listening', () => {
453
473
  breakouts.stopListening = sinon.stub();
@@ -504,6 +524,18 @@ describe('plugin-meetings', () => {
504
524
  });
505
525
  });
506
526
 
527
+ describe('#shouldQueryPreAssignments', () => {
528
+ it('returns should query preAssignments depends on status', () => {
529
+ assert.equal(breakouts.shouldQueryPreAssignments, false);
530
+ breakouts.set('canManageBreakouts', true);
531
+ assert.equal(breakouts.shouldQueryPreAssignments, false);
532
+ breakouts.set('enableBreakoutSession', true);
533
+ assert.equal(breakouts.shouldQueryPreAssignments, false);
534
+ breakouts.set('hasBreakoutPreAssignments', true);
535
+ assert.equal(breakouts.shouldQueryPreAssignments, true);
536
+ });
537
+ });
538
+
507
539
  describe('#breakoutStatus', () => {
508
540
  it('return status from groups with session type', () => {
509
541
  breakouts.set('groups', [{status: "OPEN"}]);
@@ -1453,58 +1485,50 @@ describe('plugin-meetings', () => {
1453
1485
  });
1454
1486
  });
1455
1487
 
1456
- describe('queryPreAssignments', () => {
1488
+ describe('#queryPreAssignments', () => {
1457
1489
  it('makes the expected query', async () => {
1458
- webex.request.returns(
1459
- Promise.resolve({
1460
- body: {
1461
- groups: [
1490
+ const mockPreAssignments = [
1491
+ {
1492
+ sessions: [
1462
1493
  {
1463
- sessions: [
1464
- {
1465
- name: 'Breakout session 1',
1466
- assignedEmails: ['a@a.com', 'b@b.com', 'jial2@cisco.com'],
1467
- anyoneCanJoin: false,
1468
- },
1469
- {
1470
- name: 'Breakout session 2',
1471
- anyoneCanJoin: false,
1472
- },
1473
- {
1474
- name: 'Breakout session 3',
1475
- assignedEmails: ['c@c.com'],
1476
- anyoneCanJoin: false,
1477
- },
1478
- ],
1479
- unassignedInvitees: {
1480
- emails: ['d@d.com'],
1481
- },
1482
- type: 'BREAKOUT',
1494
+ name: 'Breakout session 1',
1495
+ assignedEmails: ['aa@aa.com', 'bb@bb.com', 'cc@cc.com'],
1496
+ anyoneCanJoin: false,
1497
+ },
1498
+ {
1499
+ name: 'Breakout session 2',
1500
+ anyoneCanJoin: false,
1501
+ },
1502
+ {
1503
+ name: 'Breakout session 3',
1504
+ assignedEmails: ['cc@cc.com'],
1505
+ anyoneCanJoin: false,
1483
1506
  },
1484
1507
  ],
1508
+ unassignedInvitees: {
1509
+ emails: ['dd@dd.com'],
1510
+ },
1511
+ type: 'BREAKOUT',
1512
+ },
1513
+ ];
1514
+ webex.request.returns(
1515
+ Promise.resolve({
1516
+ body: {
1517
+ groups: mockPreAssignments,
1485
1518
  },
1486
1519
  })
1487
1520
  );
1488
- breakouts.shouldFetchPreassignments = false;
1489
- const result = await breakouts.queryPreAssignments({enableBreakoutSession: true, hasBreakoutPreAssignments: true});
1490
- const arg = webex.request.getCall(0).args[0];
1491
- assert.equal(arg.uri, 'url/preassignments');
1492
- assert.equal(breakouts.preAssignments[0].unassignedInvitees.emails[0], 'd@d.com');
1493
- assert.equal(breakouts.preAssignments[0].sessions[0].name, 'Breakout session 1');
1494
- assert.equal(breakouts.preAssignments[0].sessions[0].anyoneCanJoin, false);
1495
- assert.equal(
1496
- breakouts.preAssignments[0].sessions[0].assignedEmails.toString(),
1497
- ['a@a.com', 'b@b.com', 'jial2@cisco.com'].toString()
1498
- );
1499
- assert.equal(breakouts.preAssignments[0].sessions[1].name, 'Breakout session 2');
1500
- assert.equal(breakouts.preAssignments[0].sessions[1].anyoneCanJoin, false);
1501
- assert.equal(breakouts.preAssignments[0].sessions[1].assignedEmails, undefined);
1502
- assert.equal(breakouts.preAssignments[0].sessions[2].name, 'Breakout session 3');
1503
- assert.equal(breakouts.preAssignments[0].sessions[2].anyoneCanJoin, false);
1504
- assert.equal(breakouts.preAssignments[0].sessions[2].assignedEmails[0], 'c@c.com');
1505
- assert.equal(breakouts.preAssignments[0].unassignedInvitees.emails[0], 'd@d.com');
1506
- assert.equal(breakouts.preAssignments[0].type, 'BREAKOUT');
1507
- assert.equal(breakouts.shouldFetchPreassignments, true);
1521
+ breakouts.set('locusUrl', 'test');
1522
+
1523
+ await breakouts.queryPreAssignments();
1524
+ assert.calledOnceWithExactly(webex.request, {
1525
+ uri: 'url/preassignments',
1526
+ qs: {
1527
+ locusUrl: 'dGVzdA==',
1528
+ }
1529
+ });
1530
+
1531
+ assert.deepEqual(breakouts.preAssignments, mockPreAssignments);
1508
1532
  });
1509
1533
 
1510
1534
  it('rejects when no pre-assignments created for this meeting', async () => {
@@ -203,10 +203,9 @@ describe('plugin-meetings', () => {
203
203
  });
204
204
  });
205
205
 
206
- it('should call hasHints() with all properties after negotiating hints', () => {
206
+ it('should call hasHints() with only enabled hints when respective property is provided', () => {
207
207
  const properties = {
208
208
  enabled: true,
209
- showDisplayNameWithReactions: true,
210
209
  };
211
210
 
212
211
  ControlsOptionsUtil.canUpdateReactions({properties}, []);
@@ -214,6 +213,21 @@ describe('plugin-meetings', () => {
214
213
  assert.calledWith(ControlsOptionsUtil.hasHints, {
215
214
  requiredHints: [
216
215
  DISPLAY_HINTS.ENABLE_REACTIONS,
216
+ ],
217
+ displayHints: [],
218
+ });
219
+ });
220
+
221
+ it('should call hasHints() with only display name hints when respective property is provided', () => {
222
+ const properties = {
223
+ enabled: true,
224
+ showDisplayNameWithReactions: true,
225
+ };
226
+
227
+ ControlsOptionsUtil.canUpdateReactions({properties}, []);
228
+
229
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
230
+ requiredHints: [
217
231
  DISPLAY_HINTS.ENABLE_SHOW_DISPLAY_NAME,
218
232
  ],
219
233
  displayHints: [],
@@ -971,27 +971,6 @@ describe('plugin-meetings', () => {
971
971
  );
972
972
  });
973
973
 
974
- it('should trigger upgradeToModeratorOrCohost for breakouts', () => {
975
-
976
- locusInfo.self = self;
977
- const upgradeToModeratorOrCohost = cloneDeep(self);
978
- upgradeToModeratorOrCohost.roles = ['ATTENDEE','COHOST'];
979
-
980
- locusInfo.webex.internal.device.url = self.deviceUrl;
981
- locusInfo.emitScoped = sinon.stub();
982
- locusInfo.updateSelf(upgradeToModeratorOrCohost, []);
983
-
984
- assert.neverCalledWith(
985
- locusInfo.emitScoped,
986
- {
987
- file: 'locus-info',
988
- function: 'updateSelf',
989
- },
990
- LOCUSINFO.EVENTS.SELF_MODERATOR_OR_COHOST_UPGRADE,
991
- self
992
- );
993
- });
994
-
995
974
  it('should trigger SELF_REMOTE_MUTE_STATUS_UPDATED if muted and disallowUnmute changed', () => {
996
975
  locusInfo.self = self;
997
976
  const selfWithMutedByOthersAndDissalowUnmute = cloneDeep(self);
@@ -316,43 +316,6 @@ describe('plugin-meetings', () => {
316
316
  });
317
317
  });
318
318
 
319
- describe('isUpgradeToModeratorOrCohost', () => {
320
- it('returns true if changed', () => {
321
- assert.equal(
322
- SelfUtils.isUpgradeToModeratorOrCohost({roles: ['ATTENDEE']}, {roles: ['ATTENDEE','MODERATOR']}),
323
- true
324
- );
325
- });
326
-
327
- it('returns true if changed', () => {
328
- assert.equal(
329
- SelfUtils.isUpgradeToModeratorOrCohost({roles: ['ATTENDEE']}, {roles: ['ATTENDEE','COHOST']}),
330
- true
331
- );
332
- });
333
-
334
- it('returns false if changed', () => {
335
- assert.equal(
336
- SelfUtils.isUpgradeToModeratorOrCohost({roles: ['ATTENDEE','MODERATOR']}, {roles: ['ATTENDEE']}),
337
- false
338
- );
339
- });
340
-
341
- it('returns false if changed', () => {
342
- assert.equal(
343
- SelfUtils.isUpgradeToModeratorOrCohost({roles: ['ATTENDEE','COHOST']}, {roles: ['ATTENDEE']}),
344
- false
345
- );
346
- });
347
-
348
- it('returns false if changed', () => {
349
- assert.equal(
350
- SelfUtils.isUpgradeToModeratorOrCohost({roles: ['ATTENDEE','HOST','MODERATOR']}, {roles: ['ATTENDEE']}),
351
- false
352
- );
353
- });
354
- });
355
-
356
319
  describe('getReplacedBreakoutMoveId', () => {
357
320
  const deviceId = 'https://wdm-a.wbx2.com/wdm/api/v1/devices/20eabde3-4254-48da-9a24';
358
321
  const breakoutMoveId = 'e5caeb2c-ffcc-4e06-a08a-1122e7710398';
@@ -395,6 +358,12 @@ describe('plugin-meetings', () => {
395
358
  });
396
359
 
397
360
  describe('isRolesChanged', () => {
361
+ it('should return false if new self is null', () => {
362
+ const parsedSelf = SelfUtils.parse(self);
363
+
364
+ assert.deepEqual(SelfUtils.isRolesChanged(parsedSelf, null), false);
365
+ });
366
+
398
367
  it('should return true if self roles has changed', () => {
399
368
  const parsedSelf = SelfUtils.parse(self);
400
369
  const clonedSelf = cloneDeep(parsedSelf);