@webex/plugin-meetings 3.0.0-beta.93 → 3.0.0-beta.95

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 (50) hide show
  1. package/dist/breakouts/breakout.js +21 -25
  2. package/dist/breakouts/breakout.js.map +1 -1
  3. package/dist/breakouts/events.js +43 -0
  4. package/dist/breakouts/events.js.map +1 -0
  5. package/dist/breakouts/index.js +100 -55
  6. package/dist/breakouts/index.js.map +1 -1
  7. package/dist/constants.js +3 -1
  8. package/dist/constants.js.map +1 -1
  9. package/dist/controls-options-manager/index.js +19 -14
  10. package/dist/controls-options-manager/index.js.map +1 -1
  11. package/dist/locus-info/index.js +5 -3
  12. package/dist/locus-info/index.js.map +1 -1
  13. package/dist/locus-info/selfUtils.js +12 -0
  14. package/dist/locus-info/selfUtils.js.map +1 -1
  15. package/dist/meeting/in-meeting-actions.js +27 -3
  16. package/dist/meeting/in-meeting-actions.js.map +1 -1
  17. package/dist/meeting/index.js +59 -2
  18. package/dist/meeting/index.js.map +1 -1
  19. package/dist/meeting/util.js +0 -9
  20. package/dist/meeting/util.js.map +1 -1
  21. package/dist/metrics/config.js +3 -2
  22. package/dist/metrics/config.js.map +1 -1
  23. package/dist/types/breakouts/events.d.ts +2 -0
  24. package/dist/types/constants.d.ts +2 -0
  25. package/dist/types/controls-options-manager/index.d.ts +1 -1
  26. package/dist/types/locus-info/index.d.ts +2 -1
  27. package/dist/types/meeting/in-meeting-actions.d.ts +26 -2
  28. package/dist/types/metrics/config.d.ts +3 -2
  29. package/package.json +19 -19
  30. package/src/breakouts/breakout.ts +9 -22
  31. package/src/breakouts/events.ts +37 -0
  32. package/src/breakouts/index.ts +53 -11
  33. package/src/constants.ts +2 -0
  34. package/src/controls-options-manager/index.ts +13 -10
  35. package/src/locus-info/index.ts +8 -4
  36. package/src/locus-info/selfUtils.ts +10 -0
  37. package/src/meeting/in-meeting-actions.ts +52 -4
  38. package/src/meeting/index.ts +65 -4
  39. package/src/meeting/util.ts +0 -11
  40. package/src/metrics/config.ts +3 -2
  41. package/test/unit/spec/breakouts/breakout.ts +27 -21
  42. package/test/unit/spec/breakouts/events.ts +77 -0
  43. package/test/unit/spec/breakouts/index.ts +161 -106
  44. package/test/unit/spec/controls-options-manager/index.js +8 -1
  45. package/test/unit/spec/locus-info/index.js +7 -3
  46. package/test/unit/spec/locus-info/selfConstant.js +9 -0
  47. package/test/unit/spec/locus-info/selfUtils.js +45 -0
  48. package/test/unit/spec/meeting/in-meeting-actions.ts +26 -2
  49. package/test/unit/spec/meeting/index.js +74 -3
  50. package/test/unit/spec/meeting/utils.js +0 -21
@@ -6,6 +6,9 @@ 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
12
 
10
13
  const getBOResponse = (status: string) => {
11
14
  return {
@@ -94,6 +97,8 @@ describe('plugin-meetings', () => {
94
97
  breakouts.locusUrl = 'locusUrl';
95
98
  breakouts.breakoutServiceUrl = 'breakoutServiceUrl';
96
99
  webex.request = sinon.stub().returns(Promise.resolve('REQUEST_RETURN_VALUE'));
100
+ webex.meetings = {};
101
+ webex.meetings.getMeetingByType = sinon.stub();
97
102
  });
98
103
 
99
104
  describe('#initialize', () => {
@@ -122,6 +127,19 @@ describe('plugin-meetings', () => {
122
127
 
123
128
  assert.calledOnceWithExactly(breakouts.debouncedQueryRosters);
124
129
  });
130
+
131
+ it('call triggerReturnToMainEvent correctly when requested breakout add', () => {
132
+ breakouts.triggerReturnToMainEvent = sinon.stub();
133
+ breakouts.breakouts.add({sessionId: 'session1', sessionType: 'MAIN'});
134
+ assert.calledOnceWithExactly(breakouts.triggerReturnToMainEvent, breakouts.breakouts.get('session1'));
135
+ });
136
+
137
+ it('call triggerReturnToMainEvent correctly when breakout requestedLastModifiedTime change', () => {
138
+ breakouts.breakouts.add({sessionId: 'session1', sessionType: 'MAIN'});
139
+ breakouts.triggerReturnToMainEvent = sinon.stub();
140
+ breakouts.breakouts.get('session1').set({requestedLastModifiedTime: "2023-05-09T17:16:01.000Z"});
141
+ assert.calledOnceWithExactly(breakouts.triggerReturnToMainEvent, breakouts.breakouts.get('session1'));
142
+ });
125
143
  });
126
144
 
127
145
  describe('#listenToCurrentSessionTypeChange', () => {
@@ -130,7 +148,7 @@ describe('plugin-meetings', () => {
130
148
  breakouts.currentBreakoutSession.set({sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT})
131
149
  breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
132
150
  breakouts.currentBreakoutSession.set({sessionType: BREAKOUTS.SESSION_TYPES.MAIN});
133
-
151
+
134
152
  assert.calledOnceWithExactly(handler);
135
153
 
136
154
  breakouts.stopListening(breakouts, BREAKOUTS.EVENTS.LEAVE_BREAKOUT, handler);
@@ -216,6 +234,33 @@ describe('plugin-meetings', () => {
216
234
  });
217
235
  });
218
236
 
237
+ describe('#listenToBreakoutHelp', () => {
238
+ it('triggers ask for help event when a help received', () => {
239
+ const call = webex.internal.mercury.on.getCall(1);
240
+ const callback = call.args[1];
241
+
242
+ assert.equal(call.args[0], 'event:breakout.help');
243
+
244
+ let data;
245
+
246
+ breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.ASK_FOR_HELP, (eventData) => {
247
+ data = eventData;
248
+ });
249
+
250
+ callback({
251
+ data: {
252
+ participant: 'participant',
253
+ sessionId: 'sessionId'
254
+ },
255
+ });
256
+
257
+ assert.deepEqual(data, {
258
+ participant: 'participant',
259
+ sessionId: 'sessionId',
260
+ });
261
+ });
262
+ });
263
+
219
264
  describe('#updateBreakout', () => {
220
265
  it('updates the current breakout session', () => {
221
266
  breakouts.updateBreakout({
@@ -265,6 +310,61 @@ describe('plugin-meetings', () => {
265
310
  breakouts.updateBreakout({})
266
311
  assert.equal(breakouts.startTime, undefined);
267
312
  })
313
+
314
+ it('updates the current breakout session, call onBreakoutJoinResponse when session changed', () => {
315
+ breakouts.webex.meetings = {
316
+ getMeetingByType: sinon.stub().returns({
317
+ id: 'meeting-id'
318
+ })
319
+ };
320
+ breakoutEvent.onBreakoutJoinResponse = sinon.stub();
321
+ breakouts.currentBreakoutSession.sessionId = "sessionId-old";
322
+ breakouts.updateBreakout({
323
+ sessionId: 'sessionId-new',
324
+ groupId: 'groupId',
325
+ sessionType: 'sessionType',
326
+ url: 'url',
327
+ name: 'name',
328
+ allowBackToMain: true,
329
+ delayCloseTime: 10,
330
+ enableBreakoutSession: true,
331
+ startTime: 'startTime',
332
+ status: 'active',
333
+ locusUrl: 'locusUrl',
334
+ breakoutMoveId: 'breakoutMoveId',
335
+ });
336
+
337
+ assert.calledOnce(breakoutEvent.onBreakoutJoinResponse);
338
+
339
+ });
340
+
341
+ it('updates the current breakout session, not call onBreakoutJoinResponse when session no changed', () => {
342
+ breakouts.webex.meetings = {
343
+ getMeetingByType: sinon.stub().returns({
344
+ id: 'meeting-id'
345
+ })
346
+ };
347
+ breakoutEvent.onBreakoutJoinResponse = sinon.stub();
348
+ breakouts.currentBreakoutSession.sessionId = "sessionId";
349
+ breakouts.currentBreakoutSession.groupId = "groupId";
350
+ breakouts.updateBreakout({
351
+ sessionId: 'sessionId',
352
+ groupId: 'groupId',
353
+ sessionType: 'sessionType',
354
+ url: 'url',
355
+ name: 'name',
356
+ allowBackToMain: true,
357
+ delayCloseTime: 10,
358
+ enableBreakoutSession: true,
359
+ startTime: 'startTime',
360
+ status: 'active',
361
+ locusUrl: 'locusUrl',
362
+ breakoutMoveId: 'breakoutMoveId',
363
+ });
364
+
365
+ assert.notCalled(breakoutEvent.onBreakoutJoinResponse);
366
+
367
+ });
268
368
  });
269
369
 
270
370
  describe('#updateBreakoutSessions', () => {
@@ -305,114 +405,19 @@ describe('plugin-meetings', () => {
305
405
  checkBreakout(breakouts.breakouts.get('sessionId5'), 'sessionId5', 'requested');
306
406
  });
307
407
 
308
- it('trigger ASK_RETURN_TO_MAIN correctly', () => {
408
+ it('set requestedLastModifiedTime correctly', () => {
309
409
  const payload = {
310
410
  breakoutSessions: {
311
- active: [{sessionId: 'sessionId2', sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT}],
312
- requested: [{sessionId: 'sessionId1', sessionType: BREAKOUTS.SESSION_TYPES.MAIN}]
313
- }
314
- }
315
- const handler = sinon.stub();
316
- breakouts.updateBreakout({
317
- sessionId: 'sessionId2',
318
- groupId: 'groupId',
319
- sessionType: 'BREAKOUT',
320
- url: 'url',
321
- name: 'name',
322
- allowBackToMain: true,
323
- delayCloseTime: 10,
324
- enableBreakoutSession: true,
325
- startTime: 'startTime',
326
- status: 'active',
327
- locusUrl: 'locusUrl',
328
- });
329
- breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN, handler);
330
- breakouts.updateBreakoutSessions(payload);
331
- assert.calledOnceWithExactly(handler)
332
- breakouts.stopListening(breakouts, BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN, handler);
333
- })
411
+ assigned: [{sessionId: 'sessionId1'}],
412
+ requested: [{sessionId: 'sessionId2', modifiedAt: "2023-05-09T17:16:01.000Z"}],
413
+ },
414
+ };
334
415
 
335
- it('should not trigger ASK_RETURN_TO_MAIN when allowBackToMain is false', () => {
336
- const payload = {
337
- breakoutSessions: {
338
- active: [{sessionId: 'sessionId2', sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT}],
339
- requested: [{sessionId: 'sessionId1', sessionType: BREAKOUTS.SESSION_TYPES.MAIN}]
340
- }
341
- }
342
- const handler = sinon.stub();
343
- breakouts.updateBreakout({
344
- sessionId: 'sessionId2',
345
- groupId: 'groupId',
346
- sessionType: 'BREAKOUT',
347
- url: 'url',
348
- name: 'name',
349
- allowBackToMain: false,
350
- delayCloseTime: 10,
351
- enableBreakoutSession: true,
352
- startTime: 'startTime',
353
- status: 'active',
354
- locusUrl: 'locusUrl',
355
- });
356
- breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN, handler);
357
416
  breakouts.updateBreakoutSessions(payload);
358
- assert.notCalled(handler)
359
- breakouts.stopListening(breakouts, BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN, handler);
417
+ assert.equal(breakouts.breakouts.get('sessionId1').requestedLastModifiedTime, undefined)
418
+ assert.equal(breakouts.breakouts.get('sessionId2').requestedLastModifiedTime, "2023-05-09T17:16:01.000Z")
360
419
  });
361
-
362
- it('should not trigger ASK_RETURN_TO_MAIN when no requested in payload.breakoutSessions', () => {
363
- const payload = {
364
- breakoutSessions: {
365
- active: [{sessionId: 'sessionId1', sessionType: BREAKOUTS.SESSION_TYPES.MAIN}],
366
- }
367
- }
368
- const handler = sinon.stub();
369
- breakouts.updateBreakout({
370
- sessionId: 'sessionId',
371
- groupId: 'groupId',
372
- sessionType: 'sessionType',
373
- url: 'url',
374
- name: 'name',
375
- allowBackToMain: true,
376
- delayCloseTime: 10,
377
- enableBreakoutSession: true,
378
- startTime: 'startTime',
379
- status: 'active',
380
- locusUrl: 'locusUrl',
381
- });
382
- breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN, handler);
383
- breakouts.updateBreakoutSessions(payload);
384
- assert.notCalled(handler)
385
-
386
- breakouts.stopListening(breakouts, BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN, handler);
387
- })
388
-
389
- it('should not trigger ASK_RETURN_TO_MAIN when sessionType is not MAIN', () => {
390
- const payload = {
391
- breakoutSessions: {
392
- active: [{sessionId: 'sessionId1', sessionType: BREAKOUTS.SESSION_TYPES.MAIN}],
393
- requested: [{sessionId: 'sessionId2', sessionType: BREAKOUTS.SESSION_TYPES.BREAKOUT}]
394
- }
395
- }
396
- const handler = sinon.stub();
397
- breakouts.updateBreakout({
398
- sessionId: 'sessionId',
399
- groupId: 'groupId',
400
- sessionType: 'sessionType',
401
- url: 'url',
402
- name: 'name',
403
- allowBackToMain: true,
404
- delayCloseTime: 10,
405
- enableBreakoutSession: true,
406
- startTime: 'startTime',
407
- status: 'active',
408
- locusUrl: 'locusUrl',
409
- });
410
- breakouts.listenTo(breakouts, BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN, handler);
411
- breakouts.updateBreakoutSessions(payload);
412
- assert.notCalled(handler)
413
-
414
- breakouts.stopListening(breakouts, BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN, handler);
415
- })
420
+
416
421
  });
417
422
 
418
423
  describe('#locusUrlUpdate', () => {
@@ -1353,7 +1358,7 @@ describe('plugin-meetings', () => {
1353
1358
  })
1354
1359
  );
1355
1360
  breakouts.shouldFetchPreassignments = false;
1356
- const result = await breakouts.queryPreAssignments();
1361
+ const result = await breakouts.queryPreAssignments({enableBreakoutSession: true, hasBreakoutPreAssignments: true});
1357
1362
  const arg = webex.request.getCall(0).args[0];
1358
1363
  assert.equal(arg.uri, 'url/preassignments');
1359
1364
  assert.equal(breakouts.groups[0].unassignedInvitees.emails[0], 'd@d.com');
@@ -1384,7 +1389,7 @@ describe('plugin-meetings', () => {
1384
1389
  };
1385
1390
  webex.request.rejects(response);
1386
1391
  LoggerProxy.logger.error = sinon.stub();
1387
- const result = await breakouts.queryPreAssignments();
1392
+ const result = await breakouts.queryPreAssignments({enableBreakoutSession: true, hasBreakoutPreAssignments: true});
1388
1393
  await testUtils.flushPromises();
1389
1394
  assert.calledOnceWithExactly(
1390
1395
  LoggerProxy.logger.error,
@@ -1392,6 +1397,21 @@ describe('plugin-meetings', () => {
1392
1397
  response
1393
1398
  );
1394
1399
  });
1400
+
1401
+ it('fail when no correct params', () => {
1402
+
1403
+ assert.deepEqual(breakouts.queryPreAssignments(undefined), undefined);
1404
+
1405
+ assert.deepEqual(breakouts.queryPreAssignments({}), undefined);
1406
+
1407
+ assert.deepEqual(breakouts.queryPreAssignments({ enableBreakoutSession: true, hasBreakoutPreAssignments: false }), undefined);
1408
+
1409
+ assert.deepEqual(breakouts.queryPreAssignments({ enableBreakoutSession: false, hasBreakoutPreAssignments: true }), undefined);
1410
+
1411
+ assert.deepEqual(breakouts.queryPreAssignments({ enableBreakoutSession: false, hasBreakoutPreAssignments: false }), undefined);
1412
+
1413
+ });
1414
+
1395
1415
  });
1396
1416
 
1397
1417
  describe('#dynamicAssign', () => {
@@ -1422,5 +1442,40 @@ describe('plugin-meetings', () => {
1422
1442
  assert.equal(result, 'REQUEST_RETURN_VALUE');
1423
1443
  });
1424
1444
  });
1445
+
1446
+ describe('#triggerReturnToMainEvent', () => {
1447
+ const checkTrigger = ({breakout, shouldTrigger}) => {
1448
+ breakouts.trigger = sinon.stub();
1449
+ breakouts.triggerReturnToMainEvent(breakout);
1450
+ if (shouldTrigger) {
1451
+ assert.calledOnceWithExactly(breakouts.trigger, BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN);
1452
+ } else {
1453
+ assert.notCalled(breakouts.trigger);
1454
+ }
1455
+ }
1456
+ it('should trigger ASK_RETURN_TO_MAIN event correctly', () => {
1457
+ const breakout = {
1458
+ isMain: true,
1459
+ requested: true
1460
+ };
1461
+ checkTrigger({breakout, shouldTrigger: true})
1462
+ });
1463
+
1464
+ it('should not trigger ASK_RETURN_TO_MAIN event when sessionType is not MAIN', () => {
1465
+ const breakout = {
1466
+ isMain: false,
1467
+ requested: true
1468
+ };
1469
+ checkTrigger({breakout, shouldTrigger: false});
1470
+ });
1471
+
1472
+ it('should not trigger ASK_RETURN_TO_MAIN event when session is not requested', () => {
1473
+ const breakout = {
1474
+ isMain: true,
1475
+ requested: false
1476
+ };
1477
+ checkTrigger({breakout, shouldTrigger: false})
1478
+ });
1479
+ });
1425
1480
  });
1426
1481
  });
@@ -153,7 +153,7 @@ describe('plugin-meetings', () => {
153
153
  Util.canUpdate = restorable;
154
154
  });
155
155
 
156
- it('should call request with a body that includes formatted locus details', () => {
156
+ it('should call request multiple times with a bodies that include formatted locus details', () => {
157
157
  const restorable = Util.canUpdate;
158
158
  Util.canUpdate = sinon.stub().returns(true);
159
159
 
@@ -166,6 +166,13 @@ describe('plugin-meetings', () => {
166
166
  uri: 'test/id/controls',
167
167
  body: {
168
168
  audio: audio.properties,
169
+ },
170
+ method: HTTP_VERBS.PATCH,
171
+ });
172
+
173
+ assert.calledWith(request.request, {
174
+ uri: 'test/id/controls',
175
+ body: {
169
176
  reactions: reactions.properties,
170
177
  },
171
178
  method: HTTP_VERBS.PATCH,
@@ -19,6 +19,7 @@ import {
19
19
  } from '../../../../src/constants';
20
20
 
21
21
  import { self, selfWithInactivity } from "./selfConstant";
22
+ import uuid from "uuid";
22
23
 
23
24
  describe('plugin-meetings', () => {
24
25
  describe('LocusInfo index', () => {
@@ -280,9 +281,11 @@ describe('plugin-meetings', () => {
280
281
 
281
282
  it('should update the breakout state', () => {
282
283
  locusInfo.emitScoped = sinon.stub();
283
- newControls.breakout = 'new breakout';
284
+ let tmpStub = sinon.stub(SelfUtils, 'getReplacedBreakoutMoveId').returns('breakoutMoveId');
285
+ newControls.breakout = { 'breakout': {} };
286
+ let selfInfo = {};
284
287
 
285
- locusInfo.updateControls(newControls);
288
+ locusInfo.updateControls(newControls, selfInfo);
286
289
 
287
290
  assert.calledWith(
288
291
  locusInfo.emitScoped,
@@ -292,9 +295,10 @@ describe('plugin-meetings', () => {
292
295
  },
293
296
  LOCUSINFO.EVENTS.CONTROLS_MEETING_BREAKOUT_UPDATED,
294
297
  {
295
- breakout: 'new breakout',
298
+ breakout: newControls.breakout,
296
299
  }
297
300
  );
301
+ tmpStub.restore();
298
302
  });
299
303
 
300
304
  it('should update the transcript state', () => {
@@ -66,6 +66,15 @@ export const self = {
66
66
  },
67
67
  ],
68
68
  mediaSessionsExternal: false,
69
+ replaces: [
70
+ {
71
+ breakoutMoveId: 'e5caeb2c-ffcc-4e06-a08a-1122e7710398',
72
+ lastActive: '2023-05-04T07:14:32.068Z',
73
+ locusUrl: 'https://locus-alpha-apdx.prod.meetapi.webex.com/locus/api/v1/loci/495061ca-7b3c-3b77-85ff-4e1bd58600d1',
74
+ replacedAt: '2023-05-04T07:16:04.905Z',
75
+ sessionId: 'be3147d4-c318-86d8-7611-8d24beaaca8d',
76
+ }
77
+ ],
69
78
  state: 'JOINED',
70
79
  intent: {type: ''},
71
80
  intents: [null],
@@ -352,4 +352,49 @@ describe('plugin-meetings', () => {
352
352
  );
353
353
  });
354
354
  });
355
+
356
+ describe('getReplacedBreakoutMoveId', () => {
357
+ const deviceId = 'https://wdm-a.wbx2.com/wdm/api/v1/devices/20eabde3-4254-48da-9a24';
358
+ const breakoutMoveId = 'e5caeb2c-ffcc-4e06-a08a-1122e7710398';
359
+ const clonedSelf = cloneDeep(self);
360
+
361
+ it('get breakoutMoveId works', () => {
362
+
363
+ assert.deepEqual(SelfUtils.getReplacedBreakoutMoveId(self, deviceId), breakoutMoveId);
364
+
365
+ });
366
+
367
+ it('replaces is empty', () => {
368
+
369
+ clonedSelf.devices[0].replaces = undefined;
370
+ assert.deepEqual(SelfUtils.getReplacedBreakoutMoveId(clonedSelf, deviceId), null);
371
+
372
+ });
373
+
374
+ it('no self or self.devices is not array', () => {
375
+
376
+ assert.deepEqual(SelfUtils.getReplacedBreakoutMoveId(undefined, deviceId), null);
377
+
378
+ clonedSelf.devices = {
379
+ url: 'https://wdm-a.wbx2.com/wdm/api/v1/devices/20eabde3-4254-48da-9a24',
380
+ deviceType: 'WEB',
381
+ mediaSessionsExternal: false,
382
+ replaces: [
383
+ {
384
+ breakoutMoveId: 'e5caeb2c-ffcc-4e06-a08a-1122e7710398',
385
+ lastActive: '2023-05-04T07:14:32.068Z',
386
+ locusUrl: 'https://locus-alpha-apdx.prod.meetapi.webex.com/locus/api/v1/loci/495061ca-7b3c-3b77-85ff-4e1bd58600d1',
387
+ replacedAt: '2023-05-04T07:16:04.905Z',
388
+ sessionId: 'be3147d4-c318-86d8-7611-8d24beaaca8d',
389
+ }
390
+ ],
391
+ state: 'JOINED',
392
+ };
393
+ assert.deepEqual(SelfUtils.getReplacedBreakoutMoveId(clonedSelf, deviceId), null);
394
+
395
+ });
396
+
397
+
398
+ });
399
+
355
400
  });
@@ -36,7 +36,6 @@ describe('plugin-meetings', () => {
36
36
  isRealTimeTranslationEnabled: null,
37
37
  canSelectSpokenLanguages: null,
38
38
  waitingForOthersToJoin: null,
39
- canEnableReactions: null,
40
39
  canSendReactions: null,
41
40
  canManageBreakout: null,
42
41
  canAdmitLobbyToBreakout: null,
@@ -44,6 +43,19 @@ describe('plugin-meetings', () => {
44
43
  canUserRenameSelfAndObserved: null,
45
44
  canUserRenameOthers: null,
46
45
  isBreakoutPreassignmentsEnabled: null,
46
+ canMuteAll: null,
47
+ canUnmuteAll: null,
48
+ canEnableHardMute: null,
49
+ canDisableHardMute: null,
50
+ canEnableMuteOnEntry: null,
51
+ canDisableMuteOnEntry: null,
52
+ canEnableReactions: null,
53
+ canDisableReactions: null,
54
+ canEnableReactionDisplayNames: null,
55
+ canDisableReactionDisplayNames: null,
56
+ canUpdateShareControl: null,
57
+ canEnableViewTheParticipantsList: null,
58
+ canDisableViewTheParticipantsList: null,
47
59
  ...expected,
48
60
  };
49
61
 
@@ -85,7 +97,6 @@ describe('plugin-meetings', () => {
85
97
  'isRealTimeTranslationEnabled',
86
98
  'canSelectSpokenLanguages',
87
99
  'waitingForOthersToJoin',
88
- 'canEnableReactions',
89
100
  'canSendReactions',
90
101
  'canManageBreakout',
91
102
  'canAdmitLobbyToBreakout',
@@ -93,6 +104,19 @@ describe('plugin-meetings', () => {
93
104
  'canUserRenameSelfAndObserved',
94
105
  'canUserRenameOthers',
95
106
  'isBreakoutPreassignmentsEnabled',
107
+ 'canMuteAll',
108
+ 'canUnmuteAll',
109
+ 'canEnableHardMute',
110
+ 'canDisableHardMute',
111
+ 'canEnableMuteOnEntry',
112
+ 'canDisableMuteOnEntry',
113
+ 'canEnableReactions',
114
+ 'canDisableReactions',
115
+ 'canEnableReactionDisplayNames',
116
+ 'canDisableReactionDisplayNames',
117
+ 'canUpdateShareControl',
118
+ 'canEnableViewTheParticipantsList',
119
+ 'canDisableViewTheParticipantsList',
96
120
  ].forEach((key) => {
97
121
  it(`get and set for ${key} work as expected`, () => {
98
122
  const inMeetingActions = new InMeetingActions();
@@ -21,6 +21,7 @@ import {
21
21
  _MEETING_ID_,
22
22
  LOCUSINFO,
23
23
  PC_BAIL_TIMEOUT,
24
+ DISPLAY_HINTS,
24
25
  } from '@webex/plugin-meetings/src/constants';
25
26
  import * as InternalMediaCoreModule from '@webex/internal-media-core';
26
27
  import {
@@ -4673,6 +4674,19 @@ describe('plugin-meetings', () => {
4673
4674
  EVENT_TRIGGERS.MEETING_BREAKOUTS_LEAVE
4674
4675
  );
4675
4676
  });
4677
+
4678
+ it('listens to the breakout ask for help event and triggers the ask for help event', () => {
4679
+ TriggerProxy.trigger.reset();
4680
+ const helpEvent = {sessionId:'sessionId', participant: 'participant'}
4681
+ meeting.breakouts.trigger('ASK_FOR_HELP', helpEvent);
4682
+ assert.calledWith(
4683
+ TriggerProxy.trigger,
4684
+ meeting,
4685
+ {file: 'meeting/index', function: 'setUpBreakoutsListener'},
4686
+ EVENT_TRIGGERS.MEETING_BREAKOUTS_ASK_FOR_HELP,
4687
+ helpEvent
4688
+ );
4689
+ });
4676
4690
  });
4677
4691
 
4678
4692
  describe('#setupLocusControlsListener', () => {
@@ -5222,10 +5236,10 @@ describe('plugin-meetings', () => {
5222
5236
  let canUserLowerSomeoneElsesHandSpy;
5223
5237
  let waitingForOthersToJoinSpy;
5224
5238
  let handleDataChannelUrlChangeSpy;
5225
- let canEnableReactionsSpy;
5226
5239
  let canSendReactionsSpy;
5227
5240
  let canUserRenameSelfAndObservedSpy;
5228
5241
  let canUserRenameOthersSpy;
5242
+ let hasHintsSpy;
5229
5243
 
5230
5244
  beforeEach(() => {
5231
5245
  locusInfoOnSpy = sinon.spy(meeting.locusInfo, 'on');
@@ -5249,7 +5263,6 @@ describe('plugin-meetings', () => {
5249
5263
  canUserLowerSomeoneElsesHandSpy = sinon.spy(MeetingUtil, 'canUserLowerSomeoneElsesHand');
5250
5264
  waitingForOthersToJoinSpy = sinon.spy(MeetingUtil, 'waitingForOthersToJoin');
5251
5265
  handleDataChannelUrlChangeSpy = sinon.spy(meeting, 'handleDataChannelUrlChange');
5252
- canEnableReactionsSpy = sinon.spy(MeetingUtil, 'canEnableReactions');
5253
5266
  canSendReactionsSpy = sinon.spy(MeetingUtil, 'canSendReactions');
5254
5267
  canUserRenameSelfAndObservedSpy = sinon.spy(MeetingUtil, 'canUserRenameSelfAndObserved');
5255
5268
  canUserRenameOthersSpy = sinon.spy(MeetingUtil, 'canUserRenameOthers');
@@ -5262,6 +5275,10 @@ describe('plugin-meetings', () => {
5262
5275
  });
5263
5276
 
5264
5277
  it('registers the correct MEETING_INFO_UPDATED event', () => {
5278
+ // Due to import tree issues, hasHints must be stubed within the scope of the `it`.
5279
+ const restorableHasHints = ControlsOptionsUtil.hasHints;
5280
+ ControlsOptionsUtil.hasHints = sinon.stub().returns(true);
5281
+
5265
5282
  meeting.setUpLocusInfoMeetingInfoListener();
5266
5283
 
5267
5284
  assert.calledThrice(locusInfoOnSpy);
@@ -5296,11 +5313,63 @@ describe('plugin-meetings', () => {
5296
5313
  assert.calledWith(canUserLowerSomeoneElsesHandSpy, payload.info.userDisplayHints);
5297
5314
  assert.calledWith(waitingForOthersToJoinSpy, payload.info.userDisplayHints);
5298
5315
  assert.calledWith(handleDataChannelUrlChangeSpy, payload.info.datachannelUrl);
5299
- assert.calledWith(canEnableReactionsSpy, null, payload.info.userDisplayHints);
5300
5316
  assert.calledWith(canSendReactionsSpy, null, payload.info.userDisplayHints);
5301
5317
  assert.calledWith(canUserRenameSelfAndObservedSpy, payload.info.userDisplayHints);
5302
5318
  assert.calledWith(canUserRenameOthersSpy, payload.info.userDisplayHints);
5303
5319
 
5320
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5321
+ requiredHints: [DISPLAY_HINTS.MUTE_ALL],
5322
+ displayHints: payload.info.userDisplayHints,
5323
+ });
5324
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5325
+ requiredHints: [DISPLAY_HINTS.UNMUTE_ALL],
5326
+ displayHints: payload.info.userDisplayHints,
5327
+ });
5328
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5329
+ requiredHints: [DISPLAY_HINTS.ENABLE_HARD_MUTE],
5330
+ displayHints: payload.info.userDisplayHints,
5331
+ });
5332
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5333
+ requiredHints: [DISPLAY_HINTS.DISABLE_HARD_MUTE],
5334
+ displayHints: payload.info.userDisplayHints,
5335
+ });
5336
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5337
+ requiredHints: [DISPLAY_HINTS.ENABLE_MUTE_ON_ENTRY],
5338
+ displayHints: payload.info.userDisplayHints,
5339
+ });
5340
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5341
+ requiredHints: [DISPLAY_HINTS.DISABLE_MUTE_ON_ENTRY],
5342
+ displayHints: payload.info.userDisplayHints,
5343
+ });
5344
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5345
+ requiredHints: [DISPLAY_HINTS.ENABLE_REACTIONS],
5346
+ displayHints: payload.info.userDisplayHints,
5347
+ });
5348
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5349
+ requiredHints: [DISPLAY_HINTS.DISABLE_REACTIONS],
5350
+ displayHints: payload.info.userDisplayHints,
5351
+ });
5352
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5353
+ requiredHints: [DISPLAY_HINTS.ENABLE_SHOW_DISPLAY_NAME],
5354
+ displayHints: payload.info.userDisplayHints,
5355
+ });
5356
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5357
+ requiredHints: [DISPLAY_HINTS.DISABLE_SHOW_DISPLAY_NAME],
5358
+ displayHints: payload.info.userDisplayHints,
5359
+ });
5360
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5361
+ requiredHints: [DISPLAY_HINTS.SHARE_CONTROL],
5362
+ displayHints: payload.info.userDisplayHints,
5363
+ });
5364
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5365
+ requiredHints: [DISPLAY_HINTS.ENABLE_VIEW_THE_PARTICIPANT_LIST],
5366
+ displayHints: payload.info.userDisplayHints,
5367
+ });
5368
+ assert.calledWith(ControlsOptionsUtil.hasHints, {
5369
+ requiredHints: [DISPLAY_HINTS.DISABLE_VIEW_THE_PARTICIPANT_LIST],
5370
+ displayHints: payload.info.userDisplayHints,
5371
+ });
5372
+
5304
5373
  assert.calledWith(
5305
5374
  TriggerProxy.trigger,
5306
5375
  meeting,
@@ -5317,6 +5386,8 @@ describe('plugin-meetings', () => {
5317
5386
  callback(payload);
5318
5387
 
5319
5388
  assert.notCalled(TriggerProxy.trigger);
5389
+
5390
+ ControlsOptionsUtil.hasHints = restorableHasHints;
5320
5391
  });
5321
5392
  });
5322
5393
 
@@ -427,27 +427,6 @@ describe('plugin-meetings', () => {
427
427
  });
428
428
  });
429
429
 
430
- describe('reactions', () => {
431
- describe('canEnableReactions', () => {
432
- [
433
- [null, DISPLAY_HINTS.ENABLE_REACTIONS, true],
434
- [null, DISPLAY_HINTS.DISABLE_REACTIONS, false],
435
- [null, undefined, null],
436
- ].forEach(() => ([originalValue, displayHint, expected]) => {
437
- assert.deepEqual(MeetingUtil.canEnableReactions(originalValue, [displayHint]), expected);
438
- });
439
- });
440
- describe('canEnableReactions', () => {
441
- [
442
- [null, DISPLAY_HINTS.REACTIONS_ACTIVE, true],
443
- [null, DISPLAY_HINTS.REACTIONS_INACTIVE, false],
444
- [null, undefined, null],
445
- ].forEach(([originalValue, displayHint, expected]) => {
446
- assert.deepEqual(MeetingUtil.canSendReactions(originalValue, [displayHint]), expected);
447
- });
448
- });
449
- });
450
-
451
430
  describe('canManageBreakout', () => {
452
431
  it('works as expected', () => {
453
432
  assert.deepEqual(MeetingUtil.canManageBreakout(['BREAKOUT_MANAGEMENT']), true);