@webex/plugin-meetings 3.0.0-beta.192 → 3.0.0-beta.194
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 +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/meeting/in-meeting-actions.js +3 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +5 -1
- package/dist/meeting/index.js.map +1 -1
- package/dist/types/meeting/in-meeting-actions.d.ts +2 -0
- package/package.json +19 -19
- package/src/meeting/in-meeting-actions.ts +4 -0
- package/src/meeting/index.ts +4 -0
- package/test/unit/spec/meeting/in-meeting-actions.ts +2 -0
- package/test/unit/spec/meeting/index.js +773 -643
|
@@ -37,9 +37,7 @@ import {
|
|
|
37
37
|
RemoteTrackType,
|
|
38
38
|
MediaType,
|
|
39
39
|
} from '@webex/internal-media-core';
|
|
40
|
-
import {
|
|
41
|
-
LocalTrackEvents,
|
|
42
|
-
} from '@webex/media-helpers';
|
|
40
|
+
import {LocalTrackEvents} from '@webex/media-helpers';
|
|
43
41
|
import * as StatsAnalyzerModule from '@webex/plugin-meetings/src/statsAnalyzer';
|
|
44
42
|
import * as MuteStateModule from '@webex/plugin-meetings/src/meeting/muteState';
|
|
45
43
|
import EventsScope from '@webex/plugin-meetings/src/common/events/events-scope';
|
|
@@ -92,7 +90,7 @@ import {
|
|
|
92
90
|
MeetingInfoV2PasswordError,
|
|
93
91
|
MeetingInfoV2PolicyError,
|
|
94
92
|
} from '../../../../src/meeting-info/meeting-info-v2';
|
|
95
|
-
import {ANNOTATION_POLICY} from
|
|
93
|
+
import {ANNOTATION_POLICY} from '../../../../src/annotation/constants';
|
|
96
94
|
|
|
97
95
|
// Non-stubbed function
|
|
98
96
|
const {getDisplayMedia} = Media;
|
|
@@ -199,7 +197,7 @@ describe('plugin-meetings', () => {
|
|
|
199
197
|
},
|
|
200
198
|
config: {
|
|
201
199
|
credentials: {
|
|
202
|
-
client_id: 'mock-client-id'
|
|
200
|
+
client_id: 'mock-client-id',
|
|
203
201
|
},
|
|
204
202
|
meetings: {
|
|
205
203
|
reconnection: {
|
|
@@ -209,7 +207,7 @@ describe('plugin-meetings', () => {
|
|
|
209
207
|
metrics: {},
|
|
210
208
|
stats: {},
|
|
211
209
|
experimental: {enableUnifiedMeetings: true},
|
|
212
|
-
degradationPreferences: {
|
|
210
|
+
degradationPreferences: {maxMacroblocksLimit: 8192},
|
|
213
211
|
},
|
|
214
212
|
metrics: {
|
|
215
213
|
type: ['behavioral'],
|
|
@@ -501,7 +499,6 @@ describe('plugin-meetings', () => {
|
|
|
501
499
|
});
|
|
502
500
|
|
|
503
501
|
describe('#joinWithMedia', () => {
|
|
504
|
-
|
|
505
502
|
it('should have #joinWithMedia', () => {
|
|
506
503
|
assert.exists(meeting.joinWithMedia);
|
|
507
504
|
});
|
|
@@ -590,23 +587,24 @@ describe('plugin-meetings', () => {
|
|
|
590
587
|
});
|
|
591
588
|
|
|
592
589
|
describe('#pstnUpdate', () => {
|
|
593
|
-
|
|
594
|
-
beforeEach(()=> {
|
|
590
|
+
beforeEach(() => {
|
|
595
591
|
meeting.locusInfo.self = {state: 'IDLE'};
|
|
596
|
-
meeting.dialOutUrl =
|
|
597
|
-
})
|
|
592
|
+
meeting.dialOutUrl = 'dialout:///8167d5ec-40c8-49b8-b49a-8717dbaa7d3a';
|
|
593
|
+
});
|
|
598
594
|
|
|
599
595
|
it('checks event MEETING_SELF_PHONE_AUDIO_UPDATE can return reason', () => {
|
|
600
596
|
const fakePayload = {
|
|
601
597
|
newSelf: {
|
|
602
|
-
pstnDevices: [
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
598
|
+
pstnDevices: [
|
|
599
|
+
{
|
|
600
|
+
attendeeId: 'test-id',
|
|
601
|
+
url: 'dialout:///8167d5ec-40c8-49b8-b49a-8717dbaa7d3a',
|
|
602
|
+
deviceType: 'PROVISIONAL',
|
|
603
|
+
state: 'LEFT',
|
|
604
|
+
reason: 'FAILURE',
|
|
605
|
+
},
|
|
606
|
+
],
|
|
607
|
+
},
|
|
610
608
|
};
|
|
611
609
|
|
|
612
610
|
meeting.pstnUpdate(fakePayload);
|
|
@@ -636,13 +634,15 @@ describe('plugin-meetings', () => {
|
|
|
636
634
|
it('checks event MEETING_SELF_PHONE_AUDIO_UPDATE can return undefined reason', () => {
|
|
637
635
|
const fakePayload = {
|
|
638
636
|
newSelf: {
|
|
639
|
-
pstnDevices: [
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
637
|
+
pstnDevices: [
|
|
638
|
+
{
|
|
639
|
+
attendeeId: 'test-id',
|
|
640
|
+
url: 'dialout:///8167d5ec-40c8-49b8-b49a-8717dbaa7d3a',
|
|
641
|
+
deviceType: 'PROVISIONAL',
|
|
642
|
+
state: 'LEFT',
|
|
643
|
+
},
|
|
644
|
+
],
|
|
645
|
+
},
|
|
646
646
|
};
|
|
647
647
|
|
|
648
648
|
meeting.pstnUpdate(fakePayload);
|
|
@@ -852,9 +852,12 @@ describe('plugin-meetings', () => {
|
|
|
852
852
|
assert.calledOnce(meeting.setLocus);
|
|
853
853
|
assert.equal(result, joinMeetingResult);
|
|
854
854
|
|
|
855
|
-
assert.calledOnce(webex.internal.newMetrics.submitClientEvent)
|
|
855
|
+
assert.calledOnce(webex.internal.newMetrics.submitClientEvent);
|
|
856
856
|
|
|
857
|
-
assert.equal(
|
|
857
|
+
assert.equal(
|
|
858
|
+
webex.internal.newMetrics.submitClientEvent.getCall(0).args[0].name,
|
|
859
|
+
'client.call.initiated'
|
|
860
|
+
);
|
|
858
861
|
});
|
|
859
862
|
});
|
|
860
863
|
describe('failure', () => {
|
|
@@ -901,13 +904,20 @@ describe('plugin-meetings', () => {
|
|
|
901
904
|
|
|
902
905
|
it('should post error event if failed', async () => {
|
|
903
906
|
await meeting.join().catch(() => {
|
|
904
|
-
assert.deepEqual(
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
907
|
+
assert.deepEqual(
|
|
908
|
+
webex.internal.newMetrics.submitClientEvent.getCall(1).args[0].name,
|
|
909
|
+
'client.locus.join.response'
|
|
910
|
+
);
|
|
911
|
+
assert.match(
|
|
912
|
+
webex.internal.newMetrics.submitClientEvent.getCall(1).args[0].options.rawError,
|
|
913
|
+
{
|
|
914
|
+
code: 2,
|
|
915
|
+
error: null,
|
|
916
|
+
joinOptions: {},
|
|
917
|
+
sdkMessage:
|
|
918
|
+
'There was an issue joining the meeting, meeting could be in a bad state.',
|
|
919
|
+
}
|
|
920
|
+
);
|
|
911
921
|
});
|
|
912
922
|
});
|
|
913
923
|
it('should fail if password is required', async () => {
|
|
@@ -1015,7 +1025,7 @@ describe('plugin-meetings', () => {
|
|
|
1015
1025
|
isMultistream: false,
|
|
1016
1026
|
signalingState: 'unknown',
|
|
1017
1027
|
connectionState: 'unknown',
|
|
1018
|
-
iceConnectionState: 'unknown'
|
|
1028
|
+
iceConnectionState: 'unknown',
|
|
1019
1029
|
});
|
|
1020
1030
|
});
|
|
1021
1031
|
|
|
@@ -1038,7 +1048,7 @@ describe('plugin-meetings', () => {
|
|
|
1038
1048
|
isMultistream: false,
|
|
1039
1049
|
signalingState: 'unknown',
|
|
1040
1050
|
connectionState: 'unknown',
|
|
1041
|
-
iceConnectionState: 'unknown'
|
|
1051
|
+
iceConnectionState: 'unknown',
|
|
1042
1052
|
});
|
|
1043
1053
|
});
|
|
1044
1054
|
});
|
|
@@ -1052,7 +1062,6 @@ describe('plugin-meetings', () => {
|
|
|
1052
1062
|
});
|
|
1053
1063
|
const result = await assert.isRejected(meeting.addMedia());
|
|
1054
1064
|
|
|
1055
|
-
|
|
1056
1065
|
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
1057
1066
|
assert.calledWith(
|
|
1058
1067
|
Metrics.sendBehavioralMetric,
|
|
@@ -1066,13 +1075,12 @@ describe('plugin-meetings', () => {
|
|
|
1066
1075
|
isMultistream: false,
|
|
1067
1076
|
signalingState: 'unknown',
|
|
1068
1077
|
connectionState: 'unknown',
|
|
1069
|
-
iceConnectionState: 'unknown'
|
|
1078
|
+
iceConnectionState: 'unknown',
|
|
1070
1079
|
})
|
|
1071
1080
|
);
|
|
1072
1081
|
|
|
1073
1082
|
assert.instanceOf(result, Error);
|
|
1074
1083
|
assert.isNull(meeting.mediaProperties.webrtcMediaConnection);
|
|
1075
|
-
|
|
1076
1084
|
});
|
|
1077
1085
|
|
|
1078
1086
|
it('should include the peer connection properties correctly for multistream', async () => {
|
|
@@ -1081,15 +1089,15 @@ describe('plugin-meetings', () => {
|
|
|
1081
1089
|
// because some methods (like on() or initiateOffer()) are missing
|
|
1082
1090
|
Media.createMediaConnection = sinon.stub().returns({
|
|
1083
1091
|
close: sinon.stub(),
|
|
1084
|
-
multistreamConnection
|
|
1092
|
+
multistreamConnection: {
|
|
1085
1093
|
pc: {
|
|
1086
1094
|
pc: {
|
|
1087
1095
|
signalingState: 'have-local-offer',
|
|
1088
1096
|
connectionState: 'connecting',
|
|
1089
1097
|
iceConnectionState: 'checking',
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1098
|
+
},
|
|
1099
|
+
},
|
|
1100
|
+
},
|
|
1093
1101
|
});
|
|
1094
1102
|
// set a statsAnalyzer on the meeting so that we can check that it gets reset to null
|
|
1095
1103
|
meeting.statsAnalyzer = {stopAnalyzer: sinon.stub().resolves()};
|
|
@@ -1109,8 +1117,7 @@ describe('plugin-meetings', () => {
|
|
|
1109
1117
|
isMultistream: false,
|
|
1110
1118
|
signalingState: 'have-local-offer',
|
|
1111
1119
|
connectionState: 'connecting',
|
|
1112
|
-
iceConnectionState: 'checking'
|
|
1113
|
-
|
|
1120
|
+
iceConnectionState: 'checking',
|
|
1114
1121
|
})
|
|
1115
1122
|
);
|
|
1116
1123
|
|
|
@@ -1124,13 +1131,13 @@ describe('plugin-meetings', () => {
|
|
|
1124
1131
|
// because some methods (like on() or initiateOffer()) are missing
|
|
1125
1132
|
Media.createMediaConnection = sinon.stub().returns({
|
|
1126
1133
|
close: sinon.stub(),
|
|
1127
|
-
mediaConnection
|
|
1134
|
+
mediaConnection: {
|
|
1128
1135
|
pc: {
|
|
1129
1136
|
signalingState: 'have-local-offer',
|
|
1130
1137
|
connectionState: 'connecting',
|
|
1131
1138
|
iceConnectionState: 'checking',
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1139
|
+
},
|
|
1140
|
+
},
|
|
1134
1141
|
});
|
|
1135
1142
|
// set a statsAnalyzer on the meeting so that we can check that it gets reset to null
|
|
1136
1143
|
meeting.statsAnalyzer = {stopAnalyzer: sinon.stub().resolves()};
|
|
@@ -1150,8 +1157,7 @@ describe('plugin-meetings', () => {
|
|
|
1150
1157
|
isMultistream: false,
|
|
1151
1158
|
signalingState: 'have-local-offer',
|
|
1152
1159
|
connectionState: 'connecting',
|
|
1153
|
-
iceConnectionState: 'checking'
|
|
1154
|
-
|
|
1160
|
+
iceConnectionState: 'checking',
|
|
1155
1161
|
})
|
|
1156
1162
|
);
|
|
1157
1163
|
|
|
@@ -1232,7 +1238,7 @@ describe('plugin-meetings', () => {
|
|
|
1232
1238
|
assert.calledOnce(meeting.setMercuryListener);
|
|
1233
1239
|
assert.calledOnce(fakeMediaConnection.initiateOffer);
|
|
1234
1240
|
assert.equal(meeting.allowMediaInLobby, allowMediaInLobby);
|
|
1235
|
-
}
|
|
1241
|
+
};
|
|
1236
1242
|
|
|
1237
1243
|
it('should attach the media and return promise', async () => {
|
|
1238
1244
|
meeting.roap.doTurnDiscovery = sinon
|
|
@@ -1333,7 +1339,9 @@ describe('plugin-meetings', () => {
|
|
|
1333
1339
|
});
|
|
1334
1340
|
|
|
1335
1341
|
it('should reject if waitForMediaConnectionConnected() rejects', async () => {
|
|
1336
|
-
webex.internal.newMetrics.callDiagnosticMetrics.getErrorPayloadForClientErrorCode = sinon
|
|
1342
|
+
webex.internal.newMetrics.callDiagnosticMetrics.getErrorPayloadForClientErrorCode = sinon
|
|
1343
|
+
.stub()
|
|
1344
|
+
.returns({});
|
|
1337
1345
|
meeting.meetingState = 'ACTIVE';
|
|
1338
1346
|
meeting.mediaProperties.waitForMediaConnectionConnected.rejects(new Error('fake error'));
|
|
1339
1347
|
|
|
@@ -1375,7 +1383,7 @@ describe('plugin-meetings', () => {
|
|
|
1375
1383
|
correlation_id: meeting.correlationId,
|
|
1376
1384
|
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1377
1385
|
connectionType: 'udp',
|
|
1378
|
-
isMultistream: false
|
|
1386
|
+
isMultistream: false,
|
|
1379
1387
|
});
|
|
1380
1388
|
|
|
1381
1389
|
assert.called(webex.internal.newMetrics.submitClientEvent);
|
|
@@ -1447,7 +1455,7 @@ describe('plugin-meetings', () => {
|
|
|
1447
1455
|
|
|
1448
1456
|
assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
|
|
1449
1457
|
name: 'client.media.tx.stop',
|
|
1450
|
-
payload: {mediaType:'video'},
|
|
1458
|
+
payload: {mediaType: 'video'},
|
|
1451
1459
|
options: {
|
|
1452
1460
|
meetingId: meeting.id,
|
|
1453
1461
|
},
|
|
@@ -1514,8 +1522,8 @@ describe('plugin-meetings', () => {
|
|
|
1514
1522
|
networkType: 'wifi',
|
|
1515
1523
|
},
|
|
1516
1524
|
payload: {
|
|
1517
|
-
intervals: [fakeData]
|
|
1518
|
-
}
|
|
1525
|
+
intervals: [fakeData],
|
|
1526
|
+
},
|
|
1519
1527
|
});
|
|
1520
1528
|
});
|
|
1521
1529
|
});
|
|
@@ -1567,12 +1575,10 @@ describe('plugin-meetings', () => {
|
|
|
1567
1575
|
it('succeeds even if getDevices() throws', async () => {
|
|
1568
1576
|
meeting.meetingState = 'ACTIVE';
|
|
1569
1577
|
|
|
1570
|
-
sinon
|
|
1571
|
-
.stub(internalMediaModule, 'getDevices')
|
|
1572
|
-
.rejects(new Error('fake error'));
|
|
1578
|
+
sinon.stub(internalMediaModule, 'getDevices').rejects(new Error('fake error'));
|
|
1573
1579
|
|
|
1574
1580
|
await meeting.addMedia();
|
|
1575
|
-
})
|
|
1581
|
+
});
|
|
1576
1582
|
});
|
|
1577
1583
|
|
|
1578
1584
|
/* This set of tests are like semi-integration tests, they use real MuteState, Media, LocusMediaRequest and Roap classes.
|
|
@@ -1581,186 +1587,195 @@ describe('plugin-meetings', () => {
|
|
|
1581
1587
|
to @webex/internal-media-core when addMedia, updateMedia, publishTracks, unpublishTracks are called
|
|
1582
1588
|
in various combinations.
|
|
1583
1589
|
*/
|
|
1584
|
-
[true,false].forEach((isMultistream) =>
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
+
[true, false].forEach((isMultistream) =>
|
|
1591
|
+
describe(`addMedia/updateMedia semi-integration tests (${
|
|
1592
|
+
isMultistream ? 'multistream' : 'transcoded'
|
|
1593
|
+
})`, () => {
|
|
1594
|
+
const webrtcAudioTrack = {
|
|
1595
|
+
id: 'underlying audio track',
|
|
1596
|
+
getSettings: sinon.stub().returns({deviceId: 'fake device id for audio track'}),
|
|
1597
|
+
};
|
|
1590
1598
|
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1599
|
+
let fakeMicrophoneTrack;
|
|
1600
|
+
let fakeRoapMediaConnection;
|
|
1601
|
+
let fakeMultistreamRoapMediaConnection;
|
|
1602
|
+
let roapMediaConnectionConstructorStub;
|
|
1603
|
+
let multistreamRoapMediaConnectionConstructorStub;
|
|
1604
|
+
let locusMediaRequestStub; // stub for /media requests to Locus
|
|
1597
1605
|
|
|
1598
|
-
|
|
1606
|
+
const roapOfferMessage = {messageType: 'OFFER', sdp: 'sdp', seq: '1', tieBreaker: '123'};
|
|
1599
1607
|
|
|
1600
|
-
|
|
1601
|
-
|
|
1608
|
+
let expectedMediaConnectionConfig;
|
|
1609
|
+
let expectedDebugId;
|
|
1602
1610
|
|
|
1603
|
-
|
|
1611
|
+
let clock;
|
|
1604
1612
|
|
|
1605
|
-
|
|
1606
|
-
|
|
1613
|
+
beforeEach(() => {
|
|
1614
|
+
clock = sinon.useFakeTimers();
|
|
1607
1615
|
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1616
|
+
meeting.deviceUrl = 'deviceUrl';
|
|
1617
|
+
meeting.config.deviceType = 'web';
|
|
1618
|
+
meeting.isMultistream = isMultistream;
|
|
1619
|
+
meeting.meetingState = 'ACTIVE';
|
|
1620
|
+
meeting.mediaId = 'fake media id';
|
|
1621
|
+
meeting.selfUrl = 'selfUrl';
|
|
1622
|
+
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
|
|
1623
|
+
meeting.mediaProperties.getCurrentConnectionType = sinon.stub().resolves('udp');
|
|
1624
|
+
meeting.setMercuryListener = sinon.stub();
|
|
1625
|
+
meeting.locusInfo.onFullLocus = sinon.stub();
|
|
1626
|
+
meeting.webex.meetings.reachability = {
|
|
1627
|
+
isAnyClusterReachable: sinon.stub().resolves(true),
|
|
1628
|
+
};
|
|
1629
|
+
meeting.roap.doTurnDiscovery = sinon
|
|
1630
|
+
.stub()
|
|
1631
|
+
.resolves({turnServerInfo: {}, turnDiscoverySkippedReason: 'reachability'});
|
|
1632
|
+
|
|
1633
|
+
StaticConfig.set({bandwidth: {audio: 1234, video: 5678, startBitrate: 9876}});
|
|
1634
|
+
|
|
1635
|
+
// setup things that are expected to be the same across all the tests and are actually irrelevant for these tests
|
|
1636
|
+
expectedDebugId = `MC-${meeting.id.substring(0, 4)}`;
|
|
1637
|
+
expectedMediaConnectionConfig = {
|
|
1638
|
+
iceServers: [{urls: undefined, username: '', credential: ''}],
|
|
1639
|
+
skipInactiveTransceivers: false,
|
|
1640
|
+
requireH264: true,
|
|
1641
|
+
sdpMunging: {
|
|
1642
|
+
convertPort9to0: false,
|
|
1643
|
+
addContentSlides: true,
|
|
1644
|
+
bandwidthLimits: {
|
|
1645
|
+
audio: StaticConfig.meetings.bandwidth.audio,
|
|
1646
|
+
video: StaticConfig.meetings.bandwidth.video,
|
|
1647
|
+
},
|
|
1648
|
+
startBitrate: StaticConfig.meetings.bandwidth.startBitrate,
|
|
1649
|
+
periodicKeyframes: 20,
|
|
1650
|
+
disableExtmap: !meeting.config.enableExtmap,
|
|
1651
|
+
disableRtx: !meeting.config.enableRtx,
|
|
1639
1652
|
},
|
|
1640
|
-
|
|
1641
|
-
periodicKeyframes: 20,
|
|
1642
|
-
disableExtmap: !meeting.config.enableExtmap,
|
|
1643
|
-
disableRtx: !meeting.config.enableRtx,
|
|
1644
|
-
},
|
|
1645
|
-
};
|
|
1653
|
+
};
|
|
1646
1654
|
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1655
|
+
// setup stubs
|
|
1656
|
+
fakeMicrophoneTrack = {
|
|
1657
|
+
id: 'fake mic',
|
|
1658
|
+
on: sinon.stub(),
|
|
1659
|
+
off: sinon.stub(),
|
|
1660
|
+
setUnmuteAllowed: sinon.stub(),
|
|
1661
|
+
setMuted: sinon.stub(),
|
|
1662
|
+
setPublished: sinon.stub(),
|
|
1663
|
+
muted: false,
|
|
1664
|
+
underlyingTrack: webrtcAudioTrack,
|
|
1665
|
+
};
|
|
1658
1666
|
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
+
fakeRoapMediaConnection = {
|
|
1668
|
+
id: 'roap media connection',
|
|
1669
|
+
close: sinon.stub(),
|
|
1670
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
1671
|
+
initiateOffer: sinon.stub().resolves({}),
|
|
1672
|
+
update: sinon.stub().resolves({}),
|
|
1673
|
+
on: sinon.stub(),
|
|
1674
|
+
};
|
|
1667
1675
|
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1676
|
+
fakeMultistreamRoapMediaConnection = {
|
|
1677
|
+
id: 'multistream roap media connection',
|
|
1678
|
+
close: sinon.stub(),
|
|
1679
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
1680
|
+
initiateOffer: sinon.stub().resolves({}),
|
|
1681
|
+
publishTrack: sinon.stub().resolves({}),
|
|
1682
|
+
unpublishTrack: sinon.stub().resolves({}),
|
|
1683
|
+
on: sinon.stub(),
|
|
1684
|
+
requestMedia: sinon.stub(),
|
|
1685
|
+
createReceiveSlot: sinon.stub().resolves({on: sinon.stub()}),
|
|
1686
|
+
enableMultistreamAudio: sinon.stub(),
|
|
1687
|
+
};
|
|
1680
1688
|
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1689
|
+
roapMediaConnectionConstructorStub = sinon
|
|
1690
|
+
.stub(internalMediaModule, 'RoapMediaConnection')
|
|
1691
|
+
.returns(fakeRoapMediaConnection);
|
|
1684
1692
|
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1693
|
+
multistreamRoapMediaConnectionConstructorStub = sinon
|
|
1694
|
+
.stub(internalMediaModule, 'MultistreamRoapMediaConnection')
|
|
1695
|
+
.returns(fakeMultistreamRoapMediaConnection);
|
|
1688
1696
|
|
|
1689
|
-
|
|
1690
|
-
|
|
1697
|
+
locusMediaRequestStub = sinon
|
|
1698
|
+
.stub(WebexPlugin.prototype, 'request')
|
|
1699
|
+
.resolves({body: {locus: {fullState: {}}}});
|
|
1700
|
+
});
|
|
1691
1701
|
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1702
|
+
afterEach(() => {
|
|
1703
|
+
clock.restore();
|
|
1704
|
+
});
|
|
1695
1705
|
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1706
|
+
// helper function that waits until all promises are resolved and any queued up /media requests to Locus are sent out
|
|
1707
|
+
const stableState = async () => {
|
|
1708
|
+
await testUtils.flushPromises();
|
|
1709
|
+
clock.tick(1); // needed because LocusMediaRequest uses Lodash.defer()
|
|
1710
|
+
};
|
|
1701
1711
|
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1712
|
+
const resetHistory = () => {
|
|
1713
|
+
locusMediaRequestStub.resetHistory();
|
|
1714
|
+
fakeRoapMediaConnection.update.resetHistory();
|
|
1715
|
+
fakeMultistreamRoapMediaConnection.publishTrack.resetHistory();
|
|
1716
|
+
fakeMultistreamRoapMediaConnection.unpublishTrack.resetHistory();
|
|
1717
|
+
};
|
|
1708
1718
|
|
|
1709
|
-
|
|
1710
|
-
|
|
1719
|
+
const getRoapListener = () => {
|
|
1720
|
+
const roapMediaConnectionToCheck = isMultistream
|
|
1721
|
+
? fakeMultistreamRoapMediaConnection
|
|
1722
|
+
: fakeRoapMediaConnection;
|
|
1711
1723
|
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1724
|
+
for (let idx = 0; idx < roapMediaConnectionToCheck.on.callCount; idx += 1) {
|
|
1725
|
+
if (
|
|
1726
|
+
roapMediaConnectionToCheck.on.getCall(idx).args[0] === Event.ROAP_MESSAGE_TO_SEND
|
|
1727
|
+
) {
|
|
1728
|
+
return roapMediaConnectionToCheck.on.getCall(idx).args[1];
|
|
1729
|
+
}
|
|
1715
1730
|
}
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1731
|
+
assert.fail(
|
|
1732
|
+
'listener for "roap:messageToSend" (Event.ROAP_MESSAGE_TO_SEND) was not registered'
|
|
1733
|
+
);
|
|
1734
|
+
};
|
|
1719
1735
|
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1736
|
+
// simulates a Roap offer being generated by the RoapMediaConnection
|
|
1737
|
+
const simulateRoapOffer = async () => {
|
|
1738
|
+
const roapListener = getRoapListener();
|
|
1723
1739
|
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1740
|
+
await roapListener({roapMessage: roapOfferMessage});
|
|
1741
|
+
await stableState();
|
|
1742
|
+
};
|
|
1727
1743
|
|
|
1728
|
-
|
|
1729
|
-
|
|
1744
|
+
const checkSdpOfferSent = ({audioMuted, videoMuted}) => {
|
|
1745
|
+
const {sdp, seq, tieBreaker} = roapOfferMessage;
|
|
1730
1746
|
|
|
1731
|
-
|
|
1732
|
-
{
|
|
1747
|
+
assert.calledWith(locusMediaRequestStub, {
|
|
1733
1748
|
method: 'PUT',
|
|
1734
1749
|
uri: `${meeting.selfUrl}/media`,
|
|
1735
1750
|
body: {
|
|
1736
|
-
device: {
|
|
1751
|
+
device: {url: meeting.deviceUrl, deviceType: meeting.config.deviceType},
|
|
1737
1752
|
correlationId: meeting.correlationId,
|
|
1738
1753
|
localMedias: [
|
|
1739
1754
|
{
|
|
1740
1755
|
localSdp: `{"audioMuted":${audioMuted},"videoMuted":${videoMuted},"roapMessage":{"messageType":"OFFER","sdps":["${sdp}"],"version":"2","seq":"${seq}","tieBreaker":"${tieBreaker}"}}`,
|
|
1741
|
-
mediaId: 'fake media id'
|
|
1742
|
-
}
|
|
1756
|
+
mediaId: 'fake media id',
|
|
1757
|
+
},
|
|
1743
1758
|
],
|
|
1744
1759
|
clientMediaPreferences: {
|
|
1745
1760
|
preferTranscoding: !meeting.isMultistream,
|
|
1746
|
-
joinCookie: undefined
|
|
1747
|
-
}
|
|
1761
|
+
joinCookie: undefined,
|
|
1762
|
+
},
|
|
1748
1763
|
},
|
|
1749
1764
|
});
|
|
1750
|
-
|
|
1765
|
+
};
|
|
1751
1766
|
|
|
1752
|
-
|
|
1753
|
-
|
|
1767
|
+
const checkLocalMuteSentToLocus = ({audioMuted, videoMuted}) => {
|
|
1768
|
+
assert.calledWith(locusMediaRequestStub, {
|
|
1754
1769
|
method: 'PUT',
|
|
1755
1770
|
uri: `${meeting.selfUrl}/media`,
|
|
1756
1771
|
body: {
|
|
1757
|
-
device: {
|
|
1772
|
+
device: {url: meeting.deviceUrl, deviceType: meeting.config.deviceType},
|
|
1758
1773
|
correlationId: meeting.correlationId,
|
|
1759
1774
|
localMedias: [
|
|
1760
1775
|
{
|
|
1761
1776
|
localSdp: `{"audioMuted":${audioMuted},"videoMuted":${videoMuted}}`,
|
|
1762
|
-
mediaId: 'fake media id'
|
|
1763
|
-
}
|
|
1777
|
+
mediaId: 'fake media id',
|
|
1778
|
+
},
|
|
1764
1779
|
],
|
|
1765
1780
|
clientMediaPreferences: {
|
|
1766
1781
|
preferTranscoding: !meeting.isMultistream,
|
|
@@ -1769,197 +1784,221 @@ describe('plugin-meetings', () => {
|
|
|
1769
1784
|
usingResource: null,
|
|
1770
1785
|
},
|
|
1771
1786
|
});
|
|
1772
|
-
|
|
1787
|
+
};
|
|
1773
1788
|
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1789
|
+
const checkMediaConnectionCreated = ({
|
|
1790
|
+
mediaConnectionConfig,
|
|
1791
|
+
localTracks,
|
|
1792
|
+
direction,
|
|
1793
|
+
remoteQualityLevel,
|
|
1794
|
+
expectedDebugId,
|
|
1795
|
+
meetingId,
|
|
1796
|
+
}) => {
|
|
1797
|
+
if (isMultistream) {
|
|
1798
|
+
const {iceServers} = mediaConnectionConfig;
|
|
1777
1799
|
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1800
|
+
assert.calledOnceWithMatch(
|
|
1801
|
+
multistreamRoapMediaConnectionConstructorStub,
|
|
1802
|
+
{
|
|
1803
|
+
iceServers,
|
|
1804
|
+
enableMainAudio: direction.audio !== 'inactive',
|
|
1805
|
+
enableMainVideo: true,
|
|
1806
|
+
},
|
|
1807
|
+
meetingId
|
|
1808
|
+
);
|
|
1783
1809
|
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1810
|
+
Object.values(localTracks).forEach((track) => {
|
|
1811
|
+
if (track) {
|
|
1812
|
+
assert.calledOnceWithExactly(
|
|
1813
|
+
fakeMultistreamRoapMediaConnection.publishTrack,
|
|
1814
|
+
track
|
|
1815
|
+
);
|
|
1816
|
+
}
|
|
1817
|
+
});
|
|
1818
|
+
} else {
|
|
1819
|
+
assert.calledOnceWithExactly(
|
|
1820
|
+
roapMediaConnectionConstructorStub,
|
|
1821
|
+
mediaConnectionConfig,
|
|
1822
|
+
{
|
|
1823
|
+
localTracks: {
|
|
1824
|
+
audio: localTracks.audio?.underlyingTrack,
|
|
1825
|
+
video: localTracks.video?.underlyingTrack,
|
|
1826
|
+
screenShareVideo: localTracks.screenShareVideo?.underlyingTrack,
|
|
1827
|
+
},
|
|
1828
|
+
direction,
|
|
1829
|
+
remoteQualityLevel,
|
|
1796
1830
|
},
|
|
1797
|
-
|
|
1798
|
-
|
|
1831
|
+
expectedDebugId
|
|
1832
|
+
);
|
|
1833
|
+
}
|
|
1834
|
+
};
|
|
1835
|
+
|
|
1836
|
+
it('addMedia() works correctly when media is enabled without tracks to publish', async () => {
|
|
1837
|
+
await meeting.addMedia();
|
|
1838
|
+
await simulateRoapOffer();
|
|
1839
|
+
|
|
1840
|
+
// check RoapMediaConnection was created correctly
|
|
1841
|
+
checkMediaConnectionCreated({
|
|
1842
|
+
mediaConnectionConfig: expectedMediaConnectionConfig,
|
|
1843
|
+
localTracks: {
|
|
1844
|
+
audio: undefined,
|
|
1845
|
+
video: undefined,
|
|
1846
|
+
screenShareVideo: undefined,
|
|
1847
|
+
screenShareAudio: undefined,
|
|
1799
1848
|
},
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1849
|
+
direction: {
|
|
1850
|
+
audio: 'sendrecv',
|
|
1851
|
+
video: 'sendrecv',
|
|
1852
|
+
screenShareVideo: 'recvonly',
|
|
1853
|
+
},
|
|
1854
|
+
remoteQualityLevel: 'HIGH',
|
|
1855
|
+
expectedDebugId,
|
|
1856
|
+
meetingId: meeting.id,
|
|
1857
|
+
});
|
|
1803
1858
|
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
await simulateRoapOffer();
|
|
1859
|
+
// and SDP offer was sent with the right audioMuted/videoMuted values
|
|
1860
|
+
checkSdpOfferSent({audioMuted: true, videoMuted: true});
|
|
1807
1861
|
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
mediaConnectionConfig: expectedMediaConnectionConfig,
|
|
1811
|
-
localTracks: {
|
|
1812
|
-
audio: undefined,
|
|
1813
|
-
video: undefined,
|
|
1814
|
-
screenShareVideo: undefined,
|
|
1815
|
-
screenShareAudio: undefined,
|
|
1816
|
-
},
|
|
1817
|
-
direction: {
|
|
1818
|
-
audio: 'sendrecv',
|
|
1819
|
-
video: 'sendrecv',
|
|
1820
|
-
screenShareVideo: 'recvonly',
|
|
1821
|
-
},
|
|
1822
|
-
remoteQualityLevel: 'HIGH',
|
|
1823
|
-
expectedDebugId,
|
|
1824
|
-
meetingId: meeting.id
|
|
1862
|
+
// and that it was the only /media request that was sent
|
|
1863
|
+
assert.calledOnce(locusMediaRequestStub);
|
|
1825
1864
|
});
|
|
1826
1865
|
|
|
1827
|
-
|
|
1828
|
-
|
|
1866
|
+
it('addMedia() works correctly when media is enabled with tracks to publish', async () => {
|
|
1867
|
+
await meeting.addMedia({localTracks: {microphone: fakeMicrophoneTrack}});
|
|
1868
|
+
await simulateRoapOffer();
|
|
1829
1869
|
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1870
|
+
// check RoapMediaConnection was created correctly
|
|
1871
|
+
checkMediaConnectionCreated({
|
|
1872
|
+
mediaConnectionConfig: expectedMediaConnectionConfig,
|
|
1873
|
+
localTracks: {
|
|
1874
|
+
audio: fakeMicrophoneTrack,
|
|
1875
|
+
video: undefined,
|
|
1876
|
+
screenShareVideo: undefined,
|
|
1877
|
+
screenShareAudio: undefined,
|
|
1878
|
+
},
|
|
1879
|
+
direction: {
|
|
1880
|
+
audio: 'sendrecv',
|
|
1881
|
+
video: 'sendrecv',
|
|
1882
|
+
screenShareVideo: 'recvonly',
|
|
1883
|
+
},
|
|
1884
|
+
remoteQualityLevel: 'HIGH',
|
|
1885
|
+
expectedDebugId,
|
|
1886
|
+
meetingId: meeting.id,
|
|
1887
|
+
});
|
|
1833
1888
|
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
await simulateRoapOffer();
|
|
1889
|
+
// and SDP offer was sent with the right audioMuted/videoMuted values
|
|
1890
|
+
checkSdpOfferSent({audioMuted: false, videoMuted: true});
|
|
1837
1891
|
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
mediaConnectionConfig: expectedMediaConnectionConfig,
|
|
1841
|
-
localTracks: {
|
|
1842
|
-
audio: fakeMicrophoneTrack,
|
|
1843
|
-
video: undefined,
|
|
1844
|
-
screenShareVideo: undefined,
|
|
1845
|
-
screenShareAudio: undefined,
|
|
1846
|
-
},
|
|
1847
|
-
direction: {
|
|
1848
|
-
audio: 'sendrecv',
|
|
1849
|
-
video: 'sendrecv',
|
|
1850
|
-
screenShareVideo: 'recvonly',
|
|
1851
|
-
},
|
|
1852
|
-
remoteQualityLevel: 'HIGH',
|
|
1853
|
-
expectedDebugId,
|
|
1854
|
-
meetingId: meeting.id
|
|
1892
|
+
// and no other local mute requests were sent to Locus
|
|
1893
|
+
assert.calledOnce(locusMediaRequestStub);
|
|
1855
1894
|
});
|
|
1856
1895
|
|
|
1857
|
-
|
|
1858
|
-
|
|
1896
|
+
it('addMedia() works correctly when media is enabled with tracks to publish and track is muted', async () => {
|
|
1897
|
+
fakeMicrophoneTrack.muted = true;
|
|
1859
1898
|
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
});
|
|
1899
|
+
await meeting.addMedia({localTracks: {microphone: fakeMicrophoneTrack}});
|
|
1900
|
+
await simulateRoapOffer();
|
|
1863
1901
|
|
|
1864
|
-
|
|
1865
|
-
|
|
1902
|
+
// check RoapMediaConnection was created correctly
|
|
1903
|
+
checkMediaConnectionCreated({
|
|
1904
|
+
mediaConnectionConfig: expectedMediaConnectionConfig,
|
|
1905
|
+
localTracks: {
|
|
1906
|
+
audio: fakeMicrophoneTrack,
|
|
1907
|
+
video: undefined,
|
|
1908
|
+
screenShareVideo: undefined,
|
|
1909
|
+
screenShareAudio: undefined,
|
|
1910
|
+
},
|
|
1911
|
+
direction: {
|
|
1912
|
+
audio: 'sendrecv',
|
|
1913
|
+
video: 'sendrecv',
|
|
1914
|
+
screenShareVideo: 'recvonly',
|
|
1915
|
+
},
|
|
1916
|
+
remoteQualityLevel: 'HIGH',
|
|
1917
|
+
expectedDebugId,
|
|
1918
|
+
meetingId: meeting.id,
|
|
1919
|
+
});
|
|
1866
1920
|
|
|
1867
|
-
|
|
1868
|
-
|
|
1921
|
+
// and SDP offer was sent with the right audioMuted/videoMuted values
|
|
1922
|
+
checkSdpOfferSent({audioMuted: true, videoMuted: true});
|
|
1869
1923
|
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
mediaConnectionConfig: expectedMediaConnectionConfig,
|
|
1873
|
-
localTracks: {
|
|
1874
|
-
audio: fakeMicrophoneTrack,
|
|
1875
|
-
video: undefined,
|
|
1876
|
-
screenShareVideo: undefined,
|
|
1877
|
-
screenShareAudio: undefined,
|
|
1878
|
-
},
|
|
1879
|
-
direction: {
|
|
1880
|
-
audio: 'sendrecv',
|
|
1881
|
-
video: 'sendrecv',
|
|
1882
|
-
screenShareVideo: 'recvonly',
|
|
1883
|
-
},
|
|
1884
|
-
remoteQualityLevel: 'HIGH',
|
|
1885
|
-
expectedDebugId,
|
|
1886
|
-
meetingId: meeting.id
|
|
1924
|
+
// and no other local mute requests were sent to Locus
|
|
1925
|
+
assert.calledOnce(locusMediaRequestStub);
|
|
1887
1926
|
});
|
|
1888
1927
|
|
|
1889
|
-
|
|
1890
|
-
|
|
1928
|
+
it('addMedia() works correctly when media is disabled with tracks to publish', async () => {
|
|
1929
|
+
await meeting.addMedia({
|
|
1930
|
+
localTracks: {microphone: fakeMicrophoneTrack},
|
|
1931
|
+
audioEnabled: false,
|
|
1932
|
+
});
|
|
1933
|
+
await simulateRoapOffer();
|
|
1891
1934
|
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1935
|
+
// check RoapMediaConnection was created correctly
|
|
1936
|
+
checkMediaConnectionCreated({
|
|
1937
|
+
mediaConnectionConfig: expectedMediaConnectionConfig,
|
|
1938
|
+
localTracks: {
|
|
1939
|
+
audio: fakeMicrophoneTrack,
|
|
1940
|
+
video: undefined,
|
|
1941
|
+
screenShareVideo: undefined,
|
|
1942
|
+
screenShareAudio: undefined,
|
|
1943
|
+
},
|
|
1944
|
+
direction: {
|
|
1945
|
+
audio: 'inactive',
|
|
1946
|
+
video: 'sendrecv',
|
|
1947
|
+
screenShareVideo: 'recvonly',
|
|
1948
|
+
},
|
|
1949
|
+
remoteQualityLevel: 'HIGH',
|
|
1950
|
+
expectedDebugId,
|
|
1951
|
+
meetingId: meeting.id,
|
|
1952
|
+
});
|
|
1895
1953
|
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
await simulateRoapOffer();
|
|
1954
|
+
// and SDP offer was sent with the right audioMuted/videoMuted values
|
|
1955
|
+
checkSdpOfferSent({audioMuted: true, videoMuted: true});
|
|
1899
1956
|
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
mediaConnectionConfig: expectedMediaConnectionConfig,
|
|
1903
|
-
localTracks: {
|
|
1904
|
-
audio: fakeMicrophoneTrack,
|
|
1905
|
-
video: undefined,
|
|
1906
|
-
screenShareVideo: undefined,
|
|
1907
|
-
screenShareAudio: undefined,
|
|
1908
|
-
},
|
|
1909
|
-
direction: {
|
|
1910
|
-
audio: 'inactive',
|
|
1911
|
-
video: 'sendrecv',
|
|
1912
|
-
screenShareVideo: 'recvonly',
|
|
1913
|
-
},
|
|
1914
|
-
remoteQualityLevel: 'HIGH',
|
|
1915
|
-
expectedDebugId,
|
|
1916
|
-
meetingId: meeting.id
|
|
1957
|
+
// and no other local mute requests were sent to Locus
|
|
1958
|
+
assert.calledOnce(locusMediaRequestStub);
|
|
1917
1959
|
});
|
|
1918
1960
|
|
|
1919
|
-
|
|
1920
|
-
|
|
1961
|
+
it('addMedia() works correctly when media is disabled with no tracks to publish', async () => {
|
|
1962
|
+
await meeting.addMedia({audioEnabled: false});
|
|
1963
|
+
await simulateRoapOffer();
|
|
1921
1964
|
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1965
|
+
// check RoapMediaConnection was created correctly
|
|
1966
|
+
checkMediaConnectionCreated({
|
|
1967
|
+
mediaConnectionConfig: expectedMediaConnectionConfig,
|
|
1968
|
+
localTracks: {
|
|
1969
|
+
audio: undefined,
|
|
1970
|
+
video: undefined,
|
|
1971
|
+
screenShareVideo: undefined,
|
|
1972
|
+
screenShareAudio: undefined,
|
|
1973
|
+
},
|
|
1974
|
+
direction: {
|
|
1975
|
+
audio: 'inactive',
|
|
1976
|
+
video: 'sendrecv',
|
|
1977
|
+
screenShareVideo: 'recvonly',
|
|
1978
|
+
},
|
|
1979
|
+
remoteQualityLevel: 'HIGH',
|
|
1980
|
+
expectedDebugId,
|
|
1981
|
+
meetingId: meeting.id,
|
|
1982
|
+
});
|
|
1925
1983
|
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
await simulateRoapOffer();
|
|
1984
|
+
// and SDP offer was sent with the right audioMuted/videoMuted values
|
|
1985
|
+
checkSdpOfferSent({audioMuted: true, videoMuted: true});
|
|
1929
1986
|
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
mediaConnectionConfig: expectedMediaConnectionConfig,
|
|
1933
|
-
localTracks: {
|
|
1934
|
-
audio: undefined,
|
|
1935
|
-
video: undefined,
|
|
1936
|
-
screenShareVideo: undefined,
|
|
1937
|
-
screenShareAudio: undefined,
|
|
1938
|
-
},
|
|
1939
|
-
direction: {
|
|
1940
|
-
audio: 'inactive',
|
|
1941
|
-
video: 'sendrecv',
|
|
1942
|
-
screenShareVideo: 'recvonly',
|
|
1943
|
-
},
|
|
1944
|
-
remoteQualityLevel: 'HIGH',
|
|
1945
|
-
expectedDebugId,
|
|
1946
|
-
meetingId: meeting.id
|
|
1987
|
+
// and no other local mute requests were sent to Locus
|
|
1988
|
+
assert.calledOnce(locusMediaRequestStub);
|
|
1947
1989
|
});
|
|
1948
1990
|
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
]
|
|
1961
|
-
.forEach(({mediaEnabled, expected}) => {
|
|
1962
|
-
it(`first publishTracks() call while media is ${mediaEnabled ? 'enabled' : 'disabled'}`, async () => {
|
|
1991
|
+
describe('publishTracks()/unpublishTracks() calls', () => {
|
|
1992
|
+
[
|
|
1993
|
+
{mediaEnabled: true, expected: {direction: 'sendrecv', localMuteSentValue: false}},
|
|
1994
|
+
{
|
|
1995
|
+
mediaEnabled: false,
|
|
1996
|
+
expected: {direction: 'inactive', localMuteSentValue: undefined},
|
|
1997
|
+
},
|
|
1998
|
+
].forEach(({mediaEnabled, expected}) => {
|
|
1999
|
+
it(`first publishTracks() call while media is ${
|
|
2000
|
+
mediaEnabled ? 'enabled' : 'disabled'
|
|
2001
|
+
}`, async () => {
|
|
1963
2002
|
await meeting.addMedia({audioEnabled: mediaEnabled});
|
|
1964
2003
|
await simulateRoapOffer();
|
|
1965
2004
|
|
|
@@ -1970,27 +2009,35 @@ describe('plugin-meetings', () => {
|
|
|
1970
2009
|
|
|
1971
2010
|
if (expected.localMuteSentValue !== undefined) {
|
|
1972
2011
|
// check local mute was sent and it was the only /media request
|
|
1973
|
-
checkLocalMuteSentToLocus({
|
|
2012
|
+
checkLocalMuteSentToLocus({
|
|
2013
|
+
audioMuted: expected.localMuteSentValue,
|
|
2014
|
+
videoMuted: true,
|
|
2015
|
+
});
|
|
1974
2016
|
assert.calledOnce(locusMediaRequestStub);
|
|
1975
2017
|
} else {
|
|
1976
2018
|
assert.notCalled(locusMediaRequestStub);
|
|
1977
2019
|
}
|
|
1978
2020
|
if (isMultistream) {
|
|
1979
|
-
assert.calledOnceWithExactly(
|
|
2021
|
+
assert.calledOnceWithExactly(
|
|
2022
|
+
fakeMultistreamRoapMediaConnection.publishTrack,
|
|
2023
|
+
fakeMicrophoneTrack
|
|
2024
|
+
);
|
|
1980
2025
|
} else {
|
|
1981
2026
|
assert.calledOnceWithExactly(fakeRoapMediaConnection.update, {
|
|
1982
|
-
localTracks: {
|
|
2027
|
+
localTracks: {audio: webrtcAudioTrack, video: null, screenShareVideo: null},
|
|
1983
2028
|
direction: {
|
|
1984
2029
|
audio: expected.direction,
|
|
1985
2030
|
video: 'sendrecv',
|
|
1986
2031
|
screenShareVideo: 'recvonly',
|
|
1987
2032
|
},
|
|
1988
|
-
remoteQualityLevel: 'HIGH'
|
|
2033
|
+
remoteQualityLevel: 'HIGH',
|
|
1989
2034
|
});
|
|
1990
2035
|
}
|
|
1991
2036
|
});
|
|
1992
2037
|
|
|
1993
|
-
it(`second publishTracks() call while media is ${
|
|
2038
|
+
it(`second publishTracks() call while media is ${
|
|
2039
|
+
mediaEnabled ? 'enabled' : 'disabled'
|
|
2040
|
+
}`, async () => {
|
|
1994
2041
|
await meeting.addMedia({audioEnabled: mediaEnabled});
|
|
1995
2042
|
await simulateRoapOffer();
|
|
1996
2043
|
await meeting.publishTracks({microphone: fakeMicrophoneTrack});
|
|
@@ -2007,7 +2054,7 @@ describe('plugin-meetings', () => {
|
|
|
2007
2054
|
setMuted: sinon.stub(),
|
|
2008
2055
|
setPublished: sinon.stub(),
|
|
2009
2056
|
muted: false,
|
|
2010
|
-
underlyingTrack: webrtcAudioTrack2
|
|
2057
|
+
underlyingTrack: webrtcAudioTrack2,
|
|
2011
2058
|
};
|
|
2012
2059
|
|
|
2013
2060
|
await meeting.publishTracks({microphone: fakeMicrophoneTrack2});
|
|
@@ -2015,16 +2062,19 @@ describe('plugin-meetings', () => {
|
|
|
2015
2062
|
|
|
2016
2063
|
// only the roap media connection should be updated
|
|
2017
2064
|
if (isMultistream) {
|
|
2018
|
-
assert.calledOnceWithExactly(
|
|
2065
|
+
assert.calledOnceWithExactly(
|
|
2066
|
+
fakeMultistreamRoapMediaConnection.publishTrack,
|
|
2067
|
+
fakeMicrophoneTrack2
|
|
2068
|
+
);
|
|
2019
2069
|
} else {
|
|
2020
2070
|
assert.calledOnceWithExactly(fakeRoapMediaConnection.update, {
|
|
2021
|
-
localTracks: {
|
|
2071
|
+
localTracks: {audio: webrtcAudioTrack2, video: null, screenShareVideo: null},
|
|
2022
2072
|
direction: {
|
|
2023
2073
|
audio: expected.direction,
|
|
2024
2074
|
video: 'sendrecv',
|
|
2025
2075
|
screenShareVideo: 'recvonly',
|
|
2026
2076
|
},
|
|
2027
|
-
remoteQualityLevel: 'HIGH'
|
|
2077
|
+
remoteQualityLevel: 'HIGH',
|
|
2028
2078
|
});
|
|
2029
2079
|
}
|
|
2030
2080
|
|
|
@@ -2032,7 +2082,9 @@ describe('plugin-meetings', () => {
|
|
|
2032
2082
|
assert.notCalled(locusMediaRequestStub);
|
|
2033
2083
|
});
|
|
2034
2084
|
|
|
2035
|
-
it(`unpublishTracks() call while media is ${
|
|
2085
|
+
it(`unpublishTracks() call while media is ${
|
|
2086
|
+
mediaEnabled ? 'enabled' : 'disabled'
|
|
2087
|
+
}`, async () => {
|
|
2036
2088
|
await meeting.addMedia({audioEnabled: mediaEnabled});
|
|
2037
2089
|
await simulateRoapOffer();
|
|
2038
2090
|
await meeting.publishTracks({microphone: fakeMicrophoneTrack});
|
|
@@ -2045,174 +2097,184 @@ describe('plugin-meetings', () => {
|
|
|
2045
2097
|
|
|
2046
2098
|
// the roap media connection should be updated
|
|
2047
2099
|
if (isMultistream) {
|
|
2048
|
-
assert.calledOnceWithExactly(
|
|
2100
|
+
assert.calledOnceWithExactly(
|
|
2101
|
+
fakeMultistreamRoapMediaConnection.unpublishTrack,
|
|
2102
|
+
fakeMicrophoneTrack
|
|
2103
|
+
);
|
|
2049
2104
|
} else {
|
|
2050
2105
|
assert.calledOnceWithExactly(fakeRoapMediaConnection.update, {
|
|
2051
|
-
localTracks: {
|
|
2106
|
+
localTracks: {audio: null, video: null, screenShareVideo: null},
|
|
2052
2107
|
direction: {
|
|
2053
2108
|
audio: expected.direction,
|
|
2054
2109
|
video: 'sendrecv',
|
|
2055
2110
|
screenShareVideo: 'recvonly',
|
|
2056
2111
|
},
|
|
2057
|
-
remoteQualityLevel: 'HIGH'
|
|
2112
|
+
remoteQualityLevel: 'HIGH',
|
|
2058
2113
|
});
|
|
2059
2114
|
}
|
|
2060
2115
|
|
|
2061
2116
|
if (expected.localMuteSentValue !== undefined) {
|
|
2062
2117
|
// and local mute sent to Locus
|
|
2063
|
-
checkLocalMuteSentToLocus({
|
|
2118
|
+
checkLocalMuteSentToLocus({
|
|
2119
|
+
audioMuted:
|
|
2120
|
+
!expected.localMuteSentValue /* negation, because we're un-publishing */,
|
|
2121
|
+
videoMuted: true,
|
|
2122
|
+
});
|
|
2064
2123
|
assert.calledOnce(locusMediaRequestStub);
|
|
2065
2124
|
} else {
|
|
2066
2125
|
assert.notCalled(locusMediaRequestStub);
|
|
2067
2126
|
}
|
|
2068
2127
|
});
|
|
2069
2128
|
});
|
|
2070
|
-
|
|
2129
|
+
});
|
|
2071
2130
|
|
|
2072
|
-
|
|
2131
|
+
describe('updateMedia()', () => {
|
|
2132
|
+
const addMedia = async (enableMedia, track) => {
|
|
2133
|
+
await meeting.addMedia({audioEnabled: enableMedia, localTracks: {microphone: track}});
|
|
2134
|
+
await simulateRoapOffer();
|
|
2073
2135
|
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
await simulateRoapOffer();
|
|
2077
|
-
|
|
2078
|
-
resetHistory();
|
|
2079
|
-
}
|
|
2136
|
+
resetHistory();
|
|
2137
|
+
};
|
|
2080
2138
|
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
video:
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2139
|
+
const checkAudioEnabled = (expectedTrack, expectedDirection) => {
|
|
2140
|
+
if (isMultistream) {
|
|
2141
|
+
assert.calledOnceWithExactly(
|
|
2142
|
+
fakeMultistreamRoapMediaConnection.enableMultistreamAudio,
|
|
2143
|
+
expectedDirection !== 'inactive'
|
|
2144
|
+
);
|
|
2145
|
+
} else {
|
|
2146
|
+
assert.calledOnceWithExactly(fakeRoapMediaConnection.update, {
|
|
2147
|
+
localTracks: {audio: expectedTrack, video: null, screenShareVideo: null},
|
|
2148
|
+
direction: {
|
|
2149
|
+
audio: expectedDirection,
|
|
2150
|
+
video: 'sendrecv',
|
|
2151
|
+
screenShareVideo: 'recvonly',
|
|
2152
|
+
},
|
|
2153
|
+
remoteQualityLevel: 'HIGH',
|
|
2154
|
+
});
|
|
2155
|
+
}
|
|
2156
|
+
};
|
|
2096
2157
|
|
|
2097
|
-
|
|
2098
|
-
|
|
2158
|
+
it('updateMedia() disables media when nothing is published', async () => {
|
|
2159
|
+
await addMedia(true);
|
|
2099
2160
|
|
|
2100
|
-
|
|
2161
|
+
await meeting.updateMedia({audioEnabled: false});
|
|
2101
2162
|
|
|
2102
|
-
|
|
2103
|
-
|
|
2163
|
+
// the roap media connection should be updated
|
|
2164
|
+
checkAudioEnabled(null, 'inactive');
|
|
2104
2165
|
|
|
2105
|
-
|
|
2106
|
-
|
|
2166
|
+
// and that would trigger a new offer so we simulate it happening
|
|
2167
|
+
await simulateRoapOffer();
|
|
2107
2168
|
|
|
2108
|
-
|
|
2109
|
-
|
|
2169
|
+
// check SDP offer was sent with the right audioMuted/videoMuted values
|
|
2170
|
+
checkSdpOfferSent({audioMuted: true, videoMuted: true});
|
|
2110
2171
|
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2172
|
+
// and no other local mute requests were sent to Locus
|
|
2173
|
+
assert.calledOnce(locusMediaRequestStub);
|
|
2174
|
+
});
|
|
2114
2175
|
|
|
2115
|
-
|
|
2116
|
-
|
|
2176
|
+
it('updateMedia() enables media when nothing is published', async () => {
|
|
2177
|
+
await addMedia(false);
|
|
2117
2178
|
|
|
2118
|
-
|
|
2179
|
+
await meeting.updateMedia({audioEnabled: true});
|
|
2119
2180
|
|
|
2120
|
-
|
|
2121
|
-
|
|
2181
|
+
// the roap media connection should be updated
|
|
2182
|
+
checkAudioEnabled(null, 'sendrecv');
|
|
2122
2183
|
|
|
2123
|
-
|
|
2124
|
-
|
|
2184
|
+
// and that would trigger a new offer so we simulate it happening
|
|
2185
|
+
await simulateRoapOffer();
|
|
2125
2186
|
|
|
2126
|
-
|
|
2127
|
-
|
|
2187
|
+
// check SDP offer was sent with the right audioMuted/videoMuted values
|
|
2188
|
+
checkSdpOfferSent({audioMuted: true, videoMuted: true});
|
|
2128
2189
|
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2190
|
+
// and no other local mute requests were sent to Locus
|
|
2191
|
+
assert.calledOnce(locusMediaRequestStub);
|
|
2192
|
+
});
|
|
2132
2193
|
|
|
2133
|
-
|
|
2134
|
-
|
|
2194
|
+
it('updateMedia() disables media when track is published', async () => {
|
|
2195
|
+
await addMedia(true, fakeMicrophoneTrack);
|
|
2135
2196
|
|
|
2136
|
-
|
|
2137
|
-
|
|
2197
|
+
await meeting.updateMedia({audioEnabled: false});
|
|
2198
|
+
await stableState();
|
|
2138
2199
|
|
|
2139
|
-
|
|
2140
|
-
|
|
2200
|
+
// the roap media connection should be updated
|
|
2201
|
+
checkAudioEnabled(webrtcAudioTrack, 'inactive');
|
|
2141
2202
|
|
|
2142
|
-
|
|
2203
|
+
checkLocalMuteSentToLocus({audioMuted: true, videoMuted: true});
|
|
2143
2204
|
|
|
2144
|
-
|
|
2205
|
+
locusMediaRequestStub.resetHistory();
|
|
2145
2206
|
|
|
2146
|
-
|
|
2147
|
-
|
|
2207
|
+
// and that would trigger a new offer so we simulate it happening
|
|
2208
|
+
await simulateRoapOffer();
|
|
2148
2209
|
|
|
2149
|
-
|
|
2150
|
-
|
|
2210
|
+
// check SDP offer was sent with the right audioMuted/videoMuted values
|
|
2211
|
+
checkSdpOfferSent({audioMuted: true, videoMuted: true});
|
|
2151
2212
|
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2213
|
+
// and no other local mute requests were sent to Locus
|
|
2214
|
+
assert.calledOnce(locusMediaRequestStub);
|
|
2215
|
+
});
|
|
2155
2216
|
|
|
2156
|
-
|
|
2157
|
-
|
|
2217
|
+
it('updateMedia() enables media when track is published', async () => {
|
|
2218
|
+
await addMedia(false, fakeMicrophoneTrack);
|
|
2158
2219
|
|
|
2159
|
-
|
|
2160
|
-
|
|
2220
|
+
await meeting.updateMedia({audioEnabled: true});
|
|
2221
|
+
await stableState();
|
|
2161
2222
|
|
|
2162
|
-
|
|
2163
|
-
|
|
2223
|
+
// the roap media connection should be updated
|
|
2224
|
+
checkAudioEnabled(webrtcAudioTrack, 'sendrecv');
|
|
2164
2225
|
|
|
2165
|
-
|
|
2226
|
+
checkLocalMuteSentToLocus({audioMuted: false, videoMuted: true});
|
|
2166
2227
|
|
|
2167
|
-
|
|
2228
|
+
locusMediaRequestStub.resetHistory();
|
|
2168
2229
|
|
|
2169
|
-
|
|
2170
|
-
|
|
2230
|
+
// and that would trigger a new offer so we simulate it happening
|
|
2231
|
+
await simulateRoapOffer();
|
|
2171
2232
|
|
|
2172
|
-
|
|
2173
|
-
|
|
2233
|
+
// check SDP offer was sent with the right audioMuted/videoMuted values
|
|
2234
|
+
checkSdpOfferSent({audioMuted: false, videoMuted: true});
|
|
2174
2235
|
|
|
2175
|
-
|
|
2176
|
-
|
|
2236
|
+
// and no other local mute requests were sent to Locus
|
|
2237
|
+
assert.calledOnce(locusMediaRequestStub);
|
|
2238
|
+
});
|
|
2177
2239
|
});
|
|
2178
|
-
});
|
|
2179
2240
|
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2241
|
+
[
|
|
2242
|
+
{mute: true, title: 'muting a track before confluence is created'},
|
|
2243
|
+
{mute: false, title: 'unmuting a track before confluence is created'},
|
|
2244
|
+
].forEach(({mute, title}) =>
|
|
2245
|
+
it(title, async () => {
|
|
2246
|
+
// initialize the microphone mute state to opposite of what we do in the test
|
|
2247
|
+
fakeMicrophoneTrack.muted = !mute;
|
|
2187
2248
|
|
|
2188
|
-
|
|
2189
|
-
|
|
2249
|
+
await meeting.addMedia({localTracks: {microphone: fakeMicrophoneTrack}});
|
|
2250
|
+
await stableState();
|
|
2190
2251
|
|
|
2191
|
-
|
|
2252
|
+
resetHistory();
|
|
2192
2253
|
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2254
|
+
assert.equal(fakeMicrophoneTrack.on.getCall(0).args[0], LocalTrackEvents.Muted);
|
|
2255
|
+
const mutedListener = fakeMicrophoneTrack.on.getCall(0).args[1];
|
|
2256
|
+
// simulate track being muted
|
|
2257
|
+
mutedListener({trackState: {muted: mute}});
|
|
2197
2258
|
|
|
2198
|
-
|
|
2259
|
+
await stableState();
|
|
2199
2260
|
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2261
|
+
// nothing should happen
|
|
2262
|
+
assert.notCalled(locusMediaRequestStub);
|
|
2263
|
+
assert.notCalled(fakeRoapMediaConnection.update);
|
|
2203
2264
|
|
|
2204
|
-
|
|
2205
|
-
|
|
2265
|
+
// now simulate roap offer
|
|
2266
|
+
await simulateRoapOffer();
|
|
2206
2267
|
|
|
2207
|
-
|
|
2208
|
-
|
|
2268
|
+
// it should be sent with the right mute status
|
|
2269
|
+
checkSdpOfferSent({audioMuted: mute, videoMuted: true});
|
|
2209
2270
|
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2271
|
+
// nothing else should happen
|
|
2272
|
+
assert.calledOnce(locusMediaRequestStub);
|
|
2273
|
+
assert.notCalled(fakeRoapMediaConnection.update);
|
|
2274
|
+
})
|
|
2275
|
+
);
|
|
2276
|
+
})
|
|
2277
|
+
);
|
|
2216
2278
|
|
|
2217
2279
|
describe('#acknowledge', () => {
|
|
2218
2280
|
it('should have #acknowledge', () => {
|
|
@@ -2313,7 +2375,9 @@ describe('plugin-meetings', () => {
|
|
|
2313
2375
|
|
|
2314
2376
|
assert.exists(leave.then);
|
|
2315
2377
|
await leave;
|
|
2316
|
-
assert.calledWith(webex.internal.newMetrics.submitInternalEvent, {
|
|
2378
|
+
assert.calledWith(webex.internal.newMetrics.submitInternalEvent, {
|
|
2379
|
+
name: 'internal.reset.join.latencies',
|
|
2380
|
+
});
|
|
2317
2381
|
});
|
|
2318
2382
|
|
|
2319
2383
|
describe('after audio/video is defined', () => {
|
|
@@ -2359,11 +2423,14 @@ describe('plugin-meetings', () => {
|
|
|
2359
2423
|
correlationId: meeting.correlationId,
|
|
2360
2424
|
selfId: meeting.selfId,
|
|
2361
2425
|
resourceId: meeting.resourceId,
|
|
2362
|
-
deviceUrl: meeting.deviceUrl
|
|
2426
|
+
deviceUrl: meeting.deviceUrl,
|
|
2363
2427
|
});
|
|
2364
2428
|
});
|
|
2365
2429
|
it('should leave the meeting on the resource with reason', async () => {
|
|
2366
|
-
const leave = meeting.leave({
|
|
2430
|
+
const leave = meeting.leave({
|
|
2431
|
+
resourceId: meeting.resourceId,
|
|
2432
|
+
reason: MEETING_REMOVED_REASON.CLIENT_LEAVE_REQUEST,
|
|
2433
|
+
});
|
|
2367
2434
|
|
|
2368
2435
|
assert.exists(leave.then);
|
|
2369
2436
|
await leave;
|
|
@@ -2373,7 +2440,7 @@ describe('plugin-meetings', () => {
|
|
|
2373
2440
|
selfId: meeting.selfId,
|
|
2374
2441
|
resourceId: meeting.resourceId,
|
|
2375
2442
|
deviceUrl: meeting.deviceUrl,
|
|
2376
|
-
reason: MEETING_REMOVED_REASON.CLIENT_LEAVE_REQUEST
|
|
2443
|
+
reason: MEETING_REMOVED_REASON.CLIENT_LEAVE_REQUEST,
|
|
2377
2444
|
});
|
|
2378
2445
|
});
|
|
2379
2446
|
});
|
|
@@ -2444,12 +2511,12 @@ describe('plugin-meetings', () => {
|
|
|
2444
2511
|
let sandbox;
|
|
2445
2512
|
|
|
2446
2513
|
const createFakeLocalTrack = () => ({
|
|
2447
|
-
underlyingTrack: {id: 'fake underlying track'}
|
|
2514
|
+
underlyingTrack: {id: 'fake underlying track'},
|
|
2448
2515
|
});
|
|
2449
2516
|
beforeEach(() => {
|
|
2450
2517
|
sandbox = sinon.createSandbox();
|
|
2451
|
-
meeting.audio = {
|
|
2452
|
-
meeting.video = {
|
|
2518
|
+
meeting.audio = {enable: sinon.stub()};
|
|
2519
|
+
meeting.video = {enable: sinon.stub()};
|
|
2453
2520
|
meeting.mediaProperties.audioTrack = createFakeLocalTrack();
|
|
2454
2521
|
meeting.mediaProperties.videoTrack = createFakeLocalTrack();
|
|
2455
2522
|
meeting.mediaProperties.shareVideoTrack = createFakeLocalTrack();
|
|
@@ -2460,7 +2527,7 @@ describe('plugin-meetings', () => {
|
|
|
2460
2527
|
receiveAudio: true,
|
|
2461
2528
|
receiveVideo: true,
|
|
2462
2529
|
receiveShare: true,
|
|
2463
|
-
}
|
|
2530
|
+
};
|
|
2464
2531
|
});
|
|
2465
2532
|
|
|
2466
2533
|
afterEach(() => {
|
|
@@ -2499,11 +2566,9 @@ describe('plugin-meetings', () => {
|
|
|
2499
2566
|
|
|
2500
2567
|
let myPromiseResolved = false;
|
|
2501
2568
|
|
|
2502
|
-
meeting
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
myPromiseResolved = true;
|
|
2506
|
-
});
|
|
2569
|
+
meeting.updateMedia({audioEnabled: false, videoEnabled: false}).then(() => {
|
|
2570
|
+
myPromiseResolved = true;
|
|
2571
|
+
});
|
|
2507
2572
|
|
|
2508
2573
|
// verify that nothing was done
|
|
2509
2574
|
assert.notCalled(meeting.mediaProperties.webrtcMediaConnection.update);
|
|
@@ -2517,22 +2582,19 @@ describe('plugin-meetings', () => {
|
|
|
2517
2582
|
|
|
2518
2583
|
// and check that update is called with the original args
|
|
2519
2584
|
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.update);
|
|
2520
|
-
assert.calledWith(
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
remoteQualityLevel: 'HIGH',
|
|
2534
|
-
}
|
|
2535
|
-
);
|
|
2585
|
+
assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.update, {
|
|
2586
|
+
localTracks: {
|
|
2587
|
+
audio: meeting.mediaProperties.audioTrack.underlyingTrack,
|
|
2588
|
+
video: meeting.mediaProperties.videoTrack.underlyingTrack,
|
|
2589
|
+
screenShareVideo: meeting.mediaProperties.shareVideoTrack.underlyingTrack,
|
|
2590
|
+
},
|
|
2591
|
+
direction: {
|
|
2592
|
+
audio: 'inactive',
|
|
2593
|
+
video: 'inactive',
|
|
2594
|
+
screenShareVideo: 'sendrecv',
|
|
2595
|
+
},
|
|
2596
|
+
remoteQualityLevel: 'HIGH',
|
|
2597
|
+
});
|
|
2536
2598
|
assert.isTrue(myPromiseResolved);
|
|
2537
2599
|
});
|
|
2538
2600
|
});
|
|
@@ -2915,15 +2977,15 @@ describe('plugin-meetings', () => {
|
|
|
2915
2977
|
});
|
|
2916
2978
|
});
|
|
2917
2979
|
|
|
2918
|
-
describe(
|
|
2919
|
-
it(
|
|
2980
|
+
describe('#isJoined', () => {
|
|
2981
|
+
it('should returns isJoined correctly', () => {
|
|
2920
2982
|
meeting.joinedWith = undefined;
|
|
2921
2983
|
assert.equal(meeting.isJoined(), false);
|
|
2922
2984
|
|
|
2923
|
-
meeting.joinedWith = {state:
|
|
2985
|
+
meeting.joinedWith = {state: 'NOT_JOINED'};
|
|
2924
2986
|
assert.equal(meeting.isJoined(), false);
|
|
2925
2987
|
|
|
2926
|
-
meeting.joinedWith = {state:
|
|
2988
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
2927
2989
|
assert.equal(meeting.isJoined(), true);
|
|
2928
2990
|
});
|
|
2929
2991
|
});
|
|
@@ -2939,7 +3001,10 @@ describe('plugin-meetings', () => {
|
|
|
2939
3001
|
const FAKE_CAPTCHA_AUDIO_URL = 'http://captchaaudio';
|
|
2940
3002
|
const FAKE_CAPTCHA_REFRESH_URL = 'http://captcharefresh';
|
|
2941
3003
|
const FAKE_INSTALLED_ORG_ID = '123456';
|
|
2942
|
-
const FAKE_EXTRA_PARAMS = {
|
|
3004
|
+
const FAKE_EXTRA_PARAMS = {
|
|
3005
|
+
mtid: 'm9fe0afd8c435e892afcce9ea25b97046',
|
|
3006
|
+
joinTXId: 'TSmrX61wNF',
|
|
3007
|
+
};
|
|
2943
3008
|
let FAKE_OPTIONS;
|
|
2944
3009
|
const FAKE_MEETING_INFO = {
|
|
2945
3010
|
conversationUrl: 'some_convo_url',
|
|
@@ -2971,7 +3036,9 @@ describe('plugin-meetings', () => {
|
|
|
2971
3036
|
|
|
2972
3037
|
it('calls meetingInfoProvider with all the right parameters and parses the result', async () => {
|
|
2973
3038
|
meeting.attrs.meetingInfoProvider = {
|
|
2974
|
-
fetchMeetingInfo: sinon
|
|
3039
|
+
fetchMeetingInfo: sinon
|
|
3040
|
+
.stub()
|
|
3041
|
+
.resolves({body: FAKE_MEETING_INFO, url: FAKE_MEETING_INFO_LOOKUP_URL}),
|
|
2975
3042
|
};
|
|
2976
3043
|
meeting.requiredCaptcha = FAKE_SDK_CAPTCHA_INFO;
|
|
2977
3044
|
meeting.destination = FAKE_DESTINATION;
|
|
@@ -2997,8 +3064,15 @@ describe('plugin-meetings', () => {
|
|
|
2997
3064
|
FAKE_OPTIONS
|
|
2998
3065
|
);
|
|
2999
3066
|
|
|
3000
|
-
assert.calledWith(
|
|
3001
|
-
|
|
3067
|
+
assert.calledWith(
|
|
3068
|
+
meeting.parseMeetingInfo,
|
|
3069
|
+
{body: FAKE_MEETING_INFO, url: FAKE_MEETING_INFO_LOOKUP_URL},
|
|
3070
|
+
FAKE_DESTINATION
|
|
3071
|
+
);
|
|
3072
|
+
assert.deepEqual(meeting.meetingInfo, {
|
|
3073
|
+
...FAKE_MEETING_INFO,
|
|
3074
|
+
meetingLookupUrl: FAKE_MEETING_INFO_LOOKUP_URL,
|
|
3075
|
+
});
|
|
3002
3076
|
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.NOT_REQUIRED);
|
|
3003
3077
|
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.NONE);
|
|
3004
3078
|
assert.equal(meeting.requiredCaptcha, null);
|
|
@@ -3013,7 +3087,9 @@ describe('plugin-meetings', () => {
|
|
|
3013
3087
|
|
|
3014
3088
|
it('calls meetingInfoProvider with all the right parameters and parses the result when random delay is applied', async () => {
|
|
3015
3089
|
meeting.attrs.meetingInfoProvider = {
|
|
3016
|
-
fetchMeetingInfo: sinon
|
|
3090
|
+
fetchMeetingInfo: sinon
|
|
3091
|
+
.stub()
|
|
3092
|
+
.resolves({body: FAKE_MEETING_INFO, url: FAKE_MEETING_INFO_LOOKUP_URL}),
|
|
3017
3093
|
};
|
|
3018
3094
|
meeting.destination = FAKE_DESTINATION;
|
|
3019
3095
|
meeting.destinationType = FAKE_TYPE;
|
|
@@ -3044,9 +3120,16 @@ describe('plugin-meetings', () => {
|
|
|
3044
3120
|
);
|
|
3045
3121
|
|
|
3046
3122
|
// parseMeeting info
|
|
3047
|
-
assert.calledWith(
|
|
3123
|
+
assert.calledWith(
|
|
3124
|
+
meeting.parseMeetingInfo,
|
|
3125
|
+
{body: FAKE_MEETING_INFO, url: FAKE_MEETING_INFO_LOOKUP_URL},
|
|
3126
|
+
FAKE_DESTINATION
|
|
3127
|
+
);
|
|
3048
3128
|
|
|
3049
|
-
assert.deepEqual(meeting.meetingInfo, {
|
|
3129
|
+
assert.deepEqual(meeting.meetingInfo, {
|
|
3130
|
+
...FAKE_MEETING_INFO,
|
|
3131
|
+
meetingLookupUrl: FAKE_MEETING_INFO_LOOKUP_URL,
|
|
3132
|
+
});
|
|
3050
3133
|
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.NONE);
|
|
3051
3134
|
assert.equal(meeting.requiredCaptcha, null);
|
|
3052
3135
|
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.NOT_REQUIRED);
|
|
@@ -3062,7 +3145,9 @@ describe('plugin-meetings', () => {
|
|
|
3062
3145
|
|
|
3063
3146
|
it('fails if captchaCode is provided when captcha not needed', async () => {
|
|
3064
3147
|
meeting.attrs.meetingInfoProvider = {
|
|
3065
|
-
fetchMeetingInfo: sinon
|
|
3148
|
+
fetchMeetingInfo: sinon
|
|
3149
|
+
.stub()
|
|
3150
|
+
.resolves({body: FAKE_MEETING_INFO, url: FAKE_MEETING_INFO_LOOKUP_URL}),
|
|
3066
3151
|
};
|
|
3067
3152
|
meeting.requiredCaptcha = null;
|
|
3068
3153
|
meeting.destination = FAKE_DESTINATION;
|
|
@@ -3081,7 +3166,9 @@ describe('plugin-meetings', () => {
|
|
|
3081
3166
|
|
|
3082
3167
|
it('fails if password is provided when not required', async () => {
|
|
3083
3168
|
meeting.attrs.meetingInfoProvider = {
|
|
3084
|
-
fetchMeetingInfo: sinon
|
|
3169
|
+
fetchMeetingInfo: sinon
|
|
3170
|
+
.stub()
|
|
3171
|
+
.resolves({body: FAKE_MEETING_INFO, url: FAKE_MEETING_INFO_LOOKUP_URL}),
|
|
3085
3172
|
};
|
|
3086
3173
|
meeting.passwordStatus = PASSWORD_STATUS.NOT_REQUIRED;
|
|
3087
3174
|
meeting.destination = FAKE_DESTINATION;
|
|
@@ -3118,7 +3205,7 @@ describe('plugin-meetings', () => {
|
|
|
3118
3205
|
undefined,
|
|
3119
3206
|
'locus-id',
|
|
3120
3207
|
{},
|
|
3121
|
-
{meetingId: meeting.id}
|
|
3208
|
+
{meetingId: meeting.id}
|
|
3122
3209
|
);
|
|
3123
3210
|
|
|
3124
3211
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
@@ -3151,18 +3238,14 @@ describe('plugin-meetings', () => {
|
|
|
3151
3238
|
undefined,
|
|
3152
3239
|
'locus-id',
|
|
3153
3240
|
{},
|
|
3154
|
-
{meetingId: meeting.id}
|
|
3241
|
+
{meetingId: meeting.id}
|
|
3155
3242
|
);
|
|
3156
3243
|
|
|
3157
3244
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
3158
3245
|
assert.equal(meeting.meetingInfoFailureCode, 123456);
|
|
3159
|
-
assert.equal(
|
|
3160
|
-
meeting.meetingInfoFailureReason,
|
|
3161
|
-
MEETING_INFO_FAILURE_REASON.POLICY
|
|
3162
|
-
);
|
|
3246
|
+
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.POLICY);
|
|
3163
3247
|
});
|
|
3164
3248
|
|
|
3165
|
-
|
|
3166
3249
|
it('handles meetingInfoProvider requiring captcha because of wrong password', async () => {
|
|
3167
3250
|
meeting.destination = FAKE_DESTINATION;
|
|
3168
3251
|
meeting.destinationType = FAKE_TYPE;
|
|
@@ -3189,7 +3272,7 @@ describe('plugin-meetings', () => {
|
|
|
3189
3272
|
undefined,
|
|
3190
3273
|
'locus-id',
|
|
3191
3274
|
{},
|
|
3192
|
-
{meetingId: meeting.id}
|
|
3275
|
+
{meetingId: meeting.id}
|
|
3193
3276
|
);
|
|
3194
3277
|
|
|
3195
3278
|
assert.deepEqual(meeting.meetingInfo, {});
|
|
@@ -3197,7 +3280,7 @@ describe('plugin-meetings', () => {
|
|
|
3197
3280
|
meeting.meetingInfoFailureReason,
|
|
3198
3281
|
MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD
|
|
3199
3282
|
);
|
|
3200
|
-
|
|
3283
|
+
assert.equal(meeting.meetingInfoFailureCode, 423005);
|
|
3201
3284
|
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.REQUIRED);
|
|
3202
3285
|
assert.deepEqual(meeting.requiredCaptcha, {
|
|
3203
3286
|
captchaId: FAKE_CAPTCHA_ID,
|
|
@@ -3267,10 +3350,13 @@ describe('plugin-meetings', () => {
|
|
|
3267
3350
|
undefined,
|
|
3268
3351
|
'locus-id',
|
|
3269
3352
|
{},
|
|
3270
|
-
{meetingId: meeting.id}
|
|
3353
|
+
{meetingId: meeting.id}
|
|
3271
3354
|
);
|
|
3272
3355
|
|
|
3273
|
-
assert.deepEqual(meeting.meetingInfo, {
|
|
3356
|
+
assert.deepEqual(meeting.meetingInfo, {
|
|
3357
|
+
...FAKE_MEETING_INFO,
|
|
3358
|
+
meetingLookupUrl: undefined,
|
|
3359
|
+
});
|
|
3274
3360
|
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.NONE);
|
|
3275
3361
|
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.VERIFIED);
|
|
3276
3362
|
assert.equal(meeting.requiredCaptcha, null);
|
|
@@ -3316,7 +3402,7 @@ describe('plugin-meetings', () => {
|
|
|
3316
3402
|
undefined,
|
|
3317
3403
|
'locus-id',
|
|
3318
3404
|
{},
|
|
3319
|
-
{meetingId: meeting.id}
|
|
3405
|
+
{meetingId: meeting.id}
|
|
3320
3406
|
);
|
|
3321
3407
|
|
|
3322
3408
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
@@ -3468,12 +3554,11 @@ describe('plugin-meetings', () => {
|
|
|
3468
3554
|
|
|
3469
3555
|
it('should trigger `submitClientEvent`', async () => {
|
|
3470
3556
|
await meeting.postMetrics('client.call.leave');
|
|
3471
|
-
console.log({s: webex.internal.newMetrics.submitClientEvent.getCall(0).args[0]})
|
|
3557
|
+
console.log({s: webex.internal.newMetrics.submitClientEvent.getCall(0).args[0]});
|
|
3472
3558
|
assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
|
|
3473
3559
|
name: 'client.call.leave',
|
|
3474
3560
|
options: {meetingId: meeting.id},
|
|
3475
3561
|
});
|
|
3476
|
-
|
|
3477
3562
|
});
|
|
3478
3563
|
});
|
|
3479
3564
|
|
|
@@ -3586,7 +3671,7 @@ describe('plugin-meetings', () => {
|
|
|
3586
3671
|
});
|
|
3587
3672
|
assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
|
|
3588
3673
|
name: 'client.call.move-media',
|
|
3589
|
-
options: {meetingId: meeting.id}
|
|
3674
|
+
options: {meetingId: meeting.id},
|
|
3590
3675
|
});
|
|
3591
3676
|
});
|
|
3592
3677
|
|
|
@@ -3767,7 +3852,7 @@ describe('plugin-meetings', () => {
|
|
|
3767
3852
|
on: sinon.stub(),
|
|
3768
3853
|
off: sinon.stub(),
|
|
3769
3854
|
getSettings: sinon.stub(),
|
|
3770
|
-
}
|
|
3855
|
+
};
|
|
3771
3856
|
videoShareTrack = {
|
|
3772
3857
|
id: 'share track',
|
|
3773
3858
|
on: sinon.stub(),
|
|
@@ -3786,8 +3871,8 @@ describe('plugin-meetings', () => {
|
|
|
3786
3871
|
publishTrack: sinon.stub().resolves({}),
|
|
3787
3872
|
unpublishTrack: sinon.stub().resolves({}),
|
|
3788
3873
|
};
|
|
3789
|
-
meeting.audio = {
|
|
3790
|
-
meeting.video = {
|
|
3874
|
+
meeting.audio = {handleLocalTrackChange: sinon.stub()};
|
|
3875
|
+
meeting.video = {handleLocalTrackChange: sinon.stub()};
|
|
3791
3876
|
|
|
3792
3877
|
const createFakeLocalTrack = (originalTrack) => ({
|
|
3793
3878
|
on: sinon.stub(),
|
|
@@ -3829,10 +3914,7 @@ describe('plugin-meetings', () => {
|
|
|
3829
3914
|
|
|
3830
3915
|
const checkAudioPublished = (track) => {
|
|
3831
3916
|
assert.calledOnceWithExactly(meeting.audio.handleLocalTrackChange, meeting);
|
|
3832
|
-
assert.calledWith(
|
|
3833
|
-
meeting.mediaProperties.webrtcMediaConnection.publishTrack,
|
|
3834
|
-
track
|
|
3835
|
-
);
|
|
3917
|
+
assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, track);
|
|
3836
3918
|
assert.equal(meeting.mediaProperties.audioTrack, track);
|
|
3837
3919
|
// check that sendAudio hasn't been touched
|
|
3838
3920
|
assert.equal(meeting.mediaProperties.mediaDirection.sendAudio, 'fake value');
|
|
@@ -3840,10 +3922,7 @@ describe('plugin-meetings', () => {
|
|
|
3840
3922
|
|
|
3841
3923
|
const checkVideoPublished = (track) => {
|
|
3842
3924
|
assert.calledOnceWithExactly(meeting.video.handleLocalTrackChange, meeting);
|
|
3843
|
-
assert.calledWith(
|
|
3844
|
-
meeting.mediaProperties.webrtcMediaConnection.publishTrack,
|
|
3845
|
-
track
|
|
3846
|
-
);
|
|
3925
|
+
assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, track);
|
|
3847
3926
|
assert.equal(meeting.mediaProperties.videoTrack, track);
|
|
3848
3927
|
// check that sendVideo hasn't been touched
|
|
3849
3928
|
assert.equal(meeting.mediaProperties.mediaDirection.sendVideo, 'fake value');
|
|
@@ -3852,10 +3931,7 @@ describe('plugin-meetings', () => {
|
|
|
3852
3931
|
const checkScreenShareVideoPublished = (track) => {
|
|
3853
3932
|
assert.calledOnce(meeting.requestScreenShareFloor);
|
|
3854
3933
|
|
|
3855
|
-
assert.calledWith(
|
|
3856
|
-
meeting.mediaProperties.webrtcMediaConnection.publishTrack,
|
|
3857
|
-
track
|
|
3858
|
-
);
|
|
3934
|
+
assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, track);
|
|
3859
3935
|
assert.equal(meeting.mediaProperties.shareVideoTrack, track);
|
|
3860
3936
|
assert.equal(meeting.mediaProperties.mediaDirection.sendShare, true);
|
|
3861
3937
|
};
|
|
@@ -3863,10 +3939,7 @@ describe('plugin-meetings', () => {
|
|
|
3863
3939
|
const checkScreenShareAudioPublished = (track) => {
|
|
3864
3940
|
assert.calledOnce(meeting.requestScreenShareFloor);
|
|
3865
3941
|
|
|
3866
|
-
assert.calledWith(
|
|
3867
|
-
meeting.mediaProperties.webrtcMediaConnection.publishTrack,
|
|
3868
|
-
track
|
|
3869
|
-
);
|
|
3942
|
+
assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, track);
|
|
3870
3943
|
assert.equal(meeting.mediaProperties.shareAudioTrack, track);
|
|
3871
3944
|
assert.equal(meeting.mediaProperties.mediaDirection.sendShare, true);
|
|
3872
3945
|
};
|
|
@@ -3892,7 +3965,7 @@ describe('plugin-meetings', () => {
|
|
|
3892
3965
|
meeting.requestScreenShareFloor.reset();
|
|
3893
3966
|
await meeting.publishTracks({screenShare: {video: videoShareTrack}});
|
|
3894
3967
|
assert.notCalled(meeting.requestScreenShareFloor);
|
|
3895
|
-
})
|
|
3968
|
+
});
|
|
3896
3969
|
|
|
3897
3970
|
it('does not request screen share floor when publishing audio share track if already sharing video', async () => {
|
|
3898
3971
|
await meeting.publishTracks({screenShare: {video: videoShareTrack}});
|
|
@@ -3901,7 +3974,7 @@ describe('plugin-meetings', () => {
|
|
|
3901
3974
|
meeting.requestScreenShareFloor.reset();
|
|
3902
3975
|
await meeting.publishTracks({screenShare: {audio: audioShareTrack}});
|
|
3903
3976
|
assert.notCalled(meeting.requestScreenShareFloor);
|
|
3904
|
-
})
|
|
3977
|
+
});
|
|
3905
3978
|
|
|
3906
3979
|
it('updates MuteState instance and publishes the track for main audio', async () => {
|
|
3907
3980
|
await meeting.publishTracks({microphone: audioTrack});
|
|
@@ -4006,7 +4079,12 @@ describe('plugin-meetings', () => {
|
|
|
4006
4079
|
});
|
|
4007
4080
|
|
|
4008
4081
|
it('un-publishes the tracks correctly (all 4 together)', async () => {
|
|
4009
|
-
await meeting.unpublishTracks([
|
|
4082
|
+
await meeting.unpublishTracks([
|
|
4083
|
+
audioTrack,
|
|
4084
|
+
videoTrack,
|
|
4085
|
+
videoShareTrack,
|
|
4086
|
+
audioShareTrack,
|
|
4087
|
+
]);
|
|
4010
4088
|
|
|
4011
4089
|
assert.equal(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack.callCount, 4);
|
|
4012
4090
|
checkAudioUnpublished();
|
|
@@ -4066,36 +4144,40 @@ describe('plugin-meetings', () => {
|
|
|
4066
4144
|
describe('#enableMusicMode', () => {
|
|
4067
4145
|
beforeEach(() => {
|
|
4068
4146
|
meeting.isMultistream = true;
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
});
|
|
4074
|
-
[
|
|
4075
|
-
{shouldEnableMusicMode: true},
|
|
4076
|
-
{shouldEnableMusicMode: false},
|
|
4077
|
-
].forEach(({shouldEnableMusicMode}) => {
|
|
4078
|
-
it(`fails if there is no media connection for shouldEnableMusicMode: ${shouldEnableMusicMode}`, async () => {
|
|
4079
|
-
meeting.mediaProperties.webrtcMediaConnection = undefined;
|
|
4080
|
-
await assert.isRejected(meeting.enableMusicMode(shouldEnableMusicMode));
|
|
4081
|
-
});
|
|
4147
|
+
meeting.mediaProperties.webrtcMediaConnection = {
|
|
4148
|
+
setCodecParameters: sinon.stub().resolves({}),
|
|
4149
|
+
deleteCodecParameters: sinon.stub().resolves({}),
|
|
4150
|
+
};
|
|
4082
4151
|
});
|
|
4152
|
+
[{shouldEnableMusicMode: true}, {shouldEnableMusicMode: false}].forEach(
|
|
4153
|
+
({shouldEnableMusicMode}) => {
|
|
4154
|
+
it(`fails if there is no media connection for shouldEnableMusicMode: ${shouldEnableMusicMode}`, async () => {
|
|
4155
|
+
meeting.mediaProperties.webrtcMediaConnection = undefined;
|
|
4156
|
+
await assert.isRejected(meeting.enableMusicMode(shouldEnableMusicMode));
|
|
4157
|
+
});
|
|
4158
|
+
}
|
|
4159
|
+
);
|
|
4083
4160
|
|
|
4084
4161
|
it('should set the codec parameters when shouldEnableMusicMode is true', async () => {
|
|
4085
4162
|
await meeting.enableMusicMode(true);
|
|
4086
|
-
assert.calledOnceWithExactly(
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4163
|
+
assert.calledOnceWithExactly(
|
|
4164
|
+
meeting.mediaProperties.webrtcMediaConnection.setCodecParameters,
|
|
4165
|
+
MediaType.AudioMain,
|
|
4166
|
+
{
|
|
4167
|
+
maxaveragebitrate: '64000',
|
|
4168
|
+
maxplaybackrate: '48000',
|
|
4169
|
+
}
|
|
4170
|
+
);
|
|
4090
4171
|
assert.notCalled(meeting.mediaProperties.webrtcMediaConnection.deleteCodecParameters);
|
|
4091
4172
|
});
|
|
4092
4173
|
|
|
4093
4174
|
it('should set the codec parameters when shouldEnableMusicMode is false', async () => {
|
|
4094
4175
|
await meeting.enableMusicMode(false);
|
|
4095
|
-
assert.calledOnceWithExactly(
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4176
|
+
assert.calledOnceWithExactly(
|
|
4177
|
+
meeting.mediaProperties.webrtcMediaConnection.deleteCodecParameters,
|
|
4178
|
+
MediaType.AudioMain,
|
|
4179
|
+
['maxaveragebitrate', 'maxplaybackrate']
|
|
4180
|
+
);
|
|
4099
4181
|
assert.notCalled(meeting.mediaProperties.webrtcMediaConnection.setCodecParameters);
|
|
4100
4182
|
});
|
|
4101
4183
|
});
|
|
@@ -4301,7 +4383,8 @@ describe('plugin-meetings', () => {
|
|
|
4301
4383
|
|
|
4302
4384
|
describe('submitClientEvent on connectionFailed', () => {
|
|
4303
4385
|
it('sends client.ice.end when connectionFailed on CONNECTION_STATE_CHANGED event', () => {
|
|
4304
|
-
webex.internal.newMetrics.callDiagnosticMetrics.getErrorPayloadForClientErrorCode =
|
|
4386
|
+
webex.internal.newMetrics.callDiagnosticMetrics.getErrorPayloadForClientErrorCode =
|
|
4387
|
+
sinon.stub().returns({});
|
|
4305
4388
|
meeting.setupMediaConnectionListeners();
|
|
4306
4389
|
eventListeners[Event.CONNECTION_STATE_CHANGED]({
|
|
4307
4390
|
state: 'Failed',
|
|
@@ -4625,7 +4708,7 @@ describe('plugin-meetings', () => {
|
|
|
4625
4708
|
it('registers for audio and video source count changed', () => {
|
|
4626
4709
|
assert.isFunction(eventListeners[Event.VIDEO_SOURCES_COUNT_CHANGED]);
|
|
4627
4710
|
assert.isFunction(eventListeners[Event.AUDIO_SOURCES_COUNT_CHANGED]);
|
|
4628
|
-
})
|
|
4711
|
+
});
|
|
4629
4712
|
|
|
4630
4713
|
it('forwards the VIDEO_SOURCES_COUNT_CHANGED event as "media:remoteVideoSourceCountChanged"', () => {
|
|
4631
4714
|
const numTotalSources = 10;
|
|
@@ -4634,9 +4717,14 @@ describe('plugin-meetings', () => {
|
|
|
4634
4717
|
|
|
4635
4718
|
sinon.stub(meeting.mediaRequestManagers.video, 'setNumCurrentSources');
|
|
4636
4719
|
|
|
4637
|
-
eventListeners[Event.VIDEO_SOURCES_COUNT_CHANGED](
|
|
4720
|
+
eventListeners[Event.VIDEO_SOURCES_COUNT_CHANGED](
|
|
4721
|
+
numTotalSources,
|
|
4722
|
+
numLiveSources,
|
|
4723
|
+
mediaContent
|
|
4724
|
+
);
|
|
4638
4725
|
|
|
4639
|
-
assert.calledOnceWithExactly(
|
|
4726
|
+
assert.calledOnceWithExactly(
|
|
4727
|
+
TriggerProxy.trigger,
|
|
4640
4728
|
meeting,
|
|
4641
4729
|
sinon.match.object,
|
|
4642
4730
|
'media:remoteVideoSourceCountChanged',
|
|
@@ -4653,9 +4741,14 @@ describe('plugin-meetings', () => {
|
|
|
4653
4741
|
const numLiveSources = 2;
|
|
4654
4742
|
const mediaContent = 'MAIN';
|
|
4655
4743
|
|
|
4656
|
-
eventListeners[Event.AUDIO_SOURCES_COUNT_CHANGED](
|
|
4744
|
+
eventListeners[Event.AUDIO_SOURCES_COUNT_CHANGED](
|
|
4745
|
+
numTotalSources,
|
|
4746
|
+
numLiveSources,
|
|
4747
|
+
mediaContent
|
|
4748
|
+
);
|
|
4657
4749
|
|
|
4658
|
-
assert.calledOnceWithExactly(
|
|
4750
|
+
assert.calledOnceWithExactly(
|
|
4751
|
+
TriggerProxy.trigger,
|
|
4659
4752
|
meeting,
|
|
4660
4753
|
sinon.match.object,
|
|
4661
4754
|
'media:remoteAudioSourceCountChanged',
|
|
@@ -4671,9 +4764,16 @@ describe('plugin-meetings', () => {
|
|
|
4671
4764
|
const numTotalSources = 20;
|
|
4672
4765
|
const numLiveSources = 10;
|
|
4673
4766
|
|
|
4674
|
-
const setNumCurrentSourcesSpy = sinon.stub(
|
|
4767
|
+
const setNumCurrentSourcesSpy = sinon.stub(
|
|
4768
|
+
meeting.mediaRequestManagers.video,
|
|
4769
|
+
'setNumCurrentSources'
|
|
4770
|
+
);
|
|
4675
4771
|
|
|
4676
|
-
eventListeners[Event.VIDEO_SOURCES_COUNT_CHANGED](
|
|
4772
|
+
eventListeners[Event.VIDEO_SOURCES_COUNT_CHANGED](
|
|
4773
|
+
numTotalSources,
|
|
4774
|
+
numLiveSources,
|
|
4775
|
+
'MAIN'
|
|
4776
|
+
);
|
|
4677
4777
|
|
|
4678
4778
|
assert.calledOnceWithExactly(setNumCurrentSourcesSpy, numTotalSources, numLiveSources);
|
|
4679
4779
|
});
|
|
@@ -4682,14 +4782,20 @@ describe('plugin-meetings', () => {
|
|
|
4682
4782
|
const numTotalSources = 20;
|
|
4683
4783
|
const numLiveSources = 10;
|
|
4684
4784
|
|
|
4685
|
-
const setNumCurrentSourcesSpy = sinon.stub(
|
|
4785
|
+
const setNumCurrentSourcesSpy = sinon.stub(
|
|
4786
|
+
meeting.mediaRequestManagers.video,
|
|
4787
|
+
'setNumCurrentSources'
|
|
4788
|
+
);
|
|
4686
4789
|
|
|
4687
|
-
eventListeners[Event.VIDEO_SOURCES_COUNT_CHANGED](
|
|
4790
|
+
eventListeners[Event.VIDEO_SOURCES_COUNT_CHANGED](
|
|
4791
|
+
numTotalSources,
|
|
4792
|
+
numLiveSources,
|
|
4793
|
+
'SLIDES'
|
|
4794
|
+
);
|
|
4688
4795
|
|
|
4689
4796
|
assert.notCalled(setNumCurrentSourcesSpy);
|
|
4690
4797
|
});
|
|
4691
|
-
|
|
4692
|
-
})
|
|
4798
|
+
});
|
|
4693
4799
|
});
|
|
4694
4800
|
describe('#setUpLocusInfoSelfListener', () => {
|
|
4695
4801
|
it('listens to the self unadmitted guest event', (done) => {
|
|
@@ -4746,14 +4852,13 @@ describe('plugin-meetings', () => {
|
|
|
4746
4852
|
meeting.breakouts.updateCanManageBreakouts = sinon.stub();
|
|
4747
4853
|
meeting.simultaneousInterpretation.updateCanManageInterpreters = sinon.stub();
|
|
4748
4854
|
|
|
4749
|
-
meeting.locusInfo.emit(
|
|
4750
|
-
{function: 'test', file: 'test'},
|
|
4751
|
-
'SELF_ROLES_CHANGED',
|
|
4752
|
-
payload
|
|
4753
|
-
);
|
|
4855
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'SELF_ROLES_CHANGED', payload);
|
|
4754
4856
|
|
|
4755
4857
|
assert.calledOnceWithExactly(meeting.breakouts.updateCanManageBreakouts, true);
|
|
4756
|
-
assert.calledOnceWithExactly(
|
|
4858
|
+
assert.calledOnceWithExactly(
|
|
4859
|
+
meeting.simultaneousInterpretation.updateCanManageInterpreters,
|
|
4860
|
+
true
|
|
4861
|
+
);
|
|
4757
4862
|
assert.calledWith(
|
|
4758
4863
|
TriggerProxy.trigger,
|
|
4759
4864
|
meeting,
|
|
@@ -4774,7 +4879,10 @@ describe('plugin-meetings', () => {
|
|
|
4774
4879
|
payload
|
|
4775
4880
|
);
|
|
4776
4881
|
|
|
4777
|
-
assert.calledOnceWithExactly(
|
|
4882
|
+
assert.calledOnceWithExactly(
|
|
4883
|
+
meeting.simultaneousInterpretation.updateSelfInterpretation,
|
|
4884
|
+
payload
|
|
4885
|
+
);
|
|
4778
4886
|
assert.calledWith(
|
|
4779
4887
|
TriggerProxy.trigger,
|
|
4780
4888
|
meeting,
|
|
@@ -4827,14 +4935,14 @@ describe('plugin-meetings', () => {
|
|
|
4827
4935
|
|
|
4828
4936
|
it('should not trigger ASK_RETURN_TO_MAIN before joined', () => {
|
|
4829
4937
|
TriggerProxy.trigger.reset();
|
|
4830
|
-
meeting.joinedWith = {state:
|
|
4938
|
+
meeting.joinedWith = {state: 'NOT_JOINED'};
|
|
4831
4939
|
meeting.breakouts.trigger('ASK_RETURN_TO_MAIN');
|
|
4832
4940
|
assert.notCalled(TriggerProxy.trigger);
|
|
4833
4941
|
});
|
|
4834
4942
|
|
|
4835
4943
|
it('listens to the ask return to main event from breakouts and triggers the ask return to main event from meeting', () => {
|
|
4836
4944
|
TriggerProxy.trigger.reset();
|
|
4837
|
-
meeting.joinedWith = {state:
|
|
4945
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
4838
4946
|
meeting.breakouts.trigger('ASK_RETURN_TO_MAIN');
|
|
4839
4947
|
assert.calledWith(
|
|
4840
4948
|
TriggerProxy.trigger,
|
|
@@ -4857,7 +4965,7 @@ describe('plugin-meetings', () => {
|
|
|
4857
4965
|
|
|
4858
4966
|
it('listens to the breakout ask for help event and triggers the ask for help event', () => {
|
|
4859
4967
|
TriggerProxy.trigger.reset();
|
|
4860
|
-
const helpEvent = {sessionId:'sessionId', participant: 'participant'}
|
|
4968
|
+
const helpEvent = {sessionId: 'sessionId', participant: 'participant'};
|
|
4861
4969
|
meeting.breakouts.trigger('ASK_FOR_HELP', helpEvent);
|
|
4862
4970
|
assert.calledWith(
|
|
4863
4971
|
TriggerProxy.trigger,
|
|
@@ -4904,7 +5012,7 @@ describe('plugin-meetings', () => {
|
|
|
4904
5012
|
});
|
|
4905
5013
|
|
|
4906
5014
|
it('listens to CONTROLS_MUTE_ON_ENTRY_CHANGED', async () => {
|
|
4907
|
-
const state = {example: 'value'}
|
|
5015
|
+
const state = {example: 'value'};
|
|
4908
5016
|
|
|
4909
5017
|
await meeting.locusInfo.emitScoped(
|
|
4910
5018
|
{function: 'test', file: 'test'},
|
|
@@ -4917,12 +5025,12 @@ describe('plugin-meetings', () => {
|
|
|
4917
5025
|
meeting,
|
|
4918
5026
|
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
4919
5027
|
EVENT_TRIGGERS.MEETING_CONTROLS_MUTE_ON_ENTRY_UPDATED,
|
|
4920
|
-
{state}
|
|
5028
|
+
{state}
|
|
4921
5029
|
);
|
|
4922
5030
|
});
|
|
4923
5031
|
|
|
4924
5032
|
it('listens to MEETING_CONTROLS_SHARE_CONTROL_UPDATED', async () => {
|
|
4925
|
-
const state = {example: 'value'}
|
|
5033
|
+
const state = {example: 'value'};
|
|
4926
5034
|
|
|
4927
5035
|
await meeting.locusInfo.emitScoped(
|
|
4928
5036
|
{function: 'test', file: 'test'},
|
|
@@ -4935,12 +5043,12 @@ describe('plugin-meetings', () => {
|
|
|
4935
5043
|
meeting,
|
|
4936
5044
|
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
4937
5045
|
EVENT_TRIGGERS.MEETING_CONTROLS_SHARE_CONTROL_UPDATED,
|
|
4938
|
-
{state}
|
|
5046
|
+
{state}
|
|
4939
5047
|
);
|
|
4940
5048
|
});
|
|
4941
5049
|
|
|
4942
5050
|
it('listens to MEETING_CONTROLS_DISALLOW_UNMUTE_UPDATED', async () => {
|
|
4943
|
-
const state = {example: 'value'}
|
|
5051
|
+
const state = {example: 'value'};
|
|
4944
5052
|
|
|
4945
5053
|
await meeting.locusInfo.emitScoped(
|
|
4946
5054
|
{function: 'test', file: 'test'},
|
|
@@ -4953,12 +5061,12 @@ describe('plugin-meetings', () => {
|
|
|
4953
5061
|
meeting,
|
|
4954
5062
|
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
4955
5063
|
EVENT_TRIGGERS.MEETING_CONTROLS_DISALLOW_UNMUTE_UPDATED,
|
|
4956
|
-
{state}
|
|
5064
|
+
{state}
|
|
4957
5065
|
);
|
|
4958
5066
|
});
|
|
4959
5067
|
|
|
4960
5068
|
it('listens to MEETING_CONTROLS_REACTIONS_UPDATED', async () => {
|
|
4961
|
-
const state = {example: 'value'}
|
|
5069
|
+
const state = {example: 'value'};
|
|
4962
5070
|
|
|
4963
5071
|
await meeting.locusInfo.emitScoped(
|
|
4964
5072
|
{function: 'test', file: 'test'},
|
|
@@ -4971,12 +5079,12 @@ describe('plugin-meetings', () => {
|
|
|
4971
5079
|
meeting,
|
|
4972
5080
|
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
4973
5081
|
EVENT_TRIGGERS.MEETING_CONTROLS_REACTIONS_UPDATED,
|
|
4974
|
-
{state}
|
|
5082
|
+
{state}
|
|
4975
5083
|
);
|
|
4976
5084
|
});
|
|
4977
5085
|
|
|
4978
5086
|
it('listens to MEETING_CONTROLS_VIEW_THE_PARTICIPANTS_LIST_UPDATED', async () => {
|
|
4979
|
-
const state = {example: 'value'}
|
|
5087
|
+
const state = {example: 'value'};
|
|
4980
5088
|
|
|
4981
5089
|
await meeting.locusInfo.emitScoped(
|
|
4982
5090
|
{function: 'test', file: 'test'},
|
|
@@ -4989,12 +5097,12 @@ describe('plugin-meetings', () => {
|
|
|
4989
5097
|
meeting,
|
|
4990
5098
|
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
4991
5099
|
EVENT_TRIGGERS.MEETING_CONTROLS_VIEW_THE_PARTICIPANTS_LIST_UPDATED,
|
|
4992
|
-
{state}
|
|
5100
|
+
{state}
|
|
4993
5101
|
);
|
|
4994
5102
|
});
|
|
4995
5103
|
|
|
4996
5104
|
it('listens to MEETING_CONTROLS_RAISE_HAND_UPDATED', async () => {
|
|
4997
|
-
const state = {example: 'value'}
|
|
5105
|
+
const state = {example: 'value'};
|
|
4998
5106
|
|
|
4999
5107
|
await meeting.locusInfo.emitScoped(
|
|
5000
5108
|
{function: 'test', file: 'test'},
|
|
@@ -5007,12 +5115,12 @@ describe('plugin-meetings', () => {
|
|
|
5007
5115
|
meeting,
|
|
5008
5116
|
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
5009
5117
|
EVENT_TRIGGERS.MEETING_CONTROLS_RAISE_HAND_UPDATED,
|
|
5010
|
-
{state}
|
|
5118
|
+
{state}
|
|
5011
5119
|
);
|
|
5012
5120
|
});
|
|
5013
5121
|
|
|
5014
5122
|
it('listens to MEETING_CONTROLS_VIDEO_UPDATED', async () => {
|
|
5015
|
-
const state = {example: 'value'}
|
|
5123
|
+
const state = {example: 'value'};
|
|
5016
5124
|
|
|
5017
5125
|
await meeting.locusInfo.emitScoped(
|
|
5018
5126
|
{function: 'test', file: 'test'},
|
|
@@ -5025,7 +5133,7 @@ describe('plugin-meetings', () => {
|
|
|
5025
5133
|
meeting,
|
|
5026
5134
|
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
5027
5135
|
EVENT_TRIGGERS.MEETING_CONTROLS_VIDEO_UPDATED,
|
|
5028
|
-
{state}
|
|
5136
|
+
{state}
|
|
5029
5137
|
);
|
|
5030
5138
|
});
|
|
5031
5139
|
|
|
@@ -5076,7 +5184,10 @@ describe('plugin-meetings', () => {
|
|
|
5076
5184
|
{interpretation}
|
|
5077
5185
|
);
|
|
5078
5186
|
|
|
5079
|
-
assert.calledOnceWithExactly(
|
|
5187
|
+
assert.calledOnceWithExactly(
|
|
5188
|
+
meeting.simultaneousInterpretation.updateInterpretation,
|
|
5189
|
+
interpretation
|
|
5190
|
+
);
|
|
5080
5191
|
assert.calledWith(
|
|
5081
5192
|
TriggerProxy.trigger,
|
|
5082
5193
|
meeting,
|
|
@@ -5148,15 +5259,15 @@ describe('plugin-meetings', () => {
|
|
|
5148
5259
|
|
|
5149
5260
|
assert.calledWith(
|
|
5150
5261
|
meeting.recordingController.setServiceUrl,
|
|
5151
|
-
newLocusServices.services.record.url
|
|
5262
|
+
newLocusServices.services.record.url
|
|
5152
5263
|
);
|
|
5153
5264
|
assert.calledWith(
|
|
5154
5265
|
meeting.annotation.approvalUrlUpdate,
|
|
5155
|
-
newLocusServices.services.approval.url
|
|
5266
|
+
newLocusServices.services.approval.url
|
|
5156
5267
|
);
|
|
5157
5268
|
assert.calledWith(
|
|
5158
5269
|
meeting.simultaneousInterpretation.approvalUrlUpdate,
|
|
5159
|
-
newLocusServices.services.approval.url
|
|
5270
|
+
newLocusServices.services.approval.url
|
|
5160
5271
|
);
|
|
5161
5272
|
assert.calledOnce(meeting.recordingController.setSessionId);
|
|
5162
5273
|
done();
|
|
@@ -5569,12 +5680,12 @@ describe('plugin-meetings', () => {
|
|
|
5569
5680
|
currentSIInterpreter: false,
|
|
5570
5681
|
siLanguages: [
|
|
5571
5682
|
{
|
|
5572
|
-
languageCode:
|
|
5683
|
+
languageCode: 'ar',
|
|
5573
5684
|
languageGroupId: 4,
|
|
5574
5685
|
},
|
|
5575
|
-
]
|
|
5576
|
-
}
|
|
5577
|
-
}
|
|
5686
|
+
],
|
|
5687
|
+
},
|
|
5688
|
+
},
|
|
5578
5689
|
};
|
|
5579
5690
|
meeting.parseMeetingInfo(mockToggleOnData);
|
|
5580
5691
|
assert.calledOnceWithExactly(parseInterpretationInfo, meeting, mockToggleOnData.body);
|
|
@@ -5693,7 +5804,6 @@ describe('plugin-meetings', () => {
|
|
|
5693
5804
|
waitingForOthersToJoinSpy.restore();
|
|
5694
5805
|
});
|
|
5695
5806
|
|
|
5696
|
-
|
|
5697
5807
|
forEach(
|
|
5698
5808
|
[
|
|
5699
5809
|
{
|
|
@@ -5812,6 +5922,11 @@ describe('plugin-meetings', () => {
|
|
|
5812
5922
|
requiredPolicies: [],
|
|
5813
5923
|
enableUnifiedMeetings: false,
|
|
5814
5924
|
},
|
|
5925
|
+
{
|
|
5926
|
+
actionName: 'canAnnotate',
|
|
5927
|
+
requiredDisplayHints: [],
|
|
5928
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_ANNOTATION],
|
|
5929
|
+
},
|
|
5815
5930
|
],
|
|
5816
5931
|
({actionName, requiredDisplayHints, requiredPolicies, enableUnifiedMeetings}) => {
|
|
5817
5932
|
it(`${actionName} is enabled when the conditions are met`, () => {
|
|
@@ -6125,7 +6240,6 @@ describe('plugin-meetings', () => {
|
|
|
6125
6240
|
meeting.joinedWith = {state: 'JOINED'};
|
|
6126
6241
|
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
6127
6242
|
|
|
6128
|
-
|
|
6129
6243
|
const result = await meeting.updateLLMConnection();
|
|
6130
6244
|
|
|
6131
6245
|
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
@@ -6164,9 +6278,7 @@ describe('plugin-meetings', () => {
|
|
|
6164
6278
|
'event:relay.event',
|
|
6165
6279
|
meeting.processRelayEvent
|
|
6166
6280
|
);
|
|
6167
|
-
assert.calledTwice(
|
|
6168
|
-
meeting.webex.internal.llm.off
|
|
6169
|
-
);
|
|
6281
|
+
assert.calledTwice(meeting.webex.internal.llm.off);
|
|
6170
6282
|
assert.calledOnceWithExactly(
|
|
6171
6283
|
meeting.webex.internal.llm.on,
|
|
6172
6284
|
'event:relay.event',
|
|
@@ -6192,7 +6304,6 @@ describe('plugin-meetings', () => {
|
|
|
6192
6304
|
meeting.processRelayEvent
|
|
6193
6305
|
);
|
|
6194
6306
|
});
|
|
6195
|
-
|
|
6196
6307
|
});
|
|
6197
6308
|
|
|
6198
6309
|
describe('#setLocus', () => {
|
|
@@ -6293,15 +6404,13 @@ describe('plugin-meetings', () => {
|
|
|
6293
6404
|
});
|
|
6294
6405
|
});
|
|
6295
6406
|
describe('share scenarios', () => {
|
|
6296
|
-
|
|
6297
6407
|
describe('triggerAnnotationInfoEvent', () => {
|
|
6298
6408
|
it('check triggerAnnotationInfoEvent event', () => {
|
|
6299
|
-
|
|
6300
6409
|
TriggerProxy.trigger.reset();
|
|
6301
|
-
const annotationInfo= {version: '1', policy: 'Approval'}
|
|
6302
|
-
const expectAnnotationInfo = {annotationInfo,meetingId:meeting.id
|
|
6303
|
-
meeting.webex.meetings ={}
|
|
6304
|
-
meeting.triggerAnnotationInfoEvent({annotation:annotationInfo},{});
|
|
6410
|
+
const annotationInfo = {version: '1', policy: 'Approval'};
|
|
6411
|
+
const expectAnnotationInfo = {annotationInfo, meetingId: meeting.id};
|
|
6412
|
+
meeting.webex.meetings = {};
|
|
6413
|
+
meeting.triggerAnnotationInfoEvent({annotation: annotationInfo}, {});
|
|
6305
6414
|
assert.calledWith(
|
|
6306
6415
|
TriggerProxy.trigger,
|
|
6307
6416
|
{},
|
|
@@ -6314,13 +6423,22 @@ describe('plugin-meetings', () => {
|
|
|
6314
6423
|
);
|
|
6315
6424
|
|
|
6316
6425
|
TriggerProxy.trigger.reset();
|
|
6317
|
-
meeting.triggerAnnotationInfoEvent(
|
|
6426
|
+
meeting.triggerAnnotationInfoEvent(
|
|
6427
|
+
{annotation: annotationInfo},
|
|
6428
|
+
{annotation: annotationInfo}
|
|
6429
|
+
);
|
|
6318
6430
|
assert.notCalled(TriggerProxy.trigger);
|
|
6319
6431
|
|
|
6320
6432
|
TriggerProxy.trigger.reset();
|
|
6321
|
-
const annotationInfoUpdate = {version: '1', policy: 'AnnotationNotAllowed'}
|
|
6322
|
-
const expectAnnotationInfoUpdated = {
|
|
6323
|
-
|
|
6433
|
+
const annotationInfoUpdate = {version: '1', policy: 'AnnotationNotAllowed'};
|
|
6434
|
+
const expectAnnotationInfoUpdated = {
|
|
6435
|
+
annotationInfo: annotationInfoUpdate,
|
|
6436
|
+
meetingId: meeting.id,
|
|
6437
|
+
};
|
|
6438
|
+
meeting.triggerAnnotationInfoEvent(
|
|
6439
|
+
{annotation: annotationInfoUpdate},
|
|
6440
|
+
{annotation: annotationInfo}
|
|
6441
|
+
);
|
|
6324
6442
|
assert.calledWith(
|
|
6325
6443
|
TriggerProxy.trigger,
|
|
6326
6444
|
{},
|
|
@@ -6333,9 +6451,8 @@ describe('plugin-meetings', () => {
|
|
|
6333
6451
|
);
|
|
6334
6452
|
|
|
6335
6453
|
TriggerProxy.trigger.reset();
|
|
6336
|
-
meeting.triggerAnnotationInfoEvent(null,{annotation:annotationInfoUpdate});
|
|
6454
|
+
meeting.triggerAnnotationInfoEvent(null, {annotation: annotationInfoUpdate});
|
|
6337
6455
|
assert.notCalled(TriggerProxy.trigger);
|
|
6338
|
-
|
|
6339
6456
|
});
|
|
6340
6457
|
});
|
|
6341
6458
|
|
|
@@ -6357,7 +6474,11 @@ describe('plugin-meetings', () => {
|
|
|
6357
6474
|
'https://board-a.wbx2.com/board/api/v1/channels/977a7330-54f4-11eb-b1ef-91f5eefc7bf3',
|
|
6358
6475
|
};
|
|
6359
6476
|
|
|
6360
|
-
const generateContent = (
|
|
6477
|
+
const generateContent = (
|
|
6478
|
+
beneficiaryId = null,
|
|
6479
|
+
disposition = null,
|
|
6480
|
+
annotation = undefined
|
|
6481
|
+
) => ({
|
|
6361
6482
|
beneficiaryId,
|
|
6362
6483
|
disposition,
|
|
6363
6484
|
});
|
|
@@ -6403,7 +6524,11 @@ describe('plugin-meetings', () => {
|
|
|
6403
6524
|
if (isGranting) {
|
|
6404
6525
|
if (isContent) {
|
|
6405
6526
|
activeSharingId.content = beneficiaryId;
|
|
6406
|
-
newPayload.current.content = generateContent(
|
|
6527
|
+
newPayload.current.content = generateContent(
|
|
6528
|
+
beneficiaryId,
|
|
6529
|
+
FLOOR_ACTION.GRANTED,
|
|
6530
|
+
annotation
|
|
6531
|
+
);
|
|
6407
6532
|
|
|
6408
6533
|
if (isEqual(newPayload.current, newPayload.previous)) {
|
|
6409
6534
|
eventTrigger.member = null;
|
|
@@ -6457,7 +6582,12 @@ describe('plugin-meetings', () => {
|
|
|
6457
6582
|
eventTrigger.share.push({
|
|
6458
6583
|
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
|
6459
6584
|
functionName: 'remoteShare',
|
|
6460
|
-
eventPayload: {
|
|
6585
|
+
eventPayload: {
|
|
6586
|
+
memberId: beneficiaryId,
|
|
6587
|
+
url,
|
|
6588
|
+
shareInstanceId,
|
|
6589
|
+
annotationInfo: undefined,
|
|
6590
|
+
},
|
|
6461
6591
|
});
|
|
6462
6592
|
}
|
|
6463
6593
|
}
|