@webex/plugin-meetings 3.0.0-beta.2 → 3.0.0-beta.21
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/UPGRADING.md +9 -9
- package/browsers.js +19 -24
- package/dist/breakouts/breakout.js +116 -0
- package/dist/breakouts/breakout.js.map +1 -0
- package/dist/breakouts/collection.js +23 -0
- package/dist/breakouts/collection.js.map +1 -0
- package/dist/breakouts/index.js +226 -0
- package/dist/breakouts/index.js.map +1 -0
- package/dist/common/browser-detection.js +1 -20
- package/dist/common/browser-detection.js.map +1 -1
- package/dist/common/collection.js +5 -20
- package/dist/common/collection.js.map +1 -1
- package/dist/common/config.js +0 -7
- package/dist/common/config.js.map +1 -1
- package/dist/common/errors/captcha-error.js +10 -24
- package/dist/common/errors/captcha-error.js.map +1 -1
- package/dist/common/errors/intent-to-join.js +11 -24
- package/dist/common/errors/intent-to-join.js.map +1 -1
- package/dist/common/errors/join-meeting.js +12 -25
- package/dist/common/errors/join-meeting.js.map +1 -1
- package/dist/common/errors/media.js +10 -24
- package/dist/common/errors/media.js.map +1 -1
- package/dist/common/errors/parameter.js +5 -33
- package/dist/common/errors/parameter.js.map +1 -1
- package/dist/common/errors/password-error.js +10 -24
- package/dist/common/errors/password-error.js.map +1 -1
- package/dist/common/errors/permission.js +9 -23
- package/dist/common/errors/permission.js.map +1 -1
- package/dist/common/errors/reconnection-in-progress.js +0 -17
- package/dist/common/errors/reconnection-in-progress.js.map +1 -1
- package/dist/common/errors/reconnection.js +10 -24
- package/dist/common/errors/reconnection.js.map +1 -1
- package/dist/common/errors/stats.js +10 -24
- package/dist/common/errors/stats.js.map +1 -1
- package/dist/common/errors/webex-errors.js +6 -41
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/common/errors/webex-meetings-error.js +5 -25
- package/dist/common/errors/webex-meetings-error.js.map +1 -1
- package/dist/common/events/events-scope.js +0 -22
- package/dist/common/events/events-scope.js.map +1 -1
- package/dist/common/events/events.js +0 -23
- package/dist/common/events/events.js.map +1 -1
- package/dist/common/events/trigger-proxy.js +0 -12
- package/dist/common/events/trigger-proxy.js.map +1 -1
- package/dist/common/events/util.js +0 -15
- package/dist/common/events/util.js.map +1 -1
- package/dist/common/logs/logger-config.js +0 -4
- package/dist/common/logs/logger-config.js.map +1 -1
- package/dist/common/logs/logger-proxy.js +1 -8
- package/dist/common/logs/logger-proxy.js.map +1 -1
- package/dist/common/logs/request.js +37 -60
- package/dist/common/logs/request.js.map +1 -1
- package/dist/common/queue.js +4 -14
- package/dist/common/queue.js.map +1 -1
- package/dist/config.js +6 -6
- package/dist/config.js.map +1 -1
- package/dist/constants.js +88 -46
- package/dist/constants.js.map +1 -1
- package/dist/index.js +4 -18
- package/dist/index.js.map +1 -1
- package/dist/locus-info/controlsUtils.js +12 -29
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/embeddedAppsUtils.js +3 -26
- package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
- package/dist/locus-info/fullState.js +0 -15
- package/dist/locus-info/fullState.js.map +1 -1
- package/dist/locus-info/hostUtils.js +4 -12
- package/dist/locus-info/hostUtils.js.map +1 -1
- package/dist/locus-info/index.js +184 -190
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js +3 -37
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js +12 -38
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.js +92 -118
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +34 -91
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +67 -111
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +80 -114
- package/dist/media/properties.js.map +1 -1
- package/dist/media/util.js +2 -9
- package/dist/media/util.js.map +1 -1
- package/dist/mediaQualityMetrics/config.js +10 -12
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/effectsState.js +125 -190
- package/dist/meeting/effectsState.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +5 -14
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +1692 -1925
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +36 -77
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +224 -230
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js +7 -0
- package/dist/meeting/request.type.js.map +1 -0
- package/dist/meeting/state.js +21 -31
- package/dist/meeting/state.js.map +1 -1
- package/dist/meeting/util.js +43 -215
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/collection.js +6 -25
- package/dist/meeting-info/collection.js.map +1 -1
- package/dist/meeting-info/index.js +14 -32
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +193 -268
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/request.js +3 -15
- package/dist/meeting-info/request.js.map +1 -1
- package/dist/meeting-info/util.js +98 -183
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +137 -228
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +5 -20
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +490 -560
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/request.js +24 -41
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +99 -155
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +78 -86
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +31 -68
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js +3 -12
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +93 -200
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +16 -39
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +9 -38
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/config.js +0 -2
- package/dist/metrics/config.js.map +1 -1
- package/dist/metrics/constants.js +1 -2
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +55 -135
- package/dist/metrics/index.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +57 -32
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/multistreamMedia.js +15 -21
- package/dist/multistream/multistreamMedia.js.map +1 -1
- package/dist/multistream/receiveSlot.js +10 -50
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +45 -82
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +18 -58
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +6 -40
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +362 -416
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/networkQualityMonitor/index.js +36 -57
- package/dist/networkQualityMonitor/index.js.map +1 -1
- package/dist/personal-meeting-room/index.js +21 -45
- package/dist/personal-meeting-room/index.js.map +1 -1
- package/dist/personal-meeting-room/request.js +1 -31
- package/dist/personal-meeting-room/request.js.map +1 -1
- package/dist/personal-meeting-room/util.js +0 -13
- package/dist/personal-meeting-room/util.js.map +1 -1
- package/dist/reachability/index.js +138 -182
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +3 -18
- package/dist/reachability/request.js.map +1 -1
- package/dist/reactions/constants.js +13 -0
- package/dist/reactions/constants.js.map +1 -0
- package/dist/reactions/reactions.js +109 -0
- package/dist/reactions/reactions.js.map +1 -0
- package/dist/reactions/reactions.type.js +36 -0
- package/dist/reactions/reactions.type.js.map +1 -0
- package/dist/reconnection-manager/index.js +322 -455
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/enums.js +17 -0
- package/dist/recording-controller/enums.js.map +1 -0
- package/dist/recording-controller/index.js +343 -0
- package/dist/recording-controller/index.js.map +1 -0
- package/dist/recording-controller/util.js +63 -0
- package/dist/recording-controller/util.js.map +1 -0
- package/dist/roap/index.js +39 -64
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +94 -113
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +85 -94
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/statsAnalyzer/global.js +0 -2
- package/dist/statsAnalyzer/global.js.map +1 -1
- package/dist/statsAnalyzer/index.js +85 -175
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +72 -53
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/transcription/index.js +22 -47
- package/dist/transcription/index.js.map +1 -1
- package/internal-README.md +7 -6
- package/package.json +25 -20
- package/src/breakouts/README.md +190 -0
- package/src/breakouts/breakout.ts +110 -0
- package/src/breakouts/collection.ts +19 -0
- package/src/breakouts/index.ts +225 -0
- package/src/common/{browser-detection.js → browser-detection.ts} +9 -6
- package/src/common/collection.ts +9 -7
- package/src/common/{config.js → config.ts} +1 -1
- package/src/common/errors/{captcha-error.js → captcha-error.ts} +11 -7
- package/src/common/errors/{intent-to-join.js → intent-to-join.ts} +12 -7
- package/src/common/errors/{join-meeting.js → join-meeting.ts} +17 -8
- package/src/common/errors/{media.js → media.ts} +11 -7
- package/src/common/errors/parameter.ts +11 -7
- package/src/common/errors/{password-error.js → password-error.ts} +11 -7
- package/src/common/errors/{permission.js → permission.ts} +10 -6
- package/src/common/errors/{reconnection-in-progress.js → reconnection-in-progress.ts} +0 -0
- package/src/common/errors/{reconnection.js → reconnection.ts} +11 -7
- package/src/common/errors/{stats.js → stats.ts} +11 -7
- package/src/common/errors/{webex-errors.js → webex-errors.ts} +8 -7
- package/src/common/errors/{webex-meetings-error.js → webex-meetings-error.ts} +4 -2
- package/src/common/events/{events-scope.js → events-scope.ts} +6 -2
- package/src/common/events/{events.js → events.ts} +5 -1
- package/src/common/events/{trigger-proxy.js → trigger-proxy.ts} +9 -5
- package/src/common/events/{util.js → util.ts} +2 -3
- package/src/common/logs/{logger-config.js → logger-config.ts} +1 -2
- package/src/common/logs/logger-proxy.ts +44 -0
- package/src/common/logs/{request.js → request.ts} +22 -9
- package/src/common/queue.ts +1 -2
- package/src/{config.js → config.ts} +17 -12
- package/src/constants.ts +40 -1
- package/src/index.js +2 -1
- package/src/locus-info/controlsUtils.ts +114 -0
- package/src/locus-info/{embeddedAppsUtils.js → embeddedAppsUtils.ts} +5 -6
- package/src/locus-info/{fullState.js → fullState.ts} +16 -12
- package/src/locus-info/{hostUtils.js → hostUtils.ts} +9 -8
- package/src/locus-info/{index.js → index.ts} +148 -64
- package/src/locus-info/{infoUtils.js → infoUtils.ts} +19 -8
- package/src/locus-info/{mediaSharesUtils.js → mediaSharesUtils.ts} +17 -17
- package/src/locus-info/{parser.js → parser.ts} +67 -79
- package/src/locus-info/{selfUtils.js → selfUtils.ts} +123 -68
- package/src/media/{index.js → index.ts} +181 -131
- package/src/media/{properties.js → properties.ts} +47 -28
- package/src/media/{util.js → util.ts} +2 -2
- package/src/mediaQualityMetrics/{config.js → config.ts} +46 -46
- package/src/meeting/{effectsState.js → effectsState.ts} +47 -41
- package/src/meeting/in-meeting-actions.ts +15 -3
- package/src/meeting/{index.js → index.ts} +2263 -1427
- package/src/meeting/{muteState.js → muteState.ts} +78 -42
- package/src/meeting/{request.js → request.ts} +292 -142
- package/src/meeting/request.type.ts +13 -0
- package/src/meeting/{state.js → state.ts} +50 -35
- package/src/meeting/{util.js → util.ts} +112 -115
- package/src/meeting-info/{collection.js → collection.ts} +6 -2
- package/src/meeting-info/{index.js → index.ts} +42 -36
- package/src/meeting-info/meeting-info-v2.ts +273 -0
- package/src/meeting-info/{request.js → request.ts} +14 -4
- package/src/meeting-info/{util.js → util.ts} +60 -51
- package/src/meeting-info/{utilv2.js → utilv2.ts} +65 -58
- package/src/meetings/{collection.js → collection.ts} +6 -3
- package/src/meetings/index.ts +1159 -0
- package/src/meetings/{request.js → request.ts} +32 -25
- package/src/meetings/{util.js → util.ts} +34 -32
- package/src/member/{index.js → index.ts} +102 -56
- package/src/member/{util.js → util.ts} +52 -25
- package/src/members/{collection.js → collection.ts} +2 -2
- package/src/members/{index.js → index.ts} +219 -142
- package/src/members/{request.js → request.ts} +60 -16
- package/src/members/{util.js → util.ts} +50 -48
- package/src/metrics/{config.js → config.ts} +254 -83
- package/src/metrics/{constants.js → constants.ts} +0 -2
- package/src/metrics/{index.js → index.ts} +106 -74
- package/src/multistream/mediaRequestManager.ts +81 -15
- package/src/multistream/multistreamMedia.ts +5 -0
- package/src/multistream/receiveSlot.ts +18 -12
- package/src/multistream/receiveSlotManager.ts +23 -21
- package/src/multistream/remoteMedia.ts +15 -5
- package/src/multistream/remoteMediaGroup.ts +4 -3
- package/src/multistream/remoteMediaManager.ts +153 -37
- package/src/networkQualityMonitor/{index.js → index.ts} +37 -25
- package/src/personal-meeting-room/{index.js → index.ts} +28 -19
- package/src/personal-meeting-room/{request.js → request.ts} +13 -4
- package/src/personal-meeting-room/{util.js → util.ts} +4 -4
- package/src/reachability/{index.js → index.ts} +99 -83
- package/src/reachability/request.ts +39 -33
- package/src/reactions/constants.ts +4 -0
- package/src/reactions/reactions.ts +104 -0
- package/src/reactions/reactions.type.ts +62 -0
- package/src/reconnection-manager/{index.js → index.ts} +195 -102
- package/src/recording-controller/enums.ts +8 -0
- package/src/recording-controller/index.ts +315 -0
- package/src/recording-controller/util.ts +58 -0
- package/src/roap/{index.js → index.ts} +73 -56
- package/src/roap/request.ts +157 -0
- package/src/roap/turnDiscovery.ts +77 -37
- package/src/statsAnalyzer/{global.js → global.ts} +30 -33
- package/src/statsAnalyzer/{index.js → index.ts} +468 -192
- package/src/statsAnalyzer/mqaUtil.ts +290 -0
- package/src/transcription/{index.js → index.ts} +46 -39
- package/test/integration/spec/journey.js +664 -463
- package/test/integration/spec/space-meeting.js +320 -206
- package/test/integration/spec/transcription.js +7 -8
- package/test/unit/spec/breakouts/breakout.ts +119 -0
- package/test/unit/spec/breakouts/collection.ts +15 -0
- package/test/unit/spec/breakouts/index.ts +293 -0
- package/test/unit/spec/common/browser-detection.js +9 -28
- package/test/unit/spec/fixture/locus.js +92 -90
- package/test/unit/spec/locus-info/controlsUtils.js +25 -5
- package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
- package/test/unit/spec/locus-info/index.js +104 -2
- package/test/unit/spec/locus-info/infoUtils.js +41 -32
- package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +88 -430
- package/test/unit/spec/locus-info/lib/SeqCmp.json +513 -685
- package/test/unit/spec/locus-info/parser.js +3 -9
- package/test/unit/spec/locus-info/selfConstant.js +97 -103
- package/test/unit/spec/locus-info/selfUtils.js +105 -12
- package/test/unit/spec/media/index.ts +31 -47
- package/test/unit/spec/media/properties.ts +9 -9
- package/test/unit/spec/meeting/effectsState.js +39 -45
- package/test/unit/spec/meeting/in-meeting-actions.ts +5 -2
- package/test/unit/spec/meeting/index.js +2017 -742
- package/test/unit/spec/meeting/muteState.js +42 -33
- package/test/unit/spec/meeting/request.js +115 -44
- package/test/unit/spec/meeting/utils.js +104 -171
- package/test/unit/spec/meeting-info/meetinginfov2.js +100 -73
- package/test/unit/spec/meeting-info/request.js +7 -9
- package/test/unit/spec/meeting-info/util.js +11 -12
- package/test/unit/spec/meeting-info/utilv2.js +110 -74
- package/test/unit/spec/meetings/collection.js +1 -1
- package/test/unit/spec/meetings/index.js +439 -257
- package/test/unit/spec/meetings/utils.js +14 -12
- package/test/unit/spec/member/index.js +0 -1
- package/test/unit/spec/member/util.js +31 -7
- package/test/unit/spec/members/index.js +104 -54
- package/test/unit/spec/members/request.js +29 -20
- package/test/unit/spec/members/utils.js +8 -5
- package/test/unit/spec/metrics/index.js +16 -21
- package/test/unit/spec/multistream/mediaRequestManager.ts +316 -50
- package/test/unit/spec/multistream/receiveSlot.ts +6 -6
- package/test/unit/spec/multistream/receiveSlotManager.ts +13 -13
- package/test/unit/spec/multistream/remoteMedia.ts +10 -2
- package/test/unit/spec/multistream/remoteMediaGroup.ts +5 -5
- package/test/unit/spec/multistream/remoteMediaManager.ts +412 -65
- package/test/unit/spec/networkQualityMonitor/index.js +21 -15
- package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -7
- package/test/unit/spec/reachability/index.ts +58 -26
- package/test/unit/spec/reconnection-manager/index.js +102 -9
- package/test/unit/spec/recording-controller/index.js +231 -0
- package/test/unit/spec/recording-controller/util.js +102 -0
- package/test/unit/spec/roap/index.ts +2 -1
- package/test/unit/spec/roap/request.ts +114 -0
- package/test/unit/spec/roap/turnDiscovery.ts +64 -45
- package/test/unit/spec/stats-analyzer/index.js +27 -22
- package/test/utils/cmr.js +44 -42
- package/test/utils/testUtils.js +83 -74
- package/test/utils/webex-config.js +18 -18
- package/test/utils/webex-test-users.js +54 -50
- package/tsconfig.json +6 -0
- package/dist/media/internal-media-core-wrapper.js +0 -22
- package/dist/media/internal-media-core-wrapper.js.map +0 -1
- package/dist/peer-connection-manager/util.js +0 -124
- package/dist/peer-connection-manager/util.js.map +0 -1
- package/src/common/logs/logger-proxy.js +0 -33
- package/src/locus-info/controlsUtils.js +0 -102
- package/src/media/internal-media-core-wrapper.ts +0 -9
- package/src/meeting-info/meeting-info-v2.js +0 -255
- package/src/meetings/index.js +0 -1015
- package/src/peer-connection-manager/util.ts +0 -117
- package/src/roap/request.js +0 -127
- package/src/statsAnalyzer/mqaUtil.js +0 -173
- package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -389
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
LOCUSINFO,
|
|
23
23
|
PC_BAIL_TIMEOUT,
|
|
24
24
|
} from '@webex/plugin-meetings/src/constants';
|
|
25
|
-
import {
|
|
25
|
+
import {ConnectionState, Event, Errors, ErrorType, RemoteTrackType} from '@webex/internal-media-core';
|
|
26
26
|
import * as StatsAnalyzerModule from '@webex/plugin-meetings/src/statsAnalyzer';
|
|
27
27
|
import EventsScope from '@webex/plugin-meetings/src/common/events/events-scope';
|
|
28
28
|
import Meetings, {CONSTANTS} from '@webex/plugin-meetings';
|
|
@@ -36,6 +36,7 @@ import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
|
|
|
36
36
|
import Media from '@webex/plugin-meetings/src/media/index';
|
|
37
37
|
import ReconnectionManager from '@webex/plugin-meetings/src/reconnection-manager';
|
|
38
38
|
import MediaUtil from '@webex/plugin-meetings/src/media/util';
|
|
39
|
+
import RecordingUtil from '@webex/plugin-meetings/src/recording-controller/util';
|
|
39
40
|
import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
|
|
40
41
|
import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
|
|
41
42
|
import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
|
|
@@ -44,13 +45,18 @@ import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
|
44
45
|
import {trigger, eventType} from '@webex/plugin-meetings/src/metrics/config';
|
|
45
46
|
import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
|
|
46
47
|
import {IceGatheringFailed} from '@webex/plugin-meetings/src/common/errors/webex-errors';
|
|
48
|
+
import {MediaRequestManager} from '@webex/plugin-meetings/src/multistream/mediaRequestManager';
|
|
47
49
|
|
|
50
|
+
import LLM from '@webex/internal-plugin-llm';
|
|
51
|
+
import Mercury from '@webex/internal-plugin-mercury';
|
|
52
|
+
import Breakouts from '@webex/plugin-meetings/src/breakouts';
|
|
53
|
+
import {REACTION_RELAY_TYPES} from '../../../../src/reactions/constants';
|
|
48
54
|
import locus from '../fixture/locus';
|
|
49
55
|
import {
|
|
50
56
|
UserNotJoinedError,
|
|
51
57
|
MeetingNotActiveError,
|
|
52
58
|
UserInLobbyError,
|
|
53
|
-
NoMediaEstablishedYetError
|
|
59
|
+
NoMediaEstablishedYetError,
|
|
54
60
|
} from '../../../../src/common/errors/webex-errors';
|
|
55
61
|
import WebExMeetingsErrors from '../../../../src/common/errors/webex-meetings-error';
|
|
56
62
|
import ParameterError from '../../../../src/common/errors/parameter';
|
|
@@ -59,11 +65,12 @@ import CaptchaError from '../../../../src/common/errors/captcha-error';
|
|
|
59
65
|
import IntentToJoinError from '../../../../src/common/errors/intent-to-join';
|
|
60
66
|
import DefaultSDKConfig from '../../../../src/config';
|
|
61
67
|
import testUtils from '../../../utils/testUtils';
|
|
62
|
-
import {
|
|
68
|
+
import {
|
|
69
|
+
MeetingInfoV2CaptchaError,
|
|
70
|
+
MeetingInfoV2PasswordError,
|
|
71
|
+
} from '../../../../src/meeting-info/meeting-info-v2';
|
|
63
72
|
|
|
64
|
-
const {
|
|
65
|
-
getBrowserName
|
|
66
|
-
} = BrowserDetection();
|
|
73
|
+
const {getBrowserName} = BrowserDetection();
|
|
67
74
|
|
|
68
75
|
// Non-stubbed function
|
|
69
76
|
const {getDisplayMedia} = Media;
|
|
@@ -75,7 +82,7 @@ describe('plugin-meetings', () => {
|
|
|
75
82
|
error: () => {},
|
|
76
83
|
warn: () => {},
|
|
77
84
|
trace: () => {},
|
|
78
|
-
debug: () => {}
|
|
85
|
+
debug: () => {},
|
|
79
86
|
};
|
|
80
87
|
|
|
81
88
|
beforeEach(() => {
|
|
@@ -87,44 +94,48 @@ describe('plugin-meetings', () => {
|
|
|
87
94
|
|
|
88
95
|
before(() => {
|
|
89
96
|
const MediaStream = {
|
|
90
|
-
getVideoTracks: () => [
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
getVideoTracks: () => [
|
|
98
|
+
{
|
|
99
|
+
applyConstraints: () => {},
|
|
100
|
+
},
|
|
101
|
+
],
|
|
93
102
|
};
|
|
94
103
|
|
|
95
104
|
Object.defineProperty(global.window.navigator, 'mediaDevices', {
|
|
96
105
|
writable: true,
|
|
97
106
|
value: {
|
|
98
107
|
getDisplayMedia: sinon.stub().returns(Promise.resolve(MediaStream)),
|
|
99
|
-
enumerateDevices: sinon.stub().returns(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
108
|
+
enumerateDevices: sinon.stub().returns(
|
|
109
|
+
Promise.resolve([
|
|
110
|
+
{
|
|
111
|
+
deviceId: '',
|
|
112
|
+
kind: 'audioinput',
|
|
113
|
+
label: '',
|
|
114
|
+
groupId: '29d9339cc77bffdd24cb69ee80f6d3200481099bcd0f29267558672de0430777',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
deviceId: '',
|
|
118
|
+
kind: 'videoinput',
|
|
119
|
+
label: '',
|
|
120
|
+
groupId: '08d4f8200e7e4a3425ecf75b7edea9ae4acd934019f2a52217554bcc8e46604d',
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
deviceId: '',
|
|
124
|
+
kind: 'audiooutput',
|
|
125
|
+
label: '',
|
|
126
|
+
groupId: '29d9339cc77bffdd24cb69ee80f6d3200481099bcd0f29267558672de0430777',
|
|
127
|
+
},
|
|
128
|
+
])
|
|
129
|
+
),
|
|
119
130
|
getSupportedConstraints: sinon.stub().returns({
|
|
120
|
-
sampleRate: true
|
|
121
|
-
})
|
|
131
|
+
sampleRate: true,
|
|
132
|
+
}),
|
|
122
133
|
},
|
|
123
134
|
});
|
|
124
135
|
|
|
125
136
|
Object.defineProperty(global.window, 'MediaStream', {
|
|
126
137
|
writable: true,
|
|
127
|
-
value: MediaStream
|
|
138
|
+
value: MediaStream,
|
|
128
139
|
});
|
|
129
140
|
LoggerConfig.set({verboseEvents: true, enable: false});
|
|
130
141
|
LoggerProxy.set(logger);
|
|
@@ -149,32 +160,34 @@ describe('plugin-meetings', () => {
|
|
|
149
160
|
children: {
|
|
150
161
|
meetings: Meetings,
|
|
151
162
|
credentials: Credentials,
|
|
152
|
-
support: Support
|
|
163
|
+
support: Support,
|
|
164
|
+
llm: LLM,
|
|
165
|
+
mercury: Mercury,
|
|
153
166
|
},
|
|
154
167
|
config: {
|
|
155
168
|
credentials: {
|
|
156
|
-
client_id: 'mock-client-id'
|
|
169
|
+
client_id: 'mock-client-id',
|
|
157
170
|
},
|
|
158
171
|
meetings: {
|
|
159
172
|
reconnection: {
|
|
160
|
-
enabled: false
|
|
173
|
+
enabled: false,
|
|
161
174
|
},
|
|
162
175
|
mediaSettings: {},
|
|
163
176
|
metrics: {},
|
|
164
177
|
stats: {},
|
|
165
|
-
experimental: {enableUnifiedMeetings: true}
|
|
178
|
+
experimental: {enableUnifiedMeetings: true},
|
|
166
179
|
},
|
|
167
180
|
metrics: {
|
|
168
|
-
type: ['behavioral']
|
|
169
|
-
}
|
|
170
|
-
}
|
|
181
|
+
type: ['behavioral'],
|
|
182
|
+
},
|
|
183
|
+
},
|
|
171
184
|
});
|
|
172
185
|
|
|
173
186
|
webex.internal.support.submitLogs = sinon.stub().returns(Promise.resolve());
|
|
174
187
|
webex.credentials.getOrgId = sinon.stub().returns('fake-org-id');
|
|
175
188
|
webex.internal.metrics.submitClientMetrics = sinon.stub().returns(Promise.resolve());
|
|
176
189
|
webex.meetings.uploadLogs = sinon.stub().returns(Promise.resolve());
|
|
177
|
-
|
|
190
|
+
webex.internal.llm.on = sinon.stub();
|
|
178
191
|
|
|
179
192
|
TriggerProxy.trigger = sinon.stub().returns(true);
|
|
180
193
|
Metrics.postEvent = sinon.stub();
|
|
@@ -203,7 +216,7 @@ describe('plugin-meetings', () => {
|
|
|
203
216
|
destinationType: _MEETING_ID_,
|
|
204
217
|
},
|
|
205
218
|
{
|
|
206
|
-
parent: webex
|
|
219
|
+
parent: webex,
|
|
207
220
|
}
|
|
208
221
|
);
|
|
209
222
|
|
|
@@ -246,6 +259,13 @@ describe('plugin-meetings', () => {
|
|
|
246
259
|
assert.equal(meeting.meetingInfoFailureReason, undefined);
|
|
247
260
|
assert.equal(meeting.destination, testDestination);
|
|
248
261
|
assert.equal(meeting.destinationType, _MEETING_ID_);
|
|
262
|
+
assert.instanceOf(meeting.breakouts, Breakouts);
|
|
263
|
+
});
|
|
264
|
+
it('creates MediaRequestManager instances', () => {
|
|
265
|
+
assert.instanceOf(meeting.mediaRequestManagers.audio, MediaRequestManager);
|
|
266
|
+
assert.instanceOf(meeting.mediaRequestManagers.video, MediaRequestManager);
|
|
267
|
+
assert.instanceOf(meeting.mediaRequestManagers.screenShareAudio, MediaRequestManager);
|
|
268
|
+
assert.instanceOf(meeting.mediaRequestManagers.screenShareVideo, MediaRequestManager);
|
|
249
269
|
});
|
|
250
270
|
});
|
|
251
271
|
describe('#invite', () => {
|
|
@@ -432,7 +452,6 @@ describe('plugin-meetings', () => {
|
|
|
432
452
|
it('should return a promise resolution', async () => {
|
|
433
453
|
meeting.audio = {handleClientRequest};
|
|
434
454
|
|
|
435
|
-
|
|
436
455
|
const audio = meeting.unmuteAudio();
|
|
437
456
|
|
|
438
457
|
assert.exists(audio.then);
|
|
@@ -449,8 +468,8 @@ describe('plugin-meetings', () => {
|
|
|
449
468
|
readyState: 'live',
|
|
450
469
|
enabled: true,
|
|
451
470
|
getSettings: () => ({
|
|
452
|
-
sampleRate: 48000
|
|
453
|
-
})
|
|
471
|
+
sampleRate: 48000,
|
|
472
|
+
}),
|
|
454
473
|
});
|
|
455
474
|
|
|
456
475
|
beforeEach(() => {
|
|
@@ -458,7 +477,7 @@ describe('plugin-meetings', () => {
|
|
|
458
477
|
sinon.replace(meeting, 'addMedia', () => {
|
|
459
478
|
sinon.stub(meeting.mediaProperties, 'audioTrack').value(fakeMediaTrack());
|
|
460
479
|
sinon.stub(meeting.mediaProperties, 'mediaDirection').value({
|
|
461
|
-
receiveAudio: true
|
|
480
|
+
receiveAudio: true,
|
|
462
481
|
});
|
|
463
482
|
});
|
|
464
483
|
});
|
|
@@ -470,7 +489,7 @@ describe('plugin-meetings', () => {
|
|
|
470
489
|
describe('before audio attached to meeting', () => {
|
|
471
490
|
it('should throw no audio error', async () => {
|
|
472
491
|
await meeting.enableBNR().catch((err) => {
|
|
473
|
-
assert.equal(err.toString(),
|
|
492
|
+
assert.equal(err.toString(), "Error: Meeting doesn't have an audioTrack attached");
|
|
474
493
|
});
|
|
475
494
|
});
|
|
476
495
|
});
|
|
@@ -518,7 +537,7 @@ describe('plugin-meetings', () => {
|
|
|
518
537
|
|
|
519
538
|
it('should throw no audio error', async () => {
|
|
520
539
|
await meeting.disableBNR().catch((err) => {
|
|
521
|
-
assert.equal(err.toString(),
|
|
540
|
+
assert.equal(err.toString(), "Error: Meeting doesn't have an audioTrack attached");
|
|
522
541
|
});
|
|
523
542
|
});
|
|
524
543
|
});
|
|
@@ -650,7 +669,11 @@ describe('plugin-meetings', () => {
|
|
|
650
669
|
});
|
|
651
670
|
describe('#getMediaStreams', () => {
|
|
652
671
|
beforeEach(() => {
|
|
653
|
-
sinon
|
|
672
|
+
sinon
|
|
673
|
+
.stub(Media, 'getSupportedDevice')
|
|
674
|
+
.callsFake((options) =>
|
|
675
|
+
Promise.resolve({sendAudio: options.sendAudio, sendVideo: options.sendVideo})
|
|
676
|
+
);
|
|
654
677
|
sinon.stub(Media, 'getUserMedia').returns(Promise.resolve(['stream1', 'stream2']));
|
|
655
678
|
});
|
|
656
679
|
afterEach(() => {
|
|
@@ -674,17 +697,20 @@ describe('plugin-meetings', () => {
|
|
|
674
697
|
sinon.stub(meeting.mediaProperties, 'localQualityLevel').value('480p');
|
|
675
698
|
await meeting.getMediaStreams(mediaDirection, audioVideoSettings);
|
|
676
699
|
|
|
677
|
-
assert.calledWith(
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
700
|
+
assert.calledWith(
|
|
701
|
+
Media.getUserMedia,
|
|
702
|
+
{
|
|
703
|
+
...mediaDirection,
|
|
704
|
+
isSharing: false,
|
|
705
|
+
},
|
|
706
|
+
{
|
|
707
|
+
video: {
|
|
708
|
+
width: {max: 640, ideal: 640},
|
|
709
|
+
height: {max: 480, ideal: 480},
|
|
710
|
+
deviceId: videoDevice,
|
|
711
|
+
},
|
|
686
712
|
}
|
|
687
|
-
|
|
713
|
+
);
|
|
688
714
|
});
|
|
689
715
|
it('will set a new preferred video input device if passed in', async () => {
|
|
690
716
|
// if audioVideo settings parameter specifies a new video device it
|
|
@@ -709,23 +735,33 @@ describe('plugin-meetings', () => {
|
|
|
709
735
|
video: {
|
|
710
736
|
width: {
|
|
711
737
|
max: 400,
|
|
712
|
-
ideal: 400
|
|
738
|
+
ideal: 400,
|
|
713
739
|
},
|
|
714
740
|
height: {
|
|
715
741
|
max: 200,
|
|
716
|
-
ideal: 200
|
|
717
|
-
}
|
|
718
|
-
|
|
742
|
+
ideal: 200,
|
|
743
|
+
},
|
|
744
|
+
frameRate: {
|
|
745
|
+
ideal: 15,
|
|
746
|
+
max: 30,
|
|
747
|
+
},
|
|
748
|
+
facingMode: {
|
|
749
|
+
ideal: 'user',
|
|
750
|
+
},
|
|
751
|
+
},
|
|
719
752
|
};
|
|
720
753
|
|
|
721
754
|
sinon.stub(meeting.mediaProperties, 'localQualityLevel').value('200p');
|
|
722
755
|
await meeting.getMediaStreams(mediaDirection, customAudioVideoSettings);
|
|
723
756
|
|
|
724
|
-
assert.calledWith(
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
757
|
+
assert.calledWith(
|
|
758
|
+
Media.getUserMedia,
|
|
759
|
+
{
|
|
760
|
+
...mediaDirection,
|
|
761
|
+
isSharing: false,
|
|
762
|
+
},
|
|
763
|
+
customAudioVideoSettings
|
|
764
|
+
);
|
|
729
765
|
});
|
|
730
766
|
it('should not access camera if sendVideo is false ', async () => {
|
|
731
767
|
await meeting.getMediaStreams({sendAudio: true, sendVideo: false});
|
|
@@ -759,13 +795,12 @@ describe('plugin-meetings', () => {
|
|
|
759
795
|
});
|
|
760
796
|
});
|
|
761
797
|
|
|
762
|
-
it(
|
|
798
|
+
it("should throw error if request doesn't work", async () => {
|
|
763
799
|
meeting.request = sinon.stub().returns(Promise.reject());
|
|
764
800
|
|
|
765
801
|
try {
|
|
766
802
|
await meeting.receiveTranscription();
|
|
767
|
-
}
|
|
768
|
-
catch (err) {
|
|
803
|
+
} catch (err) {
|
|
769
804
|
assert(err, {});
|
|
770
805
|
}
|
|
771
806
|
});
|
|
@@ -773,15 +808,74 @@ describe('plugin-meetings', () => {
|
|
|
773
808
|
describe('#stopReceivingTranscription', () => {
|
|
774
809
|
it('should get invoked', () => {
|
|
775
810
|
meeting.transcription = {
|
|
776
|
-
closeSocket: sinon.stub()
|
|
811
|
+
closeSocket: sinon.stub(),
|
|
777
812
|
};
|
|
778
813
|
|
|
779
814
|
meeting.stopReceivingTranscription();
|
|
780
815
|
assert.calledOnce(meeting.transcription.closeSocket);
|
|
781
816
|
});
|
|
782
817
|
});
|
|
818
|
+
describe('#isReactionsSupported', () => {
|
|
819
|
+
it('should return false if the feature is not supported for the meeting', () => {
|
|
820
|
+
meeting.locusInfo.controls = {reactions: {enabled: false}};
|
|
821
|
+
|
|
822
|
+
assert.equal(meeting.isReactionsSupported(), false);
|
|
823
|
+
});
|
|
824
|
+
it('should return true if the feature is not supported for the meeting', () => {
|
|
825
|
+
meeting.locusInfo.controls = {reactions: {enabled: true}};
|
|
826
|
+
|
|
827
|
+
assert.equal(meeting.isReactionsSupported(), true);
|
|
828
|
+
});
|
|
829
|
+
});
|
|
830
|
+
describe('#processRelayEvent', () => {
|
|
831
|
+
it('should process a Reaction event type', () => {
|
|
832
|
+
meeting.isReactionsSupported = sinon.stub().returns(true);
|
|
833
|
+
meeting.config.receiveReactions = true;
|
|
834
|
+
const fakeSendersName = 'Fake reactors name';
|
|
835
|
+
meeting.members.membersCollection.get = sinon.stub().returns({name: fakeSendersName});
|
|
836
|
+
const fakeReactionPayload = {
|
|
837
|
+
type: 'fake_type',
|
|
838
|
+
codepoints: 'fake_codepoints',
|
|
839
|
+
shortcodes: 'fake_shortcodes',
|
|
840
|
+
tone: {
|
|
841
|
+
type: 'fake_tone_type',
|
|
842
|
+
codepoints: 'fake_tone_codepoints',
|
|
843
|
+
shortcodes: 'fake_tone_shortcodes',
|
|
844
|
+
},
|
|
845
|
+
};
|
|
846
|
+
const fakeSenderPayload = {
|
|
847
|
+
participantId: 'fake_participant_id',
|
|
848
|
+
};
|
|
849
|
+
const fakeProcessedReaction = {
|
|
850
|
+
reaction: fakeReactionPayload,
|
|
851
|
+
sender: {
|
|
852
|
+
id: fakeSenderPayload.participantId,
|
|
853
|
+
name: fakeSendersName,
|
|
854
|
+
},
|
|
855
|
+
};
|
|
856
|
+
const fakeRelayEvent = {
|
|
857
|
+
data: {
|
|
858
|
+
relayType: REACTION_RELAY_TYPES.REACTION,
|
|
859
|
+
reaction: fakeReactionPayload,
|
|
860
|
+
sender: fakeSenderPayload,
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
meeting.processRelayEvent(fakeRelayEvent);
|
|
864
|
+
assert.calledWith(
|
|
865
|
+
TriggerProxy.trigger,
|
|
866
|
+
sinon.match.instanceOf(Meeting),
|
|
867
|
+
{
|
|
868
|
+
file: 'meeting/index',
|
|
869
|
+
function: 'join',
|
|
870
|
+
},
|
|
871
|
+
EVENT_TRIGGERS.MEETING_RECEIVE_REACTIONS,
|
|
872
|
+
fakeProcessedReaction
|
|
873
|
+
);
|
|
874
|
+
})
|
|
875
|
+
})
|
|
783
876
|
describe('#join', () => {
|
|
784
877
|
let sandbox = null;
|
|
878
|
+
const joinMeetingResult = 'JOIN_MEETINGS_OPTION_RESULT';
|
|
785
879
|
|
|
786
880
|
beforeEach(() => {
|
|
787
881
|
sandbox = sinon.createSandbox();
|
|
@@ -799,22 +893,47 @@ describe('plugin-meetings', () => {
|
|
|
799
893
|
meeting.setCorrelationId = sinon.stub().returns(true);
|
|
800
894
|
meeting.setLocus = sinon.stub().returns(true);
|
|
801
895
|
webex.meetings.registered = true;
|
|
896
|
+
meeting.updateLLMConnection = sinon.stub();
|
|
802
897
|
});
|
|
803
898
|
describe('successful', () => {
|
|
804
899
|
beforeEach(() => {
|
|
805
|
-
sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve());
|
|
900
|
+
sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve(joinMeetingResult));
|
|
806
901
|
});
|
|
807
902
|
|
|
808
903
|
it('should join the meeting and return promise', async () => {
|
|
809
904
|
const join = meeting.join();
|
|
810
905
|
|
|
811
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
906
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
907
|
+
event: eventType.CALL_INITIATED,
|
|
908
|
+
data: {trigger: trigger.USER_INTERACTION, isRoapCallEnabled: true},
|
|
909
|
+
});
|
|
812
910
|
|
|
813
911
|
assert.exists(join.then);
|
|
814
|
-
await join;
|
|
912
|
+
const result = await join;
|
|
913
|
+
|
|
815
914
|
assert.calledOnce(MeetingUtil.joinMeeting);
|
|
816
915
|
assert.calledOnce(meeting.setLocus);
|
|
916
|
+
assert.equal(result, joinMeetingResult);
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
it('should call updateLLMConnection upon joining if config value is set', async () => {
|
|
920
|
+
meeting.config.enableAutomaticLLM = true;
|
|
921
|
+
meeting.webex.internal.llm.on = sinon.stub();
|
|
922
|
+
meeting.processRelayEvent = sinon.stub();
|
|
923
|
+
await meeting.join();
|
|
924
|
+
|
|
925
|
+
assert.calledOnce(meeting.updateLLMConnection);
|
|
926
|
+
assert.calledOnceWithExactly(meeting.webex.internal.llm.on, 'event:relay.event', meeting.processRelayEvent);
|
|
927
|
+
});
|
|
928
|
+
|
|
929
|
+
it('should not call updateLLMConnection upon joining if config value is not set', async () => {
|
|
930
|
+
meeting.webex.internal.llm.on = sinon.stub();
|
|
931
|
+
await meeting.join();
|
|
932
|
+
|
|
933
|
+
assert.notCalled(meeting.updateLLMConnection);
|
|
934
|
+
assert.notCalled(meeting.webex.internal.llm.on);
|
|
817
935
|
});
|
|
936
|
+
|
|
818
937
|
it('should invoke `receiveTranscription()` if receiveTranscription is set to true', async () => {
|
|
819
938
|
meeting.isTranscriptionSupported = sinon.stub().returns(true);
|
|
820
939
|
meeting.receiveTranscription = sinon.stub().returns(Promise.resolve());
|
|
@@ -856,8 +975,7 @@ describe('plugin-meetings', () => {
|
|
|
856
975
|
try {
|
|
857
976
|
await meeting.join();
|
|
858
977
|
joinSucceeded = true;
|
|
859
|
-
}
|
|
860
|
-
catch (e) {
|
|
978
|
+
} catch (e) {
|
|
861
979
|
assert.instanceOf(e, IntentToJoinError);
|
|
862
980
|
}
|
|
863
981
|
assert.isFalse(joinSucceeded);
|
|
@@ -905,7 +1023,7 @@ describe('plugin-meetings', () => {
|
|
|
905
1023
|
describe('#addMedia', () => {
|
|
906
1024
|
const muteStateStub = {
|
|
907
1025
|
handleClientRequest: sinon.stub().returns(Promise.resolve(true)),
|
|
908
|
-
applyClientStateLocally: sinon.stub().returns(Promise.resolve(true))
|
|
1026
|
+
applyClientStateLocally: sinon.stub().returns(Promise.resolve(true)),
|
|
909
1027
|
};
|
|
910
1028
|
|
|
911
1029
|
let fakeMediaConnection;
|
|
@@ -913,7 +1031,7 @@ describe('plugin-meetings', () => {
|
|
|
913
1031
|
beforeEach(() => {
|
|
914
1032
|
fakeMediaConnection = {
|
|
915
1033
|
close: sinon.stub(),
|
|
916
|
-
getConnectionState: sinon.stub().returns(
|
|
1034
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
917
1035
|
initiateOffer: sinon.stub().resolves({}),
|
|
918
1036
|
on: sinon.stub(),
|
|
919
1037
|
};
|
|
@@ -926,7 +1044,9 @@ describe('plugin-meetings', () => {
|
|
|
926
1044
|
meeting.setMercuryListener = sinon.stub().returns(true);
|
|
927
1045
|
meeting.setupMediaConnectionListeners = sinon.stub();
|
|
928
1046
|
meeting.setMercuryListener = sinon.stub();
|
|
929
|
-
meeting.roap.doTurnDiscovery = sinon
|
|
1047
|
+
meeting.roap.doTurnDiscovery = sinon
|
|
1048
|
+
.stub()
|
|
1049
|
+
.resolves({turnServerInfo: {}, turnDiscoverySkippedReason: undefined});
|
|
930
1050
|
});
|
|
931
1051
|
|
|
932
1052
|
it('should have #addMedia', () => {
|
|
@@ -955,8 +1075,7 @@ describe('plugin-meetings', () => {
|
|
|
955
1075
|
try {
|
|
956
1076
|
await meeting.addMedia();
|
|
957
1077
|
assert.fail('addMedia should have thrown an exception.');
|
|
958
|
-
}
|
|
959
|
-
catch (err) {
|
|
1078
|
+
} catch (err) {
|
|
960
1079
|
assert.instanceOf(err, UserInLobbyError);
|
|
961
1080
|
}
|
|
962
1081
|
});
|
|
@@ -974,37 +1093,33 @@ describe('plugin-meetings', () => {
|
|
|
974
1093
|
|
|
975
1094
|
assert.isNull(meeting.statsAnalyzer);
|
|
976
1095
|
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
977
|
-
assert.calledWith(
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
turnServerUsed: true
|
|
987
|
-
}
|
|
988
|
-
);
|
|
1096
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE, {
|
|
1097
|
+
correlation_id: meeting.correlationId,
|
|
1098
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1099
|
+
reason: error.message,
|
|
1100
|
+
stack: error.stack,
|
|
1101
|
+
code: error.code,
|
|
1102
|
+
turnDiscoverySkippedReason: undefined,
|
|
1103
|
+
turnServerUsed: true,
|
|
1104
|
+
});
|
|
989
1105
|
});
|
|
990
1106
|
|
|
991
1107
|
it('checks metrics called with skipped reason config', async () => {
|
|
992
|
-
meeting.roap.doTurnDiscovery = sinon
|
|
1108
|
+
meeting.roap.doTurnDiscovery = sinon
|
|
1109
|
+
.stub()
|
|
1110
|
+
.resolves({turnServerInfo: undefined, turnDiscoverySkippedReason: 'config'});
|
|
993
1111
|
meeting.meetingState = 'ACTIVE';
|
|
994
1112
|
await meeting.addMedia().catch((err) => {
|
|
995
1113
|
assert.exists(err);
|
|
996
1114
|
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
997
|
-
assert.calledWith(
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
turnServerUsed: false
|
|
1006
|
-
}
|
|
1007
|
-
);
|
|
1115
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE, {
|
|
1116
|
+
correlation_id: meeting.correlationId,
|
|
1117
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1118
|
+
reason: err.message,
|
|
1119
|
+
stack: err.stack,
|
|
1120
|
+
turnDiscoverySkippedReason: 'config',
|
|
1121
|
+
turnServerUsed: false,
|
|
1122
|
+
});
|
|
1008
1123
|
});
|
|
1009
1124
|
});
|
|
1010
1125
|
|
|
@@ -1023,12 +1138,13 @@ describe('plugin-meetings', () => {
|
|
|
1023
1138
|
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
1024
1139
|
assert.calledWith(
|
|
1025
1140
|
Metrics.sendBehavioralMetric,
|
|
1026
|
-
BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE,
|
|
1141
|
+
BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE,
|
|
1142
|
+
sinon.match({
|
|
1027
1143
|
correlation_id: meeting.correlationId,
|
|
1028
1144
|
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1029
1145
|
reason: result.message,
|
|
1030
1146
|
turnDiscoverySkippedReason: undefined,
|
|
1031
|
-
turnServerUsed: true
|
|
1147
|
+
turnServerUsed: true,
|
|
1032
1148
|
})
|
|
1033
1149
|
);
|
|
1034
1150
|
});
|
|
@@ -1049,10 +1165,9 @@ describe('plugin-meetings', () => {
|
|
|
1049
1165
|
|
|
1050
1166
|
try {
|
|
1051
1167
|
await meeting.addMedia({
|
|
1052
|
-
mediaSettings: {}
|
|
1168
|
+
mediaSettings: {},
|
|
1053
1169
|
});
|
|
1054
|
-
}
|
|
1055
|
-
catch (err) {
|
|
1170
|
+
} catch (err) {
|
|
1056
1171
|
assert.fail('should not throw an error');
|
|
1057
1172
|
}
|
|
1058
1173
|
});
|
|
@@ -1092,11 +1207,13 @@ describe('plugin-meetings', () => {
|
|
|
1092
1207
|
});
|
|
1093
1208
|
|
|
1094
1209
|
it('should attach the media and return promise', async () => {
|
|
1095
|
-
meeting.roap.doTurnDiscovery = sinon
|
|
1210
|
+
meeting.roap.doTurnDiscovery = sinon
|
|
1211
|
+
.stub()
|
|
1212
|
+
.resolves({turnServerInfo: undefined, turnDiscoverySkippedReason: undefined});
|
|
1096
1213
|
|
|
1097
1214
|
meeting.meetingState = 'ACTIVE';
|
|
1098
1215
|
const media = meeting.addMedia({
|
|
1099
|
-
mediaSettings: {}
|
|
1216
|
+
mediaSettings: {},
|
|
1100
1217
|
});
|
|
1101
1218
|
|
|
1102
1219
|
assert.exists(media);
|
|
@@ -1105,12 +1222,17 @@ describe('plugin-meetings', () => {
|
|
|
1105
1222
|
assert.calledWith(meeting.roap.doTurnDiscovery, meeting, false);
|
|
1106
1223
|
assert.calledOnce(meeting.mediaProperties.setMediaDirection);
|
|
1107
1224
|
assert.calledOnce(Media.createMediaConnection);
|
|
1108
|
-
assert.calledWith(
|
|
1225
|
+
assert.calledWith(
|
|
1226
|
+
Media.createMediaConnection,
|
|
1227
|
+
false,
|
|
1228
|
+
meeting.getMediaConnectionDebugId(),
|
|
1229
|
+
sinon.match({turnServerInfo: undefined})
|
|
1230
|
+
);
|
|
1109
1231
|
assert.calledOnce(meeting.setMercuryListener);
|
|
1110
1232
|
assert.calledOnce(fakeMediaConnection.initiateOffer);
|
|
1111
1233
|
/* statsAnalyzer is initiated inside of addMedia so there isn't
|
|
1112
|
-
|
|
1113
|
-
|
|
1234
|
+
* a good way to mock it without mocking the constructor
|
|
1235
|
+
*/
|
|
1114
1236
|
});
|
|
1115
1237
|
|
|
1116
1238
|
it('should pass the turn server info to the peer connection', async () => {
|
|
@@ -1121,17 +1243,16 @@ describe('plugin-meetings', () => {
|
|
|
1121
1243
|
meeting.meetingState = 'ACTIVE';
|
|
1122
1244
|
Media.createMediaConnection.resetHistory();
|
|
1123
1245
|
|
|
1124
|
-
|
|
1125
1246
|
meeting.roap.doTurnDiscovery = sinon.stub().resolves({
|
|
1126
1247
|
turnServerInfo: {
|
|
1127
1248
|
url: FAKE_TURN_URL,
|
|
1128
1249
|
username: FAKE_TURN_USER,
|
|
1129
|
-
password: FAKE_TURN_PASSWORD
|
|
1250
|
+
password: FAKE_TURN_PASSWORD,
|
|
1130
1251
|
},
|
|
1131
|
-
turnServerSkippedReason: undefined
|
|
1252
|
+
turnServerSkippedReason: undefined,
|
|
1132
1253
|
});
|
|
1133
1254
|
const media = meeting.addMedia({
|
|
1134
|
-
mediaSettings: {}
|
|
1255
|
+
mediaSettings: {},
|
|
1135
1256
|
});
|
|
1136
1257
|
|
|
1137
1258
|
assert.exists(media);
|
|
@@ -1139,25 +1260,35 @@ describe('plugin-meetings', () => {
|
|
|
1139
1260
|
assert.calledOnce(meeting.roap.doTurnDiscovery);
|
|
1140
1261
|
assert.calledWith(meeting.roap.doTurnDiscovery, meeting, false);
|
|
1141
1262
|
assert.calledOnce(Media.createMediaConnection);
|
|
1142
|
-
assert.calledWith(
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1263
|
+
assert.calledWith(
|
|
1264
|
+
Media.createMediaConnection,
|
|
1265
|
+
false,
|
|
1266
|
+
meeting.getMediaConnectionDebugId(),
|
|
1267
|
+
sinon.match({
|
|
1268
|
+
turnServerInfo: {
|
|
1269
|
+
url: FAKE_TURN_URL,
|
|
1270
|
+
username: FAKE_TURN_USER,
|
|
1271
|
+
password: FAKE_TURN_PASSWORD,
|
|
1272
|
+
},
|
|
1273
|
+
})
|
|
1274
|
+
);
|
|
1149
1275
|
assert.calledOnce(fakeMediaConnection.initiateOffer);
|
|
1150
1276
|
});
|
|
1151
1277
|
|
|
1152
1278
|
it('should attach the media and return WebExMeetingsErrors when connection does not reach CONNECTED state', async () => {
|
|
1153
1279
|
meeting.meetingState = 'ACTIVE';
|
|
1154
|
-
fakeMediaConnection.getConnectionState = sinon
|
|
1280
|
+
fakeMediaConnection.getConnectionState = sinon
|
|
1281
|
+
.stub()
|
|
1282
|
+
.returns(ConnectionState.Connecting);
|
|
1155
1283
|
const clock = sinon.useFakeTimers();
|
|
1156
1284
|
const media = meeting.addMedia({
|
|
1157
|
-
mediaSettings: {}
|
|
1285
|
+
mediaSettings: {},
|
|
1158
1286
|
});
|
|
1159
1287
|
|
|
1160
|
-
await clock.tickAsync(
|
|
1288
|
+
await clock.tickAsync(
|
|
1289
|
+
4000 /* meetingState timer, hardcoded inside addMedia */ +
|
|
1290
|
+
PC_BAIL_TIMEOUT /* connection state timer */
|
|
1291
|
+
);
|
|
1161
1292
|
await testUtils.flushPromises();
|
|
1162
1293
|
|
|
1163
1294
|
assert.exists(media);
|
|
@@ -1174,9 +1305,10 @@ describe('plugin-meetings', () => {
|
|
|
1174
1305
|
|
|
1175
1306
|
let errorThrown = false;
|
|
1176
1307
|
|
|
1177
|
-
await meeting
|
|
1178
|
-
|
|
1179
|
-
|
|
1308
|
+
await meeting
|
|
1309
|
+
.addMedia({
|
|
1310
|
+
mediaSettings: {},
|
|
1311
|
+
})
|
|
1180
1312
|
.catch((error) => {
|
|
1181
1313
|
assert.equal(error.code, IceGatheringFailed.CODE);
|
|
1182
1314
|
errorThrown = true;
|
|
@@ -1188,19 +1320,15 @@ describe('plugin-meetings', () => {
|
|
|
1188
1320
|
it('should send ADD_MEDIA_SUCCESS metrics', async () => {
|
|
1189
1321
|
meeting.meetingState = 'ACTIVE';
|
|
1190
1322
|
await meeting.addMedia({
|
|
1191
|
-
mediaSettings: {}
|
|
1323
|
+
mediaSettings: {},
|
|
1192
1324
|
});
|
|
1193
1325
|
|
|
1194
1326
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
1195
|
-
assert.calledWith(
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1201
|
-
connectionType: 'udp'
|
|
1202
|
-
}
|
|
1203
|
-
);
|
|
1327
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS, {
|
|
1328
|
+
correlation_id: meeting.correlationId,
|
|
1329
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1330
|
+
connectionType: 'udp',
|
|
1331
|
+
});
|
|
1204
1332
|
});
|
|
1205
1333
|
|
|
1206
1334
|
describe('handles StatsAnalyzer events', () => {
|
|
@@ -1218,7 +1346,7 @@ describe('plugin-meetings', () => {
|
|
|
1218
1346
|
sinon.stub(StatsAnalyzerModule, 'StatsAnalyzer').returns(statsAnalyzerStub);
|
|
1219
1347
|
|
|
1220
1348
|
await meeting.addMedia({
|
|
1221
|
-
mediaSettings: {}
|
|
1349
|
+
mediaSettings: {},
|
|
1222
1350
|
});
|
|
1223
1351
|
});
|
|
1224
1352
|
|
|
@@ -1227,51 +1355,79 @@ describe('plugin-meetings', () => {
|
|
|
1227
1355
|
});
|
|
1228
1356
|
|
|
1229
1357
|
it('LOCAL_MEDIA_STARTED triggers "meeting:media:local:start" event and sends metrics', async () => {
|
|
1230
|
-
statsAnalyzerStub.emit(
|
|
1358
|
+
statsAnalyzerStub.emit(
|
|
1359
|
+
{file: 'test', function: 'test'},
|
|
1360
|
+
StatsAnalyzerModule.EVENTS.LOCAL_MEDIA_STARTED,
|
|
1361
|
+
{type: 'audio'}
|
|
1362
|
+
);
|
|
1231
1363
|
|
|
1232
1364
|
assert.calledWith(
|
|
1233
1365
|
TriggerProxy.trigger,
|
|
1234
1366
|
sinon.match.instanceOf(Meeting),
|
|
1235
1367
|
{
|
|
1236
1368
|
file: 'meeting/index',
|
|
1237
|
-
function: 'addMedia'
|
|
1369
|
+
function: 'addMedia',
|
|
1238
1370
|
},
|
|
1239
1371
|
EVENT_TRIGGERS.MEETING_MEDIA_LOCAL_STARTED,
|
|
1240
1372
|
{
|
|
1241
|
-
type: 'audio'
|
|
1373
|
+
type: 'audio',
|
|
1242
1374
|
}
|
|
1243
1375
|
);
|
|
1244
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
1376
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
1377
|
+
event: eventType.SENDING_MEDIA_START,
|
|
1378
|
+
data: {mediaType: 'audio'},
|
|
1379
|
+
});
|
|
1245
1380
|
});
|
|
1246
1381
|
|
|
1247
1382
|
it('LOCAL_MEDIA_STOPPED triggers the right metrics', async () => {
|
|
1248
|
-
statsAnalyzerStub.emit(
|
|
1383
|
+
statsAnalyzerStub.emit(
|
|
1384
|
+
{file: 'test', function: 'test'},
|
|
1385
|
+
StatsAnalyzerModule.EVENTS.LOCAL_MEDIA_STOPPED,
|
|
1386
|
+
{type: 'video'}
|
|
1387
|
+
);
|
|
1249
1388
|
|
|
1250
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
1389
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
1390
|
+
event: eventType.SENDING_MEDIA_STOP,
|
|
1391
|
+
data: {mediaType: 'video'},
|
|
1392
|
+
});
|
|
1251
1393
|
});
|
|
1252
1394
|
|
|
1253
1395
|
it('REMOTE_MEDIA_STARTED triggers "meeting:media:remote:start" event and sends metrics', async () => {
|
|
1254
|
-
statsAnalyzerStub.emit(
|
|
1396
|
+
statsAnalyzerStub.emit(
|
|
1397
|
+
{file: 'test', function: 'test'},
|
|
1398
|
+
StatsAnalyzerModule.EVENTS.REMOTE_MEDIA_STARTED,
|
|
1399
|
+
{type: 'video'}
|
|
1400
|
+
);
|
|
1255
1401
|
|
|
1256
1402
|
assert.calledWith(
|
|
1257
1403
|
TriggerProxy.trigger,
|
|
1258
1404
|
sinon.match.instanceOf(Meeting),
|
|
1259
1405
|
{
|
|
1260
1406
|
file: 'meeting/index',
|
|
1261
|
-
function: 'addMedia'
|
|
1407
|
+
function: 'addMedia',
|
|
1262
1408
|
},
|
|
1263
1409
|
EVENT_TRIGGERS.MEETING_MEDIA_REMOTE_STARTED,
|
|
1264
1410
|
{
|
|
1265
|
-
type: 'video'
|
|
1411
|
+
type: 'video',
|
|
1266
1412
|
}
|
|
1267
1413
|
);
|
|
1268
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
1414
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
1415
|
+
event: eventType.RECEIVING_MEDIA_START,
|
|
1416
|
+
data: {mediaType: 'video'},
|
|
1417
|
+
});
|
|
1269
1418
|
});
|
|
1270
1419
|
|
|
1271
1420
|
it('REMOTE_MEDIA_STOPPED triggers the right metrics', async () => {
|
|
1272
|
-
statsAnalyzerStub.emit(
|
|
1421
|
+
statsAnalyzerStub.emit(
|
|
1422
|
+
{file: 'test', function: 'test'},
|
|
1423
|
+
StatsAnalyzerModule.EVENTS.REMOTE_MEDIA_STOPPED,
|
|
1424
|
+
{type: 'audio'}
|
|
1425
|
+
);
|
|
1273
1426
|
|
|
1274
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
1427
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
1428
|
+
event: eventType.RECEIVING_MEDIA_STOP,
|
|
1429
|
+
data: {mediaType: 'audio'},
|
|
1430
|
+
});
|
|
1275
1431
|
});
|
|
1276
1432
|
|
|
1277
1433
|
it('MEDIA_QUALITY triggers the right metrics', async () => {
|
|
@@ -1283,7 +1439,10 @@ describe('plugin-meetings', () => {
|
|
|
1283
1439
|
{data: fakeData, networkType: 'wifi'}
|
|
1284
1440
|
);
|
|
1285
1441
|
|
|
1286
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
1442
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
1443
|
+
event: eventType.MEDIA_QUALITY,
|
|
1444
|
+
data: {intervalData: fakeData, networkType: 'wifi'},
|
|
1445
|
+
});
|
|
1287
1446
|
});
|
|
1288
1447
|
});
|
|
1289
1448
|
});
|
|
@@ -1346,7 +1505,9 @@ describe('plugin-meetings', () => {
|
|
|
1346
1505
|
sandbox = sinon.createSandbox();
|
|
1347
1506
|
meeting.meetingFiniteStateMachine.ring();
|
|
1348
1507
|
meeting.meetingFiniteStateMachine.join();
|
|
1349
|
-
meeting.meetingRequest.leaveMeeting = sinon
|
|
1508
|
+
meeting.meetingRequest.leaveMeeting = sinon
|
|
1509
|
+
.stub()
|
|
1510
|
+
.returns(Promise.resolve({body: 'test'}));
|
|
1350
1511
|
meeting.locusInfo.onFullLocus = sinon.stub().returns(true);
|
|
1351
1512
|
// the 3 need to be promises because we do closeLocalStream.then(closeLocalShare.then) etc in the src code
|
|
1352
1513
|
meeting.closeLocalStream = sinon.stub().returns(Promise.resolve());
|
|
@@ -1361,6 +1522,7 @@ describe('plugin-meetings', () => {
|
|
|
1361
1522
|
meeting.unsetRemoteStream = sinon.stub().returns(true);
|
|
1362
1523
|
meeting.unsetPeerConnections = sinon.stub().returns(true);
|
|
1363
1524
|
meeting.logger.error = sinon.stub().returns(true);
|
|
1525
|
+
meeting.updateLLMConnection = sinon.stub().returns(Promise.resolve());
|
|
1364
1526
|
|
|
1365
1527
|
// A meeting needs to be joined to leave
|
|
1366
1528
|
meeting.meetingState = 'ACTIVE';
|
|
@@ -1415,7 +1577,7 @@ describe('plugin-meetings', () => {
|
|
|
1415
1577
|
correlationId: meeting.correlationId,
|
|
1416
1578
|
selfId: meeting.selfId,
|
|
1417
1579
|
resourceId: null,
|
|
1418
|
-
deviceUrl: meeting.deviceUrl
|
|
1580
|
+
deviceUrl: meeting.deviceUrl,
|
|
1419
1581
|
});
|
|
1420
1582
|
});
|
|
1421
1583
|
it('should leave the meeting on the resource', async () => {
|
|
@@ -1428,13 +1590,13 @@ describe('plugin-meetings', () => {
|
|
|
1428
1590
|
correlationId: meeting.correlationId,
|
|
1429
1591
|
selfId: meeting.selfId,
|
|
1430
1592
|
resourceId: meeting.resourceId,
|
|
1431
|
-
deviceUrl: meeting.deviceUrl
|
|
1593
|
+
deviceUrl: meeting.deviceUrl,
|
|
1432
1594
|
});
|
|
1433
1595
|
});
|
|
1434
1596
|
});
|
|
1435
|
-
describe('#
|
|
1436
|
-
it('should have #
|
|
1437
|
-
assert.exists(meeting.
|
|
1597
|
+
describe('#requestScreenShareFloor', () => {
|
|
1598
|
+
it('should have #requestScreenShareFloor', () => {
|
|
1599
|
+
assert.exists(meeting.requestScreenShareFloor);
|
|
1438
1600
|
});
|
|
1439
1601
|
beforeEach(() => {
|
|
1440
1602
|
meeting.locusInfo.mediaShares = [{name: 'content', url: url1}];
|
|
@@ -1442,7 +1604,7 @@ describe('plugin-meetings', () => {
|
|
|
1442
1604
|
meeting.meetingRequest.changeMeetingFloor = sinon.stub().returns(Promise.resolve());
|
|
1443
1605
|
});
|
|
1444
1606
|
it('should send the share', async () => {
|
|
1445
|
-
const share = meeting.
|
|
1607
|
+
const share = meeting.requestScreenShareFloor();
|
|
1446
1608
|
|
|
1447
1609
|
assert.exists(share.then);
|
|
1448
1610
|
await share;
|
|
@@ -1455,7 +1617,9 @@ describe('plugin-meetings', () => {
|
|
|
1455
1617
|
|
|
1456
1618
|
beforeEach(() => {
|
|
1457
1619
|
_mediaDirection = meeting.mediaProperties.mediaDirection || {};
|
|
1458
|
-
sinon
|
|
1620
|
+
sinon
|
|
1621
|
+
.stub(meeting.mediaProperties, 'mediaDirection')
|
|
1622
|
+
.value({sendAudio: true, sendVideo: true, sendShare: false});
|
|
1459
1623
|
});
|
|
1460
1624
|
|
|
1461
1625
|
afterEach(() => {
|
|
@@ -1492,7 +1656,11 @@ describe('plugin-meetings', () => {
|
|
|
1492
1656
|
it('properly assigns default values', async () => {
|
|
1493
1657
|
await meeting.shareScreen({sharePreferences: {highFrameRate: true}});
|
|
1494
1658
|
|
|
1495
|
-
assert.calledWith(Media.getDisplayMedia, {
|
|
1659
|
+
assert.calledWith(Media.getDisplayMedia, {
|
|
1660
|
+
sendShare: true,
|
|
1661
|
+
sendAudio: false,
|
|
1662
|
+
sharePreferences: {highFrameRate: true},
|
|
1663
|
+
});
|
|
1496
1664
|
});
|
|
1497
1665
|
});
|
|
1498
1666
|
|
|
@@ -1522,18 +1690,17 @@ describe('plugin-meetings', () => {
|
|
|
1522
1690
|
sendShare,
|
|
1523
1691
|
receiveShare,
|
|
1524
1692
|
stream,
|
|
1525
|
-
skipSignalingCheck: true
|
|
1693
|
+
skipSignalingCheck: true,
|
|
1526
1694
|
});
|
|
1527
1695
|
|
|
1528
1696
|
assert.notCalled(meeting.canUpdateMedia);
|
|
1529
1697
|
});
|
|
1530
1698
|
|
|
1531
|
-
|
|
1532
1699
|
it('skips canUpdateMedia() check on contentTracks.onended', () => {
|
|
1533
1700
|
const {mediaProperties} = meeting;
|
|
1534
1701
|
const fakeTrack = {
|
|
1535
1702
|
getSettings: sinon.stub().returns({}),
|
|
1536
|
-
onended: sinon.stub()
|
|
1703
|
+
onended: sinon.stub(),
|
|
1537
1704
|
};
|
|
1538
1705
|
|
|
1539
1706
|
sandbox.stub(mediaProperties, 'setLocalShareTrack');
|
|
@@ -1547,12 +1714,11 @@ describe('plugin-meetings', () => {
|
|
|
1547
1714
|
assert.calledWith(meeting.stopShare, {skipSignalingCheck: true});
|
|
1548
1715
|
});
|
|
1549
1716
|
|
|
1550
|
-
|
|
1551
1717
|
it('stopShare accepts and passes along optional parameters', () => {
|
|
1552
1718
|
const args = {
|
|
1553
1719
|
abc: 123,
|
|
1554
1720
|
receiveShare: false,
|
|
1555
|
-
sendShare: false
|
|
1721
|
+
sendShare: false,
|
|
1556
1722
|
};
|
|
1557
1723
|
|
|
1558
1724
|
sandbox.stub(meeting, 'updateShare').returns(Promise.resolve());
|
|
@@ -1589,12 +1755,12 @@ describe('plugin-meetings', () => {
|
|
|
1589
1755
|
sinon.match.instanceOf(Meeting),
|
|
1590
1756
|
{
|
|
1591
1757
|
file: 'meeting/index',
|
|
1592
|
-
function: 'handleShareTrackEnded'
|
|
1758
|
+
function: 'handleShareTrackEnded',
|
|
1593
1759
|
},
|
|
1594
1760
|
EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
1595
1761
|
{
|
|
1596
1762
|
stream,
|
|
1597
|
-
type: EVENT_TYPES.LOCAL_SHARE
|
|
1763
|
+
type: EVENT_TYPES.LOCAL_SHARE,
|
|
1598
1764
|
}
|
|
1599
1765
|
);
|
|
1600
1766
|
});
|
|
@@ -1607,20 +1773,22 @@ describe('plugin-meetings', () => {
|
|
|
1607
1773
|
const {resolution} = config;
|
|
1608
1774
|
const shareOptions = {
|
|
1609
1775
|
sendShare: true,
|
|
1610
|
-
sendAudio: false
|
|
1776
|
+
sendAudio: false,
|
|
1611
1777
|
};
|
|
1612
1778
|
const fireFoxOptions = {
|
|
1613
1779
|
audio: false,
|
|
1614
1780
|
video: {
|
|
1615
1781
|
audio: shareOptions.sendAudio,
|
|
1616
|
-
video: shareOptions.sendShare
|
|
1617
|
-
}
|
|
1782
|
+
video: shareOptions.sendShare,
|
|
1783
|
+
},
|
|
1618
1784
|
};
|
|
1619
1785
|
|
|
1620
1786
|
const MediaStream = {
|
|
1621
|
-
getVideoTracks: () => [
|
|
1622
|
-
|
|
1623
|
-
|
|
1787
|
+
getVideoTracks: () => [
|
|
1788
|
+
{
|
|
1789
|
+
applyConstraints: () => {},
|
|
1790
|
+
},
|
|
1791
|
+
],
|
|
1624
1792
|
};
|
|
1625
1793
|
|
|
1626
1794
|
const MediaConstraint = {
|
|
@@ -1628,7 +1796,7 @@ describe('plugin-meetings', () => {
|
|
|
1628
1796
|
aspectRatio: config.aspectRatio,
|
|
1629
1797
|
frameRate: config.screenFrameRate,
|
|
1630
1798
|
width: null,
|
|
1631
|
-
height: null
|
|
1799
|
+
height: null,
|
|
1632
1800
|
};
|
|
1633
1801
|
|
|
1634
1802
|
const browserConditionalValue = (value) => {
|
|
@@ -1644,31 +1812,23 @@ describe('plugin-meetings', () => {
|
|
|
1644
1812
|
if (!global.navigator) {
|
|
1645
1813
|
global.navigator = {
|
|
1646
1814
|
mediaDevices: {
|
|
1647
|
-
getDisplayMedia: null
|
|
1648
|
-
}
|
|
1815
|
+
getDisplayMedia: null,
|
|
1816
|
+
},
|
|
1649
1817
|
};
|
|
1650
1818
|
}
|
|
1651
1819
|
_getDisplayMedia = global.navigator.mediaDevices.getDisplayMedia;
|
|
1652
|
-
Object.defineProperty(
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
value: sinon.stub().returns(Promise.resolve(MediaStream)),
|
|
1657
|
-
writable: true
|
|
1658
|
-
}
|
|
1659
|
-
);
|
|
1820
|
+
Object.defineProperty(global.navigator.mediaDevices, 'getDisplayMedia', {
|
|
1821
|
+
value: sinon.stub().returns(Promise.resolve(MediaStream)),
|
|
1822
|
+
writable: true,
|
|
1823
|
+
});
|
|
1660
1824
|
});
|
|
1661
1825
|
|
|
1662
1826
|
after(() => {
|
|
1663
1827
|
// clean up for browser
|
|
1664
|
-
Object.defineProperty(
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
value: _getDisplayMedia,
|
|
1669
|
-
writable: true
|
|
1670
|
-
}
|
|
1671
|
-
);
|
|
1828
|
+
Object.defineProperty(global.navigator.mediaDevices, 'getDisplayMedia', {
|
|
1829
|
+
value: _getDisplayMedia,
|
|
1830
|
+
writable: true,
|
|
1831
|
+
});
|
|
1672
1832
|
});
|
|
1673
1833
|
|
|
1674
1834
|
// eslint-disable-next-line max-len
|
|
@@ -1680,39 +1840,48 @@ describe('plugin-meetings', () => {
|
|
|
1680
1840
|
maxWidth: SHARE_WIDTH,
|
|
1681
1841
|
maxHeight: SHARE_HEIGHT,
|
|
1682
1842
|
idealWidth: SHARE_WIDTH,
|
|
1683
|
-
idealHeight: SHARE_HEIGHT
|
|
1843
|
+
idealHeight: SHARE_HEIGHT,
|
|
1684
1844
|
};
|
|
1685
1845
|
|
|
1686
1846
|
// If sharePreferences.shareConstraints is defined it ignores
|
|
1687
1847
|
// default SDK config settings
|
|
1688
|
-
getDisplayMedia(
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1848
|
+
getDisplayMedia(
|
|
1849
|
+
{
|
|
1850
|
+
...shareOptions,
|
|
1851
|
+
sharePreferences: {shareConstraints},
|
|
1852
|
+
},
|
|
1853
|
+
config
|
|
1854
|
+
);
|
|
1692
1855
|
|
|
1693
1856
|
// eslint-disable-next-line no-undef
|
|
1694
|
-
assert.calledWith(
|
|
1857
|
+
assert.calledWith(
|
|
1858
|
+
navigator.mediaDevices.getDisplayMedia,
|
|
1695
1859
|
browserConditionalValue({
|
|
1696
1860
|
default: {
|
|
1697
|
-
video: {...shareConstraints}
|
|
1861
|
+
video: {...shareConstraints},
|
|
1698
1862
|
},
|
|
1699
1863
|
// Firefox is being handled differently
|
|
1700
|
-
firefox: fireFoxOptions
|
|
1701
|
-
})
|
|
1864
|
+
firefox: fireFoxOptions,
|
|
1865
|
+
})
|
|
1866
|
+
);
|
|
1702
1867
|
});
|
|
1703
1868
|
|
|
1704
1869
|
// eslint-disable-next-line max-len
|
|
1705
1870
|
it('will use default resolution if shareConstraints is undefined and highFrameRate is defined', () => {
|
|
1706
1871
|
// If highFrameRate is defined it ignores default SDK config settings
|
|
1707
|
-
getDisplayMedia(
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1872
|
+
getDisplayMedia(
|
|
1873
|
+
{
|
|
1874
|
+
...shareOptions,
|
|
1875
|
+
sharePreferences: {
|
|
1876
|
+
highFrameRate: true,
|
|
1877
|
+
},
|
|
1878
|
+
},
|
|
1879
|
+
config
|
|
1880
|
+
);
|
|
1713
1881
|
|
|
1714
1882
|
// eslint-disable-next-line no-undef
|
|
1715
|
-
assert.calledWith(
|
|
1883
|
+
assert.calledWith(
|
|
1884
|
+
navigator.mediaDevices.getDisplayMedia,
|
|
1716
1885
|
browserConditionalValue({
|
|
1717
1886
|
default: {
|
|
1718
1887
|
video: {
|
|
@@ -1723,11 +1892,12 @@ describe('plugin-meetings', () => {
|
|
|
1723
1892
|
maxWidth: resolution.maxWidth,
|
|
1724
1893
|
maxHeight: resolution.maxHeight,
|
|
1725
1894
|
idealWidth: resolution.idealWidth,
|
|
1726
|
-
idealHeight: resolution.idealHeight
|
|
1727
|
-
}
|
|
1895
|
+
idealHeight: resolution.idealHeight,
|
|
1896
|
+
},
|
|
1728
1897
|
},
|
|
1729
|
-
firefox: fireFoxOptions
|
|
1730
|
-
})
|
|
1898
|
+
firefox: fireFoxOptions,
|
|
1899
|
+
})
|
|
1900
|
+
);
|
|
1731
1901
|
});
|
|
1732
1902
|
|
|
1733
1903
|
// eslint-disable-next-line max-len
|
|
@@ -1736,17 +1906,19 @@ describe('plugin-meetings', () => {
|
|
|
1736
1906
|
const {screenResolution} = config;
|
|
1737
1907
|
|
|
1738
1908
|
// eslint-disable-next-line no-undef
|
|
1739
|
-
assert.calledWith(
|
|
1909
|
+
assert.calledWith(
|
|
1910
|
+
navigator.mediaDevices.getDisplayMedia,
|
|
1740
1911
|
browserConditionalValue({
|
|
1741
1912
|
default: {
|
|
1742
1913
|
video: {
|
|
1743
1914
|
...MediaConstraint,
|
|
1744
1915
|
width: screenResolution.idealWidth,
|
|
1745
|
-
height: screenResolution.idealHeight
|
|
1746
|
-
}
|
|
1916
|
+
height: screenResolution.idealHeight,
|
|
1917
|
+
},
|
|
1747
1918
|
},
|
|
1748
|
-
firefox: fireFoxOptions
|
|
1749
|
-
})
|
|
1919
|
+
firefox: fireFoxOptions,
|
|
1920
|
+
})
|
|
1921
|
+
);
|
|
1750
1922
|
});
|
|
1751
1923
|
|
|
1752
1924
|
// Test screenResolution
|
|
@@ -1759,14 +1931,15 @@ describe('plugin-meetings', () => {
|
|
|
1759
1931
|
maxWidth: SHARE_WIDTH,
|
|
1760
1932
|
maxHeight: SHARE_HEIGHT,
|
|
1761
1933
|
idealWidth: SHARE_WIDTH,
|
|
1762
|
-
idealHeight: SHARE_HEIGHT
|
|
1763
|
-
}
|
|
1934
|
+
idealHeight: SHARE_HEIGHT,
|
|
1935
|
+
},
|
|
1764
1936
|
};
|
|
1765
1937
|
|
|
1766
1938
|
getDisplayMedia(shareOptions, customConfig);
|
|
1767
1939
|
|
|
1768
1940
|
// eslint-disable-next-line no-undef
|
|
1769
|
-
assert.calledWith(
|
|
1941
|
+
assert.calledWith(
|
|
1942
|
+
navigator.mediaDevices.getDisplayMedia,
|
|
1770
1943
|
browserConditionalValue({
|
|
1771
1944
|
default: {
|
|
1772
1945
|
video: {
|
|
@@ -1776,11 +1949,12 @@ describe('plugin-meetings', () => {
|
|
|
1776
1949
|
maxWidth: SHARE_WIDTH,
|
|
1777
1950
|
maxHeight: SHARE_HEIGHT,
|
|
1778
1951
|
idealWidth: SHARE_WIDTH,
|
|
1779
|
-
idealHeight: SHARE_HEIGHT
|
|
1780
|
-
}
|
|
1952
|
+
idealHeight: SHARE_HEIGHT,
|
|
1953
|
+
},
|
|
1781
1954
|
},
|
|
1782
|
-
firefox: fireFoxOptions
|
|
1783
|
-
})
|
|
1955
|
+
firefox: fireFoxOptions,
|
|
1956
|
+
})
|
|
1957
|
+
);
|
|
1784
1958
|
});
|
|
1785
1959
|
|
|
1786
1960
|
// Test screenFrameRate
|
|
@@ -1793,14 +1967,15 @@ describe('plugin-meetings', () => {
|
|
|
1793
1967
|
maxWidth: SHARE_WIDTH,
|
|
1794
1968
|
maxHeight: SHARE_HEIGHT,
|
|
1795
1969
|
idealWidth: SHARE_WIDTH,
|
|
1796
|
-
idealHeight: SHARE_HEIGHT
|
|
1797
|
-
}
|
|
1970
|
+
idealHeight: SHARE_HEIGHT,
|
|
1971
|
+
},
|
|
1798
1972
|
};
|
|
1799
1973
|
|
|
1800
1974
|
getDisplayMedia(shareOptions, customConfig);
|
|
1801
1975
|
|
|
1802
1976
|
// eslint-disable-next-line no-undef
|
|
1803
|
-
assert.calledWith(
|
|
1977
|
+
assert.calledWith(
|
|
1978
|
+
navigator.mediaDevices.getDisplayMedia,
|
|
1804
1979
|
browserConditionalValue({
|
|
1805
1980
|
default: {
|
|
1806
1981
|
video: {
|
|
@@ -1811,11 +1986,12 @@ describe('plugin-meetings', () => {
|
|
|
1811
1986
|
maxWidth: SHARE_WIDTH,
|
|
1812
1987
|
maxHeight: SHARE_HEIGHT,
|
|
1813
1988
|
idealWidth: SHARE_WIDTH,
|
|
1814
|
-
idealHeight: SHARE_HEIGHT
|
|
1815
|
-
}
|
|
1989
|
+
idealHeight: SHARE_HEIGHT,
|
|
1990
|
+
},
|
|
1816
1991
|
},
|
|
1817
|
-
firefox: fireFoxOptions
|
|
1818
|
-
})
|
|
1992
|
+
firefox: fireFoxOptions,
|
|
1993
|
+
})
|
|
1994
|
+
);
|
|
1819
1995
|
});
|
|
1820
1996
|
});
|
|
1821
1997
|
|
|
@@ -1857,22 +2033,35 @@ describe('plugin-meetings', () => {
|
|
|
1857
2033
|
receiveVideo: true,
|
|
1858
2034
|
receiveShare: true,
|
|
1859
2035
|
};
|
|
1860
|
-
meeting.mediaProperties.webrtcMediaConnection = {
|
|
2036
|
+
meeting.mediaProperties.webrtcMediaConnection = {
|
|
2037
|
+
updateSendReceiveOptions: sinon.stub(),
|
|
2038
|
+
};
|
|
1861
2039
|
sinon.stub(MeetingUtil, 'getTrack').returns({audioTrack: FAKE_AUDIO_TRACK});
|
|
1862
2040
|
});
|
|
1863
|
-
it('calls this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions', () =>
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
2041
|
+
it('calls this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions', () =>
|
|
2042
|
+
meeting
|
|
2043
|
+
.updateAudio({
|
|
2044
|
+
sendAudio: true,
|
|
2045
|
+
receiveAudio: true,
|
|
2046
|
+
stream: {id: 'fake stream'},
|
|
2047
|
+
})
|
|
2048
|
+
.then(() => {
|
|
2049
|
+
assert.calledOnce(
|
|
2050
|
+
meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions
|
|
2051
|
+
);
|
|
2052
|
+
assert.calledWith(
|
|
2053
|
+
meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions,
|
|
2054
|
+
{
|
|
2055
|
+
send: {audio: FAKE_AUDIO_TRACK},
|
|
2056
|
+
receive: {
|
|
2057
|
+
audio: true,
|
|
2058
|
+
video: true,
|
|
2059
|
+
screenShareVideo: true,
|
|
2060
|
+
remoteQualityLevel: 'HIGH',
|
|
2061
|
+
},
|
|
2062
|
+
}
|
|
2063
|
+
);
|
|
2064
|
+
}));
|
|
1876
2065
|
});
|
|
1877
2066
|
afterEach(() => {
|
|
1878
2067
|
sinon.restore();
|
|
@@ -1892,7 +2081,7 @@ describe('plugin-meetings', () => {
|
|
|
1892
2081
|
|
|
1893
2082
|
meeting.locusInfo.self = {
|
|
1894
2083
|
enableDTMF: true,
|
|
1895
|
-
url: url2
|
|
2084
|
+
url: url2,
|
|
1896
2085
|
};
|
|
1897
2086
|
|
|
1898
2087
|
await meeting.sendDTMF(tones);
|
|
@@ -1900,7 +2089,7 @@ describe('plugin-meetings', () => {
|
|
|
1900
2089
|
assert.calledWith(meeting.meetingRequest.sendDTMF, {
|
|
1901
2090
|
locusUrl: meeting.locusInfo.self.url,
|
|
1902
2091
|
deviceUrl: meeting.deviceUrl,
|
|
1903
|
-
tones
|
|
2092
|
+
tones,
|
|
1904
2093
|
});
|
|
1905
2094
|
});
|
|
1906
2095
|
|
|
@@ -1914,7 +2103,7 @@ describe('plugin-meetings', () => {
|
|
|
1914
2103
|
it('should throw an error', () => {
|
|
1915
2104
|
meeting.locusInfo.self = {
|
|
1916
2105
|
enableDTMF: false,
|
|
1917
|
-
url: url2
|
|
2106
|
+
url: url2,
|
|
1918
2107
|
};
|
|
1919
2108
|
|
|
1920
2109
|
assert.isRejected(meeting.sendDTMF('123'));
|
|
@@ -1939,7 +2128,6 @@ describe('plugin-meetings', () => {
|
|
|
1939
2128
|
id: 'fake share track',
|
|
1940
2129
|
getSettings: sinon.stub().returns({}),
|
|
1941
2130
|
},
|
|
1942
|
-
|
|
1943
2131
|
};
|
|
1944
2132
|
|
|
1945
2133
|
beforeEach(() => {
|
|
@@ -1971,21 +2159,22 @@ describe('plugin-meetings', () => {
|
|
|
1971
2159
|
receiveVideo: true,
|
|
1972
2160
|
sendShare: true,
|
|
1973
2161
|
receiveShare: true,
|
|
1974
|
-
isSharing: true
|
|
2162
|
+
isSharing: true,
|
|
1975
2163
|
};
|
|
1976
2164
|
|
|
1977
2165
|
sandbox.stub(meeting, 'canUpdateMedia').returns(false);
|
|
1978
2166
|
meeting.mediaProperties.webrtcMediaConnection = {
|
|
1979
|
-
updateSendReceiveOptions: sinon.stub().resolves({})
|
|
2167
|
+
updateSendReceiveOptions: sinon.stub().resolves({}),
|
|
1980
2168
|
};
|
|
1981
2169
|
|
|
1982
2170
|
let myPromiseResolved = false;
|
|
1983
2171
|
|
|
1984
|
-
meeting
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
2172
|
+
meeting
|
|
2173
|
+
.updateMedia({
|
|
2174
|
+
localStream: mockLocalStream,
|
|
2175
|
+
localShare: mockLocalShare,
|
|
2176
|
+
mediaSettings,
|
|
2177
|
+
})
|
|
1989
2178
|
.then(() => {
|
|
1990
2179
|
myPromiseResolved = true;
|
|
1991
2180
|
});
|
|
@@ -2002,77 +2191,268 @@ describe('plugin-meetings', () => {
|
|
|
2002
2191
|
|
|
2003
2192
|
// and check that updateSendReceiveOptions is called with the original args
|
|
2004
2193
|
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
|
|
2005
|
-
assert.calledWith(
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2194
|
+
assert.calledWith(
|
|
2195
|
+
meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions,
|
|
2196
|
+
{
|
|
2197
|
+
send: {
|
|
2198
|
+
audio: FAKE_TRACKS.audio,
|
|
2199
|
+
video: FAKE_TRACKS.video,
|
|
2200
|
+
screenShareVideo: FAKE_TRACKS.screenshareVideo,
|
|
2201
|
+
},
|
|
2202
|
+
receive: {
|
|
2203
|
+
audio: true,
|
|
2204
|
+
video: true,
|
|
2205
|
+
screenShareVideo: true,
|
|
2206
|
+
remoteQualityLevel: 'HIGH',
|
|
2207
|
+
},
|
|
2016
2208
|
}
|
|
2017
|
-
|
|
2209
|
+
);
|
|
2018
2210
|
assert.isTrue(myPromiseResolved);
|
|
2019
2211
|
});
|
|
2020
|
-
});
|
|
2021
2212
|
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
let mediaDirection;
|
|
2025
|
-
const layoutTypeSingle = 'Single';
|
|
2213
|
+
it('should request floor only after roap transaction is completed', async () => {
|
|
2214
|
+
const eventListeners = {};
|
|
2026
2215
|
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
sendVideo: true,
|
|
2031
|
-
sendShare: false,
|
|
2032
|
-
receiveVideo: true
|
|
2033
|
-
};
|
|
2034
|
-
meeting.getMediaStreams = sinon.stub().returns(Promise.resolve([]));
|
|
2035
|
-
meeting.updateVideo = sinon.stub().returns(Promise.resolve());
|
|
2036
|
-
meeting.mediaProperties.mediaDirection = mediaDirection;
|
|
2037
|
-
meeting.mediaProperties.remoteVideoTrack = sinon.stub().returns({mockTrack: 'mockTrack'});
|
|
2216
|
+
meeting.webex.meetings.reachability = {
|
|
2217
|
+
isAnyClusterReachable: sandbox.stub().resolves(true)
|
|
2218
|
+
};
|
|
2038
2219
|
|
|
2039
|
-
|
|
2220
|
+
const fakeMediaConnection = {
|
|
2221
|
+
close: sinon.stub(),
|
|
2222
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
2223
|
+
initiateOffer: sinon.stub().resolves({}),
|
|
2040
2224
|
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2225
|
+
// mock the on() method and store all the listeners
|
|
2226
|
+
on: sinon.stub().callsFake((event, listener) => {
|
|
2227
|
+
eventListeners[event] = listener;
|
|
2228
|
+
}),
|
|
2229
|
+
|
|
2230
|
+
updateSendReceiveOptions: sinon.stub().callsFake(() => {
|
|
2231
|
+
// trigger ROAP_STARTED before updateSendReceiveOptions() resolves
|
|
2232
|
+
if (eventListeners[Event.ROAP_STARTED]) {
|
|
2233
|
+
eventListeners[Event.ROAP_STARTED]();
|
|
2234
|
+
} else {
|
|
2235
|
+
throw new Error('ROAP_STARTED listener not registered')
|
|
2236
|
+
}
|
|
2237
|
+
return Promise.resolve();
|
|
2238
|
+
}),
|
|
2239
|
+
};
|
|
2045
2240
|
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2241
|
+
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
|
|
2242
|
+
meeting.mediaProperties.getCurrentConnectionType = sinon.stub().resolves('udp');
|
|
2243
|
+
Media.createMediaConnection = sinon.stub().returns(fakeMediaConnection);
|
|
2049
2244
|
|
|
2050
|
-
|
|
2245
|
+
const requestScreenShareFloorStub = sandbox.stub(meeting, 'requestScreenShareFloor').resolves({});
|
|
2051
2246
|
|
|
2052
|
-
|
|
2053
|
-
});
|
|
2247
|
+
let myPromiseResolved = false;
|
|
2054
2248
|
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2249
|
+
meeting.meetingState = 'ACTIVE';
|
|
2250
|
+
await meeting.addMedia({
|
|
2251
|
+
mediaSettings: {},
|
|
2058
2252
|
});
|
|
2059
2253
|
|
|
2060
|
-
|
|
2061
|
-
|
|
2254
|
+
meeting
|
|
2255
|
+
.updateMedia({
|
|
2256
|
+
localShare: mockLocalShare,
|
|
2257
|
+
mediaSettings: {
|
|
2258
|
+
sendShare: true,
|
|
2259
|
+
},
|
|
2260
|
+
})
|
|
2261
|
+
.then(() => {
|
|
2262
|
+
myPromiseResolved = true;
|
|
2263
|
+
});
|
|
2062
2264
|
|
|
2063
|
-
|
|
2265
|
+
await testUtils.flushPromises();
|
|
2064
2266
|
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2267
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
|
|
2268
|
+
assert.isFalse(myPromiseResolved);
|
|
2269
|
+
|
|
2270
|
+
// verify that requestScreenShareFloorStub was not called yet
|
|
2271
|
+
assert.notCalled(requestScreenShareFloorStub);
|
|
2272
|
+
|
|
2273
|
+
eventListeners[Event.ROAP_DONE]();
|
|
2274
|
+
await testUtils.flushPromises();
|
|
2275
|
+
|
|
2276
|
+
// now it should have been called
|
|
2277
|
+
assert.calledOnce(requestScreenShareFloorStub);
|
|
2278
|
+
});
|
|
2279
|
+
});
|
|
2280
|
+
|
|
2281
|
+
describe('#updateShare', () => {
|
|
2282
|
+
const mockLocalShare = {id: 'mock local share stream'};
|
|
2283
|
+
let eventListeners;
|
|
2284
|
+
let fakeMediaConnection;
|
|
2285
|
+
let requestScreenShareFloorStub;
|
|
2286
|
+
|
|
2287
|
+
const FAKE_TRACKS = {
|
|
2288
|
+
screenshareVideo: {
|
|
2289
|
+
id: 'fake share track',
|
|
2290
|
+
getSettings: sinon.stub().returns({}),
|
|
2291
|
+
},
|
|
2292
|
+
};
|
|
2293
|
+
|
|
2294
|
+
beforeEach(async () => {
|
|
2295
|
+
eventListeners = {};
|
|
2296
|
+
|
|
2297
|
+
sinon.stub(MeetingUtil, 'getTrack').callsFake((stream) => {
|
|
2298
|
+
if (stream === mockLocalShare) {
|
|
2299
|
+
return {audioTrack: null, videoTrack: FAKE_TRACKS.screenshareVideo};
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
return {audioTrack: null, videoTrack: null};
|
|
2303
|
+
});
|
|
2304
|
+
|
|
2305
|
+
meeting.webex.meetings.reachability = {
|
|
2306
|
+
isAnyClusterReachable: sinon.stub().resolves(true)
|
|
2307
|
+
};
|
|
2308
|
+
|
|
2309
|
+
fakeMediaConnection = {
|
|
2310
|
+
close: sinon.stub(),
|
|
2311
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
2312
|
+
initiateOffer: sinon.stub().resolves({}),
|
|
2313
|
+
|
|
2314
|
+
// mock the on() method and store all the listeners
|
|
2315
|
+
on: sinon.stub().callsFake((event, listener) => {
|
|
2316
|
+
eventListeners[event] = listener;
|
|
2317
|
+
}),
|
|
2318
|
+
|
|
2319
|
+
updateSendReceiveOptions: sinon.stub().callsFake(() => {
|
|
2320
|
+
// trigger ROAP_STARTED before updateSendReceiveOptions() resolves
|
|
2321
|
+
if (eventListeners[Event.ROAP_STARTED]) {
|
|
2322
|
+
eventListeners[Event.ROAP_STARTED]();
|
|
2323
|
+
} else {
|
|
2324
|
+
throw new Error('ROAP_STARTED listener not registered')
|
|
2325
|
+
}
|
|
2326
|
+
return Promise.resolve();
|
|
2327
|
+
}),
|
|
2328
|
+
};
|
|
2329
|
+
|
|
2330
|
+
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
|
|
2331
|
+
meeting.mediaProperties.getCurrentConnectionType = sinon.stub().resolves('udp');
|
|
2332
|
+
Media.createMediaConnection = sinon.stub().returns(fakeMediaConnection);
|
|
2333
|
+
|
|
2334
|
+
requestScreenShareFloorStub = sinon.stub(meeting, 'requestScreenShareFloor').resolves({});
|
|
2335
|
+
|
|
2336
|
+
meeting.meetingState = 'ACTIVE';
|
|
2337
|
+
await meeting.addMedia({
|
|
2338
|
+
mediaSettings: {},
|
|
2339
|
+
});
|
|
2340
|
+
});
|
|
2341
|
+
|
|
2342
|
+
afterEach(() => {
|
|
2343
|
+
sinon.restore();
|
|
2344
|
+
});
|
|
2345
|
+
|
|
2346
|
+
it('when starting share, it should request floor only after roap transaction is completed', async () => {
|
|
2347
|
+
let myPromiseResolved = false;
|
|
2348
|
+
|
|
2349
|
+
meeting
|
|
2350
|
+
.updateShare({
|
|
2351
|
+
sendShare: true,
|
|
2352
|
+
receiveShare: true,
|
|
2353
|
+
stream: mockLocalShare,
|
|
2354
|
+
})
|
|
2355
|
+
.then(() => {
|
|
2356
|
+
myPromiseResolved = true;
|
|
2357
|
+
});
|
|
2358
|
+
|
|
2359
|
+
await testUtils.flushPromises();
|
|
2360
|
+
|
|
2361
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
|
|
2362
|
+
assert.isFalse(myPromiseResolved);
|
|
2363
|
+
|
|
2364
|
+
// verify that requestScreenShareFloorStub was not called yet
|
|
2365
|
+
assert.notCalled(requestScreenShareFloorStub);
|
|
2366
|
+
|
|
2367
|
+
eventListeners[Event.ROAP_DONE]();
|
|
2368
|
+
await testUtils.flushPromises();
|
|
2369
|
+
|
|
2370
|
+
// now it should have been called
|
|
2371
|
+
assert.calledOnce(requestScreenShareFloorStub);
|
|
2372
|
+
});
|
|
2373
|
+
|
|
2374
|
+
it('when changing screen share stream and no roap transaction happening, it requests floor immediately', async () => {
|
|
2375
|
+
let myPromiseResolved = false;
|
|
2376
|
+
|
|
2377
|
+
// simulate a case when no roap transaction is triggered by updateSendReceiveOptions
|
|
2378
|
+
meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions = sinon.stub().resolves({});
|
|
2379
|
+
|
|
2380
|
+
meeting
|
|
2381
|
+
.updateShare({
|
|
2382
|
+
sendShare: true,
|
|
2383
|
+
receiveShare: true,
|
|
2384
|
+
stream: mockLocalShare,
|
|
2385
|
+
})
|
|
2386
|
+
.then(() => {
|
|
2387
|
+
myPromiseResolved = true;
|
|
2388
|
+
});
|
|
2389
|
+
|
|
2390
|
+
await testUtils.flushPromises();
|
|
2391
|
+
|
|
2392
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
|
|
2393
|
+
assert.calledOnce(requestScreenShareFloorStub);
|
|
2394
|
+
assert.isTrue(myPromiseResolved);
|
|
2395
|
+
});
|
|
2396
|
+
});
|
|
2397
|
+
|
|
2398
|
+
describe('#changeVideoLayout', () => {
|
|
2399
|
+
describe('when media direction has recieve video and there is remoteStream', () => {
|
|
2400
|
+
let mediaDirection;
|
|
2401
|
+
const layoutTypeSingle = 'Single';
|
|
2402
|
+
|
|
2403
|
+
beforeEach(() => {
|
|
2404
|
+
mediaDirection = {
|
|
2405
|
+
sendAudio: true,
|
|
2406
|
+
sendVideo: true,
|
|
2407
|
+
sendShare: false,
|
|
2408
|
+
receiveVideo: true,
|
|
2409
|
+
};
|
|
2410
|
+
meeting.getMediaStreams = sinon.stub().returns(Promise.resolve([]));
|
|
2411
|
+
meeting.updateVideo = sinon.stub().returns(Promise.resolve());
|
|
2412
|
+
meeting.mediaProperties.mediaDirection = mediaDirection;
|
|
2413
|
+
meeting.mediaProperties.remoteVideoTrack = sinon
|
|
2414
|
+
.stub()
|
|
2415
|
+
.returns({mockTrack: 'mockTrack'});
|
|
2416
|
+
|
|
2417
|
+
meeting.meetingRequest.changeVideoLayoutDebounced = sinon
|
|
2418
|
+
.stub()
|
|
2419
|
+
.returns(Promise.resolve());
|
|
2420
|
+
|
|
2421
|
+
meeting.locusInfo.self = {
|
|
2422
|
+
url: url2,
|
|
2423
|
+
};
|
|
2424
|
+
});
|
|
2425
|
+
|
|
2426
|
+
it('should listen once for CONTROLS_MEETING_LAYOUT_UPDATED', async () => {
|
|
2427
|
+
// const spy = sinon.spy(TriggerProxy, 'trigger');
|
|
2428
|
+
const spy = sinon.spy(meeting.locusInfo, 'once');
|
|
2429
|
+
|
|
2430
|
+
await meeting.changeVideoLayout('Equal');
|
|
2431
|
+
|
|
2432
|
+
assert.calledWith(spy, LOCUSINFO.EVENTS.CONTROLS_MEETING_LAYOUT_UPDATED);
|
|
2433
|
+
});
|
|
2434
|
+
|
|
2435
|
+
it('should have receiveVideo true and remote video track should exist', () => {
|
|
2436
|
+
assert.equal(meeting.mediaProperties.mediaDirection.receiveVideo, true);
|
|
2437
|
+
assert.exists(meeting.mediaProperties.remoteVideoTrack);
|
|
2438
|
+
});
|
|
2439
|
+
|
|
2440
|
+
it('has layoutType which exists in the list of allowed layoutTypes and should call meetingRequest changeVideoLayoutDebounced method', async () => {
|
|
2441
|
+
const layoutType = 'Equal';
|
|
2442
|
+
|
|
2443
|
+
await meeting.changeVideoLayout(layoutType);
|
|
2444
|
+
|
|
2445
|
+
assert(CONSTANTS.LAYOUT_TYPES.includes(layoutType));
|
|
2446
|
+
assert.calledWith(meeting.meetingRequest.changeVideoLayoutDebounced, {
|
|
2447
|
+
locusUrl: meeting.locusInfo.self.url,
|
|
2068
2448
|
deviceUrl: meeting.deviceUrl,
|
|
2069
2449
|
layoutType,
|
|
2070
2450
|
main: undefined,
|
|
2071
|
-
content: undefined
|
|
2451
|
+
content: undefined,
|
|
2072
2452
|
});
|
|
2073
2453
|
});
|
|
2074
2454
|
|
|
2075
|
-
it(
|
|
2455
|
+
it("doesn't have layoutType which exists in the list of allowed layoutTypes should throw an error", async () => {
|
|
2076
2456
|
const layoutType = 'Invalid Layout';
|
|
2077
2457
|
|
|
2078
2458
|
assert.isRejected(meeting.changeVideoLayout(layoutType));
|
|
@@ -2086,12 +2466,14 @@ describe('plugin-meetings', () => {
|
|
|
2086
2466
|
deviceUrl: meeting.deviceUrl,
|
|
2087
2467
|
layoutType: undefined,
|
|
2088
2468
|
main: {width: 100, height: 200},
|
|
2089
|
-
content: undefined
|
|
2469
|
+
content: undefined,
|
|
2090
2470
|
});
|
|
2091
2471
|
});
|
|
2092
2472
|
|
|
2093
2473
|
it('throws if trying to send renderInfo for content when not receiving content', async () => {
|
|
2094
|
-
assert.isRejected(
|
|
2474
|
+
assert.isRejected(
|
|
2475
|
+
meeting.changeVideoLayout(layoutTypeSingle, {content: {width: 1280, height: 720}})
|
|
2476
|
+
);
|
|
2095
2477
|
});
|
|
2096
2478
|
|
|
2097
2479
|
it('calls changeVideoLayoutDebounced with renderInfo for main and content', async () => {
|
|
@@ -2103,7 +2485,7 @@ describe('plugin-meetings', () => {
|
|
|
2103
2485
|
deviceUrl: meeting.deviceUrl,
|
|
2104
2486
|
layoutType: layoutTypeSingle,
|
|
2105
2487
|
main: {width: 100, height: 200},
|
|
2106
|
-
content: undefined
|
|
2488
|
+
content: undefined,
|
|
2107
2489
|
});
|
|
2108
2490
|
|
|
2109
2491
|
meeting.mediaProperties.mediaDirection.receiveShare = true;
|
|
@@ -2117,18 +2499,21 @@ describe('plugin-meetings', () => {
|
|
|
2117
2499
|
deviceUrl: meeting.deviceUrl,
|
|
2118
2500
|
layoutType: layoutTypeSingle,
|
|
2119
2501
|
main: {width: 100, height: 200},
|
|
2120
|
-
content: {width: 500, height: 600}
|
|
2502
|
+
content: {width: 500, height: 600},
|
|
2121
2503
|
});
|
|
2122
2504
|
|
|
2123
2505
|
// and now call with both
|
|
2124
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2506
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2507
|
+
main: {width: 300, height: 400},
|
|
2508
|
+
content: {width: 700, height: 800},
|
|
2509
|
+
});
|
|
2125
2510
|
|
|
2126
2511
|
assert.calledWith(meeting.meetingRequest.changeVideoLayoutDebounced, {
|
|
2127
2512
|
locusUrl: meeting.locusInfo.self.url,
|
|
2128
2513
|
deviceUrl: meeting.deviceUrl,
|
|
2129
2514
|
layoutType: layoutTypeSingle,
|
|
2130
2515
|
main: {width: 300, height: 400},
|
|
2131
|
-
content: {width: 700, height: 800}
|
|
2516
|
+
content: {width: 700, height: 800},
|
|
2132
2517
|
});
|
|
2133
2518
|
|
|
2134
2519
|
// and now set just the layoutType, the previous main and content values should be used
|
|
@@ -2141,7 +2526,7 @@ describe('plugin-meetings', () => {
|
|
|
2141
2526
|
deviceUrl: meeting.deviceUrl,
|
|
2142
2527
|
layoutType,
|
|
2143
2528
|
main: {width: 300, height: 400},
|
|
2144
|
-
content: {width: 700, height: 800}
|
|
2529
|
+
content: {width: 700, height: 800},
|
|
2145
2530
|
});
|
|
2146
2531
|
});
|
|
2147
2532
|
|
|
@@ -2153,7 +2538,7 @@ describe('plugin-meetings', () => {
|
|
|
2153
2538
|
deviceUrl: meeting.deviceUrl,
|
|
2154
2539
|
layoutType: layoutTypeSingle,
|
|
2155
2540
|
main: {width: 1024, height: 768},
|
|
2156
|
-
content: undefined
|
|
2541
|
+
content: undefined,
|
|
2157
2542
|
});
|
|
2158
2543
|
meeting.meetingRequest.changeVideoLayoutDebounced.resetHistory();
|
|
2159
2544
|
|
|
@@ -2175,28 +2560,39 @@ describe('plugin-meetings', () => {
|
|
|
2175
2560
|
meeting.mediaProperties.mediaDirection.receiveShare = true;
|
|
2176
2561
|
meeting.mediaProperties.remoteShare = sinon.stub().returns({mockTrack: 'mockTrack'});
|
|
2177
2562
|
|
|
2178
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2563
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2564
|
+
main: {width: 500, height: 510},
|
|
2565
|
+
content: {width: 1024, height: 768},
|
|
2566
|
+
});
|
|
2179
2567
|
|
|
2180
2568
|
assert.calledWith(meeting.meetingRequest.changeVideoLayoutDebounced, {
|
|
2181
2569
|
locusUrl: meeting.locusInfo.self.url,
|
|
2182
2570
|
deviceUrl: meeting.deviceUrl,
|
|
2183
2571
|
layoutType: layoutTypeSingle,
|
|
2184
2572
|
main: {width: 500, height: 510},
|
|
2185
|
-
content: {width: 1024, height: 768}
|
|
2573
|
+
content: {width: 1024, height: 768},
|
|
2186
2574
|
});
|
|
2187
2575
|
meeting.meetingRequest.changeVideoLayoutDebounced.resetHistory();
|
|
2188
2576
|
|
|
2189
2577
|
// now send main with width/height different by just 2px - it should be ignored
|
|
2190
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2578
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2579
|
+
content: {width: 1026, height: 768},
|
|
2580
|
+
});
|
|
2191
2581
|
assert.notCalled(meeting.meetingRequest.changeVideoLayoutDebounced);
|
|
2192
2582
|
|
|
2193
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2583
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2584
|
+
content: {width: 1022, height: 768},
|
|
2585
|
+
});
|
|
2194
2586
|
assert.notCalled(meeting.meetingRequest.changeVideoLayoutDebounced);
|
|
2195
2587
|
|
|
2196
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2588
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2589
|
+
content: {width: 1024, height: 770},
|
|
2590
|
+
});
|
|
2197
2591
|
assert.notCalled(meeting.meetingRequest.changeVideoLayoutDebounced);
|
|
2198
2592
|
|
|
2199
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2593
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2594
|
+
content: {width: 1024, height: 766},
|
|
2595
|
+
});
|
|
2200
2596
|
assert.notCalled(meeting.meetingRequest.changeVideoLayoutDebounced);
|
|
2201
2597
|
});
|
|
2202
2598
|
|
|
@@ -2204,14 +2600,17 @@ describe('plugin-meetings', () => {
|
|
|
2204
2600
|
meeting.mediaProperties.mediaDirection.receiveShare = true;
|
|
2205
2601
|
meeting.mediaProperties.remoteShare = sinon.stub().returns({mockTrack: 'mockTrack'});
|
|
2206
2602
|
|
|
2207
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2603
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2604
|
+
main: {width: 500.5, height: 510.09},
|
|
2605
|
+
content: {width: 1024.2, height: 768.85},
|
|
2606
|
+
});
|
|
2208
2607
|
|
|
2209
2608
|
assert.calledWith(meeting.meetingRequest.changeVideoLayoutDebounced, {
|
|
2210
2609
|
locusUrl: meeting.locusInfo.self.url,
|
|
2211
2610
|
deviceUrl: meeting.deviceUrl,
|
|
2212
2611
|
layoutType: layoutTypeSingle,
|
|
2213
2612
|
main: {width: 501, height: 510},
|
|
2214
|
-
content: {width: 1024, height: 769}
|
|
2613
|
+
content: {width: 1024, height: 769},
|
|
2215
2614
|
});
|
|
2216
2615
|
});
|
|
2217
2616
|
});
|
|
@@ -2223,7 +2622,7 @@ describe('plugin-meetings', () => {
|
|
|
2223
2622
|
sendAudio: true,
|
|
2224
2623
|
sendVideo: true,
|
|
2225
2624
|
sendShare: false,
|
|
2226
|
-
receiveVideo: true
|
|
2625
|
+
receiveVideo: true,
|
|
2227
2626
|
};
|
|
2228
2627
|
|
|
2229
2628
|
meeting.mediaProperties.mediaDirection = mediaDirection;
|
|
@@ -2237,7 +2636,7 @@ describe('plugin-meetings', () => {
|
|
|
2237
2636
|
sendAudio: true,
|
|
2238
2637
|
sendVideo: true,
|
|
2239
2638
|
sendShare: false,
|
|
2240
|
-
receiveVideo: false
|
|
2639
|
+
receiveVideo: false,
|
|
2241
2640
|
};
|
|
2242
2641
|
|
|
2243
2642
|
meeting.mediaProperties.mediaDirection = mediaDirection;
|
|
@@ -2251,8 +2650,8 @@ describe('plugin-meetings', () => {
|
|
|
2251
2650
|
|
|
2252
2651
|
const fakeTrack = {getSettings: () => ({height: 720})};
|
|
2253
2652
|
const USER_AGENT_CHROME_MAC =
|
|
2254
|
-
|
|
2255
|
-
|
|
2653
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ' +
|
|
2654
|
+
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36';
|
|
2256
2655
|
|
|
2257
2656
|
beforeEach(() => {
|
|
2258
2657
|
mediaDirection = {sendAudio: true, sendVideo: true, sendShare: false};
|
|
@@ -2268,34 +2667,36 @@ describe('plugin-meetings', () => {
|
|
|
2268
2667
|
assert.exists(meeting.setLocalVideoQuality);
|
|
2269
2668
|
});
|
|
2270
2669
|
|
|
2271
|
-
it('should call getMediaStreams with the proper level', () =>
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2670
|
+
it('should call getMediaStreams with the proper level', () =>
|
|
2671
|
+
meeting.setLocalVideoQuality(CONSTANTS.QUALITY_LEVELS.LOW).then(() => {
|
|
2672
|
+
delete mediaDirection.receiveVideo;
|
|
2673
|
+
assert.calledWith(
|
|
2674
|
+
meeting.getMediaStreams,
|
|
2675
|
+
mediaDirection,
|
|
2676
|
+
CONSTANTS.VIDEO_RESOLUTIONS[CONSTANTS.QUALITY_LEVELS.LOW]
|
|
2677
|
+
);
|
|
2678
|
+
}));
|
|
2277
2679
|
|
|
2278
2680
|
it('when browser is chrome then it should stop previous video track', () => {
|
|
2279
2681
|
meeting.mediaProperties.videoTrack = fakeTrack;
|
|
2280
|
-
assert.equal(
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
);
|
|
2284
|
-
meeting.setLocalVideoQuality(CONSTANTS.QUALITY_LEVELS.LOW)
|
|
2285
|
-
.then(() => {
|
|
2286
|
-
assert.calledWith(Media.stopTracks, fakeTrack);
|
|
2287
|
-
});
|
|
2682
|
+
assert.equal(BrowserDetection(USER_AGENT_CHROME_MAC).getBrowserName(), 'Chrome');
|
|
2683
|
+
meeting.setLocalVideoQuality(CONSTANTS.QUALITY_LEVELS.LOW).then(() => {
|
|
2684
|
+
assert.calledWith(Media.stopTracks, fakeTrack);
|
|
2685
|
+
});
|
|
2288
2686
|
});
|
|
2289
2687
|
|
|
2290
|
-
it('should set mediaProperty with the proper level', () =>
|
|
2291
|
-
|
|
2292
|
-
|
|
2688
|
+
it('should set mediaProperty with the proper level', () =>
|
|
2689
|
+
meeting.setLocalVideoQuality(CONSTANTS.QUALITY_LEVELS.LOW).then(() => {
|
|
2690
|
+
assert.equal(meeting.mediaProperties.localQualityLevel, CONSTANTS.QUALITY_LEVELS.LOW);
|
|
2691
|
+
}));
|
|
2293
2692
|
|
|
2294
2693
|
it('when device does not support 1080p then it should set localQualityLevel with highest possible resolution', () => {
|
|
2295
|
-
meeting.setLocalVideoQuality(CONSTANTS.QUALITY_LEVELS['1080p'])
|
|
2296
|
-
.
|
|
2297
|
-
|
|
2298
|
-
|
|
2694
|
+
meeting.setLocalVideoQuality(CONSTANTS.QUALITY_LEVELS['1080p']).then(() => {
|
|
2695
|
+
assert.equal(
|
|
2696
|
+
meeting.mediaProperties.localQualityLevel,
|
|
2697
|
+
CONSTANTS.QUALITY_LEVELS['720p']
|
|
2698
|
+
);
|
|
2699
|
+
});
|
|
2299
2700
|
});
|
|
2300
2701
|
|
|
2301
2702
|
it('should error if set to a invalid level', () => {
|
|
@@ -2321,13 +2722,15 @@ describe('plugin-meetings', () => {
|
|
|
2321
2722
|
assert.exists(meeting.setRemoteQualityLevel);
|
|
2322
2723
|
});
|
|
2323
2724
|
|
|
2324
|
-
it('should set mediaProperty with the proper level', () =>
|
|
2325
|
-
|
|
2326
|
-
|
|
2725
|
+
it('should set mediaProperty with the proper level', () =>
|
|
2726
|
+
meeting.setRemoteQualityLevel(CONSTANTS.QUALITY_LEVELS.LOW).then(() => {
|
|
2727
|
+
assert.equal(meeting.mediaProperties.remoteQualityLevel, CONSTANTS.QUALITY_LEVELS.LOW);
|
|
2728
|
+
}));
|
|
2327
2729
|
|
|
2328
|
-
it('should call updateMedia', () =>
|
|
2329
|
-
|
|
2330
|
-
|
|
2730
|
+
it('should call updateMedia', () =>
|
|
2731
|
+
meeting.setRemoteQualityLevel(CONSTANTS.QUALITY_LEVELS.LOW).then(() => {
|
|
2732
|
+
assert.calledOnce(meeting.updateMedia);
|
|
2733
|
+
}));
|
|
2331
2734
|
|
|
2332
2735
|
it('should error if set to a invalid level', () => {
|
|
2333
2736
|
assert.isRejected(meeting.setRemoteQualityLevel('invalid'));
|
|
@@ -2341,8 +2744,12 @@ describe('plugin-meetings', () => {
|
|
|
2341
2744
|
|
|
2342
2745
|
describe('#usePhoneAudio', () => {
|
|
2343
2746
|
beforeEach(() => {
|
|
2344
|
-
meeting.meetingRequest.dialIn = sinon
|
|
2345
|
-
|
|
2747
|
+
meeting.meetingRequest.dialIn = sinon
|
|
2748
|
+
.stub()
|
|
2749
|
+
.returns(Promise.resolve({body: {locus: 'testData'}}));
|
|
2750
|
+
meeting.meetingRequest.dialOut = sinon
|
|
2751
|
+
.stub()
|
|
2752
|
+
.returns(Promise.resolve({body: {locus: 'testData'}}));
|
|
2346
2753
|
meeting.locusInfo.onFullLocus = sinon.stub().returns(Promise.resolve());
|
|
2347
2754
|
});
|
|
2348
2755
|
|
|
@@ -2354,7 +2761,7 @@ describe('plugin-meetings', () => {
|
|
|
2354
2761
|
correlationId: meeting.correlationId,
|
|
2355
2762
|
dialInUrl: DIAL_IN_URL,
|
|
2356
2763
|
locusUrl: meeting.locusUrl,
|
|
2357
|
-
clientUrl: meeting.deviceUrl
|
|
2764
|
+
clientUrl: meeting.deviceUrl,
|
|
2358
2765
|
});
|
|
2359
2766
|
assert.calledWith(meeting.locusInfo.onFullLocus, 'testData');
|
|
2360
2767
|
assert.notCalled(meeting.meetingRequest.dialOut);
|
|
@@ -2369,7 +2776,7 @@ describe('plugin-meetings', () => {
|
|
|
2369
2776
|
correlationId: meeting.correlationId,
|
|
2370
2777
|
dialInUrl: DIAL_IN_URL,
|
|
2371
2778
|
locusUrl: meeting.locusUrl,
|
|
2372
|
-
clientUrl: meeting.deviceUrl
|
|
2779
|
+
clientUrl: meeting.deviceUrl,
|
|
2373
2780
|
});
|
|
2374
2781
|
assert.calledWith(meeting.locusInfo.onFullLocus, 'testData');
|
|
2375
2782
|
assert.notCalled(meeting.meetingRequest.dialOut);
|
|
@@ -2386,7 +2793,7 @@ describe('plugin-meetings', () => {
|
|
|
2386
2793
|
dialOutUrl: DIAL_OUT_URL,
|
|
2387
2794
|
locusUrl: meeting.locusUrl,
|
|
2388
2795
|
clientUrl: meeting.deviceUrl,
|
|
2389
|
-
phoneNumber
|
|
2796
|
+
phoneNumber,
|
|
2390
2797
|
});
|
|
2391
2798
|
assert.calledWith(meeting.locusInfo.onFullLocus, 'testData');
|
|
2392
2799
|
assert.notCalled(meeting.meetingRequest.dialIn);
|
|
@@ -2402,7 +2809,7 @@ describe('plugin-meetings', () => {
|
|
|
2402
2809
|
dialOutUrl: DIAL_OUT_URL,
|
|
2403
2810
|
locusUrl: meeting.locusUrl,
|
|
2404
2811
|
clientUrl: meeting.deviceUrl,
|
|
2405
|
-
phoneNumber
|
|
2812
|
+
phoneNumber,
|
|
2406
2813
|
});
|
|
2407
2814
|
assert.calledWith(meeting.locusInfo.onFullLocus, 'testData');
|
|
2408
2815
|
assert.notCalled(meeting.meetingRequest.dialIn);
|
|
@@ -2413,11 +2820,14 @@ describe('plugin-meetings', () => {
|
|
|
2413
2820
|
|
|
2414
2821
|
meeting.meetingRequest.dialIn = sinon.stub().returns(Promise.reject(error));
|
|
2415
2822
|
|
|
2416
|
-
return meeting
|
|
2417
|
-
|
|
2823
|
+
return meeting
|
|
2824
|
+
.usePhoneAudio()
|
|
2825
|
+
.then(() => Promise.reject(new Error('Promise resolved when it should have rejected')))
|
|
2826
|
+
.catch((e) => {
|
|
2827
|
+
assert.equal(e, error);
|
|
2418
2828
|
|
|
2419
|
-
|
|
2420
|
-
|
|
2829
|
+
return Promise.resolve();
|
|
2830
|
+
});
|
|
2421
2831
|
});
|
|
2422
2832
|
|
|
2423
2833
|
it('rejects if the request failed (dial out)', async () => {
|
|
@@ -2425,11 +2835,14 @@ describe('plugin-meetings', () => {
|
|
|
2425
2835
|
|
|
2426
2836
|
meeting.meetingRequest.dialOut = sinon.stub().returns(Promise.reject(error));
|
|
2427
2837
|
|
|
2428
|
-
return meeting
|
|
2429
|
-
|
|
2838
|
+
return meeting
|
|
2839
|
+
.usePhoneAudio('+441234567890')
|
|
2840
|
+
.then(() => Promise.reject(new Error('Promise resolved when it should have rejected')))
|
|
2841
|
+
.catch((e) => {
|
|
2842
|
+
assert.equal(e, error);
|
|
2430
2843
|
|
|
2431
|
-
|
|
2432
|
-
|
|
2844
|
+
return Promise.resolve();
|
|
2845
|
+
});
|
|
2433
2846
|
});
|
|
2434
2847
|
});
|
|
2435
2848
|
|
|
@@ -2448,34 +2861,42 @@ describe('plugin-meetings', () => {
|
|
|
2448
2861
|
locusUrl: 'some_locus_url',
|
|
2449
2862
|
sipUrl: 'some_sip_url', // or sipMeetingUri
|
|
2450
2863
|
meetingNumber: '123456', // this.config.experimental.enableUnifiedMeetings
|
|
2451
|
-
hostId: 'some_host_id' // this.owner;
|
|
2864
|
+
hostId: 'some_host_id', // this.owner;
|
|
2452
2865
|
};
|
|
2453
2866
|
const FAKE_SDK_CAPTCHA_INFO = {
|
|
2454
2867
|
captchaId: FAKE_CAPTCHA_ID,
|
|
2455
2868
|
verificationImageURL: FAKE_CAPTCHA_IMAGE_URL,
|
|
2456
2869
|
verificationAudioURL: FAKE_CAPTCHA_AUDIO_URL,
|
|
2457
|
-
refreshURL: FAKE_CAPTCHA_REFRESH_URL
|
|
2870
|
+
refreshURL: FAKE_CAPTCHA_REFRESH_URL,
|
|
2458
2871
|
};
|
|
2459
2872
|
const FAKE_WBXAPPAPI_CAPTCHA_INFO = {
|
|
2460
2873
|
captchaID: `${FAKE_CAPTCHA_ID}-2`,
|
|
2461
2874
|
verificationImageURL: `${FAKE_CAPTCHA_IMAGE_URL}-2`,
|
|
2462
2875
|
verificationAudioURL: `${FAKE_CAPTCHA_AUDIO_URL}-2`,
|
|
2463
|
-
refreshURL: `${FAKE_CAPTCHA_REFRESH_URL}-2
|
|
2876
|
+
refreshURL: `${FAKE_CAPTCHA_REFRESH_URL}-2`,
|
|
2464
2877
|
};
|
|
2465
2878
|
|
|
2466
|
-
|
|
2467
2879
|
it('calls meetingInfoProvider with all the right parameters and parses the result', async () => {
|
|
2468
|
-
meeting.attrs.meetingInfoProvider = {
|
|
2880
|
+
meeting.attrs.meetingInfoProvider = {
|
|
2881
|
+
fetchMeetingInfo: sinon.stub().resolves({body: FAKE_MEETING_INFO}),
|
|
2882
|
+
};
|
|
2469
2883
|
meeting.requiredCaptcha = FAKE_SDK_CAPTCHA_INFO;
|
|
2470
2884
|
meeting.destination = FAKE_DESTINATION;
|
|
2471
2885
|
meeting.destinationType = FAKE_TYPE;
|
|
2472
2886
|
meeting.parseMeetingInfo = sinon.stub().returns(undefined);
|
|
2473
2887
|
|
|
2474
2888
|
await meeting.fetchMeetingInfo({
|
|
2475
|
-
password: FAKE_PASSWORD,
|
|
2889
|
+
password: FAKE_PASSWORD,
|
|
2890
|
+
captchaCode: FAKE_CAPTCHA_CODE,
|
|
2476
2891
|
});
|
|
2477
2892
|
|
|
2478
|
-
assert.calledWith(
|
|
2893
|
+
assert.calledWith(
|
|
2894
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
2895
|
+
FAKE_DESTINATION,
|
|
2896
|
+
FAKE_TYPE,
|
|
2897
|
+
FAKE_PASSWORD,
|
|
2898
|
+
{code: FAKE_CAPTCHA_CODE, id: FAKE_CAPTCHA_ID}
|
|
2899
|
+
);
|
|
2479
2900
|
|
|
2480
2901
|
assert.calledWith(meeting.parseMeetingInfo, {body: FAKE_MEETING_INFO}, FAKE_DESTINATION);
|
|
2481
2902
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
@@ -2483,11 +2904,18 @@ describe('plugin-meetings', () => {
|
|
|
2483
2904
|
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.NONE);
|
|
2484
2905
|
assert.equal(meeting.requiredCaptcha, null);
|
|
2485
2906
|
assert.calledTwice(TriggerProxy.trigger);
|
|
2486
|
-
assert.calledWith(
|
|
2907
|
+
assert.calledWith(
|
|
2908
|
+
TriggerProxy.trigger,
|
|
2909
|
+
meeting,
|
|
2910
|
+
{file: 'meetings', function: 'fetchMeetingInfo'},
|
|
2911
|
+
'meeting:meetingInfoAvailable'
|
|
2912
|
+
);
|
|
2487
2913
|
});
|
|
2488
2914
|
|
|
2489
2915
|
it('calls meetingInfoProvider with all the right parameters and parses the result when random delay is applied', async () => {
|
|
2490
|
-
meeting.attrs.meetingInfoProvider = {
|
|
2916
|
+
meeting.attrs.meetingInfoProvider = {
|
|
2917
|
+
fetchMeetingInfo: sinon.stub().resolves({body: FAKE_MEETING_INFO}),
|
|
2918
|
+
};
|
|
2491
2919
|
meeting.destination = FAKE_DESTINATION;
|
|
2492
2920
|
meeting.destinationType = FAKE_TYPE;
|
|
2493
2921
|
meeting.parseMeetingInfo = sinon.stub().returns(undefined);
|
|
@@ -2504,7 +2932,13 @@ describe('plugin-meetings', () => {
|
|
|
2504
2932
|
assert.isUndefined(meeting.fetchMeetingInfoTimeoutId);
|
|
2505
2933
|
|
|
2506
2934
|
// meeting info provider
|
|
2507
|
-
assert.calledWith(
|
|
2935
|
+
assert.calledWith(
|
|
2936
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
2937
|
+
FAKE_DESTINATION,
|
|
2938
|
+
FAKE_TYPE,
|
|
2939
|
+
null,
|
|
2940
|
+
null
|
|
2941
|
+
);
|
|
2508
2942
|
|
|
2509
2943
|
// parseMeeting info
|
|
2510
2944
|
assert.calledWith(meeting.parseMeetingInfo, {body: FAKE_MEETING_INFO}, FAKE_DESTINATION);
|
|
@@ -2515,31 +2949,48 @@ describe('plugin-meetings', () => {
|
|
|
2515
2949
|
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.NOT_REQUIRED);
|
|
2516
2950
|
|
|
2517
2951
|
assert.calledTwice(TriggerProxy.trigger);
|
|
2518
|
-
assert.calledWith(
|
|
2952
|
+
assert.calledWith(
|
|
2953
|
+
TriggerProxy.trigger,
|
|
2954
|
+
meeting,
|
|
2955
|
+
{file: 'meetings', function: 'fetchMeetingInfo'},
|
|
2956
|
+
'meeting:meetingInfoAvailable'
|
|
2957
|
+
);
|
|
2519
2958
|
});
|
|
2520
2959
|
|
|
2521
2960
|
it('fails if captchaCode is provided when captcha not needed', async () => {
|
|
2522
|
-
meeting.attrs.meetingInfoProvider = {
|
|
2961
|
+
meeting.attrs.meetingInfoProvider = {
|
|
2962
|
+
fetchMeetingInfo: sinon.stub().resolves({body: FAKE_MEETING_INFO}),
|
|
2963
|
+
};
|
|
2523
2964
|
meeting.requiredCaptcha = null;
|
|
2524
2965
|
meeting.destination = FAKE_DESTINATION;
|
|
2525
2966
|
meeting.destinationType = FAKE_TYPE;
|
|
2526
2967
|
|
|
2527
|
-
await assert.isRejected(
|
|
2528
|
-
|
|
2529
|
-
|
|
2968
|
+
await assert.isRejected(
|
|
2969
|
+
meeting.fetchMeetingInfo({
|
|
2970
|
+
captchaCode: FAKE_CAPTCHA_CODE,
|
|
2971
|
+
}),
|
|
2972
|
+
Error,
|
|
2973
|
+
'fetchMeetingInfo() called with captchaCode when captcha was not required'
|
|
2974
|
+
);
|
|
2530
2975
|
|
|
2531
2976
|
assert.notCalled(meeting.attrs.meetingInfoProvider.fetchMeetingInfo);
|
|
2532
2977
|
});
|
|
2533
2978
|
|
|
2534
2979
|
it('fails if password is provided when not required', async () => {
|
|
2535
|
-
meeting.attrs.meetingInfoProvider = {
|
|
2980
|
+
meeting.attrs.meetingInfoProvider = {
|
|
2981
|
+
fetchMeetingInfo: sinon.stub().resolves({body: FAKE_MEETING_INFO}),
|
|
2982
|
+
};
|
|
2536
2983
|
meeting.passwordStatus = PASSWORD_STATUS.NOT_REQUIRED;
|
|
2537
2984
|
meeting.destination = FAKE_DESTINATION;
|
|
2538
2985
|
meeting.destinationType = FAKE_TYPE;
|
|
2539
2986
|
|
|
2540
|
-
await assert.isRejected(
|
|
2541
|
-
|
|
2542
|
-
|
|
2987
|
+
await assert.isRejected(
|
|
2988
|
+
meeting.fetchMeetingInfo({
|
|
2989
|
+
password: FAKE_PASSWORD,
|
|
2990
|
+
}),
|
|
2991
|
+
Error,
|
|
2992
|
+
'fetchMeetingInfo() called with password when password was not required'
|
|
2993
|
+
);
|
|
2543
2994
|
|
|
2544
2995
|
assert.notCalled(meeting.attrs.meetingInfoProvider.fetchMeetingInfo);
|
|
2545
2996
|
});
|
|
@@ -2548,15 +2999,26 @@ describe('plugin-meetings', () => {
|
|
|
2548
2999
|
meeting.destination = FAKE_DESTINATION;
|
|
2549
3000
|
meeting.destinationType = FAKE_TYPE;
|
|
2550
3001
|
meeting.attrs.meetingInfoProvider = {
|
|
2551
|
-
fetchMeetingInfo: sinon
|
|
3002
|
+
fetchMeetingInfo: sinon
|
|
3003
|
+
.stub()
|
|
3004
|
+
.throws(new MeetingInfoV2PasswordError(403004, FAKE_MEETING_INFO)),
|
|
2552
3005
|
};
|
|
2553
3006
|
|
|
2554
3007
|
await assert.isRejected(meeting.fetchMeetingInfo({}), PasswordError);
|
|
2555
3008
|
|
|
2556
|
-
assert.calledWith(
|
|
3009
|
+
assert.calledWith(
|
|
3010
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
3011
|
+
FAKE_DESTINATION,
|
|
3012
|
+
FAKE_TYPE,
|
|
3013
|
+
null,
|
|
3014
|
+
null
|
|
3015
|
+
);
|
|
2557
3016
|
|
|
2558
3017
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
2559
|
-
assert.equal(
|
|
3018
|
+
assert.equal(
|
|
3019
|
+
meeting.meetingInfoFailureReason,
|
|
3020
|
+
MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD
|
|
3021
|
+
);
|
|
2560
3022
|
assert.equal(meeting.requiredCaptcha, null);
|
|
2561
3023
|
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.REQUIRED);
|
|
2562
3024
|
});
|
|
@@ -2565,25 +3027,38 @@ describe('plugin-meetings', () => {
|
|
|
2565
3027
|
meeting.destination = FAKE_DESTINATION;
|
|
2566
3028
|
meeting.destinationType = FAKE_TYPE;
|
|
2567
3029
|
meeting.attrs.meetingInfoProvider = {
|
|
2568
|
-
fetchMeetingInfo: sinon
|
|
3030
|
+
fetchMeetingInfo: sinon
|
|
3031
|
+
.stub()
|
|
3032
|
+
.throws(new MeetingInfoV2CaptchaError(423005, FAKE_SDK_CAPTCHA_INFO)),
|
|
2569
3033
|
};
|
|
2570
3034
|
meeting.requiredCaptcha = null;
|
|
2571
3035
|
|
|
2572
|
-
await assert.isRejected(
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
3036
|
+
await assert.isRejected(
|
|
3037
|
+
meeting.fetchMeetingInfo({
|
|
3038
|
+
password: 'aaa',
|
|
3039
|
+
}),
|
|
3040
|
+
CaptchaError
|
|
3041
|
+
);
|
|
2577
3042
|
|
|
3043
|
+
assert.calledWith(
|
|
3044
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
3045
|
+
FAKE_DESTINATION,
|
|
3046
|
+
FAKE_TYPE,
|
|
3047
|
+
'aaa',
|
|
3048
|
+
null
|
|
3049
|
+
);
|
|
2578
3050
|
|
|
2579
3051
|
assert.deepEqual(meeting.meetingInfo, {});
|
|
2580
|
-
assert.equal(
|
|
3052
|
+
assert.equal(
|
|
3053
|
+
meeting.meetingInfoFailureReason,
|
|
3054
|
+
MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD
|
|
3055
|
+
);
|
|
2581
3056
|
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.REQUIRED);
|
|
2582
3057
|
assert.deepEqual(meeting.requiredCaptcha, {
|
|
2583
3058
|
captchaId: FAKE_CAPTCHA_ID,
|
|
2584
3059
|
verificationImageURL: FAKE_CAPTCHA_IMAGE_URL,
|
|
2585
3060
|
verificationAudioURL: FAKE_CAPTCHA_AUDIO_URL,
|
|
2586
|
-
refreshURL: FAKE_CAPTCHA_REFRESH_URL
|
|
3061
|
+
refreshURL: FAKE_CAPTCHA_REFRESH_URL,
|
|
2587
3062
|
});
|
|
2588
3063
|
});
|
|
2589
3064
|
|
|
@@ -2591,15 +3066,27 @@ describe('plugin-meetings', () => {
|
|
|
2591
3066
|
meeting.destination = FAKE_DESTINATION;
|
|
2592
3067
|
meeting.destinationType = FAKE_TYPE;
|
|
2593
3068
|
meeting.attrs.meetingInfoProvider = {
|
|
2594
|
-
fetchMeetingInfo: sinon
|
|
3069
|
+
fetchMeetingInfo: sinon
|
|
3070
|
+
.stub()
|
|
3071
|
+
.throws(new MeetingInfoV2CaptchaError(423005, FAKE_SDK_CAPTCHA_INFO)),
|
|
2595
3072
|
};
|
|
2596
3073
|
meeting.requiredCaptcha = FAKE_SDK_CAPTCHA_INFO;
|
|
2597
3074
|
|
|
2598
|
-
await assert.isRejected(
|
|
2599
|
-
|
|
2600
|
-
|
|
3075
|
+
await assert.isRejected(
|
|
3076
|
+
meeting.fetchMeetingInfo({
|
|
3077
|
+
password: 'aaa',
|
|
3078
|
+
captchaCode: 'bbb',
|
|
3079
|
+
}),
|
|
3080
|
+
CaptchaError
|
|
3081
|
+
);
|
|
2601
3082
|
|
|
2602
|
-
assert.calledWith(
|
|
3083
|
+
assert.calledWith(
|
|
3084
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
3085
|
+
FAKE_DESTINATION,
|
|
3086
|
+
FAKE_TYPE,
|
|
3087
|
+
'aaa',
|
|
3088
|
+
{code: 'bbb', id: FAKE_CAPTCHA_ID}
|
|
3089
|
+
);
|
|
2603
3090
|
|
|
2604
3091
|
assert.deepEqual(meeting.meetingInfo, {});
|
|
2605
3092
|
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA);
|
|
@@ -2611,20 +3098,24 @@ describe('plugin-meetings', () => {
|
|
|
2611
3098
|
meeting.destination = FAKE_DESTINATION;
|
|
2612
3099
|
meeting.destinationType = FAKE_TYPE;
|
|
2613
3100
|
meeting.attrs.meetingInfoProvider = {
|
|
2614
|
-
fetchMeetingInfo: sinon.stub().resolves(
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
}
|
|
2619
|
-
)
|
|
3101
|
+
fetchMeetingInfo: sinon.stub().resolves({
|
|
3102
|
+
statusCode: 200,
|
|
3103
|
+
body: FAKE_MEETING_INFO,
|
|
3104
|
+
}),
|
|
2620
3105
|
};
|
|
2621
3106
|
meeting.passwordStatus = PASSWORD_STATUS.REQUIRED;
|
|
2622
3107
|
|
|
2623
3108
|
await meeting.fetchMeetingInfo({
|
|
2624
|
-
password: 'aaa'
|
|
3109
|
+
password: 'aaa',
|
|
2625
3110
|
});
|
|
2626
3111
|
|
|
2627
|
-
assert.calledWith(
|
|
3112
|
+
assert.calledWith(
|
|
3113
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
3114
|
+
FAKE_DESTINATION,
|
|
3115
|
+
FAKE_TYPE,
|
|
3116
|
+
'aaa',
|
|
3117
|
+
null
|
|
3118
|
+
);
|
|
2628
3119
|
|
|
2629
3120
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
2630
3121
|
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.NONE);
|
|
@@ -2638,36 +3129,50 @@ describe('plugin-meetings', () => {
|
|
|
2638
3129
|
const refreshedCaptcha = {
|
|
2639
3130
|
captchaID: FAKE_WBXAPPAPI_CAPTCHA_INFO.captchaID,
|
|
2640
3131
|
verificationImageURL: FAKE_WBXAPPAPI_CAPTCHA_INFO.verificationImageURL,
|
|
2641
|
-
verificationAudioURL: FAKE_WBXAPPAPI_CAPTCHA_INFO.verificationAudioURL
|
|
3132
|
+
verificationAudioURL: FAKE_WBXAPPAPI_CAPTCHA_INFO.verificationAudioURL,
|
|
2642
3133
|
};
|
|
2643
3134
|
|
|
2644
3135
|
meeting.attrs.meetingInfoProvider = {
|
|
2645
|
-
fetchMeetingInfo: sinon
|
|
3136
|
+
fetchMeetingInfo: sinon
|
|
3137
|
+
.stub()
|
|
3138
|
+
.throws(new MeetingInfoV2PasswordError(403004, FAKE_MEETING_INFO)),
|
|
2646
3139
|
};
|
|
2647
|
-
meeting.meetingRequest.refreshCaptcha = sinon.stub().returns(
|
|
2648
|
-
{
|
|
2649
|
-
body: refreshedCaptcha
|
|
2650
|
-
}
|
|
2651
|
-
)
|
|
3140
|
+
meeting.meetingRequest.refreshCaptcha = sinon.stub().returns(
|
|
3141
|
+
Promise.resolve({
|
|
3142
|
+
body: refreshedCaptcha,
|
|
3143
|
+
})
|
|
3144
|
+
);
|
|
2652
3145
|
meeting.passwordStatus = PASSWORD_STATUS.REQUIRED;
|
|
2653
3146
|
meeting.requiredCaptcha = FAKE_SDK_CAPTCHA_INFO;
|
|
2654
3147
|
meeting.destination = FAKE_DESTINATION;
|
|
2655
3148
|
meeting.destinationType = FAKE_TYPE;
|
|
2656
3149
|
|
|
2657
|
-
await assert.isRejected(
|
|
2658
|
-
|
|
2659
|
-
|
|
3150
|
+
await assert.isRejected(
|
|
3151
|
+
meeting.fetchMeetingInfo({
|
|
3152
|
+
password: 'aaa',
|
|
3153
|
+
captchaCode: 'bbb',
|
|
3154
|
+
})
|
|
3155
|
+
);
|
|
2660
3156
|
|
|
2661
|
-
assert.calledWith(
|
|
3157
|
+
assert.calledWith(
|
|
3158
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
3159
|
+
FAKE_DESTINATION,
|
|
3160
|
+
FAKE_TYPE,
|
|
3161
|
+
'aaa',
|
|
3162
|
+
{code: 'bbb', id: FAKE_CAPTCHA_ID}
|
|
3163
|
+
);
|
|
2662
3164
|
|
|
2663
3165
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
2664
|
-
assert.equal(
|
|
3166
|
+
assert.equal(
|
|
3167
|
+
meeting.meetingInfoFailureReason,
|
|
3168
|
+
MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD
|
|
3169
|
+
);
|
|
2665
3170
|
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.REQUIRED);
|
|
2666
3171
|
assert.deepEqual(meeting.requiredCaptcha, {
|
|
2667
3172
|
captchaId: refreshedCaptcha.captchaID,
|
|
2668
3173
|
verificationImageURL: refreshedCaptcha.verificationImageURL,
|
|
2669
3174
|
verificationAudioURL: refreshedCaptcha.verificationAudioURL,
|
|
2670
|
-
refreshURL: FAKE_SDK_CAPTCHA_INFO.refreshURL // refresh url doesn't change
|
|
3175
|
+
refreshURL: FAKE_SDK_CAPTCHA_INFO.refreshURL, // refresh url doesn't change
|
|
2671
3176
|
});
|
|
2672
3177
|
});
|
|
2673
3178
|
});
|
|
@@ -2677,48 +3182,56 @@ describe('plugin-meetings', () => {
|
|
|
2677
3182
|
assert.isRejected(meeting.refreshCaptcha(), Error);
|
|
2678
3183
|
});
|
|
2679
3184
|
it('sends correct request to captcha service refresh url', async () => {
|
|
2680
|
-
const REFRESH_URL =
|
|
2681
|
-
|
|
3185
|
+
const REFRESH_URL =
|
|
3186
|
+
'https://something.webex.com/captchaservice/v1/captchas/refresh?blablabla=something&captchaID=xxx';
|
|
3187
|
+
const EXPECTED_REFRESH_URL =
|
|
3188
|
+
'https://something.webex.com/captchaservice/v1/captchas/refresh?blablabla=something&captchaID=xxx&siteFullName=something.webex.com';
|
|
2682
3189
|
|
|
2683
3190
|
const FAKE_SDK_CAPTCHA_INFO = {
|
|
2684
3191
|
captchaId: 'some id',
|
|
2685
3192
|
verificationImageURL: 'some image url',
|
|
2686
3193
|
verificationAudioURL: 'some audio url',
|
|
2687
|
-
refreshURL: REFRESH_URL
|
|
3194
|
+
refreshURL: REFRESH_URL,
|
|
2688
3195
|
};
|
|
2689
3196
|
|
|
2690
3197
|
const FAKE_REFRESHED_CAPTCHA = {
|
|
2691
3198
|
captchaID: 'some id',
|
|
2692
3199
|
verificationImageURL: 'some image url',
|
|
2693
|
-
verificationAudioURL: 'some audio url'
|
|
3200
|
+
verificationAudioURL: 'some audio url',
|
|
2694
3201
|
};
|
|
2695
3202
|
|
|
2696
3203
|
// setup the meeting so that a captcha is required
|
|
2697
3204
|
meeting.attrs.meetingInfoProvider = {
|
|
2698
|
-
fetchMeetingInfo: sinon
|
|
3205
|
+
fetchMeetingInfo: sinon
|
|
3206
|
+
.stub()
|
|
3207
|
+
.throws(new MeetingInfoV2CaptchaError(423005, FAKE_SDK_CAPTCHA_INFO)),
|
|
2699
3208
|
};
|
|
2700
3209
|
|
|
2701
|
-
await assert.isRejected(
|
|
2702
|
-
|
|
2703
|
-
|
|
3210
|
+
await assert.isRejected(
|
|
3211
|
+
meeting.fetchMeetingInfo({
|
|
3212
|
+
password: '',
|
|
3213
|
+
}),
|
|
3214
|
+
CaptchaError
|
|
3215
|
+
);
|
|
2704
3216
|
|
|
2705
3217
|
assert.deepEqual(meeting.requiredCaptcha, FAKE_SDK_CAPTCHA_INFO);
|
|
2706
|
-
meeting.meetingRequest.refreshCaptcha = sinon
|
|
3218
|
+
meeting.meetingRequest.refreshCaptcha = sinon
|
|
3219
|
+
.stub()
|
|
3220
|
+
.returns(Promise.resolve({body: FAKE_REFRESHED_CAPTCHA}));
|
|
2707
3221
|
|
|
2708
3222
|
// test the captcha refresh
|
|
2709
3223
|
await meeting.refreshCaptcha();
|
|
2710
3224
|
|
|
2711
|
-
assert.calledWith(meeting.meetingRequest.refreshCaptcha,
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
});
|
|
3225
|
+
assert.calledWith(meeting.meetingRequest.refreshCaptcha, {
|
|
3226
|
+
captchaRefreshUrl: EXPECTED_REFRESH_URL,
|
|
3227
|
+
captchaId: FAKE_SDK_CAPTCHA_INFO.captchaId,
|
|
3228
|
+
});
|
|
2716
3229
|
|
|
2717
3230
|
assert.deepEqual(meeting.requiredCaptcha, {
|
|
2718
3231
|
captchaId: FAKE_REFRESHED_CAPTCHA.captchaID,
|
|
2719
3232
|
verificationImageURL: FAKE_REFRESHED_CAPTCHA.verificationImageURL,
|
|
2720
3233
|
verificationAudioURL: FAKE_REFRESHED_CAPTCHA.verificationAudioURL,
|
|
2721
|
-
refreshURL: FAKE_SDK_CAPTCHA_INFO.refreshURL // refresh url doesn't change
|
|
3234
|
+
refreshURL: FAKE_SDK_CAPTCHA_INFO.refreshURL, // refresh url doesn't change
|
|
2722
3235
|
});
|
|
2723
3236
|
});
|
|
2724
3237
|
});
|
|
@@ -2732,7 +3245,7 @@ describe('plugin-meetings', () => {
|
|
|
2732
3245
|
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
2733
3246
|
assert.calledWith(
|
|
2734
3247
|
Metrics.sendBehavioralMetric,
|
|
2735
|
-
BEHAVIORAL_METRICS.VERIFY_PASSWORD_SUCCESS
|
|
3248
|
+
BEHAVIORAL_METRICS.VERIFY_PASSWORD_SUCCESS
|
|
2736
3249
|
);
|
|
2737
3250
|
assert.equal(result.isPasswordValid, true);
|
|
2738
3251
|
assert.equal(result.requiredCaptcha, null);
|
|
@@ -2807,7 +3320,9 @@ describe('plugin-meetings', () => {
|
|
|
2807
3320
|
sandbox = sinon.createSandbox();
|
|
2808
3321
|
meeting.meetingFiniteStateMachine.ring();
|
|
2809
3322
|
meeting.meetingFiniteStateMachine.join();
|
|
2810
|
-
meeting.meetingRequest.endMeetingForAll = sinon
|
|
3323
|
+
meeting.meetingRequest.endMeetingForAll = sinon
|
|
3324
|
+
.stub()
|
|
3325
|
+
.returns(Promise.resolve({body: 'test'}));
|
|
2811
3326
|
meeting.locusInfo.onFullLocus = sinon.stub().returns(true);
|
|
2812
3327
|
meeting.closeLocalStream = sinon.stub().returns(Promise.resolve());
|
|
2813
3328
|
meeting.closeLocalShare = sinon.stub().returns(Promise.resolve());
|
|
@@ -2821,6 +3336,7 @@ describe('plugin-meetings', () => {
|
|
|
2821
3336
|
meeting.unsetRemoteStream = sinon.stub().returns(true);
|
|
2822
3337
|
meeting.unsetPeerConnections = sinon.stub().returns(true);
|
|
2823
3338
|
meeting.logger.error = sinon.stub().returns(true);
|
|
3339
|
+
meeting.updateLLMConnection = sinon.stub().returns(Promise.resolve());
|
|
2824
3340
|
|
|
2825
3341
|
// A meeting needs to be joined to end
|
|
2826
3342
|
meeting.meetingState = 'ACTIVE';
|
|
@@ -2859,7 +3375,11 @@ describe('plugin-meetings', () => {
|
|
|
2859
3375
|
sandbox.stub(meeting.mediaProperties, 'unsetMediaTracks');
|
|
2860
3376
|
|
|
2861
3377
|
sandbox.stub(meeting.reconnectionManager, 'reconnectMedia').returns(Promise.resolve());
|
|
2862
|
-
sandbox
|
|
3378
|
+
sandbox
|
|
3379
|
+
.stub(MeetingUtil, 'joinMeeting')
|
|
3380
|
+
.returns(
|
|
3381
|
+
Promise.resolve(MeetingUtil.parseLocusJoin({body: {locus, mediaConnections: []}}))
|
|
3382
|
+
);
|
|
2863
3383
|
});
|
|
2864
3384
|
|
|
2865
3385
|
afterEach(() => {
|
|
@@ -2870,8 +3390,7 @@ describe('plugin-meetings', () => {
|
|
|
2870
3390
|
it('should throw an error if resourceId not passed', async () => {
|
|
2871
3391
|
try {
|
|
2872
3392
|
await meeting.moveTo();
|
|
2873
|
-
}
|
|
2874
|
-
catch (err) {
|
|
3393
|
+
} catch (err) {
|
|
2875
3394
|
assert.instanceOf(err, ParameterError);
|
|
2876
3395
|
assert.equal(err.sdkMessage, 'Cannot move call without a resourceId.');
|
|
2877
3396
|
}
|
|
@@ -2888,17 +3407,17 @@ describe('plugin-meetings', () => {
|
|
|
2888
3407
|
share: true,
|
|
2889
3408
|
share_audio: false,
|
|
2890
3409
|
video: false,
|
|
2891
|
-
whiteboard: false
|
|
3410
|
+
whiteboard: false,
|
|
2892
3411
|
},
|
|
2893
3412
|
tx: {
|
|
2894
3413
|
audio: false,
|
|
2895
3414
|
share: false,
|
|
2896
3415
|
share_audio: false,
|
|
2897
3416
|
video: false,
|
|
2898
|
-
whiteboard: false
|
|
2899
|
-
}
|
|
2900
|
-
}
|
|
2901
|
-
}
|
|
3417
|
+
whiteboard: false,
|
|
3418
|
+
},
|
|
3419
|
+
},
|
|
3420
|
+
},
|
|
2902
3421
|
});
|
|
2903
3422
|
assert.calledWithMatch(Metrics.postEvent, {event: eventType.MOVE_MEDIA});
|
|
2904
3423
|
});
|
|
@@ -2907,17 +3426,19 @@ describe('plugin-meetings', () => {
|
|
|
2907
3426
|
sinon.spy(MeetingUtil, 'joinMeetingOptions');
|
|
2908
3427
|
await meeting.moveTo('resourceId');
|
|
2909
3428
|
|
|
2910
|
-
assert.calledWith(MeetingUtil.joinMeetingOptions, meeting, {
|
|
3429
|
+
assert.calledWith(MeetingUtil.joinMeetingOptions, meeting, {
|
|
3430
|
+
resourceId: 'resourceId',
|
|
3431
|
+
moveToResource: true,
|
|
3432
|
+
});
|
|
2911
3433
|
});
|
|
2912
3434
|
|
|
2913
3435
|
it('should reconnectMedia after DX joins after moveTo', async () => {
|
|
2914
3436
|
await meeting.moveTo('resourceId');
|
|
2915
3437
|
|
|
2916
|
-
|
|
2917
3438
|
await meeting.locusInfo.emitScoped(
|
|
2918
3439
|
{
|
|
2919
3440
|
file: 'locus-info',
|
|
2920
|
-
function: 'updateSelf'
|
|
3441
|
+
function: 'updateSelf',
|
|
2921
3442
|
},
|
|
2922
3443
|
'SELF_OBSERVING'
|
|
2923
3444
|
);
|
|
@@ -2933,36 +3454,30 @@ describe('plugin-meetings', () => {
|
|
|
2933
3454
|
assert.called(meeting.mediaProperties.setMediaDirection);
|
|
2934
3455
|
assert.called(meeting.mediaProperties.unsetMediaTracks);
|
|
2935
3456
|
|
|
2936
|
-
assert.calledWith(meeting.reconnectionManager.reconnectMedia,
|
|
2937
|
-
{
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
});
|
|
3457
|
+
assert.calledWith(meeting.reconnectionManager.reconnectMedia, {
|
|
3458
|
+
mediaDirection: {
|
|
3459
|
+
sendVideo: false,
|
|
3460
|
+
receiveVideo: false,
|
|
3461
|
+
sendAudio: false,
|
|
3462
|
+
receiveAudio: false,
|
|
3463
|
+
sendShare: false,
|
|
3464
|
+
receiveShare: true,
|
|
3465
|
+
},
|
|
3466
|
+
});
|
|
2947
3467
|
});
|
|
2948
3468
|
|
|
2949
3469
|
it('should throw an error if moveTo call fails', async () => {
|
|
2950
3470
|
MeetingUtil.joinMeeting = sinon.stub().returns(Promise.reject());
|
|
2951
3471
|
try {
|
|
2952
3472
|
await meeting.moveTo('resourceId');
|
|
2953
|
-
}
|
|
2954
|
-
catch {
|
|
3473
|
+
} catch {
|
|
2955
3474
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
2956
|
-
assert.calledWith(
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
reason: sinon.match.any,
|
|
2963
|
-
stack: sinon.match.any
|
|
2964
|
-
}
|
|
2965
|
-
);
|
|
3475
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.MOVE_TO_FAILURE, {
|
|
3476
|
+
correlation_id: meeting.correlationId,
|
|
3477
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
3478
|
+
reason: sinon.match.any,
|
|
3479
|
+
stack: sinon.match.any,
|
|
3480
|
+
});
|
|
2966
3481
|
}
|
|
2967
3482
|
Metrics.sendBehavioralMetric.reset();
|
|
2968
3483
|
meeting.reconnectionManager.reconnectMedia = sinon.stub().returns(Promise.reject());
|
|
@@ -2972,23 +3487,18 @@ describe('plugin-meetings', () => {
|
|
|
2972
3487
|
await meeting.locusInfo.emitScoped(
|
|
2973
3488
|
{
|
|
2974
3489
|
file: 'locus-info',
|
|
2975
|
-
function: 'updateSelf'
|
|
3490
|
+
function: 'updateSelf',
|
|
2976
3491
|
},
|
|
2977
3492
|
'SELF_OBSERVING'
|
|
2978
3493
|
);
|
|
2979
|
-
}
|
|
2980
|
-
catch {
|
|
3494
|
+
} catch {
|
|
2981
3495
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
2982
|
-
assert.calledWith(
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
reason: sinon.match.any,
|
|
2989
|
-
stack: sinon.match.any
|
|
2990
|
-
}
|
|
2991
|
-
);
|
|
3496
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.MOVE_TO_FAILURE, {
|
|
3497
|
+
correlation_id: meeting.correlationId,
|
|
3498
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
3499
|
+
reason: sinon.match.any,
|
|
3500
|
+
stack: sinon.match.any,
|
|
3501
|
+
});
|
|
2992
3502
|
}
|
|
2993
3503
|
});
|
|
2994
3504
|
});
|
|
@@ -2998,7 +3508,11 @@ describe('plugin-meetings', () => {
|
|
|
2998
3508
|
|
|
2999
3509
|
beforeEach(() => {
|
|
3000
3510
|
sandbox = sinon.createSandbox();
|
|
3001
|
-
sandbox
|
|
3511
|
+
sandbox
|
|
3512
|
+
.stub(MeetingUtil, 'joinMeeting')
|
|
3513
|
+
.returns(
|
|
3514
|
+
Promise.resolve(MeetingUtil.parseLocusJoin({body: {locus, mediaConnections: []}}))
|
|
3515
|
+
);
|
|
3002
3516
|
sandbox.stub(MeetingUtil, 'leaveMeeting').returns(Promise.resolve());
|
|
3003
3517
|
});
|
|
3004
3518
|
|
|
@@ -3010,8 +3524,7 @@ describe('plugin-meetings', () => {
|
|
|
3010
3524
|
it('should throw an error if resourceId not passed', async () => {
|
|
3011
3525
|
try {
|
|
3012
3526
|
await meeting.moveFrom();
|
|
3013
|
-
}
|
|
3014
|
-
catch (err) {
|
|
3527
|
+
} catch (err) {
|
|
3015
3528
|
assert.instanceOf(err, ParameterError);
|
|
3016
3529
|
|
|
3017
3530
|
assert.equal(err.sdkMessage, 'Cannot move call without a resourceId.');
|
|
@@ -3032,33 +3545,25 @@ describe('plugin-meetings', () => {
|
|
|
3032
3545
|
assert.calledWith(MeetingUtil.leaveMeeting, meeting, {
|
|
3033
3546
|
resourceId: 'resourceId',
|
|
3034
3547
|
correlationId: meeting.correlationId,
|
|
3035
|
-
moveMeeting: true
|
|
3548
|
+
moveMeeting: true,
|
|
3036
3549
|
});
|
|
3037
3550
|
|
|
3038
3551
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
3039
|
-
assert.calledWith(
|
|
3040
|
-
Metrics.sendBehavioralMetric,
|
|
3041
|
-
BEHAVIORAL_METRICS.MOVE_FROM_SUCCESS,
|
|
3042
|
-
);
|
|
3552
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.MOVE_FROM_SUCCESS);
|
|
3043
3553
|
});
|
|
3044
3554
|
|
|
3045
3555
|
it('should throw an error if moveFrom call fails', async () => {
|
|
3046
3556
|
MeetingUtil.joinMeeting = sinon.stub().returns(Promise.reject());
|
|
3047
3557
|
try {
|
|
3048
3558
|
await meeting.moveFrom('resourceId');
|
|
3049
|
-
}
|
|
3050
|
-
catch {
|
|
3559
|
+
} catch {
|
|
3051
3560
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
3052
|
-
assert.calledWith(
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
reason: sinon.match.any,
|
|
3059
|
-
stack: sinon.match.any
|
|
3060
|
-
}
|
|
3061
|
-
);
|
|
3561
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.MOVE_FROM_FAILURE, {
|
|
3562
|
+
correlation_id: meeting.correlationId,
|
|
3563
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
3564
|
+
reason: sinon.match.any,
|
|
3565
|
+
stack: sinon.match.any,
|
|
3566
|
+
});
|
|
3062
3567
|
}
|
|
3063
3568
|
});
|
|
3064
3569
|
});
|
|
@@ -3127,7 +3632,9 @@ describe('plugin-meetings', () => {
|
|
|
3127
3632
|
meeting.config.reconnection.enabled = true;
|
|
3128
3633
|
meeting.currentMediaStatus = {audio: true};
|
|
3129
3634
|
meeting.reconnectionManager = new ReconnectionManager(meeting);
|
|
3130
|
-
meeting.reconnectionManager.reconnect = sinon
|
|
3635
|
+
meeting.reconnectionManager.reconnect = sinon
|
|
3636
|
+
.stub()
|
|
3637
|
+
.returns(Promise.reject(new Error()));
|
|
3131
3638
|
meeting.reconnectionManager.reset = sinon.stub().returns(true);
|
|
3132
3639
|
});
|
|
3133
3640
|
|
|
@@ -3152,7 +3659,7 @@ describe('plugin-meetings', () => {
|
|
|
3152
3659
|
correlation_id: meeting.correlationId,
|
|
3153
3660
|
locus_id: meeting.locusUrl.split('/').pop(),
|
|
3154
3661
|
reason: sinon.match.any,
|
|
3155
|
-
stack: sinon.match.any
|
|
3662
|
+
stack: sinon.match.any,
|
|
3156
3663
|
}
|
|
3157
3664
|
);
|
|
3158
3665
|
});
|
|
@@ -3164,7 +3671,7 @@ describe('plugin-meetings', () => {
|
|
|
3164
3671
|
sinon.match.instanceOf(Meeting),
|
|
3165
3672
|
{file: 'meeting/index', function: 'reconnect'},
|
|
3166
3673
|
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
3167
|
-
sinon.match.instanceOf(Meeting)
|
|
3674
|
+
sinon.match.instanceOf(Meeting)
|
|
3168
3675
|
);
|
|
3169
3676
|
});
|
|
3170
3677
|
|
|
@@ -3248,8 +3755,8 @@ describe('plugin-meetings', () => {
|
|
|
3248
3755
|
height: 1980,
|
|
3249
3756
|
width: 1080,
|
|
3250
3757
|
displaySurface: true,
|
|
3251
|
-
cursor: true
|
|
3252
|
-
})
|
|
3758
|
+
cursor: true,
|
|
3759
|
+
}),
|
|
3253
3760
|
};
|
|
3254
3761
|
const getVideoTracks = sinon.stub().returns([track]);
|
|
3255
3762
|
|
|
@@ -3281,33 +3788,51 @@ describe('plugin-meetings', () => {
|
|
|
3281
3788
|
// mock the on() method and store all the listeners
|
|
3282
3789
|
on: sinon.stub().callsFake((event, listener) => {
|
|
3283
3790
|
eventListeners[event] = listener;
|
|
3284
|
-
})
|
|
3791
|
+
}),
|
|
3285
3792
|
};
|
|
3286
3793
|
});
|
|
3287
3794
|
|
|
3288
3795
|
it('should register for all the correct RoapMediaConnection events', () => {
|
|
3289
3796
|
meeting.setupMediaConnectionListeners();
|
|
3290
|
-
assert.isFunction(eventListeners[
|
|
3291
|
-
assert.isFunction(eventListeners[
|
|
3292
|
-
assert.isFunction(eventListeners[
|
|
3293
|
-
assert.isFunction(eventListeners[
|
|
3294
|
-
assert.isFunction(eventListeners[
|
|
3295
|
-
assert.isFunction(eventListeners[
|
|
3797
|
+
assert.isFunction(eventListeners[Event.ROAP_STARTED]);
|
|
3798
|
+
assert.isFunction(eventListeners[Event.ROAP_DONE]);
|
|
3799
|
+
assert.isFunction(eventListeners[Event.ROAP_FAILURE]);
|
|
3800
|
+
assert.isFunction(eventListeners[Event.ROAP_MESSAGE_TO_SEND]);
|
|
3801
|
+
assert.isFunction(eventListeners[Event.REMOTE_TRACK_ADDED]);
|
|
3802
|
+
assert.isFunction(eventListeners[Event.CONNECTION_STATE_CHANGED]);
|
|
3296
3803
|
});
|
|
3297
3804
|
|
|
3298
3805
|
it('should trigger a media:ready event when REMOTE_TRACK_ADDED is fired', () => {
|
|
3299
3806
|
meeting.setupMediaConnectionListeners();
|
|
3300
|
-
eventListeners[
|
|
3807
|
+
eventListeners[Event.REMOTE_TRACK_ADDED]({
|
|
3808
|
+
track: 'track',
|
|
3809
|
+
type: RemoteTrackType.AUDIO,
|
|
3810
|
+
});
|
|
3301
3811
|
assert.equal(TriggerProxy.trigger.getCall(1).args[2], 'media:ready');
|
|
3302
|
-
assert.deepEqual(TriggerProxy.trigger.getCall(1).args[3], {
|
|
3812
|
+
assert.deepEqual(TriggerProxy.trigger.getCall(1).args[3], {
|
|
3813
|
+
type: 'remoteAudio',
|
|
3814
|
+
stream: true,
|
|
3815
|
+
});
|
|
3303
3816
|
|
|
3304
|
-
eventListeners[
|
|
3817
|
+
eventListeners[Event.REMOTE_TRACK_ADDED]({
|
|
3818
|
+
track: 'track',
|
|
3819
|
+
type: RemoteTrackType.VIDEO,
|
|
3820
|
+
});
|
|
3305
3821
|
assert.equal(TriggerProxy.trigger.getCall(2).args[2], 'media:ready');
|
|
3306
|
-
assert.deepEqual(TriggerProxy.trigger.getCall(2).args[3], {
|
|
3822
|
+
assert.deepEqual(TriggerProxy.trigger.getCall(2).args[3], {
|
|
3823
|
+
type: 'remoteVideo',
|
|
3824
|
+
stream: true,
|
|
3825
|
+
});
|
|
3307
3826
|
|
|
3308
|
-
eventListeners[
|
|
3827
|
+
eventListeners[Event.REMOTE_TRACK_ADDED]({
|
|
3828
|
+
track: 'track',
|
|
3829
|
+
type: RemoteTrackType.SCREENSHARE_VIDEO,
|
|
3830
|
+
});
|
|
3309
3831
|
assert.equal(TriggerProxy.trigger.getCall(3).args[2], 'media:ready');
|
|
3310
|
-
assert.deepEqual(TriggerProxy.trigger.getCall(3).args[3], {
|
|
3832
|
+
assert.deepEqual(TriggerProxy.trigger.getCall(3).args[3], {
|
|
3833
|
+
type: 'remoteShare',
|
|
3834
|
+
stream: true,
|
|
3835
|
+
});
|
|
3311
3836
|
});
|
|
3312
3837
|
|
|
3313
3838
|
describe('should send correct metrics for ROAP_FAILURE event', () => {
|
|
@@ -3321,10 +3846,19 @@ describe('plugin-meetings', () => {
|
|
|
3321
3846
|
|
|
3322
3847
|
const checkMetricSent = (event) => {
|
|
3323
3848
|
assert.calledOnce(Metrics.postEvent);
|
|
3324
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
3849
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
3850
|
+
event,
|
|
3851
|
+
meetingId: meeting.id,
|
|
3852
|
+
data: {canProceed: false},
|
|
3853
|
+
});
|
|
3325
3854
|
};
|
|
3326
3855
|
|
|
3327
|
-
const checkBehavioralMetricSent = (
|
|
3856
|
+
const checkBehavioralMetricSent = (
|
|
3857
|
+
metricName,
|
|
3858
|
+
expectedCode,
|
|
3859
|
+
expectedReason,
|
|
3860
|
+
expectedMetadataType
|
|
3861
|
+
) => {
|
|
3328
3862
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
3329
3863
|
assert.calledWith(
|
|
3330
3864
|
Metrics.sendBehavioralMetric,
|
|
@@ -3333,65 +3867,101 @@ describe('plugin-meetings', () => {
|
|
|
3333
3867
|
code: expectedCode,
|
|
3334
3868
|
correlation_id: meeting.correlationId,
|
|
3335
3869
|
reason: expectedReason,
|
|
3336
|
-
stack: sinon.match.any
|
|
3870
|
+
stack: sinon.match.any,
|
|
3337
3871
|
},
|
|
3338
3872
|
{
|
|
3339
|
-
type: expectedMetadataType
|
|
3873
|
+
type: expectedMetadataType,
|
|
3340
3874
|
}
|
|
3341
3875
|
);
|
|
3342
3876
|
};
|
|
3343
3877
|
|
|
3344
3878
|
it('should send metrics for SdpOfferCreationError error', () => {
|
|
3345
|
-
const fakeError = new
|
|
3879
|
+
const fakeError = new Errors.SdpOfferCreationError(fakeErrorMessage, {
|
|
3880
|
+
name: fakeErrorName,
|
|
3881
|
+
cause: {name: fakeRootCauseName},
|
|
3882
|
+
});
|
|
3346
3883
|
|
|
3347
|
-
eventListeners[
|
|
3884
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3348
3885
|
|
|
3349
3886
|
checkMetricSent(eventType.LOCAL_SDP_GENERATED);
|
|
3350
|
-
checkBehavioralMetricSent(
|
|
3887
|
+
checkBehavioralMetricSent(
|
|
3888
|
+
BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
|
|
3889
|
+
Errors.ErrorCode.SdpOfferCreationError,
|
|
3890
|
+
fakeErrorMessage,
|
|
3891
|
+
fakeRootCauseName
|
|
3892
|
+
);
|
|
3351
3893
|
});
|
|
3352
3894
|
|
|
3353
3895
|
it('should send metrics for SdpOfferHandlingError error', () => {
|
|
3354
|
-
const fakeError = new
|
|
3896
|
+
const fakeError = new Errors.SdpOfferHandlingError(fakeErrorMessage, {
|
|
3897
|
+
name: fakeErrorName,
|
|
3898
|
+
cause: {name: fakeRootCauseName},
|
|
3899
|
+
});
|
|
3355
3900
|
|
|
3356
|
-
eventListeners[
|
|
3901
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3357
3902
|
|
|
3358
3903
|
checkMetricSent(eventType.REMOTE_SDP_RECEIVED);
|
|
3359
|
-
checkBehavioralMetricSent(
|
|
3904
|
+
checkBehavioralMetricSent(
|
|
3905
|
+
BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
|
|
3906
|
+
Errors.ErrorCode.SdpOfferHandlingError,
|
|
3907
|
+
fakeErrorMessage,
|
|
3908
|
+
fakeRootCauseName
|
|
3909
|
+
);
|
|
3360
3910
|
});
|
|
3361
3911
|
|
|
3362
3912
|
it('should send metrics for SdpAnswerHandlingError error', () => {
|
|
3363
|
-
const fakeError = new
|
|
3913
|
+
const fakeError = new Errors.SdpAnswerHandlingError(fakeErrorMessage, {
|
|
3914
|
+
name: fakeErrorName,
|
|
3915
|
+
cause: {name: fakeRootCauseName},
|
|
3916
|
+
});
|
|
3364
3917
|
|
|
3365
|
-
eventListeners[
|
|
3918
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3366
3919
|
|
|
3367
3920
|
checkMetricSent(eventType.REMOTE_SDP_RECEIVED);
|
|
3368
|
-
checkBehavioralMetricSent(
|
|
3921
|
+
checkBehavioralMetricSent(
|
|
3922
|
+
BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
|
|
3923
|
+
Errors.ErrorCode.SdpAnswerHandlingError,
|
|
3924
|
+
fakeErrorMessage,
|
|
3925
|
+
fakeRootCauseName
|
|
3926
|
+
);
|
|
3369
3927
|
});
|
|
3370
3928
|
|
|
3371
3929
|
it('should send metrics for SdpError error', () => {
|
|
3372
3930
|
// SdpError is usually without a cause
|
|
3373
|
-
const fakeError = new
|
|
3931
|
+
const fakeError = new Errors.SdpError(fakeErrorMessage, {name: fakeErrorName});
|
|
3374
3932
|
|
|
3375
|
-
eventListeners[
|
|
3933
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3376
3934
|
|
|
3377
3935
|
checkMetricSent(eventType.LOCAL_SDP_GENERATED);
|
|
3378
3936
|
// expectedMetadataType is the error name in this case
|
|
3379
|
-
checkBehavioralMetricSent(
|
|
3937
|
+
checkBehavioralMetricSent(
|
|
3938
|
+
BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE,
|
|
3939
|
+
Errors.ErrorCode.SdpError,
|
|
3940
|
+
fakeErrorMessage,
|
|
3941
|
+
fakeErrorName
|
|
3942
|
+
);
|
|
3380
3943
|
});
|
|
3381
3944
|
|
|
3382
3945
|
it('should send metrics for IceGatheringError error', () => {
|
|
3383
3946
|
// IceGatheringError is usually without a cause
|
|
3384
|
-
const fakeError = new
|
|
3947
|
+
const fakeError = new Errors.IceGatheringError(fakeErrorMessage, {
|
|
3948
|
+
name: fakeErrorName,
|
|
3949
|
+
});
|
|
3385
3950
|
|
|
3386
|
-
eventListeners[
|
|
3951
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3387
3952
|
|
|
3388
3953
|
checkMetricSent(eventType.LOCAL_SDP_GENERATED);
|
|
3389
3954
|
// expectedMetadataType is the error name in this case
|
|
3390
|
-
checkBehavioralMetricSent(
|
|
3955
|
+
checkBehavioralMetricSent(
|
|
3956
|
+
BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE,
|
|
3957
|
+
Errors.ErrorCode.IceGatheringError,
|
|
3958
|
+
fakeErrorMessage,
|
|
3959
|
+
fakeErrorName
|
|
3960
|
+
);
|
|
3391
3961
|
});
|
|
3392
3962
|
});
|
|
3393
3963
|
|
|
3394
|
-
describe('handles
|
|
3964
|
+
describe('handles Event.ROAP_MESSAGE_TO_SEND correctly', () => {
|
|
3395
3965
|
let sendRoapOKStub;
|
|
3396
3966
|
let sendRoapMediaRequestStub;
|
|
3397
3967
|
let sendRoapAnswerStub;
|
|
@@ -3399,7 +3969,9 @@ describe('plugin-meetings', () => {
|
|
|
3399
3969
|
|
|
3400
3970
|
beforeEach(() => {
|
|
3401
3971
|
sendRoapOKStub = sinon.stub(meeting.roap, 'sendRoapOK').resolves({});
|
|
3402
|
-
sendRoapMediaRequestStub = sinon
|
|
3972
|
+
sendRoapMediaRequestStub = sinon
|
|
3973
|
+
.stub(meeting.roap, 'sendRoapMediaRequest')
|
|
3974
|
+
.resolves({});
|
|
3403
3975
|
sendRoapAnswerStub = sinon.stub(meeting.roap, 'sendRoapAnswer').resolves({});
|
|
3404
3976
|
sendRoapErrorStub = sinon.stub(meeting.roap, 'sendRoapError').resolves({});
|
|
3405
3977
|
|
|
@@ -3407,106 +3979,140 @@ describe('plugin-meetings', () => {
|
|
|
3407
3979
|
});
|
|
3408
3980
|
|
|
3409
3981
|
it('handles OK message correctly', () => {
|
|
3410
|
-
eventListeners[
|
|
3982
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3983
|
+
roapMessage: {messageType: 'OK', seq: 1},
|
|
3984
|
+
});
|
|
3411
3985
|
|
|
3412
3986
|
assert.calledOnce(Metrics.postEvent);
|
|
3413
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
3987
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
3988
|
+
event: eventType.REMOTE_SDP_RECEIVED,
|
|
3989
|
+
meetingId: meeting.id,
|
|
3990
|
+
});
|
|
3414
3991
|
|
|
3415
3992
|
assert.calledOnce(sendRoapOKStub);
|
|
3416
|
-
assert.calledWith(sendRoapOKStub, {
|
|
3993
|
+
assert.calledWith(sendRoapOKStub, {
|
|
3994
|
+
seq: 1,
|
|
3995
|
+
mediaId: meeting.mediaId,
|
|
3996
|
+
correlationId: meeting.correlationId,
|
|
3997
|
+
});
|
|
3417
3998
|
});
|
|
3418
3999
|
|
|
3419
4000
|
it('handles OFFER message correctly', () => {
|
|
3420
|
-
eventListeners[
|
|
4001
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3421
4002
|
roapMessage: {
|
|
3422
4003
|
messageType: 'OFFER',
|
|
3423
4004
|
seq: 1,
|
|
3424
4005
|
sdp: 'fake sdp',
|
|
3425
4006
|
tieBreaker: 12345,
|
|
3426
|
-
}
|
|
4007
|
+
},
|
|
3427
4008
|
});
|
|
3428
4009
|
|
|
3429
4010
|
assert.calledOnce(Metrics.postEvent);
|
|
3430
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
4011
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
4012
|
+
event: eventType.LOCAL_SDP_GENERATED,
|
|
4013
|
+
meetingId: meeting.id,
|
|
4014
|
+
});
|
|
3431
4015
|
|
|
3432
4016
|
assert.calledOnce(sendRoapMediaRequestStub);
|
|
3433
4017
|
assert.calledWith(sendRoapMediaRequestStub, {
|
|
3434
|
-
seq: 1,
|
|
4018
|
+
seq: 1,
|
|
4019
|
+
sdp: 'fake sdp',
|
|
4020
|
+
tieBreaker: 12345,
|
|
4021
|
+
meeting,
|
|
4022
|
+
reconnect: false,
|
|
3435
4023
|
});
|
|
3436
4024
|
});
|
|
3437
4025
|
|
|
3438
4026
|
it('handles ANSWER message correctly', () => {
|
|
3439
|
-
eventListeners[
|
|
4027
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3440
4028
|
roapMessage: {
|
|
3441
4029
|
messageType: 'ANSWER',
|
|
3442
4030
|
seq: 10,
|
|
3443
4031
|
sdp: 'fake sdp answer',
|
|
3444
4032
|
tieBreaker: 12345,
|
|
3445
|
-
}
|
|
4033
|
+
},
|
|
3446
4034
|
});
|
|
3447
4035
|
|
|
3448
4036
|
assert.calledOnce(Metrics.postEvent);
|
|
3449
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
4037
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
4038
|
+
event: eventType.REMOTE_SDP_RECEIVED,
|
|
4039
|
+
meetingId: meeting.id,
|
|
4040
|
+
});
|
|
3450
4041
|
|
|
3451
4042
|
assert.calledOnce(sendRoapAnswerStub);
|
|
3452
4043
|
assert.calledWith(sendRoapAnswerStub, {
|
|
3453
|
-
seq: 10,
|
|
4044
|
+
seq: 10,
|
|
4045
|
+
sdp: 'fake sdp answer',
|
|
4046
|
+
mediaId: meeting.mediaId,
|
|
4047
|
+
correlationId: meeting.correlationId,
|
|
3454
4048
|
});
|
|
3455
4049
|
});
|
|
3456
4050
|
|
|
3457
4051
|
it('sends metrics if fails to send roap ANSWER message', async () => {
|
|
3458
4052
|
sendRoapAnswerStub.rejects(new Error('sending answer failed'));
|
|
3459
4053
|
|
|
3460
|
-
await eventListeners[
|
|
4054
|
+
await eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3461
4055
|
roapMessage: {
|
|
3462
4056
|
messageType: 'ANSWER',
|
|
3463
4057
|
seq: 10,
|
|
3464
4058
|
sdp: 'fake sdp answer',
|
|
3465
4059
|
tieBreaker: 12345,
|
|
3466
|
-
}
|
|
4060
|
+
},
|
|
3467
4061
|
});
|
|
3468
4062
|
await testUtils.flushPromises();
|
|
3469
4063
|
|
|
3470
4064
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
3471
|
-
assert.calledWithMatch(
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
4065
|
+
assert.calledWithMatch(
|
|
4066
|
+
Metrics.sendBehavioralMetric,
|
|
4067
|
+
BEHAVIORAL_METRICS.ROAP_ANSWER_FAILURE,
|
|
4068
|
+
{
|
|
4069
|
+
correlation_id: meeting.correlationId,
|
|
4070
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
4071
|
+
reason: 'sending answer failed',
|
|
4072
|
+
}
|
|
4073
|
+
);
|
|
3476
4074
|
});
|
|
3477
4075
|
|
|
3478
|
-
[
|
|
4076
|
+
[ErrorType.CONFLICT, ErrorType.DOUBLECONFLICT].forEach((errorType) =>
|
|
3479
4077
|
it(`handles ERROR message indicating glare condition correctly (errorType=${errorType})`, () => {
|
|
3480
|
-
eventListeners[
|
|
4078
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3481
4079
|
roapMessage: {
|
|
3482
4080
|
messageType: 'ERROR',
|
|
3483
4081
|
seq: 10,
|
|
3484
4082
|
errorType,
|
|
3485
4083
|
tieBreaker: 12345,
|
|
3486
|
-
}
|
|
4084
|
+
},
|
|
3487
4085
|
});
|
|
3488
4086
|
|
|
3489
4087
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
3490
|
-
assert.calledWithMatch(
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
4088
|
+
assert.calledWithMatch(
|
|
4089
|
+
Metrics.sendBehavioralMetric,
|
|
4090
|
+
BEHAVIORAL_METRICS.ROAP_GLARE_CONDITION,
|
|
4091
|
+
{
|
|
4092
|
+
correlation_id: meeting.correlationId,
|
|
4093
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
4094
|
+
sequence: 10,
|
|
4095
|
+
}
|
|
4096
|
+
);
|
|
3495
4097
|
|
|
3496
4098
|
assert.calledOnce(sendRoapErrorStub);
|
|
3497
4099
|
assert.calledWith(sendRoapErrorStub, {
|
|
3498
|
-
seq: 10,
|
|
4100
|
+
seq: 10,
|
|
4101
|
+
errorType,
|
|
4102
|
+
mediaId: meeting.mediaId,
|
|
4103
|
+
correlationId: meeting.correlationId,
|
|
3499
4104
|
});
|
|
3500
|
-
})
|
|
4105
|
+
})
|
|
4106
|
+
);
|
|
3501
4107
|
|
|
3502
4108
|
it('handles ERROR message indicating other errors correctly', () => {
|
|
3503
|
-
eventListeners[
|
|
4109
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3504
4110
|
roapMessage: {
|
|
3505
4111
|
messageType: 'ERROR',
|
|
3506
4112
|
seq: 10,
|
|
3507
|
-
errorType:
|
|
4113
|
+
errorType: ErrorType.FAILED,
|
|
3508
4114
|
tieBreaker: 12345,
|
|
3509
|
-
}
|
|
4115
|
+
},
|
|
3510
4116
|
});
|
|
3511
4117
|
|
|
3512
4118
|
assert.notCalled(Metrics.sendBehavioralMetric);
|
|
@@ -3514,9 +4120,9 @@ describe('plugin-meetings', () => {
|
|
|
3514
4120
|
assert.calledOnce(sendRoapErrorStub);
|
|
3515
4121
|
assert.calledWith(sendRoapErrorStub, {
|
|
3516
4122
|
seq: 10,
|
|
3517
|
-
errorType:
|
|
4123
|
+
errorType: ErrorType.FAILED,
|
|
3518
4124
|
mediaId: meeting.mediaId,
|
|
3519
|
-
correlationId: meeting.correlationId
|
|
4125
|
+
correlationId: meeting.correlationId,
|
|
3520
4126
|
});
|
|
3521
4127
|
});
|
|
3522
4128
|
});
|
|
@@ -3550,6 +4156,83 @@ describe('plugin-meetings', () => {
|
|
|
3550
4156
|
);
|
|
3551
4157
|
done();
|
|
3552
4158
|
});
|
|
4159
|
+
|
|
4160
|
+
it('listens to the breakouts changed event', () => {
|
|
4161
|
+
meeting.breakouts.updateBreakoutSessions = sinon.stub();
|
|
4162
|
+
|
|
4163
|
+
const payload = 'payload';
|
|
4164
|
+
|
|
4165
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'SELF_MEETING_BREAKOUTS_CHANGED', payload);
|
|
4166
|
+
|
|
4167
|
+
assert.calledOnceWithExactly(meeting.breakouts.updateBreakoutSessions, payload);
|
|
4168
|
+
assert.calledWith(
|
|
4169
|
+
TriggerProxy.trigger,
|
|
4170
|
+
meeting,
|
|
4171
|
+
{file: 'meeting/index', function: 'setUpLocusInfoSelfListener'},
|
|
4172
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
4173
|
+
);
|
|
4174
|
+
});
|
|
4175
|
+
});
|
|
4176
|
+
|
|
4177
|
+
describe('#setUpBreakoutsListener', () => {
|
|
4178
|
+
it('listens to the closing event from breakouts and triggers the closing event', () => {
|
|
4179
|
+
TriggerProxy.trigger.reset();
|
|
4180
|
+
meeting.breakouts.trigger('BREAKOUTS_CLOSING');
|
|
4181
|
+
|
|
4182
|
+
assert.calledWith(
|
|
4183
|
+
TriggerProxy.trigger,
|
|
4184
|
+
meeting,
|
|
4185
|
+
{file: 'meeting/index', function: 'setUpBreakoutsListener'},
|
|
4186
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_CLOSING
|
|
4187
|
+
);
|
|
4188
|
+
});
|
|
4189
|
+
|
|
4190
|
+
it('listens to the message event from breakouts and triggers the message event', () => {
|
|
4191
|
+
TriggerProxy.trigger.reset();
|
|
4192
|
+
|
|
4193
|
+
const messageEvent = 'message';
|
|
4194
|
+
|
|
4195
|
+
meeting.breakouts.trigger('MESSAGE', messageEvent);
|
|
4196
|
+
|
|
4197
|
+
assert.calledWith(
|
|
4198
|
+
TriggerProxy.trigger,
|
|
4199
|
+
meeting,
|
|
4200
|
+
{file: 'meeting/index', function: 'setUpBreakoutsListener'},
|
|
4201
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_MESSAGE,
|
|
4202
|
+
messageEvent
|
|
4203
|
+
);
|
|
4204
|
+
});
|
|
4205
|
+
|
|
4206
|
+
it('listens to the members update event from breakouts and triggers the breakouts update event', () => {
|
|
4207
|
+
TriggerProxy.trigger.reset();
|
|
4208
|
+
meeting.breakouts.trigger('MEMBERS_UPDATE');
|
|
4209
|
+
|
|
4210
|
+
assert.calledWith(
|
|
4211
|
+
TriggerProxy.trigger,
|
|
4212
|
+
meeting,
|
|
4213
|
+
{file: 'meeting/index', function: 'setUpBreakoutsListener'},
|
|
4214
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
4215
|
+
);
|
|
4216
|
+
});
|
|
4217
|
+
});
|
|
4218
|
+
|
|
4219
|
+
describe('#setupLocusControlsListener', () => {
|
|
4220
|
+
it('listens to the locus breakouts update event', () => {
|
|
4221
|
+
const locus = {
|
|
4222
|
+
breakout: 'breakout'
|
|
4223
|
+
};
|
|
4224
|
+
|
|
4225
|
+
meeting.breakouts.updateBreakout = sinon.stub();
|
|
4226
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'CONTROLS_MEETING_BREAKOUT_UPDATED', locus);
|
|
4227
|
+
|
|
4228
|
+
assert.calledOnceWithExactly(meeting.breakouts.updateBreakout, locus.breakout);
|
|
4229
|
+
assert.calledWith(
|
|
4230
|
+
TriggerProxy.trigger,
|
|
4231
|
+
meeting,
|
|
4232
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
4233
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
4234
|
+
);
|
|
4235
|
+
});
|
|
3553
4236
|
});
|
|
3554
4237
|
|
|
3555
4238
|
describe('#setUpLocusUrlListener', () => {
|
|
@@ -3557,21 +4240,55 @@ describe('plugin-meetings', () => {
|
|
|
3557
4240
|
const newLocusUrl = 'newLocusUrl/12345';
|
|
3558
4241
|
|
|
3559
4242
|
meeting.members = {locusUrlUpdate: sinon.stub().returns(Promise.resolve(test1))};
|
|
4243
|
+
meeting.recordingController = {setLocusUrl: sinon.stub().returns(undefined)};
|
|
4244
|
+
|
|
4245
|
+
meeting.breakouts.locusUrlUpdate = sinon.stub();
|
|
3560
4246
|
|
|
3561
4247
|
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'LOCUS_INFO_UPDATE_URL', newLocusUrl);
|
|
3562
4248
|
assert.calledWith(
|
|
3563
4249
|
meeting.members.locusUrlUpdate,
|
|
3564
4250
|
newLocusUrl
|
|
3565
4251
|
);
|
|
4252
|
+
assert.calledOnceWithExactly(meeting.breakouts.locusUrlUpdate, newLocusUrl);
|
|
4253
|
+
assert.calledWith(meeting.members.locusUrlUpdate, newLocusUrl);
|
|
4254
|
+
assert.calledWith(meeting.recordingController.setLocusUrl, newLocusUrl);
|
|
3566
4255
|
assert.equal(meeting.locusUrl, newLocusUrl);
|
|
3567
4256
|
assert(meeting.locusId, '12345');
|
|
3568
4257
|
done();
|
|
3569
4258
|
});
|
|
3570
4259
|
});
|
|
4260
|
+
|
|
4261
|
+
describe('#setUpLocusServicesListener', () => {
|
|
4262
|
+
it('listens to the locus services update event', (done) => {
|
|
4263
|
+
const newLocusServices = {
|
|
4264
|
+
services: {
|
|
4265
|
+
record: {
|
|
4266
|
+
url: 'url',
|
|
4267
|
+
}
|
|
4268
|
+
},
|
|
4269
|
+
};
|
|
4270
|
+
|
|
4271
|
+
meeting.recordingController = {setServiceUrl: sinon.stub().returns(undefined), setSessionId: sinon.stub().returns(undefined)};
|
|
4272
|
+
|
|
4273
|
+
meeting.locusInfo.emit(
|
|
4274
|
+
{function: 'test', file: 'test'},
|
|
4275
|
+
'LINKS_SERVICES',
|
|
4276
|
+
newLocusServices
|
|
4277
|
+
);
|
|
4278
|
+
|
|
4279
|
+
assert.calledWith(meeting.recordingController.setServiceUrl, newLocusServices.services.record.url);
|
|
4280
|
+
assert.calledOnce(meeting.recordingController.setSessionId);
|
|
4281
|
+
done();
|
|
4282
|
+
});
|
|
4283
|
+
});
|
|
3571
4284
|
describe('#setUpLocusInfoMediaInactiveListener', () => {
|
|
3572
4285
|
it('listens to disconnect due to un activity ', (done) => {
|
|
3573
4286
|
TriggerProxy.trigger.reset();
|
|
3574
|
-
meeting.locusInfo.emit(
|
|
4287
|
+
meeting.locusInfo.emit(
|
|
4288
|
+
{function: 'test', file: 'test'},
|
|
4289
|
+
EVENTS.DISCONNECT_DUE_TO_INACTIVITY,
|
|
4290
|
+
{reason: 'inactive'}
|
|
4291
|
+
);
|
|
3575
4292
|
assert.calledTwice(TriggerProxy.trigger);
|
|
3576
4293
|
|
|
3577
4294
|
assert.calledWith(
|
|
@@ -3598,7 +4315,11 @@ describe('plugin-meetings', () => {
|
|
|
3598
4315
|
sinon.stub(meeting, 'reconnect');
|
|
3599
4316
|
|
|
3600
4317
|
meeting.config.reconnection.autoRejoin = true;
|
|
3601
|
-
meeting.locusInfo.emit(
|
|
4318
|
+
meeting.locusInfo.emit(
|
|
4319
|
+
{function: 'test', file: 'test'},
|
|
4320
|
+
EVENTS.DISCONNECT_DUE_TO_INACTIVITY,
|
|
4321
|
+
{reason: 'inactive'}
|
|
4322
|
+
);
|
|
3602
4323
|
assert.calledOnce(TriggerProxy.trigger);
|
|
3603
4324
|
|
|
3604
4325
|
assert.calledWith(
|
|
@@ -3623,7 +4344,10 @@ describe('plugin-meetings', () => {
|
|
|
3623
4344
|
sinon.stub(meeting.reconnectionManager, 'cleanUp');
|
|
3624
4345
|
sinon.spy(MeetingUtil, 'cleanUp');
|
|
3625
4346
|
|
|
3626
|
-
meeting.locusInfo.emit({function: 'test', file: 'test'}, EVENTS.DESTROY_MEETING, {
|
|
4347
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, EVENTS.DESTROY_MEETING, {
|
|
4348
|
+
shouldLeave: false,
|
|
4349
|
+
reason: 'ended',
|
|
4350
|
+
});
|
|
3627
4351
|
assert.calledOnce(TriggerProxy.trigger);
|
|
3628
4352
|
assert.calledOnce(MeetingUtil.cleanUp);
|
|
3629
4353
|
assert.calledWith(
|
|
@@ -3631,12 +4355,12 @@ describe('plugin-meetings', () => {
|
|
|
3631
4355
|
meeting,
|
|
3632
4356
|
{
|
|
3633
4357
|
file: 'meeting/index',
|
|
3634
|
-
function: 'setUpLocusInfoMeetingListener'
|
|
4358
|
+
function: 'setUpLocusInfoMeetingListener',
|
|
3635
4359
|
},
|
|
3636
4360
|
EVENTS.DESTROY_MEETING,
|
|
3637
4361
|
{
|
|
3638
4362
|
reason: 'ended',
|
|
3639
|
-
meetingId: meeting.id
|
|
4363
|
+
meetingId: meeting.id,
|
|
3640
4364
|
}
|
|
3641
4365
|
);
|
|
3642
4366
|
done();
|
|
@@ -3656,22 +4380,36 @@ describe('plugin-meetings', () => {
|
|
|
3656
4380
|
sandbox = null;
|
|
3657
4381
|
});
|
|
3658
4382
|
|
|
3659
|
-
describe('#
|
|
3660
|
-
it('should have #
|
|
3661
|
-
assert.exists(meeting.
|
|
4383
|
+
describe('#releaseScreenShareFloor', () => {
|
|
4384
|
+
it('should have #releaseScreenShareFloor', () => {
|
|
4385
|
+
assert.exists(meeting.releaseScreenShareFloor);
|
|
3662
4386
|
});
|
|
3663
4387
|
beforeEach(() => {
|
|
3664
|
-
meeting.
|
|
4388
|
+
meeting.selfId = 'some self id';
|
|
4389
|
+
meeting.locusInfo.mediaShares = [
|
|
4390
|
+
{name: 'content', url: url1, floor: {beneficiary: {id: meeting.selfId}}},
|
|
4391
|
+
];
|
|
3665
4392
|
meeting.locusInfo.self = {url: url2};
|
|
4393
|
+
meeting.mediaProperties = {mediaDirection: {sendShare: true}};
|
|
3666
4394
|
meeting.meetingRequest.changeMeetingFloor = sinon.stub().returns(Promise.resolve());
|
|
3667
4395
|
});
|
|
3668
|
-
it('should call
|
|
3669
|
-
const share = meeting.
|
|
4396
|
+
it('should call changeMeetingFloor()', async () => {
|
|
4397
|
+
const share = meeting.releaseScreenShareFloor();
|
|
3670
4398
|
|
|
3671
4399
|
assert.exists(share.then);
|
|
3672
4400
|
await share;
|
|
3673
4401
|
assert.calledOnce(meeting.meetingRequest.changeMeetingFloor);
|
|
3674
4402
|
});
|
|
4403
|
+
it('should not call changeMeetingFloor() if someone else already has the floor', async () => {
|
|
4404
|
+
// change selfId so that it doesn't match the beneficiary id from meeting.locusInfo.mediaShares
|
|
4405
|
+
meeting.selfId = 'new self id';
|
|
4406
|
+
|
|
4407
|
+
const share = meeting.releaseScreenShareFloor();
|
|
4408
|
+
|
|
4409
|
+
assert.exists(share.then);
|
|
4410
|
+
await share;
|
|
4411
|
+
assert.notCalled(meeting.meetingRequest.changeMeetingFloor);
|
|
4412
|
+
});
|
|
3675
4413
|
});
|
|
3676
4414
|
|
|
3677
4415
|
describe('#setSipUri', () => {
|
|
@@ -3753,8 +4491,8 @@ describe('plugin-meetings', () => {
|
|
|
3753
4491
|
permissionToken: 'abc',
|
|
3754
4492
|
sipMeetingUri: test1,
|
|
3755
4493
|
sipUrl: test1,
|
|
3756
|
-
owner: test2
|
|
3757
|
-
}
|
|
4494
|
+
owner: test2,
|
|
4495
|
+
},
|
|
3758
4496
|
};
|
|
3759
4497
|
|
|
3760
4498
|
meeting.parseMeetingInfo(FAKE_MEETING_INFO);
|
|
@@ -3765,7 +4503,7 @@ describe('plugin-meetings', () => {
|
|
|
3765
4503
|
meetingNumber: '12345',
|
|
3766
4504
|
meetingJoinUrl: url2,
|
|
3767
4505
|
owner: test2,
|
|
3768
|
-
permissionToken: 'abc'
|
|
4506
|
+
permissionToken: 'abc',
|
|
3769
4507
|
};
|
|
3770
4508
|
|
|
3771
4509
|
checkParseMeetingInfo(expectedInfoToParse);
|
|
@@ -3779,8 +4517,8 @@ describe('plugin-meetings', () => {
|
|
|
3779
4517
|
info: {
|
|
3780
4518
|
webExMeetingId: 'locusMeetingId',
|
|
3781
4519
|
sipUri: 'locusSipUri',
|
|
3782
|
-
owner: 'locusOwner'
|
|
3783
|
-
}
|
|
4520
|
+
owner: 'locusOwner',
|
|
4521
|
+
},
|
|
3784
4522
|
};
|
|
3785
4523
|
const FAKE_MEETING_INFO = {
|
|
3786
4524
|
body: {
|
|
@@ -3791,8 +4529,8 @@ describe('plugin-meetings', () => {
|
|
|
3791
4529
|
permissionToken: 'abc',
|
|
3792
4530
|
sipMeetingUri: test1,
|
|
3793
4531
|
sipUrl: test1,
|
|
3794
|
-
owner: test2
|
|
3795
|
-
}
|
|
4532
|
+
owner: test2,
|
|
4533
|
+
},
|
|
3796
4534
|
};
|
|
3797
4535
|
|
|
3798
4536
|
meeting.parseMeetingInfo(FAKE_MEETING_INFO, FAKE_LOCUS_MEETING);
|
|
@@ -3803,7 +4541,7 @@ describe('plugin-meetings', () => {
|
|
|
3803
4541
|
meetingNumber: 'locusMeetingId',
|
|
3804
4542
|
meetingJoinUrl: url2,
|
|
3805
4543
|
owner: 'locusOwner',
|
|
3806
|
-
permissionToken: 'abc'
|
|
4544
|
+
permissionToken: 'abc',
|
|
3807
4545
|
};
|
|
3808
4546
|
|
|
3809
4547
|
checkParseMeetingInfo(expectedInfoToParse);
|
|
@@ -3820,8 +4558,8 @@ describe('plugin-meetings', () => {
|
|
|
3820
4558
|
permissionToken: 'abc',
|
|
3821
4559
|
sipMeetingUri: test1,
|
|
3822
4560
|
sipUrl: test1,
|
|
3823
|
-
owner: test2
|
|
3824
|
-
}
|
|
4561
|
+
owner: test2,
|
|
4562
|
+
},
|
|
3825
4563
|
};
|
|
3826
4564
|
|
|
3827
4565
|
meeting.parseMeetingInfo(FAKE_MEETING_INFO);
|
|
@@ -3832,7 +4570,7 @@ describe('plugin-meetings', () => {
|
|
|
3832
4570
|
meetingNumber: '12345',
|
|
3833
4571
|
meetingJoinUrl: url2,
|
|
3834
4572
|
owner: test2,
|
|
3835
|
-
permissionToken: 'abc'
|
|
4573
|
+
permissionToken: 'abc',
|
|
3836
4574
|
};
|
|
3837
4575
|
|
|
3838
4576
|
checkParseMeetingInfo(expectedInfoToParse);
|
|
@@ -3850,8 +4588,8 @@ describe('plugin-meetings', () => {
|
|
|
3850
4588
|
permissionToken: 'abc',
|
|
3851
4589
|
sipMeetingUri: test1,
|
|
3852
4590
|
sipUrl: test1,
|
|
3853
|
-
owner: test2
|
|
3854
|
-
}
|
|
4591
|
+
owner: test2,
|
|
4592
|
+
},
|
|
3855
4593
|
};
|
|
3856
4594
|
|
|
3857
4595
|
meeting.parseMeetingInfo(FAKE_MEETING_INFO, FAKE_STRING_DESTINATION);
|
|
@@ -3862,7 +4600,7 @@ describe('plugin-meetings', () => {
|
|
|
3862
4600
|
meetingNumber: '12345',
|
|
3863
4601
|
meetingJoinUrl: url2,
|
|
3864
4602
|
owner: test2,
|
|
3865
|
-
permissionToken: 'abc'
|
|
4603
|
+
permissionToken: 'abc',
|
|
3866
4604
|
};
|
|
3867
4605
|
|
|
3868
4606
|
checkParseMeetingInfo(expectedInfoToParse);
|
|
@@ -3878,7 +4616,11 @@ describe('plugin-meetings', () => {
|
|
|
3878
4616
|
meeting.type = 'CALL';
|
|
3879
4617
|
meeting.parseLocus({url: url1, participants: [{id: uuid1}], self: {id: uuid2}});
|
|
3880
4618
|
assert.calledOnce(meeting.setLocus);
|
|
3881
|
-
assert.calledWith(meeting.setLocus, {
|
|
4619
|
+
assert.calledWith(meeting.setLocus, {
|
|
4620
|
+
url: url1,
|
|
4621
|
+
participants: [{id: uuid1}],
|
|
4622
|
+
self: {id: uuid2},
|
|
4623
|
+
});
|
|
3882
4624
|
assert.calledOnce(MeetingUtil.getLocusPartner);
|
|
3883
4625
|
assert.calledWith(MeetingUtil.getLocusPartner, [{id: uuid1}], {id: uuid2});
|
|
3884
4626
|
assert.deepEqual(meeting.partner, {person: {sipUrl: uuid3}});
|
|
@@ -3927,7 +4669,7 @@ describe('plugin-meetings', () => {
|
|
|
3927
4669
|
meeting,
|
|
3928
4670
|
{
|
|
3929
4671
|
file: 'meeting/index',
|
|
3930
|
-
function: 'setUpLocusInfoAssignHostListener'
|
|
4672
|
+
function: 'setUpLocusInfoAssignHostListener',
|
|
3931
4673
|
},
|
|
3932
4674
|
'meeting:actionsUpdate',
|
|
3933
4675
|
meeting.inMeetingActions.get()
|
|
@@ -3946,7 +4688,7 @@ describe('plugin-meetings', () => {
|
|
|
3946
4688
|
let inMeetingActionsSetSpy;
|
|
3947
4689
|
let canUserLockSpy;
|
|
3948
4690
|
let canUserUnlockSpy;
|
|
3949
|
-
let
|
|
4691
|
+
let canUserStartSpy;
|
|
3950
4692
|
let canUserStopSpy;
|
|
3951
4693
|
let canUserPauseSpy;
|
|
3952
4694
|
let canUserResumeSpy;
|
|
@@ -3955,21 +4697,30 @@ describe('plugin-meetings', () => {
|
|
|
3955
4697
|
let canUserLowerAllHandsSpy;
|
|
3956
4698
|
let canUserLowerSomeoneElsesHandSpy;
|
|
3957
4699
|
let waitingForOthersToJoinSpy;
|
|
4700
|
+
let handleDataChannelUrlChangeSpy;
|
|
4701
|
+
let canEnableReactionsSpy;
|
|
4702
|
+
let canSendReactionsSpy;
|
|
3958
4703
|
|
|
3959
4704
|
beforeEach(() => {
|
|
3960
4705
|
locusInfoOnSpy = sinon.spy(meeting.locusInfo, 'on');
|
|
3961
4706
|
canUserLockSpy = sinon.spy(MeetingUtil, 'canUserLock');
|
|
3962
4707
|
canUserUnlockSpy = sinon.spy(MeetingUtil, 'canUserUnlock');
|
|
3963
|
-
|
|
3964
|
-
canUserStopSpy = sinon.spy(
|
|
3965
|
-
canUserPauseSpy = sinon.spy(
|
|
3966
|
-
canUserResumeSpy = sinon.spy(
|
|
4708
|
+
canUserStartSpy = sinon.spy(RecordingUtil, 'canUserStart');
|
|
4709
|
+
canUserStopSpy = sinon.spy(RecordingUtil, 'canUserStop');
|
|
4710
|
+
canUserPauseSpy = sinon.spy(RecordingUtil, 'canUserPause');
|
|
4711
|
+
canUserResumeSpy = sinon.spy(RecordingUtil, 'canUserResume');
|
|
3967
4712
|
inMeetingActionsSetSpy = sinon.spy(meeting.inMeetingActions, 'set');
|
|
3968
4713
|
canUserRaiseHandSpy = sinon.spy(MeetingUtil, 'canUserRaiseHand');
|
|
3969
4714
|
canUserLowerAllHandsSpy = sinon.spy(MeetingUtil, 'canUserLowerAllHands');
|
|
3970
|
-
bothLeaveAndEndMeetingAvailableSpy = sinon.spy(
|
|
4715
|
+
bothLeaveAndEndMeetingAvailableSpy = sinon.spy(
|
|
4716
|
+
MeetingUtil,
|
|
4717
|
+
'bothLeaveAndEndMeetingAvailable'
|
|
4718
|
+
);
|
|
3971
4719
|
canUserLowerSomeoneElsesHandSpy = sinon.spy(MeetingUtil, 'canUserLowerSomeoneElsesHand');
|
|
3972
4720
|
waitingForOthersToJoinSpy = sinon.spy(MeetingUtil, 'waitingForOthersToJoin');
|
|
4721
|
+
handleDataChannelUrlChangeSpy = sinon.spy(meeting, 'handleDataChannelUrlChange');
|
|
4722
|
+
canEnableReactionsSpy = sinon.spy(MeetingUtil, 'canEnableReactions');
|
|
4723
|
+
canSendReactionsSpy = sinon.spy(MeetingUtil, 'canSendReactions');
|
|
3973
4724
|
});
|
|
3974
4725
|
|
|
3975
4726
|
afterEach(() => {
|
|
@@ -3978,7 +4729,6 @@ describe('plugin-meetings', () => {
|
|
|
3978
4729
|
waitingForOthersToJoinSpy.restore();
|
|
3979
4730
|
});
|
|
3980
4731
|
|
|
3981
|
-
|
|
3982
4732
|
it('registers the correct MEETING_INFO_UPDATED event', () => {
|
|
3983
4733
|
meeting.setUpLocusInfoMeetingInfoListener();
|
|
3984
4734
|
|
|
@@ -3991,15 +4741,16 @@ describe('plugin-meetings', () => {
|
|
|
3991
4741
|
|
|
3992
4742
|
const payload = {
|
|
3993
4743
|
info: {
|
|
3994
|
-
userDisplayHints: ['LOCK_CONTROL_UNLOCK']
|
|
3995
|
-
|
|
4744
|
+
userDisplayHints: ['LOCK_CONTROL_UNLOCK'],
|
|
4745
|
+
datachannelUrl: 'some url',
|
|
4746
|
+
},
|
|
3996
4747
|
};
|
|
3997
4748
|
|
|
3998
4749
|
callback(payload);
|
|
3999
4750
|
|
|
4000
4751
|
assert.calledWith(canUserLockSpy, payload.info.userDisplayHints);
|
|
4001
4752
|
assert.calledWith(canUserUnlockSpy, payload.info.userDisplayHints);
|
|
4002
|
-
assert.calledWith(
|
|
4753
|
+
assert.calledWith(canUserStartSpy, payload.info.userDisplayHints);
|
|
4003
4754
|
assert.calledWith(canUserStopSpy, payload.info.userDisplayHints);
|
|
4004
4755
|
assert.calledWith(canUserPauseSpy, payload.info.userDisplayHints);
|
|
4005
4756
|
assert.calledWith(canUserResumeSpy, payload.info.userDisplayHints);
|
|
@@ -4008,13 +4759,16 @@ describe('plugin-meetings', () => {
|
|
|
4008
4759
|
assert.calledWith(canUserLowerAllHandsSpy, payload.info.userDisplayHints);
|
|
4009
4760
|
assert.calledWith(canUserLowerSomeoneElsesHandSpy, payload.info.userDisplayHints);
|
|
4010
4761
|
assert.calledWith(waitingForOthersToJoinSpy, payload.info.userDisplayHints);
|
|
4762
|
+
assert.calledWith(handleDataChannelUrlChangeSpy, payload.info.datachannelUrl);
|
|
4763
|
+
assert.calledWith(canEnableReactionsSpy, null, payload.info.userDisplayHints);
|
|
4764
|
+
assert.calledWith(canSendReactionsSpy, null, payload.info.userDisplayHints);
|
|
4011
4765
|
|
|
4012
4766
|
assert.calledWith(
|
|
4013
4767
|
TriggerProxy.trigger,
|
|
4014
4768
|
meeting,
|
|
4015
4769
|
{
|
|
4016
4770
|
file: 'meeting/index',
|
|
4017
|
-
function: 'setUpLocusInfoMeetingInfoListener'
|
|
4771
|
+
function: 'setUpLocusInfoMeetingInfoListener',
|
|
4018
4772
|
},
|
|
4019
4773
|
'meeting:actionsUpdate',
|
|
4020
4774
|
meeting.inMeetingActions.get()
|
|
@@ -4028,6 +4782,123 @@ describe('plugin-meetings', () => {
|
|
|
4028
4782
|
});
|
|
4029
4783
|
});
|
|
4030
4784
|
|
|
4785
|
+
describe('#handleDataChannelUrlChange', () => {
|
|
4786
|
+
let updateLLMConnectionSpy;
|
|
4787
|
+
|
|
4788
|
+
beforeEach(() => {
|
|
4789
|
+
updateLLMConnectionSpy = sinon.spy(meeting, 'updateLLMConnection');
|
|
4790
|
+
});
|
|
4791
|
+
|
|
4792
|
+
const check = async (url, expectedCalled) => {
|
|
4793
|
+
meeting.handleDataChannelUrlChange(url);
|
|
4794
|
+
|
|
4795
|
+
assert.notCalled(updateLLMConnectionSpy);
|
|
4796
|
+
|
|
4797
|
+
await testUtils.waitUntil(0);
|
|
4798
|
+
|
|
4799
|
+
if (expectedCalled) {
|
|
4800
|
+
assert.calledWith(updateLLMConnectionSpy);
|
|
4801
|
+
} else {
|
|
4802
|
+
assert.notCalled(updateLLMConnectionSpy);
|
|
4803
|
+
}
|
|
4804
|
+
};
|
|
4805
|
+
|
|
4806
|
+
it('calls deferred updateLLMConnection if datachannelURL is set and the enableAutomaticLLM is true', async () => {
|
|
4807
|
+
meeting.config.enableAutomaticLLM = true;
|
|
4808
|
+
check('some url', true);
|
|
4809
|
+
});
|
|
4810
|
+
|
|
4811
|
+
it('does not call updateLLMConnection if datachannelURL is undefined', async () => {
|
|
4812
|
+
meeting.config.enableAutomaticLLM = true;
|
|
4813
|
+
check(undefined, false);
|
|
4814
|
+
});
|
|
4815
|
+
|
|
4816
|
+
it('does not call updateLLMConnection if enableAutomaticLLM is false', async () => {
|
|
4817
|
+
check('some url', false);
|
|
4818
|
+
});
|
|
4819
|
+
});
|
|
4820
|
+
|
|
4821
|
+
describe('#updateLLMConnection', () => {
|
|
4822
|
+
beforeEach(() => {
|
|
4823
|
+
webex.internal.llm.isConnected = sinon.stub().returns(false);
|
|
4824
|
+
webex.internal.llm.getLocusUrl = sinon.stub();
|
|
4825
|
+
webex.internal.llm.registerAndConnect = sinon
|
|
4826
|
+
.stub()
|
|
4827
|
+
.returns(Promise.resolve('something'));
|
|
4828
|
+
webex.internal.llm.disconnectLLM = sinon.stub().returns(Promise.resolve());
|
|
4829
|
+
});
|
|
4830
|
+
|
|
4831
|
+
it('does not connect if the call is not joined yet', async () => {
|
|
4832
|
+
meeting.joinedWith = {state: 'any other state'};
|
|
4833
|
+
webex.internal.llm.getLocusUrl.returns('a url');
|
|
4834
|
+
|
|
4835
|
+
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
4836
|
+
|
|
4837
|
+
const result = await meeting.updateLLMConnection();
|
|
4838
|
+
|
|
4839
|
+
assert.notCalled(webex.internal.llm.registerAndConnect);
|
|
4840
|
+
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
4841
|
+
assert.equal(result, undefined);
|
|
4842
|
+
});
|
|
4843
|
+
|
|
4844
|
+
it('returns undefined if llm is already connected and the locus url is unchanged', async () => {
|
|
4845
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
4846
|
+
webex.internal.llm.isConnected.returns(true);
|
|
4847
|
+
webex.internal.llm.getLocusUrl.returns('a url');
|
|
4848
|
+
|
|
4849
|
+
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
4850
|
+
|
|
4851
|
+
const result = await meeting.updateLLMConnection();
|
|
4852
|
+
|
|
4853
|
+
assert.notCalled(webex.internal.llm.registerAndConnect);
|
|
4854
|
+
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
4855
|
+
assert.equal(result, undefined);
|
|
4856
|
+
});
|
|
4857
|
+
|
|
4858
|
+
it('connects if not already connected', async () => {
|
|
4859
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
4860
|
+
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
4861
|
+
|
|
4862
|
+
const result = await meeting.updateLLMConnection();
|
|
4863
|
+
|
|
4864
|
+
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
4865
|
+
assert.calledWith(webex.internal.llm.registerAndConnect, 'a url', 'a datachannel url');
|
|
4866
|
+
assert.equal(result, 'something');
|
|
4867
|
+
});
|
|
4868
|
+
|
|
4869
|
+
it('disconnects if first if the locus url has changed', async () => {
|
|
4870
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
4871
|
+
webex.internal.llm.isConnected.returns(true);
|
|
4872
|
+
webex.internal.llm.getLocusUrl.returns('a url');
|
|
4873
|
+
|
|
4874
|
+
meeting.locusInfo = {url: 'a different url', info: {datachannelUrl: 'a datachannel url'}};
|
|
4875
|
+
|
|
4876
|
+
const result = await meeting.updateLLMConnection();
|
|
4877
|
+
|
|
4878
|
+
assert.calledWith(webex.internal.llm.disconnectLLM);
|
|
4879
|
+
assert.calledWith(
|
|
4880
|
+
webex.internal.llm.registerAndConnect,
|
|
4881
|
+
'a different url',
|
|
4882
|
+
'a datachannel url'
|
|
4883
|
+
);
|
|
4884
|
+
assert.equal(result, 'something');
|
|
4885
|
+
});
|
|
4886
|
+
|
|
4887
|
+
it('disconnects when the state is not JOINED', async () => {
|
|
4888
|
+
meeting.joinedWith = {state: 'any other state'};
|
|
4889
|
+
webex.internal.llm.isConnected.returns(true);
|
|
4890
|
+
webex.internal.llm.getLocusUrl.returns('a url');
|
|
4891
|
+
|
|
4892
|
+
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
4893
|
+
|
|
4894
|
+
const result = await meeting.updateLLMConnection();
|
|
4895
|
+
|
|
4896
|
+
assert.calledWith(webex.internal.llm.disconnectLLM);
|
|
4897
|
+
assert.notCalled(webex.internal.llm.registerAndConnect);
|
|
4898
|
+
assert.equal(result, undefined);
|
|
4899
|
+
});
|
|
4900
|
+
});
|
|
4901
|
+
|
|
4031
4902
|
describe('#setLocus', () => {
|
|
4032
4903
|
beforeEach(() => {
|
|
4033
4904
|
meeting.locusInfo.initialSetup = sinon.stub().returns(true);
|
|
@@ -4039,7 +4910,7 @@ describe('plugin-meetings', () => {
|
|
|
4039
4910
|
locusId: uuid1,
|
|
4040
4911
|
selfId: uuid2,
|
|
4041
4912
|
mediaId: uuid3,
|
|
4042
|
-
host: {id: uuid4}
|
|
4913
|
+
host: {id: uuid4},
|
|
4043
4914
|
});
|
|
4044
4915
|
assert.calledOnce(meeting.locusInfo.initialSetup);
|
|
4045
4916
|
assert.calledWith(meeting.locusInfo.initialSetup, {
|
|
@@ -4048,7 +4919,7 @@ describe('plugin-meetings', () => {
|
|
|
4048
4919
|
locusId: uuid1,
|
|
4049
4920
|
selfId: uuid2,
|
|
4050
4921
|
mediaId: uuid3,
|
|
4051
|
-
host: {id: uuid4}
|
|
4922
|
+
host: {id: uuid4},
|
|
4052
4923
|
});
|
|
4053
4924
|
assert.equal(meeting.mediaConnections, test1);
|
|
4054
4925
|
assert.equal(meeting.locusUrl, url1);
|
|
@@ -4097,7 +4968,7 @@ describe('plugin-meetings', () => {
|
|
|
4097
4968
|
});
|
|
4098
4969
|
it('should send the whiteboard share', async () => {
|
|
4099
4970
|
const whiteboardShare = meeting.startWhiteboardShare({
|
|
4100
|
-
channelUrl: url2
|
|
4971
|
+
channelUrl: url2,
|
|
4101
4972
|
});
|
|
4102
4973
|
|
|
4103
4974
|
assert.exists(whiteboardShare.then);
|
|
@@ -4137,18 +5008,35 @@ describe('plugin-meetings', () => {
|
|
|
4137
5008
|
const USER_IDS = {
|
|
4138
5009
|
ME: '9528d952-e4de-46cf-8157-fd4823b98377',
|
|
4139
5010
|
REMOTE_A: '5be7e7b0-b304-48da-8083-83bd72b5300d',
|
|
4140
|
-
REMOTE_B: 'd4d102a1-17ce-4e17-9b08-bded3de467e4'
|
|
5011
|
+
REMOTE_B: 'd4d102a1-17ce-4e17-9b08-bded3de467e4',
|
|
4141
5012
|
};
|
|
4142
5013
|
|
|
4143
5014
|
const RESOURCE_URLS = {
|
|
4144
|
-
WHITEBOARD_A:
|
|
4145
|
-
|
|
5015
|
+
WHITEBOARD_A:
|
|
5016
|
+
'https://board-a.wbx2.com/board/api/v1/channels/49cfb550-5517-11eb-a2af-1b9e4bc3da13',
|
|
5017
|
+
WHITEBOARD_B:
|
|
5018
|
+
'https://board-a.wbx2.com/board/api/v1/channels/977a7330-54f4-11eb-b1ef-91f5eefc7bf3',
|
|
4146
5019
|
};
|
|
4147
5020
|
|
|
4148
|
-
const generateContent = (beneficiaryId = null, disposition = null) => ({
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
5021
|
+
const generateContent = (beneficiaryId = null, disposition = null) => ({
|
|
5022
|
+
beneficiaryId,
|
|
5023
|
+
disposition,
|
|
5024
|
+
});
|
|
5025
|
+
const generateWhiteboard = (
|
|
5026
|
+
beneficiaryId = null,
|
|
5027
|
+
disposition = null,
|
|
5028
|
+
resourceUrl = null
|
|
5029
|
+
) => ({beneficiaryId, disposition, resourceUrl});
|
|
5030
|
+
|
|
5031
|
+
const generateData = (
|
|
5032
|
+
payload,
|
|
5033
|
+
isGranting,
|
|
5034
|
+
isContent,
|
|
5035
|
+
beneficiaryId,
|
|
5036
|
+
resourceUrl,
|
|
5037
|
+
isAccepting,
|
|
5038
|
+
otherBeneficiaryId
|
|
5039
|
+
) => {
|
|
4152
5040
|
const newPayload = cloneDeep(payload);
|
|
4153
5041
|
|
|
4154
5042
|
newPayload.previous = cloneDeep(payload.current);
|
|
@@ -4159,15 +5047,15 @@ describe('plugin-meetings', () => {
|
|
|
4159
5047
|
eventName: EVENT_TRIGGERS.MEMBERS_CONTENT_UPDATE,
|
|
4160
5048
|
eventPayload: {
|
|
4161
5049
|
activeSharingId: null,
|
|
4162
|
-
endedSharingId: null
|
|
4163
|
-
}
|
|
4164
|
-
}
|
|
5050
|
+
endedSharingId: null,
|
|
5051
|
+
},
|
|
5052
|
+
},
|
|
4165
5053
|
};
|
|
4166
5054
|
|
|
4167
5055
|
let shareStatus = null;
|
|
4168
5056
|
const activeSharingId = {
|
|
4169
5057
|
whiteboard: null,
|
|
4170
|
-
content: null
|
|
5058
|
+
content: null,
|
|
4171
5059
|
};
|
|
4172
5060
|
|
|
4173
5061
|
if (isGranting) {
|
|
@@ -4177,68 +5065,72 @@ describe('plugin-meetings', () => {
|
|
|
4177
5065
|
|
|
4178
5066
|
if (isEqual(newPayload.current, newPayload.previous)) {
|
|
4179
5067
|
eventTrigger.member = null;
|
|
4180
|
-
}
|
|
4181
|
-
else {
|
|
5068
|
+
} else {
|
|
4182
5069
|
if (newPayload.current.whiteboard.beneficiaryId) {
|
|
4183
5070
|
if (newPayload.current.whiteboard.disposition === FLOOR_ACTION.GRANTED) {
|
|
4184
5071
|
newPayload.current.whiteboard.disposition = FLOOR_ACTION.RELEASED;
|
|
4185
5072
|
eventTrigger.share.push({
|
|
4186
5073
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_WHITEBOARD,
|
|
4187
|
-
functionName: 'stopWhiteboardShare'
|
|
5074
|
+
functionName: 'stopWhiteboardShare',
|
|
4188
5075
|
});
|
|
4189
|
-
eventTrigger.member.eventPayload.endedSharingId =
|
|
5076
|
+
eventTrigger.member.eventPayload.endedSharingId =
|
|
5077
|
+
newPayload.current.whiteboard.beneficiaryId;
|
|
4190
5078
|
}
|
|
4191
5079
|
}
|
|
4192
5080
|
|
|
4193
5081
|
if (newPayload.previous.content.beneficiaryId) {
|
|
4194
|
-
if (
|
|
5082
|
+
if (
|
|
5083
|
+
newPayload.previous.content.beneficiaryId !==
|
|
5084
|
+
newPayload.current.content.beneficiaryId
|
|
5085
|
+
) {
|
|
4195
5086
|
if (newPayload.previous.content.beneficiaryId === USER_IDS.ME) {
|
|
4196
5087
|
eventTrigger.share.push({
|
|
4197
5088
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
4198
|
-
functionName: '
|
|
5089
|
+
functionName: 'localShare',
|
|
4199
5090
|
});
|
|
4200
|
-
}
|
|
4201
|
-
else if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
5091
|
+
} else if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
4202
5092
|
eventTrigger.share.push({
|
|
4203
5093
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_REMOTE,
|
|
4204
|
-
functionName: 'remoteShare'
|
|
5094
|
+
functionName: 'remoteShare',
|
|
4205
5095
|
});
|
|
4206
5096
|
}
|
|
4207
|
-
eventTrigger.member.eventPayload.endedSharingId =
|
|
5097
|
+
eventTrigger.member.eventPayload.endedSharingId =
|
|
5098
|
+
newPayload.previous.content.beneficiaryId;
|
|
4208
5099
|
}
|
|
4209
5100
|
}
|
|
4210
5101
|
|
|
4211
5102
|
if (isAccepting) {
|
|
4212
5103
|
eventTrigger.share.push({
|
|
4213
5104
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_WHITEBOARD,
|
|
4214
|
-
functionName: 'stopWhiteboardShare'
|
|
5105
|
+
functionName: 'stopWhiteboardShare',
|
|
4215
5106
|
});
|
|
4216
5107
|
}
|
|
4217
5108
|
|
|
4218
5109
|
if (beneficiaryId === USER_IDS.ME) {
|
|
4219
5110
|
eventTrigger.share.push({
|
|
4220
5111
|
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_LOCAL,
|
|
4221
|
-
functionName: 'share'
|
|
5112
|
+
functionName: 'share',
|
|
4222
5113
|
});
|
|
4223
|
-
}
|
|
4224
|
-
else {
|
|
5114
|
+
} else {
|
|
4225
5115
|
eventTrigger.share.push({
|
|
4226
5116
|
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
|
4227
5117
|
functionName: 'remoteShare',
|
|
4228
|
-
eventPayload: {memberId: beneficiaryId}
|
|
5118
|
+
eventPayload: {memberId: beneficiaryId},
|
|
4229
5119
|
});
|
|
4230
5120
|
}
|
|
4231
5121
|
}
|
|
4232
5122
|
|
|
4233
5123
|
if (beneficiaryId === USER_IDS.ME) {
|
|
4234
5124
|
shareStatus = SHARE_STATUS.LOCAL_SHARE_ACTIVE;
|
|
4235
|
-
}
|
|
4236
|
-
else {
|
|
5125
|
+
} else {
|
|
4237
5126
|
shareStatus = SHARE_STATUS.REMOTE_SHARE_ACTIVE;
|
|
4238
5127
|
}
|
|
4239
|
-
}
|
|
4240
|
-
|
|
4241
|
-
|
|
5128
|
+
} else {
|
|
5129
|
+
newPayload.current.whiteboard = generateWhiteboard(
|
|
5130
|
+
beneficiaryId,
|
|
5131
|
+
FLOOR_ACTION.GRANTED,
|
|
5132
|
+
resourceUrl
|
|
5133
|
+
);
|
|
4242
5134
|
|
|
4243
5135
|
if (newPayload.current.content.beneficiaryId) {
|
|
4244
5136
|
if (newPayload.current.content.disposition === FLOOR_ACTION.GRANTED) {
|
|
@@ -4246,41 +5138,48 @@ describe('plugin-meetings', () => {
|
|
|
4246
5138
|
if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
4247
5139
|
eventTrigger.share.push({
|
|
4248
5140
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
4249
|
-
functionName: '
|
|
5141
|
+
functionName: 'localShare',
|
|
4250
5142
|
});
|
|
4251
|
-
}
|
|
4252
|
-
else {
|
|
5143
|
+
} else {
|
|
4253
5144
|
eventTrigger.share.push({
|
|
4254
5145
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_REMOTE,
|
|
4255
|
-
functionName: 'remoteShare'
|
|
5146
|
+
functionName: 'remoteShare',
|
|
4256
5147
|
});
|
|
4257
5148
|
}
|
|
4258
5149
|
|
|
4259
|
-
eventTrigger.member.eventPayload.endedSharingId =
|
|
5150
|
+
eventTrigger.member.eventPayload.endedSharingId =
|
|
5151
|
+
newPayload.current.content.beneficiaryId;
|
|
4260
5152
|
}
|
|
4261
5153
|
}
|
|
4262
5154
|
|
|
4263
5155
|
if (newPayload.previous.content.beneficiaryId) {
|
|
4264
|
-
if (
|
|
5156
|
+
if (
|
|
5157
|
+
newPayload.previous.content.beneficiaryId !==
|
|
5158
|
+
newPayload.current.content.beneficiaryId
|
|
5159
|
+
) {
|
|
4265
5160
|
if (newPayload.previous.content.beneficiaryId === USER_IDS.ME) {
|
|
4266
5161
|
eventTrigger.share.push({
|
|
4267
5162
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
4268
|
-
functionName: '
|
|
5163
|
+
functionName: 'localShare',
|
|
4269
5164
|
});
|
|
4270
|
-
}
|
|
4271
|
-
else if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
5165
|
+
} else if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
4272
5166
|
eventTrigger.share.push({
|
|
4273
5167
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_REMOTE,
|
|
4274
|
-
functionName: 'remoteShare'
|
|
5168
|
+
functionName: 'remoteShare',
|
|
4275
5169
|
});
|
|
4276
5170
|
}
|
|
4277
|
-
eventTrigger.member.eventPayload.endedSharingId =
|
|
5171
|
+
eventTrigger.member.eventPayload.endedSharingId =
|
|
5172
|
+
newPayload.previous.content.beneficiaryId;
|
|
4278
5173
|
}
|
|
4279
5174
|
}
|
|
4280
5175
|
|
|
4281
5176
|
if (newPayload.previous.whiteboard.beneficiaryId) {
|
|
4282
|
-
if (
|
|
4283
|
-
|
|
5177
|
+
if (
|
|
5178
|
+
newPayload.previous.whiteboard.beneficiaryId !==
|
|
5179
|
+
newPayload.current.whiteboard.beneficiaryId
|
|
5180
|
+
) {
|
|
5181
|
+
eventTrigger.member.eventPayload.endedSharingId =
|
|
5182
|
+
newPayload.previous.whiteboard.beneficiaryId;
|
|
4284
5183
|
}
|
|
4285
5184
|
}
|
|
4286
5185
|
|
|
@@ -4289,7 +5188,7 @@ describe('plugin-meetings', () => {
|
|
|
4289
5188
|
eventTrigger.share.push({
|
|
4290
5189
|
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
|
|
4291
5190
|
functionName: 'startWhiteboardShare',
|
|
4292
|
-
eventPayload: {resourceUrl, memberId: beneficiaryId}
|
|
5191
|
+
eventPayload: {resourceUrl, memberId: beneficiaryId},
|
|
4293
5192
|
});
|
|
4294
5193
|
|
|
4295
5194
|
shareStatus = SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
|
@@ -4298,8 +5197,7 @@ describe('plugin-meetings', () => {
|
|
|
4298
5197
|
if (eventTrigger.member) {
|
|
4299
5198
|
eventTrigger.member.eventPayload.activeSharingId = beneficiaryId;
|
|
4300
5199
|
}
|
|
4301
|
-
}
|
|
4302
|
-
else {
|
|
5200
|
+
} else {
|
|
4303
5201
|
eventTrigger.member.eventPayload.endedSharingId = beneficiaryId;
|
|
4304
5202
|
|
|
4305
5203
|
if (isContent) {
|
|
@@ -4308,19 +5206,17 @@ describe('plugin-meetings', () => {
|
|
|
4308
5206
|
if (beneficiaryId === USER_IDS.ME) {
|
|
4309
5207
|
eventTrigger.share.push({
|
|
4310
5208
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
4311
|
-
functionName: '
|
|
5209
|
+
functionName: 'localShare',
|
|
4312
5210
|
});
|
|
4313
|
-
}
|
|
4314
|
-
else {
|
|
5211
|
+
} else {
|
|
4315
5212
|
eventTrigger.share.push({
|
|
4316
5213
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_REMOTE,
|
|
4317
|
-
functionName: 'remoteShare'
|
|
5214
|
+
functionName: 'remoteShare',
|
|
4318
5215
|
});
|
|
4319
5216
|
}
|
|
4320
5217
|
|
|
4321
5218
|
shareStatus = SHARE_STATUS.NO_SHARE;
|
|
4322
|
-
}
|
|
4323
|
-
else {
|
|
5219
|
+
} else {
|
|
4324
5220
|
newPayload.current.whiteboard.disposition = FLOOR_ACTION.RELEASED;
|
|
4325
5221
|
|
|
4326
5222
|
if (isAccepting) {
|
|
@@ -4330,15 +5226,14 @@ describe('plugin-meetings', () => {
|
|
|
4330
5226
|
eventTrigger.share.push({
|
|
4331
5227
|
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
|
|
4332
5228
|
functionName: 'startWhiteboardShare',
|
|
4333
|
-
eventPayload: {resourceUrl, memberId: beneficiaryId}
|
|
5229
|
+
eventPayload: {resourceUrl, memberId: beneficiaryId},
|
|
4334
5230
|
});
|
|
4335
5231
|
|
|
4336
5232
|
shareStatus = SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
|
4337
|
-
}
|
|
4338
|
-
else {
|
|
5233
|
+
} else {
|
|
4339
5234
|
eventTrigger.share.push({
|
|
4340
5235
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_WHITEBOARD,
|
|
4341
|
-
functionName: 'stopWhiteboardShare'
|
|
5236
|
+
functionName: 'stopWhiteboardShare',
|
|
4342
5237
|
});
|
|
4343
5238
|
|
|
4344
5239
|
shareStatus = SHARE_STATUS.NO_SHARE;
|
|
@@ -4347,22 +5242,24 @@ describe('plugin-meetings', () => {
|
|
|
4347
5242
|
}
|
|
4348
5243
|
|
|
4349
5244
|
return {
|
|
4350
|
-
payload: newPayload,
|
|
5245
|
+
payload: newPayload,
|
|
5246
|
+
eventTrigger,
|
|
5247
|
+
shareStatus,
|
|
5248
|
+
activeSharingId,
|
|
4351
5249
|
};
|
|
4352
5250
|
};
|
|
4353
5251
|
|
|
4354
5252
|
const blankPayload = {
|
|
4355
5253
|
previous: {
|
|
4356
5254
|
content: generateContent(),
|
|
4357
|
-
whiteboard: generateWhiteboard()
|
|
5255
|
+
whiteboard: generateWhiteboard(),
|
|
4358
5256
|
},
|
|
4359
5257
|
current: {
|
|
4360
5258
|
content: generateContent(),
|
|
4361
|
-
whiteboard: generateWhiteboard()
|
|
4362
|
-
}
|
|
5259
|
+
whiteboard: generateWhiteboard(),
|
|
5260
|
+
},
|
|
4363
5261
|
};
|
|
4364
5262
|
|
|
4365
|
-
|
|
4366
5263
|
const payloadTestHelper = (data) => {
|
|
4367
5264
|
assert.equal(meeting.shareStatus, SHARE_STATUS.NO_SHARE);
|
|
4368
5265
|
|
|
@@ -4370,23 +5267,33 @@ describe('plugin-meetings', () => {
|
|
|
4370
5267
|
let callCounter = 1;
|
|
4371
5268
|
|
|
4372
5269
|
data.forEach((d, index) => {
|
|
4373
|
-
meeting.locusInfo.emit(
|
|
5270
|
+
meeting.locusInfo.emit(
|
|
5271
|
+
{function: 'test', file: 'test'},
|
|
5272
|
+
EVENTS.LOCUS_INFO_UPDATE_MEDIA_SHARES,
|
|
5273
|
+
d.payload
|
|
5274
|
+
);
|
|
4374
5275
|
|
|
4375
5276
|
assert.equal(meeting.shareStatus, data[index].shareStatus);
|
|
4376
5277
|
|
|
4377
|
-
callCounter +=
|
|
5278
|
+
callCounter +=
|
|
5279
|
+
data[index].eventTrigger.share.length + (data[index].eventTrigger.member ? 1 : 0);
|
|
4378
5280
|
|
|
4379
5281
|
assert.callCount(TriggerProxy.trigger, callCounter);
|
|
4380
5282
|
|
|
4381
|
-
assert.equal(
|
|
4382
|
-
|
|
5283
|
+
assert.equal(
|
|
5284
|
+
meeting.members.mediaShareWhiteboardId,
|
|
5285
|
+
data[index].activeSharingId.whiteboard
|
|
5286
|
+
);
|
|
5287
|
+
assert.equal(
|
|
5288
|
+
meeting.members.mediaShareContentId,
|
|
5289
|
+
data[index].activeSharingId.content
|
|
5290
|
+
);
|
|
4383
5291
|
});
|
|
4384
5292
|
|
|
4385
5293
|
assert.callCount(TriggerProxy.trigger, callCounter);
|
|
4386
5294
|
|
|
4387
5295
|
// Start with 1 to ignore members:update trigger
|
|
4388
5296
|
|
|
4389
|
-
|
|
4390
5297
|
let i = 1;
|
|
4391
5298
|
let offset = 2;
|
|
4392
5299
|
|
|
@@ -4398,21 +5305,24 @@ describe('plugin-meetings', () => {
|
|
|
4398
5305
|
for (let idx = 0; idx < share.length; idx += 1) {
|
|
4399
5306
|
const shareCallArgs = TriggerProxy.trigger.getCall(i + idx).args;
|
|
4400
5307
|
const {functionName, eventName, eventPayload} = share[idx];
|
|
4401
|
-
const fileName =
|
|
5308
|
+
const fileName =
|
|
5309
|
+
functionName === 'remoteShare' ? 'meetings/index' : 'meeting/index';
|
|
4402
5310
|
|
|
4403
5311
|
assert.deepEqual(shareCallArgs[1], {
|
|
4404
5312
|
file: fileName,
|
|
4405
|
-
function: functionName
|
|
5313
|
+
function: functionName,
|
|
4406
5314
|
});
|
|
4407
5315
|
|
|
4408
|
-
|
|
4409
5316
|
assert.equal(shareCallArgs[2], eventName);
|
|
4410
5317
|
|
|
4411
5318
|
if (functionName === 'startWhiteboardShare') {
|
|
4412
5319
|
assert.deepEqual(shareCallArgs[3], eventPayload);
|
|
4413
5320
|
}
|
|
4414
5321
|
|
|
4415
|
-
if (
|
|
5322
|
+
if (
|
|
5323
|
+
functionName === 'remoteShare' &&
|
|
5324
|
+
eventName === EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE
|
|
5325
|
+
) {
|
|
4416
5326
|
assert.deepEqual(shareCallArgs[3], eventPayload);
|
|
4417
5327
|
}
|
|
4418
5328
|
}
|
|
@@ -4423,7 +5333,7 @@ describe('plugin-meetings', () => {
|
|
|
4423
5333
|
|
|
4424
5334
|
assert.deepEqual(memberCallArgs[1], {
|
|
4425
5335
|
file: 'members',
|
|
4426
|
-
function: 'locusMediaSharesUpdate'
|
|
5336
|
+
function: 'locusMediaSharesUpdate',
|
|
4427
5337
|
});
|
|
4428
5338
|
assert.equal(memberCallArgs[2], member.eventName);
|
|
4429
5339
|
|
|
@@ -4437,9 +5347,8 @@ describe('plugin-meetings', () => {
|
|
|
4437
5347
|
|
|
4438
5348
|
if (share.length + 1 > offset) {
|
|
4439
5349
|
offset = (offset + share.length + 1) / 2;
|
|
4440
|
-
}
|
|
4441
|
-
|
|
4442
|
-
offset = (share.length + 1) + 0.5;
|
|
5350
|
+
} else if (share.length + 1 < offset) {
|
|
5351
|
+
offset = share.length + 1 + 0.5;
|
|
4443
5352
|
}
|
|
4444
5353
|
}
|
|
4445
5354
|
};
|
|
@@ -4450,40 +5359,100 @@ describe('plugin-meetings', () => {
|
|
|
4450
5359
|
|
|
4451
5360
|
describe('Whiteboard A --> Whiteboard B', () => {
|
|
4452
5361
|
it('Scenario #1: you share both whiteboards', () => {
|
|
4453
|
-
const data1 = generateData(
|
|
4454
|
-
|
|
5362
|
+
const data1 = generateData(
|
|
5363
|
+
blankPayload,
|
|
5364
|
+
true,
|
|
5365
|
+
false,
|
|
5366
|
+
USER_IDS.ME,
|
|
5367
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5368
|
+
);
|
|
5369
|
+
const data2 = generateData(
|
|
5370
|
+
data1.payload,
|
|
5371
|
+
true,
|
|
5372
|
+
false,
|
|
5373
|
+
USER_IDS.ME,
|
|
5374
|
+
RESOURCE_URLS.WHITEBOARD_B
|
|
5375
|
+
);
|
|
4455
5376
|
const data3 = generateData(data2.payload, false, false, USER_IDS.ME);
|
|
4456
5377
|
|
|
4457
5378
|
payloadTestHelper([data1, data2, data3]);
|
|
4458
5379
|
});
|
|
4459
5380
|
|
|
4460
5381
|
it('Scenario #2: you share whiteboard A and remote person A shares whiteboard B', () => {
|
|
4461
|
-
const data1 = generateData(
|
|
4462
|
-
|
|
5382
|
+
const data1 = generateData(
|
|
5383
|
+
blankPayload,
|
|
5384
|
+
true,
|
|
5385
|
+
false,
|
|
5386
|
+
USER_IDS.ME,
|
|
5387
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5388
|
+
);
|
|
5389
|
+
const data2 = generateData(
|
|
5390
|
+
data1.payload,
|
|
5391
|
+
true,
|
|
5392
|
+
false,
|
|
5393
|
+
USER_IDS.REMOTE_A,
|
|
5394
|
+
RESOURCE_URLS.WHITEBOARD_B
|
|
5395
|
+
);
|
|
4463
5396
|
const data3 = generateData(data2.payload, false, false, USER_IDS.REMOTE_A);
|
|
4464
5397
|
|
|
4465
5398
|
payloadTestHelper([data1, data2, data3]);
|
|
4466
5399
|
});
|
|
4467
5400
|
|
|
4468
5401
|
it('Scenario #3: remote person A shares whiteboard A and you share whiteboard B', () => {
|
|
4469
|
-
const data1 = generateData(
|
|
4470
|
-
|
|
5402
|
+
const data1 = generateData(
|
|
5403
|
+
blankPayload,
|
|
5404
|
+
true,
|
|
5405
|
+
false,
|
|
5406
|
+
USER_IDS.REMOTE_A,
|
|
5407
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5408
|
+
);
|
|
5409
|
+
const data2 = generateData(
|
|
5410
|
+
data1.payload,
|
|
5411
|
+
true,
|
|
5412
|
+
false,
|
|
5413
|
+
USER_IDS.ME,
|
|
5414
|
+
RESOURCE_URLS.WHITEBOARD_B
|
|
5415
|
+
);
|
|
4471
5416
|
const data3 = generateData(data2.payload, false, false, USER_IDS.ME);
|
|
4472
5417
|
|
|
4473
5418
|
payloadTestHelper([data1, data2, data3]);
|
|
4474
5419
|
});
|
|
4475
5420
|
|
|
4476
5421
|
it('Scenario #4: remote person A shares both whiteboards', () => {
|
|
4477
|
-
const data1 = generateData(
|
|
4478
|
-
|
|
5422
|
+
const data1 = generateData(
|
|
5423
|
+
blankPayload,
|
|
5424
|
+
true,
|
|
5425
|
+
false,
|
|
5426
|
+
USER_IDS.REMOTE_A,
|
|
5427
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5428
|
+
);
|
|
5429
|
+
const data2 = generateData(
|
|
5430
|
+
data1.payload,
|
|
5431
|
+
true,
|
|
5432
|
+
false,
|
|
5433
|
+
USER_IDS.REMOTE_A,
|
|
5434
|
+
RESOURCE_URLS.WHITEBOARD_B
|
|
5435
|
+
);
|
|
4479
5436
|
const data3 = generateData(data2.payload, false, false, USER_IDS.REMOTE_A);
|
|
4480
5437
|
|
|
4481
5438
|
payloadTestHelper([data1, data2, data3]);
|
|
4482
5439
|
});
|
|
4483
5440
|
|
|
4484
5441
|
it('Scenario #5: remote person A shares whiteboard A and remote person B shares whiteboard B', () => {
|
|
4485
|
-
const data1 = generateData(
|
|
4486
|
-
|
|
5442
|
+
const data1 = generateData(
|
|
5443
|
+
blankPayload,
|
|
5444
|
+
true,
|
|
5445
|
+
false,
|
|
5446
|
+
USER_IDS.REMOTE_A,
|
|
5447
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5448
|
+
);
|
|
5449
|
+
const data2 = generateData(
|
|
5450
|
+
data1.payload,
|
|
5451
|
+
true,
|
|
5452
|
+
false,
|
|
5453
|
+
USER_IDS.REMOTE_B,
|
|
5454
|
+
RESOURCE_URLS.WHITEBOARD_B
|
|
5455
|
+
);
|
|
4487
5456
|
const data3 = generateData(data2.payload, false, false, USER_IDS.REMOTE_B);
|
|
4488
5457
|
|
|
4489
5458
|
payloadTestHelper([data1, data2, data3]);
|
|
@@ -4492,45 +5461,155 @@ describe('plugin-meetings', () => {
|
|
|
4492
5461
|
|
|
4493
5462
|
describe('Whiteboard A --> Desktop', () => {
|
|
4494
5463
|
it('Scenario #1: you share whiteboard and then share desktop', () => {
|
|
4495
|
-
const data1 = generateData(
|
|
4496
|
-
|
|
4497
|
-
|
|
5464
|
+
const data1 = generateData(
|
|
5465
|
+
blankPayload,
|
|
5466
|
+
true,
|
|
5467
|
+
false,
|
|
5468
|
+
USER_IDS.ME,
|
|
5469
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5470
|
+
);
|
|
5471
|
+
const data2 = generateData(
|
|
5472
|
+
data1.payload,
|
|
5473
|
+
false,
|
|
5474
|
+
false,
|
|
5475
|
+
USER_IDS.ME,
|
|
5476
|
+
RESOURCE_URLS.WHITEBOARD_A,
|
|
5477
|
+
true,
|
|
5478
|
+
USER_IDS.ME
|
|
5479
|
+
);
|
|
5480
|
+
const data3 = generateData(
|
|
5481
|
+
data2.payload,
|
|
5482
|
+
true,
|
|
5483
|
+
true,
|
|
5484
|
+
USER_IDS.ME,
|
|
5485
|
+
undefined,
|
|
5486
|
+
true,
|
|
5487
|
+
USER_IDS.ME
|
|
5488
|
+
);
|
|
4498
5489
|
const data4 = generateData(data3.payload, false, true, USER_IDS.ME);
|
|
4499
5490
|
|
|
4500
5491
|
payloadTestHelper([data1, data2, data3, data4]);
|
|
4501
5492
|
});
|
|
4502
5493
|
|
|
4503
5494
|
it('Scenario #2: you share whiteboard A and remote person A shares desktop', () => {
|
|
4504
|
-
const data1 = generateData(
|
|
4505
|
-
|
|
4506
|
-
|
|
5495
|
+
const data1 = generateData(
|
|
5496
|
+
blankPayload,
|
|
5497
|
+
true,
|
|
5498
|
+
false,
|
|
5499
|
+
USER_IDS.ME,
|
|
5500
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5501
|
+
);
|
|
5502
|
+
const data2 = generateData(
|
|
5503
|
+
data1.payload,
|
|
5504
|
+
false,
|
|
5505
|
+
false,
|
|
5506
|
+
USER_IDS.ME,
|
|
5507
|
+
RESOURCE_URLS.WHITEBOARD_A,
|
|
5508
|
+
true,
|
|
5509
|
+
USER_IDS.REMOTE_A
|
|
5510
|
+
);
|
|
5511
|
+
const data3 = generateData(
|
|
5512
|
+
data2.payload,
|
|
5513
|
+
true,
|
|
5514
|
+
true,
|
|
5515
|
+
USER_IDS.REMOTE_A,
|
|
5516
|
+
undefined,
|
|
5517
|
+
true,
|
|
5518
|
+
USER_IDS.ME
|
|
5519
|
+
);
|
|
4507
5520
|
const data4 = generateData(data3.payload, false, true, USER_IDS.REMOTE_A);
|
|
4508
5521
|
|
|
4509
5522
|
payloadTestHelper([data1, data2, data3, data4]);
|
|
4510
5523
|
});
|
|
4511
5524
|
|
|
4512
5525
|
it('Scenario #3: remote person A shares whiteboard and you share desktop', () => {
|
|
4513
|
-
const data1 = generateData(
|
|
4514
|
-
|
|
4515
|
-
|
|
5526
|
+
const data1 = generateData(
|
|
5527
|
+
blankPayload,
|
|
5528
|
+
true,
|
|
5529
|
+
false,
|
|
5530
|
+
USER_IDS.REMOTE_A,
|
|
5531
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5532
|
+
);
|
|
5533
|
+
const data2 = generateData(
|
|
5534
|
+
data1.payload,
|
|
5535
|
+
false,
|
|
5536
|
+
false,
|
|
5537
|
+
USER_IDS.REMOTE_A,
|
|
5538
|
+
RESOURCE_URLS.WHITEBOARD_A,
|
|
5539
|
+
true,
|
|
5540
|
+
USER_IDS.ME
|
|
5541
|
+
);
|
|
5542
|
+
const data3 = generateData(
|
|
5543
|
+
data2.payload,
|
|
5544
|
+
true,
|
|
5545
|
+
true,
|
|
5546
|
+
USER_IDS.ME,
|
|
5547
|
+
undefined,
|
|
5548
|
+
true,
|
|
5549
|
+
USER_IDS.REMOTE_A
|
|
5550
|
+
);
|
|
4516
5551
|
const data4 = generateData(data3.payload, false, true, USER_IDS.ME);
|
|
4517
5552
|
|
|
4518
5553
|
payloadTestHelper([data1, data2, data3, data4]);
|
|
4519
5554
|
});
|
|
4520
5555
|
|
|
4521
5556
|
it('Scenario #4: remote person A shares whiteboard and then shares desktop', () => {
|
|
4522
|
-
const data1 = generateData(
|
|
4523
|
-
|
|
4524
|
-
|
|
5557
|
+
const data1 = generateData(
|
|
5558
|
+
blankPayload,
|
|
5559
|
+
true,
|
|
5560
|
+
false,
|
|
5561
|
+
USER_IDS.REMOTE_A,
|
|
5562
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5563
|
+
);
|
|
5564
|
+
const data2 = generateData(
|
|
5565
|
+
data1.payload,
|
|
5566
|
+
false,
|
|
5567
|
+
false,
|
|
5568
|
+
USER_IDS.REMOTE_A,
|
|
5569
|
+
RESOURCE_URLS.WHITEBOARD_A,
|
|
5570
|
+
true,
|
|
5571
|
+
USER_IDS.REMOTE_A
|
|
5572
|
+
);
|
|
5573
|
+
const data3 = generateData(
|
|
5574
|
+
data2.payload,
|
|
5575
|
+
true,
|
|
5576
|
+
true,
|
|
5577
|
+
USER_IDS.REMOTE_A,
|
|
5578
|
+
undefined,
|
|
5579
|
+
true,
|
|
5580
|
+
USER_IDS.REMOTE_A
|
|
5581
|
+
);
|
|
4525
5582
|
const data4 = generateData(data3.payload, false, true, USER_IDS.REMOTE_A);
|
|
4526
5583
|
|
|
4527
5584
|
payloadTestHelper([data1, data2, data3, data4]);
|
|
4528
5585
|
});
|
|
4529
5586
|
|
|
4530
5587
|
it('Scenario #5: remote person A shares whiteboard and remote person B shares desktop', () => {
|
|
4531
|
-
const data1 = generateData(
|
|
4532
|
-
|
|
4533
|
-
|
|
5588
|
+
const data1 = generateData(
|
|
5589
|
+
blankPayload,
|
|
5590
|
+
true,
|
|
5591
|
+
false,
|
|
5592
|
+
USER_IDS.REMOTE_A,
|
|
5593
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5594
|
+
);
|
|
5595
|
+
const data2 = generateData(
|
|
5596
|
+
data1.payload,
|
|
5597
|
+
false,
|
|
5598
|
+
false,
|
|
5599
|
+
USER_IDS.REMOTE_A,
|
|
5600
|
+
RESOURCE_URLS.WHITEBOARD_A,
|
|
5601
|
+
true,
|
|
5602
|
+
USER_IDS.REMOTE_B
|
|
5603
|
+
);
|
|
5604
|
+
const data3 = generateData(
|
|
5605
|
+
data2.payload,
|
|
5606
|
+
true,
|
|
5607
|
+
true,
|
|
5608
|
+
USER_IDS.REMOTE_B,
|
|
5609
|
+
undefined,
|
|
5610
|
+
true,
|
|
5611
|
+
USER_IDS.REMOTE_A
|
|
5612
|
+
);
|
|
4534
5613
|
const data4 = generateData(data3.payload, false, true, USER_IDS.REMOTE_B);
|
|
4535
5614
|
|
|
4536
5615
|
payloadTestHelper([data1, data2, data3, data4]);
|
|
@@ -4540,7 +5619,13 @@ describe('plugin-meetings', () => {
|
|
|
4540
5619
|
describe('Desktop --> Whiteboard A', () => {
|
|
4541
5620
|
it('Scenario #1: you share desktop and then share whiteboard', () => {
|
|
4542
5621
|
const data1 = generateData(blankPayload, true, true, USER_IDS.ME);
|
|
4543
|
-
const data2 = generateData(
|
|
5622
|
+
const data2 = generateData(
|
|
5623
|
+
data1.payload,
|
|
5624
|
+
true,
|
|
5625
|
+
false,
|
|
5626
|
+
USER_IDS.ME,
|
|
5627
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5628
|
+
);
|
|
4544
5629
|
const data3 = generateData(data2.payload, false, false, USER_IDS.ME);
|
|
4545
5630
|
|
|
4546
5631
|
payloadTestHelper([data1, data2, data3]);
|
|
@@ -4548,7 +5633,13 @@ describe('plugin-meetings', () => {
|
|
|
4548
5633
|
|
|
4549
5634
|
it('Scenario #2: you share desktop and remote person A shares whiteboard', () => {
|
|
4550
5635
|
const data1 = generateData(blankPayload, true, true, USER_IDS.ME);
|
|
4551
|
-
const data2 = generateData(
|
|
5636
|
+
const data2 = generateData(
|
|
5637
|
+
data1.payload,
|
|
5638
|
+
true,
|
|
5639
|
+
false,
|
|
5640
|
+
USER_IDS.REMOTE_A,
|
|
5641
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5642
|
+
);
|
|
4552
5643
|
const data3 = generateData(data2.payload, false, false, USER_IDS.REMOTE_A);
|
|
4553
5644
|
|
|
4554
5645
|
payloadTestHelper([data1, data2, data3]);
|
|
@@ -4556,7 +5647,13 @@ describe('plugin-meetings', () => {
|
|
|
4556
5647
|
|
|
4557
5648
|
it('Scenario #3: remote person A shares desktop and you share whiteboard', () => {
|
|
4558
5649
|
const data1 = generateData(blankPayload, true, true, USER_IDS.REMOTE_A);
|
|
4559
|
-
const data2 = generateData(
|
|
5650
|
+
const data2 = generateData(
|
|
5651
|
+
data1.payload,
|
|
5652
|
+
true,
|
|
5653
|
+
false,
|
|
5654
|
+
USER_IDS.REMOTE_A,
|
|
5655
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5656
|
+
);
|
|
4560
5657
|
const data3 = generateData(data2.payload, false, false, USER_IDS.REMOTE_A);
|
|
4561
5658
|
|
|
4562
5659
|
payloadTestHelper([data1, data2, data3]);
|
|
@@ -4564,7 +5661,13 @@ describe('plugin-meetings', () => {
|
|
|
4564
5661
|
|
|
4565
5662
|
it('Scenario #4: remote person A shares desktop and then shares whiteboard', () => {
|
|
4566
5663
|
const data1 = generateData(blankPayload, true, true, USER_IDS.REMOTE_A);
|
|
4567
|
-
const data2 = generateData(
|
|
5664
|
+
const data2 = generateData(
|
|
5665
|
+
data1.payload,
|
|
5666
|
+
true,
|
|
5667
|
+
false,
|
|
5668
|
+
USER_IDS.ME,
|
|
5669
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5670
|
+
);
|
|
4568
5671
|
const data3 = generateData(data2.payload, false, false, USER_IDS.ME);
|
|
4569
5672
|
|
|
4570
5673
|
payloadTestHelper([data1, data2, data3]);
|
|
@@ -4572,7 +5675,13 @@ describe('plugin-meetings', () => {
|
|
|
4572
5675
|
|
|
4573
5676
|
it('Scenario #5: remote person A shares desktop and remote person B shares whiteboard', () => {
|
|
4574
5677
|
const data1 = generateData(blankPayload, true, true, USER_IDS.REMOTE_A);
|
|
4575
|
-
const data2 = generateData(
|
|
5678
|
+
const data2 = generateData(
|
|
5679
|
+
data1.payload,
|
|
5680
|
+
true,
|
|
5681
|
+
false,
|
|
5682
|
+
USER_IDS.REMOTE_A,
|
|
5683
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5684
|
+
);
|
|
4576
5685
|
const data3 = generateData(data2.payload, false, false, USER_IDS.REMOTE_A);
|
|
4577
5686
|
|
|
4578
5687
|
payloadTestHelper([data1, data2, data3]);
|
|
@@ -4648,17 +5757,21 @@ describe('plugin-meetings', () => {
|
|
|
4648
5757
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4649
5758
|
meeting.joinedWith = {
|
|
4650
5759
|
keepAliveUrl: defaultKeepAliveUrl,
|
|
4651
|
-
keepAliveSecs: defaultKeepAliveSecs
|
|
5760
|
+
keepAliveSecs: defaultKeepAliveSecs,
|
|
4652
5761
|
};
|
|
4653
5762
|
meeting.startKeepAlive();
|
|
4654
5763
|
assert.isNumber(meeting.keepAliveTimerId.id);
|
|
4655
5764
|
await testUtils.flushPromises();
|
|
4656
5765
|
assert.notCalled(meeting.meetingRequest.keepAlive);
|
|
4657
5766
|
await progressTime(defaultExpectedInterval);
|
|
4658
|
-
assert.calledOnceWithExactly(meeting.meetingRequest.keepAlive, {
|
|
5767
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.keepAlive, {
|
|
5768
|
+
keepAliveUrl: defaultKeepAliveUrl,
|
|
5769
|
+
});
|
|
4659
5770
|
await progressTime(defaultExpectedInterval);
|
|
4660
5771
|
assert.calledTwice(meeting.meetingRequest.keepAlive);
|
|
4661
|
-
assert.alwaysCalledWithExactly(meeting.meetingRequest.keepAlive, {
|
|
5772
|
+
assert.alwaysCalledWithExactly(meeting.meetingRequest.keepAlive, {
|
|
5773
|
+
keepAliveUrl: defaultKeepAliveUrl,
|
|
5774
|
+
});
|
|
4662
5775
|
});
|
|
4663
5776
|
it('startKeepAlive handles existing keepAliveTimerId', async () => {
|
|
4664
5777
|
meeting.meetingRequest.keepAlive = sinon.stub().returns(Promise.resolve());
|
|
@@ -4667,7 +5780,7 @@ describe('plugin-meetings', () => {
|
|
|
4667
5780
|
meeting.keepAliveTimerId = 7;
|
|
4668
5781
|
meeting.joinedWith = {
|
|
4669
5782
|
keepAliveUrl: defaultKeepAliveUrl,
|
|
4670
|
-
keepAliveSecs: defaultKeepAliveSecs
|
|
5783
|
+
keepAliveSecs: defaultKeepAliveSecs,
|
|
4671
5784
|
};
|
|
4672
5785
|
meeting.startKeepAlive();
|
|
4673
5786
|
assert.equal(meeting.keepAliveTimerId, 7);
|
|
@@ -4680,7 +5793,7 @@ describe('plugin-meetings', () => {
|
|
|
4680
5793
|
|
|
4681
5794
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4682
5795
|
meeting.joinedWith = {
|
|
4683
|
-
keepAliveSecs: defaultKeepAliveSecs
|
|
5796
|
+
keepAliveSecs: defaultKeepAliveSecs,
|
|
4684
5797
|
};
|
|
4685
5798
|
meeting.startKeepAlive();
|
|
4686
5799
|
assert.isNull(meeting.keepAliveTimerId);
|
|
@@ -4693,7 +5806,7 @@ describe('plugin-meetings', () => {
|
|
|
4693
5806
|
|
|
4694
5807
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4695
5808
|
meeting.joinedWith = {
|
|
4696
|
-
keepAliveUrl: defaultKeepAliveUrl
|
|
5809
|
+
keepAliveUrl: defaultKeepAliveUrl,
|
|
4697
5810
|
};
|
|
4698
5811
|
meeting.startKeepAlive();
|
|
4699
5812
|
assert.isNull(meeting.keepAliveTimerId);
|
|
@@ -4707,7 +5820,7 @@ describe('plugin-meetings', () => {
|
|
|
4707
5820
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4708
5821
|
meeting.joinedWith = {
|
|
4709
5822
|
keepAliveUrl: defaultKeepAliveUrl,
|
|
4710
|
-
keepAliveSecs: 1
|
|
5823
|
+
keepAliveSecs: 1,
|
|
4711
5824
|
};
|
|
4712
5825
|
meeting.startKeepAlive();
|
|
4713
5826
|
assert.isNull(meeting.keepAliveTimerId);
|
|
@@ -4720,14 +5833,16 @@ describe('plugin-meetings', () => {
|
|
|
4720
5833
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4721
5834
|
meeting.joinedWith = {
|
|
4722
5835
|
keepAliveUrl: defaultKeepAliveUrl,
|
|
4723
|
-
keepAliveSecs: defaultKeepAliveSecs
|
|
5836
|
+
keepAliveSecs: defaultKeepAliveSecs,
|
|
4724
5837
|
};
|
|
4725
5838
|
meeting.startKeepAlive();
|
|
4726
5839
|
assert.isNumber(meeting.keepAliveTimerId.id);
|
|
4727
5840
|
await testUtils.flushPromises();
|
|
4728
5841
|
assert.notCalled(meeting.meetingRequest.keepAlive);
|
|
4729
5842
|
await progressTime(defaultExpectedInterval);
|
|
4730
|
-
assert.calledOnceWithExactly(meeting.meetingRequest.keepAlive, {
|
|
5843
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.keepAlive, {
|
|
5844
|
+
keepAliveUrl: defaultKeepAliveUrl,
|
|
5845
|
+
});
|
|
4731
5846
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4732
5847
|
await progressTime(defaultExpectedInterval);
|
|
4733
5848
|
assert.calledOnce(meeting.meetingRequest.keepAlive);
|
|
@@ -4757,12 +5872,14 @@ describe('plugin-meetings', () => {
|
|
|
4757
5872
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4758
5873
|
meeting.joinedWith = {
|
|
4759
5874
|
keepAliveUrl: defaultKeepAliveUrl,
|
|
4760
|
-
keepAliveSecs: defaultKeepAliveSecs
|
|
5875
|
+
keepAliveSecs: defaultKeepAliveSecs,
|
|
4761
5876
|
};
|
|
4762
5877
|
meeting.startKeepAlive();
|
|
4763
5878
|
assert.isNumber(meeting.keepAliveTimerId.id);
|
|
4764
5879
|
await progressTime(defaultExpectedInterval);
|
|
4765
|
-
assert.calledOnceWithExactly(meeting.meetingRequest.keepAlive, {
|
|
5880
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.keepAlive, {
|
|
5881
|
+
keepAliveUrl: defaultKeepAliveUrl,
|
|
5882
|
+
});
|
|
4766
5883
|
|
|
4767
5884
|
meeting.stopKeepAlive();
|
|
4768
5885
|
assert.isNull(meeting.keepAliveTimerId);
|
|
@@ -4774,6 +5891,164 @@ describe('plugin-meetings', () => {
|
|
|
4774
5891
|
meeting.stopKeepAlive();
|
|
4775
5892
|
});
|
|
4776
5893
|
});
|
|
5894
|
+
|
|
5895
|
+
describe('#sendReaction', () => {
|
|
5896
|
+
it('should have #sendReaction', () => {
|
|
5897
|
+
assert.exists(meeting.sendReaction);
|
|
5898
|
+
});
|
|
5899
|
+
|
|
5900
|
+
beforeEach(() => {
|
|
5901
|
+
meeting.meetingRequest.sendReaction = sinon.stub().returns(Promise.resolve());
|
|
5902
|
+
});
|
|
5903
|
+
|
|
5904
|
+
it('should send reaction with the right data and return a promise', async () => {
|
|
5905
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: 'Fake URL'}};
|
|
5906
|
+
|
|
5907
|
+
const reactionPromise = meeting.sendReaction('thumb_down', 'light');
|
|
5908
|
+
|
|
5909
|
+
assert.exists(reactionPromise.then);
|
|
5910
|
+
await reactionPromise;
|
|
5911
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.sendReaction, {
|
|
5912
|
+
reactionChannelUrl: 'Fake URL',
|
|
5913
|
+
reaction: {
|
|
5914
|
+
type: 'thumb_down',
|
|
5915
|
+
codepoints: '1F44E',
|
|
5916
|
+
shortcodes: ':thumbsdown:',
|
|
5917
|
+
tone: {
|
|
5918
|
+
type: 'light_skin_tone',
|
|
5919
|
+
codepoints: '1F3FB',
|
|
5920
|
+
shortcodes: ':skin-tone-2:',
|
|
5921
|
+
},
|
|
5922
|
+
},
|
|
5923
|
+
participantId: meeting.members.selfId,
|
|
5924
|
+
});
|
|
5925
|
+
});
|
|
5926
|
+
|
|
5927
|
+
it('should fail sending a reaction if data channel is undefined', async () => {
|
|
5928
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: undefined}};
|
|
5929
|
+
|
|
5930
|
+
await assert.isRejected(
|
|
5931
|
+
meeting.sendReaction('thumb_down', 'light'),
|
|
5932
|
+
Error,
|
|
5933
|
+
'Error sending reaction, service url not found.'
|
|
5934
|
+
);
|
|
5935
|
+
|
|
5936
|
+
assert.notCalled(meeting.meetingRequest.sendReaction);
|
|
5937
|
+
});
|
|
5938
|
+
|
|
5939
|
+
it('should fail sending a reaction if reactionType is invalid ', async () => {
|
|
5940
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: 'Fake URL'}};
|
|
5941
|
+
|
|
5942
|
+
await assert.isRejected(
|
|
5943
|
+
meeting.sendReaction('invalid_reaction', 'light'),
|
|
5944
|
+
Error,
|
|
5945
|
+
'invalid_reaction is not a valid reaction.'
|
|
5946
|
+
);
|
|
5947
|
+
|
|
5948
|
+
assert.notCalled(meeting.meetingRequest.sendReaction);
|
|
5949
|
+
});
|
|
5950
|
+
|
|
5951
|
+
it('should send a reaction with default skin tone if provided skinToneType is invalid ', async () => {
|
|
5952
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: 'Fake URL'}};
|
|
5953
|
+
|
|
5954
|
+
const reactionPromise = meeting.sendReaction('thumb_down', 'invalid_skin_tone');
|
|
5955
|
+
|
|
5956
|
+
assert.exists(reactionPromise.then);
|
|
5957
|
+
await reactionPromise;
|
|
5958
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.sendReaction, {
|
|
5959
|
+
reactionChannelUrl: 'Fake URL',
|
|
5960
|
+
reaction: {
|
|
5961
|
+
type: 'thumb_down',
|
|
5962
|
+
codepoints: '1F44E',
|
|
5963
|
+
shortcodes: ':thumbsdown:',
|
|
5964
|
+
tone: {type: 'normal_skin_tone', codepoints: '', shortcodes: ''},
|
|
5965
|
+
},
|
|
5966
|
+
participantId: meeting.members.selfId,
|
|
5967
|
+
});
|
|
5968
|
+
});
|
|
5969
|
+
|
|
5970
|
+
it('should send a reaction with default skin tone if none provided', async () => {
|
|
5971
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: 'Fake URL'}};
|
|
5972
|
+
|
|
5973
|
+
const reactionPromise = meeting.sendReaction('thumb_down');
|
|
5974
|
+
|
|
5975
|
+
assert.exists(reactionPromise.then);
|
|
5976
|
+
await reactionPromise;
|
|
5977
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.sendReaction, {
|
|
5978
|
+
reactionChannelUrl: 'Fake URL',
|
|
5979
|
+
reaction: {
|
|
5980
|
+
type: 'thumb_down',
|
|
5981
|
+
codepoints: '1F44E',
|
|
5982
|
+
shortcodes: ':thumbsdown:',
|
|
5983
|
+
tone: {type: 'normal_skin_tone', codepoints: '', shortcodes: ''},
|
|
5984
|
+
},
|
|
5985
|
+
participantId: meeting.members.selfId,
|
|
5986
|
+
});
|
|
5987
|
+
});
|
|
5988
|
+
});
|
|
5989
|
+
describe('#toggleReactions', () => {
|
|
5990
|
+
it('should have #toggleReactions', () => {
|
|
5991
|
+
assert.exists(meeting.toggleReactions);
|
|
5992
|
+
});
|
|
5993
|
+
|
|
5994
|
+
beforeEach(() => {
|
|
5995
|
+
meeting.meetingRequest.toggleReactions = sinon.stub().returns(Promise.resolve());
|
|
5996
|
+
});
|
|
5997
|
+
|
|
5998
|
+
it('should toggle the reactions with the right data and return a promise', async () => {
|
|
5999
|
+
meeting.locusUrl = 'locusUrl';
|
|
6000
|
+
meeting.locusInfo.controls = {reactions: {enabled: false}};
|
|
6001
|
+
|
|
6002
|
+
const togglePromise = meeting.toggleReactions(true);
|
|
6003
|
+
|
|
6004
|
+
assert.exists(togglePromise.then);
|
|
6005
|
+
await togglePromise;
|
|
6006
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.toggleReactions, {
|
|
6007
|
+
locusUrl: 'locusUrl',
|
|
6008
|
+
enable: true,
|
|
6009
|
+
requestingParticipantId: meeting.members.selfId,
|
|
6010
|
+
});
|
|
6011
|
+
});
|
|
6012
|
+
|
|
6013
|
+
it('should resolve immediately if already enabled', async () => {
|
|
6014
|
+
meeting.locusUrl = 'locusUrl';
|
|
6015
|
+
meeting.locusInfo.controls = {reactions: {enabled: true}};
|
|
6016
|
+
|
|
6017
|
+
const togglePromise = meeting.toggleReactions(true);
|
|
6018
|
+
|
|
6019
|
+
const response = await togglePromise;
|
|
6020
|
+
|
|
6021
|
+
assert.equal(response, 'Reactions are already enabled.');
|
|
6022
|
+
assert.notCalled(meeting.meetingRequest.toggleReactions);
|
|
6023
|
+
});
|
|
6024
|
+
|
|
6025
|
+
it('should resolve immediately if already disabled', async () => {
|
|
6026
|
+
meeting.locusUrl = 'locusUrl';
|
|
6027
|
+
meeting.locusInfo.controls = {reactions: {enabled: false}};
|
|
6028
|
+
|
|
6029
|
+
const togglePromise = meeting.toggleReactions(false);
|
|
6030
|
+
|
|
6031
|
+
const response = await togglePromise;
|
|
6032
|
+
|
|
6033
|
+
assert.equal(response, 'Reactions are already disabled.');
|
|
6034
|
+
assert.notCalled(meeting.meetingRequest.toggleReactions);
|
|
6035
|
+
});
|
|
6036
|
+
|
|
6037
|
+
it('should toggle reactions on if controls is undefined and enable = true', async () => {
|
|
6038
|
+
meeting.locusUrl = 'locusUrl';
|
|
6039
|
+
meeting.locusInfo.controls = undefined;
|
|
6040
|
+
|
|
6041
|
+
const togglePromise = meeting.toggleReactions(true);
|
|
6042
|
+
|
|
6043
|
+
assert.exists(togglePromise.then);
|
|
6044
|
+
await togglePromise;
|
|
6045
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.toggleReactions, {
|
|
6046
|
+
locusUrl: 'locusUrl',
|
|
6047
|
+
enable: true,
|
|
6048
|
+
requestingParticipantId: meeting.members.selfId,
|
|
6049
|
+
});
|
|
6050
|
+
});
|
|
6051
|
+
});
|
|
4777
6052
|
});
|
|
4778
6053
|
});
|
|
4779
6054
|
});
|