@webex/plugin-meetings 3.0.0-beta.17 → 3.0.0-beta.19
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 +38 -5
- 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/index.js +719 -490
- 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 +4 -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 +35 -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/index.ts +398 -129
- package/src/meeting/request.ts +9 -31
- package/src/meeting/request.type.ts +2 -0
- package/src/meeting/util.ts +3 -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/index.js +419 -50
- package/test/unit/spec/meeting/request.js +17 -0
- package/test/unit/spec/meeting/utils.js +20 -129
- 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: {},
|
|
@@ -2130,6 +2209,190 @@ describe('plugin-meetings', () => {
|
|
|
2130
2209
|
);
|
|
2131
2210
|
assert.isTrue(myPromiseResolved);
|
|
2132
2211
|
});
|
|
2212
|
+
|
|
2213
|
+
it('should request floor only after roap transaction is completed', async () => {
|
|
2214
|
+
const eventListeners = {};
|
|
2215
|
+
|
|
2216
|
+
meeting.webex.meetings.reachability = {
|
|
2217
|
+
isAnyClusterReachable: sandbox.stub().resolves(true)
|
|
2218
|
+
};
|
|
2219
|
+
|
|
2220
|
+
const fakeMediaConnection = {
|
|
2221
|
+
close: sinon.stub(),
|
|
2222
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
2223
|
+
initiateOffer: sinon.stub().resolves({}),
|
|
2224
|
+
|
|
2225
|
+
// mock the on() method and store all the listeners
|
|
2226
|
+
on: sinon.stub().callsFake((event, listener) => {
|
|
2227
|
+
eventListeners[event] = listener;
|
|
2228
|
+
}),
|
|
2229
|
+
|
|
2230
|
+
updateSendReceiveOptions: sinon.stub().callsFake(() => {
|
|
2231
|
+
// trigger ROAP_STARTED before updateSendReceiveOptions() resolves
|
|
2232
|
+
if (eventListeners[Event.ROAP_STARTED]) {
|
|
2233
|
+
eventListeners[Event.ROAP_STARTED]();
|
|
2234
|
+
} else {
|
|
2235
|
+
throw new Error('ROAP_STARTED listener not registered')
|
|
2236
|
+
}
|
|
2237
|
+
return Promise.resolve();
|
|
2238
|
+
}),
|
|
2239
|
+
};
|
|
2240
|
+
|
|
2241
|
+
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
|
|
2242
|
+
meeting.mediaProperties.getCurrentConnectionType = sinon.stub().resolves('udp');
|
|
2243
|
+
Media.createMediaConnection = sinon.stub().returns(fakeMediaConnection);
|
|
2244
|
+
|
|
2245
|
+
const requestScreenShareFloorStub = sandbox.stub(meeting, 'requestScreenShareFloor').resolves({});
|
|
2246
|
+
|
|
2247
|
+
let myPromiseResolved = false;
|
|
2248
|
+
|
|
2249
|
+
meeting.meetingState = 'ACTIVE';
|
|
2250
|
+
await meeting.addMedia({
|
|
2251
|
+
mediaSettings: {},
|
|
2252
|
+
});
|
|
2253
|
+
|
|
2254
|
+
meeting
|
|
2255
|
+
.updateMedia({
|
|
2256
|
+
localShare: mockLocalShare,
|
|
2257
|
+
mediaSettings: {
|
|
2258
|
+
sendShare: true,
|
|
2259
|
+
},
|
|
2260
|
+
})
|
|
2261
|
+
.then(() => {
|
|
2262
|
+
myPromiseResolved = true;
|
|
2263
|
+
});
|
|
2264
|
+
|
|
2265
|
+
await testUtils.flushPromises();
|
|
2266
|
+
|
|
2267
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
|
|
2268
|
+
assert.isFalse(myPromiseResolved);
|
|
2269
|
+
|
|
2270
|
+
// verify that requestScreenShareFloorStub was not called yet
|
|
2271
|
+
assert.notCalled(requestScreenShareFloorStub);
|
|
2272
|
+
|
|
2273
|
+
eventListeners[Event.ROAP_DONE]();
|
|
2274
|
+
await testUtils.flushPromises();
|
|
2275
|
+
|
|
2276
|
+
// now it should have been called
|
|
2277
|
+
assert.calledOnce(requestScreenShareFloorStub);
|
|
2278
|
+
});
|
|
2279
|
+
});
|
|
2280
|
+
|
|
2281
|
+
describe('#updateShare', () => {
|
|
2282
|
+
const mockLocalShare = {id: 'mock local share stream'};
|
|
2283
|
+
let eventListeners;
|
|
2284
|
+
let fakeMediaConnection;
|
|
2285
|
+
let requestScreenShareFloorStub;
|
|
2286
|
+
|
|
2287
|
+
const FAKE_TRACKS = {
|
|
2288
|
+
screenshareVideo: {
|
|
2289
|
+
id: 'fake share track',
|
|
2290
|
+
getSettings: sinon.stub().returns({}),
|
|
2291
|
+
},
|
|
2292
|
+
};
|
|
2293
|
+
|
|
2294
|
+
beforeEach(async () => {
|
|
2295
|
+
eventListeners = {};
|
|
2296
|
+
|
|
2297
|
+
sinon.stub(MeetingUtil, 'getTrack').callsFake((stream) => {
|
|
2298
|
+
if (stream === mockLocalShare) {
|
|
2299
|
+
return {audioTrack: null, videoTrack: FAKE_TRACKS.screenshareVideo};
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
return {audioTrack: null, videoTrack: null};
|
|
2303
|
+
});
|
|
2304
|
+
|
|
2305
|
+
meeting.webex.meetings.reachability = {
|
|
2306
|
+
isAnyClusterReachable: sinon.stub().resolves(true)
|
|
2307
|
+
};
|
|
2308
|
+
|
|
2309
|
+
fakeMediaConnection = {
|
|
2310
|
+
close: sinon.stub(),
|
|
2311
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
2312
|
+
initiateOffer: sinon.stub().resolves({}),
|
|
2313
|
+
|
|
2314
|
+
// mock the on() method and store all the listeners
|
|
2315
|
+
on: sinon.stub().callsFake((event, listener) => {
|
|
2316
|
+
eventListeners[event] = listener;
|
|
2317
|
+
}),
|
|
2318
|
+
|
|
2319
|
+
updateSendReceiveOptions: sinon.stub().callsFake(() => {
|
|
2320
|
+
// trigger ROAP_STARTED before updateSendReceiveOptions() resolves
|
|
2321
|
+
if (eventListeners[Event.ROAP_STARTED]) {
|
|
2322
|
+
eventListeners[Event.ROAP_STARTED]();
|
|
2323
|
+
} else {
|
|
2324
|
+
throw new Error('ROAP_STARTED listener not registered')
|
|
2325
|
+
}
|
|
2326
|
+
return Promise.resolve();
|
|
2327
|
+
}),
|
|
2328
|
+
};
|
|
2329
|
+
|
|
2330
|
+
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
|
|
2331
|
+
meeting.mediaProperties.getCurrentConnectionType = sinon.stub().resolves('udp');
|
|
2332
|
+
Media.createMediaConnection = sinon.stub().returns(fakeMediaConnection);
|
|
2333
|
+
|
|
2334
|
+
requestScreenShareFloorStub = sinon.stub(meeting, 'requestScreenShareFloor').resolves({});
|
|
2335
|
+
|
|
2336
|
+
meeting.meetingState = 'ACTIVE';
|
|
2337
|
+
await meeting.addMedia({
|
|
2338
|
+
mediaSettings: {},
|
|
2339
|
+
});
|
|
2340
|
+
});
|
|
2341
|
+
|
|
2342
|
+
afterEach(() => {
|
|
2343
|
+
sinon.restore();
|
|
2344
|
+
});
|
|
2345
|
+
|
|
2346
|
+
it('when starting share, it should request floor only after roap transaction is completed', async () => {
|
|
2347
|
+
let myPromiseResolved = false;
|
|
2348
|
+
|
|
2349
|
+
meeting
|
|
2350
|
+
.updateShare({
|
|
2351
|
+
sendShare: true,
|
|
2352
|
+
receiveShare: true,
|
|
2353
|
+
stream: mockLocalShare,
|
|
2354
|
+
})
|
|
2355
|
+
.then(() => {
|
|
2356
|
+
myPromiseResolved = true;
|
|
2357
|
+
});
|
|
2358
|
+
|
|
2359
|
+
await testUtils.flushPromises();
|
|
2360
|
+
|
|
2361
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
|
|
2362
|
+
assert.isFalse(myPromiseResolved);
|
|
2363
|
+
|
|
2364
|
+
// verify that requestScreenShareFloorStub was not called yet
|
|
2365
|
+
assert.notCalled(requestScreenShareFloorStub);
|
|
2366
|
+
|
|
2367
|
+
eventListeners[Event.ROAP_DONE]();
|
|
2368
|
+
await testUtils.flushPromises();
|
|
2369
|
+
|
|
2370
|
+
// now it should have been called
|
|
2371
|
+
assert.calledOnce(requestScreenShareFloorStub);
|
|
2372
|
+
});
|
|
2373
|
+
|
|
2374
|
+
it('when changing screen share stream and no roap transaction happening, it requests floor immediately', async () => {
|
|
2375
|
+
let myPromiseResolved = false;
|
|
2376
|
+
|
|
2377
|
+
// simulate a case when no roap transaction is triggered by updateSendReceiveOptions
|
|
2378
|
+
meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions = sinon.stub().resolves({});
|
|
2379
|
+
|
|
2380
|
+
meeting
|
|
2381
|
+
.updateShare({
|
|
2382
|
+
sendShare: true,
|
|
2383
|
+
receiveShare: true,
|
|
2384
|
+
stream: mockLocalShare,
|
|
2385
|
+
})
|
|
2386
|
+
.then(() => {
|
|
2387
|
+
myPromiseResolved = true;
|
|
2388
|
+
});
|
|
2389
|
+
|
|
2390
|
+
await testUtils.flushPromises();
|
|
2391
|
+
|
|
2392
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
|
|
2393
|
+
assert.calledOnce(requestScreenShareFloorStub);
|
|
2394
|
+
assert.isTrue(myPromiseResolved);
|
|
2395
|
+
});
|
|
2133
2396
|
});
|
|
2134
2397
|
|
|
2135
2398
|
describe('#changeVideoLayout', () => {
|
|
@@ -3531,19 +3794,19 @@ describe('plugin-meetings', () => {
|
|
|
3531
3794
|
|
|
3532
3795
|
it('should register for all the correct RoapMediaConnection events', () => {
|
|
3533
3796
|
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[
|
|
3797
|
+
assert.isFunction(eventListeners[Event.ROAP_STARTED]);
|
|
3798
|
+
assert.isFunction(eventListeners[Event.ROAP_DONE]);
|
|
3799
|
+
assert.isFunction(eventListeners[Event.ROAP_FAILURE]);
|
|
3800
|
+
assert.isFunction(eventListeners[Event.ROAP_MESSAGE_TO_SEND]);
|
|
3801
|
+
assert.isFunction(eventListeners[Event.REMOTE_TRACK_ADDED]);
|
|
3802
|
+
assert.isFunction(eventListeners[Event.CONNECTION_STATE_CHANGED]);
|
|
3540
3803
|
});
|
|
3541
3804
|
|
|
3542
3805
|
it('should trigger a media:ready event when REMOTE_TRACK_ADDED is fired', () => {
|
|
3543
3806
|
meeting.setupMediaConnectionListeners();
|
|
3544
|
-
eventListeners[
|
|
3807
|
+
eventListeners[Event.REMOTE_TRACK_ADDED]({
|
|
3545
3808
|
track: 'track',
|
|
3546
|
-
type:
|
|
3809
|
+
type: RemoteTrackType.AUDIO,
|
|
3547
3810
|
});
|
|
3548
3811
|
assert.equal(TriggerProxy.trigger.getCall(1).args[2], 'media:ready');
|
|
3549
3812
|
assert.deepEqual(TriggerProxy.trigger.getCall(1).args[3], {
|
|
@@ -3551,9 +3814,9 @@ describe('plugin-meetings', () => {
|
|
|
3551
3814
|
stream: true,
|
|
3552
3815
|
});
|
|
3553
3816
|
|
|
3554
|
-
eventListeners[
|
|
3817
|
+
eventListeners[Event.REMOTE_TRACK_ADDED]({
|
|
3555
3818
|
track: 'track',
|
|
3556
|
-
type:
|
|
3819
|
+
type: RemoteTrackType.VIDEO,
|
|
3557
3820
|
});
|
|
3558
3821
|
assert.equal(TriggerProxy.trigger.getCall(2).args[2], 'media:ready');
|
|
3559
3822
|
assert.deepEqual(TriggerProxy.trigger.getCall(2).args[3], {
|
|
@@ -3561,9 +3824,9 @@ describe('plugin-meetings', () => {
|
|
|
3561
3824
|
stream: true,
|
|
3562
3825
|
});
|
|
3563
3826
|
|
|
3564
|
-
eventListeners[
|
|
3827
|
+
eventListeners[Event.REMOTE_TRACK_ADDED]({
|
|
3565
3828
|
track: 'track',
|
|
3566
|
-
type:
|
|
3829
|
+
type: RemoteTrackType.SCREENSHARE_VIDEO,
|
|
3567
3830
|
});
|
|
3568
3831
|
assert.equal(TriggerProxy.trigger.getCall(3).args[2], 'media:ready');
|
|
3569
3832
|
assert.deepEqual(TriggerProxy.trigger.getCall(3).args[3], {
|
|
@@ -3613,51 +3876,51 @@ describe('plugin-meetings', () => {
|
|
|
3613
3876
|
};
|
|
3614
3877
|
|
|
3615
3878
|
it('should send metrics for SdpOfferCreationError error', () => {
|
|
3616
|
-
const fakeError = new
|
|
3879
|
+
const fakeError = new Errors.SdpOfferCreationError(fakeErrorMessage, {
|
|
3617
3880
|
name: fakeErrorName,
|
|
3618
3881
|
cause: {name: fakeRootCauseName},
|
|
3619
3882
|
});
|
|
3620
3883
|
|
|
3621
|
-
eventListeners[
|
|
3884
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3622
3885
|
|
|
3623
3886
|
checkMetricSent(eventType.LOCAL_SDP_GENERATED);
|
|
3624
3887
|
checkBehavioralMetricSent(
|
|
3625
3888
|
BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
|
|
3626
|
-
|
|
3889
|
+
Errors.ErrorCode.SdpOfferCreationError,
|
|
3627
3890
|
fakeErrorMessage,
|
|
3628
3891
|
fakeRootCauseName
|
|
3629
3892
|
);
|
|
3630
3893
|
});
|
|
3631
3894
|
|
|
3632
3895
|
it('should send metrics for SdpOfferHandlingError error', () => {
|
|
3633
|
-
const fakeError = new
|
|
3896
|
+
const fakeError = new Errors.SdpOfferHandlingError(fakeErrorMessage, {
|
|
3634
3897
|
name: fakeErrorName,
|
|
3635
3898
|
cause: {name: fakeRootCauseName},
|
|
3636
3899
|
});
|
|
3637
3900
|
|
|
3638
|
-
eventListeners[
|
|
3901
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3639
3902
|
|
|
3640
3903
|
checkMetricSent(eventType.REMOTE_SDP_RECEIVED);
|
|
3641
3904
|
checkBehavioralMetricSent(
|
|
3642
3905
|
BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
|
|
3643
|
-
|
|
3906
|
+
Errors.ErrorCode.SdpOfferHandlingError,
|
|
3644
3907
|
fakeErrorMessage,
|
|
3645
3908
|
fakeRootCauseName
|
|
3646
3909
|
);
|
|
3647
3910
|
});
|
|
3648
3911
|
|
|
3649
3912
|
it('should send metrics for SdpAnswerHandlingError error', () => {
|
|
3650
|
-
const fakeError = new
|
|
3913
|
+
const fakeError = new Errors.SdpAnswerHandlingError(fakeErrorMessage, {
|
|
3651
3914
|
name: fakeErrorName,
|
|
3652
3915
|
cause: {name: fakeRootCauseName},
|
|
3653
3916
|
});
|
|
3654
3917
|
|
|
3655
|
-
eventListeners[
|
|
3918
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3656
3919
|
|
|
3657
3920
|
checkMetricSent(eventType.REMOTE_SDP_RECEIVED);
|
|
3658
3921
|
checkBehavioralMetricSent(
|
|
3659
3922
|
BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
|
|
3660
|
-
|
|
3923
|
+
Errors.ErrorCode.SdpAnswerHandlingError,
|
|
3661
3924
|
fakeErrorMessage,
|
|
3662
3925
|
fakeRootCauseName
|
|
3663
3926
|
);
|
|
@@ -3665,15 +3928,15 @@ describe('plugin-meetings', () => {
|
|
|
3665
3928
|
|
|
3666
3929
|
it('should send metrics for SdpError error', () => {
|
|
3667
3930
|
// SdpError is usually without a cause
|
|
3668
|
-
const fakeError = new
|
|
3931
|
+
const fakeError = new Errors.SdpError(fakeErrorMessage, {name: fakeErrorName});
|
|
3669
3932
|
|
|
3670
|
-
eventListeners[
|
|
3933
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3671
3934
|
|
|
3672
3935
|
checkMetricSent(eventType.LOCAL_SDP_GENERATED);
|
|
3673
3936
|
// expectedMetadataType is the error name in this case
|
|
3674
3937
|
checkBehavioralMetricSent(
|
|
3675
3938
|
BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE,
|
|
3676
|
-
|
|
3939
|
+
Errors.ErrorCode.SdpError,
|
|
3677
3940
|
fakeErrorMessage,
|
|
3678
3941
|
fakeErrorName
|
|
3679
3942
|
);
|
|
@@ -3681,24 +3944,24 @@ describe('plugin-meetings', () => {
|
|
|
3681
3944
|
|
|
3682
3945
|
it('should send metrics for IceGatheringError error', () => {
|
|
3683
3946
|
// IceGatheringError is usually without a cause
|
|
3684
|
-
const fakeError = new
|
|
3947
|
+
const fakeError = new Errors.IceGatheringError(fakeErrorMessage, {
|
|
3685
3948
|
name: fakeErrorName,
|
|
3686
3949
|
});
|
|
3687
3950
|
|
|
3688
|
-
eventListeners[
|
|
3951
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3689
3952
|
|
|
3690
3953
|
checkMetricSent(eventType.LOCAL_SDP_GENERATED);
|
|
3691
3954
|
// expectedMetadataType is the error name in this case
|
|
3692
3955
|
checkBehavioralMetricSent(
|
|
3693
3956
|
BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE,
|
|
3694
|
-
|
|
3957
|
+
Errors.ErrorCode.IceGatheringError,
|
|
3695
3958
|
fakeErrorMessage,
|
|
3696
3959
|
fakeErrorName
|
|
3697
3960
|
);
|
|
3698
3961
|
});
|
|
3699
3962
|
});
|
|
3700
3963
|
|
|
3701
|
-
describe('handles
|
|
3964
|
+
describe('handles Event.ROAP_MESSAGE_TO_SEND correctly', () => {
|
|
3702
3965
|
let sendRoapOKStub;
|
|
3703
3966
|
let sendRoapMediaRequestStub;
|
|
3704
3967
|
let sendRoapAnswerStub;
|
|
@@ -3716,7 +3979,7 @@ describe('plugin-meetings', () => {
|
|
|
3716
3979
|
});
|
|
3717
3980
|
|
|
3718
3981
|
it('handles OK message correctly', () => {
|
|
3719
|
-
eventListeners[
|
|
3982
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3720
3983
|
roapMessage: {messageType: 'OK', seq: 1},
|
|
3721
3984
|
});
|
|
3722
3985
|
|
|
@@ -3735,7 +3998,7 @@ describe('plugin-meetings', () => {
|
|
|
3735
3998
|
});
|
|
3736
3999
|
|
|
3737
4000
|
it('handles OFFER message correctly', () => {
|
|
3738
|
-
eventListeners[
|
|
4001
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3739
4002
|
roapMessage: {
|
|
3740
4003
|
messageType: 'OFFER',
|
|
3741
4004
|
seq: 1,
|
|
@@ -3761,7 +4024,7 @@ describe('plugin-meetings', () => {
|
|
|
3761
4024
|
});
|
|
3762
4025
|
|
|
3763
4026
|
it('handles ANSWER message correctly', () => {
|
|
3764
|
-
eventListeners[
|
|
4027
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3765
4028
|
roapMessage: {
|
|
3766
4029
|
messageType: 'ANSWER',
|
|
3767
4030
|
seq: 10,
|
|
@@ -3788,7 +4051,7 @@ describe('plugin-meetings', () => {
|
|
|
3788
4051
|
it('sends metrics if fails to send roap ANSWER message', async () => {
|
|
3789
4052
|
sendRoapAnswerStub.rejects(new Error('sending answer failed'));
|
|
3790
4053
|
|
|
3791
|
-
await eventListeners[
|
|
4054
|
+
await eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3792
4055
|
roapMessage: {
|
|
3793
4056
|
messageType: 'ANSWER',
|
|
3794
4057
|
seq: 10,
|
|
@@ -3810,9 +4073,9 @@ describe('plugin-meetings', () => {
|
|
|
3810
4073
|
);
|
|
3811
4074
|
});
|
|
3812
4075
|
|
|
3813
|
-
[
|
|
4076
|
+
[ErrorType.CONFLICT, ErrorType.DOUBLECONFLICT].forEach((errorType) =>
|
|
3814
4077
|
it(`handles ERROR message indicating glare condition correctly (errorType=${errorType})`, () => {
|
|
3815
|
-
eventListeners[
|
|
4078
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3816
4079
|
roapMessage: {
|
|
3817
4080
|
messageType: 'ERROR',
|
|
3818
4081
|
seq: 10,
|
|
@@ -3843,11 +4106,11 @@ describe('plugin-meetings', () => {
|
|
|
3843
4106
|
);
|
|
3844
4107
|
|
|
3845
4108
|
it('handles ERROR message indicating other errors correctly', () => {
|
|
3846
|
-
eventListeners[
|
|
4109
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3847
4110
|
roapMessage: {
|
|
3848
4111
|
messageType: 'ERROR',
|
|
3849
4112
|
seq: 10,
|
|
3850
|
-
errorType:
|
|
4113
|
+
errorType: ErrorType.FAILED,
|
|
3851
4114
|
tieBreaker: 12345,
|
|
3852
4115
|
},
|
|
3853
4116
|
});
|
|
@@ -3857,7 +4120,7 @@ describe('plugin-meetings', () => {
|
|
|
3857
4120
|
assert.calledOnce(sendRoapErrorStub);
|
|
3858
4121
|
assert.calledWith(sendRoapErrorStub, {
|
|
3859
4122
|
seq: 10,
|
|
3860
|
-
errorType:
|
|
4123
|
+
errorType: ErrorType.FAILED,
|
|
3861
4124
|
mediaId: meeting.mediaId,
|
|
3862
4125
|
correlationId: meeting.correlationId,
|
|
3863
4126
|
});
|
|
@@ -3893,6 +4156,83 @@ describe('plugin-meetings', () => {
|
|
|
3893
4156
|
);
|
|
3894
4157
|
done();
|
|
3895
4158
|
});
|
|
4159
|
+
|
|
4160
|
+
it('listens to the breakouts changed event', () => {
|
|
4161
|
+
meeting.breakouts.updateBreakoutSessions = sinon.stub();
|
|
4162
|
+
|
|
4163
|
+
const payload = 'payload';
|
|
4164
|
+
|
|
4165
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'SELF_MEETING_BREAKOUTS_CHANGED', payload);
|
|
4166
|
+
|
|
4167
|
+
assert.calledOnceWithExactly(meeting.breakouts.updateBreakoutSessions, payload);
|
|
4168
|
+
assert.calledWith(
|
|
4169
|
+
TriggerProxy.trigger,
|
|
4170
|
+
meeting,
|
|
4171
|
+
{file: 'meeting/index', function: 'setUpLocusInfoSelfListener'},
|
|
4172
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
4173
|
+
);
|
|
4174
|
+
});
|
|
4175
|
+
});
|
|
4176
|
+
|
|
4177
|
+
describe('#setUpBreakoutsListener', () => {
|
|
4178
|
+
it('listens to the closing event from breakouts and triggers the closing event', () => {
|
|
4179
|
+
TriggerProxy.trigger.reset();
|
|
4180
|
+
meeting.breakouts.trigger('BREAKOUTS_CLOSING');
|
|
4181
|
+
|
|
4182
|
+
assert.calledWith(
|
|
4183
|
+
TriggerProxy.trigger,
|
|
4184
|
+
meeting,
|
|
4185
|
+
{file: 'meeting/index', function: 'setUpBreakoutsListener'},
|
|
4186
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_CLOSING
|
|
4187
|
+
);
|
|
4188
|
+
});
|
|
4189
|
+
|
|
4190
|
+
it('listens to the message event from breakouts and triggers the message event', () => {
|
|
4191
|
+
TriggerProxy.trigger.reset();
|
|
4192
|
+
|
|
4193
|
+
const messageEvent = 'message';
|
|
4194
|
+
|
|
4195
|
+
meeting.breakouts.trigger('MESSAGE', messageEvent);
|
|
4196
|
+
|
|
4197
|
+
assert.calledWith(
|
|
4198
|
+
TriggerProxy.trigger,
|
|
4199
|
+
meeting,
|
|
4200
|
+
{file: 'meeting/index', function: 'setUpBreakoutsListener'},
|
|
4201
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_MESSAGE,
|
|
4202
|
+
messageEvent
|
|
4203
|
+
);
|
|
4204
|
+
});
|
|
4205
|
+
|
|
4206
|
+
it('listens to the members update event from breakouts and triggers the breakouts update event', () => {
|
|
4207
|
+
TriggerProxy.trigger.reset();
|
|
4208
|
+
meeting.breakouts.trigger('MEMBERS_UPDATE');
|
|
4209
|
+
|
|
4210
|
+
assert.calledWith(
|
|
4211
|
+
TriggerProxy.trigger,
|
|
4212
|
+
meeting,
|
|
4213
|
+
{file: 'meeting/index', function: 'setUpBreakoutsListener'},
|
|
4214
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
4215
|
+
);
|
|
4216
|
+
});
|
|
4217
|
+
});
|
|
4218
|
+
|
|
4219
|
+
describe('#setupLocusControlsListener', () => {
|
|
4220
|
+
it('listens to the locus breakouts update event', () => {
|
|
4221
|
+
const locus = {
|
|
4222
|
+
breakout: 'breakout'
|
|
4223
|
+
};
|
|
4224
|
+
|
|
4225
|
+
meeting.breakouts.updateBreakout = sinon.stub();
|
|
4226
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'CONTROLS_MEETING_BREAKOUT_UPDATED', locus);
|
|
4227
|
+
|
|
4228
|
+
assert.calledOnceWithExactly(meeting.breakouts.updateBreakout, locus.breakout);
|
|
4229
|
+
assert.calledWith(
|
|
4230
|
+
TriggerProxy.trigger,
|
|
4231
|
+
meeting,
|
|
4232
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
4233
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
4234
|
+
);
|
|
4235
|
+
});
|
|
3896
4236
|
});
|
|
3897
4237
|
|
|
3898
4238
|
describe('#setUpLocusUrlListener', () => {
|
|
@@ -3900,18 +4240,47 @@ describe('plugin-meetings', () => {
|
|
|
3900
4240
|
const newLocusUrl = 'newLocusUrl/12345';
|
|
3901
4241
|
|
|
3902
4242
|
meeting.members = {locusUrlUpdate: sinon.stub().returns(Promise.resolve(test1))};
|
|
4243
|
+
meeting.recordingController = {setLocusUrl: sinon.stub().returns(undefined)};
|
|
3903
4244
|
|
|
3904
|
-
meeting.
|
|
3905
|
-
|
|
3906
|
-
|
|
4245
|
+
meeting.breakouts.locusUrlUpdate = sinon.stub();
|
|
4246
|
+
|
|
4247
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'LOCUS_INFO_UPDATE_URL', newLocusUrl);
|
|
4248
|
+
assert.calledWith(
|
|
4249
|
+
meeting.members.locusUrlUpdate,
|
|
3907
4250
|
newLocusUrl
|
|
3908
4251
|
);
|
|
4252
|
+
assert.calledOnceWithExactly(meeting.breakouts.locusUrlUpdate, newLocusUrl);
|
|
3909
4253
|
assert.calledWith(meeting.members.locusUrlUpdate, newLocusUrl);
|
|
4254
|
+
assert.calledWith(meeting.recordingController.setLocusUrl, newLocusUrl);
|
|
3910
4255
|
assert.equal(meeting.locusUrl, newLocusUrl);
|
|
3911
4256
|
assert(meeting.locusId, '12345');
|
|
3912
4257
|
done();
|
|
3913
4258
|
});
|
|
3914
4259
|
});
|
|
4260
|
+
|
|
4261
|
+
describe('#setUpLocusServicesListener', () => {
|
|
4262
|
+
it('listens to the locus services update event', (done) => {
|
|
4263
|
+
const newLocusServices = {
|
|
4264
|
+
services: {
|
|
4265
|
+
record: {
|
|
4266
|
+
url: 'url',
|
|
4267
|
+
}
|
|
4268
|
+
},
|
|
4269
|
+
};
|
|
4270
|
+
|
|
4271
|
+
meeting.recordingController = {setServiceUrl: sinon.stub().returns(undefined), setSessionId: sinon.stub().returns(undefined)};
|
|
4272
|
+
|
|
4273
|
+
meeting.locusInfo.emit(
|
|
4274
|
+
{function: 'test', file: 'test'},
|
|
4275
|
+
'LINKS_SERVICES',
|
|
4276
|
+
newLocusServices
|
|
4277
|
+
);
|
|
4278
|
+
|
|
4279
|
+
assert.calledWith(meeting.recordingController.setServiceUrl, newLocusServices.services.record.url);
|
|
4280
|
+
assert.calledOnce(meeting.recordingController.setSessionId);
|
|
4281
|
+
done();
|
|
4282
|
+
});
|
|
4283
|
+
});
|
|
3915
4284
|
describe('#setUpLocusInfoMediaInactiveListener', () => {
|
|
3916
4285
|
it('listens to disconnect due to un activity ', (done) => {
|
|
3917
4286
|
TriggerProxy.trigger.reset();
|
|
@@ -4319,7 +4688,7 @@ describe('plugin-meetings', () => {
|
|
|
4319
4688
|
let inMeetingActionsSetSpy;
|
|
4320
4689
|
let canUserLockSpy;
|
|
4321
4690
|
let canUserUnlockSpy;
|
|
4322
|
-
let
|
|
4691
|
+
let canUserStartSpy;
|
|
4323
4692
|
let canUserStopSpy;
|
|
4324
4693
|
let canUserPauseSpy;
|
|
4325
4694
|
let canUserResumeSpy;
|
|
@@ -4336,10 +4705,10 @@ describe('plugin-meetings', () => {
|
|
|
4336
4705
|
locusInfoOnSpy = sinon.spy(meeting.locusInfo, 'on');
|
|
4337
4706
|
canUserLockSpy = sinon.spy(MeetingUtil, 'canUserLock');
|
|
4338
4707
|
canUserUnlockSpy = sinon.spy(MeetingUtil, 'canUserUnlock');
|
|
4339
|
-
|
|
4340
|
-
canUserStopSpy = sinon.spy(
|
|
4341
|
-
canUserPauseSpy = sinon.spy(
|
|
4342
|
-
canUserResumeSpy = sinon.spy(
|
|
4708
|
+
canUserStartSpy = sinon.spy(RecordingUtil, 'canUserStart');
|
|
4709
|
+
canUserStopSpy = sinon.spy(RecordingUtil, 'canUserStop');
|
|
4710
|
+
canUserPauseSpy = sinon.spy(RecordingUtil, 'canUserPause');
|
|
4711
|
+
canUserResumeSpy = sinon.spy(RecordingUtil, 'canUserResume');
|
|
4343
4712
|
inMeetingActionsSetSpy = sinon.spy(meeting.inMeetingActions, 'set');
|
|
4344
4713
|
canUserRaiseHandSpy = sinon.spy(MeetingUtil, 'canUserRaiseHand');
|
|
4345
4714
|
canUserLowerAllHandsSpy = sinon.spy(MeetingUtil, 'canUserLowerAllHands');
|
|
@@ -4381,7 +4750,7 @@ describe('plugin-meetings', () => {
|
|
|
4381
4750
|
|
|
4382
4751
|
assert.calledWith(canUserLockSpy, payload.info.userDisplayHints);
|
|
4383
4752
|
assert.calledWith(canUserUnlockSpy, payload.info.userDisplayHints);
|
|
4384
|
-
assert.calledWith(
|
|
4753
|
+
assert.calledWith(canUserStartSpy, payload.info.userDisplayHints);
|
|
4385
4754
|
assert.calledWith(canUserStopSpy, payload.info.userDisplayHints);
|
|
4386
4755
|
assert.calledWith(canUserPauseSpy, payload.info.userDisplayHints);
|
|
4387
4756
|
assert.calledWith(canUserResumeSpy, payload.info.userDisplayHints);
|