@webex/plugin-meetings 3.0.0-beta.16 → 3.0.0-beta.18
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 +116 -0
- package/dist/breakouts/breakout.js.map +1 -0
- package/dist/breakouts/collection.js +23 -0
- package/dist/breakouts/collection.js.map +1 -0
- package/dist/breakouts/index.js +226 -0
- package/dist/breakouts/index.js.map +1 -0
- package/dist/config.js +4 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +43 -6
- package/dist/constants.js.map +1 -1
- package/dist/locus-info/controlsUtils.js +2 -1
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +48 -0
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/parser.js +1 -0
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +19 -11
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +3 -3
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +4 -4
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +5 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +652 -459
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +25 -44
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +22 -57
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +2 -0
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +28 -18
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/request.js +14 -12
- package/dist/meetings/request.js.map +1 -1
- package/dist/member/index.js +9 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +14 -1
- package/dist/member/util.js.map +1 -1
- package/dist/members/index.js +8 -6
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +3 -1
- package/dist/members/request.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +46 -6
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/multistreamMedia.js +4 -0
- package/dist/multistream/multistreamMedia.js.map +1 -1
- package/dist/multistream/receiveSlot.js +3 -3
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +8 -6
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +168 -63
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/reachability/index.js +63 -51
- package/dist/reachability/index.js.map +1 -1
- package/dist/reactions/constants.js +13 -0
- package/dist/reactions/constants.js.map +1 -0
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/reconnection-manager/index.js +25 -12
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/enums.js +17 -0
- package/dist/recording-controller/enums.js.map +1 -0
- package/dist/recording-controller/index.js +343 -0
- package/dist/recording-controller/index.js.map +1 -0
- package/dist/recording-controller/util.js +63 -0
- package/dist/recording-controller/util.js.map +1 -0
- package/dist/roap/request.js +88 -68
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +72 -47
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/statsAnalyzer/index.js +3 -3
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +18 -6
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/package.json +24 -19
- package/src/breakouts/README.md +190 -0
- package/src/breakouts/breakout.ts +110 -0
- package/src/breakouts/collection.ts +19 -0
- package/src/breakouts/index.ts +225 -0
- package/src/config.ts +4 -1
- package/src/constants.ts +39 -1
- package/src/locus-info/controlsUtils.ts +2 -0
- package/src/locus-info/index.ts +59 -1
- package/src/locus-info/parser.ts +1 -0
- package/src/locus-info/selfUtils.ts +8 -0
- package/src/media/index.ts +1 -2
- package/src/media/properties.ts +6 -9
- package/src/meeting/in-meeting-actions.ts +8 -0
- package/src/meeting/index.ts +360 -111
- package/src/meeting/request.ts +9 -31
- package/src/meeting/request.type.ts +2 -0
- package/src/meeting/util.ts +25 -60
- package/src/meeting-info/meeting-info-v2.ts +2 -0
- package/src/meetings/index.ts +10 -5
- package/src/meetings/request.ts +1 -1
- package/src/member/index.ts +9 -0
- package/src/member/util.ts +14 -1
- package/src/members/index.ts +1 -0
- package/src/members/request.ts +1 -0
- package/src/multistream/mediaRequestManager.ts +79 -15
- package/src/multistream/multistreamMedia.ts +4 -0
- package/src/multistream/receiveSlot.ts +17 -12
- package/src/multistream/receiveSlotManager.ts +22 -21
- package/src/multistream/remoteMedia.ts +1 -1
- package/src/multistream/remoteMediaGroup.ts +2 -2
- package/src/multistream/remoteMediaManager.ts +150 -37
- package/src/reachability/index.ts +16 -13
- package/src/reactions/constants.ts +4 -0
- package/src/reactions/reactions.type.ts +25 -0
- package/src/reconnection-manager/index.ts +18 -9
- package/src/recording-controller/enums.ts +8 -0
- package/src/recording-controller/index.ts +315 -0
- package/src/recording-controller/util.ts +58 -0
- package/src/roap/request.ts +78 -73
- package/src/roap/turnDiscovery.ts +8 -6
- package/src/statsAnalyzer/index.ts +4 -4
- package/src/statsAnalyzer/mqaUtil.ts +6 -0
- package/test/unit/spec/breakouts/breakout.ts +119 -0
- package/test/unit/spec/breakouts/collection.ts +15 -0
- package/test/unit/spec/breakouts/index.ts +293 -0
- package/test/unit/spec/locus-info/controlsUtils.js +20 -0
- package/test/unit/spec/locus-info/index.js +103 -0
- package/test/unit/spec/locus-info/selfConstant.js +25 -0
- package/test/unit/spec/locus-info/selfUtils.js +84 -0
- package/test/unit/spec/media/index.ts +1 -1
- package/test/unit/spec/media/properties.ts +9 -9
- package/test/unit/spec/meeting/effectsState.js +5 -1
- package/test/unit/spec/meeting/in-meeting-actions.ts +5 -1
- package/test/unit/spec/meeting/index.js +241 -50
- package/test/unit/spec/meeting/request.js +17 -0
- package/test/unit/spec/meeting/utils.js +28 -122
- package/test/unit/spec/meetings/index.js +1 -0
- package/test/unit/spec/member/util.js +26 -1
- package/test/unit/spec/multistream/mediaRequestManager.ts +312 -50
- package/test/unit/spec/multistream/receiveSlot.ts +6 -6
- package/test/unit/spec/multistream/receiveSlotManager.ts +13 -13
- package/test/unit/spec/multistream/remoteMedia.ts +2 -2
- package/test/unit/spec/multistream/remoteMediaGroup.ts +5 -5
- package/test/unit/spec/multistream/remoteMediaManager.ts +354 -65
- package/test/unit/spec/reachability/index.ts +58 -24
- package/test/unit/spec/reconnection-manager/index.js +42 -13
- package/test/unit/spec/recording-controller/index.js +231 -0
- package/test/unit/spec/recording-controller/util.js +102 -0
- package/test/unit/spec/roap/index.ts +2 -1
- package/test/unit/spec/roap/request.ts +114 -0
- package/test/unit/spec/roap/turnDiscovery.ts +45 -29
- package/test/unit/spec/stats-analyzer/index.js +2 -2
- package/test/utils/webex-test-users.js +1 -0
- package/tsconfig.json +6 -0
- package/dist/media/internal-media-core-wrapper.js +0 -18
- package/dist/media/internal-media-core-wrapper.js.map +0 -1
- package/src/media/internal-media-core-wrapper.ts +0 -9
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
LOCUSINFO,
|
|
23
23
|
PC_BAIL_TIMEOUT,
|
|
24
24
|
} from '@webex/plugin-meetings/src/constants';
|
|
25
|
-
import {
|
|
25
|
+
import {ConnectionState, Event, Errors, ErrorType, RemoteTrackType} from '@webex/internal-media-core';
|
|
26
26
|
import * as StatsAnalyzerModule from '@webex/plugin-meetings/src/statsAnalyzer';
|
|
27
27
|
import EventsScope from '@webex/plugin-meetings/src/common/events/events-scope';
|
|
28
28
|
import Meetings, {CONSTANTS} from '@webex/plugin-meetings';
|
|
@@ -36,6 +36,7 @@ import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
|
|
|
36
36
|
import Media from '@webex/plugin-meetings/src/media/index';
|
|
37
37
|
import ReconnectionManager from '@webex/plugin-meetings/src/reconnection-manager';
|
|
38
38
|
import MediaUtil from '@webex/plugin-meetings/src/media/util';
|
|
39
|
+
import RecordingUtil from '@webex/plugin-meetings/src/recording-controller/util';
|
|
39
40
|
import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
|
|
40
41
|
import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
|
|
41
42
|
import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
|
|
@@ -44,7 +45,12 @@ import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
|
44
45
|
import {trigger, eventType} from '@webex/plugin-meetings/src/metrics/config';
|
|
45
46
|
import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
|
|
46
47
|
import {IceGatheringFailed} from '@webex/plugin-meetings/src/common/errors/webex-errors';
|
|
48
|
+
import {MediaRequestManager} from '@webex/plugin-meetings/src/multistream/mediaRequestManager';
|
|
47
49
|
|
|
50
|
+
import LLM from '@webex/internal-plugin-llm';
|
|
51
|
+
import Mercury from '@webex/internal-plugin-mercury';
|
|
52
|
+
import Breakouts from '@webex/plugin-meetings/src/breakouts';
|
|
53
|
+
import {REACTION_RELAY_TYPES} from '../../../../src/reactions/constants';
|
|
48
54
|
import locus from '../fixture/locus';
|
|
49
55
|
import {
|
|
50
56
|
UserNotJoinedError,
|
|
@@ -155,6 +161,8 @@ describe('plugin-meetings', () => {
|
|
|
155
161
|
meetings: Meetings,
|
|
156
162
|
credentials: Credentials,
|
|
157
163
|
support: Support,
|
|
164
|
+
llm: LLM,
|
|
165
|
+
mercury: Mercury,
|
|
158
166
|
},
|
|
159
167
|
config: {
|
|
160
168
|
credentials: {
|
|
@@ -179,6 +187,7 @@ describe('plugin-meetings', () => {
|
|
|
179
187
|
webex.credentials.getOrgId = sinon.stub().returns('fake-org-id');
|
|
180
188
|
webex.internal.metrics.submitClientMetrics = sinon.stub().returns(Promise.resolve());
|
|
181
189
|
webex.meetings.uploadLogs = sinon.stub().returns(Promise.resolve());
|
|
190
|
+
webex.internal.llm.on = sinon.stub();
|
|
182
191
|
|
|
183
192
|
TriggerProxy.trigger = sinon.stub().returns(true);
|
|
184
193
|
Metrics.postEvent = sinon.stub();
|
|
@@ -250,6 +259,13 @@ describe('plugin-meetings', () => {
|
|
|
250
259
|
assert.equal(meeting.meetingInfoFailureReason, undefined);
|
|
251
260
|
assert.equal(meeting.destination, testDestination);
|
|
252
261
|
assert.equal(meeting.destinationType, _MEETING_ID_);
|
|
262
|
+
assert.instanceOf(meeting.breakouts, Breakouts);
|
|
263
|
+
});
|
|
264
|
+
it('creates MediaRequestManager instances', () => {
|
|
265
|
+
assert.instanceOf(meeting.mediaRequestManagers.audio, MediaRequestManager);
|
|
266
|
+
assert.instanceOf(meeting.mediaRequestManagers.video, MediaRequestManager);
|
|
267
|
+
assert.instanceOf(meeting.mediaRequestManagers.screenShareAudio, MediaRequestManager);
|
|
268
|
+
assert.instanceOf(meeting.mediaRequestManagers.screenShareVideo, MediaRequestManager);
|
|
253
269
|
});
|
|
254
270
|
});
|
|
255
271
|
describe('#invite', () => {
|
|
@@ -779,7 +795,7 @@ describe('plugin-meetings', () => {
|
|
|
779
795
|
});
|
|
780
796
|
});
|
|
781
797
|
|
|
782
|
-
it(
|
|
798
|
+
it("should throw error if request doesn't work", async () => {
|
|
783
799
|
meeting.request = sinon.stub().returns(Promise.reject());
|
|
784
800
|
|
|
785
801
|
try {
|
|
@@ -799,6 +815,64 @@ describe('plugin-meetings', () => {
|
|
|
799
815
|
assert.calledOnce(meeting.transcription.closeSocket);
|
|
800
816
|
});
|
|
801
817
|
});
|
|
818
|
+
describe('#isReactionsSupported', () => {
|
|
819
|
+
it('should return false if the feature is not supported for the meeting', () => {
|
|
820
|
+
meeting.locusInfo.controls = {reactions: {enabled: false}};
|
|
821
|
+
|
|
822
|
+
assert.equal(meeting.isReactionsSupported(), false);
|
|
823
|
+
});
|
|
824
|
+
it('should return true if the feature is not supported for the meeting', () => {
|
|
825
|
+
meeting.locusInfo.controls = {reactions: {enabled: true}};
|
|
826
|
+
|
|
827
|
+
assert.equal(meeting.isReactionsSupported(), true);
|
|
828
|
+
});
|
|
829
|
+
});
|
|
830
|
+
describe('#processRelayEvent', () => {
|
|
831
|
+
it('should process a Reaction event type', () => {
|
|
832
|
+
meeting.isReactionsSupported = sinon.stub().returns(true);
|
|
833
|
+
meeting.config.receiveReactions = true;
|
|
834
|
+
const fakeSendersName = 'Fake reactors name';
|
|
835
|
+
meeting.members.membersCollection.get = sinon.stub().returns({name: fakeSendersName});
|
|
836
|
+
const fakeReactionPayload = {
|
|
837
|
+
type: 'fake_type',
|
|
838
|
+
codepoints: 'fake_codepoints',
|
|
839
|
+
shortcodes: 'fake_shortcodes',
|
|
840
|
+
tone: {
|
|
841
|
+
type: 'fake_tone_type',
|
|
842
|
+
codepoints: 'fake_tone_codepoints',
|
|
843
|
+
shortcodes: 'fake_tone_shortcodes',
|
|
844
|
+
},
|
|
845
|
+
};
|
|
846
|
+
const fakeSenderPayload = {
|
|
847
|
+
participantId: 'fake_participant_id',
|
|
848
|
+
};
|
|
849
|
+
const fakeProcessedReaction = {
|
|
850
|
+
reaction: fakeReactionPayload,
|
|
851
|
+
sender: {
|
|
852
|
+
id: fakeSenderPayload.participantId,
|
|
853
|
+
name: fakeSendersName,
|
|
854
|
+
},
|
|
855
|
+
};
|
|
856
|
+
const fakeRelayEvent = {
|
|
857
|
+
data: {
|
|
858
|
+
relayType: REACTION_RELAY_TYPES.REACTION,
|
|
859
|
+
reaction: fakeReactionPayload,
|
|
860
|
+
sender: fakeSenderPayload,
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
meeting.processRelayEvent(fakeRelayEvent);
|
|
864
|
+
assert.calledWith(
|
|
865
|
+
TriggerProxy.trigger,
|
|
866
|
+
sinon.match.instanceOf(Meeting),
|
|
867
|
+
{
|
|
868
|
+
file: 'meeting/index',
|
|
869
|
+
function: 'join',
|
|
870
|
+
},
|
|
871
|
+
EVENT_TRIGGERS.MEETING_RECEIVE_REACTIONS,
|
|
872
|
+
fakeProcessedReaction
|
|
873
|
+
);
|
|
874
|
+
})
|
|
875
|
+
})
|
|
802
876
|
describe('#join', () => {
|
|
803
877
|
let sandbox = null;
|
|
804
878
|
const joinMeetingResult = 'JOIN_MEETINGS_OPTION_RESULT';
|
|
@@ -844,15 +918,20 @@ describe('plugin-meetings', () => {
|
|
|
844
918
|
|
|
845
919
|
it('should call updateLLMConnection upon joining if config value is set', async () => {
|
|
846
920
|
meeting.config.enableAutomaticLLM = true;
|
|
921
|
+
meeting.webex.internal.llm.on = sinon.stub();
|
|
922
|
+
meeting.processRelayEvent = sinon.stub();
|
|
847
923
|
await meeting.join();
|
|
848
924
|
|
|
849
925
|
assert.calledOnce(meeting.updateLLMConnection);
|
|
926
|
+
assert.calledOnceWithExactly(meeting.webex.internal.llm.on, 'event:relay.event', meeting.processRelayEvent);
|
|
850
927
|
});
|
|
851
928
|
|
|
852
929
|
it('should not call updateLLMConnection upon joining if config value is not set', async () => {
|
|
930
|
+
meeting.webex.internal.llm.on = sinon.stub();
|
|
853
931
|
await meeting.join();
|
|
854
932
|
|
|
855
933
|
assert.notCalled(meeting.updateLLMConnection);
|
|
934
|
+
assert.notCalled(meeting.webex.internal.llm.on);
|
|
856
935
|
});
|
|
857
936
|
|
|
858
937
|
it('should invoke `receiveTranscription()` if receiveTranscription is set to true', async () => {
|
|
@@ -952,7 +1031,7 @@ describe('plugin-meetings', () => {
|
|
|
952
1031
|
beforeEach(() => {
|
|
953
1032
|
fakeMediaConnection = {
|
|
954
1033
|
close: sinon.stub(),
|
|
955
|
-
getConnectionState: sinon.stub().returns(
|
|
1034
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
956
1035
|
initiateOffer: sinon.stub().resolves({}),
|
|
957
1036
|
on: sinon.stub(),
|
|
958
1037
|
};
|
|
@@ -1200,7 +1279,7 @@ describe('plugin-meetings', () => {
|
|
|
1200
1279
|
meeting.meetingState = 'ACTIVE';
|
|
1201
1280
|
fakeMediaConnection.getConnectionState = sinon
|
|
1202
1281
|
.stub()
|
|
1203
|
-
.returns(
|
|
1282
|
+
.returns(ConnectionState.Connecting);
|
|
1204
1283
|
const clock = sinon.useFakeTimers();
|
|
1205
1284
|
const media = meeting.addMedia({
|
|
1206
1285
|
mediaSettings: {},
|
|
@@ -3531,19 +3610,19 @@ describe('plugin-meetings', () => {
|
|
|
3531
3610
|
|
|
3532
3611
|
it('should register for all the correct RoapMediaConnection events', () => {
|
|
3533
3612
|
meeting.setupMediaConnectionListeners();
|
|
3534
|
-
assert.isFunction(eventListeners[
|
|
3535
|
-
assert.isFunction(eventListeners[
|
|
3536
|
-
assert.isFunction(eventListeners[
|
|
3537
|
-
assert.isFunction(eventListeners[
|
|
3538
|
-
assert.isFunction(eventListeners[
|
|
3539
|
-
assert.isFunction(eventListeners[
|
|
3613
|
+
assert.isFunction(eventListeners[Event.ROAP_STARTED]);
|
|
3614
|
+
assert.isFunction(eventListeners[Event.ROAP_DONE]);
|
|
3615
|
+
assert.isFunction(eventListeners[Event.ROAP_FAILURE]);
|
|
3616
|
+
assert.isFunction(eventListeners[Event.ROAP_MESSAGE_TO_SEND]);
|
|
3617
|
+
assert.isFunction(eventListeners[Event.REMOTE_TRACK_ADDED]);
|
|
3618
|
+
assert.isFunction(eventListeners[Event.CONNECTION_STATE_CHANGED]);
|
|
3540
3619
|
});
|
|
3541
3620
|
|
|
3542
3621
|
it('should trigger a media:ready event when REMOTE_TRACK_ADDED is fired', () => {
|
|
3543
3622
|
meeting.setupMediaConnectionListeners();
|
|
3544
|
-
eventListeners[
|
|
3623
|
+
eventListeners[Event.REMOTE_TRACK_ADDED]({
|
|
3545
3624
|
track: 'track',
|
|
3546
|
-
type:
|
|
3625
|
+
type: RemoteTrackType.AUDIO,
|
|
3547
3626
|
});
|
|
3548
3627
|
assert.equal(TriggerProxy.trigger.getCall(1).args[2], 'media:ready');
|
|
3549
3628
|
assert.deepEqual(TriggerProxy.trigger.getCall(1).args[3], {
|
|
@@ -3551,9 +3630,9 @@ describe('plugin-meetings', () => {
|
|
|
3551
3630
|
stream: true,
|
|
3552
3631
|
});
|
|
3553
3632
|
|
|
3554
|
-
eventListeners[
|
|
3633
|
+
eventListeners[Event.REMOTE_TRACK_ADDED]({
|
|
3555
3634
|
track: 'track',
|
|
3556
|
-
type:
|
|
3635
|
+
type: RemoteTrackType.VIDEO,
|
|
3557
3636
|
});
|
|
3558
3637
|
assert.equal(TriggerProxy.trigger.getCall(2).args[2], 'media:ready');
|
|
3559
3638
|
assert.deepEqual(TriggerProxy.trigger.getCall(2).args[3], {
|
|
@@ -3561,9 +3640,9 @@ describe('plugin-meetings', () => {
|
|
|
3561
3640
|
stream: true,
|
|
3562
3641
|
});
|
|
3563
3642
|
|
|
3564
|
-
eventListeners[
|
|
3643
|
+
eventListeners[Event.REMOTE_TRACK_ADDED]({
|
|
3565
3644
|
track: 'track',
|
|
3566
|
-
type:
|
|
3645
|
+
type: RemoteTrackType.SCREENSHARE_VIDEO,
|
|
3567
3646
|
});
|
|
3568
3647
|
assert.equal(TriggerProxy.trigger.getCall(3).args[2], 'media:ready');
|
|
3569
3648
|
assert.deepEqual(TriggerProxy.trigger.getCall(3).args[3], {
|
|
@@ -3613,51 +3692,51 @@ describe('plugin-meetings', () => {
|
|
|
3613
3692
|
};
|
|
3614
3693
|
|
|
3615
3694
|
it('should send metrics for SdpOfferCreationError error', () => {
|
|
3616
|
-
const fakeError = new
|
|
3695
|
+
const fakeError = new Errors.SdpOfferCreationError(fakeErrorMessage, {
|
|
3617
3696
|
name: fakeErrorName,
|
|
3618
3697
|
cause: {name: fakeRootCauseName},
|
|
3619
3698
|
});
|
|
3620
3699
|
|
|
3621
|
-
eventListeners[
|
|
3700
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3622
3701
|
|
|
3623
3702
|
checkMetricSent(eventType.LOCAL_SDP_GENERATED);
|
|
3624
3703
|
checkBehavioralMetricSent(
|
|
3625
3704
|
BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
|
|
3626
|
-
|
|
3705
|
+
Errors.ErrorCode.SdpOfferCreationError,
|
|
3627
3706
|
fakeErrorMessage,
|
|
3628
3707
|
fakeRootCauseName
|
|
3629
3708
|
);
|
|
3630
3709
|
});
|
|
3631
3710
|
|
|
3632
3711
|
it('should send metrics for SdpOfferHandlingError error', () => {
|
|
3633
|
-
const fakeError = new
|
|
3712
|
+
const fakeError = new Errors.SdpOfferHandlingError(fakeErrorMessage, {
|
|
3634
3713
|
name: fakeErrorName,
|
|
3635
3714
|
cause: {name: fakeRootCauseName},
|
|
3636
3715
|
});
|
|
3637
3716
|
|
|
3638
|
-
eventListeners[
|
|
3717
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3639
3718
|
|
|
3640
3719
|
checkMetricSent(eventType.REMOTE_SDP_RECEIVED);
|
|
3641
3720
|
checkBehavioralMetricSent(
|
|
3642
3721
|
BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
|
|
3643
|
-
|
|
3722
|
+
Errors.ErrorCode.SdpOfferHandlingError,
|
|
3644
3723
|
fakeErrorMessage,
|
|
3645
3724
|
fakeRootCauseName
|
|
3646
3725
|
);
|
|
3647
3726
|
});
|
|
3648
3727
|
|
|
3649
3728
|
it('should send metrics for SdpAnswerHandlingError error', () => {
|
|
3650
|
-
const fakeError = new
|
|
3729
|
+
const fakeError = new Errors.SdpAnswerHandlingError(fakeErrorMessage, {
|
|
3651
3730
|
name: fakeErrorName,
|
|
3652
3731
|
cause: {name: fakeRootCauseName},
|
|
3653
3732
|
});
|
|
3654
3733
|
|
|
3655
|
-
eventListeners[
|
|
3734
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3656
3735
|
|
|
3657
3736
|
checkMetricSent(eventType.REMOTE_SDP_RECEIVED);
|
|
3658
3737
|
checkBehavioralMetricSent(
|
|
3659
3738
|
BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
|
|
3660
|
-
|
|
3739
|
+
Errors.ErrorCode.SdpAnswerHandlingError,
|
|
3661
3740
|
fakeErrorMessage,
|
|
3662
3741
|
fakeRootCauseName
|
|
3663
3742
|
);
|
|
@@ -3665,15 +3744,15 @@ describe('plugin-meetings', () => {
|
|
|
3665
3744
|
|
|
3666
3745
|
it('should send metrics for SdpError error', () => {
|
|
3667
3746
|
// SdpError is usually without a cause
|
|
3668
|
-
const fakeError = new
|
|
3747
|
+
const fakeError = new Errors.SdpError(fakeErrorMessage, {name: fakeErrorName});
|
|
3669
3748
|
|
|
3670
|
-
eventListeners[
|
|
3749
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3671
3750
|
|
|
3672
3751
|
checkMetricSent(eventType.LOCAL_SDP_GENERATED);
|
|
3673
3752
|
// expectedMetadataType is the error name in this case
|
|
3674
3753
|
checkBehavioralMetricSent(
|
|
3675
3754
|
BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE,
|
|
3676
|
-
|
|
3755
|
+
Errors.ErrorCode.SdpError,
|
|
3677
3756
|
fakeErrorMessage,
|
|
3678
3757
|
fakeErrorName
|
|
3679
3758
|
);
|
|
@@ -3681,24 +3760,24 @@ describe('plugin-meetings', () => {
|
|
|
3681
3760
|
|
|
3682
3761
|
it('should send metrics for IceGatheringError error', () => {
|
|
3683
3762
|
// IceGatheringError is usually without a cause
|
|
3684
|
-
const fakeError = new
|
|
3763
|
+
const fakeError = new Errors.IceGatheringError(fakeErrorMessage, {
|
|
3685
3764
|
name: fakeErrorName,
|
|
3686
3765
|
});
|
|
3687
3766
|
|
|
3688
|
-
eventListeners[
|
|
3767
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3689
3768
|
|
|
3690
3769
|
checkMetricSent(eventType.LOCAL_SDP_GENERATED);
|
|
3691
3770
|
// expectedMetadataType is the error name in this case
|
|
3692
3771
|
checkBehavioralMetricSent(
|
|
3693
3772
|
BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE,
|
|
3694
|
-
|
|
3773
|
+
Errors.ErrorCode.IceGatheringError,
|
|
3695
3774
|
fakeErrorMessage,
|
|
3696
3775
|
fakeErrorName
|
|
3697
3776
|
);
|
|
3698
3777
|
});
|
|
3699
3778
|
});
|
|
3700
3779
|
|
|
3701
|
-
describe('handles
|
|
3780
|
+
describe('handles Event.ROAP_MESSAGE_TO_SEND correctly', () => {
|
|
3702
3781
|
let sendRoapOKStub;
|
|
3703
3782
|
let sendRoapMediaRequestStub;
|
|
3704
3783
|
let sendRoapAnswerStub;
|
|
@@ -3716,7 +3795,7 @@ describe('plugin-meetings', () => {
|
|
|
3716
3795
|
});
|
|
3717
3796
|
|
|
3718
3797
|
it('handles OK message correctly', () => {
|
|
3719
|
-
eventListeners[
|
|
3798
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3720
3799
|
roapMessage: {messageType: 'OK', seq: 1},
|
|
3721
3800
|
});
|
|
3722
3801
|
|
|
@@ -3735,7 +3814,7 @@ describe('plugin-meetings', () => {
|
|
|
3735
3814
|
});
|
|
3736
3815
|
|
|
3737
3816
|
it('handles OFFER message correctly', () => {
|
|
3738
|
-
eventListeners[
|
|
3817
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3739
3818
|
roapMessage: {
|
|
3740
3819
|
messageType: 'OFFER',
|
|
3741
3820
|
seq: 1,
|
|
@@ -3761,7 +3840,7 @@ describe('plugin-meetings', () => {
|
|
|
3761
3840
|
});
|
|
3762
3841
|
|
|
3763
3842
|
it('handles ANSWER message correctly', () => {
|
|
3764
|
-
eventListeners[
|
|
3843
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3765
3844
|
roapMessage: {
|
|
3766
3845
|
messageType: 'ANSWER',
|
|
3767
3846
|
seq: 10,
|
|
@@ -3788,7 +3867,7 @@ describe('plugin-meetings', () => {
|
|
|
3788
3867
|
it('sends metrics if fails to send roap ANSWER message', async () => {
|
|
3789
3868
|
sendRoapAnswerStub.rejects(new Error('sending answer failed'));
|
|
3790
3869
|
|
|
3791
|
-
await eventListeners[
|
|
3870
|
+
await eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3792
3871
|
roapMessage: {
|
|
3793
3872
|
messageType: 'ANSWER',
|
|
3794
3873
|
seq: 10,
|
|
@@ -3810,9 +3889,9 @@ describe('plugin-meetings', () => {
|
|
|
3810
3889
|
);
|
|
3811
3890
|
});
|
|
3812
3891
|
|
|
3813
|
-
[
|
|
3892
|
+
[ErrorType.CONFLICT, ErrorType.DOUBLECONFLICT].forEach((errorType) =>
|
|
3814
3893
|
it(`handles ERROR message indicating glare condition correctly (errorType=${errorType})`, () => {
|
|
3815
|
-
eventListeners[
|
|
3894
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3816
3895
|
roapMessage: {
|
|
3817
3896
|
messageType: 'ERROR',
|
|
3818
3897
|
seq: 10,
|
|
@@ -3843,11 +3922,11 @@ describe('plugin-meetings', () => {
|
|
|
3843
3922
|
);
|
|
3844
3923
|
|
|
3845
3924
|
it('handles ERROR message indicating other errors correctly', () => {
|
|
3846
|
-
eventListeners[
|
|
3925
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3847
3926
|
roapMessage: {
|
|
3848
3927
|
messageType: 'ERROR',
|
|
3849
3928
|
seq: 10,
|
|
3850
|
-
errorType:
|
|
3929
|
+
errorType: ErrorType.FAILED,
|
|
3851
3930
|
tieBreaker: 12345,
|
|
3852
3931
|
},
|
|
3853
3932
|
});
|
|
@@ -3857,7 +3936,7 @@ describe('plugin-meetings', () => {
|
|
|
3857
3936
|
assert.calledOnce(sendRoapErrorStub);
|
|
3858
3937
|
assert.calledWith(sendRoapErrorStub, {
|
|
3859
3938
|
seq: 10,
|
|
3860
|
-
errorType:
|
|
3939
|
+
errorType: ErrorType.FAILED,
|
|
3861
3940
|
mediaId: meeting.mediaId,
|
|
3862
3941
|
correlationId: meeting.correlationId,
|
|
3863
3942
|
});
|
|
@@ -3893,6 +3972,83 @@ describe('plugin-meetings', () => {
|
|
|
3893
3972
|
);
|
|
3894
3973
|
done();
|
|
3895
3974
|
});
|
|
3975
|
+
|
|
3976
|
+
it('listens to the breakouts changed event', () => {
|
|
3977
|
+
meeting.breakouts.updateBreakoutSessions = sinon.stub();
|
|
3978
|
+
|
|
3979
|
+
const payload = 'payload';
|
|
3980
|
+
|
|
3981
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'SELF_MEETING_BREAKOUTS_CHANGED', payload);
|
|
3982
|
+
|
|
3983
|
+
assert.calledOnceWithExactly(meeting.breakouts.updateBreakoutSessions, payload);
|
|
3984
|
+
assert.calledWith(
|
|
3985
|
+
TriggerProxy.trigger,
|
|
3986
|
+
meeting,
|
|
3987
|
+
{file: 'meeting/index', function: 'setUpLocusInfoSelfListener'},
|
|
3988
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
3989
|
+
);
|
|
3990
|
+
});
|
|
3991
|
+
});
|
|
3992
|
+
|
|
3993
|
+
describe('#setUpBreakoutsListener', () => {
|
|
3994
|
+
it('listens to the closing event from breakouts and triggers the closing event', () => {
|
|
3995
|
+
TriggerProxy.trigger.reset();
|
|
3996
|
+
meeting.breakouts.trigger('BREAKOUTS_CLOSING');
|
|
3997
|
+
|
|
3998
|
+
assert.calledWith(
|
|
3999
|
+
TriggerProxy.trigger,
|
|
4000
|
+
meeting,
|
|
4001
|
+
{file: 'meeting/index', function: 'setUpBreakoutsListener'},
|
|
4002
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_CLOSING
|
|
4003
|
+
);
|
|
4004
|
+
});
|
|
4005
|
+
|
|
4006
|
+
it('listens to the message event from breakouts and triggers the message event', () => {
|
|
4007
|
+
TriggerProxy.trigger.reset();
|
|
4008
|
+
|
|
4009
|
+
const messageEvent = 'message';
|
|
4010
|
+
|
|
4011
|
+
meeting.breakouts.trigger('MESSAGE', messageEvent);
|
|
4012
|
+
|
|
4013
|
+
assert.calledWith(
|
|
4014
|
+
TriggerProxy.trigger,
|
|
4015
|
+
meeting,
|
|
4016
|
+
{file: 'meeting/index', function: 'setUpBreakoutsListener'},
|
|
4017
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_MESSAGE,
|
|
4018
|
+
messageEvent
|
|
4019
|
+
);
|
|
4020
|
+
});
|
|
4021
|
+
|
|
4022
|
+
it('listens to the members update event from breakouts and triggers the breakouts update event', () => {
|
|
4023
|
+
TriggerProxy.trigger.reset();
|
|
4024
|
+
meeting.breakouts.trigger('MEMBERS_UPDATE');
|
|
4025
|
+
|
|
4026
|
+
assert.calledWith(
|
|
4027
|
+
TriggerProxy.trigger,
|
|
4028
|
+
meeting,
|
|
4029
|
+
{file: 'meeting/index', function: 'setUpBreakoutsListener'},
|
|
4030
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
4031
|
+
);
|
|
4032
|
+
});
|
|
4033
|
+
});
|
|
4034
|
+
|
|
4035
|
+
describe('#setupLocusControlsListener', () => {
|
|
4036
|
+
it('listens to the locus breakouts update event', () => {
|
|
4037
|
+
const locus = {
|
|
4038
|
+
breakout: 'breakout'
|
|
4039
|
+
};
|
|
4040
|
+
|
|
4041
|
+
meeting.breakouts.updateBreakout = sinon.stub();
|
|
4042
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'CONTROLS_MEETING_BREAKOUT_UPDATED', locus);
|
|
4043
|
+
|
|
4044
|
+
assert.calledOnceWithExactly(meeting.breakouts.updateBreakout, locus.breakout);
|
|
4045
|
+
assert.calledWith(
|
|
4046
|
+
TriggerProxy.trigger,
|
|
4047
|
+
meeting,
|
|
4048
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
4049
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
4050
|
+
);
|
|
4051
|
+
});
|
|
3896
4052
|
});
|
|
3897
4053
|
|
|
3898
4054
|
describe('#setUpLocusUrlListener', () => {
|
|
@@ -3900,18 +4056,47 @@ describe('plugin-meetings', () => {
|
|
|
3900
4056
|
const newLocusUrl = 'newLocusUrl/12345';
|
|
3901
4057
|
|
|
3902
4058
|
meeting.members = {locusUrlUpdate: sinon.stub().returns(Promise.resolve(test1))};
|
|
4059
|
+
meeting.recordingController = {setLocusUrl: sinon.stub().returns(undefined)};
|
|
3903
4060
|
|
|
3904
|
-
meeting.
|
|
3905
|
-
|
|
3906
|
-
|
|
4061
|
+
meeting.breakouts.locusUrlUpdate = sinon.stub();
|
|
4062
|
+
|
|
4063
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'LOCUS_INFO_UPDATE_URL', newLocusUrl);
|
|
4064
|
+
assert.calledWith(
|
|
4065
|
+
meeting.members.locusUrlUpdate,
|
|
3907
4066
|
newLocusUrl
|
|
3908
4067
|
);
|
|
4068
|
+
assert.calledOnceWithExactly(meeting.breakouts.locusUrlUpdate, newLocusUrl);
|
|
3909
4069
|
assert.calledWith(meeting.members.locusUrlUpdate, newLocusUrl);
|
|
4070
|
+
assert.calledWith(meeting.recordingController.setLocusUrl, newLocusUrl);
|
|
3910
4071
|
assert.equal(meeting.locusUrl, newLocusUrl);
|
|
3911
4072
|
assert(meeting.locusId, '12345');
|
|
3912
4073
|
done();
|
|
3913
4074
|
});
|
|
3914
4075
|
});
|
|
4076
|
+
|
|
4077
|
+
describe('#setUpLocusServicesListener', () => {
|
|
4078
|
+
it('listens to the locus services update event', (done) => {
|
|
4079
|
+
const newLocusServices = {
|
|
4080
|
+
services: {
|
|
4081
|
+
record: {
|
|
4082
|
+
url: 'url',
|
|
4083
|
+
}
|
|
4084
|
+
},
|
|
4085
|
+
};
|
|
4086
|
+
|
|
4087
|
+
meeting.recordingController = {setServiceUrl: sinon.stub().returns(undefined), setSessionId: sinon.stub().returns(undefined)};
|
|
4088
|
+
|
|
4089
|
+
meeting.locusInfo.emit(
|
|
4090
|
+
{function: 'test', file: 'test'},
|
|
4091
|
+
'LINKS_SERVICES',
|
|
4092
|
+
newLocusServices
|
|
4093
|
+
);
|
|
4094
|
+
|
|
4095
|
+
assert.calledWith(meeting.recordingController.setServiceUrl, newLocusServices.services.record.url);
|
|
4096
|
+
assert.calledOnce(meeting.recordingController.setSessionId);
|
|
4097
|
+
done();
|
|
4098
|
+
});
|
|
4099
|
+
});
|
|
3915
4100
|
describe('#setUpLocusInfoMediaInactiveListener', () => {
|
|
3916
4101
|
it('listens to disconnect due to un activity ', (done) => {
|
|
3917
4102
|
TriggerProxy.trigger.reset();
|
|
@@ -4319,7 +4504,7 @@ describe('plugin-meetings', () => {
|
|
|
4319
4504
|
let inMeetingActionsSetSpy;
|
|
4320
4505
|
let canUserLockSpy;
|
|
4321
4506
|
let canUserUnlockSpy;
|
|
4322
|
-
let
|
|
4507
|
+
let canUserStartSpy;
|
|
4323
4508
|
let canUserStopSpy;
|
|
4324
4509
|
let canUserPauseSpy;
|
|
4325
4510
|
let canUserResumeSpy;
|
|
@@ -4329,15 +4514,17 @@ describe('plugin-meetings', () => {
|
|
|
4329
4514
|
let canUserLowerSomeoneElsesHandSpy;
|
|
4330
4515
|
let waitingForOthersToJoinSpy;
|
|
4331
4516
|
let handleDataChannelUrlChangeSpy;
|
|
4517
|
+
let canEnableReactionsSpy;
|
|
4518
|
+
let canSendReactionsSpy;
|
|
4332
4519
|
|
|
4333
4520
|
beforeEach(() => {
|
|
4334
4521
|
locusInfoOnSpy = sinon.spy(meeting.locusInfo, 'on');
|
|
4335
4522
|
canUserLockSpy = sinon.spy(MeetingUtil, 'canUserLock');
|
|
4336
4523
|
canUserUnlockSpy = sinon.spy(MeetingUtil, 'canUserUnlock');
|
|
4337
|
-
|
|
4338
|
-
canUserStopSpy = sinon.spy(
|
|
4339
|
-
canUserPauseSpy = sinon.spy(
|
|
4340
|
-
canUserResumeSpy = sinon.spy(
|
|
4524
|
+
canUserStartSpy = sinon.spy(RecordingUtil, 'canUserStart');
|
|
4525
|
+
canUserStopSpy = sinon.spy(RecordingUtil, 'canUserStop');
|
|
4526
|
+
canUserPauseSpy = sinon.spy(RecordingUtil, 'canUserPause');
|
|
4527
|
+
canUserResumeSpy = sinon.spy(RecordingUtil, 'canUserResume');
|
|
4341
4528
|
inMeetingActionsSetSpy = sinon.spy(meeting.inMeetingActions, 'set');
|
|
4342
4529
|
canUserRaiseHandSpy = sinon.spy(MeetingUtil, 'canUserRaiseHand');
|
|
4343
4530
|
canUserLowerAllHandsSpy = sinon.spy(MeetingUtil, 'canUserLowerAllHands');
|
|
@@ -4348,6 +4535,8 @@ describe('plugin-meetings', () => {
|
|
|
4348
4535
|
canUserLowerSomeoneElsesHandSpy = sinon.spy(MeetingUtil, 'canUserLowerSomeoneElsesHand');
|
|
4349
4536
|
waitingForOthersToJoinSpy = sinon.spy(MeetingUtil, 'waitingForOthersToJoin');
|
|
4350
4537
|
handleDataChannelUrlChangeSpy = sinon.spy(meeting, 'handleDataChannelUrlChange');
|
|
4538
|
+
canEnableReactionsSpy = sinon.spy(MeetingUtil, 'canEnableReactions');
|
|
4539
|
+
canSendReactionsSpy = sinon.spy(MeetingUtil, 'canSendReactions');
|
|
4351
4540
|
});
|
|
4352
4541
|
|
|
4353
4542
|
afterEach(() => {
|
|
@@ -4377,7 +4566,7 @@ describe('plugin-meetings', () => {
|
|
|
4377
4566
|
|
|
4378
4567
|
assert.calledWith(canUserLockSpy, payload.info.userDisplayHints);
|
|
4379
4568
|
assert.calledWith(canUserUnlockSpy, payload.info.userDisplayHints);
|
|
4380
|
-
assert.calledWith(
|
|
4569
|
+
assert.calledWith(canUserStartSpy, payload.info.userDisplayHints);
|
|
4381
4570
|
assert.calledWith(canUserStopSpy, payload.info.userDisplayHints);
|
|
4382
4571
|
assert.calledWith(canUserPauseSpy, payload.info.userDisplayHints);
|
|
4383
4572
|
assert.calledWith(canUserResumeSpy, payload.info.userDisplayHints);
|
|
@@ -4387,6 +4576,8 @@ describe('plugin-meetings', () => {
|
|
|
4387
4576
|
assert.calledWith(canUserLowerSomeoneElsesHandSpy, payload.info.userDisplayHints);
|
|
4388
4577
|
assert.calledWith(waitingForOthersToJoinSpy, payload.info.userDisplayHints);
|
|
4389
4578
|
assert.calledWith(handleDataChannelUrlChangeSpy, payload.info.datachannelUrl);
|
|
4579
|
+
assert.calledWith(canEnableReactionsSpy, null, payload.info.userDisplayHints);
|
|
4580
|
+
assert.calledWith(canSendReactionsSpy, null, payload.info.userDisplayHints);
|
|
4390
4581
|
|
|
4391
4582
|
assert.calledWith(
|
|
4392
4583
|
TriggerProxy.trigger,
|
|
@@ -190,6 +190,23 @@ describe('plugin-meetings', () => {
|
|
|
190
190
|
assert.equal(requestParams.uri, 'locusUrl/loci/call?alternateRedirect=true');
|
|
191
191
|
assert.equal(requestParams.body.invitee.address, 'sipUrl');
|
|
192
192
|
});
|
|
193
|
+
|
|
194
|
+
it('adds deviceCapabilities to request when breakouts are supported', async () => {
|
|
195
|
+
await meetingsRequest.joinMeeting({
|
|
196
|
+
breakoutsSupported: true
|
|
197
|
+
});
|
|
198
|
+
const requestParams = meetingsRequest.request.getCall(0).args[0];
|
|
199
|
+
|
|
200
|
+
assert.deepEqual(requestParams.body.deviceCapabilities, ['BREAKOUTS_SUPPORTED']);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('does not add deviceCapabilities to request when breakouts are not supported', async () => {
|
|
204
|
+
await meetingsRequest.joinMeeting({});
|
|
205
|
+
|
|
206
|
+
const requestParams = meetingsRequest.request.getCall(0).args[0];
|
|
207
|
+
|
|
208
|
+
assert.deepEqual(requestParams.body.deviceCapabilities, undefined);
|
|
209
|
+
});
|
|
193
210
|
});
|
|
194
211
|
|
|
195
212
|
describe('#pstn', () => {
|