@webex/plugin-meetings 3.0.0-beta.181 → 3.0.0-beta.183
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.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/interpretation/index.js +16 -2
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +4 -1
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/parser.js +44 -3
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/meeting/index.js +1 -2
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/util.js +49 -0
- package/dist/meeting/util.js.map +1 -1
- package/dist/member/util.js +3 -2
- package/dist/member/util.js.map +1 -1
- package/dist/types/locus-info/parser.d.ts +15 -0
- package/dist/types/meeting/util.d.ts +1 -0
- package/package.json +19 -19
- package/src/interpretation/index.ts +15 -1
- package/src/locus-info/index.ts +8 -1
- package/src/locus-info/parser.ts +43 -0
- package/src/meeting/index.ts +1 -3
- package/src/meeting/util.ts +43 -0
- package/src/member/util.ts +2 -2
- package/test/unit/spec/interpretation/index.ts +19 -0
- package/test/unit/spec/locus-info/index.js +27 -0
- package/test/unit/spec/locus-info/parser.js +62 -0
- package/test/unit/spec/meeting/index.js +13 -11
- package/test/unit/spec/meeting/utils.js +62 -0
- package/test/unit/spec/meetings/index.js +1 -1
package/src/meeting/util.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
DISPLAY_HINTS,
|
|
12
12
|
FULL_STATE,
|
|
13
13
|
SELF_POLICY,
|
|
14
|
+
EVENT_TRIGGERS,
|
|
14
15
|
} from '../constants';
|
|
15
16
|
import IntentToJoinError from '../common/errors/intent-to-join';
|
|
16
17
|
import JoinMeetingError from '../common/errors/join-meeting';
|
|
@@ -18,6 +19,7 @@ import ParameterError from '../common/errors/parameter';
|
|
|
18
19
|
import PermissionError from '../common/errors/permission';
|
|
19
20
|
import PasswordError from '../common/errors/password-error';
|
|
20
21
|
import CaptchaError from '../common/errors/captcha-error';
|
|
22
|
+
import Trigger from '../common/events/trigger-proxy';
|
|
21
23
|
|
|
22
24
|
const MeetingUtil = {
|
|
23
25
|
parseLocusJoin: (response) => {
|
|
@@ -566,6 +568,47 @@ const MeetingUtil = {
|
|
|
566
568
|
|
|
567
569
|
return userPolicies[feature];
|
|
568
570
|
},
|
|
571
|
+
|
|
572
|
+
parseInterpretationInfo: (meeting, meetingInfo) => {
|
|
573
|
+
if (!meeting || !meetingInfo) {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
const siInfo = meetingInfo.simultaneousInterpretation;
|
|
577
|
+
meeting.simultaneousInterpretation.updateMeetingSIEnabled(
|
|
578
|
+
!!meetingInfo.turnOnSimultaneousInterpretation,
|
|
579
|
+
!!siInfo?.currentSIInterpreter
|
|
580
|
+
);
|
|
581
|
+
const hostSIEnabled = !!(
|
|
582
|
+
meetingInfo.turnOnSimultaneousInterpretation &&
|
|
583
|
+
meetingInfo?.meetingSiteSetting?.enableHostInterpreterControlSI
|
|
584
|
+
);
|
|
585
|
+
meeting.simultaneousInterpretation.updateHostSIEnabled(hostSIEnabled);
|
|
586
|
+
|
|
587
|
+
function renameKey(obj, oldKey, newKey) {
|
|
588
|
+
if (oldKey in obj) {
|
|
589
|
+
obj[newKey] = obj[oldKey];
|
|
590
|
+
delete obj[oldKey];
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
if (siInfo) {
|
|
594
|
+
const lanuagesInfo = cloneDeep(siInfo.siLanguages);
|
|
595
|
+
for (const language of lanuagesInfo) {
|
|
596
|
+
renameKey(language, 'languageCode', 'languageName');
|
|
597
|
+
renameKey(language, 'languageGroupId', 'languageCode');
|
|
598
|
+
}
|
|
599
|
+
if (!meeting.simultaneousInterpretation?.siLanguages?.length) {
|
|
600
|
+
meeting.simultaneousInterpretation.updateInterpretation(lanuagesInfo);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
Trigger.trigger(
|
|
604
|
+
this,
|
|
605
|
+
{
|
|
606
|
+
file: 'meeting/util',
|
|
607
|
+
function: 'parseInterpretationInfo',
|
|
608
|
+
},
|
|
609
|
+
EVENT_TRIGGERS.MEETING_INTERPRETATION_UPDATE
|
|
610
|
+
);
|
|
611
|
+
},
|
|
569
612
|
};
|
|
570
613
|
|
|
571
614
|
export default MeetingUtil;
|
package/src/member/util.ts
CHANGED
|
@@ -364,8 +364,8 @@ MemberUtil.extractMediaStatus = (participant: any): IMediaStatus => {
|
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
return {
|
|
367
|
-
audio: participant.status
|
|
368
|
-
video: participant.status
|
|
367
|
+
audio: participant.status?.audioStatus,
|
|
368
|
+
video: participant.status?.videoStatus,
|
|
369
369
|
};
|
|
370
370
|
};
|
|
371
371
|
|
|
@@ -83,6 +83,25 @@ describe('plugin-meetings', () => {
|
|
|
83
83
|
});
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
+
describe('#updateMeetingSIEnabled', () => {
|
|
87
|
+
it('update meeting SI feature is on or off, and self is scheduled interpreter or not', () => {
|
|
88
|
+
interpretation.updateMeetingSIEnabled(true, false);
|
|
89
|
+
|
|
90
|
+
assert.equal(interpretation.meetingSIEnabled, true);
|
|
91
|
+
assert.equal(interpretation.selfIsInterpreter, false);
|
|
92
|
+
|
|
93
|
+
interpretation.updateMeetingSIEnabled(true, true);
|
|
94
|
+
|
|
95
|
+
assert.equal(interpretation.meetingSIEnabled, true);
|
|
96
|
+
assert.equal(interpretation.selfIsInterpreter, true);
|
|
97
|
+
|
|
98
|
+
interpretation.updateMeetingSIEnabled(false, false);
|
|
99
|
+
|
|
100
|
+
assert.equal(interpretation.meetingSIEnabled, false);
|
|
101
|
+
assert.equal(interpretation.selfIsInterpreter, false);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
86
105
|
describe('#updateInterpretation', () => {
|
|
87
106
|
const checkSILanguage = (siLanguage, expectResult) => {
|
|
88
107
|
return siLanguage?.languageCode === expectResult.languageCode && siLanguage?.languageName === expectResult.languageName
|
|
@@ -1648,12 +1648,39 @@ describe('plugin-meetings', () => {
|
|
|
1648
1648
|
sandbox.stub(locusInfo, 'updateParticipants');
|
|
1649
1649
|
sandbox.stub(locusInfo, 'isMeetingActive');
|
|
1650
1650
|
sandbox.stub(locusInfo, 'handleOneOnOneEvent');
|
|
1651
|
+
sandbox.stub(locusParser, 'isNewFullLocus').returns(true);
|
|
1651
1652
|
|
|
1652
1653
|
locusInfo.onFullLocus(fakeLocus, eventType);
|
|
1653
1654
|
|
|
1654
1655
|
assert.equal(fakeLocus, locusParser.workingCopy);
|
|
1655
1656
|
});
|
|
1656
1657
|
|
|
1658
|
+
it('onFullLocus() does not do anything if the incoming full locus DTO is old', () => {
|
|
1659
|
+
const eventType = 'fakeEvent';
|
|
1660
|
+
|
|
1661
|
+
locusParser.workingCopy = {};
|
|
1662
|
+
|
|
1663
|
+
const oldWorkingCopy = locusParser.workingCopy;
|
|
1664
|
+
|
|
1665
|
+
const spies = [
|
|
1666
|
+
sandbox.stub(locusInfo, 'updateParticipantDeltas'),
|
|
1667
|
+
sandbox.stub(locusInfo, 'updateLocusInfo'),
|
|
1668
|
+
sandbox.stub(locusInfo, 'updateParticipants'),
|
|
1669
|
+
sandbox.stub(locusInfo, 'isMeetingActive'),
|
|
1670
|
+
sandbox.stub(locusInfo, 'handleOneOnOneEvent'),
|
|
1671
|
+
];
|
|
1672
|
+
|
|
1673
|
+
sandbox.stub(locusParser, 'isNewFullLocus').returns(false);
|
|
1674
|
+
|
|
1675
|
+
locusInfo.onFullLocus(fakeLocus, eventType);
|
|
1676
|
+
|
|
1677
|
+
spies.forEach((spy) => {
|
|
1678
|
+
assert.notCalled(spy);
|
|
1679
|
+
})
|
|
1680
|
+
|
|
1681
|
+
assert.equal(oldWorkingCopy, locusParser.workingCopy);
|
|
1682
|
+
});
|
|
1683
|
+
|
|
1657
1684
|
it('onDeltaAction applies locus delta data to meeting', () => {
|
|
1658
1685
|
const action = 'fake action';
|
|
1659
1686
|
const parsedLoci = 'fake loci';
|
|
@@ -238,6 +238,68 @@ describe('locus-info/parser', () => {
|
|
|
238
238
|
});
|
|
239
239
|
});
|
|
240
240
|
|
|
241
|
+
describe('Full Locus handling', () => {
|
|
242
|
+
describe('isNewFullLocus', () => {
|
|
243
|
+
let parser;
|
|
244
|
+
|
|
245
|
+
beforeEach(() => {
|
|
246
|
+
parser = new LocusDeltaParser();
|
|
247
|
+
})
|
|
248
|
+
it('returns false if incoming Locus is not valid', () => {
|
|
249
|
+
const fakeInvalidIncomingLocus = {};
|
|
250
|
+
|
|
251
|
+
parser.workingCopy = { sequence: {rangeStart: 0, rangeEnd: 0, entries: [1]}};
|
|
252
|
+
|
|
253
|
+
assert.isFalse(parser.isNewFullLocus(fakeInvalidIncomingLocus));
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
const runCheck = (incomingSequence, currentSequence, expectedResult) => {
|
|
257
|
+
parser.workingCopy = { sequence: {rangeStart: 0, rangeEnd: 0, entries: [1, 2, currentSequence]}};
|
|
258
|
+
|
|
259
|
+
const fakeIncomingLocus = { sequence: {rangeStart: 0, rangeEnd: 0, entries: [1, 10, incomingSequence]}};
|
|
260
|
+
|
|
261
|
+
assert.strictEqual(parser.isNewFullLocus(fakeIncomingLocus), expectedResult);
|
|
262
|
+
}
|
|
263
|
+
it('returns true if there is no working copy', () => {
|
|
264
|
+
const fakeIncomingLocus = { sequence: {rangeStart: 0, rangeEnd: 0, entries: [10]}};
|
|
265
|
+
|
|
266
|
+
// sanity check that we initially have no working copy
|
|
267
|
+
assert.isNull(parser.workingCopy);
|
|
268
|
+
|
|
269
|
+
assert.isTrue(parser.isNewFullLocus(fakeIncomingLocus));
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('returns true if new sequence is higher than existing one', () => {
|
|
273
|
+
runCheck(101, 100, true);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it('returns false if new sequence is same than existing one', () => {
|
|
277
|
+
runCheck(100, 100, false);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('returns false if new sequence is older than existing one', () => {
|
|
281
|
+
runCheck(99, 100, false);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it('returns true if incoming Locus has empty sequence', () => {
|
|
285
|
+
parser.workingCopy = { sequence: {rangeStart: 0, rangeEnd: 0, entries: [1, 2, 3]}};
|
|
286
|
+
|
|
287
|
+
const fakeIncomingLocus = { sequence: {rangeStart: 0, rangeEnd: 0, entries: []}};
|
|
288
|
+
|
|
289
|
+
assert.isTrue(parser.isNewFullLocus(fakeIncomingLocus));
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('returns true if working copy has empty sequence', () => {
|
|
293
|
+
parser.workingCopy = { sequence: {rangeStart: 0, rangeEnd: 0, entries: []}};
|
|
294
|
+
|
|
295
|
+
const fakeIncomingLocus = { sequence: {rangeStart: 0, rangeEnd: 0, entries: [1,2,3]}};
|
|
296
|
+
|
|
297
|
+
assert.isTrue(parser.isNewFullLocus(fakeIncomingLocus));
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
})
|
|
301
|
+
});
|
|
302
|
+
|
|
241
303
|
describe('Invalid Locus objects', () => {
|
|
242
304
|
let sandbox = null;
|
|
243
305
|
let parser;
|
|
@@ -5531,25 +5531,27 @@ describe('plugin-meetings', () => {
|
|
|
5531
5531
|
|
|
5532
5532
|
checkParseMeetingInfo(expectedInfoToParse);
|
|
5533
5533
|
});
|
|
5534
|
-
it('should
|
|
5535
|
-
const
|
|
5534
|
+
it('should parse interpretation info correctly', () => {
|
|
5535
|
+
const parseInterpretationInfo = sinon.spy(MeetingUtil, 'parseInterpretationInfo');
|
|
5536
5536
|
const mockToggleOnData = {
|
|
5537
5537
|
body: {
|
|
5538
5538
|
meetingSiteSetting: {
|
|
5539
5539
|
enableHostInterpreterControlSI: true,
|
|
5540
|
+
},
|
|
5541
|
+
turnOnSimultaneousInterpretation: true,
|
|
5542
|
+
simultaneousInterpretation: {
|
|
5543
|
+
currentSIInterpreter: false,
|
|
5544
|
+
siLanguages: [
|
|
5545
|
+
{
|
|
5546
|
+
languageCode: "ar",
|
|
5547
|
+
languageGroupId: 4,
|
|
5548
|
+
},
|
|
5549
|
+
]
|
|
5540
5550
|
}
|
|
5541
5551
|
}
|
|
5542
5552
|
};
|
|
5543
5553
|
meeting.parseMeetingInfo(mockToggleOnData);
|
|
5544
|
-
assert.
|
|
5545
|
-
|
|
5546
|
-
const mockToggleOffData = {
|
|
5547
|
-
body: {
|
|
5548
|
-
meetingSiteSetting: {}
|
|
5549
|
-
}
|
|
5550
|
-
};
|
|
5551
|
-
meeting.parseMeetingInfo(mockToggleOffData);
|
|
5552
|
-
assert.calledWith(updateHostSIEnabledSpy, false);
|
|
5554
|
+
assert.calledOnceWithExactly(parseInterpretationInfo, meeting, mockToggleOnData.body);
|
|
5553
5555
|
});
|
|
5554
5556
|
});
|
|
5555
5557
|
|
|
@@ -740,5 +740,67 @@ describe('plugin-meetings', () => {
|
|
|
740
740
|
assert.deepEqual(MeetingUtil.isBreakoutPreassignmentsEnabled([]), true);
|
|
741
741
|
});
|
|
742
742
|
});
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
describe('parseInterpretationInfo', () => {
|
|
746
|
+
let meetingInfo = {};
|
|
747
|
+
beforeEach(() => {
|
|
748
|
+
meeting.simultaneousInterpretation = {
|
|
749
|
+
updateMeetingSIEnabled: sinon.stub(),
|
|
750
|
+
updateHostSIEnabled: sinon.stub(),
|
|
751
|
+
updateInterpretation: sinon.stub(),
|
|
752
|
+
siLanguages: [],
|
|
753
|
+
};
|
|
754
|
+
});
|
|
755
|
+
it('should update simultaneous interpretation settings with SI and host enabled', () => {
|
|
756
|
+
meetingInfo.turnOnSimultaneousInterpretation = true;
|
|
757
|
+
meetingInfo.meetingSiteSetting = {
|
|
758
|
+
enableHostInterpreterControlSI: true,
|
|
759
|
+
};
|
|
760
|
+
meetingInfo.simultaneousInterpretation = {
|
|
761
|
+
currentSIInterpreter: true,
|
|
762
|
+
siLanguages: [
|
|
763
|
+
{ languageCode: 'en', languageGroupId: 1 },
|
|
764
|
+
{ languageCode: 'es', languageGroupId: 2 },
|
|
765
|
+
],
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
MeetingUtil.parseInterpretationInfo(meeting, meetingInfo);
|
|
769
|
+
assert.calledWith(meeting.simultaneousInterpretation.updateMeetingSIEnabled, true, true);
|
|
770
|
+
assert.calledWith(meeting.simultaneousInterpretation.updateHostSIEnabled, true);
|
|
771
|
+
assert.calledWith(meeting.simultaneousInterpretation.updateInterpretation, [
|
|
772
|
+
{ languageName: 'en', languageCode: 1 },
|
|
773
|
+
{ languageName: 'es', languageCode: 2 },
|
|
774
|
+
]);
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
it('should update simultaneous interpretation settings with host SI disabled', () => {
|
|
778
|
+
meetingInfo.meetingSiteSetting.enableHostInterpreterControlSI = false;
|
|
779
|
+
meetingInfo.simultaneousInterpretation.currentSIInterpreter = false;
|
|
780
|
+
MeetingUtil.parseInterpretationInfo(meeting, meetingInfo);
|
|
781
|
+
assert.calledWith(meeting.simultaneousInterpretation.updateMeetingSIEnabled, true, false);
|
|
782
|
+
assert.calledWith(meeting.simultaneousInterpretation.updateHostSIEnabled, false);
|
|
783
|
+
assert.calledWith(meeting.simultaneousInterpretation.updateInterpretation, [
|
|
784
|
+
{ languageName: 'en', languageCode: 1 },
|
|
785
|
+
{ languageName: 'es', languageCode: 2 },
|
|
786
|
+
]);
|
|
787
|
+
});
|
|
788
|
+
it('should update simultaneous interpretation settings with SI disabled', () => {
|
|
789
|
+
meetingInfo.turnOnSimultaneousInterpretation = false;
|
|
790
|
+
MeetingUtil.parseInterpretationInfo(meeting, meetingInfo);
|
|
791
|
+
assert.calledWith(meeting.simultaneousInterpretation.updateMeetingSIEnabled, false, false);
|
|
792
|
+
assert.calledWith(meeting.simultaneousInterpretation.updateHostSIEnabled, false);
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
it('should not update simultaneous interpretation settings for invalid input', () => {
|
|
796
|
+
// Call the function with invalid inputs
|
|
797
|
+
MeetingUtil.parseInterpretationInfo(null, null);
|
|
798
|
+
|
|
799
|
+
// Ensure that the update functions are not called
|
|
800
|
+
assert.notCalled(meeting.simultaneousInterpretation.updateMeetingSIEnabled);
|
|
801
|
+
assert.notCalled(meeting.simultaneousInterpretation.updateHostSIEnabled);
|
|
802
|
+
assert.notCalled(meeting.simultaneousInterpretation.updateInterpretation);
|
|
803
|
+
});
|
|
804
|
+
});
|
|
743
805
|
});
|
|
744
806
|
});
|
|
@@ -1085,7 +1085,7 @@ describe('plugin-meetings', () => {
|
|
|
1085
1085
|
assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
|
|
1086
1086
|
assert.calledOnce(MeetingsUtil.getMeetingAddedType);
|
|
1087
1087
|
assert.notCalled(setTimeoutSpy);
|
|
1088
|
-
assert.
|
|
1088
|
+
assert.callCount(TriggerProxy.trigger, 4);
|
|
1089
1089
|
assert.calledWith(webex.meetings.meetingInfo.fetchMeetingInfo, destination, type, null, null, undefined, undefined, extraParams, {meetingId: meeting.id});
|
|
1090
1090
|
assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
|
|
1091
1091
|
|