@webex/plugin-meetings 2.60.0-next.1 → 2.60.0-next.11
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/annotation/annotation.types.d.ts +42 -0
- package/dist/annotation/constants.d.ts +31 -0
- package/dist/annotation/index.d.ts +117 -0
- package/dist/breakouts/breakout.d.ts +8 -0
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/collection.d.ts +5 -0
- package/dist/breakouts/edit-lock-error.d.ts +15 -0
- package/dist/breakouts/events.d.ts +8 -0
- package/dist/breakouts/index.d.ts +5 -0
- package/dist/breakouts/index.js +1 -1
- package/dist/breakouts/request.d.ts +22 -0
- package/dist/breakouts/utils.d.ts +15 -0
- package/dist/common/browser-detection.d.ts +9 -0
- package/dist/common/collection.d.ts +48 -0
- package/dist/common/config.d.ts +2 -0
- package/dist/common/errors/captcha-error.d.ts +15 -0
- package/dist/common/errors/intent-to-join.d.ts +16 -0
- package/dist/common/errors/join-meeting.d.ts +17 -0
- package/dist/common/errors/media.d.ts +15 -0
- package/dist/common/errors/no-meeting-info.d.ts +14 -0
- package/dist/common/errors/parameter.d.ts +15 -0
- package/dist/common/errors/password-error.d.ts +15 -0
- package/dist/common/errors/permission.d.ts +14 -0
- package/dist/common/errors/reclaim-host-role-errors.d.ts +60 -0
- package/dist/common/errors/reconnection-in-progress.d.ts +9 -0
- package/dist/common/errors/reconnection.d.ts +15 -0
- package/dist/common/errors/stats.d.ts +15 -0
- package/dist/common/errors/webex-errors.d.ts +93 -0
- package/dist/common/errors/webex-meetings-error.d.ts +20 -0
- package/dist/common/events/events-scope.d.ts +17 -0
- package/dist/common/events/events.d.ts +12 -0
- package/dist/common/events/trigger-proxy.d.ts +2 -0
- package/dist/common/events/util.d.ts +2 -0
- package/dist/common/logs/logger-config.d.ts +2 -0
- package/dist/common/logs/logger-proxy.d.ts +2 -0
- package/dist/common/logs/request.d.ts +36 -0
- package/dist/common/queue.d.ts +34 -0
- package/dist/config.d.ts +71 -0
- package/dist/constants.d.ts +1072 -0
- package/dist/constants.js +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/constants.d.ts +4 -0
- package/dist/controls-options-manager/enums.d.ts +15 -0
- package/dist/controls-options-manager/enums.js +2 -1
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.d.ts +136 -0
- package/dist/controls-options-manager/types.d.ts +43 -0
- package/dist/controls-options-manager/util.d.ts +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/interpretation/collection.d.ts +5 -0
- package/dist/interpretation/index.d.ts +5 -0
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.d.ts +5 -0
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.d.ts +2 -0
- package/dist/locus-info/embeddedAppsUtils.d.ts +2 -0
- package/dist/locus-info/fullState.d.ts +2 -0
- package/dist/locus-info/hostUtils.d.ts +2 -0
- package/dist/locus-info/index.d.ts +322 -0
- package/dist/locus-info/infoUtils.d.ts +2 -0
- package/dist/locus-info/mediaSharesUtils.d.ts +2 -0
- package/dist/locus-info/parser.d.ts +272 -0
- package/dist/locus-info/parser.js +5 -5
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.d.ts +2 -0
- package/dist/media/index.d.ts +34 -0
- package/dist/media/index.js +6 -5
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.d.ts +93 -0
- package/dist/media/util.d.ts +2 -0
- package/dist/mediaQualityMetrics/config.d.ts +237 -0
- package/dist/mediaQualityMetrics/config.js +1 -202
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/in-meeting-actions.d.ts +167 -0
- package/dist/meeting/in-meeting-actions.js +4 -0
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.d.ts +1719 -0
- package/dist/meeting/index.js +288 -155
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.d.ts +74 -0
- package/dist/meeting/muteState.d.ts +184 -0
- package/dist/meeting/request.d.ts +290 -0
- package/dist/meeting/request.type.d.ts +11 -0
- package/dist/meeting/state.d.ts +9 -0
- package/dist/meeting/util.d.ts +103 -0
- package/dist/meeting-info/collection.d.ts +20 -0
- package/dist/meeting-info/index.d.ts +69 -0
- package/dist/meeting-info/meeting-info-v2.d.ts +123 -0
- package/dist/meeting-info/meeting-info-v2.js +3 -0
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/request.d.ts +22 -0
- package/dist/meeting-info/util.d.ts +2 -0
- package/dist/meeting-info/utilv2.d.ts +2 -0
- package/dist/meeting-info/utilv2.js +14 -29
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.d.ts +40 -0
- package/dist/meetings/collection.js +17 -0
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.d.ts +378 -0
- package/dist/meetings/index.js +30 -9
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.d.ts +4 -0
- package/dist/meetings/request.d.ts +27 -0
- package/dist/meetings/util.d.ts +18 -0
- package/dist/member/index.d.ts +160 -0
- package/dist/member/member.types.d.ts +11 -0
- package/dist/member/types.d.ts +32 -0
- package/dist/member/util.d.ts +2 -0
- package/dist/members/collection.d.ts +29 -0
- package/dist/members/index.d.ts +353 -0
- package/dist/members/request.d.ts +114 -0
- package/dist/members/types.d.ts +25 -0
- package/dist/members/util.d.ts +215 -0
- package/dist/metrics/constants.d.ts +68 -0
- package/dist/metrics/constants.js +3 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.d.ts +45 -0
- package/dist/multistream/mediaRequestManager.d.ts +118 -0
- package/dist/multistream/receiveSlot.d.ts +68 -0
- package/dist/multistream/receiveSlotManager.d.ts +56 -0
- package/dist/multistream/remoteMedia.d.ts +72 -0
- package/dist/multistream/remoteMediaGroup.d.ts +47 -0
- package/dist/multistream/remoteMediaManager.d.ts +285 -0
- package/dist/multistream/sendSlotManager.d.ts +61 -0
- package/dist/networkQualityMonitor/index.d.ts +70 -0
- package/dist/personal-meeting-room/index.d.ts +47 -0
- package/dist/personal-meeting-room/request.d.ts +14 -0
- package/dist/personal-meeting-room/util.d.ts +2 -0
- package/dist/reachability/index.d.ts +194 -0
- package/dist/reachability/request.d.ts +39 -0
- package/dist/reactions/constants.d.ts +3 -0
- package/dist/reactions/reactions.d.ts +4 -0
- package/dist/reactions/reactions.type.d.ts +52 -0
- package/dist/reconnection-manager/index.d.ts +136 -0
- package/dist/reconnection-manager/index.js +27 -28
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/enums.d.ts +7 -0
- package/dist/recording-controller/index.d.ts +207 -0
- package/dist/recording-controller/util.d.ts +14 -0
- package/dist/roap/index.d.ts +78 -0
- package/dist/roap/request.d.ts +41 -0
- package/dist/roap/turnDiscovery.d.ts +92 -0
- package/dist/rtcMetrics/constants.d.ts +4 -0
- package/dist/rtcMetrics/index.d.ts +54 -0
- package/dist/rtcMetrics/index.js +25 -0
- package/dist/rtcMetrics/index.js.map +1 -1
- package/dist/statsAnalyzer/global.d.ts +36 -0
- package/dist/statsAnalyzer/index.d.ts +191 -0
- package/dist/statsAnalyzer/index.js +53 -146
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.d.ts +24 -0
- package/dist/statsAnalyzer/mqaUtil.js +11 -12
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/transcription/index.d.ts +64 -0
- package/dist/webinar/collection.d.ts +16 -0
- package/dist/webinar/index.d.ts +5 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +26 -27
- package/src/constants.ts +10 -4
- package/src/controls-options-manager/enums.ts +2 -0
- package/src/locus-info/parser.ts +6 -6
- package/src/media/index.ts +5 -5
- package/src/mediaQualityMetrics/config.ts +0 -135
- package/src/meeting/in-meeting-actions.ts +8 -0
- package/src/meeting/index.ts +263 -125
- package/src/meeting-info/meeting-info-v2.ts +4 -0
- package/src/meeting-info/utilv2.ts +6 -19
- package/src/meetings/collection.ts +13 -0
- package/src/meetings/index.ts +28 -10
- package/src/metrics/constants.ts +3 -0
- package/src/reconnection-manager/index.ts +63 -68
- package/src/rtcMetrics/index.ts +24 -0
- package/src/statsAnalyzer/index.ts +68 -216
- package/src/statsAnalyzer/mqaUtil.ts +17 -22
- package/test/unit/spec/media/index.ts +20 -4
- package/test/unit/spec/meeting/in-meeting-actions.ts +4 -0
- package/test/unit/spec/meeting/index.js +1376 -189
- package/test/unit/spec/meeting/muteState.js +2 -1
- package/test/unit/spec/meeting-info/meetinginfov2.js +28 -0
- package/test/unit/spec/meetings/collection.js +12 -0
- package/test/unit/spec/meetings/index.js +382 -118
- package/test/unit/spec/member/util.js +0 -31
- package/test/unit/spec/reconnection-manager/index.js +42 -12
- package/test/unit/spec/rtcMetrics/index.ts +20 -0
- package/test/unit/spec/stats-analyzer/index.js +12 -2
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
NETWORK_STATUS,
|
|
34
34
|
ONLINE,
|
|
35
35
|
OFFLINE,
|
|
36
|
+
RECONNECTION,
|
|
36
37
|
} from '@webex/plugin-meetings/src/constants';
|
|
37
38
|
import * as InternalMediaCoreModule from '@webex/internal-media-core';
|
|
38
39
|
import {
|
|
@@ -307,6 +308,7 @@ describe('plugin-meetings', () => {
|
|
|
307
308
|
assert.equal(meeting.resource, uuid2);
|
|
308
309
|
assert.equal(meeting.deviceUrl, uuid3);
|
|
309
310
|
assert.equal(meeting.correlationId, correlationId);
|
|
311
|
+
assert.deepEqual(meeting.callStateForMetrics, {correlationId});
|
|
310
312
|
assert.deepEqual(meeting.meetingInfo, {});
|
|
311
313
|
assert.instanceOf(meeting.members, Members);
|
|
312
314
|
assert.calledOnceWithExactly(
|
|
@@ -374,6 +376,34 @@ describe('plugin-meetings', () => {
|
|
|
374
376
|
}
|
|
375
377
|
);
|
|
376
378
|
assert.equal(newMeeting.correlationId, newMeeting.id);
|
|
379
|
+
assert.deepEqual(newMeeting.callStateForMetrics, {correlationId: newMeeting.id});
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
it('correlationId can be provided in callStateForMetrics', () => {
|
|
383
|
+
const newMeeting = new Meeting(
|
|
384
|
+
{
|
|
385
|
+
userId: uuid1,
|
|
386
|
+
resource: uuid2,
|
|
387
|
+
deviceUrl: uuid3,
|
|
388
|
+
locus: {url: url1},
|
|
389
|
+
destination: testDestination,
|
|
390
|
+
destinationType: _MEETING_ID_,
|
|
391
|
+
callStateForMetrics: {
|
|
392
|
+
correlationId: uuid4,
|
|
393
|
+
joinTrigger: 'fake-join-trigger',
|
|
394
|
+
loginType: 'fake-login-type',
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
parent: webex,
|
|
399
|
+
}
|
|
400
|
+
);
|
|
401
|
+
assert.equal(newMeeting.correlationId, uuid4);
|
|
402
|
+
assert.deepEqual(newMeeting.callStateForMetrics, {
|
|
403
|
+
correlationId: uuid4,
|
|
404
|
+
joinTrigger: 'fake-join-trigger',
|
|
405
|
+
loginType: 'fake-login-type',
|
|
406
|
+
});
|
|
377
407
|
});
|
|
378
408
|
|
|
379
409
|
describe('creates ReceiveSlot manager instance', () => {
|
|
@@ -827,11 +857,11 @@ describe('plugin-meetings', () => {
|
|
|
827
857
|
});
|
|
828
858
|
|
|
829
859
|
it('should join the meeting and return promise', async () => {
|
|
830
|
-
const join = meeting.join();
|
|
860
|
+
const join = meeting.join({pstnAudioType: 'dial-in'});
|
|
831
861
|
|
|
832
|
-
assert.
|
|
862
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
833
863
|
name: 'client.call.initiated',
|
|
834
|
-
payload: {trigger: 'user-interaction', isRoapCallEnabled: true},
|
|
864
|
+
payload: {trigger: 'user-interaction', isRoapCallEnabled: true, pstnAudioType: 'dial-in'},
|
|
835
865
|
options: {meetingId: meeting.id},
|
|
836
866
|
});
|
|
837
867
|
|
|
@@ -850,6 +880,17 @@ describe('plugin-meetings', () => {
|
|
|
850
880
|
assert.calledOnce(meeting.startTranscription);
|
|
851
881
|
});
|
|
852
882
|
|
|
883
|
+
it('should take trigger from meeting joinTrigger if available', () => {
|
|
884
|
+
meeting.updateCallStateForMetrics({joinTrigger: 'fake-join-trigger'});
|
|
885
|
+
const join = meeting.join();
|
|
886
|
+
|
|
887
|
+
assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
|
|
888
|
+
name: 'client.call.initiated',
|
|
889
|
+
payload: {trigger: 'fake-join-trigger', isRoapCallEnabled: true},
|
|
890
|
+
options: {meetingId: meeting.id},
|
|
891
|
+
});
|
|
892
|
+
});
|
|
893
|
+
|
|
853
894
|
it('should not create new correlation ID on join immediately after create', async () => {
|
|
854
895
|
await meeting.join();
|
|
855
896
|
sinon.assert.notCalled(setCorrelationIdSpy);
|
|
@@ -1172,8 +1213,8 @@ describe('plugin-meetings', () => {
|
|
|
1172
1213
|
assert.exists(meeting.addMedia);
|
|
1173
1214
|
});
|
|
1174
1215
|
|
|
1175
|
-
it('should reject promise if meeting is not active', async () => {
|
|
1176
|
-
const result = await assert.isRejected(meeting.addMedia());
|
|
1216
|
+
it('should reject promise if meeting is not active and the meeting in lobby is not enabled', async () => {
|
|
1217
|
+
const result = await assert.isRejected(meeting.addMedia({allowMediaInLobby: false}));
|
|
1177
1218
|
|
|
1178
1219
|
assert.instanceOf(result, MeetingNotActiveError);
|
|
1179
1220
|
});
|
|
@@ -1791,17 +1832,26 @@ describe('plugin-meetings', () => {
|
|
|
1791
1832
|
}]);
|
|
1792
1833
|
|
|
1793
1834
|
const sendBehavioralMetricCalls = Metrics.sendBehavioralMetric.getCalls();
|
|
1794
|
-
assert.equal(sendBehavioralMetricCalls.length,
|
|
1795
|
-
assert.deepEqual(sendBehavioralMetricCalls[0].args, [
|
|
1835
|
+
assert.equal(sendBehavioralMetricCalls.length, 3);
|
|
1836
|
+
assert.deepEqual(sendBehavioralMetricCalls[0].args, [
|
|
1837
|
+
BEHAVIORAL_METRICS.ADD_MEDIA_RETRY,
|
|
1838
|
+
{
|
|
1839
|
+
correlation_id: meeting.correlationId,
|
|
1840
|
+
state: meeting.state,
|
|
1841
|
+
meetingState: meeting.meetingState,
|
|
1842
|
+
reason: 'forcingTurnTls',
|
|
1843
|
+
},
|
|
1844
|
+
]);
|
|
1845
|
+
assert.deepEqual(sendBehavioralMetricCalls[1].args, [
|
|
1796
1846
|
BEHAVIORAL_METRICS.TURN_DISCOVERY_LATENCY,
|
|
1797
1847
|
{
|
|
1798
1848
|
correlation_id: meeting.correlationId,
|
|
1799
1849
|
turnServerUsed: true,
|
|
1800
1850
|
retriedWithTurnServer: true,
|
|
1801
1851
|
latency: undefined,
|
|
1802
|
-
}
|
|
1852
|
+
},
|
|
1803
1853
|
]);
|
|
1804
|
-
assert.deepEqual(sendBehavioralMetricCalls[
|
|
1854
|
+
assert.deepEqual(sendBehavioralMetricCalls[2].args, [
|
|
1805
1855
|
BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE,
|
|
1806
1856
|
{
|
|
1807
1857
|
correlation_id: meeting.correlationId,
|
|
@@ -1816,7 +1866,7 @@ describe('plugin-meetings', () => {
|
|
|
1816
1866
|
signalingState: 'unknown',
|
|
1817
1867
|
connectionState: 'unknown',
|
|
1818
1868
|
iceConnectionState: 'unknown',
|
|
1819
|
-
}
|
|
1869
|
+
},
|
|
1820
1870
|
]);
|
|
1821
1871
|
|
|
1822
1872
|
// Check that doTurnDiscovery is called with th4 correct value of isForced
|
|
@@ -1957,17 +2007,26 @@ describe('plugin-meetings', () => {
|
|
|
1957
2007
|
}]);
|
|
1958
2008
|
|
|
1959
2009
|
const sendBehavioralMetricCalls = Metrics.sendBehavioralMetric.getCalls();
|
|
1960
|
-
assert.equal(sendBehavioralMetricCalls.length,
|
|
1961
|
-
assert.deepEqual(sendBehavioralMetricCalls[0].args, [
|
|
2010
|
+
assert.equal(sendBehavioralMetricCalls.length, 3);
|
|
2011
|
+
assert.deepEqual(sendBehavioralMetricCalls[0].args, [
|
|
2012
|
+
BEHAVIORAL_METRICS.ADD_MEDIA_RETRY,
|
|
2013
|
+
{
|
|
2014
|
+
correlation_id: meeting.correlationId,
|
|
2015
|
+
state: meeting.state,
|
|
2016
|
+
meetingState: meeting.meetingState,
|
|
2017
|
+
reason: 'forcingTurnTls',
|
|
2018
|
+
},
|
|
2019
|
+
]);
|
|
2020
|
+
assert.deepEqual(sendBehavioralMetricCalls[1].args, [
|
|
1962
2021
|
BEHAVIORAL_METRICS.TURN_DISCOVERY_LATENCY,
|
|
1963
2022
|
{
|
|
1964
2023
|
correlation_id: meeting.correlationId,
|
|
1965
2024
|
turnServerUsed: true,
|
|
1966
2025
|
retriedWithTurnServer: true,
|
|
1967
2026
|
latency: undefined,
|
|
1968
|
-
}
|
|
2027
|
+
},
|
|
1969
2028
|
]);
|
|
1970
|
-
assert.deepEqual(sendBehavioralMetricCalls[
|
|
2029
|
+
assert.deepEqual(sendBehavioralMetricCalls[2].args, [
|
|
1971
2030
|
BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS,
|
|
1972
2031
|
{
|
|
1973
2032
|
correlation_id: meeting.correlationId,
|
|
@@ -1975,7 +2034,7 @@ describe('plugin-meetings', () => {
|
|
|
1975
2034
|
connectionType: 'udp',
|
|
1976
2035
|
isMultistream: false,
|
|
1977
2036
|
retriedWithTurnServer: true,
|
|
1978
|
-
}
|
|
2037
|
+
},
|
|
1979
2038
|
]);
|
|
1980
2039
|
meeting.roap.doTurnDiscovery
|
|
1981
2040
|
|
|
@@ -1999,6 +2058,90 @@ describe('plugin-meetings', () => {
|
|
|
1999
2058
|
assert.isNotOk(errorThrown);
|
|
2000
2059
|
});
|
|
2001
2060
|
|
|
2061
|
+
it('should call join if state is LEFT after first media connection attempt', async () => {
|
|
2062
|
+
const FAKE_TURN_URL = 'turns:webex.com:3478';
|
|
2063
|
+
const FAKE_TURN_USER = 'some-turn-username';
|
|
2064
|
+
const FAKE_TURN_PASSWORD = 'some-password';
|
|
2065
|
+
let errorThrown = undefined;
|
|
2066
|
+
|
|
2067
|
+
meeting.meetingState = 'ACTIVE';
|
|
2068
|
+
meeting.state = 'LEFT';
|
|
2069
|
+
meeting.roap.doTurnDiscovery = sinon.stub().onFirstCall().returns({
|
|
2070
|
+
turnServerInfo: undefined,
|
|
2071
|
+
turnDiscoverySkippedReason: 'reachability',
|
|
2072
|
+
}).onSecondCall().returns({
|
|
2073
|
+
turnServerInfo: {
|
|
2074
|
+
url: FAKE_TURN_URL,
|
|
2075
|
+
username: FAKE_TURN_USER,
|
|
2076
|
+
password: FAKE_TURN_PASSWORD,
|
|
2077
|
+
},
|
|
2078
|
+
turnDiscoverySkippedReason: undefined,
|
|
2079
|
+
});
|
|
2080
|
+
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().onFirstCall().rejects().onSecondCall().resolves();
|
|
2081
|
+
meeting.join = sinon.stub().resolves();
|
|
2082
|
+
|
|
2083
|
+
const closeMediaConnectionStub = sinon.stub();
|
|
2084
|
+
Media.createMediaConnection = sinon.stub().returns({
|
|
2085
|
+
close: closeMediaConnectionStub,
|
|
2086
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
2087
|
+
initiateOffer: sinon.stub().resolves({}),
|
|
2088
|
+
on: sinon.stub(),
|
|
2089
|
+
});
|
|
2090
|
+
|
|
2091
|
+
await meeting
|
|
2092
|
+
.addMedia({
|
|
2093
|
+
mediaSettings: {},
|
|
2094
|
+
})
|
|
2095
|
+
.catch((err) => {
|
|
2096
|
+
errorThrown = err;
|
|
2097
|
+
});
|
|
2098
|
+
|
|
2099
|
+
assert.isNotOk(errorThrown);
|
|
2100
|
+
assert.calledOnceWithExactly(meeting.join, {rejoin: true});
|
|
2101
|
+
});
|
|
2102
|
+
|
|
2103
|
+
it('should reject if join attempt fails if state is LEFT after first media connection attempt', async () => {
|
|
2104
|
+
const FAKE_TURN_URL = 'turns:webex.com:3478';
|
|
2105
|
+
const FAKE_TURN_USER = 'some-turn-username';
|
|
2106
|
+
const FAKE_TURN_PASSWORD = 'some-password';
|
|
2107
|
+
let errorThrown = undefined;
|
|
2108
|
+
|
|
2109
|
+
meeting.meetingState = 'ACTIVE';
|
|
2110
|
+
meeting.state = 'LEFT';
|
|
2111
|
+
meeting.roap.doTurnDiscovery = sinon.stub().onFirstCall().returns({
|
|
2112
|
+
turnServerInfo: undefined,
|
|
2113
|
+
turnDiscoverySkippedReason: 'reachability',
|
|
2114
|
+
}).onSecondCall().returns({
|
|
2115
|
+
turnServerInfo: {
|
|
2116
|
+
url: FAKE_TURN_URL,
|
|
2117
|
+
username: FAKE_TURN_USER,
|
|
2118
|
+
password: FAKE_TURN_PASSWORD,
|
|
2119
|
+
},
|
|
2120
|
+
turnDiscoverySkippedReason: undefined,
|
|
2121
|
+
});
|
|
2122
|
+
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().onFirstCall().rejects().onSecondCall().resolves();
|
|
2123
|
+
meeting.join = sinon.stub().rejects();
|
|
2124
|
+
|
|
2125
|
+
const closeMediaConnectionStub = sinon.stub();
|
|
2126
|
+
Media.createMediaConnection = sinon.stub().returns({
|
|
2127
|
+
close: closeMediaConnectionStub,
|
|
2128
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
2129
|
+
initiateOffer: sinon.stub().resolves({}),
|
|
2130
|
+
on: sinon.stub(),
|
|
2131
|
+
});
|
|
2132
|
+
|
|
2133
|
+
await meeting
|
|
2134
|
+
.addMedia({
|
|
2135
|
+
mediaSettings: {},
|
|
2136
|
+
})
|
|
2137
|
+
.catch((err) => {
|
|
2138
|
+
errorThrown = err;
|
|
2139
|
+
});
|
|
2140
|
+
|
|
2141
|
+
assert.isOk(errorThrown);
|
|
2142
|
+
assert.calledOnceWithExactly(meeting.join, {rejoin: true});
|
|
2143
|
+
});
|
|
2144
|
+
|
|
2002
2145
|
it('should send ADD_MEDIA_SUCCESS metrics', async () => {
|
|
2003
2146
|
meeting.meetingState = 'ACTIVE';
|
|
2004
2147
|
meeting.webex.meetings.reachability = {
|
|
@@ -2383,6 +2526,7 @@ describe('plugin-meetings', () => {
|
|
|
2383
2526
|
category: 'media',
|
|
2384
2527
|
errorCode: clientErrorCode,
|
|
2385
2528
|
serviceErrorCode: undefined,
|
|
2529
|
+
rawErrorMessage: undefined,
|
|
2386
2530
|
...expectedErrorPayload,
|
|
2387
2531
|
},
|
|
2388
2532
|
],
|
|
@@ -2479,8 +2623,12 @@ describe('plugin-meetings', () => {
|
|
|
2479
2623
|
setUnmuteAllowed: sinon.stub(),
|
|
2480
2624
|
setMuted: sinon.stub(),
|
|
2481
2625
|
setServerMuted: sinon.stub(),
|
|
2482
|
-
|
|
2483
|
-
|
|
2626
|
+
outputStream: {
|
|
2627
|
+
getTracks: () => {
|
|
2628
|
+
return [{
|
|
2629
|
+
id: 'fake mic'
|
|
2630
|
+
}];
|
|
2631
|
+
}
|
|
2484
2632
|
}
|
|
2485
2633
|
}
|
|
2486
2634
|
|
|
@@ -2691,10 +2839,10 @@ describe('plugin-meetings', () => {
|
|
|
2691
2839
|
assert.calledOnceWithExactly(roapMediaConnectionConstructorStub, mediaConnectionConfig,
|
|
2692
2840
|
{
|
|
2693
2841
|
localTracks: {
|
|
2694
|
-
audio: localStreams.audio?.
|
|
2695
|
-
video: localStreams.video?.
|
|
2696
|
-
screenShareVideo: localStreams.screenShareVideo?.
|
|
2697
|
-
screenShareAudio: localStreams.screenShareAudio?.
|
|
2842
|
+
audio: localStreams.audio?.outputStream?.getTracks()[0],
|
|
2843
|
+
video: localStreams.video?.outputStream?.getTracks()[0],
|
|
2844
|
+
screenShareVideo: localStreams.screenShareVideo?.outputStream?.getTracks()[0],
|
|
2845
|
+
screenShareAudio: localStreams.screenShareAudio?.outputStream?.getTracks()[0],
|
|
2698
2846
|
},
|
|
2699
2847
|
direction: {audio: direction.audio, video: direction.video, screenShareVideo: direction.screenShare},
|
|
2700
2848
|
remoteQualityLevel,
|
|
@@ -2969,7 +3117,7 @@ describe('plugin-meetings', () => {
|
|
|
2969
3117
|
assert.calledOnceWithExactly(meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream, fakeMicrophoneStream);
|
|
2970
3118
|
} else {
|
|
2971
3119
|
assert.calledOnceWithExactly(fakeRoapMediaConnection.update, {
|
|
2972
|
-
localTracks: { audio: fakeMicrophoneStream.
|
|
3120
|
+
localTracks: { audio: fakeMicrophoneStream.outputStream.getTracks()[0], video: null, screenShareVideo: null, screenShareAudio: null },
|
|
2973
3121
|
direction: {
|
|
2974
3122
|
audio: expected.direction,
|
|
2975
3123
|
video: 'sendrecv',
|
|
@@ -2995,8 +3143,12 @@ describe('plugin-meetings', () => {
|
|
|
2995
3143
|
muted: false,
|
|
2996
3144
|
setUnmuteAllowed: sinon.stub(),
|
|
2997
3145
|
setMuted: sinon.stub(),
|
|
2998
|
-
|
|
2999
|
-
|
|
3146
|
+
outputStream: {
|
|
3147
|
+
getTracks: () => {
|
|
3148
|
+
return [{
|
|
3149
|
+
id: 'fake mic 2',
|
|
3150
|
+
}];
|
|
3151
|
+
}
|
|
3000
3152
|
}
|
|
3001
3153
|
}
|
|
3002
3154
|
|
|
@@ -3008,7 +3160,7 @@ describe('plugin-meetings', () => {
|
|
|
3008
3160
|
assert.calledOnceWithExactly(meeting.sendSlotManager.getSlot(MediaType.AudioMain).publishStream, fakeMicrophoneStream2);
|
|
3009
3161
|
} else {
|
|
3010
3162
|
assert.calledOnceWithExactly(fakeRoapMediaConnection.update, {
|
|
3011
|
-
localTracks: { audio: fakeMicrophoneStream2.
|
|
3163
|
+
localTracks: { audio: fakeMicrophoneStream2.outputStream.getTracks()[0], video: null, screenShareVideo: null, screenShareAudio: null },
|
|
3012
3164
|
direction: {
|
|
3013
3165
|
audio: expected.direction,
|
|
3014
3166
|
video: 'sendrecv',
|
|
@@ -3079,7 +3231,7 @@ describe('plugin-meetings', () => {
|
|
|
3079
3231
|
assert.equal(meeting.sendSlotManager.getSlot(MediaType.AudioMain).active, expectedDirection !== 'inactive');
|
|
3080
3232
|
} else {
|
|
3081
3233
|
assert.calledOnceWithExactly(fakeRoapMediaConnection.update, {
|
|
3082
|
-
localTracks: { audio: expectedStream?.
|
|
3234
|
+
localTracks: { audio: expectedStream?.outputStream.getTracks()[0] ?? null, video: null, screenShareVideo: null, screenShareAudio: null },
|
|
3083
3235
|
direction: {
|
|
3084
3236
|
audio: expectedDirection,
|
|
3085
3237
|
video: 'sendrecv',
|
|
@@ -3529,7 +3681,11 @@ describe('plugin-meetings', () => {
|
|
|
3529
3681
|
let sandbox;
|
|
3530
3682
|
|
|
3531
3683
|
const createFakeLocalStream = () => ({
|
|
3532
|
-
|
|
3684
|
+
outputStream: {
|
|
3685
|
+
getTracks: () => {
|
|
3686
|
+
return [{id: 'fake underlying track'}];
|
|
3687
|
+
}
|
|
3688
|
+
}
|
|
3533
3689
|
});
|
|
3534
3690
|
beforeEach(() => {
|
|
3535
3691
|
sandbox = sinon.createSandbox();
|
|
@@ -3612,10 +3768,10 @@ describe('plugin-meetings', () => {
|
|
|
3612
3768
|
meeting.mediaProperties.webrtcMediaConnection.update,
|
|
3613
3769
|
{
|
|
3614
3770
|
localTracks: {
|
|
3615
|
-
audio: meeting.mediaProperties.audioStream.
|
|
3616
|
-
video: meeting.mediaProperties.videoStream.
|
|
3617
|
-
screenShareVideo: meeting.mediaProperties.shareVideoStream.
|
|
3618
|
-
screenShareAudio: meeting.mediaProperties.shareVideoStream.
|
|
3771
|
+
audio: meeting.mediaProperties.audioStream.outputStream.getTracks()[0],
|
|
3772
|
+
video: meeting.mediaProperties.videoStream.outputStream.getTracks()[0],
|
|
3773
|
+
screenShareVideo: meeting.mediaProperties.shareVideoStream.outputStream.getTracks()[0],
|
|
3774
|
+
screenShareAudio: meeting.mediaProperties.shareVideoStream.outputStream.getTracks()[0],
|
|
3619
3775
|
},
|
|
3620
3776
|
direction: {
|
|
3621
3777
|
audio: 'inactive',
|
|
@@ -3644,7 +3800,13 @@ describe('plugin-meetings', () => {
|
|
|
3644
3800
|
meeting.mediaProperties.mediaDirection = mediaDirection;
|
|
3645
3801
|
meeting.mediaProperties.remoteVideoStream = sinon
|
|
3646
3802
|
.stub()
|
|
3647
|
-
.returns({
|
|
3803
|
+
.returns({
|
|
3804
|
+
outputStream: {
|
|
3805
|
+
getTracks: () => {
|
|
3806
|
+
id: 'some mock id'
|
|
3807
|
+
}
|
|
3808
|
+
}
|
|
3809
|
+
});
|
|
3648
3810
|
|
|
3649
3811
|
meeting.meetingRequest.changeVideoLayoutDebounced = sinon
|
|
3650
3812
|
.stub()
|
|
@@ -4469,7 +4631,7 @@ describe('plugin-meetings', () => {
|
|
|
4469
4631
|
};
|
|
4470
4632
|
const FAKE_MEETING_INFO_LOOKUP_URL = 'meetingLookupUrl';
|
|
4471
4633
|
const FAKE_PERMISSION_TOKEN = {someField: 'some value'};
|
|
4472
|
-
const
|
|
4634
|
+
const FAKE_TIMESTAMPS = {timeLeft: 13, expiryTime: 123456, currentTime: 123478};
|
|
4473
4635
|
|
|
4474
4636
|
beforeEach(() => {
|
|
4475
4637
|
meeting.locusId = 'locus-id';
|
|
@@ -4479,7 +4641,7 @@ describe('plugin-meetings', () => {
|
|
|
4479
4641
|
meeting.destination = 'meeting-destination';
|
|
4480
4642
|
meeting.destinationType = 'meeting-destination-type';
|
|
4481
4643
|
meeting.updateMeetingActions = sinon.stub().returns(undefined);
|
|
4482
|
-
|
|
4644
|
+
|
|
4483
4645
|
meeting.meetingInfoExtraParams = {
|
|
4484
4646
|
extraParam1: 'value1'
|
|
4485
4647
|
};
|
|
@@ -4500,6 +4662,50 @@ describe('plugin-meetings', () => {
|
|
|
4500
4662
|
});
|
|
4501
4663
|
|
|
4502
4664
|
it('calls meetingInfoProvider.fetchMeetingInfo() with the right params', async () => {
|
|
4665
|
+
meeting.getPermissionTokenExpiryInfo = sinon.stub().returns(FAKE_TIMESTAMPS);
|
|
4666
|
+
await meeting.refreshPermissionToken('fake reason');
|
|
4667
|
+
|
|
4668
|
+
assert.calledOnceWithExactly(
|
|
4669
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
4670
|
+
'meeting-destination',
|
|
4671
|
+
'meeting-destination-type',
|
|
4672
|
+
null,
|
|
4673
|
+
null,
|
|
4674
|
+
'fake-installed-org-id',
|
|
4675
|
+
'locus-id',
|
|
4676
|
+
{extraParam1: 'value1', permissionToken: FAKE_PERMISSION_TOKEN},
|
|
4677
|
+
{meetingId: meeting.id, sendCAevents: true}
|
|
4678
|
+
);
|
|
4679
|
+
assert.deepEqual(meeting.meetingInfo, {
|
|
4680
|
+
...FAKE_MEETING_INFO,
|
|
4681
|
+
meetingLookupUrl: FAKE_MEETING_INFO_LOOKUP_URL
|
|
4682
|
+
});
|
|
4683
|
+
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.NONE);
|
|
4684
|
+
assert.equal(meeting.requiredCaptcha, null);
|
|
4685
|
+
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.NOT_REQUIRED);
|
|
4686
|
+
|
|
4687
|
+
assert.calledWith(
|
|
4688
|
+
TriggerProxy.trigger,
|
|
4689
|
+
meeting,
|
|
4690
|
+
{file: 'meetings', function: 'fetchMeetingInfo'},
|
|
4691
|
+
'meeting:meetingInfoAvailable'
|
|
4692
|
+
);
|
|
4693
|
+
assert.calledWith(meeting.updateMeetingActions);
|
|
4694
|
+
|
|
4695
|
+
assert.calledWith(
|
|
4696
|
+
Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH, {
|
|
4697
|
+
correlationId: meeting.correlationId,
|
|
4698
|
+
timeLeft: FAKE_TIMESTAMPS.timeLeft,
|
|
4699
|
+
expiryTime: FAKE_TIMESTAMPS.expiryTime,
|
|
4700
|
+
currentTime: FAKE_TIMESTAMPS.currentTime,
|
|
4701
|
+
reason: 'fake reason',
|
|
4702
|
+
destinationType: 'meeting-destination-type',
|
|
4703
|
+
}
|
|
4704
|
+
);
|
|
4705
|
+
});
|
|
4706
|
+
|
|
4707
|
+
it('calls meetingInfoProvider.fetchMeetingInfo() with the right params when getPermissionTokenExpiryInfo returns undefined', async () => {
|
|
4708
|
+
meeting.getPermissionTokenExpiryInfo = sinon.stub().returns(undefined);
|
|
4503
4709
|
await meeting.refreshPermissionToken('fake reason');
|
|
4504
4710
|
|
|
4505
4711
|
assert.calledOnceWithExactly(
|
|
@@ -4532,7 +4738,9 @@ describe('plugin-meetings', () => {
|
|
|
4532
4738
|
assert.calledWith(
|
|
4533
4739
|
Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH, {
|
|
4534
4740
|
correlationId: meeting.correlationId,
|
|
4535
|
-
timeLeft:
|
|
4741
|
+
timeLeft: undefined,
|
|
4742
|
+
expiryTime: undefined,
|
|
4743
|
+
currentTime: undefined,
|
|
4536
4744
|
reason: 'fake reason',
|
|
4537
4745
|
destinationType: 'meeting-destination-type',
|
|
4538
4746
|
}
|
|
@@ -4540,6 +4748,7 @@ describe('plugin-meetings', () => {
|
|
|
4540
4748
|
});
|
|
4541
4749
|
|
|
4542
4750
|
it('calls meetingInfoProvider.fetchMeetingInfo() with the right params when we are starting an instant space meeting', async () => {
|
|
4751
|
+
meeting.getPermissionTokenExpiryInfo = sinon.stub().returns(FAKE_TIMESTAMPS);
|
|
4543
4752
|
meeting.destination = 'some-convo-url';
|
|
4544
4753
|
meeting.destinationType = 'CONVERSATION_URL';
|
|
4545
4754
|
meeting.config.experimental = {enableAdhocMeetings: true};
|
|
@@ -4581,7 +4790,9 @@ describe('plugin-meetings', () => {
|
|
|
4581
4790
|
assert.calledWith(
|
|
4582
4791
|
Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH, {
|
|
4583
4792
|
correlationId: meeting.correlationId,
|
|
4584
|
-
timeLeft:
|
|
4793
|
+
timeLeft: FAKE_TIMESTAMPS.timeLeft,
|
|
4794
|
+
expiryTime: FAKE_TIMESTAMPS.expiryTime,
|
|
4795
|
+
currentTime: FAKE_TIMESTAMPS.currentTime,
|
|
4585
4796
|
reason: 'some reason',
|
|
4586
4797
|
destinationType: 'MEETING_LINK',
|
|
4587
4798
|
}
|
|
@@ -5074,6 +5285,31 @@ describe('plugin-meetings', () => {
|
|
|
5074
5285
|
}
|
|
5075
5286
|
});
|
|
5076
5287
|
});
|
|
5288
|
+
|
|
5289
|
+
describe('#setCorrelationId', () => {
|
|
5290
|
+
it('should set the correlationId and return undefined', () => {
|
|
5291
|
+
assert.equal(meeting.correlationId, correlationId);
|
|
5292
|
+
assert.deepEqual(meeting.callStateForMetrics, {correlationId});
|
|
5293
|
+
meeting.setCorrelationId(uuid1);
|
|
5294
|
+
assert.equal(meeting.correlationId, uuid1);
|
|
5295
|
+
assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1});
|
|
5296
|
+
});
|
|
5297
|
+
});
|
|
5298
|
+
|
|
5299
|
+
describe('#updateCallStateForMetrics', () => {
|
|
5300
|
+
it('should update the callState, overriding existing values', () => {
|
|
5301
|
+
assert.deepEqual(meeting.callStateForMetrics, {correlationId});
|
|
5302
|
+
meeting.updateCallStateForMetrics({correlationId: uuid1, joinTrigger: 'jt', loginType: 'lt'});
|
|
5303
|
+
assert.deepEqual(meeting.callStateForMetrics, {correlationId: uuid1, joinTrigger: 'jt', loginType: 'lt'});
|
|
5304
|
+
});
|
|
5305
|
+
|
|
5306
|
+
it('should update the callState, keeping non-supplied values', () => {
|
|
5307
|
+
assert.deepEqual(meeting.callStateForMetrics, {correlationId});
|
|
5308
|
+
meeting.updateCallStateForMetrics({joinTrigger: 'jt', loginType: 'lt'});
|
|
5309
|
+
assert.deepEqual(meeting.callStateForMetrics, {correlationId, joinTrigger: 'jt', loginType: 'lt'});
|
|
5310
|
+
});
|
|
5311
|
+
});
|
|
5312
|
+
|
|
5077
5313
|
describe('Local tracks publishing', () => {
|
|
5078
5314
|
let audioStream;
|
|
5079
5315
|
let videoStream;
|
|
@@ -5436,31 +5672,72 @@ describe('plugin-meetings', () => {
|
|
|
5436
5672
|
it('should have #reconnect', () => {
|
|
5437
5673
|
assert.exists(meeting.reconnect);
|
|
5438
5674
|
});
|
|
5675
|
+
|
|
5439
5676
|
describe('successful reconnect', () => {
|
|
5677
|
+
let eventListeners;
|
|
5678
|
+
|
|
5440
5679
|
beforeEach(() => {
|
|
5680
|
+
eventListeners = {};
|
|
5681
|
+
meeting.mediaProperties.webrtcMediaConnection = {
|
|
5682
|
+
// mock the on() method and store all the listeners
|
|
5683
|
+
on: sinon.stub().callsFake((event, listener) => {
|
|
5684
|
+
eventListeners[event] = listener;
|
|
5685
|
+
}),
|
|
5686
|
+
};
|
|
5687
|
+
meeting.setupMediaConnectionListeners();
|
|
5688
|
+
meeting.deferSDPAnswer = {
|
|
5689
|
+
resolve: sinon.stub(),
|
|
5690
|
+
reject: sinon.stub(),
|
|
5691
|
+
};
|
|
5692
|
+
meeting.sdpResponseTimer = '1234';
|
|
5693
|
+
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
|
|
5694
|
+
|
|
5695
|
+
eventListeners[Event.REMOTE_SDP_ANSWER_PROCESSED]();
|
|
5441
5696
|
meeting.config.reconnection.enabled = true;
|
|
5442
5697
|
meeting.currentMediaStatus = {audio: true};
|
|
5443
5698
|
meeting.reconnectionManager = new ReconnectionManager(meeting);
|
|
5444
5699
|
meeting.reconnectionManager.reconnect = sinon.stub().returns(Promise.resolve());
|
|
5445
5700
|
meeting.reconnectionManager.reset = sinon.stub().returns(true);
|
|
5446
5701
|
meeting.reconnectionManager.cleanup = sinon.stub().returns(true);
|
|
5702
|
+
meeting.reconnectionManager.setStatus = sinon.stub();
|
|
5447
5703
|
});
|
|
5448
5704
|
|
|
5449
|
-
it('should throw error if media not established before trying
|
|
5705
|
+
it('should throw error if media not established before trying reconnect', async () => {
|
|
5450
5706
|
meeting.currentMediaStatus = null;
|
|
5451
5707
|
await meeting.reconnect().catch((err) => {
|
|
5452
5708
|
assert.instanceOf(err, ParameterError);
|
|
5453
5709
|
});
|
|
5454
5710
|
});
|
|
5455
5711
|
|
|
5456
|
-
it('should
|
|
5712
|
+
it('should reconnect successfully if reconnectionManager.cleanUp is called before reconnection attempt', async () => {
|
|
5713
|
+
meeting.reconnectionManager.cleanUp();
|
|
5714
|
+
|
|
5715
|
+
try {
|
|
5716
|
+
await meeting.reconnect();
|
|
5717
|
+
} catch (err) {
|
|
5718
|
+
assert.fail('reconnect should not error after clean up');
|
|
5719
|
+
}
|
|
5720
|
+
})
|
|
5721
|
+
|
|
5722
|
+
it('should trigger reconnection success and send CA metric', async () => {
|
|
5457
5723
|
await meeting.reconnect();
|
|
5724
|
+
|
|
5458
5725
|
assert.calledWith(
|
|
5459
5726
|
TriggerProxy.trigger,
|
|
5460
5727
|
sinon.match.instanceOf(Meeting),
|
|
5461
5728
|
{file: 'meeting/index', function: 'reconnect'},
|
|
5462
5729
|
'meeting:reconnectionSuccess'
|
|
5463
5730
|
);
|
|
5731
|
+
assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
|
|
5732
|
+
name: 'client.media.recovered',
|
|
5733
|
+
payload: {
|
|
5734
|
+
recoveredBy: 'new',
|
|
5735
|
+
},
|
|
5736
|
+
options: {
|
|
5737
|
+
meetingId: meeting.id,
|
|
5738
|
+
},
|
|
5739
|
+
});
|
|
5740
|
+
assert.calledOnceWithExactly(meeting.reconnectionManager.setStatus, RECONNECTION.STATE.COMPLETE);
|
|
5464
5741
|
});
|
|
5465
5742
|
|
|
5466
5743
|
it('should reset after reconnection success', async () => {
|
|
@@ -5527,7 +5804,7 @@ describe('plugin-meetings', () => {
|
|
|
5527
5804
|
it('should stop remote tracks, and trigger a media:stopped event when the remote tracks are stopped', async () => {
|
|
5528
5805
|
await meeting.closeRemoteStreams();
|
|
5529
5806
|
|
|
5530
|
-
assert.equal(TriggerProxy.trigger.callCount,
|
|
5807
|
+
assert.equal(TriggerProxy.trigger.callCount, 5);
|
|
5531
5808
|
assert.calledWith(
|
|
5532
5809
|
TriggerProxy.trigger,
|
|
5533
5810
|
sinon.match.instanceOf(Meeting),
|
|
@@ -5613,37 +5890,42 @@ describe('plugin-meetings', () => {
|
|
|
5613
5890
|
});
|
|
5614
5891
|
});
|
|
5615
5892
|
|
|
5616
|
-
describe('
|
|
5617
|
-
it('sends client.ice.
|
|
5618
|
-
|
|
5619
|
-
const getErrorPayloadForClientErrorCodeStub = webex.internal.newMetrics.callDiagnosticMetrics.getErrorPayloadForClientErrorCode = sinon
|
|
5620
|
-
.stub()
|
|
5621
|
-
.returns(FAKE_ERROR);
|
|
5893
|
+
describe('CONNECTION_STATE_CHANGED event when state = "Connecting"', () => {
|
|
5894
|
+
it('sends client.ice.start correctly when hasMediaConnectionConnectedAtLeastOnce = true', () => {
|
|
5895
|
+
meeting.hasMediaConnectionConnectedAtLeastOnce = true;
|
|
5622
5896
|
meeting.setupMediaConnectionListeners();
|
|
5623
5897
|
eventListeners[Event.CONNECTION_STATE_CHANGED]({
|
|
5624
|
-
state: '
|
|
5898
|
+
state: 'Connecting',
|
|
5899
|
+
});
|
|
5900
|
+
|
|
5901
|
+
assert.notCalled(webex.internal.newMetrics.submitClientEvent);
|
|
5902
|
+
})
|
|
5903
|
+
|
|
5904
|
+
it('sends client.ice.start correctly when hasMediaConnectionConnectedAtLeastOnce = false', () => {
|
|
5905
|
+
meeting.hasMediaConnectionConnectedAtLeastOnce = false;
|
|
5906
|
+
meeting.setupMediaConnectionListeners();
|
|
5907
|
+
eventListeners[Event.CONNECTION_STATE_CHANGED]({
|
|
5908
|
+
state: 'Connecting',
|
|
5625
5909
|
});
|
|
5626
|
-
|
|
5910
|
+
|
|
5627
5911
|
assert.calledOnce(webex.internal.newMetrics.submitClientEvent);
|
|
5628
5912
|
assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
|
|
5629
|
-
name: 'client.ice.
|
|
5630
|
-
payload: {
|
|
5631
|
-
canProceed: false,
|
|
5632
|
-
icePhase: 'IN_MEETING',
|
|
5633
|
-
errors: [FAKE_ERROR],
|
|
5634
|
-
},
|
|
5913
|
+
name: 'client.ice.start',
|
|
5635
5914
|
options: {
|
|
5636
5915
|
meetingId: meeting.id,
|
|
5637
5916
|
},
|
|
5638
5917
|
});
|
|
5639
|
-
})
|
|
5918
|
+
})
|
|
5640
5919
|
});
|
|
5641
5920
|
|
|
5642
5921
|
describe('submitClientEvent on connectionSuccess', () => {
|
|
5643
|
-
|
|
5922
|
+
let setNetworkStatusSpy;
|
|
5923
|
+
|
|
5924
|
+
const setupSpies = () => {
|
|
5925
|
+
setNetworkStatusSpy = sinon.spy(meeting, 'setNetworkStatus');
|
|
5926
|
+
|
|
5644
5927
|
meeting.reconnectionManager = new ReconnectionManager(meeting);
|
|
5645
5928
|
meeting.reconnectionManager.iceReconnected = sinon.stub().returns(undefined);
|
|
5646
|
-
meeting.setNetworkStatus = sinon.stub().returns(undefined);
|
|
5647
5929
|
meeting.statsAnalyzer = {startAnalyzer: sinon.stub()};
|
|
5648
5930
|
meeting.mediaProperties.webrtcMediaConnection = {
|
|
5649
5931
|
// mock the on() method and store all the listeners
|
|
@@ -5651,45 +5933,234 @@ describe('plugin-meetings', () => {
|
|
|
5651
5933
|
eventListeners[event] = listener;
|
|
5652
5934
|
}),
|
|
5653
5935
|
};
|
|
5936
|
+
};
|
|
5654
5937
|
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5938
|
+
const checkExpectedSpies = (expected) => {
|
|
5939
|
+
if (expected.icePhase) {
|
|
5940
|
+
assert.calledOnce(webex.internal.newMetrics.submitClientEvent);
|
|
5941
|
+
assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
|
|
5942
|
+
name: 'client.ice.end',
|
|
5943
|
+
options: {
|
|
5944
|
+
meetingId: meeting.id,
|
|
5945
|
+
},
|
|
5946
|
+
payload: {
|
|
5947
|
+
canProceed: true,
|
|
5948
|
+
icePhase: expected.icePhase,
|
|
5949
|
+
},
|
|
5950
|
+
});
|
|
5951
|
+
} else {
|
|
5952
|
+
assert.notCalled(webex.internal.newMetrics.submitClientEvent);
|
|
5953
|
+
}
|
|
5666
5954
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
5667
5955
|
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.CONNECTION_SUCCESS, {
|
|
5668
5956
|
correlation_id: meeting.correlationId,
|
|
5669
5957
|
locus_id: meeting.locusId,
|
|
5670
5958
|
latency: undefined,
|
|
5671
5959
|
});
|
|
5672
|
-
assert.
|
|
5673
|
-
|
|
5960
|
+
assert.deepEqual(
|
|
5961
|
+
setNetworkStatusSpy.getCalls().map((call) => call.args[0]),
|
|
5962
|
+
expected.setNetworkStatusCallParams
|
|
5963
|
+
);
|
|
5674
5964
|
assert.calledOnce(meeting.reconnectionManager.iceReconnected);
|
|
5675
5965
|
assert.calledOnce(meeting.statsAnalyzer.startAnalyzer);
|
|
5676
5966
|
assert.calledWith(
|
|
5677
5967
|
meeting.statsAnalyzer.startAnalyzer,
|
|
5678
5968
|
meeting.mediaProperties.webrtcMediaConnection
|
|
5679
5969
|
);
|
|
5680
|
-
}
|
|
5681
|
-
});
|
|
5970
|
+
};
|
|
5682
5971
|
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5972
|
+
const resetSpies = () => {
|
|
5973
|
+
setNetworkStatusSpy.resetHistory();
|
|
5974
|
+
webex.internal.newMetrics.submitClientEvent.resetHistory();
|
|
5975
|
+
Metrics.sendBehavioralMetric.resetHistory();
|
|
5976
|
+
meeting.reconnectionManager.iceReconnected.resetHistory();
|
|
5977
|
+
meeting.statsAnalyzer.startAnalyzer.resetHistory();
|
|
5978
|
+
};
|
|
5979
|
+
|
|
5980
|
+
it('sends client.ice.end with the correct icePhase when we get ConnectionState.Connected on CONNECTION_STATE_CHANGED event', () => {
|
|
5981
|
+
setupSpies();
|
|
5687
5982
|
|
|
5688
|
-
beforeEach(() => {
|
|
5689
5983
|
meeting.setupMediaConnectionListeners();
|
|
5690
|
-
});
|
|
5691
5984
|
|
|
5692
|
-
|
|
5985
|
+
assert.equal(meeting.hasMediaConnectionConnectedAtLeastOnce, false);
|
|
5986
|
+
|
|
5987
|
+
// simulate first connection success
|
|
5988
|
+
eventListeners[Event.CONNECTION_STATE_CHANGED]({
|
|
5989
|
+
state: 'Connected',
|
|
5990
|
+
});
|
|
5991
|
+
checkExpectedSpies({
|
|
5992
|
+
icePhase: 'JOIN_MEETING_FINAL',
|
|
5993
|
+
setNetworkStatusCallParams: [NETWORK_STATUS.CONNECTED],
|
|
5994
|
+
});
|
|
5995
|
+
assert.equal(meeting.hasMediaConnectionConnectedAtLeastOnce, true);
|
|
5996
|
+
|
|
5997
|
+
// now simulate short connection loss, client.ice.end is not sent a second time as hasMediaConnectionConnectedAtLeastOnce = true
|
|
5998
|
+
resetSpies();
|
|
5999
|
+
|
|
6000
|
+
eventListeners[Event.CONNECTION_STATE_CHANGED]({
|
|
6001
|
+
state: 'Disconnected',
|
|
6002
|
+
});
|
|
6003
|
+
eventListeners[Event.CONNECTION_STATE_CHANGED]({
|
|
6004
|
+
state: 'Connected',
|
|
6005
|
+
});
|
|
6006
|
+
|
|
6007
|
+
checkExpectedSpies({
|
|
6008
|
+
setNetworkStatusCallParams: [NETWORK_STATUS.DISCONNECTED, NETWORK_STATUS.CONNECTED],
|
|
6009
|
+
});
|
|
6010
|
+
|
|
6011
|
+
resetSpies();
|
|
6012
|
+
|
|
6013
|
+
eventListeners[Event.CONNECTION_STATE_CHANGED]({
|
|
6014
|
+
state: 'Disconnected',
|
|
6015
|
+
});
|
|
6016
|
+
eventListeners[Event.CONNECTION_STATE_CHANGED]({
|
|
6017
|
+
state: 'Connected',
|
|
6018
|
+
});
|
|
6019
|
+
});
|
|
6020
|
+
});
|
|
6021
|
+
|
|
6022
|
+
describe('CONNECTION_STATE_CHANGED event when state = "Disconnected"', () => {
|
|
6023
|
+
beforeEach(() => {
|
|
6024
|
+
meeting.reconnectionManager = new ReconnectionManager(meeting);
|
|
6025
|
+
meeting.reconnectionManager.iceReconnected = sinon.stub().returns(undefined);
|
|
6026
|
+
meeting.setNetworkStatus = sinon.stub().returns(undefined);
|
|
6027
|
+
meeting.statsAnalyzer = {startAnalyzer: sinon.stub()};
|
|
6028
|
+
meeting.mediaProperties.webrtcMediaConnection = {
|
|
6029
|
+
// mock the on() method and store all the listeners
|
|
6030
|
+
on: sinon.stub().callsFake((event, listener) => {
|
|
6031
|
+
eventListeners[event] = listener;
|
|
6032
|
+
}),
|
|
6033
|
+
};
|
|
6034
|
+
meeting.reconnect = sinon.stub().resolves();
|
|
6035
|
+
});
|
|
6036
|
+
|
|
6037
|
+
const mockDisconnectedEvent = () => {
|
|
6038
|
+
meeting.setupMediaConnectionListeners();
|
|
6039
|
+
eventListeners[Event.CONNECTION_STATE_CHANGED]({
|
|
6040
|
+
state: 'Disconnected',
|
|
6041
|
+
});
|
|
6042
|
+
};
|
|
6043
|
+
|
|
6044
|
+
const checkBehavioralMetricSent = (hasMediaConnectionConnectedAtLeastOnce = false) => {
|
|
6045
|
+
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
6046
|
+
assert.calledWith(
|
|
6047
|
+
Metrics.sendBehavioralMetric,
|
|
6048
|
+
BEHAVIORAL_METRICS.CONNECTION_FAILURE,
|
|
6049
|
+
{
|
|
6050
|
+
correlation_id: meeting.correlationId,
|
|
6051
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
6052
|
+
networkStatus: meeting.networkStatus,
|
|
6053
|
+
hasMediaConnectionConnectedAtLeastOnce,
|
|
6054
|
+
},
|
|
6055
|
+
);
|
|
6056
|
+
};
|
|
6057
|
+
|
|
6058
|
+
it('handles "Disconnected" state correctly when waitForIceReconnect resolves', async () => {
|
|
6059
|
+
meeting.reconnectionManager.waitForIceReconnect = sinon.stub().resolves();
|
|
6060
|
+
|
|
6061
|
+
|
|
6062
|
+
mockDisconnectedEvent();
|
|
6063
|
+
|
|
6064
|
+
await testUtils.flushPromises();
|
|
6065
|
+
|
|
6066
|
+
assert.calledOnce(meeting.setNetworkStatus);
|
|
6067
|
+
assert.calledWith(meeting.setNetworkStatus, NETWORK_STATUS.DISCONNECTED);
|
|
6068
|
+
assert.calledOnce(meeting.reconnectionManager.waitForIceReconnect);
|
|
6069
|
+
assert.notCalled(webex.internal.newMetrics.submitClientEvent);
|
|
6070
|
+
assert.notCalled(Metrics.sendBehavioralMetric);
|
|
6071
|
+
});
|
|
6072
|
+
|
|
6073
|
+
it('handles "Disconnected" state correctly when waitForIceReconnect rejects and hasMediaConnectionConnectedAtLeastOnce = true', async () => {
|
|
6074
|
+
const FAKE_ERROR = {fatal: true};
|
|
6075
|
+
const getErrorPayloadForClientErrorCodeStub = webex.internal.newMetrics.callDiagnosticMetrics.getErrorPayloadForClientErrorCode = sinon
|
|
6076
|
+
.stub()
|
|
6077
|
+
.returns(FAKE_ERROR);
|
|
6078
|
+
meeting.waitForMediaConnectionConnected = sinon.stub().resolves();
|
|
6079
|
+
meeting.reconnectionManager.waitForIceReconnect = sinon.stub().rejects();
|
|
6080
|
+
meeting.hasMediaConnectionConnectedAtLeastOnce = true;
|
|
6081
|
+
|
|
6082
|
+
|
|
6083
|
+
mockDisconnectedEvent();
|
|
6084
|
+
|
|
6085
|
+
await testUtils.flushPromises();
|
|
6086
|
+
|
|
6087
|
+
assert.calledOnce(meeting.setNetworkStatus);
|
|
6088
|
+
assert.calledWith(meeting.setNetworkStatus, NETWORK_STATUS.DISCONNECTED);
|
|
6089
|
+
assert.calledOnce(meeting.reconnectionManager.waitForIceReconnect);
|
|
6090
|
+
assert.notCalled(webex.internal.newMetrics.submitClientEvent);
|
|
6091
|
+
checkBehavioralMetricSent(true);
|
|
6092
|
+
});
|
|
6093
|
+
|
|
6094
|
+
it('handles "Disconnected" state correctly when waitForIceReconnect rejects and hasMediaConnectionConnectedAtLeastOnce = false', async () => {
|
|
6095
|
+
meeting.reconnectionManager.waitForIceReconnect = sinon.stub().rejects();
|
|
6096
|
+
|
|
6097
|
+
|
|
6098
|
+
mockDisconnectedEvent();
|
|
6099
|
+
|
|
6100
|
+
await testUtils.flushPromises();
|
|
6101
|
+
|
|
6102
|
+
assert.calledOnce(meeting.setNetworkStatus);
|
|
6103
|
+
assert.calledWith(meeting.setNetworkStatus, NETWORK_STATUS.DISCONNECTED);
|
|
6104
|
+
assert.calledOnce(meeting.reconnectionManager.waitForIceReconnect);
|
|
6105
|
+
assert.notCalled(webex.internal.newMetrics.submitClientEvent);
|
|
6106
|
+
checkBehavioralMetricSent();
|
|
6107
|
+
});
|
|
6108
|
+
});
|
|
6109
|
+
|
|
6110
|
+
describe('CONNECTION_STATE_CHANGED event when state = "Failed"', () => {
|
|
6111
|
+
|
|
6112
|
+
const mockFailedEvent = () => {
|
|
6113
|
+
meeting.setupMediaConnectionListeners();
|
|
6114
|
+
eventListeners[Event.CONNECTION_STATE_CHANGED]({
|
|
6115
|
+
state: 'Failed',
|
|
6116
|
+
});
|
|
6117
|
+
};
|
|
6118
|
+
|
|
6119
|
+
const checkBehavioralMetricSent = (hasMediaConnectionConnectedAtLeastOnce = false) => {
|
|
6120
|
+
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
6121
|
+
assert.calledWith(
|
|
6122
|
+
Metrics.sendBehavioralMetric,
|
|
6123
|
+
BEHAVIORAL_METRICS.CONNECTION_FAILURE,
|
|
6124
|
+
{
|
|
6125
|
+
correlation_id: meeting.correlationId,
|
|
6126
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
6127
|
+
networkStatus: meeting.networkStatus,
|
|
6128
|
+
hasMediaConnectionConnectedAtLeastOnce,
|
|
6129
|
+
},
|
|
6130
|
+
);
|
|
6131
|
+
};
|
|
6132
|
+
|
|
6133
|
+
it('handles "Failed" state correctly when hasMediaConnectionConnectedAtLeastOnce = false', async () => {
|
|
6134
|
+
meeting.waitForMediaConnectionConnected = sinon.stub().resolves();
|
|
6135
|
+
|
|
6136
|
+
mockFailedEvent();
|
|
6137
|
+
|
|
6138
|
+
assert.notCalled(webex.internal.newMetrics.submitClientEvent);
|
|
6139
|
+
checkBehavioralMetricSent();
|
|
6140
|
+
});
|
|
6141
|
+
|
|
6142
|
+
it('handles "Failed" state correctly when hasMediaConnectionConnectedAtLeastOnce = true', async () => {
|
|
6143
|
+
meeting.hasMediaConnectionConnectedAtLeastOnce = true;
|
|
6144
|
+
|
|
6145
|
+
mockFailedEvent();
|
|
6146
|
+
|
|
6147
|
+
assert.notCalled(webex.internal.newMetrics.submitClientEvent);
|
|
6148
|
+
checkBehavioralMetricSent(true);
|
|
6149
|
+
});
|
|
6150
|
+
});
|
|
6151
|
+
|
|
6152
|
+
describe('should send correct metrics for ROAP_FAILURE event', () => {
|
|
6153
|
+
const fakeErrorMessage = 'test error';
|
|
6154
|
+
const fakeRootCauseName = 'root cause name';
|
|
6155
|
+
const fakeErrorName = 'test error name';
|
|
6156
|
+
|
|
6157
|
+
beforeEach(() => {
|
|
6158
|
+
meeting.setupMediaConnectionListeners();
|
|
6159
|
+
webex.internal.newMetrics.submitClientEvent.resetHistory();
|
|
6160
|
+
Metrics.sendBehavioralMetric.resetHistory();
|
|
6161
|
+
});
|
|
6162
|
+
|
|
6163
|
+
const checkMetricSent = (event, error) => {
|
|
5693
6164
|
assert.calledOnce(webex.internal.newMetrics.submitClientEvent);
|
|
5694
6165
|
assert.calledWithMatch(webex.internal.newMetrics.submitClientEvent, {
|
|
5695
6166
|
name: event,
|
|
@@ -6732,6 +7203,7 @@ describe('plugin-meetings', () => {
|
|
|
6732
7203
|
done();
|
|
6733
7204
|
});
|
|
6734
7205
|
});
|
|
7206
|
+
|
|
6735
7207
|
describe('#setUpLocusInfoMediaInactiveListener', () => {
|
|
6736
7208
|
it('listens to disconnect due to un activity ', (done) => {
|
|
6737
7209
|
TriggerProxy.trigger.reset();
|
|
@@ -6901,6 +7373,20 @@ describe('plugin-meetings', () => {
|
|
|
6901
7373
|
});
|
|
6902
7374
|
|
|
6903
7375
|
describe('#setPermissionTokenPayload', () => {
|
|
7376
|
+
|
|
7377
|
+
let now;
|
|
7378
|
+
let clock;
|
|
7379
|
+
|
|
7380
|
+
beforeEach(() => {
|
|
7381
|
+
now = Date.now();
|
|
7382
|
+
|
|
7383
|
+
// mock `new Date()` with constant `now`
|
|
7384
|
+
clock = sinon.useFakeTimers(now);
|
|
7385
|
+
});
|
|
7386
|
+
|
|
7387
|
+
afterEach(() => {
|
|
7388
|
+
clock.restore();
|
|
7389
|
+
})
|
|
6904
7390
|
it('sets correctly', () => {
|
|
6905
7391
|
assert.notOk(meeting.permissionTokenPayload);
|
|
6906
7392
|
|
|
@@ -6912,6 +7398,7 @@ describe('plugin-meetings', () => {
|
|
|
6912
7398
|
|
|
6913
7399
|
assert.calledOnce(jwtDecodeStub);
|
|
6914
7400
|
assert.deepEqual(meeting.permissionTokenPayload, permissionTokenPayloadData);
|
|
7401
|
+
assert.deepEqual(meeting.permissionTokenReceivedLocalTime, now);
|
|
6915
7402
|
});
|
|
6916
7403
|
});
|
|
6917
7404
|
|
|
@@ -6919,12 +7406,18 @@ describe('plugin-meetings', () => {
|
|
|
6919
7406
|
it('sets correctly when policy data is present in token', () => {
|
|
6920
7407
|
assert.notOk(meeting.selfUserPolicies);
|
|
6921
7408
|
|
|
6922
|
-
const
|
|
7409
|
+
const testUrl = 'https://example.com';
|
|
7410
|
+
|
|
7411
|
+
const policyData = {permission: {
|
|
7412
|
+
userPolicies: {a: true},
|
|
7413
|
+
enforceVBGImagesURL: testUrl
|
|
7414
|
+
}};
|
|
6923
7415
|
meeting.permissionTokenPayload = policyData;
|
|
6924
7416
|
|
|
6925
7417
|
meeting.setSelfUserPolicies();
|
|
6926
7418
|
|
|
6927
7419
|
assert.deepEqual(meeting.selfUserPolicies, policyData.permission.userPolicies);
|
|
7420
|
+
assert.equal(meeting.enforceVBGImagesURL, testUrl);
|
|
6928
7421
|
});
|
|
6929
7422
|
|
|
6930
7423
|
it('handles missing permission data', () => {
|
|
@@ -6977,12 +7470,14 @@ describe('plugin-meetings', () => {
|
|
|
6977
7470
|
});
|
|
6978
7471
|
describe('#closePeerConnections', () => {
|
|
6979
7472
|
it('should close the webrtc media connection, and return a promise', async () => {
|
|
7473
|
+
const setNetworkStatusSpy = sinon.spy(meeting, 'setNetworkStatus');
|
|
6980
7474
|
meeting.mediaProperties.webrtcMediaConnection = {close: sinon.stub()};
|
|
6981
7475
|
const pcs = meeting.closePeerConnections();
|
|
6982
7476
|
|
|
6983
7477
|
assert.exists(pcs.then);
|
|
6984
7478
|
await pcs;
|
|
6985
7479
|
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.close);
|
|
7480
|
+
assert.calledOnceWithExactly(setNetworkStatusSpy, undefined);
|
|
6986
7481
|
});
|
|
6987
7482
|
});
|
|
6988
7483
|
describe('#unsetPeerConnections', () => {
|
|
@@ -7190,14 +7685,6 @@ describe('plugin-meetings', () => {
|
|
|
7190
7685
|
});
|
|
7191
7686
|
});
|
|
7192
7687
|
|
|
7193
|
-
describe('#setCorrelationId', () => {
|
|
7194
|
-
it('should set the correlationId and return undefined', () => {
|
|
7195
|
-
assert.ok(meeting.correlationId);
|
|
7196
|
-
meeting.setCorrelationId(uuid1);
|
|
7197
|
-
assert.equal(meeting.correlationId, uuid1);
|
|
7198
|
-
});
|
|
7199
|
-
});
|
|
7200
|
-
|
|
7201
7688
|
describe('#setUpLocusInfoAssignHostListener', () => {
|
|
7202
7689
|
let locusInfoOnSpy;
|
|
7203
7690
|
let inMeetingActionsSetSpy;
|
|
@@ -7246,47 +7733,12 @@ describe('plugin-meetings', () => {
|
|
|
7246
7733
|
});
|
|
7247
7734
|
|
|
7248
7735
|
describe('#setUpLocusInfoMeetingInfoListener', () => {
|
|
7249
|
-
let inMeetingActionsSetSpy;
|
|
7250
|
-
let canUserLockSpy;
|
|
7251
|
-
let canUserUnlockSpy;
|
|
7252
|
-
let canUserStartSpy;
|
|
7253
|
-
let canUserStopSpy;
|
|
7254
|
-
let canUserPauseSpy;
|
|
7255
|
-
let canUserResumeSpy;
|
|
7256
|
-
let canSetMuteOnEntrySpy;
|
|
7257
|
-
let canUnsetMuteOnEntrySpy;
|
|
7258
|
-
let canSetDisallowUnmuteSpy;
|
|
7259
|
-
let canUnsetDisallowUnmuteSpy;
|
|
7260
|
-
let canUserRaiseHandSpy;
|
|
7261
|
-
let bothLeaveAndEndMeetingAvailableSpy;
|
|
7262
|
-
let canUserLowerAllHandsSpy;
|
|
7263
|
-
let canUserLowerSomeoneElsesHandSpy;
|
|
7264
|
-
let waitingForOthersToJoinSpy;
|
|
7265
7736
|
let locusInfoOnSpy;
|
|
7266
7737
|
let handleDataChannelUrlChangeSpy;
|
|
7267
7738
|
let updateMeetingActionsSpy;
|
|
7268
7739
|
|
|
7269
7740
|
beforeEach(() => {
|
|
7270
7741
|
locusInfoOnSpy = sinon.spy(meeting.locusInfo, 'on');
|
|
7271
|
-
canUserLockSpy = sinon.spy(MeetingUtil, 'canUserLock');
|
|
7272
|
-
canUserUnlockSpy = sinon.spy(MeetingUtil, 'canUserUnlock');
|
|
7273
|
-
canUserStartSpy = sinon.spy(RecordingUtil, 'canUserStart');
|
|
7274
|
-
canUserStopSpy = sinon.spy(RecordingUtil, 'canUserStop');
|
|
7275
|
-
canUserPauseSpy = sinon.spy(RecordingUtil, 'canUserPause');
|
|
7276
|
-
canUserResumeSpy = sinon.spy(RecordingUtil, 'canUserResume');
|
|
7277
|
-
canSetMuteOnEntrySpy = sinon.spy(ControlsOptionsUtil, 'canSetMuteOnEntry');
|
|
7278
|
-
canUnsetMuteOnEntrySpy = sinon.spy(ControlsOptionsUtil, 'canUnsetMuteOnEntry');
|
|
7279
|
-
canSetDisallowUnmuteSpy = sinon.spy(ControlsOptionsUtil, 'canSetDisallowUnmute');
|
|
7280
|
-
canUnsetDisallowUnmuteSpy = sinon.spy(ControlsOptionsUtil, 'canUnsetDisallowUnmute');
|
|
7281
|
-
inMeetingActionsSetSpy = sinon.spy(meeting.inMeetingActions, 'set');
|
|
7282
|
-
canUserRaiseHandSpy = sinon.spy(MeetingUtil, 'canUserRaiseHand');
|
|
7283
|
-
canUserLowerAllHandsSpy = sinon.spy(MeetingUtil, 'canUserLowerAllHands');
|
|
7284
|
-
bothLeaveAndEndMeetingAvailableSpy = sinon.spy(
|
|
7285
|
-
MeetingUtil,
|
|
7286
|
-
'bothLeaveAndEndMeetingAvailable'
|
|
7287
|
-
);
|
|
7288
|
-
canUserLowerSomeoneElsesHandSpy = sinon.spy(MeetingUtil, 'canUserLowerSomeoneElsesHand');
|
|
7289
|
-
waitingForOthersToJoinSpy = sinon.spy(MeetingUtil, 'waitingForOthersToJoin');
|
|
7290
7742
|
handleDataChannelUrlChangeSpy = sinon.spy(meeting, 'handleDataChannelUrlChange');
|
|
7291
7743
|
updateMeetingActionsSpy = sinon.spy(meeting, 'updateMeetingActions');
|
|
7292
7744
|
});
|
|
@@ -7324,30 +7776,8 @@ describe('plugin-meetings', () => {
|
|
|
7324
7776
|
assert.equal(locusInfoOnSpy.thirdCall.args[0], 'MEETING_INFO_UPDATED');
|
|
7325
7777
|
const callback = locusInfoOnSpy.thirdCall.args[1];
|
|
7326
7778
|
|
|
7327
|
-
const payload = {
|
|
7328
|
-
info: {
|
|
7329
|
-
userDisplayHints: ['LOCK_CONTROL_UNLOCK'],
|
|
7330
|
-
},
|
|
7331
|
-
};
|
|
7332
|
-
|
|
7333
7779
|
callback();
|
|
7334
7780
|
|
|
7335
|
-
assert.calledWith(canUserLockSpy, payload.info.userDisplayHints);
|
|
7336
|
-
assert.calledWith(canUserUnlockSpy, payload.info.userDisplayHints);
|
|
7337
|
-
assert.calledWith(canUserStartSpy, payload.info.userDisplayHints);
|
|
7338
|
-
assert.calledWith(canUserStopSpy, payload.info.userDisplayHints);
|
|
7339
|
-
assert.calledWith(canUserPauseSpy, payload.info.userDisplayHints);
|
|
7340
|
-
assert.calledWith(canUserResumeSpy, payload.info.userDisplayHints);
|
|
7341
|
-
assert.calledWith(canSetMuteOnEntrySpy, payload.info.userDisplayHints);
|
|
7342
|
-
assert.calledWith(canUnsetMuteOnEntrySpy, payload.info.userDisplayHints);
|
|
7343
|
-
assert.calledWith(canSetDisallowUnmuteSpy, payload.info.userDisplayHints);
|
|
7344
|
-
assert.calledWith(canUnsetDisallowUnmuteSpy, payload.info.userDisplayHints);
|
|
7345
|
-
assert.calledWith(canUserRaiseHandSpy, payload.info.userDisplayHints);
|
|
7346
|
-
assert.calledWith(bothLeaveAndEndMeetingAvailableSpy, payload.info.userDisplayHints);
|
|
7347
|
-
assert.calledWith(canUserLowerAllHandsSpy, payload.info.userDisplayHints);
|
|
7348
|
-
assert.calledWith(canUserLowerSomeoneElsesHandSpy, payload.info.userDisplayHints);
|
|
7349
|
-
assert.calledWith(waitingForOthersToJoinSpy, payload.info.userDisplayHints);
|
|
7350
|
-
|
|
7351
7781
|
assert.calledWith(updateMeetingActionsSpy);
|
|
7352
7782
|
assert.calledWith(setRecordingDisplayHintsSpy, userDisplayHints);
|
|
7353
7783
|
assert.calledWith(setUserPolicySpy, userDisplayPolicy);
|
|
@@ -7500,6 +7930,11 @@ describe('plugin-meetings', () => {
|
|
|
7500
7930
|
requiredDisplayHints: [],
|
|
7501
7931
|
requiredPolicies: [SELF_POLICY.SUPPORT_FILE_TRANSFER],
|
|
7502
7932
|
},
|
|
7933
|
+
{
|
|
7934
|
+
actionName: 'canChat',
|
|
7935
|
+
requiredDisplayHints: [],
|
|
7936
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_CHAT],
|
|
7937
|
+
},
|
|
7503
7938
|
{
|
|
7504
7939
|
actionName: 'canShareDesktop',
|
|
7505
7940
|
requiredDisplayHints: [DISPLAY_HINTS.SHARE_DESKTOP],
|
|
@@ -7678,6 +8113,60 @@ describe('plugin-meetings', () => {
|
|
|
7678
8113
|
}
|
|
7679
8114
|
);
|
|
7680
8115
|
|
|
8116
|
+
forEach(
|
|
8117
|
+
[
|
|
8118
|
+
// policies supported and enforce is true
|
|
8119
|
+
{
|
|
8120
|
+
meetingInfo: {video: {}},
|
|
8121
|
+
selfUserPolicies: {
|
|
8122
|
+
[SELF_POLICY.ENFORCE_VIRTUAL_BACKGROUND]: true,
|
|
8123
|
+
},
|
|
8124
|
+
expectedActions: {
|
|
8125
|
+
enforceVirtualBackground: true,
|
|
8126
|
+
},
|
|
8127
|
+
},
|
|
8128
|
+
// policies supported and enforce is false
|
|
8129
|
+
{
|
|
8130
|
+
meetingInfo: {video: {}},
|
|
8131
|
+
selfUserPolicies: {
|
|
8132
|
+
[SELF_POLICY.ENFORCE_VIRTUAL_BACKGROUND]: false,
|
|
8133
|
+
},
|
|
8134
|
+
expectedActions: {
|
|
8135
|
+
enforceVirtualBackground: false,
|
|
8136
|
+
},
|
|
8137
|
+
},
|
|
8138
|
+
// policies not supported but enforce is true
|
|
8139
|
+
{
|
|
8140
|
+
meetingInfo: undefined,
|
|
8141
|
+
selfUserPolicies: {
|
|
8142
|
+
[SELF_POLICY.ENFORCE_VIRTUAL_BACKGROUND]: true,
|
|
8143
|
+
},
|
|
8144
|
+
expectedActions: {
|
|
8145
|
+
enforceVirtualBackground: false,
|
|
8146
|
+
},
|
|
8147
|
+
},
|
|
8148
|
+
],
|
|
8149
|
+
({meetingInfo, selfUserPolicies, expectedActions}) => {
|
|
8150
|
+
it(`expectedActions are ${JSON.stringify(
|
|
8151
|
+
expectedActions
|
|
8152
|
+
)} when policies are ${JSON.stringify(
|
|
8153
|
+
selfUserPolicies
|
|
8154
|
+
)} and meetingInfo is ${JSON.stringify(meetingInfo)}`, () => {
|
|
8155
|
+
meeting.meetingInfo = meetingInfo;
|
|
8156
|
+
meeting.selfUserPolicies = selfUserPolicies;
|
|
8157
|
+
|
|
8158
|
+
meeting.updateMeetingActions();
|
|
8159
|
+
|
|
8160
|
+
assert.deepEqual(
|
|
8161
|
+
{
|
|
8162
|
+
enforceVirtualBackground: meeting.inMeetingActions.enforceVirtualBackground,
|
|
8163
|
+
},
|
|
8164
|
+
expectedActions
|
|
8165
|
+
);
|
|
8166
|
+
});
|
|
8167
|
+
}
|
|
8168
|
+
);
|
|
8169
|
+
|
|
7681
8170
|
it('canUseVoip is disabled when the required policies are missing', () => {
|
|
7682
8171
|
meeting.userDisplayHints = [DISPLAY_HINTS.VOIP_IS_ENABLED];
|
|
7683
8172
|
meeting.selfUserPolicies = {};
|
|
@@ -7968,40 +8457,660 @@ describe('plugin-meetings', () => {
|
|
|
7968
8457
|
policies: selfUserPolicies,
|
|
7969
8458
|
});
|
|
7970
8459
|
|
|
7971
|
-
assert.calledWith(
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
function: 'updateMeetingActions',
|
|
7977
|
-
},
|
|
7978
|
-
'meeting:actionsUpdate',
|
|
7979
|
-
meeting.inMeetingActions.get()
|
|
7980
|
-
);
|
|
7981
|
-
|
|
7982
|
-
TriggerProxy.trigger.resetHistory();
|
|
7983
|
-
|
|
7984
|
-
meeting.updateMeetingActions();
|
|
7985
|
-
|
|
7986
|
-
assert.notCalled(TriggerProxy.trigger);
|
|
7987
|
-
|
|
7988
|
-
ControlsOptionsUtil.hasHints = restorableHasHints;
|
|
8460
|
+
assert.calledWith(updateMeetingActionsSpy);
|
|
8461
|
+
assert.calledWith(setRecordingDisplayHintsSpy, userDisplayHints);
|
|
8462
|
+
assert.calledWith(setUserPolicySpy, userDisplayPolicy);
|
|
8463
|
+
assert.calledWith(setControlsDisplayHintsSpy, userDisplayHints);
|
|
8464
|
+
assert.calledWith(handleDataChannelUrlChangeSpy, datachannelUrl);
|
|
7989
8465
|
});
|
|
7990
8466
|
});
|
|
7991
8467
|
|
|
7992
|
-
describe('#
|
|
7993
|
-
let
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
|
|
8003
|
-
|
|
8004
|
-
|
|
8468
|
+
describe('#updateMeetingActions', () => {
|
|
8469
|
+
let inMeetingActionsSetSpy;
|
|
8470
|
+
let canUserLockSpy;
|
|
8471
|
+
let canUserUnlockSpy;
|
|
8472
|
+
let canUserStartSpy;
|
|
8473
|
+
let canUserStopSpy;
|
|
8474
|
+
let canUserPauseSpy;
|
|
8475
|
+
let canUserResumeSpy;
|
|
8476
|
+
let canSetMuteOnEntrySpy;
|
|
8477
|
+
let canUnsetMuteOnEntrySpy;
|
|
8478
|
+
let canSetDisallowUnmuteSpy;
|
|
8479
|
+
let canUnsetDisallowUnmuteSpy;
|
|
8480
|
+
let canUserRaiseHandSpy;
|
|
8481
|
+
let bothLeaveAndEndMeetingAvailableSpy;
|
|
8482
|
+
let canUserLowerAllHandsSpy;
|
|
8483
|
+
let canUserLowerSomeoneElsesHandSpy;
|
|
8484
|
+
let waitingForOthersToJoinSpy;
|
|
8485
|
+
let canSendReactionsSpy;
|
|
8486
|
+
let canUserRenameSelfAndObservedSpy;
|
|
8487
|
+
let canUserRenameOthersSpy;
|
|
8488
|
+
let canShareWhiteBoardSpy;
|
|
8489
|
+
// Due to import tree issues, hasHints must be stubed within the scope of the `it`.
|
|
8490
|
+
|
|
8491
|
+
beforeEach(() => {
|
|
8492
|
+
canUserLockSpy = sinon.spy(MeetingUtil, 'canUserLock');
|
|
8493
|
+
canUserUnlockSpy = sinon.spy(MeetingUtil, 'canUserUnlock');
|
|
8494
|
+
canUserStartSpy = sinon.spy(RecordingUtil, 'canUserStart');
|
|
8495
|
+
canUserStopSpy = sinon.spy(RecordingUtil, 'canUserStop');
|
|
8496
|
+
canUserPauseSpy = sinon.spy(RecordingUtil, 'canUserPause');
|
|
8497
|
+
canUserResumeSpy = sinon.spy(RecordingUtil, 'canUserResume');
|
|
8498
|
+
canSetMuteOnEntrySpy = sinon.spy(ControlsOptionsUtil, 'canSetMuteOnEntry');
|
|
8499
|
+
canUnsetMuteOnEntrySpy = sinon.spy(ControlsOptionsUtil, 'canUnsetMuteOnEntry');
|
|
8500
|
+
canSetDisallowUnmuteSpy = sinon.spy(ControlsOptionsUtil, 'canSetDisallowUnmute');
|
|
8501
|
+
canUnsetDisallowUnmuteSpy = sinon.spy(ControlsOptionsUtil, 'canUnsetDisallowUnmute');
|
|
8502
|
+
inMeetingActionsSetSpy = sinon.spy(meeting.inMeetingActions, 'set');
|
|
8503
|
+
canUserRaiseHandSpy = sinon.spy(MeetingUtil, 'canUserRaiseHand');
|
|
8504
|
+
canUserLowerAllHandsSpy = sinon.spy(MeetingUtil, 'canUserLowerAllHands');
|
|
8505
|
+
bothLeaveAndEndMeetingAvailableSpy = sinon.spy(
|
|
8506
|
+
MeetingUtil,
|
|
8507
|
+
'bothLeaveAndEndMeetingAvailable'
|
|
8508
|
+
);
|
|
8509
|
+
canUserLowerSomeoneElsesHandSpy = sinon.spy(MeetingUtil, 'canUserLowerSomeoneElsesHand');
|
|
8510
|
+
waitingForOthersToJoinSpy = sinon.spy(MeetingUtil, 'waitingForOthersToJoin');
|
|
8511
|
+
canSendReactionsSpy = sinon.spy(MeetingUtil, 'canSendReactions');
|
|
8512
|
+
canUserRenameSelfAndObservedSpy = sinon.spy(MeetingUtil, 'canUserRenameSelfAndObserved');
|
|
8513
|
+
canUserRenameOthersSpy = sinon.spy(MeetingUtil, 'canUserRenameOthers');
|
|
8514
|
+
canShareWhiteBoardSpy = sinon.spy(MeetingUtil, 'canShareWhiteBoard');
|
|
8515
|
+
});
|
|
8516
|
+
|
|
8517
|
+
afterEach(() => {
|
|
8518
|
+
inMeetingActionsSetSpy.restore();
|
|
8519
|
+
waitingForOthersToJoinSpy.restore();
|
|
8520
|
+
});
|
|
8521
|
+
|
|
8522
|
+
forEach(
|
|
8523
|
+
[
|
|
8524
|
+
{
|
|
8525
|
+
actionName: 'canShareApplication',
|
|
8526
|
+
expectedEnabled: true,
|
|
8527
|
+
arePolicyRestrictionsSupported: false,
|
|
8528
|
+
},
|
|
8529
|
+
{
|
|
8530
|
+
actionName: 'canShareApplication',
|
|
8531
|
+
expectedEnabled: false,
|
|
8532
|
+
arePolicyRestrictionsSupported: true,
|
|
8533
|
+
},
|
|
8534
|
+
{
|
|
8535
|
+
actionName: 'canShareDesktop',
|
|
8536
|
+
arePolicyRestrictionsSupported: false,
|
|
8537
|
+
expectedEnabled: true,
|
|
8538
|
+
},
|
|
8539
|
+
{
|
|
8540
|
+
actionName: 'canShareDesktop',
|
|
8541
|
+
arePolicyRestrictionsSupported: true,
|
|
8542
|
+
expectedEnabled: false,
|
|
8543
|
+
},
|
|
8544
|
+
{
|
|
8545
|
+
actionName: 'canShareContent',
|
|
8546
|
+
arePolicyRestrictionsSupported: false,
|
|
8547
|
+
expectedEnabled: true,
|
|
8548
|
+
},
|
|
8549
|
+
{
|
|
8550
|
+
actionName: 'canShareContent',
|
|
8551
|
+
arePolicyRestrictionsSupported: true,
|
|
8552
|
+
expectedEnabled: false,
|
|
8553
|
+
},
|
|
8554
|
+
{
|
|
8555
|
+
actionName: 'canUseVoip',
|
|
8556
|
+
expectedEnabled: true,
|
|
8557
|
+
arePolicyRestrictionsSupported: false,
|
|
8558
|
+
},
|
|
8559
|
+
{
|
|
8560
|
+
actionName: 'canUseVoip',
|
|
8561
|
+
expectedEnabled: false,
|
|
8562
|
+
arePolicyRestrictionsSupported: true,
|
|
8563
|
+
},
|
|
8564
|
+
],
|
|
8565
|
+
({actionName, arePolicyRestrictionsSupported, expectedEnabled}) => {
|
|
8566
|
+
it(`${actionName} is ${expectedEnabled} when the call type is ${arePolicyRestrictionsSupported}`, () => {
|
|
8567
|
+
meeting.userDisplayHints = [];
|
|
8568
|
+
meeting.meetingInfo = {some: 'info'};
|
|
8569
|
+
sinon
|
|
8570
|
+
.stub(meeting, 'arePolicyRestrictionsSupported')
|
|
8571
|
+
.returns(arePolicyRestrictionsSupported);
|
|
8572
|
+
|
|
8573
|
+
meeting.updateMeetingActions();
|
|
8574
|
+
|
|
8575
|
+
assert.equal(meeting.inMeetingActions.get()[actionName], expectedEnabled);
|
|
8576
|
+
});
|
|
8577
|
+
}
|
|
8578
|
+
);
|
|
8579
|
+
|
|
8580
|
+
forEach(
|
|
8581
|
+
[
|
|
8582
|
+
{
|
|
8583
|
+
actionName: 'canShareFile',
|
|
8584
|
+
requiredDisplayHints: [DISPLAY_HINTS.SHARE_FILE],
|
|
8585
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_FILE_SHARE],
|
|
8586
|
+
},
|
|
8587
|
+
{
|
|
8588
|
+
actionName: 'canShareApplication',
|
|
8589
|
+
requiredDisplayHints: [DISPLAY_HINTS.SHARE_APPLICATION],
|
|
8590
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_APP_SHARE],
|
|
8591
|
+
},
|
|
8592
|
+
{
|
|
8593
|
+
actionName: 'canShareCamera',
|
|
8594
|
+
requiredDisplayHints: [DISPLAY_HINTS.SHARE_CAMERA],
|
|
8595
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_CAMERA_SHARE],
|
|
8596
|
+
},
|
|
8597
|
+
{
|
|
8598
|
+
actionName: 'canBroadcastMessageToBreakout',
|
|
8599
|
+
requiredDisplayHints: [DISPLAY_HINTS.BROADCAST_MESSAGE_TO_BREAKOUT],
|
|
8600
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_BROADCAST_MESSAGE],
|
|
8601
|
+
},
|
|
8602
|
+
{
|
|
8603
|
+
actionName: 'canShareDesktop',
|
|
8604
|
+
requiredDisplayHints: [DISPLAY_HINTS.SHARE_DESKTOP],
|
|
8605
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_DESKTOP_SHARE],
|
|
8606
|
+
},
|
|
8607
|
+
{
|
|
8608
|
+
actionName: 'canTransferFile',
|
|
8609
|
+
requiredDisplayHints: [],
|
|
8610
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_FILE_TRANSFER],
|
|
8611
|
+
},
|
|
8612
|
+
{
|
|
8613
|
+
actionName: 'canShareDesktop',
|
|
8614
|
+
requiredDisplayHints: [DISPLAY_HINTS.SHARE_DESKTOP],
|
|
8615
|
+
requiredPolicies: [],
|
|
8616
|
+
enableUnifiedMeetings: false,
|
|
8617
|
+
arePolicyRestrictionsSupported: false,
|
|
8618
|
+
},
|
|
8619
|
+
{
|
|
8620
|
+
actionName: 'canShareApplication',
|
|
8621
|
+
requiredDisplayHints: [DISPLAY_HINTS.SHARE_APPLICATION],
|
|
8622
|
+
requiredPolicies: [],
|
|
8623
|
+
enableUnifiedMeetings: false,
|
|
8624
|
+
arePolicyRestrictionsSupported: false,
|
|
8625
|
+
},
|
|
8626
|
+
{
|
|
8627
|
+
actionName: 'canAnnotate',
|
|
8628
|
+
requiredDisplayHints: [],
|
|
8629
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_ANNOTATION],
|
|
8630
|
+
},
|
|
8631
|
+
],
|
|
8632
|
+
({
|
|
8633
|
+
actionName,
|
|
8634
|
+
requiredDisplayHints,
|
|
8635
|
+
requiredPolicies,
|
|
8636
|
+
enableUnifiedMeetings,
|
|
8637
|
+
meetingInfo,
|
|
8638
|
+
arePolicyRestrictionsSupported,
|
|
8639
|
+
}) => {
|
|
8640
|
+
it(`${actionName} is enabled when the conditions are met`, () => {
|
|
8641
|
+
meeting.userDisplayHints = requiredDisplayHints;
|
|
8642
|
+
meeting.selfUserPolicies = undefined;
|
|
8643
|
+
sinon
|
|
8644
|
+
.stub(meeting, 'arePolicyRestrictionsSupported')
|
|
8645
|
+
.returns(arePolicyRestrictionsSupported);
|
|
8646
|
+
|
|
8647
|
+
meeting.config.experimental.enableUnifiedMeetings = isUndefined(enableUnifiedMeetings)
|
|
8648
|
+
? true
|
|
8649
|
+
: enableUnifiedMeetings;
|
|
8650
|
+
|
|
8651
|
+
meeting.meetingInfo = isUndefined(meetingInfo) ? {some: 'info'} : meetingInfo;
|
|
8652
|
+
|
|
8653
|
+
if (requiredPolicies) {
|
|
8654
|
+
meeting.selfUserPolicies = {};
|
|
8655
|
+
}
|
|
8656
|
+
forEach(requiredPolicies, (policy) => {
|
|
8657
|
+
meeting.selfUserPolicies[policy] = true;
|
|
8658
|
+
});
|
|
8659
|
+
|
|
8660
|
+
meeting.updateMeetingActions();
|
|
8661
|
+
|
|
8662
|
+
assert.isTrue(meeting.inMeetingActions.get()[actionName]);
|
|
8663
|
+
});
|
|
8664
|
+
|
|
8665
|
+
if (requiredDisplayHints.length !== 0) {
|
|
8666
|
+
it(`${actionName} is disabled when the required display hints are missing`, () => {
|
|
8667
|
+
meeting.userDisplayHints = [];
|
|
8668
|
+
meeting.selfUserPolicies = undefined;
|
|
8669
|
+
|
|
8670
|
+
meeting.meetingInfo = isUndefined(meetingInfo) ? {some: 'info'} : meetingInfo;
|
|
8671
|
+
|
|
8672
|
+
if (requiredPolicies) {
|
|
8673
|
+
meeting.selfUserPolicies = {};
|
|
8674
|
+
}
|
|
8675
|
+
forEach(requiredPolicies, (policy) => {
|
|
8676
|
+
meeting.selfUserPolicies[policy] = true;
|
|
8677
|
+
});
|
|
8678
|
+
|
|
8679
|
+
meeting.updateMeetingActions();
|
|
8680
|
+
|
|
8681
|
+
assert.isFalse(meeting.inMeetingActions.get()[actionName]);
|
|
8682
|
+
});
|
|
8683
|
+
}
|
|
8684
|
+
|
|
8685
|
+
it(`${actionName} is disabled when the required policies are missing`, () => {
|
|
8686
|
+
meeting.userDisplayHints = requiredDisplayHints;
|
|
8687
|
+
meeting.selfUserPolicies = undefined;
|
|
8688
|
+
|
|
8689
|
+
if (requiredPolicies) {
|
|
8690
|
+
meeting.selfUserPolicies = {};
|
|
8691
|
+
}
|
|
8692
|
+
meeting.meetingInfo = isUndefined(meetingInfo) ? {some: 'info'} : meetingInfo;
|
|
8693
|
+
|
|
8694
|
+
meeting.updateMeetingActions();
|
|
8695
|
+
|
|
8696
|
+
assert.isFalse(meeting.inMeetingActions.get()[actionName]);
|
|
8697
|
+
});
|
|
8698
|
+
}
|
|
8699
|
+
);
|
|
8700
|
+
|
|
8701
|
+
forEach(
|
|
8702
|
+
[
|
|
8703
|
+
{
|
|
8704
|
+
meetingInfo: {
|
|
8705
|
+
video: {
|
|
8706
|
+
supportHDV: true,
|
|
8707
|
+
supportHQV: true,
|
|
8708
|
+
},
|
|
8709
|
+
},
|
|
8710
|
+
selfUserPolicies: {
|
|
8711
|
+
[SELF_POLICY.SUPPORT_HDV]: true,
|
|
8712
|
+
[SELF_POLICY.SUPPORT_HQV]: true,
|
|
8713
|
+
},
|
|
8714
|
+
expectedActions: {
|
|
8715
|
+
supportHQV: true,
|
|
8716
|
+
supportHDV: true,
|
|
8717
|
+
},
|
|
8718
|
+
},
|
|
8719
|
+
{
|
|
8720
|
+
meetingInfo: {
|
|
8721
|
+
video: {
|
|
8722
|
+
supportHDV: false,
|
|
8723
|
+
supportHQV: false,
|
|
8724
|
+
},
|
|
8725
|
+
},
|
|
8726
|
+
selfUserPolicies: {
|
|
8727
|
+
[SELF_POLICY.SUPPORT_HDV]: true,
|
|
8728
|
+
[SELF_POLICY.SUPPORT_HQV]: true,
|
|
8729
|
+
},
|
|
8730
|
+
expectedActions: {
|
|
8731
|
+
supportHQV: false,
|
|
8732
|
+
supportHDV: false,
|
|
8733
|
+
},
|
|
8734
|
+
},
|
|
8735
|
+
{
|
|
8736
|
+
meetingInfo: {
|
|
8737
|
+
video: {
|
|
8738
|
+
supportHDV: true,
|
|
8739
|
+
supportHQV: true,
|
|
8740
|
+
},
|
|
8741
|
+
},
|
|
8742
|
+
selfUserPolicies: {
|
|
8743
|
+
[SELF_POLICY.SUPPORT_HDV]: false,
|
|
8744
|
+
[SELF_POLICY.SUPPORT_HQV]: false,
|
|
8745
|
+
},
|
|
8746
|
+
expectedActions: {
|
|
8747
|
+
supportHQV: false,
|
|
8748
|
+
supportHDV: false,
|
|
8749
|
+
},
|
|
8750
|
+
},
|
|
8751
|
+
{
|
|
8752
|
+
meetingInfo: undefined,
|
|
8753
|
+
selfUserPolicies: {},
|
|
8754
|
+
expectedActions: {
|
|
8755
|
+
supportHQV: true,
|
|
8756
|
+
supportHDV: true,
|
|
8757
|
+
},
|
|
8758
|
+
},
|
|
8759
|
+
{
|
|
8760
|
+
meetingInfo: {some: 'data'},
|
|
8761
|
+
selfUserPolicies: undefined,
|
|
8762
|
+
expectedActions: {
|
|
8763
|
+
supportHQV: true,
|
|
8764
|
+
supportHDV: true,
|
|
8765
|
+
},
|
|
8766
|
+
},
|
|
8767
|
+
],
|
|
8768
|
+
({meetingInfo, selfUserPolicies, expectedActions}) => {
|
|
8769
|
+
it(`expectedActions are ${JSON.stringify(
|
|
8770
|
+
expectedActions
|
|
8771
|
+
)} when policies are ${JSON.stringify(
|
|
8772
|
+
selfUserPolicies
|
|
8773
|
+
)} and meetingInfo is ${JSON.stringify(meetingInfo)}`, () => {
|
|
8774
|
+
meeting.meetingInfo = meetingInfo;
|
|
8775
|
+
meeting.selfUserPolicies = selfUserPolicies;
|
|
8776
|
+
|
|
8777
|
+
meeting.updateMeetingActions();
|
|
8778
|
+
|
|
8779
|
+
assert.deepEqual(
|
|
8780
|
+
{
|
|
8781
|
+
supportHDV: meeting.inMeetingActions.supportHDV,
|
|
8782
|
+
supportHQV: meeting.inMeetingActions.supportHQV,
|
|
8783
|
+
},
|
|
8784
|
+
expectedActions
|
|
8785
|
+
);
|
|
8786
|
+
});
|
|
8787
|
+
}
|
|
8788
|
+
);
|
|
8789
|
+
|
|
8790
|
+
it('canUseVoip is disabled when the required policies are missing', () => {
|
|
8791
|
+
meeting.userDisplayHints = [DISPLAY_HINTS.VOIP_IS_ENABLED];
|
|
8792
|
+
meeting.selfUserPolicies = {};
|
|
8793
|
+
meeting.meetingInfo.supportVoIP = true;
|
|
8794
|
+
|
|
8795
|
+
meeting.updateMeetingActions();
|
|
8796
|
+
|
|
8797
|
+
assert.isFalse(meeting.inMeetingActions.get()['canUseVoip']);
|
|
8798
|
+
});
|
|
8799
|
+
|
|
8800
|
+
it('canUseVoip is enabled based on api info when the conditions are met', () => {
|
|
8801
|
+
meeting.userDisplayHints = undefined;
|
|
8802
|
+
meeting.selfUserPolicies = {[SELF_POLICY.SUPPORT_VOIP]: true};
|
|
8803
|
+
meeting.meetingInfo.supportVoIP = true;
|
|
8804
|
+
|
|
8805
|
+
meeting.updateMeetingActions();
|
|
8806
|
+
|
|
8807
|
+
assert.isTrue(meeting.inMeetingActions.get()['canUseVoip']);
|
|
8808
|
+
});
|
|
8809
|
+
|
|
8810
|
+
it('canUseVoip is enabled based on api info when the conditions are met - no display hints', () => {
|
|
8811
|
+
meeting.userDisplayHints = [];
|
|
8812
|
+
meeting.selfUserPolicies = {[SELF_POLICY.SUPPORT_VOIP]: true};
|
|
8813
|
+
meeting.meetingInfo.supportVoIP = true;
|
|
8814
|
+
|
|
8815
|
+
meeting.updateMeetingActions();
|
|
8816
|
+
|
|
8817
|
+
assert.isTrue(meeting.inMeetingActions.get()['canUseVoip']);
|
|
8818
|
+
});
|
|
8819
|
+
|
|
8820
|
+
it('canUseVoip is enabled when there is no meeting info', () => {
|
|
8821
|
+
meeting.updateMeetingActions();
|
|
8822
|
+
|
|
8823
|
+
assert.isTrue(meeting.inMeetingActions.get()['canUseVoip']);
|
|
8824
|
+
});
|
|
8825
|
+
|
|
8826
|
+
it('canUseVoip is enabled when it is a locus call', () => {
|
|
8827
|
+
meeting.meetingInfo = {some: 'info'};
|
|
8828
|
+
meeting.type = 'CALL';
|
|
8829
|
+
|
|
8830
|
+
meeting.updateMeetingActions();
|
|
8831
|
+
|
|
8832
|
+
assert.isTrue(meeting.inMeetingActions.get()['canUseVoip']);
|
|
8833
|
+
});
|
|
8834
|
+
|
|
8835
|
+
it('canUseVoip is disabled based on api info when supportVoip is false', () => {
|
|
8836
|
+
meeting.userDisplayHints = undefined;
|
|
8837
|
+
meeting.selfUserPolicies = {[SELF_POLICY.SUPPORT_VOIP]: true};
|
|
8838
|
+
meeting.meetingInfo.supportVoIP = false;
|
|
8839
|
+
|
|
8840
|
+
meeting.updateMeetingActions();
|
|
8841
|
+
|
|
8842
|
+
assert.isFalse(meeting.inMeetingActions.get()['canUseVoip']);
|
|
8843
|
+
});
|
|
8844
|
+
|
|
8845
|
+
it('canUseVoip is disabled based on api info when the required policies are missing', () => {
|
|
8846
|
+
meeting.userDisplayHints = undefined;
|
|
8847
|
+
meeting.selfUserPolicies = {};
|
|
8848
|
+
meeting.meetingInfo.supportVoIP = true;
|
|
8849
|
+
|
|
8850
|
+
meeting.updateMeetingActions();
|
|
8851
|
+
|
|
8852
|
+
assert.isFalse(meeting.inMeetingActions.get()['canUseVoip']);
|
|
8853
|
+
});
|
|
8854
|
+
|
|
8855
|
+
it('canUseVoip is enabled when there are no policies', () => {
|
|
8856
|
+
meeting.userDisplayHints = [DISPLAY_HINTS.VOIP_IS_ENABLED];
|
|
8857
|
+
meeting.selfUserPolicies = undefined;
|
|
8858
|
+
meeting.meetingInfo.supportVoIP = false;
|
|
8859
|
+
|
|
8860
|
+
meeting.updateMeetingActions();
|
|
8861
|
+
|
|
8862
|
+
assert.isTrue(meeting.inMeetingActions.get()['canUseVoip']);
|
|
8863
|
+
});
|
|
8864
|
+
|
|
8865
|
+
forEach(
|
|
8866
|
+
[
|
|
8867
|
+
{
|
|
8868
|
+
meetingInfo: {},
|
|
8869
|
+
selfUserPolicies: {
|
|
8870
|
+
[SELF_POLICY.SUPPORT_VIDEO]: true,
|
|
8871
|
+
},
|
|
8872
|
+
expectedActions: {
|
|
8873
|
+
canDoVideo: true,
|
|
8874
|
+
},
|
|
8875
|
+
},
|
|
8876
|
+
{
|
|
8877
|
+
meetingInfo: {},
|
|
8878
|
+
selfUserPolicies: {
|
|
8879
|
+
[SELF_POLICY.SUPPORT_VIDEO]: false,
|
|
8880
|
+
},
|
|
8881
|
+
expectedActions: {
|
|
8882
|
+
canDoVideo: true,
|
|
8883
|
+
},
|
|
8884
|
+
},
|
|
8885
|
+
{
|
|
8886
|
+
meetingInfo: {some: 'data'},
|
|
8887
|
+
selfUserPolicies: {
|
|
8888
|
+
[SELF_POLICY.SUPPORT_VIDEO]: true,
|
|
8889
|
+
},
|
|
8890
|
+
expectedActions: {
|
|
8891
|
+
canDoVideo: false,
|
|
8892
|
+
},
|
|
8893
|
+
},
|
|
8894
|
+
{
|
|
8895
|
+
meetingInfo: {some: 'data'},
|
|
8896
|
+
selfUserPolicies: undefined,
|
|
8897
|
+
expectedActions: {
|
|
8898
|
+
canDoVideo: true,
|
|
8899
|
+
},
|
|
8900
|
+
},
|
|
8901
|
+
{
|
|
8902
|
+
meetingInfo: {
|
|
8903
|
+
video: {},
|
|
8904
|
+
},
|
|
8905
|
+
selfUserPolicies: {
|
|
8906
|
+
[SELF_POLICY.SUPPORT_VIDEO]: true,
|
|
8907
|
+
},
|
|
8908
|
+
expectedActions: {
|
|
8909
|
+
canDoVideo: true,
|
|
8910
|
+
},
|
|
8911
|
+
},
|
|
8912
|
+
{
|
|
8913
|
+
meetingInfo: undefined,
|
|
8914
|
+
selfUserPolicies: {},
|
|
8915
|
+
expectedActions: {
|
|
8916
|
+
canDoVideo: true,
|
|
8917
|
+
},
|
|
8918
|
+
},
|
|
8919
|
+
{
|
|
8920
|
+
meetingInfo: {
|
|
8921
|
+
video: {},
|
|
8922
|
+
},
|
|
8923
|
+
selfUserPolicies: {
|
|
8924
|
+
[SELF_POLICY.SUPPORT_VIDEO]: false,
|
|
8925
|
+
},
|
|
8926
|
+
expectedActions: {
|
|
8927
|
+
canDoVideo: false,
|
|
8928
|
+
},
|
|
8929
|
+
},
|
|
8930
|
+
],
|
|
8931
|
+
({meetingInfo, selfUserPolicies, expectedActions}) => {
|
|
8932
|
+
it(`has expectedActions ${JSON.stringify(
|
|
8933
|
+
expectedActions
|
|
8934
|
+
)} when policies are ${JSON.stringify(
|
|
8935
|
+
selfUserPolicies
|
|
8936
|
+
)} and meetingInfo is ${JSON.stringify(meetingInfo)}`, () => {
|
|
8937
|
+
meeting.meetingInfo = meetingInfo;
|
|
8938
|
+
meeting.selfUserPolicies = selfUserPolicies;
|
|
8939
|
+
meeting.config.experimental.enableUnifiedMeetings = true;
|
|
8940
|
+
|
|
8941
|
+
meeting.updateMeetingActions();
|
|
8942
|
+
|
|
8943
|
+
assert.deepEqual(
|
|
8944
|
+
{
|
|
8945
|
+
canDoVideo: meeting.inMeetingActions.canDoVideo,
|
|
8946
|
+
},
|
|
8947
|
+
expectedActions
|
|
8948
|
+
);
|
|
8949
|
+
});
|
|
8950
|
+
}
|
|
8951
|
+
);
|
|
8952
|
+
|
|
8953
|
+
it('correctly updates the meeting actions', () => {
|
|
8954
|
+
// Due to import tree issues, hasHints must be stubed within the scope of the `it`.
|
|
8955
|
+
const restorableHasHints = ControlsOptionsUtil.hasHints;
|
|
8956
|
+
ControlsOptionsUtil.hasHints = sinon.stub().returns(true);
|
|
8957
|
+
ControlsOptionsUtil.hasPolicies = sinon.stub().returns(true);
|
|
8958
|
+
|
|
8959
|
+
const selfUserPolicies = {a: true};
|
|
8960
|
+
meeting.selfUserPolicies = {a: true};
|
|
8961
|
+
const userDisplayHints = ['LOCK_CONTROL_UNLOCK'];
|
|
8962
|
+
meeting.userDisplayHints = ['LOCK_CONTROL_UNLOCK'];
|
|
8963
|
+
meeting.meetingInfo.supportVoIP = true;
|
|
8964
|
+
|
|
8965
|
+
meeting.updateMeetingActions();
|
|
8966
|
+
|
|
8967
|
+
assert.calledWith(canUserLockSpy, userDisplayHints);
|
|
8968
|
+
assert.calledWith(canUserUnlockSpy, userDisplayHints);
|
|
8969
|
+
assert.calledWith(canUserStartSpy, userDisplayHints);
|
|
8970
|
+
assert.calledWith(canUserStopSpy, userDisplayHints);
|
|
8971
|
+
assert.calledWith(canUserPauseSpy, userDisplayHints);
|
|
8972
|
+
assert.calledWith(canUserResumeSpy, userDisplayHints);
|
|
8973
|
+
assert.calledWith(canSetMuteOnEntrySpy, userDisplayHints);
|
|
8974
|
+
assert.calledWith(canUnsetMuteOnEntrySpy, userDisplayHints);
|
|
8975
|
+
assert.calledWith(canSetDisallowUnmuteSpy, userDisplayHints);
|
|
8976
|
+
assert.calledWith(canUnsetDisallowUnmuteSpy, userDisplayHints);
|
|
8977
|
+
assert.calledWith(canUserRaiseHandSpy, userDisplayHints);
|
|
8978
|
+
assert.calledWith(bothLeaveAndEndMeetingAvailableSpy, userDisplayHints);
|
|
8979
|
+
assert.calledWith(canUserLowerAllHandsSpy, userDisplayHints);
|
|
8980
|
+
assert.calledWith(canUserLowerSomeoneElsesHandSpy, userDisplayHints);
|
|
8981
|
+
assert.calledWith(waitingForOthersToJoinSpy, userDisplayHints);
|
|
8982
|
+
assert.calledWith(canSendReactionsSpy, null, userDisplayHints);
|
|
8983
|
+
assert.calledWith(canUserRenameSelfAndObservedSpy, userDisplayHints);
|
|
8984
|
+
assert.calledWith(canUserRenameOthersSpy, userDisplayHints);
|
|
8985
|
+
assert.calledWith(canShareWhiteBoardSpy, userDisplayHints);
|
|
8986
|
+
|
|
8987
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
8988
|
+
requiredHints: [DISPLAY_HINTS.MUTE_ALL],
|
|
8989
|
+
displayHints: userDisplayHints,
|
|
8990
|
+
});
|
|
8991
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
8992
|
+
requiredHints: [DISPLAY_HINTS.UNMUTE_ALL],
|
|
8993
|
+
displayHints: userDisplayHints,
|
|
8994
|
+
});
|
|
8995
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
8996
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_HARD_MUTE],
|
|
8997
|
+
displayHints: userDisplayHints,
|
|
8998
|
+
});
|
|
8999
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9000
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_HARD_MUTE],
|
|
9001
|
+
displayHints: userDisplayHints,
|
|
9002
|
+
});
|
|
9003
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9004
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_MUTE_ON_ENTRY],
|
|
9005
|
+
displayHints: userDisplayHints,
|
|
9006
|
+
});
|
|
9007
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9008
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_MUTE_ON_ENTRY],
|
|
9009
|
+
displayHints: userDisplayHints,
|
|
9010
|
+
});
|
|
9011
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9012
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_REACTIONS],
|
|
9013
|
+
displayHints: userDisplayHints,
|
|
9014
|
+
});
|
|
9015
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9016
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_REACTIONS],
|
|
9017
|
+
displayHints: userDisplayHints,
|
|
9018
|
+
});
|
|
9019
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9020
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_SHOW_DISPLAY_NAME],
|
|
9021
|
+
displayHints: userDisplayHints,
|
|
9022
|
+
});
|
|
9023
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9024
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_SHOW_DISPLAY_NAME],
|
|
9025
|
+
displayHints: userDisplayHints,
|
|
9026
|
+
});
|
|
9027
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9028
|
+
requiredHints: [DISPLAY_HINTS.SHARE_CONTROL],
|
|
9029
|
+
displayHints: userDisplayHints,
|
|
9030
|
+
});
|
|
9031
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9032
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_VIEW_THE_PARTICIPANT_LIST],
|
|
9033
|
+
displayHints: userDisplayHints,
|
|
9034
|
+
});
|
|
9035
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9036
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_VIEW_THE_PARTICIPANT_LIST],
|
|
9037
|
+
displayHints: userDisplayHints,
|
|
9038
|
+
});
|
|
9039
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9040
|
+
requiredHints: [DISPLAY_HINTS.SHARE_FILE],
|
|
9041
|
+
displayHints: userDisplayHints,
|
|
9042
|
+
});
|
|
9043
|
+
assert.calledWith(ControlsOptionsUtil.hasPolicies, {
|
|
9044
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_FILE_SHARE],
|
|
9045
|
+
policies: selfUserPolicies,
|
|
9046
|
+
});
|
|
9047
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9048
|
+
requiredHints: [DISPLAY_HINTS.SHARE_APPLICATION],
|
|
9049
|
+
displayHints: userDisplayHints,
|
|
9050
|
+
});
|
|
9051
|
+
assert.calledWith(ControlsOptionsUtil.hasPolicies, {
|
|
9052
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_APP_SHARE],
|
|
9053
|
+
policies: selfUserPolicies,
|
|
9054
|
+
});
|
|
9055
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9056
|
+
requiredHints: [DISPLAY_HINTS.SHARE_CAMERA],
|
|
9057
|
+
displayHints: userDisplayHints,
|
|
9058
|
+
});
|
|
9059
|
+
assert.calledWith(ControlsOptionsUtil.hasPolicies, {
|
|
9060
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_CAMERA_SHARE],
|
|
9061
|
+
policies: selfUserPolicies,
|
|
9062
|
+
});
|
|
9063
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9064
|
+
requiredHints: [DISPLAY_HINTS.SHARE_DESKTOP],
|
|
9065
|
+
displayHints: userDisplayHints,
|
|
9066
|
+
});
|
|
9067
|
+
assert.calledWith(ControlsOptionsUtil.hasPolicies, {
|
|
9068
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_DESKTOP_SHARE],
|
|
9069
|
+
policies: selfUserPolicies,
|
|
9070
|
+
});
|
|
9071
|
+
assert.calledWith(ControlsOptionsUtil.hasHints, {
|
|
9072
|
+
requiredHints: [DISPLAY_HINTS.SHARE_CONTENT],
|
|
9073
|
+
displayHints: userDisplayHints,
|
|
9074
|
+
});
|
|
9075
|
+
assert.calledWith(ControlsOptionsUtil.hasPolicies, {
|
|
9076
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_VOIP],
|
|
9077
|
+
policies: selfUserPolicies,
|
|
9078
|
+
});
|
|
9079
|
+
|
|
9080
|
+
assert.calledWith(
|
|
9081
|
+
TriggerProxy.trigger,
|
|
9082
|
+
meeting,
|
|
9083
|
+
{
|
|
9084
|
+
file: 'meeting/index',
|
|
9085
|
+
function: 'updateMeetingActions',
|
|
9086
|
+
},
|
|
9087
|
+
'meeting:actionsUpdate',
|
|
9088
|
+
meeting.inMeetingActions.get()
|
|
9089
|
+
);
|
|
9090
|
+
|
|
9091
|
+
TriggerProxy.trigger.resetHistory();
|
|
9092
|
+
|
|
9093
|
+
meeting.updateMeetingActions();
|
|
9094
|
+
|
|
9095
|
+
assert.notCalled(TriggerProxy.trigger);
|
|
9096
|
+
|
|
9097
|
+
ControlsOptionsUtil.hasHints = restorableHasHints;
|
|
9098
|
+
});
|
|
9099
|
+
});
|
|
9100
|
+
|
|
9101
|
+
describe('#handleDataChannelUrlChange', () => {
|
|
9102
|
+
let updateLLMConnectionSpy;
|
|
9103
|
+
|
|
9104
|
+
beforeEach(() => {
|
|
9105
|
+
updateLLMConnectionSpy = sinon.spy(meeting, 'updateLLMConnection');
|
|
9106
|
+
});
|
|
9107
|
+
|
|
9108
|
+
const check = (url, expectedCalled) => {
|
|
9109
|
+
meeting.handleDataChannelUrlChange(url);
|
|
9110
|
+
|
|
9111
|
+
if (expectedCalled) {
|
|
9112
|
+
assert.calledWith(updateLLMConnectionSpy);
|
|
9113
|
+
} else {
|
|
8005
9114
|
assert.notCalled(updateLLMConnectionSpy);
|
|
8006
9115
|
}
|
|
8007
9116
|
};
|
|
@@ -9465,7 +10574,7 @@ describe('plugin-meetings', () => {
|
|
|
9465
10574
|
});
|
|
9466
10575
|
});
|
|
9467
10576
|
|
|
9468
|
-
describe('#
|
|
10577
|
+
describe('#getPermissionTokenExpiryInfo', () => {
|
|
9469
10578
|
let now;
|
|
9470
10579
|
let clock;
|
|
9471
10580
|
|
|
@@ -9481,63 +10590,141 @@ describe('plugin-meetings', () => {
|
|
|
9481
10590
|
})
|
|
9482
10591
|
|
|
9483
10592
|
it('should return undefined if exp is undefined', () => {
|
|
9484
|
-
assert.equal(meeting.
|
|
10593
|
+
assert.equal(meeting.getPermissionTokenExpiryInfo(), undefined)
|
|
9485
10594
|
});
|
|
9486
10595
|
|
|
9487
10596
|
it('should return the expected positive exp', () => {
|
|
9488
10597
|
// set permission token as now + 1 sec
|
|
9489
|
-
|
|
9490
|
-
|
|
10598
|
+
const expiryTime = now + 1000;
|
|
10599
|
+
meeting.permissionTokenPayload = {exp: (expiryTime).toString(), iat: now};
|
|
10600
|
+
meeting.permissionTokenReceivedLocalTime = now;
|
|
10601
|
+
assert.deepEqual(meeting.getPermissionTokenExpiryInfo(), {timeLeft: 1, expiryTime: Number(expiryTime), currentTime: now});
|
|
9491
10602
|
});
|
|
9492
10603
|
|
|
9493
10604
|
it('should return the expected negative exp', () => {
|
|
9494
10605
|
// set permission token as now - 1 sec
|
|
9495
|
-
|
|
9496
|
-
|
|
10606
|
+
const expiryTime = now - 1000;
|
|
10607
|
+
meeting.permissionTokenPayload = {exp: (expiryTime).toString(), iat: now};
|
|
10608
|
+
meeting.permissionTokenReceivedLocalTime = now;
|
|
10609
|
+
assert.deepEqual(meeting.getPermissionTokenExpiryInfo(), {timeLeft: -1, expiryTime: Number(expiryTime), currentTime: now});
|
|
10610
|
+
});
|
|
10611
|
+
|
|
10612
|
+
describe('#getPermissionTokenExpiryInfo with wrong current time which is in future', () => {
|
|
10613
|
+
let now;
|
|
10614
|
+
let clock;
|
|
10615
|
+
beforeEach(() => {
|
|
10616
|
+
// current time is 3 hours off
|
|
10617
|
+
now = Date.now() + 10800000;
|
|
10618
|
+
|
|
10619
|
+
// mock `new Date()` with constant `now`
|
|
10620
|
+
clock = sinon.useFakeTimers(now);
|
|
10621
|
+
});
|
|
10622
|
+
|
|
10623
|
+
afterEach(() => {
|
|
10624
|
+
clock.restore();
|
|
10625
|
+
})
|
|
10626
|
+
|
|
10627
|
+
it('should return the expected positive exp when client time is wrong', () => {
|
|
10628
|
+
const serverTime = Date.now();
|
|
10629
|
+
|
|
10630
|
+
// set permission token as now + 1 sec
|
|
10631
|
+
const expiryTime = serverTime + 1000;
|
|
10632
|
+
meeting.permissionTokenPayload = {exp: (expiryTime).toString(), iat: serverTime};
|
|
10633
|
+
meeting.permissionTokenReceivedLocalTime = now;
|
|
10634
|
+
assert.deepEqual(meeting.getPermissionTokenExpiryInfo(), {timeLeft: 1, expiryTime: Number(expiryTime), currentTime: now});
|
|
10635
|
+
});
|
|
10636
|
+
|
|
10637
|
+
it('should return the expected negative exp when client time is wrong', () => {
|
|
10638
|
+
const serverTime = Date.now();
|
|
10639
|
+
// set permission token as now - 1 sec
|
|
10640
|
+
const expiryTime = serverTime - 1000;
|
|
10641
|
+
meeting.permissionTokenPayload = {exp: (expiryTime).toString(), iat: serverTime};
|
|
10642
|
+
meeting.permissionTokenReceivedLocalTime = now;
|
|
10643
|
+
assert.deepEqual(meeting.getPermissionTokenExpiryInfo(), {timeLeft: -1, expiryTime: Number(expiryTime), currentTime: now});
|
|
10644
|
+
});
|
|
10645
|
+
|
|
10646
|
+
});
|
|
10647
|
+
|
|
10648
|
+
describe('#getPermissionTokenExpiryInfo with wrong current Time which is in the past', () => {
|
|
10649
|
+
let now;
|
|
10650
|
+
let clock;
|
|
10651
|
+
beforeEach(() => {
|
|
10652
|
+
// current time is 3 hours off
|
|
10653
|
+
now = Date.now() - 10800000;
|
|
10654
|
+
|
|
10655
|
+
// mock `new Date()` with constant `now`
|
|
10656
|
+
clock = sinon.useFakeTimers(now);
|
|
10657
|
+
});
|
|
10658
|
+
|
|
10659
|
+
afterEach(() => {
|
|
10660
|
+
clock.restore();
|
|
10661
|
+
})
|
|
10662
|
+
|
|
10663
|
+
it('should return the expected positive exp when client time is wrong', () => {
|
|
10664
|
+
const serverTime = Date.now();
|
|
10665
|
+
|
|
10666
|
+
// set permission token as now + 1 sec
|
|
10667
|
+
const expiryTime = serverTime + 1000;
|
|
10668
|
+
meeting.permissionTokenPayload = {exp: (expiryTime).toString(), iat: serverTime};
|
|
10669
|
+
meeting.permissionTokenReceivedLocalTime = now;
|
|
10670
|
+
assert.deepEqual(meeting.getPermissionTokenExpiryInfo(), {timeLeft: 1, expiryTime: Number(expiryTime), currentTime: now});
|
|
10671
|
+
});
|
|
10672
|
+
|
|
10673
|
+
it('should return the expected negative exp when client time is wrong', () => {
|
|
10674
|
+
const serverTime = Date.now();
|
|
10675
|
+
// set permission token as now - 1 sec
|
|
10676
|
+
const expiryTime = serverTime - 1000;
|
|
10677
|
+
meeting.permissionTokenPayload = {exp: (expiryTime).toString(), iat: serverTime};
|
|
10678
|
+
meeting.permissionTokenReceivedLocalTime = now;
|
|
10679
|
+
assert.deepEqual(meeting.getPermissionTokenExpiryInfo(), {timeLeft: -1, expiryTime: Number(expiryTime), currentTime: now});
|
|
10680
|
+
});
|
|
10681
|
+
|
|
9497
10682
|
});
|
|
9498
10683
|
});
|
|
9499
10684
|
|
|
10685
|
+
|
|
10686
|
+
|
|
9500
10687
|
describe('#checkAndRefreshPermissionToken', () => {
|
|
9501
10688
|
it('should not fire refreshPermissionToken if permissionToken is not defined', async() => {
|
|
9502
|
-
meeting.
|
|
10689
|
+
meeting.getPermissionTokenExpiryInfo = sinon.stub().returns(undefined)
|
|
9503
10690
|
meeting.refreshPermissionToken = sinon.stub().returns(Promise.resolve('test return value'));
|
|
9504
10691
|
|
|
9505
10692
|
const returnValue = await meeting.checkAndRefreshPermissionToken(10, 'ttl-join');
|
|
9506
10693
|
|
|
9507
|
-
assert.calledOnce(meeting.
|
|
10694
|
+
assert.calledOnce(meeting.getPermissionTokenExpiryInfo);
|
|
9508
10695
|
assert.notCalled(meeting.refreshPermissionToken);
|
|
9509
10696
|
assert.equal(returnValue, undefined);
|
|
9510
10697
|
});
|
|
9511
10698
|
|
|
9512
10699
|
it('should fire refreshPermissionToken if time left is below 10sec', async() => {
|
|
9513
|
-
meeting.
|
|
10700
|
+
meeting.getPermissionTokenExpiryInfo = sinon.stub().returns({timeLeft: 9, expiryTime: 122132, currentTime: Date.now()})
|
|
9514
10701
|
meeting.refreshPermissionToken = sinon.stub().returns(Promise.resolve('test return value'));
|
|
9515
10702
|
|
|
9516
10703
|
const returnValue = await meeting.checkAndRefreshPermissionToken(10, 'ttl-join');
|
|
9517
10704
|
|
|
9518
|
-
assert.calledOnce(meeting.
|
|
10705
|
+
assert.calledOnce(meeting.getPermissionTokenExpiryInfo);
|
|
9519
10706
|
assert.calledOnceWithExactly(meeting.refreshPermissionToken, 'ttl-join');
|
|
9520
10707
|
assert.equal(returnValue, 'test return value');
|
|
9521
10708
|
});
|
|
9522
10709
|
|
|
9523
10710
|
it('should fire refreshPermissionToken if time left is equal 10sec', async () => {
|
|
9524
|
-
meeting.
|
|
10711
|
+
meeting.getPermissionTokenExpiryInfo = sinon.stub().returns({timeLeft: 10, expiryTime: 122132, currentTime: Date.now()})
|
|
9525
10712
|
meeting.refreshPermissionToken = sinon.stub().returns(Promise.resolve('test return value'));
|
|
9526
10713
|
|
|
9527
10714
|
const returnValue = await meeting.checkAndRefreshPermissionToken(10, 'ttl-join');
|
|
9528
10715
|
|
|
9529
|
-
assert.calledOnce(meeting.
|
|
10716
|
+
assert.calledOnce(meeting.getPermissionTokenExpiryInfo);
|
|
9530
10717
|
assert.calledOnceWithExactly(meeting.refreshPermissionToken, 'ttl-join');
|
|
9531
10718
|
assert.equal(returnValue, 'test return value');
|
|
9532
10719
|
});
|
|
9533
10720
|
|
|
9534
10721
|
it('should not fire refreshPermissionToken if time left is higher than 10sec', async () => {
|
|
9535
|
-
meeting.
|
|
10722
|
+
meeting.getPermissionTokenExpiryInfo = sinon.stub().returns({timeLeft: 11, expiryTime: 122132, currentTime: Date.now()})
|
|
9536
10723
|
meeting.refreshPermissionToken = sinon.stub().returns(Promise.resolve('test return value'));
|
|
9537
10724
|
|
|
9538
10725
|
const returnValue = await meeting.checkAndRefreshPermissionToken(10, 'ttl-join');
|
|
9539
10726
|
|
|
9540
|
-
assert.calledOnce(meeting.
|
|
10727
|
+
assert.calledOnce(meeting.getPermissionTokenExpiryInfo);
|
|
9541
10728
|
assert.notCalled(meeting.refreshPermissionToken);
|
|
9542
10729
|
assert.equal(returnValue, undefined);
|
|
9543
10730
|
});
|