@webex/plugin-meetings 3.0.0-beta.3 → 3.0.0-beta.30
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 +137 -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 +374 -0
- package/dist/breakouts/index.js.map +1 -0
- package/dist/breakouts/request.js +78 -0
- package/dist/breakouts/request.js.map +1 -0
- package/dist/breakouts/utils.js +23 -0
- package/dist/breakouts/utils.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 +92 -49
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/constants.js +14 -0
- package/dist/controls-options-manager/constants.js.map +1 -0
- package/dist/controls-options-manager/enums.js +15 -0
- package/dist/controls-options-manager/enums.js.map +1 -0
- package/dist/controls-options-manager/index.js +203 -0
- package/dist/controls-options-manager/index.js.map +1 -0
- package/dist/controls-options-manager/util.js +28 -0
- package/dist/controls-options-manager/util.js.map +1 -0
- 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 +186 -192
- 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 +64 -137
- 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 +505 -495
- 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 +13 -14
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +2142 -2101
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +39 -80
- 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 +116 -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 +94 -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 -33
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +30 -50
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +60 -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 +360 -413
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/networkQualityMonitor/index.js +40 -59
- 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 +1 -95
- package/dist/statsAnalyzer/global.js.map +1 -1
- package/dist/statsAnalyzer/index.js +357 -449
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +137 -81
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/transcription/index.js +22 -47
- package/dist/transcription/index.js.map +1 -1
- package/dist/types/breakouts/breakout.d.ts +8 -0
- package/dist/types/breakouts/collection.d.ts +5 -0
- package/dist/types/breakouts/index.d.ts +5 -0
- package/dist/types/breakouts/request.d.ts +22 -0
- package/dist/types/breakouts/utils.d.ts +1 -0
- package/dist/types/common/browser-detection.d.ts +9 -0
- package/dist/types/common/collection.d.ts +48 -0
- package/dist/types/common/config.d.ts +2 -0
- package/dist/types/common/errors/captcha-error.d.ts +15 -0
- package/dist/types/common/errors/intent-to-join.d.ts +16 -0
- package/dist/types/common/errors/join-meeting.d.ts +17 -0
- package/dist/types/common/errors/media.d.ts +15 -0
- package/dist/types/common/errors/parameter.d.ts +15 -0
- package/dist/types/common/errors/password-error.d.ts +15 -0
- package/dist/types/common/errors/permission.d.ts +14 -0
- package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
- package/dist/types/common/errors/reconnection.d.ts +15 -0
- package/dist/types/common/errors/stats.d.ts +15 -0
- package/dist/types/common/errors/webex-errors.d.ts +69 -0
- package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
- package/dist/types/common/events/events-scope.d.ts +17 -0
- package/dist/types/common/events/events.d.ts +12 -0
- package/dist/types/common/events/trigger-proxy.d.ts +2 -0
- package/dist/types/common/events/util.d.ts +2 -0
- package/dist/types/common/logs/logger-config.d.ts +2 -0
- package/dist/types/common/logs/logger-proxy.d.ts +2 -0
- package/dist/types/common/logs/request.d.ts +34 -0
- package/dist/types/common/queue.d.ts +32 -0
- package/dist/types/config.d.ts +77 -0
- package/dist/types/constants.d.ts +899 -0
- package/dist/types/controls-options-manager/constants.d.ts +4 -0
- package/dist/types/controls-options-manager/enums.d.ts +5 -0
- package/dist/types/controls-options-manager/index.d.ts +120 -0
- package/dist/types/controls-options-manager/util.d.ts +7 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/locus-info/controlsUtils.d.ts +2 -0
- package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
- package/dist/types/locus-info/fullState.d.ts +2 -0
- package/dist/types/locus-info/hostUtils.d.ts +2 -0
- package/dist/types/locus-info/index.d.ts +269 -0
- package/dist/types/locus-info/infoUtils.d.ts +2 -0
- package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
- package/dist/types/locus-info/parser.d.ts +212 -0
- package/dist/types/locus-info/selfUtils.d.ts +2 -0
- package/dist/types/media/index.d.ts +32 -0
- package/dist/types/media/properties.d.ts +107 -0
- package/dist/types/media/util.d.ts +2 -0
- package/dist/types/mediaQualityMetrics/config.d.ts +365 -0
- package/dist/types/meeting/effectsState.d.ts +42 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +83 -0
- package/dist/types/meeting/index.d.ts +1724 -0
- package/dist/types/meeting/muteState.d.ts +108 -0
- package/dist/types/meeting/request.d.ts +261 -0
- package/dist/types/meeting/request.type.d.ts +11 -0
- package/dist/types/meeting/state.d.ts +9 -0
- package/dist/types/meeting/util.d.ts +2 -0
- package/dist/types/meeting-info/collection.d.ts +20 -0
- package/dist/types/meeting-info/index.d.ts +57 -0
- package/dist/types/meeting-info/meeting-info-v2.d.ts +93 -0
- package/dist/types/meeting-info/request.d.ts +22 -0
- package/dist/types/meeting-info/util.d.ts +2 -0
- package/dist/types/meeting-info/utilv2.d.ts +2 -0
- package/dist/types/meetings/collection.d.ts +23 -0
- package/dist/types/meetings/index.d.ts +297 -0
- package/dist/types/meetings/request.d.ts +27 -0
- package/dist/types/meetings/util.d.ts +18 -0
- package/dist/types/member/index.d.ts +146 -0
- package/dist/types/member/util.d.ts +2 -0
- package/dist/types/members/collection.d.ts +24 -0
- package/dist/types/members/index.d.ts +320 -0
- package/dist/types/members/request.d.ts +50 -0
- package/dist/types/members/util.d.ts +2 -0
- package/dist/types/metrics/config.d.ts +178 -0
- package/dist/types/metrics/constants.d.ts +57 -0
- package/dist/types/metrics/index.d.ts +160 -0
- package/dist/types/multistream/mediaRequestManager.d.ts +50 -0
- package/dist/types/multistream/receiveSlot.d.ts +66 -0
- package/dist/types/multistream/receiveSlotManager.d.ts +46 -0
- package/dist/types/multistream/remoteMedia.d.ts +93 -0
- package/dist/types/multistream/remoteMediaGroup.d.ts +56 -0
- package/dist/types/multistream/remoteMediaManager.d.ts +241 -0
- package/dist/types/networkQualityMonitor/index.d.ts +70 -0
- package/dist/types/personal-meeting-room/index.d.ts +47 -0
- package/dist/types/personal-meeting-room/request.d.ts +14 -0
- package/dist/types/personal-meeting-room/util.d.ts +2 -0
- package/dist/types/reachability/index.d.ts +140 -0
- package/dist/types/reachability/request.d.ts +35 -0
- package/dist/types/reactions/constants.d.ts +3 -0
- package/dist/types/reactions/reactions.d.ts +4 -0
- package/dist/types/reactions/reactions.type.d.ts +52 -0
- package/dist/types/reconnection-manager/index.d.ts +117 -0
- package/dist/types/recording-controller/enums.d.ts +7 -0
- package/dist/types/recording-controller/index.d.ts +193 -0
- package/dist/types/recording-controller/util.d.ts +13 -0
- package/dist/types/roap/index.d.ts +77 -0
- package/dist/types/roap/request.d.ts +35 -0
- package/dist/types/roap/turnDiscovery.d.ts +74 -0
- package/dist/types/statsAnalyzer/global.d.ts +36 -0
- package/dist/types/statsAnalyzer/index.d.ts +195 -0
- package/dist/types/statsAnalyzer/mqaUtil.d.ts +24 -0
- package/dist/types/transcription/index.d.ts +64 -0
- package/internal-README.md +7 -6
- package/package.json +25 -20
- package/src/breakouts/README.md +190 -0
- package/src/breakouts/breakout.ts +130 -0
- package/src/breakouts/collection.ts +19 -0
- package/src/breakouts/index.ts +353 -0
- package/src/breakouts/request.ts +55 -0
- package/src/breakouts/utils.ts +15 -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.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 +44 -4
- package/src/controls-options-manager/constants.ts +5 -0
- package/src/controls-options-manager/enums.ts +6 -0
- package/src/controls-options-manager/index.ts +183 -0
- package/src/controls-options-manager/util.ts +20 -0
- 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} +150 -66
- 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} +176 -157
- package/src/media/{properties.js → properties.ts} +48 -31
- package/src/media/{util.js → util.ts} +2 -2
- package/src/mediaQualityMetrics/config.ts +384 -0
- package/src/meeting/{effectsState.js → effectsState.ts} +47 -41
- package/src/meeting/in-meeting-actions.ts +31 -3
- package/src/meeting/{index.js → index.ts} +2479 -1466
- package/src/meeting/{muteState.js → muteState.ts} +80 -45
- 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} +58 -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} +221 -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 +79 -15
- package/src/multistream/receiveSlot.ts +42 -13
- package/src/multistream/receiveSlotManager.ts +35 -21
- package/src/multistream/remoteMedia.ts +15 -5
- package/src/multistream/remoteMediaGroup.ts +4 -3
- package/src/multistream/remoteMediaManager.ts +152 -36
- package/src/networkQualityMonitor/{index.js → index.ts} +41 -29
- 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.ts +37 -0
- package/src/statsAnalyzer/index.ts +1234 -0
- package/src/statsAnalyzer/mqaUtil.ts +293 -0
- package/src/transcription/{index.js → index.ts} +46 -39
- package/test/integration/spec/converged-space-meetings.js +176 -0
- 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 +147 -0
- package/test/unit/spec/breakouts/collection.ts +15 -0
- package/test/unit/spec/breakouts/index.ts +464 -0
- package/test/unit/spec/breakouts/request.ts +104 -0
- package/test/unit/spec/breakouts/utils.js +21 -0
- package/test/unit/spec/common/browser-detection.js +9 -28
- package/test/unit/spec/controls-options-manager/index.js +124 -0
- package/test/unit/spec/controls-options-manager/util.js +66 -0
- 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 +13 -2
- package/test/unit/spec/meeting/index.js +2214 -746
- package/test/unit/spec/meeting/muteState.js +43 -34
- 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 +312 -50
- package/test/unit/spec/multistream/receiveSlot.ts +57 -6
- package/test/unit/spec/multistream/receiveSlotManager.ts +41 -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 +24 -18
- 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 +86 -57
- package/test/utils/cmr.js +44 -42
- package/test/utils/constants.js +9 -0
- package/test/utils/testUtils.js +96 -80
- package/test/utils/webex-config.js +22 -18
- package/test/utils/webex-test-users.js +57 -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/multistream/multistreamMedia.js +0 -116
- package/dist/multistream/multistreamMedia.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/mediaQualityMetrics/config.js +0 -382
- package/src/meeting-info/meeting-info-v2.js +0 -255
- package/src/meetings/index.js +0 -1015
- package/src/multistream/multistreamMedia.ts +0 -92
- package/src/peer-connection-manager/util.ts +0 -117
- package/src/roap/request.js +0 -127
- package/src/statsAnalyzer/global.js +0 -133
- package/src/statsAnalyzer/index.js +0 -1006
- package/src/statsAnalyzer/mqaUtil.js +0 -173
- package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -389
- /package/src/common/errors/{reconnection-in-progress.js → reconnection-in-progress.ts} +0 -0
|
@@ -22,8 +22,9 @@ 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
|
+
import * as MuteStateModule from '@webex/plugin-meetings/src/meeting/muteState';
|
|
27
28
|
import EventsScope from '@webex/plugin-meetings/src/common/events/events-scope';
|
|
28
29
|
import Meetings, {CONSTANTS} from '@webex/plugin-meetings';
|
|
29
30
|
import Meeting from '@webex/plugin-meetings/src/meeting';
|
|
@@ -36,6 +37,8 @@ import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
|
|
|
36
37
|
import Media from '@webex/plugin-meetings/src/media/index';
|
|
37
38
|
import ReconnectionManager from '@webex/plugin-meetings/src/reconnection-manager';
|
|
38
39
|
import MediaUtil from '@webex/plugin-meetings/src/media/util';
|
|
40
|
+
import RecordingUtil from '@webex/plugin-meetings/src/recording-controller/util';
|
|
41
|
+
import ControlsOptionsUtil from '@webex/plugin-meetings/src/controls-options-manager/util';
|
|
39
42
|
import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
|
|
40
43
|
import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
|
|
41
44
|
import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
|
|
@@ -44,13 +47,18 @@ import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
|
44
47
|
import {trigger, eventType} from '@webex/plugin-meetings/src/metrics/config';
|
|
45
48
|
import BEHAVIORAL_METRICS from '@webex/plugin-meetings/src/metrics/constants';
|
|
46
49
|
import {IceGatheringFailed} from '@webex/plugin-meetings/src/common/errors/webex-errors';
|
|
50
|
+
import {MediaRequestManager} from '@webex/plugin-meetings/src/multistream/mediaRequestManager';
|
|
47
51
|
|
|
52
|
+
import LLM from '@webex/internal-plugin-llm';
|
|
53
|
+
import Mercury from '@webex/internal-plugin-mercury';
|
|
54
|
+
import Breakouts from '@webex/plugin-meetings/src/breakouts';
|
|
55
|
+
import {REACTION_RELAY_TYPES} from '../../../../src/reactions/constants';
|
|
48
56
|
import locus from '../fixture/locus';
|
|
49
57
|
import {
|
|
50
58
|
UserNotJoinedError,
|
|
51
59
|
MeetingNotActiveError,
|
|
52
60
|
UserInLobbyError,
|
|
53
|
-
NoMediaEstablishedYetError
|
|
61
|
+
NoMediaEstablishedYetError,
|
|
54
62
|
} from '../../../../src/common/errors/webex-errors';
|
|
55
63
|
import WebExMeetingsErrors from '../../../../src/common/errors/webex-meetings-error';
|
|
56
64
|
import ParameterError from '../../../../src/common/errors/parameter';
|
|
@@ -59,11 +67,12 @@ import CaptchaError from '../../../../src/common/errors/captcha-error';
|
|
|
59
67
|
import IntentToJoinError from '../../../../src/common/errors/intent-to-join';
|
|
60
68
|
import DefaultSDKConfig from '../../../../src/config';
|
|
61
69
|
import testUtils from '../../../utils/testUtils';
|
|
62
|
-
import {
|
|
70
|
+
import {
|
|
71
|
+
MeetingInfoV2CaptchaError,
|
|
72
|
+
MeetingInfoV2PasswordError,
|
|
73
|
+
} from '../../../../src/meeting-info/meeting-info-v2';
|
|
63
74
|
|
|
64
|
-
const {
|
|
65
|
-
getBrowserName
|
|
66
|
-
} = BrowserDetection();
|
|
75
|
+
const {getBrowserName} = BrowserDetection();
|
|
67
76
|
|
|
68
77
|
// Non-stubbed function
|
|
69
78
|
const {getDisplayMedia} = Media;
|
|
@@ -75,7 +84,7 @@ describe('plugin-meetings', () => {
|
|
|
75
84
|
error: () => {},
|
|
76
85
|
warn: () => {},
|
|
77
86
|
trace: () => {},
|
|
78
|
-
debug: () => {}
|
|
87
|
+
debug: () => {},
|
|
79
88
|
};
|
|
80
89
|
|
|
81
90
|
beforeEach(() => {
|
|
@@ -87,44 +96,48 @@ describe('plugin-meetings', () => {
|
|
|
87
96
|
|
|
88
97
|
before(() => {
|
|
89
98
|
const MediaStream = {
|
|
90
|
-
getVideoTracks: () => [
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
getVideoTracks: () => [
|
|
100
|
+
{
|
|
101
|
+
applyConstraints: () => {},
|
|
102
|
+
},
|
|
103
|
+
],
|
|
93
104
|
};
|
|
94
105
|
|
|
95
106
|
Object.defineProperty(global.window.navigator, 'mediaDevices', {
|
|
96
107
|
writable: true,
|
|
97
108
|
value: {
|
|
98
109
|
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
|
-
|
|
110
|
+
enumerateDevices: sinon.stub().returns(
|
|
111
|
+
Promise.resolve([
|
|
112
|
+
{
|
|
113
|
+
deviceId: '',
|
|
114
|
+
kind: 'audioinput',
|
|
115
|
+
label: '',
|
|
116
|
+
groupId: '29d9339cc77bffdd24cb69ee80f6d3200481099bcd0f29267558672de0430777',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
deviceId: '',
|
|
120
|
+
kind: 'videoinput',
|
|
121
|
+
label: '',
|
|
122
|
+
groupId: '08d4f8200e7e4a3425ecf75b7edea9ae4acd934019f2a52217554bcc8e46604d',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
deviceId: '',
|
|
126
|
+
kind: 'audiooutput',
|
|
127
|
+
label: '',
|
|
128
|
+
groupId: '29d9339cc77bffdd24cb69ee80f6d3200481099bcd0f29267558672de0430777',
|
|
129
|
+
},
|
|
130
|
+
])
|
|
131
|
+
),
|
|
119
132
|
getSupportedConstraints: sinon.stub().returns({
|
|
120
|
-
sampleRate: true
|
|
121
|
-
})
|
|
133
|
+
sampleRate: true,
|
|
134
|
+
}),
|
|
122
135
|
},
|
|
123
136
|
});
|
|
124
137
|
|
|
125
138
|
Object.defineProperty(global.window, 'MediaStream', {
|
|
126
139
|
writable: true,
|
|
127
|
-
value: MediaStream
|
|
140
|
+
value: MediaStream,
|
|
128
141
|
});
|
|
129
142
|
LoggerConfig.set({verboseEvents: true, enable: false});
|
|
130
143
|
LoggerProxy.set(logger);
|
|
@@ -149,32 +162,34 @@ describe('plugin-meetings', () => {
|
|
|
149
162
|
children: {
|
|
150
163
|
meetings: Meetings,
|
|
151
164
|
credentials: Credentials,
|
|
152
|
-
support: Support
|
|
165
|
+
support: Support,
|
|
166
|
+
llm: LLM,
|
|
167
|
+
mercury: Mercury,
|
|
153
168
|
},
|
|
154
169
|
config: {
|
|
155
170
|
credentials: {
|
|
156
|
-
client_id: 'mock-client-id'
|
|
171
|
+
client_id: 'mock-client-id',
|
|
157
172
|
},
|
|
158
173
|
meetings: {
|
|
159
174
|
reconnection: {
|
|
160
|
-
enabled: false
|
|
175
|
+
enabled: false,
|
|
161
176
|
},
|
|
162
177
|
mediaSettings: {},
|
|
163
178
|
metrics: {},
|
|
164
179
|
stats: {},
|
|
165
|
-
experimental: {enableUnifiedMeetings: true}
|
|
180
|
+
experimental: {enableUnifiedMeetings: true},
|
|
166
181
|
},
|
|
167
182
|
metrics: {
|
|
168
|
-
type: ['behavioral']
|
|
169
|
-
}
|
|
170
|
-
}
|
|
183
|
+
type: ['behavioral'],
|
|
184
|
+
},
|
|
185
|
+
},
|
|
171
186
|
});
|
|
172
187
|
|
|
173
188
|
webex.internal.support.submitLogs = sinon.stub().returns(Promise.resolve());
|
|
174
189
|
webex.credentials.getOrgId = sinon.stub().returns('fake-org-id');
|
|
175
190
|
webex.internal.metrics.submitClientMetrics = sinon.stub().returns(Promise.resolve());
|
|
176
191
|
webex.meetings.uploadLogs = sinon.stub().returns(Promise.resolve());
|
|
177
|
-
|
|
192
|
+
webex.internal.llm.on = sinon.stub();
|
|
178
193
|
|
|
179
194
|
TriggerProxy.trigger = sinon.stub().returns(true);
|
|
180
195
|
Metrics.postEvent = sinon.stub();
|
|
@@ -203,7 +218,7 @@ describe('plugin-meetings', () => {
|
|
|
203
218
|
destinationType: _MEETING_ID_,
|
|
204
219
|
},
|
|
205
220
|
{
|
|
206
|
-
parent: webex
|
|
221
|
+
parent: webex,
|
|
207
222
|
}
|
|
208
223
|
);
|
|
209
224
|
|
|
@@ -246,6 +261,13 @@ describe('plugin-meetings', () => {
|
|
|
246
261
|
assert.equal(meeting.meetingInfoFailureReason, undefined);
|
|
247
262
|
assert.equal(meeting.destination, testDestination);
|
|
248
263
|
assert.equal(meeting.destinationType, _MEETING_ID_);
|
|
264
|
+
assert.instanceOf(meeting.breakouts, Breakouts);
|
|
265
|
+
});
|
|
266
|
+
it('creates MediaRequestManager instances', () => {
|
|
267
|
+
assert.instanceOf(meeting.mediaRequestManagers.audio, MediaRequestManager);
|
|
268
|
+
assert.instanceOf(meeting.mediaRequestManagers.video, MediaRequestManager);
|
|
269
|
+
assert.instanceOf(meeting.mediaRequestManagers.screenShareAudio, MediaRequestManager);
|
|
270
|
+
assert.instanceOf(meeting.mediaRequestManagers.screenShareVideo, MediaRequestManager);
|
|
249
271
|
});
|
|
250
272
|
});
|
|
251
273
|
describe('#invite', () => {
|
|
@@ -432,7 +454,6 @@ describe('plugin-meetings', () => {
|
|
|
432
454
|
it('should return a promise resolution', async () => {
|
|
433
455
|
meeting.audio = {handleClientRequest};
|
|
434
456
|
|
|
435
|
-
|
|
436
457
|
const audio = meeting.unmuteAudio();
|
|
437
458
|
|
|
438
459
|
assert.exists(audio.then);
|
|
@@ -449,8 +470,8 @@ describe('plugin-meetings', () => {
|
|
|
449
470
|
readyState: 'live',
|
|
450
471
|
enabled: true,
|
|
451
472
|
getSettings: () => ({
|
|
452
|
-
sampleRate: 48000
|
|
453
|
-
})
|
|
473
|
+
sampleRate: 48000,
|
|
474
|
+
}),
|
|
454
475
|
});
|
|
455
476
|
|
|
456
477
|
beforeEach(() => {
|
|
@@ -458,7 +479,7 @@ describe('plugin-meetings', () => {
|
|
|
458
479
|
sinon.replace(meeting, 'addMedia', () => {
|
|
459
480
|
sinon.stub(meeting.mediaProperties, 'audioTrack').value(fakeMediaTrack());
|
|
460
481
|
sinon.stub(meeting.mediaProperties, 'mediaDirection').value({
|
|
461
|
-
receiveAudio: true
|
|
482
|
+
receiveAudio: true,
|
|
462
483
|
});
|
|
463
484
|
});
|
|
464
485
|
});
|
|
@@ -470,7 +491,7 @@ describe('plugin-meetings', () => {
|
|
|
470
491
|
describe('before audio attached to meeting', () => {
|
|
471
492
|
it('should throw no audio error', async () => {
|
|
472
493
|
await meeting.enableBNR().catch((err) => {
|
|
473
|
-
assert.equal(err.toString(),
|
|
494
|
+
assert.equal(err.toString(), "Error: Meeting doesn't have an audioTrack attached");
|
|
474
495
|
});
|
|
475
496
|
});
|
|
476
497
|
});
|
|
@@ -518,7 +539,7 @@ describe('plugin-meetings', () => {
|
|
|
518
539
|
|
|
519
540
|
it('should throw no audio error', async () => {
|
|
520
541
|
await meeting.disableBNR().catch((err) => {
|
|
521
|
-
assert.equal(err.toString(),
|
|
542
|
+
assert.equal(err.toString(), "Error: Meeting doesn't have an audioTrack attached");
|
|
522
543
|
});
|
|
523
544
|
});
|
|
524
545
|
});
|
|
@@ -650,7 +671,11 @@ describe('plugin-meetings', () => {
|
|
|
650
671
|
});
|
|
651
672
|
describe('#getMediaStreams', () => {
|
|
652
673
|
beforeEach(() => {
|
|
653
|
-
sinon
|
|
674
|
+
sinon
|
|
675
|
+
.stub(Media, 'getSupportedDevice')
|
|
676
|
+
.callsFake((options) =>
|
|
677
|
+
Promise.resolve({sendAudio: options.sendAudio, sendVideo: options.sendVideo})
|
|
678
|
+
);
|
|
654
679
|
sinon.stub(Media, 'getUserMedia').returns(Promise.resolve(['stream1', 'stream2']));
|
|
655
680
|
});
|
|
656
681
|
afterEach(() => {
|
|
@@ -674,17 +699,20 @@ describe('plugin-meetings', () => {
|
|
|
674
699
|
sinon.stub(meeting.mediaProperties, 'localQualityLevel').value('480p');
|
|
675
700
|
await meeting.getMediaStreams(mediaDirection, audioVideoSettings);
|
|
676
701
|
|
|
677
|
-
assert.calledWith(
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
702
|
+
assert.calledWith(
|
|
703
|
+
Media.getUserMedia,
|
|
704
|
+
{
|
|
705
|
+
...mediaDirection,
|
|
706
|
+
isSharing: false,
|
|
707
|
+
},
|
|
708
|
+
{
|
|
709
|
+
video: {
|
|
710
|
+
width: {max: 640, ideal: 640},
|
|
711
|
+
height: {max: 480, ideal: 480},
|
|
712
|
+
deviceId: videoDevice,
|
|
713
|
+
},
|
|
686
714
|
}
|
|
687
|
-
|
|
715
|
+
);
|
|
688
716
|
});
|
|
689
717
|
it('will set a new preferred video input device if passed in', async () => {
|
|
690
718
|
// if audioVideo settings parameter specifies a new video device it
|
|
@@ -709,23 +737,33 @@ describe('plugin-meetings', () => {
|
|
|
709
737
|
video: {
|
|
710
738
|
width: {
|
|
711
739
|
max: 400,
|
|
712
|
-
ideal: 400
|
|
740
|
+
ideal: 400,
|
|
713
741
|
},
|
|
714
742
|
height: {
|
|
715
743
|
max: 200,
|
|
716
|
-
ideal: 200
|
|
717
|
-
}
|
|
718
|
-
|
|
744
|
+
ideal: 200,
|
|
745
|
+
},
|
|
746
|
+
frameRate: {
|
|
747
|
+
ideal: 15,
|
|
748
|
+
max: 30,
|
|
749
|
+
},
|
|
750
|
+
facingMode: {
|
|
751
|
+
ideal: 'user',
|
|
752
|
+
},
|
|
753
|
+
},
|
|
719
754
|
};
|
|
720
755
|
|
|
721
756
|
sinon.stub(meeting.mediaProperties, 'localQualityLevel').value('200p');
|
|
722
757
|
await meeting.getMediaStreams(mediaDirection, customAudioVideoSettings);
|
|
723
758
|
|
|
724
|
-
assert.calledWith(
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
759
|
+
assert.calledWith(
|
|
760
|
+
Media.getUserMedia,
|
|
761
|
+
{
|
|
762
|
+
...mediaDirection,
|
|
763
|
+
isSharing: false,
|
|
764
|
+
},
|
|
765
|
+
customAudioVideoSettings
|
|
766
|
+
);
|
|
729
767
|
});
|
|
730
768
|
it('should not access camera if sendVideo is false ', async () => {
|
|
731
769
|
await meeting.getMediaStreams({sendAudio: true, sendVideo: false});
|
|
@@ -759,13 +797,12 @@ describe('plugin-meetings', () => {
|
|
|
759
797
|
});
|
|
760
798
|
});
|
|
761
799
|
|
|
762
|
-
it(
|
|
800
|
+
it("should throw error if request doesn't work", async () => {
|
|
763
801
|
meeting.request = sinon.stub().returns(Promise.reject());
|
|
764
802
|
|
|
765
803
|
try {
|
|
766
804
|
await meeting.receiveTranscription();
|
|
767
|
-
}
|
|
768
|
-
catch (err) {
|
|
805
|
+
} catch (err) {
|
|
769
806
|
assert(err, {});
|
|
770
807
|
}
|
|
771
808
|
});
|
|
@@ -773,15 +810,74 @@ describe('plugin-meetings', () => {
|
|
|
773
810
|
describe('#stopReceivingTranscription', () => {
|
|
774
811
|
it('should get invoked', () => {
|
|
775
812
|
meeting.transcription = {
|
|
776
|
-
closeSocket: sinon.stub()
|
|
813
|
+
closeSocket: sinon.stub(),
|
|
777
814
|
};
|
|
778
815
|
|
|
779
816
|
meeting.stopReceivingTranscription();
|
|
780
817
|
assert.calledOnce(meeting.transcription.closeSocket);
|
|
781
818
|
});
|
|
782
819
|
});
|
|
820
|
+
describe('#isReactionsSupported', () => {
|
|
821
|
+
it('should return false if the feature is not supported for the meeting', () => {
|
|
822
|
+
meeting.locusInfo.controls = {reactions: {enabled: false}};
|
|
823
|
+
|
|
824
|
+
assert.equal(meeting.isReactionsSupported(), false);
|
|
825
|
+
});
|
|
826
|
+
it('should return true if the feature is not supported for the meeting', () => {
|
|
827
|
+
meeting.locusInfo.controls = {reactions: {enabled: true}};
|
|
828
|
+
|
|
829
|
+
assert.equal(meeting.isReactionsSupported(), true);
|
|
830
|
+
});
|
|
831
|
+
});
|
|
832
|
+
describe('#processRelayEvent', () => {
|
|
833
|
+
it('should process a Reaction event type', () => {
|
|
834
|
+
meeting.isReactionsSupported = sinon.stub().returns(true);
|
|
835
|
+
meeting.config.receiveReactions = true;
|
|
836
|
+
const fakeSendersName = 'Fake reactors name';
|
|
837
|
+
meeting.members.membersCollection.get = sinon.stub().returns({name: fakeSendersName});
|
|
838
|
+
const fakeReactionPayload = {
|
|
839
|
+
type: 'fake_type',
|
|
840
|
+
codepoints: 'fake_codepoints',
|
|
841
|
+
shortcodes: 'fake_shortcodes',
|
|
842
|
+
tone: {
|
|
843
|
+
type: 'fake_tone_type',
|
|
844
|
+
codepoints: 'fake_tone_codepoints',
|
|
845
|
+
shortcodes: 'fake_tone_shortcodes',
|
|
846
|
+
},
|
|
847
|
+
};
|
|
848
|
+
const fakeSenderPayload = {
|
|
849
|
+
participantId: 'fake_participant_id',
|
|
850
|
+
};
|
|
851
|
+
const fakeProcessedReaction = {
|
|
852
|
+
reaction: fakeReactionPayload,
|
|
853
|
+
sender: {
|
|
854
|
+
id: fakeSenderPayload.participantId,
|
|
855
|
+
name: fakeSendersName,
|
|
856
|
+
},
|
|
857
|
+
};
|
|
858
|
+
const fakeRelayEvent = {
|
|
859
|
+
data: {
|
|
860
|
+
relayType: REACTION_RELAY_TYPES.REACTION,
|
|
861
|
+
reaction: fakeReactionPayload,
|
|
862
|
+
sender: fakeSenderPayload,
|
|
863
|
+
}
|
|
864
|
+
};
|
|
865
|
+
meeting.processRelayEvent(fakeRelayEvent);
|
|
866
|
+
assert.calledWith(
|
|
867
|
+
TriggerProxy.trigger,
|
|
868
|
+
sinon.match.instanceOf(Meeting),
|
|
869
|
+
{
|
|
870
|
+
file: 'meeting/index',
|
|
871
|
+
function: 'join',
|
|
872
|
+
},
|
|
873
|
+
EVENT_TRIGGERS.MEETING_RECEIVE_REACTIONS,
|
|
874
|
+
fakeProcessedReaction
|
|
875
|
+
);
|
|
876
|
+
})
|
|
877
|
+
})
|
|
783
878
|
describe('#join', () => {
|
|
784
879
|
let sandbox = null;
|
|
880
|
+
const joinMeetingResult = 'JOIN_MEETINGS_OPTION_RESULT';
|
|
785
881
|
|
|
786
882
|
beforeEach(() => {
|
|
787
883
|
sandbox = sinon.createSandbox();
|
|
@@ -799,22 +895,47 @@ describe('plugin-meetings', () => {
|
|
|
799
895
|
meeting.setCorrelationId = sinon.stub().returns(true);
|
|
800
896
|
meeting.setLocus = sinon.stub().returns(true);
|
|
801
897
|
webex.meetings.registered = true;
|
|
898
|
+
meeting.updateLLMConnection = sinon.stub();
|
|
802
899
|
});
|
|
803
900
|
describe('successful', () => {
|
|
804
901
|
beforeEach(() => {
|
|
805
|
-
sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve());
|
|
902
|
+
sandbox.stub(MeetingUtil, 'joinMeeting').returns(Promise.resolve(joinMeetingResult));
|
|
806
903
|
});
|
|
807
904
|
|
|
808
905
|
it('should join the meeting and return promise', async () => {
|
|
809
906
|
const join = meeting.join();
|
|
810
907
|
|
|
811
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
908
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
909
|
+
event: eventType.CALL_INITIATED,
|
|
910
|
+
data: {trigger: trigger.USER_INTERACTION, isRoapCallEnabled: true},
|
|
911
|
+
});
|
|
812
912
|
|
|
813
913
|
assert.exists(join.then);
|
|
814
|
-
await join;
|
|
914
|
+
const result = await join;
|
|
915
|
+
|
|
815
916
|
assert.calledOnce(MeetingUtil.joinMeeting);
|
|
816
917
|
assert.calledOnce(meeting.setLocus);
|
|
918
|
+
assert.equal(result, joinMeetingResult);
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
it('should call updateLLMConnection upon joining if config value is set', async () => {
|
|
922
|
+
meeting.config.enableAutomaticLLM = true;
|
|
923
|
+
meeting.webex.internal.llm.on = sinon.stub();
|
|
924
|
+
meeting.processRelayEvent = sinon.stub();
|
|
925
|
+
await meeting.join();
|
|
926
|
+
|
|
927
|
+
assert.calledOnce(meeting.updateLLMConnection);
|
|
928
|
+
assert.calledOnceWithExactly(meeting.webex.internal.llm.on, 'event:relay.event', meeting.processRelayEvent);
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
it('should not call updateLLMConnection upon joining if config value is not set', async () => {
|
|
932
|
+
meeting.webex.internal.llm.on = sinon.stub();
|
|
933
|
+
await meeting.join();
|
|
934
|
+
|
|
935
|
+
assert.notCalled(meeting.updateLLMConnection);
|
|
936
|
+
assert.notCalled(meeting.webex.internal.llm.on);
|
|
817
937
|
});
|
|
938
|
+
|
|
818
939
|
it('should invoke `receiveTranscription()` if receiveTranscription is set to true', async () => {
|
|
819
940
|
meeting.isTranscriptionSupported = sinon.stub().returns(true);
|
|
820
941
|
meeting.receiveTranscription = sinon.stub().returns(Promise.resolve());
|
|
@@ -856,8 +977,7 @@ describe('plugin-meetings', () => {
|
|
|
856
977
|
try {
|
|
857
978
|
await meeting.join();
|
|
858
979
|
joinSucceeded = true;
|
|
859
|
-
}
|
|
860
|
-
catch (e) {
|
|
980
|
+
} catch (e) {
|
|
861
981
|
assert.instanceOf(e, IntentToJoinError);
|
|
862
982
|
}
|
|
863
983
|
assert.isFalse(joinSucceeded);
|
|
@@ -905,7 +1025,7 @@ describe('plugin-meetings', () => {
|
|
|
905
1025
|
describe('#addMedia', () => {
|
|
906
1026
|
const muteStateStub = {
|
|
907
1027
|
handleClientRequest: sinon.stub().returns(Promise.resolve(true)),
|
|
908
|
-
applyClientStateLocally: sinon.stub().returns(Promise.resolve(true))
|
|
1028
|
+
applyClientStateLocally: sinon.stub().returns(Promise.resolve(true)),
|
|
909
1029
|
};
|
|
910
1030
|
|
|
911
1031
|
let fakeMediaConnection;
|
|
@@ -913,7 +1033,7 @@ describe('plugin-meetings', () => {
|
|
|
913
1033
|
beforeEach(() => {
|
|
914
1034
|
fakeMediaConnection = {
|
|
915
1035
|
close: sinon.stub(),
|
|
916
|
-
getConnectionState: sinon.stub().returns(
|
|
1036
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
917
1037
|
initiateOffer: sinon.stub().resolves({}),
|
|
918
1038
|
on: sinon.stub(),
|
|
919
1039
|
};
|
|
@@ -926,7 +1046,9 @@ describe('plugin-meetings', () => {
|
|
|
926
1046
|
meeting.setMercuryListener = sinon.stub().returns(true);
|
|
927
1047
|
meeting.setupMediaConnectionListeners = sinon.stub();
|
|
928
1048
|
meeting.setMercuryListener = sinon.stub();
|
|
929
|
-
meeting.roap.doTurnDiscovery = sinon
|
|
1049
|
+
meeting.roap.doTurnDiscovery = sinon
|
|
1050
|
+
.stub()
|
|
1051
|
+
.resolves({turnServerInfo: {}, turnDiscoverySkippedReason: undefined});
|
|
930
1052
|
});
|
|
931
1053
|
|
|
932
1054
|
it('should have #addMedia', () => {
|
|
@@ -955,8 +1077,7 @@ describe('plugin-meetings', () => {
|
|
|
955
1077
|
try {
|
|
956
1078
|
await meeting.addMedia();
|
|
957
1079
|
assert.fail('addMedia should have thrown an exception.');
|
|
958
|
-
}
|
|
959
|
-
catch (err) {
|
|
1080
|
+
} catch (err) {
|
|
960
1081
|
assert.instanceOf(err, UserInLobbyError);
|
|
961
1082
|
}
|
|
962
1083
|
});
|
|
@@ -974,37 +1095,33 @@ describe('plugin-meetings', () => {
|
|
|
974
1095
|
|
|
975
1096
|
assert.isNull(meeting.statsAnalyzer);
|
|
976
1097
|
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
977
|
-
assert.calledWith(
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
turnServerUsed: true
|
|
987
|
-
}
|
|
988
|
-
);
|
|
1098
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE, {
|
|
1099
|
+
correlation_id: meeting.correlationId,
|
|
1100
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1101
|
+
reason: error.message,
|
|
1102
|
+
stack: error.stack,
|
|
1103
|
+
code: error.code,
|
|
1104
|
+
turnDiscoverySkippedReason: undefined,
|
|
1105
|
+
turnServerUsed: true,
|
|
1106
|
+
});
|
|
989
1107
|
});
|
|
990
1108
|
|
|
991
1109
|
it('checks metrics called with skipped reason config', async () => {
|
|
992
|
-
meeting.roap.doTurnDiscovery = sinon
|
|
1110
|
+
meeting.roap.doTurnDiscovery = sinon
|
|
1111
|
+
.stub()
|
|
1112
|
+
.resolves({turnServerInfo: undefined, turnDiscoverySkippedReason: 'config'});
|
|
993
1113
|
meeting.meetingState = 'ACTIVE';
|
|
994
1114
|
await meeting.addMedia().catch((err) => {
|
|
995
1115
|
assert.exists(err);
|
|
996
1116
|
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
997
|
-
assert.calledWith(
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
turnServerUsed: false
|
|
1006
|
-
}
|
|
1007
|
-
);
|
|
1117
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE, {
|
|
1118
|
+
correlation_id: meeting.correlationId,
|
|
1119
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1120
|
+
reason: err.message,
|
|
1121
|
+
stack: err.stack,
|
|
1122
|
+
turnDiscoverySkippedReason: 'config',
|
|
1123
|
+
turnServerUsed: false,
|
|
1124
|
+
});
|
|
1008
1125
|
});
|
|
1009
1126
|
});
|
|
1010
1127
|
|
|
@@ -1023,12 +1140,13 @@ describe('plugin-meetings', () => {
|
|
|
1023
1140
|
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
1024
1141
|
assert.calledWith(
|
|
1025
1142
|
Metrics.sendBehavioralMetric,
|
|
1026
|
-
BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE,
|
|
1143
|
+
BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE,
|
|
1144
|
+
sinon.match({
|
|
1027
1145
|
correlation_id: meeting.correlationId,
|
|
1028
1146
|
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1029
1147
|
reason: result.message,
|
|
1030
1148
|
turnDiscoverySkippedReason: undefined,
|
|
1031
|
-
turnServerUsed: true
|
|
1149
|
+
turnServerUsed: true,
|
|
1032
1150
|
})
|
|
1033
1151
|
);
|
|
1034
1152
|
});
|
|
@@ -1049,10 +1167,9 @@ describe('plugin-meetings', () => {
|
|
|
1049
1167
|
|
|
1050
1168
|
try {
|
|
1051
1169
|
await meeting.addMedia({
|
|
1052
|
-
mediaSettings: {}
|
|
1170
|
+
mediaSettings: {},
|
|
1053
1171
|
});
|
|
1054
|
-
}
|
|
1055
|
-
catch (err) {
|
|
1172
|
+
} catch (err) {
|
|
1056
1173
|
assert.fail('should not throw an error');
|
|
1057
1174
|
}
|
|
1058
1175
|
});
|
|
@@ -1092,11 +1209,13 @@ describe('plugin-meetings', () => {
|
|
|
1092
1209
|
});
|
|
1093
1210
|
|
|
1094
1211
|
it('should attach the media and return promise', async () => {
|
|
1095
|
-
meeting.roap.doTurnDiscovery = sinon
|
|
1212
|
+
meeting.roap.doTurnDiscovery = sinon
|
|
1213
|
+
.stub()
|
|
1214
|
+
.resolves({turnServerInfo: undefined, turnDiscoverySkippedReason: undefined});
|
|
1096
1215
|
|
|
1097
1216
|
meeting.meetingState = 'ACTIVE';
|
|
1098
1217
|
const media = meeting.addMedia({
|
|
1099
|
-
mediaSettings: {}
|
|
1218
|
+
mediaSettings: {},
|
|
1100
1219
|
});
|
|
1101
1220
|
|
|
1102
1221
|
assert.exists(media);
|
|
@@ -1105,12 +1224,17 @@ describe('plugin-meetings', () => {
|
|
|
1105
1224
|
assert.calledWith(meeting.roap.doTurnDiscovery, meeting, false);
|
|
1106
1225
|
assert.calledOnce(meeting.mediaProperties.setMediaDirection);
|
|
1107
1226
|
assert.calledOnce(Media.createMediaConnection);
|
|
1108
|
-
assert.calledWith(
|
|
1227
|
+
assert.calledWith(
|
|
1228
|
+
Media.createMediaConnection,
|
|
1229
|
+
false,
|
|
1230
|
+
meeting.getMediaConnectionDebugId(),
|
|
1231
|
+
sinon.match({turnServerInfo: undefined})
|
|
1232
|
+
);
|
|
1109
1233
|
assert.calledOnce(meeting.setMercuryListener);
|
|
1110
1234
|
assert.calledOnce(fakeMediaConnection.initiateOffer);
|
|
1111
1235
|
/* statsAnalyzer is initiated inside of addMedia so there isn't
|
|
1112
|
-
|
|
1113
|
-
|
|
1236
|
+
* a good way to mock it without mocking the constructor
|
|
1237
|
+
*/
|
|
1114
1238
|
});
|
|
1115
1239
|
|
|
1116
1240
|
it('should pass the turn server info to the peer connection', async () => {
|
|
@@ -1121,17 +1245,16 @@ describe('plugin-meetings', () => {
|
|
|
1121
1245
|
meeting.meetingState = 'ACTIVE';
|
|
1122
1246
|
Media.createMediaConnection.resetHistory();
|
|
1123
1247
|
|
|
1124
|
-
|
|
1125
1248
|
meeting.roap.doTurnDiscovery = sinon.stub().resolves({
|
|
1126
1249
|
turnServerInfo: {
|
|
1127
1250
|
url: FAKE_TURN_URL,
|
|
1128
1251
|
username: FAKE_TURN_USER,
|
|
1129
|
-
password: FAKE_TURN_PASSWORD
|
|
1252
|
+
password: FAKE_TURN_PASSWORD,
|
|
1130
1253
|
},
|
|
1131
|
-
turnServerSkippedReason: undefined
|
|
1254
|
+
turnServerSkippedReason: undefined,
|
|
1132
1255
|
});
|
|
1133
1256
|
const media = meeting.addMedia({
|
|
1134
|
-
mediaSettings: {}
|
|
1257
|
+
mediaSettings: {},
|
|
1135
1258
|
});
|
|
1136
1259
|
|
|
1137
1260
|
assert.exists(media);
|
|
@@ -1139,25 +1262,35 @@ describe('plugin-meetings', () => {
|
|
|
1139
1262
|
assert.calledOnce(meeting.roap.doTurnDiscovery);
|
|
1140
1263
|
assert.calledWith(meeting.roap.doTurnDiscovery, meeting, false);
|
|
1141
1264
|
assert.calledOnce(Media.createMediaConnection);
|
|
1142
|
-
assert.calledWith(
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1265
|
+
assert.calledWith(
|
|
1266
|
+
Media.createMediaConnection,
|
|
1267
|
+
false,
|
|
1268
|
+
meeting.getMediaConnectionDebugId(),
|
|
1269
|
+
sinon.match({
|
|
1270
|
+
turnServerInfo: {
|
|
1271
|
+
url: FAKE_TURN_URL,
|
|
1272
|
+
username: FAKE_TURN_USER,
|
|
1273
|
+
password: FAKE_TURN_PASSWORD,
|
|
1274
|
+
},
|
|
1275
|
+
})
|
|
1276
|
+
);
|
|
1149
1277
|
assert.calledOnce(fakeMediaConnection.initiateOffer);
|
|
1150
1278
|
});
|
|
1151
1279
|
|
|
1152
1280
|
it('should attach the media and return WebExMeetingsErrors when connection does not reach CONNECTED state', async () => {
|
|
1153
1281
|
meeting.meetingState = 'ACTIVE';
|
|
1154
|
-
fakeMediaConnection.getConnectionState = sinon
|
|
1282
|
+
fakeMediaConnection.getConnectionState = sinon
|
|
1283
|
+
.stub()
|
|
1284
|
+
.returns(ConnectionState.Connecting);
|
|
1155
1285
|
const clock = sinon.useFakeTimers();
|
|
1156
1286
|
const media = meeting.addMedia({
|
|
1157
|
-
mediaSettings: {}
|
|
1287
|
+
mediaSettings: {},
|
|
1158
1288
|
});
|
|
1159
1289
|
|
|
1160
|
-
await clock.tickAsync(
|
|
1290
|
+
await clock.tickAsync(
|
|
1291
|
+
4000 /* meetingState timer, hardcoded inside addMedia */ +
|
|
1292
|
+
PC_BAIL_TIMEOUT /* connection state timer */
|
|
1293
|
+
);
|
|
1161
1294
|
await testUtils.flushPromises();
|
|
1162
1295
|
|
|
1163
1296
|
assert.exists(media);
|
|
@@ -1174,9 +1307,10 @@ describe('plugin-meetings', () => {
|
|
|
1174
1307
|
|
|
1175
1308
|
let errorThrown = false;
|
|
1176
1309
|
|
|
1177
|
-
await meeting
|
|
1178
|
-
|
|
1179
|
-
|
|
1310
|
+
await meeting
|
|
1311
|
+
.addMedia({
|
|
1312
|
+
mediaSettings: {},
|
|
1313
|
+
})
|
|
1180
1314
|
.catch((error) => {
|
|
1181
1315
|
assert.equal(error.code, IceGatheringFailed.CODE);
|
|
1182
1316
|
errorThrown = true;
|
|
@@ -1188,19 +1322,15 @@ describe('plugin-meetings', () => {
|
|
|
1188
1322
|
it('should send ADD_MEDIA_SUCCESS metrics', async () => {
|
|
1189
1323
|
meeting.meetingState = 'ACTIVE';
|
|
1190
1324
|
await meeting.addMedia({
|
|
1191
|
-
mediaSettings: {}
|
|
1325
|
+
mediaSettings: {},
|
|
1192
1326
|
});
|
|
1193
1327
|
|
|
1194
1328
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
1195
|
-
assert.calledWith(
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1201
|
-
connectionType: 'udp'
|
|
1202
|
-
}
|
|
1203
|
-
);
|
|
1329
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS, {
|
|
1330
|
+
correlation_id: meeting.correlationId,
|
|
1331
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
1332
|
+
connectionType: 'udp',
|
|
1333
|
+
});
|
|
1204
1334
|
});
|
|
1205
1335
|
|
|
1206
1336
|
describe('handles StatsAnalyzer events', () => {
|
|
@@ -1218,7 +1348,7 @@ describe('plugin-meetings', () => {
|
|
|
1218
1348
|
sinon.stub(StatsAnalyzerModule, 'StatsAnalyzer').returns(statsAnalyzerStub);
|
|
1219
1349
|
|
|
1220
1350
|
await meeting.addMedia({
|
|
1221
|
-
mediaSettings: {}
|
|
1351
|
+
mediaSettings: {},
|
|
1222
1352
|
});
|
|
1223
1353
|
});
|
|
1224
1354
|
|
|
@@ -1227,51 +1357,79 @@ describe('plugin-meetings', () => {
|
|
|
1227
1357
|
});
|
|
1228
1358
|
|
|
1229
1359
|
it('LOCAL_MEDIA_STARTED triggers "meeting:media:local:start" event and sends metrics', async () => {
|
|
1230
|
-
statsAnalyzerStub.emit(
|
|
1360
|
+
statsAnalyzerStub.emit(
|
|
1361
|
+
{file: 'test', function: 'test'},
|
|
1362
|
+
StatsAnalyzerModule.EVENTS.LOCAL_MEDIA_STARTED,
|
|
1363
|
+
{type: 'audio'}
|
|
1364
|
+
);
|
|
1231
1365
|
|
|
1232
1366
|
assert.calledWith(
|
|
1233
1367
|
TriggerProxy.trigger,
|
|
1234
1368
|
sinon.match.instanceOf(Meeting),
|
|
1235
1369
|
{
|
|
1236
1370
|
file: 'meeting/index',
|
|
1237
|
-
function: 'addMedia'
|
|
1371
|
+
function: 'addMedia',
|
|
1238
1372
|
},
|
|
1239
1373
|
EVENT_TRIGGERS.MEETING_MEDIA_LOCAL_STARTED,
|
|
1240
1374
|
{
|
|
1241
|
-
type: 'audio'
|
|
1375
|
+
type: 'audio',
|
|
1242
1376
|
}
|
|
1243
1377
|
);
|
|
1244
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
1378
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
1379
|
+
event: eventType.SENDING_MEDIA_START,
|
|
1380
|
+
data: {mediaType: 'audio'},
|
|
1381
|
+
});
|
|
1245
1382
|
});
|
|
1246
1383
|
|
|
1247
1384
|
it('LOCAL_MEDIA_STOPPED triggers the right metrics', async () => {
|
|
1248
|
-
statsAnalyzerStub.emit(
|
|
1385
|
+
statsAnalyzerStub.emit(
|
|
1386
|
+
{file: 'test', function: 'test'},
|
|
1387
|
+
StatsAnalyzerModule.EVENTS.LOCAL_MEDIA_STOPPED,
|
|
1388
|
+
{type: 'video'}
|
|
1389
|
+
);
|
|
1249
1390
|
|
|
1250
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
1391
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
1392
|
+
event: eventType.SENDING_MEDIA_STOP,
|
|
1393
|
+
data: {mediaType: 'video'},
|
|
1394
|
+
});
|
|
1251
1395
|
});
|
|
1252
1396
|
|
|
1253
1397
|
it('REMOTE_MEDIA_STARTED triggers "meeting:media:remote:start" event and sends metrics', async () => {
|
|
1254
|
-
statsAnalyzerStub.emit(
|
|
1398
|
+
statsAnalyzerStub.emit(
|
|
1399
|
+
{file: 'test', function: 'test'},
|
|
1400
|
+
StatsAnalyzerModule.EVENTS.REMOTE_MEDIA_STARTED,
|
|
1401
|
+
{type: 'video'}
|
|
1402
|
+
);
|
|
1255
1403
|
|
|
1256
1404
|
assert.calledWith(
|
|
1257
1405
|
TriggerProxy.trigger,
|
|
1258
1406
|
sinon.match.instanceOf(Meeting),
|
|
1259
1407
|
{
|
|
1260
1408
|
file: 'meeting/index',
|
|
1261
|
-
function: 'addMedia'
|
|
1409
|
+
function: 'addMedia',
|
|
1262
1410
|
},
|
|
1263
1411
|
EVENT_TRIGGERS.MEETING_MEDIA_REMOTE_STARTED,
|
|
1264
1412
|
{
|
|
1265
|
-
type: 'video'
|
|
1413
|
+
type: 'video',
|
|
1266
1414
|
}
|
|
1267
1415
|
);
|
|
1268
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
1416
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
1417
|
+
event: eventType.RECEIVING_MEDIA_START,
|
|
1418
|
+
data: {mediaType: 'video'},
|
|
1419
|
+
});
|
|
1269
1420
|
});
|
|
1270
1421
|
|
|
1271
1422
|
it('REMOTE_MEDIA_STOPPED triggers the right metrics', async () => {
|
|
1272
|
-
statsAnalyzerStub.emit(
|
|
1423
|
+
statsAnalyzerStub.emit(
|
|
1424
|
+
{file: 'test', function: 'test'},
|
|
1425
|
+
StatsAnalyzerModule.EVENTS.REMOTE_MEDIA_STOPPED,
|
|
1426
|
+
{type: 'audio'}
|
|
1427
|
+
);
|
|
1273
1428
|
|
|
1274
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
1429
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
1430
|
+
event: eventType.RECEIVING_MEDIA_STOP,
|
|
1431
|
+
data: {mediaType: 'audio'},
|
|
1432
|
+
});
|
|
1275
1433
|
});
|
|
1276
1434
|
|
|
1277
1435
|
it('MEDIA_QUALITY triggers the right metrics', async () => {
|
|
@@ -1283,7 +1441,10 @@ describe('plugin-meetings', () => {
|
|
|
1283
1441
|
{data: fakeData, networkType: 'wifi'}
|
|
1284
1442
|
);
|
|
1285
1443
|
|
|
1286
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
1444
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
1445
|
+
event: eventType.MEDIA_QUALITY,
|
|
1446
|
+
data: {intervalData: fakeData, networkType: 'wifi'},
|
|
1447
|
+
});
|
|
1287
1448
|
});
|
|
1288
1449
|
});
|
|
1289
1450
|
});
|
|
@@ -1346,7 +1507,9 @@ describe('plugin-meetings', () => {
|
|
|
1346
1507
|
sandbox = sinon.createSandbox();
|
|
1347
1508
|
meeting.meetingFiniteStateMachine.ring();
|
|
1348
1509
|
meeting.meetingFiniteStateMachine.join();
|
|
1349
|
-
meeting.meetingRequest.leaveMeeting = sinon
|
|
1510
|
+
meeting.meetingRequest.leaveMeeting = sinon
|
|
1511
|
+
.stub()
|
|
1512
|
+
.returns(Promise.resolve({body: 'test'}));
|
|
1350
1513
|
meeting.locusInfo.onFullLocus = sinon.stub().returns(true);
|
|
1351
1514
|
// the 3 need to be promises because we do closeLocalStream.then(closeLocalShare.then) etc in the src code
|
|
1352
1515
|
meeting.closeLocalStream = sinon.stub().returns(Promise.resolve());
|
|
@@ -1361,6 +1524,7 @@ describe('plugin-meetings', () => {
|
|
|
1361
1524
|
meeting.unsetRemoteStream = sinon.stub().returns(true);
|
|
1362
1525
|
meeting.unsetPeerConnections = sinon.stub().returns(true);
|
|
1363
1526
|
meeting.logger.error = sinon.stub().returns(true);
|
|
1527
|
+
meeting.updateLLMConnection = sinon.stub().returns(Promise.resolve());
|
|
1364
1528
|
|
|
1365
1529
|
// A meeting needs to be joined to leave
|
|
1366
1530
|
meeting.meetingState = 'ACTIVE';
|
|
@@ -1415,7 +1579,7 @@ describe('plugin-meetings', () => {
|
|
|
1415
1579
|
correlationId: meeting.correlationId,
|
|
1416
1580
|
selfId: meeting.selfId,
|
|
1417
1581
|
resourceId: null,
|
|
1418
|
-
deviceUrl: meeting.deviceUrl
|
|
1582
|
+
deviceUrl: meeting.deviceUrl,
|
|
1419
1583
|
});
|
|
1420
1584
|
});
|
|
1421
1585
|
it('should leave the meeting on the resource', async () => {
|
|
@@ -1428,13 +1592,13 @@ describe('plugin-meetings', () => {
|
|
|
1428
1592
|
correlationId: meeting.correlationId,
|
|
1429
1593
|
selfId: meeting.selfId,
|
|
1430
1594
|
resourceId: meeting.resourceId,
|
|
1431
|
-
deviceUrl: meeting.deviceUrl
|
|
1595
|
+
deviceUrl: meeting.deviceUrl,
|
|
1432
1596
|
});
|
|
1433
1597
|
});
|
|
1434
1598
|
});
|
|
1435
|
-
describe('#
|
|
1436
|
-
it('should have #
|
|
1437
|
-
assert.exists(meeting.
|
|
1599
|
+
describe('#requestScreenShareFloor', () => {
|
|
1600
|
+
it('should have #requestScreenShareFloor', () => {
|
|
1601
|
+
assert.exists(meeting.requestScreenShareFloor);
|
|
1438
1602
|
});
|
|
1439
1603
|
beforeEach(() => {
|
|
1440
1604
|
meeting.locusInfo.mediaShares = [{name: 'content', url: url1}];
|
|
@@ -1442,7 +1606,7 @@ describe('plugin-meetings', () => {
|
|
|
1442
1606
|
meeting.meetingRequest.changeMeetingFloor = sinon.stub().returns(Promise.resolve());
|
|
1443
1607
|
});
|
|
1444
1608
|
it('should send the share', async () => {
|
|
1445
|
-
const share = meeting.
|
|
1609
|
+
const share = meeting.requestScreenShareFloor();
|
|
1446
1610
|
|
|
1447
1611
|
assert.exists(share.then);
|
|
1448
1612
|
await share;
|
|
@@ -1455,7 +1619,9 @@ describe('plugin-meetings', () => {
|
|
|
1455
1619
|
|
|
1456
1620
|
beforeEach(() => {
|
|
1457
1621
|
_mediaDirection = meeting.mediaProperties.mediaDirection || {};
|
|
1458
|
-
sinon
|
|
1622
|
+
sinon
|
|
1623
|
+
.stub(meeting.mediaProperties, 'mediaDirection')
|
|
1624
|
+
.value({sendAudio: true, sendVideo: true, sendShare: false});
|
|
1459
1625
|
});
|
|
1460
1626
|
|
|
1461
1627
|
afterEach(() => {
|
|
@@ -1492,7 +1658,11 @@ describe('plugin-meetings', () => {
|
|
|
1492
1658
|
it('properly assigns default values', async () => {
|
|
1493
1659
|
await meeting.shareScreen({sharePreferences: {highFrameRate: true}});
|
|
1494
1660
|
|
|
1495
|
-
assert.calledWith(Media.getDisplayMedia, {
|
|
1661
|
+
assert.calledWith(Media.getDisplayMedia, {
|
|
1662
|
+
sendShare: true,
|
|
1663
|
+
sendAudio: false,
|
|
1664
|
+
sharePreferences: {highFrameRate: true},
|
|
1665
|
+
});
|
|
1496
1666
|
});
|
|
1497
1667
|
});
|
|
1498
1668
|
|
|
@@ -1522,18 +1692,21 @@ describe('plugin-meetings', () => {
|
|
|
1522
1692
|
sendShare,
|
|
1523
1693
|
receiveShare,
|
|
1524
1694
|
stream,
|
|
1525
|
-
skipSignalingCheck: true
|
|
1695
|
+
skipSignalingCheck: true,
|
|
1526
1696
|
});
|
|
1527
1697
|
|
|
1528
1698
|
assert.notCalled(meeting.canUpdateMedia);
|
|
1529
1699
|
});
|
|
1530
1700
|
|
|
1531
|
-
|
|
1532
1701
|
it('skips canUpdateMedia() check on contentTracks.onended', () => {
|
|
1533
1702
|
const {mediaProperties} = meeting;
|
|
1703
|
+
let registeredListener = null;
|
|
1534
1704
|
const fakeTrack = {
|
|
1535
1705
|
getSettings: sinon.stub().returns({}),
|
|
1536
|
-
onended: sinon.stub()
|
|
1706
|
+
onended: sinon.stub(),
|
|
1707
|
+
addEventListener: sinon.stub().callsFake((event, listener) => {
|
|
1708
|
+
registeredListener = listener;
|
|
1709
|
+
}),
|
|
1537
1710
|
};
|
|
1538
1711
|
|
|
1539
1712
|
sandbox.stub(mediaProperties, 'setLocalShareTrack');
|
|
@@ -1542,17 +1715,20 @@ describe('plugin-meetings', () => {
|
|
|
1542
1715
|
sandbox.stub(meeting, 'stopShare').resolves(true);
|
|
1543
1716
|
meeting.setLocalShareTrack(fakeTrack);
|
|
1544
1717
|
|
|
1545
|
-
fakeTrack.
|
|
1718
|
+
assert.calledOnce(fakeTrack.addEventListener);
|
|
1719
|
+
assert.calledWith(fakeTrack.addEventListener, 'ended', sinon.match.any);
|
|
1720
|
+
assert.isNotNull(registeredListener);
|
|
1721
|
+
|
|
1722
|
+
registeredListener();
|
|
1546
1723
|
|
|
1547
1724
|
assert.calledWith(meeting.stopShare, {skipSignalingCheck: true});
|
|
1548
1725
|
});
|
|
1549
1726
|
|
|
1550
|
-
|
|
1551
1727
|
it('stopShare accepts and passes along optional parameters', () => {
|
|
1552
1728
|
const args = {
|
|
1553
1729
|
abc: 123,
|
|
1554
1730
|
receiveShare: false,
|
|
1555
|
-
sendShare: false
|
|
1731
|
+
sendShare: false,
|
|
1556
1732
|
};
|
|
1557
1733
|
|
|
1558
1734
|
sandbox.stub(meeting, 'updateShare').returns(Promise.resolve());
|
|
@@ -1577,24 +1753,22 @@ describe('plugin-meetings', () => {
|
|
|
1577
1753
|
});
|
|
1578
1754
|
|
|
1579
1755
|
it('handleShareTrackEnded triggers an event', () => {
|
|
1580
|
-
const stream = 'stream';
|
|
1581
1756
|
const {EVENT_TYPES} = CONSTANTS;
|
|
1582
1757
|
|
|
1583
1758
|
sandbox.stub(meeting, 'stopShare').resolves(true);
|
|
1584
1759
|
|
|
1585
|
-
meeting.handleShareTrackEnded(
|
|
1760
|
+
meeting.handleShareTrackEnded();
|
|
1586
1761
|
|
|
1587
1762
|
assert.calledWith(
|
|
1588
1763
|
TriggerProxy.trigger,
|
|
1589
1764
|
sinon.match.instanceOf(Meeting),
|
|
1590
1765
|
{
|
|
1591
1766
|
file: 'meeting/index',
|
|
1592
|
-
function: 'handleShareTrackEnded'
|
|
1767
|
+
function: 'handleShareTrackEnded',
|
|
1593
1768
|
},
|
|
1594
1769
|
EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
1595
1770
|
{
|
|
1596
|
-
|
|
1597
|
-
type: EVENT_TYPES.LOCAL_SHARE
|
|
1771
|
+
type: EVENT_TYPES.LOCAL_SHARE,
|
|
1598
1772
|
}
|
|
1599
1773
|
);
|
|
1600
1774
|
});
|
|
@@ -1607,20 +1781,22 @@ describe('plugin-meetings', () => {
|
|
|
1607
1781
|
const {resolution} = config;
|
|
1608
1782
|
const shareOptions = {
|
|
1609
1783
|
sendShare: true,
|
|
1610
|
-
sendAudio: false
|
|
1784
|
+
sendAudio: false,
|
|
1611
1785
|
};
|
|
1612
1786
|
const fireFoxOptions = {
|
|
1613
1787
|
audio: false,
|
|
1614
1788
|
video: {
|
|
1615
1789
|
audio: shareOptions.sendAudio,
|
|
1616
|
-
video: shareOptions.sendShare
|
|
1617
|
-
}
|
|
1790
|
+
video: shareOptions.sendShare,
|
|
1791
|
+
},
|
|
1618
1792
|
};
|
|
1619
1793
|
|
|
1620
1794
|
const MediaStream = {
|
|
1621
|
-
getVideoTracks: () => [
|
|
1622
|
-
|
|
1623
|
-
|
|
1795
|
+
getVideoTracks: () => [
|
|
1796
|
+
{
|
|
1797
|
+
applyConstraints: () => {},
|
|
1798
|
+
},
|
|
1799
|
+
],
|
|
1624
1800
|
};
|
|
1625
1801
|
|
|
1626
1802
|
const MediaConstraint = {
|
|
@@ -1628,7 +1804,7 @@ describe('plugin-meetings', () => {
|
|
|
1628
1804
|
aspectRatio: config.aspectRatio,
|
|
1629
1805
|
frameRate: config.screenFrameRate,
|
|
1630
1806
|
width: null,
|
|
1631
|
-
height: null
|
|
1807
|
+
height: null,
|
|
1632
1808
|
};
|
|
1633
1809
|
|
|
1634
1810
|
const browserConditionalValue = (value) => {
|
|
@@ -1644,31 +1820,23 @@ describe('plugin-meetings', () => {
|
|
|
1644
1820
|
if (!global.navigator) {
|
|
1645
1821
|
global.navigator = {
|
|
1646
1822
|
mediaDevices: {
|
|
1647
|
-
getDisplayMedia: null
|
|
1648
|
-
}
|
|
1823
|
+
getDisplayMedia: null,
|
|
1824
|
+
},
|
|
1649
1825
|
};
|
|
1650
1826
|
}
|
|
1651
1827
|
_getDisplayMedia = global.navigator.mediaDevices.getDisplayMedia;
|
|
1652
|
-
Object.defineProperty(
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
value: sinon.stub().returns(Promise.resolve(MediaStream)),
|
|
1657
|
-
writable: true
|
|
1658
|
-
}
|
|
1659
|
-
);
|
|
1828
|
+
Object.defineProperty(global.navigator.mediaDevices, 'getDisplayMedia', {
|
|
1829
|
+
value: sinon.stub().returns(Promise.resolve(MediaStream)),
|
|
1830
|
+
writable: true,
|
|
1831
|
+
});
|
|
1660
1832
|
});
|
|
1661
1833
|
|
|
1662
1834
|
after(() => {
|
|
1663
1835
|
// clean up for browser
|
|
1664
|
-
Object.defineProperty(
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
value: _getDisplayMedia,
|
|
1669
|
-
writable: true
|
|
1670
|
-
}
|
|
1671
|
-
);
|
|
1836
|
+
Object.defineProperty(global.navigator.mediaDevices, 'getDisplayMedia', {
|
|
1837
|
+
value: _getDisplayMedia,
|
|
1838
|
+
writable: true,
|
|
1839
|
+
});
|
|
1672
1840
|
});
|
|
1673
1841
|
|
|
1674
1842
|
// eslint-disable-next-line max-len
|
|
@@ -1680,39 +1848,48 @@ describe('plugin-meetings', () => {
|
|
|
1680
1848
|
maxWidth: SHARE_WIDTH,
|
|
1681
1849
|
maxHeight: SHARE_HEIGHT,
|
|
1682
1850
|
idealWidth: SHARE_WIDTH,
|
|
1683
|
-
idealHeight: SHARE_HEIGHT
|
|
1851
|
+
idealHeight: SHARE_HEIGHT,
|
|
1684
1852
|
};
|
|
1685
1853
|
|
|
1686
1854
|
// If sharePreferences.shareConstraints is defined it ignores
|
|
1687
1855
|
// default SDK config settings
|
|
1688
|
-
getDisplayMedia(
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1856
|
+
getDisplayMedia(
|
|
1857
|
+
{
|
|
1858
|
+
...shareOptions,
|
|
1859
|
+
sharePreferences: {shareConstraints},
|
|
1860
|
+
},
|
|
1861
|
+
config
|
|
1862
|
+
);
|
|
1692
1863
|
|
|
1693
1864
|
// eslint-disable-next-line no-undef
|
|
1694
|
-
assert.calledWith(
|
|
1865
|
+
assert.calledWith(
|
|
1866
|
+
navigator.mediaDevices.getDisplayMedia,
|
|
1695
1867
|
browserConditionalValue({
|
|
1696
1868
|
default: {
|
|
1697
|
-
video: {...shareConstraints}
|
|
1869
|
+
video: {...shareConstraints},
|
|
1698
1870
|
},
|
|
1699
1871
|
// Firefox is being handled differently
|
|
1700
|
-
firefox: fireFoxOptions
|
|
1701
|
-
})
|
|
1872
|
+
firefox: fireFoxOptions,
|
|
1873
|
+
})
|
|
1874
|
+
);
|
|
1702
1875
|
});
|
|
1703
1876
|
|
|
1704
1877
|
// eslint-disable-next-line max-len
|
|
1705
1878
|
it('will use default resolution if shareConstraints is undefined and highFrameRate is defined', () => {
|
|
1706
1879
|
// If highFrameRate is defined it ignores default SDK config settings
|
|
1707
|
-
getDisplayMedia(
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1880
|
+
getDisplayMedia(
|
|
1881
|
+
{
|
|
1882
|
+
...shareOptions,
|
|
1883
|
+
sharePreferences: {
|
|
1884
|
+
highFrameRate: true,
|
|
1885
|
+
},
|
|
1886
|
+
},
|
|
1887
|
+
config
|
|
1888
|
+
);
|
|
1713
1889
|
|
|
1714
1890
|
// eslint-disable-next-line no-undef
|
|
1715
|
-
assert.calledWith(
|
|
1891
|
+
assert.calledWith(
|
|
1892
|
+
navigator.mediaDevices.getDisplayMedia,
|
|
1716
1893
|
browserConditionalValue({
|
|
1717
1894
|
default: {
|
|
1718
1895
|
video: {
|
|
@@ -1723,11 +1900,12 @@ describe('plugin-meetings', () => {
|
|
|
1723
1900
|
maxWidth: resolution.maxWidth,
|
|
1724
1901
|
maxHeight: resolution.maxHeight,
|
|
1725
1902
|
idealWidth: resolution.idealWidth,
|
|
1726
|
-
idealHeight: resolution.idealHeight
|
|
1727
|
-
}
|
|
1903
|
+
idealHeight: resolution.idealHeight,
|
|
1904
|
+
},
|
|
1728
1905
|
},
|
|
1729
|
-
firefox: fireFoxOptions
|
|
1730
|
-
})
|
|
1906
|
+
firefox: fireFoxOptions,
|
|
1907
|
+
})
|
|
1908
|
+
);
|
|
1731
1909
|
});
|
|
1732
1910
|
|
|
1733
1911
|
// eslint-disable-next-line max-len
|
|
@@ -1736,17 +1914,19 @@ describe('plugin-meetings', () => {
|
|
|
1736
1914
|
const {screenResolution} = config;
|
|
1737
1915
|
|
|
1738
1916
|
// eslint-disable-next-line no-undef
|
|
1739
|
-
assert.calledWith(
|
|
1917
|
+
assert.calledWith(
|
|
1918
|
+
navigator.mediaDevices.getDisplayMedia,
|
|
1740
1919
|
browserConditionalValue({
|
|
1741
1920
|
default: {
|
|
1742
1921
|
video: {
|
|
1743
1922
|
...MediaConstraint,
|
|
1744
1923
|
width: screenResolution.idealWidth,
|
|
1745
|
-
height: screenResolution.idealHeight
|
|
1746
|
-
}
|
|
1924
|
+
height: screenResolution.idealHeight,
|
|
1925
|
+
},
|
|
1747
1926
|
},
|
|
1748
|
-
firefox: fireFoxOptions
|
|
1749
|
-
})
|
|
1927
|
+
firefox: fireFoxOptions,
|
|
1928
|
+
})
|
|
1929
|
+
);
|
|
1750
1930
|
});
|
|
1751
1931
|
|
|
1752
1932
|
// Test screenResolution
|
|
@@ -1759,14 +1939,15 @@ describe('plugin-meetings', () => {
|
|
|
1759
1939
|
maxWidth: SHARE_WIDTH,
|
|
1760
1940
|
maxHeight: SHARE_HEIGHT,
|
|
1761
1941
|
idealWidth: SHARE_WIDTH,
|
|
1762
|
-
idealHeight: SHARE_HEIGHT
|
|
1763
|
-
}
|
|
1942
|
+
idealHeight: SHARE_HEIGHT,
|
|
1943
|
+
},
|
|
1764
1944
|
};
|
|
1765
1945
|
|
|
1766
1946
|
getDisplayMedia(shareOptions, customConfig);
|
|
1767
1947
|
|
|
1768
1948
|
// eslint-disable-next-line no-undef
|
|
1769
|
-
assert.calledWith(
|
|
1949
|
+
assert.calledWith(
|
|
1950
|
+
navigator.mediaDevices.getDisplayMedia,
|
|
1770
1951
|
browserConditionalValue({
|
|
1771
1952
|
default: {
|
|
1772
1953
|
video: {
|
|
@@ -1776,11 +1957,12 @@ describe('plugin-meetings', () => {
|
|
|
1776
1957
|
maxWidth: SHARE_WIDTH,
|
|
1777
1958
|
maxHeight: SHARE_HEIGHT,
|
|
1778
1959
|
idealWidth: SHARE_WIDTH,
|
|
1779
|
-
idealHeight: SHARE_HEIGHT
|
|
1780
|
-
}
|
|
1960
|
+
idealHeight: SHARE_HEIGHT,
|
|
1961
|
+
},
|
|
1781
1962
|
},
|
|
1782
|
-
firefox: fireFoxOptions
|
|
1783
|
-
})
|
|
1963
|
+
firefox: fireFoxOptions,
|
|
1964
|
+
})
|
|
1965
|
+
);
|
|
1784
1966
|
});
|
|
1785
1967
|
|
|
1786
1968
|
// Test screenFrameRate
|
|
@@ -1793,14 +1975,15 @@ describe('plugin-meetings', () => {
|
|
|
1793
1975
|
maxWidth: SHARE_WIDTH,
|
|
1794
1976
|
maxHeight: SHARE_HEIGHT,
|
|
1795
1977
|
idealWidth: SHARE_WIDTH,
|
|
1796
|
-
idealHeight: SHARE_HEIGHT
|
|
1797
|
-
}
|
|
1978
|
+
idealHeight: SHARE_HEIGHT,
|
|
1979
|
+
},
|
|
1798
1980
|
};
|
|
1799
1981
|
|
|
1800
1982
|
getDisplayMedia(shareOptions, customConfig);
|
|
1801
1983
|
|
|
1802
1984
|
// eslint-disable-next-line no-undef
|
|
1803
|
-
assert.calledWith(
|
|
1985
|
+
assert.calledWith(
|
|
1986
|
+
navigator.mediaDevices.getDisplayMedia,
|
|
1804
1987
|
browserConditionalValue({
|
|
1805
1988
|
default: {
|
|
1806
1989
|
video: {
|
|
@@ -1811,11 +1994,12 @@ describe('plugin-meetings', () => {
|
|
|
1811
1994
|
maxWidth: SHARE_WIDTH,
|
|
1812
1995
|
maxHeight: SHARE_HEIGHT,
|
|
1813
1996
|
idealWidth: SHARE_WIDTH,
|
|
1814
|
-
idealHeight: SHARE_HEIGHT
|
|
1815
|
-
}
|
|
1997
|
+
idealHeight: SHARE_HEIGHT,
|
|
1998
|
+
},
|
|
1816
1999
|
},
|
|
1817
|
-
firefox: fireFoxOptions
|
|
1818
|
-
})
|
|
2000
|
+
firefox: fireFoxOptions,
|
|
2001
|
+
})
|
|
2002
|
+
);
|
|
1819
2003
|
});
|
|
1820
2004
|
});
|
|
1821
2005
|
|
|
@@ -1857,22 +2041,35 @@ describe('plugin-meetings', () => {
|
|
|
1857
2041
|
receiveVideo: true,
|
|
1858
2042
|
receiveShare: true,
|
|
1859
2043
|
};
|
|
1860
|
-
meeting.mediaProperties.webrtcMediaConnection = {
|
|
2044
|
+
meeting.mediaProperties.webrtcMediaConnection = {
|
|
2045
|
+
updateSendReceiveOptions: sinon.stub(),
|
|
2046
|
+
};
|
|
1861
2047
|
sinon.stub(MeetingUtil, 'getTrack').returns({audioTrack: FAKE_AUDIO_TRACK});
|
|
1862
2048
|
});
|
|
1863
|
-
it('calls this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions', () =>
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
2049
|
+
it('calls this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions', () =>
|
|
2050
|
+
meeting
|
|
2051
|
+
.updateAudio({
|
|
2052
|
+
sendAudio: true,
|
|
2053
|
+
receiveAudio: true,
|
|
2054
|
+
stream: {id: 'fake stream'},
|
|
2055
|
+
})
|
|
2056
|
+
.then(() => {
|
|
2057
|
+
assert.calledOnce(
|
|
2058
|
+
meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions
|
|
2059
|
+
);
|
|
2060
|
+
assert.calledWith(
|
|
2061
|
+
meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions,
|
|
2062
|
+
{
|
|
2063
|
+
send: {audio: FAKE_AUDIO_TRACK},
|
|
2064
|
+
receive: {
|
|
2065
|
+
audio: true,
|
|
2066
|
+
video: true,
|
|
2067
|
+
screenShareVideo: true,
|
|
2068
|
+
remoteQualityLevel: 'HIGH',
|
|
2069
|
+
},
|
|
2070
|
+
}
|
|
2071
|
+
);
|
|
2072
|
+
}));
|
|
1876
2073
|
});
|
|
1877
2074
|
afterEach(() => {
|
|
1878
2075
|
sinon.restore();
|
|
@@ -1892,7 +2089,7 @@ describe('plugin-meetings', () => {
|
|
|
1892
2089
|
|
|
1893
2090
|
meeting.locusInfo.self = {
|
|
1894
2091
|
enableDTMF: true,
|
|
1895
|
-
url: url2
|
|
2092
|
+
url: url2,
|
|
1896
2093
|
};
|
|
1897
2094
|
|
|
1898
2095
|
await meeting.sendDTMF(tones);
|
|
@@ -1900,7 +2097,7 @@ describe('plugin-meetings', () => {
|
|
|
1900
2097
|
assert.calledWith(meeting.meetingRequest.sendDTMF, {
|
|
1901
2098
|
locusUrl: meeting.locusInfo.self.url,
|
|
1902
2099
|
deviceUrl: meeting.deviceUrl,
|
|
1903
|
-
tones
|
|
2100
|
+
tones,
|
|
1904
2101
|
});
|
|
1905
2102
|
});
|
|
1906
2103
|
|
|
@@ -1914,7 +2111,7 @@ describe('plugin-meetings', () => {
|
|
|
1914
2111
|
it('should throw an error', () => {
|
|
1915
2112
|
meeting.locusInfo.self = {
|
|
1916
2113
|
enableDTMF: false,
|
|
1917
|
-
url: url2
|
|
2114
|
+
url: url2,
|
|
1918
2115
|
};
|
|
1919
2116
|
|
|
1920
2117
|
assert.isRejected(meeting.sendDTMF('123'));
|
|
@@ -1938,8 +2135,8 @@ describe('plugin-meetings', () => {
|
|
|
1938
2135
|
screenshareVideo: {
|
|
1939
2136
|
id: 'fake share track',
|
|
1940
2137
|
getSettings: sinon.stub().returns({}),
|
|
2138
|
+
addEventListener: sinon.stub()
|
|
1941
2139
|
},
|
|
1942
|
-
|
|
1943
2140
|
};
|
|
1944
2141
|
|
|
1945
2142
|
beforeEach(() => {
|
|
@@ -1971,21 +2168,22 @@ describe('plugin-meetings', () => {
|
|
|
1971
2168
|
receiveVideo: true,
|
|
1972
2169
|
sendShare: true,
|
|
1973
2170
|
receiveShare: true,
|
|
1974
|
-
isSharing: true
|
|
2171
|
+
isSharing: true,
|
|
1975
2172
|
};
|
|
1976
2173
|
|
|
1977
2174
|
sandbox.stub(meeting, 'canUpdateMedia').returns(false);
|
|
1978
2175
|
meeting.mediaProperties.webrtcMediaConnection = {
|
|
1979
|
-
updateSendReceiveOptions: sinon.stub().resolves({})
|
|
2176
|
+
updateSendReceiveOptions: sinon.stub().resolves({}),
|
|
1980
2177
|
};
|
|
1981
2178
|
|
|
1982
2179
|
let myPromiseResolved = false;
|
|
1983
2180
|
|
|
1984
|
-
meeting
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
2181
|
+
meeting
|
|
2182
|
+
.updateMedia({
|
|
2183
|
+
localStream: mockLocalStream,
|
|
2184
|
+
localShare: mockLocalShare,
|
|
2185
|
+
mediaSettings,
|
|
2186
|
+
})
|
|
1989
2187
|
.then(() => {
|
|
1990
2188
|
myPromiseResolved = true;
|
|
1991
2189
|
});
|
|
@@ -2002,63 +2200,255 @@ describe('plugin-meetings', () => {
|
|
|
2002
2200
|
|
|
2003
2201
|
// and check that updateSendReceiveOptions is called with the original args
|
|
2004
2202
|
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
|
|
2005
|
-
assert.calledWith(
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2203
|
+
assert.calledWith(
|
|
2204
|
+
meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions,
|
|
2205
|
+
{
|
|
2206
|
+
send: {
|
|
2207
|
+
audio: FAKE_TRACKS.audio,
|
|
2208
|
+
video: FAKE_TRACKS.video,
|
|
2209
|
+
screenShareVideo: FAKE_TRACKS.screenshareVideo,
|
|
2210
|
+
},
|
|
2211
|
+
receive: {
|
|
2212
|
+
audio: true,
|
|
2213
|
+
video: true,
|
|
2214
|
+
screenShareVideo: true,
|
|
2215
|
+
remoteQualityLevel: 'HIGH',
|
|
2216
|
+
},
|
|
2016
2217
|
}
|
|
2017
|
-
|
|
2218
|
+
);
|
|
2018
2219
|
assert.isTrue(myPromiseResolved);
|
|
2019
2220
|
});
|
|
2020
|
-
});
|
|
2021
2221
|
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
let mediaDirection;
|
|
2025
|
-
const layoutTypeSingle = 'Single';
|
|
2222
|
+
it('should request floor only after roap transaction is completed', async () => {
|
|
2223
|
+
const eventListeners = {};
|
|
2026
2224
|
|
|
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'});
|
|
2225
|
+
meeting.webex.meetings.reachability = {
|
|
2226
|
+
isAnyClusterReachable: sandbox.stub().resolves(true)
|
|
2227
|
+
};
|
|
2038
2228
|
|
|
2039
|
-
|
|
2229
|
+
const fakeMediaConnection = {
|
|
2230
|
+
close: sinon.stub(),
|
|
2231
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
2232
|
+
initiateOffer: sinon.stub().resolves({}),
|
|
2040
2233
|
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2234
|
+
// mock the on() method and store all the listeners
|
|
2235
|
+
on: sinon.stub().callsFake((event, listener) => {
|
|
2236
|
+
eventListeners[event] = listener;
|
|
2237
|
+
}),
|
|
2238
|
+
|
|
2239
|
+
updateSendReceiveOptions: sinon.stub().callsFake(() => {
|
|
2240
|
+
// trigger ROAP_STARTED before updateSendReceiveOptions() resolves
|
|
2241
|
+
if (eventListeners[Event.ROAP_STARTED]) {
|
|
2242
|
+
eventListeners[Event.ROAP_STARTED]();
|
|
2243
|
+
} else {
|
|
2244
|
+
throw new Error('ROAP_STARTED listener not registered')
|
|
2245
|
+
}
|
|
2246
|
+
return Promise.resolve();
|
|
2247
|
+
}),
|
|
2248
|
+
};
|
|
2045
2249
|
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2250
|
+
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
|
|
2251
|
+
meeting.mediaProperties.getCurrentConnectionType = sinon.stub().resolves('udp');
|
|
2252
|
+
Media.createMediaConnection = sinon.stub().returns(fakeMediaConnection);
|
|
2049
2253
|
|
|
2050
|
-
|
|
2254
|
+
const requestScreenShareFloorStub = sandbox.stub(meeting, 'requestScreenShareFloor').resolves({});
|
|
2051
2255
|
|
|
2052
|
-
|
|
2053
|
-
});
|
|
2256
|
+
let myPromiseResolved = false;
|
|
2054
2257
|
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2258
|
+
meeting.meetingState = 'ACTIVE';
|
|
2259
|
+
await meeting.addMedia({
|
|
2260
|
+
mediaSettings: {},
|
|
2058
2261
|
});
|
|
2059
2262
|
|
|
2060
|
-
|
|
2061
|
-
|
|
2263
|
+
meeting
|
|
2264
|
+
.updateMedia({
|
|
2265
|
+
localShare: mockLocalShare,
|
|
2266
|
+
mediaSettings: {
|
|
2267
|
+
sendShare: true,
|
|
2268
|
+
},
|
|
2269
|
+
})
|
|
2270
|
+
.then(() => {
|
|
2271
|
+
myPromiseResolved = true;
|
|
2272
|
+
});
|
|
2273
|
+
|
|
2274
|
+
await testUtils.flushPromises();
|
|
2275
|
+
|
|
2276
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
|
|
2277
|
+
assert.isFalse(myPromiseResolved);
|
|
2278
|
+
|
|
2279
|
+
// verify that requestScreenShareFloorStub was not called yet
|
|
2280
|
+
assert.notCalled(requestScreenShareFloorStub);
|
|
2281
|
+
|
|
2282
|
+
eventListeners[Event.ROAP_DONE]();
|
|
2283
|
+
await testUtils.flushPromises();
|
|
2284
|
+
|
|
2285
|
+
// now it should have been called
|
|
2286
|
+
assert.calledOnce(requestScreenShareFloorStub);
|
|
2287
|
+
});
|
|
2288
|
+
});
|
|
2289
|
+
|
|
2290
|
+
describe('#updateShare', () => {
|
|
2291
|
+
const mockLocalShare = {id: 'mock local share stream'};
|
|
2292
|
+
let eventListeners;
|
|
2293
|
+
let fakeMediaConnection;
|
|
2294
|
+
let requestScreenShareFloorStub;
|
|
2295
|
+
|
|
2296
|
+
const FAKE_TRACKS = {
|
|
2297
|
+
screenshareVideo: {
|
|
2298
|
+
id: 'fake share track',
|
|
2299
|
+
getSettings: sinon.stub().returns({}),
|
|
2300
|
+
addEventListener: sinon.stub(),
|
|
2301
|
+
},
|
|
2302
|
+
};
|
|
2303
|
+
|
|
2304
|
+
beforeEach(async () => {
|
|
2305
|
+
eventListeners = {};
|
|
2306
|
+
|
|
2307
|
+
sinon.stub(MeetingUtil, 'getTrack').callsFake((stream) => {
|
|
2308
|
+
if (stream === mockLocalShare) {
|
|
2309
|
+
return {audioTrack: null, videoTrack: FAKE_TRACKS.screenshareVideo};
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
return {audioTrack: null, videoTrack: null};
|
|
2313
|
+
});
|
|
2314
|
+
|
|
2315
|
+
meeting.webex.meetings.reachability = {
|
|
2316
|
+
isAnyClusterReachable: sinon.stub().resolves(true)
|
|
2317
|
+
};
|
|
2318
|
+
|
|
2319
|
+
fakeMediaConnection = {
|
|
2320
|
+
close: sinon.stub(),
|
|
2321
|
+
getConnectionState: sinon.stub().returns(ConnectionState.Connected),
|
|
2322
|
+
initiateOffer: sinon.stub().resolves({}),
|
|
2323
|
+
|
|
2324
|
+
// mock the on() method and store all the listeners
|
|
2325
|
+
on: sinon.stub().callsFake((event, listener) => {
|
|
2326
|
+
eventListeners[event] = listener;
|
|
2327
|
+
}),
|
|
2328
|
+
|
|
2329
|
+
updateSendReceiveOptions: sinon.stub().callsFake(() => {
|
|
2330
|
+
// trigger ROAP_STARTED before updateSendReceiveOptions() resolves
|
|
2331
|
+
if (eventListeners[Event.ROAP_STARTED]) {
|
|
2332
|
+
eventListeners[Event.ROAP_STARTED]();
|
|
2333
|
+
} else {
|
|
2334
|
+
throw new Error('ROAP_STARTED listener not registered')
|
|
2335
|
+
}
|
|
2336
|
+
return Promise.resolve();
|
|
2337
|
+
}),
|
|
2338
|
+
};
|
|
2339
|
+
|
|
2340
|
+
meeting.mediaProperties.waitForMediaConnectionConnected = sinon.stub().resolves();
|
|
2341
|
+
meeting.mediaProperties.getCurrentConnectionType = sinon.stub().resolves('udp');
|
|
2342
|
+
Media.createMediaConnection = sinon.stub().returns(fakeMediaConnection);
|
|
2343
|
+
|
|
2344
|
+
requestScreenShareFloorStub = sinon.stub(meeting, 'requestScreenShareFloor').resolves({});
|
|
2345
|
+
|
|
2346
|
+
meeting.meetingState = 'ACTIVE';
|
|
2347
|
+
await meeting.addMedia({
|
|
2348
|
+
mediaSettings: {},
|
|
2349
|
+
});
|
|
2350
|
+
});
|
|
2351
|
+
|
|
2352
|
+
afterEach(() => {
|
|
2353
|
+
sinon.restore();
|
|
2354
|
+
});
|
|
2355
|
+
|
|
2356
|
+
it('when starting share, it should request floor only after roap transaction is completed', async () => {
|
|
2357
|
+
let myPromiseResolved = false;
|
|
2358
|
+
|
|
2359
|
+
meeting
|
|
2360
|
+
.updateShare({
|
|
2361
|
+
sendShare: true,
|
|
2362
|
+
receiveShare: true,
|
|
2363
|
+
stream: mockLocalShare,
|
|
2364
|
+
})
|
|
2365
|
+
.then(() => {
|
|
2366
|
+
myPromiseResolved = true;
|
|
2367
|
+
});
|
|
2368
|
+
|
|
2369
|
+
await testUtils.flushPromises();
|
|
2370
|
+
|
|
2371
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
|
|
2372
|
+
assert.isFalse(myPromiseResolved);
|
|
2373
|
+
|
|
2374
|
+
// verify that requestScreenShareFloorStub was not called yet
|
|
2375
|
+
assert.notCalled(requestScreenShareFloorStub);
|
|
2376
|
+
|
|
2377
|
+
eventListeners[Event.ROAP_DONE]();
|
|
2378
|
+
await testUtils.flushPromises();
|
|
2379
|
+
|
|
2380
|
+
// now it should have been called
|
|
2381
|
+
assert.calledOnce(requestScreenShareFloorStub);
|
|
2382
|
+
});
|
|
2383
|
+
|
|
2384
|
+
it('when changing screen share stream and no roap transaction happening, it requests floor immediately', async () => {
|
|
2385
|
+
let myPromiseResolved = false;
|
|
2386
|
+
|
|
2387
|
+
// simulate a case when no roap transaction is triggered by updateSendReceiveOptions
|
|
2388
|
+
meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions = sinon.stub().resolves({});
|
|
2389
|
+
|
|
2390
|
+
meeting
|
|
2391
|
+
.updateShare({
|
|
2392
|
+
sendShare: true,
|
|
2393
|
+
receiveShare: true,
|
|
2394
|
+
stream: mockLocalShare,
|
|
2395
|
+
})
|
|
2396
|
+
.then(() => {
|
|
2397
|
+
myPromiseResolved = true;
|
|
2398
|
+
});
|
|
2399
|
+
|
|
2400
|
+
await testUtils.flushPromises();
|
|
2401
|
+
|
|
2402
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions);
|
|
2403
|
+
assert.calledOnce(requestScreenShareFloorStub);
|
|
2404
|
+
assert.isTrue(myPromiseResolved);
|
|
2405
|
+
});
|
|
2406
|
+
});
|
|
2407
|
+
|
|
2408
|
+
describe('#changeVideoLayout', () => {
|
|
2409
|
+
describe('when media direction has recieve video and there is remoteStream', () => {
|
|
2410
|
+
let mediaDirection;
|
|
2411
|
+
const layoutTypeSingle = 'Single';
|
|
2412
|
+
|
|
2413
|
+
beforeEach(() => {
|
|
2414
|
+
mediaDirection = {
|
|
2415
|
+
sendAudio: true,
|
|
2416
|
+
sendVideo: true,
|
|
2417
|
+
sendShare: false,
|
|
2418
|
+
receiveVideo: true,
|
|
2419
|
+
};
|
|
2420
|
+
meeting.getMediaStreams = sinon.stub().returns(Promise.resolve([]));
|
|
2421
|
+
meeting.updateVideo = sinon.stub().returns(Promise.resolve());
|
|
2422
|
+
meeting.mediaProperties.mediaDirection = mediaDirection;
|
|
2423
|
+
meeting.mediaProperties.remoteVideoTrack = sinon
|
|
2424
|
+
.stub()
|
|
2425
|
+
.returns({mockTrack: 'mockTrack'});
|
|
2426
|
+
|
|
2427
|
+
meeting.meetingRequest.changeVideoLayoutDebounced = sinon
|
|
2428
|
+
.stub()
|
|
2429
|
+
.returns(Promise.resolve());
|
|
2430
|
+
|
|
2431
|
+
meeting.locusInfo.self = {
|
|
2432
|
+
url: url2,
|
|
2433
|
+
};
|
|
2434
|
+
});
|
|
2435
|
+
|
|
2436
|
+
it('should listen once for CONTROLS_MEETING_LAYOUT_UPDATED', async () => {
|
|
2437
|
+
// const spy = sinon.spy(TriggerProxy, 'trigger');
|
|
2438
|
+
const spy = sinon.spy(meeting.locusInfo, 'once');
|
|
2439
|
+
|
|
2440
|
+
await meeting.changeVideoLayout('Equal');
|
|
2441
|
+
|
|
2442
|
+
assert.calledWith(spy, LOCUSINFO.EVENTS.CONTROLS_MEETING_LAYOUT_UPDATED);
|
|
2443
|
+
});
|
|
2444
|
+
|
|
2445
|
+
it('should have receiveVideo true and remote video track should exist', () => {
|
|
2446
|
+
assert.equal(meeting.mediaProperties.mediaDirection.receiveVideo, true);
|
|
2447
|
+
assert.exists(meeting.mediaProperties.remoteVideoTrack);
|
|
2448
|
+
});
|
|
2449
|
+
|
|
2450
|
+
it('has layoutType which exists in the list of allowed layoutTypes and should call meetingRequest changeVideoLayoutDebounced method', async () => {
|
|
2451
|
+
const layoutType = 'Equal';
|
|
2062
2452
|
|
|
2063
2453
|
await meeting.changeVideoLayout(layoutType);
|
|
2064
2454
|
|
|
@@ -2068,11 +2458,11 @@ describe('plugin-meetings', () => {
|
|
|
2068
2458
|
deviceUrl: meeting.deviceUrl,
|
|
2069
2459
|
layoutType,
|
|
2070
2460
|
main: undefined,
|
|
2071
|
-
content: undefined
|
|
2461
|
+
content: undefined,
|
|
2072
2462
|
});
|
|
2073
2463
|
});
|
|
2074
2464
|
|
|
2075
|
-
it(
|
|
2465
|
+
it("doesn't have layoutType which exists in the list of allowed layoutTypes should throw an error", async () => {
|
|
2076
2466
|
const layoutType = 'Invalid Layout';
|
|
2077
2467
|
|
|
2078
2468
|
assert.isRejected(meeting.changeVideoLayout(layoutType));
|
|
@@ -2086,12 +2476,14 @@ describe('plugin-meetings', () => {
|
|
|
2086
2476
|
deviceUrl: meeting.deviceUrl,
|
|
2087
2477
|
layoutType: undefined,
|
|
2088
2478
|
main: {width: 100, height: 200},
|
|
2089
|
-
content: undefined
|
|
2479
|
+
content: undefined,
|
|
2090
2480
|
});
|
|
2091
2481
|
});
|
|
2092
2482
|
|
|
2093
2483
|
it('throws if trying to send renderInfo for content when not receiving content', async () => {
|
|
2094
|
-
assert.isRejected(
|
|
2484
|
+
assert.isRejected(
|
|
2485
|
+
meeting.changeVideoLayout(layoutTypeSingle, {content: {width: 1280, height: 720}})
|
|
2486
|
+
);
|
|
2095
2487
|
});
|
|
2096
2488
|
|
|
2097
2489
|
it('calls changeVideoLayoutDebounced with renderInfo for main and content', async () => {
|
|
@@ -2103,7 +2495,7 @@ describe('plugin-meetings', () => {
|
|
|
2103
2495
|
deviceUrl: meeting.deviceUrl,
|
|
2104
2496
|
layoutType: layoutTypeSingle,
|
|
2105
2497
|
main: {width: 100, height: 200},
|
|
2106
|
-
content: undefined
|
|
2498
|
+
content: undefined,
|
|
2107
2499
|
});
|
|
2108
2500
|
|
|
2109
2501
|
meeting.mediaProperties.mediaDirection.receiveShare = true;
|
|
@@ -2117,18 +2509,21 @@ describe('plugin-meetings', () => {
|
|
|
2117
2509
|
deviceUrl: meeting.deviceUrl,
|
|
2118
2510
|
layoutType: layoutTypeSingle,
|
|
2119
2511
|
main: {width: 100, height: 200},
|
|
2120
|
-
content: {width: 500, height: 600}
|
|
2512
|
+
content: {width: 500, height: 600},
|
|
2121
2513
|
});
|
|
2122
2514
|
|
|
2123
2515
|
// and now call with both
|
|
2124
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2516
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2517
|
+
main: {width: 300, height: 400},
|
|
2518
|
+
content: {width: 700, height: 800},
|
|
2519
|
+
});
|
|
2125
2520
|
|
|
2126
2521
|
assert.calledWith(meeting.meetingRequest.changeVideoLayoutDebounced, {
|
|
2127
2522
|
locusUrl: meeting.locusInfo.self.url,
|
|
2128
2523
|
deviceUrl: meeting.deviceUrl,
|
|
2129
2524
|
layoutType: layoutTypeSingle,
|
|
2130
2525
|
main: {width: 300, height: 400},
|
|
2131
|
-
content: {width: 700, height: 800}
|
|
2526
|
+
content: {width: 700, height: 800},
|
|
2132
2527
|
});
|
|
2133
2528
|
|
|
2134
2529
|
// and now set just the layoutType, the previous main and content values should be used
|
|
@@ -2141,7 +2536,7 @@ describe('plugin-meetings', () => {
|
|
|
2141
2536
|
deviceUrl: meeting.deviceUrl,
|
|
2142
2537
|
layoutType,
|
|
2143
2538
|
main: {width: 300, height: 400},
|
|
2144
|
-
content: {width: 700, height: 800}
|
|
2539
|
+
content: {width: 700, height: 800},
|
|
2145
2540
|
});
|
|
2146
2541
|
});
|
|
2147
2542
|
|
|
@@ -2153,7 +2548,7 @@ describe('plugin-meetings', () => {
|
|
|
2153
2548
|
deviceUrl: meeting.deviceUrl,
|
|
2154
2549
|
layoutType: layoutTypeSingle,
|
|
2155
2550
|
main: {width: 1024, height: 768},
|
|
2156
|
-
content: undefined
|
|
2551
|
+
content: undefined,
|
|
2157
2552
|
});
|
|
2158
2553
|
meeting.meetingRequest.changeVideoLayoutDebounced.resetHistory();
|
|
2159
2554
|
|
|
@@ -2175,28 +2570,39 @@ describe('plugin-meetings', () => {
|
|
|
2175
2570
|
meeting.mediaProperties.mediaDirection.receiveShare = true;
|
|
2176
2571
|
meeting.mediaProperties.remoteShare = sinon.stub().returns({mockTrack: 'mockTrack'});
|
|
2177
2572
|
|
|
2178
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2573
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2574
|
+
main: {width: 500, height: 510},
|
|
2575
|
+
content: {width: 1024, height: 768},
|
|
2576
|
+
});
|
|
2179
2577
|
|
|
2180
2578
|
assert.calledWith(meeting.meetingRequest.changeVideoLayoutDebounced, {
|
|
2181
2579
|
locusUrl: meeting.locusInfo.self.url,
|
|
2182
2580
|
deviceUrl: meeting.deviceUrl,
|
|
2183
2581
|
layoutType: layoutTypeSingle,
|
|
2184
2582
|
main: {width: 500, height: 510},
|
|
2185
|
-
content: {width: 1024, height: 768}
|
|
2583
|
+
content: {width: 1024, height: 768},
|
|
2186
2584
|
});
|
|
2187
2585
|
meeting.meetingRequest.changeVideoLayoutDebounced.resetHistory();
|
|
2188
2586
|
|
|
2189
2587
|
// now send main with width/height different by just 2px - it should be ignored
|
|
2190
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2588
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2589
|
+
content: {width: 1026, height: 768},
|
|
2590
|
+
});
|
|
2191
2591
|
assert.notCalled(meeting.meetingRequest.changeVideoLayoutDebounced);
|
|
2192
2592
|
|
|
2193
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2593
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2594
|
+
content: {width: 1022, height: 768},
|
|
2595
|
+
});
|
|
2194
2596
|
assert.notCalled(meeting.meetingRequest.changeVideoLayoutDebounced);
|
|
2195
2597
|
|
|
2196
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2598
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2599
|
+
content: {width: 1024, height: 770},
|
|
2600
|
+
});
|
|
2197
2601
|
assert.notCalled(meeting.meetingRequest.changeVideoLayoutDebounced);
|
|
2198
2602
|
|
|
2199
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2603
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2604
|
+
content: {width: 1024, height: 766},
|
|
2605
|
+
});
|
|
2200
2606
|
assert.notCalled(meeting.meetingRequest.changeVideoLayoutDebounced);
|
|
2201
2607
|
});
|
|
2202
2608
|
|
|
@@ -2204,14 +2610,17 @@ describe('plugin-meetings', () => {
|
|
|
2204
2610
|
meeting.mediaProperties.mediaDirection.receiveShare = true;
|
|
2205
2611
|
meeting.mediaProperties.remoteShare = sinon.stub().returns({mockTrack: 'mockTrack'});
|
|
2206
2612
|
|
|
2207
|
-
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2613
|
+
await meeting.changeVideoLayout(layoutTypeSingle, {
|
|
2614
|
+
main: {width: 500.5, height: 510.09},
|
|
2615
|
+
content: {width: 1024.2, height: 768.85},
|
|
2616
|
+
});
|
|
2208
2617
|
|
|
2209
2618
|
assert.calledWith(meeting.meetingRequest.changeVideoLayoutDebounced, {
|
|
2210
2619
|
locusUrl: meeting.locusInfo.self.url,
|
|
2211
2620
|
deviceUrl: meeting.deviceUrl,
|
|
2212
2621
|
layoutType: layoutTypeSingle,
|
|
2213
2622
|
main: {width: 501, height: 510},
|
|
2214
|
-
content: {width: 1024, height: 769}
|
|
2623
|
+
content: {width: 1024, height: 769},
|
|
2215
2624
|
});
|
|
2216
2625
|
});
|
|
2217
2626
|
});
|
|
@@ -2223,7 +2632,7 @@ describe('plugin-meetings', () => {
|
|
|
2223
2632
|
sendAudio: true,
|
|
2224
2633
|
sendVideo: true,
|
|
2225
2634
|
sendShare: false,
|
|
2226
|
-
receiveVideo: true
|
|
2635
|
+
receiveVideo: true,
|
|
2227
2636
|
};
|
|
2228
2637
|
|
|
2229
2638
|
meeting.mediaProperties.mediaDirection = mediaDirection;
|
|
@@ -2237,7 +2646,7 @@ describe('plugin-meetings', () => {
|
|
|
2237
2646
|
sendAudio: true,
|
|
2238
2647
|
sendVideo: true,
|
|
2239
2648
|
sendShare: false,
|
|
2240
|
-
receiveVideo: false
|
|
2649
|
+
receiveVideo: false,
|
|
2241
2650
|
};
|
|
2242
2651
|
|
|
2243
2652
|
meeting.mediaProperties.mediaDirection = mediaDirection;
|
|
@@ -2251,8 +2660,8 @@ describe('plugin-meetings', () => {
|
|
|
2251
2660
|
|
|
2252
2661
|
const fakeTrack = {getSettings: () => ({height: 720})};
|
|
2253
2662
|
const USER_AGENT_CHROME_MAC =
|
|
2254
|
-
|
|
2255
|
-
|
|
2663
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ' +
|
|
2664
|
+
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36';
|
|
2256
2665
|
|
|
2257
2666
|
beforeEach(() => {
|
|
2258
2667
|
mediaDirection = {sendAudio: true, sendVideo: true, sendShare: false};
|
|
@@ -2268,34 +2677,36 @@ describe('plugin-meetings', () => {
|
|
|
2268
2677
|
assert.exists(meeting.setLocalVideoQuality);
|
|
2269
2678
|
});
|
|
2270
2679
|
|
|
2271
|
-
it('should call getMediaStreams with the proper level', () =>
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2680
|
+
it('should call getMediaStreams with the proper level', () =>
|
|
2681
|
+
meeting.setLocalVideoQuality(CONSTANTS.QUALITY_LEVELS.LOW).then(() => {
|
|
2682
|
+
delete mediaDirection.receiveVideo;
|
|
2683
|
+
assert.calledWith(
|
|
2684
|
+
meeting.getMediaStreams,
|
|
2685
|
+
mediaDirection,
|
|
2686
|
+
CONSTANTS.VIDEO_RESOLUTIONS[CONSTANTS.QUALITY_LEVELS.LOW]
|
|
2687
|
+
);
|
|
2688
|
+
}));
|
|
2277
2689
|
|
|
2278
2690
|
it('when browser is chrome then it should stop previous video track', () => {
|
|
2279
2691
|
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
|
-
});
|
|
2692
|
+
assert.equal(BrowserDetection(USER_AGENT_CHROME_MAC).getBrowserName(), 'Chrome');
|
|
2693
|
+
meeting.setLocalVideoQuality(CONSTANTS.QUALITY_LEVELS.LOW).then(() => {
|
|
2694
|
+
assert.calledWith(Media.stopTracks, fakeTrack);
|
|
2695
|
+
});
|
|
2288
2696
|
});
|
|
2289
2697
|
|
|
2290
|
-
it('should set mediaProperty with the proper level', () =>
|
|
2291
|
-
|
|
2292
|
-
|
|
2698
|
+
it('should set mediaProperty with the proper level', () =>
|
|
2699
|
+
meeting.setLocalVideoQuality(CONSTANTS.QUALITY_LEVELS.LOW).then(() => {
|
|
2700
|
+
assert.equal(meeting.mediaProperties.localQualityLevel, CONSTANTS.QUALITY_LEVELS.LOW);
|
|
2701
|
+
}));
|
|
2293
2702
|
|
|
2294
2703
|
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
|
-
|
|
2704
|
+
meeting.setLocalVideoQuality(CONSTANTS.QUALITY_LEVELS['1080p']).then(() => {
|
|
2705
|
+
assert.equal(
|
|
2706
|
+
meeting.mediaProperties.localQualityLevel,
|
|
2707
|
+
CONSTANTS.QUALITY_LEVELS['720p']
|
|
2708
|
+
);
|
|
2709
|
+
});
|
|
2299
2710
|
});
|
|
2300
2711
|
|
|
2301
2712
|
it('should error if set to a invalid level', () => {
|
|
@@ -2321,13 +2732,15 @@ describe('plugin-meetings', () => {
|
|
|
2321
2732
|
assert.exists(meeting.setRemoteQualityLevel);
|
|
2322
2733
|
});
|
|
2323
2734
|
|
|
2324
|
-
it('should set mediaProperty with the proper level', () =>
|
|
2325
|
-
|
|
2326
|
-
|
|
2735
|
+
it('should set mediaProperty with the proper level', () =>
|
|
2736
|
+
meeting.setRemoteQualityLevel(CONSTANTS.QUALITY_LEVELS.LOW).then(() => {
|
|
2737
|
+
assert.equal(meeting.mediaProperties.remoteQualityLevel, CONSTANTS.QUALITY_LEVELS.LOW);
|
|
2738
|
+
}));
|
|
2327
2739
|
|
|
2328
|
-
it('should call updateMedia', () =>
|
|
2329
|
-
|
|
2330
|
-
|
|
2740
|
+
it('should call updateMedia', () =>
|
|
2741
|
+
meeting.setRemoteQualityLevel(CONSTANTS.QUALITY_LEVELS.LOW).then(() => {
|
|
2742
|
+
assert.calledOnce(meeting.updateMedia);
|
|
2743
|
+
}));
|
|
2331
2744
|
|
|
2332
2745
|
it('should error if set to a invalid level', () => {
|
|
2333
2746
|
assert.isRejected(meeting.setRemoteQualityLevel('invalid'));
|
|
@@ -2341,8 +2754,12 @@ describe('plugin-meetings', () => {
|
|
|
2341
2754
|
|
|
2342
2755
|
describe('#usePhoneAudio', () => {
|
|
2343
2756
|
beforeEach(() => {
|
|
2344
|
-
meeting.meetingRequest.dialIn = sinon
|
|
2345
|
-
|
|
2757
|
+
meeting.meetingRequest.dialIn = sinon
|
|
2758
|
+
.stub()
|
|
2759
|
+
.returns(Promise.resolve({body: {locus: 'testData'}}));
|
|
2760
|
+
meeting.meetingRequest.dialOut = sinon
|
|
2761
|
+
.stub()
|
|
2762
|
+
.returns(Promise.resolve({body: {locus: 'testData'}}));
|
|
2346
2763
|
meeting.locusInfo.onFullLocus = sinon.stub().returns(Promise.resolve());
|
|
2347
2764
|
});
|
|
2348
2765
|
|
|
@@ -2354,7 +2771,7 @@ describe('plugin-meetings', () => {
|
|
|
2354
2771
|
correlationId: meeting.correlationId,
|
|
2355
2772
|
dialInUrl: DIAL_IN_URL,
|
|
2356
2773
|
locusUrl: meeting.locusUrl,
|
|
2357
|
-
clientUrl: meeting.deviceUrl
|
|
2774
|
+
clientUrl: meeting.deviceUrl,
|
|
2358
2775
|
});
|
|
2359
2776
|
assert.calledWith(meeting.locusInfo.onFullLocus, 'testData');
|
|
2360
2777
|
assert.notCalled(meeting.meetingRequest.dialOut);
|
|
@@ -2369,7 +2786,7 @@ describe('plugin-meetings', () => {
|
|
|
2369
2786
|
correlationId: meeting.correlationId,
|
|
2370
2787
|
dialInUrl: DIAL_IN_URL,
|
|
2371
2788
|
locusUrl: meeting.locusUrl,
|
|
2372
|
-
clientUrl: meeting.deviceUrl
|
|
2789
|
+
clientUrl: meeting.deviceUrl,
|
|
2373
2790
|
});
|
|
2374
2791
|
assert.calledWith(meeting.locusInfo.onFullLocus, 'testData');
|
|
2375
2792
|
assert.notCalled(meeting.meetingRequest.dialOut);
|
|
@@ -2386,7 +2803,7 @@ describe('plugin-meetings', () => {
|
|
|
2386
2803
|
dialOutUrl: DIAL_OUT_URL,
|
|
2387
2804
|
locusUrl: meeting.locusUrl,
|
|
2388
2805
|
clientUrl: meeting.deviceUrl,
|
|
2389
|
-
phoneNumber
|
|
2806
|
+
phoneNumber,
|
|
2390
2807
|
});
|
|
2391
2808
|
assert.calledWith(meeting.locusInfo.onFullLocus, 'testData');
|
|
2392
2809
|
assert.notCalled(meeting.meetingRequest.dialIn);
|
|
@@ -2402,7 +2819,7 @@ describe('plugin-meetings', () => {
|
|
|
2402
2819
|
dialOutUrl: DIAL_OUT_URL,
|
|
2403
2820
|
locusUrl: meeting.locusUrl,
|
|
2404
2821
|
clientUrl: meeting.deviceUrl,
|
|
2405
|
-
phoneNumber
|
|
2822
|
+
phoneNumber,
|
|
2406
2823
|
});
|
|
2407
2824
|
assert.calledWith(meeting.locusInfo.onFullLocus, 'testData');
|
|
2408
2825
|
assert.notCalled(meeting.meetingRequest.dialIn);
|
|
@@ -2413,11 +2830,14 @@ describe('plugin-meetings', () => {
|
|
|
2413
2830
|
|
|
2414
2831
|
meeting.meetingRequest.dialIn = sinon.stub().returns(Promise.reject(error));
|
|
2415
2832
|
|
|
2416
|
-
return meeting
|
|
2417
|
-
|
|
2833
|
+
return meeting
|
|
2834
|
+
.usePhoneAudio()
|
|
2835
|
+
.then(() => Promise.reject(new Error('Promise resolved when it should have rejected')))
|
|
2836
|
+
.catch((e) => {
|
|
2837
|
+
assert.equal(e, error);
|
|
2418
2838
|
|
|
2419
|
-
|
|
2420
|
-
|
|
2839
|
+
return Promise.resolve();
|
|
2840
|
+
});
|
|
2421
2841
|
});
|
|
2422
2842
|
|
|
2423
2843
|
it('rejects if the request failed (dial out)', async () => {
|
|
@@ -2425,11 +2845,14 @@ describe('plugin-meetings', () => {
|
|
|
2425
2845
|
|
|
2426
2846
|
meeting.meetingRequest.dialOut = sinon.stub().returns(Promise.reject(error));
|
|
2427
2847
|
|
|
2428
|
-
return meeting
|
|
2429
|
-
|
|
2848
|
+
return meeting
|
|
2849
|
+
.usePhoneAudio('+441234567890')
|
|
2850
|
+
.then(() => Promise.reject(new Error('Promise resolved when it should have rejected')))
|
|
2851
|
+
.catch((e) => {
|
|
2852
|
+
assert.equal(e, error);
|
|
2430
2853
|
|
|
2431
|
-
|
|
2432
|
-
|
|
2854
|
+
return Promise.resolve();
|
|
2855
|
+
});
|
|
2433
2856
|
});
|
|
2434
2857
|
});
|
|
2435
2858
|
|
|
@@ -2448,34 +2871,42 @@ describe('plugin-meetings', () => {
|
|
|
2448
2871
|
locusUrl: 'some_locus_url',
|
|
2449
2872
|
sipUrl: 'some_sip_url', // or sipMeetingUri
|
|
2450
2873
|
meetingNumber: '123456', // this.config.experimental.enableUnifiedMeetings
|
|
2451
|
-
hostId: 'some_host_id' // this.owner;
|
|
2874
|
+
hostId: 'some_host_id', // this.owner;
|
|
2452
2875
|
};
|
|
2453
2876
|
const FAKE_SDK_CAPTCHA_INFO = {
|
|
2454
2877
|
captchaId: FAKE_CAPTCHA_ID,
|
|
2455
2878
|
verificationImageURL: FAKE_CAPTCHA_IMAGE_URL,
|
|
2456
2879
|
verificationAudioURL: FAKE_CAPTCHA_AUDIO_URL,
|
|
2457
|
-
refreshURL: FAKE_CAPTCHA_REFRESH_URL
|
|
2880
|
+
refreshURL: FAKE_CAPTCHA_REFRESH_URL,
|
|
2458
2881
|
};
|
|
2459
2882
|
const FAKE_WBXAPPAPI_CAPTCHA_INFO = {
|
|
2460
2883
|
captchaID: `${FAKE_CAPTCHA_ID}-2`,
|
|
2461
2884
|
verificationImageURL: `${FAKE_CAPTCHA_IMAGE_URL}-2`,
|
|
2462
2885
|
verificationAudioURL: `${FAKE_CAPTCHA_AUDIO_URL}-2`,
|
|
2463
|
-
refreshURL: `${FAKE_CAPTCHA_REFRESH_URL}-2
|
|
2886
|
+
refreshURL: `${FAKE_CAPTCHA_REFRESH_URL}-2`,
|
|
2464
2887
|
};
|
|
2465
2888
|
|
|
2466
|
-
|
|
2467
2889
|
it('calls meetingInfoProvider with all the right parameters and parses the result', async () => {
|
|
2468
|
-
meeting.attrs.meetingInfoProvider = {
|
|
2890
|
+
meeting.attrs.meetingInfoProvider = {
|
|
2891
|
+
fetchMeetingInfo: sinon.stub().resolves({body: FAKE_MEETING_INFO}),
|
|
2892
|
+
};
|
|
2469
2893
|
meeting.requiredCaptcha = FAKE_SDK_CAPTCHA_INFO;
|
|
2470
2894
|
meeting.destination = FAKE_DESTINATION;
|
|
2471
2895
|
meeting.destinationType = FAKE_TYPE;
|
|
2472
2896
|
meeting.parseMeetingInfo = sinon.stub().returns(undefined);
|
|
2473
2897
|
|
|
2474
2898
|
await meeting.fetchMeetingInfo({
|
|
2475
|
-
password: FAKE_PASSWORD,
|
|
2899
|
+
password: FAKE_PASSWORD,
|
|
2900
|
+
captchaCode: FAKE_CAPTCHA_CODE,
|
|
2476
2901
|
});
|
|
2477
2902
|
|
|
2478
|
-
assert.calledWith(
|
|
2903
|
+
assert.calledWith(
|
|
2904
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
2905
|
+
FAKE_DESTINATION,
|
|
2906
|
+
FAKE_TYPE,
|
|
2907
|
+
FAKE_PASSWORD,
|
|
2908
|
+
{code: FAKE_CAPTCHA_CODE, id: FAKE_CAPTCHA_ID}
|
|
2909
|
+
);
|
|
2479
2910
|
|
|
2480
2911
|
assert.calledWith(meeting.parseMeetingInfo, {body: FAKE_MEETING_INFO}, FAKE_DESTINATION);
|
|
2481
2912
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
@@ -2483,11 +2914,18 @@ describe('plugin-meetings', () => {
|
|
|
2483
2914
|
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.NONE);
|
|
2484
2915
|
assert.equal(meeting.requiredCaptcha, null);
|
|
2485
2916
|
assert.calledTwice(TriggerProxy.trigger);
|
|
2486
|
-
assert.calledWith(
|
|
2917
|
+
assert.calledWith(
|
|
2918
|
+
TriggerProxy.trigger,
|
|
2919
|
+
meeting,
|
|
2920
|
+
{file: 'meetings', function: 'fetchMeetingInfo'},
|
|
2921
|
+
'meeting:meetingInfoAvailable'
|
|
2922
|
+
);
|
|
2487
2923
|
});
|
|
2488
2924
|
|
|
2489
2925
|
it('calls meetingInfoProvider with all the right parameters and parses the result when random delay is applied', async () => {
|
|
2490
|
-
meeting.attrs.meetingInfoProvider = {
|
|
2926
|
+
meeting.attrs.meetingInfoProvider = {
|
|
2927
|
+
fetchMeetingInfo: sinon.stub().resolves({body: FAKE_MEETING_INFO}),
|
|
2928
|
+
};
|
|
2491
2929
|
meeting.destination = FAKE_DESTINATION;
|
|
2492
2930
|
meeting.destinationType = FAKE_TYPE;
|
|
2493
2931
|
meeting.parseMeetingInfo = sinon.stub().returns(undefined);
|
|
@@ -2504,7 +2942,13 @@ describe('plugin-meetings', () => {
|
|
|
2504
2942
|
assert.isUndefined(meeting.fetchMeetingInfoTimeoutId);
|
|
2505
2943
|
|
|
2506
2944
|
// meeting info provider
|
|
2507
|
-
assert.calledWith(
|
|
2945
|
+
assert.calledWith(
|
|
2946
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
2947
|
+
FAKE_DESTINATION,
|
|
2948
|
+
FAKE_TYPE,
|
|
2949
|
+
null,
|
|
2950
|
+
null
|
|
2951
|
+
);
|
|
2508
2952
|
|
|
2509
2953
|
// parseMeeting info
|
|
2510
2954
|
assert.calledWith(meeting.parseMeetingInfo, {body: FAKE_MEETING_INFO}, FAKE_DESTINATION);
|
|
@@ -2515,31 +2959,48 @@ describe('plugin-meetings', () => {
|
|
|
2515
2959
|
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.NOT_REQUIRED);
|
|
2516
2960
|
|
|
2517
2961
|
assert.calledTwice(TriggerProxy.trigger);
|
|
2518
|
-
assert.calledWith(
|
|
2962
|
+
assert.calledWith(
|
|
2963
|
+
TriggerProxy.trigger,
|
|
2964
|
+
meeting,
|
|
2965
|
+
{file: 'meetings', function: 'fetchMeetingInfo'},
|
|
2966
|
+
'meeting:meetingInfoAvailable'
|
|
2967
|
+
);
|
|
2519
2968
|
});
|
|
2520
2969
|
|
|
2521
2970
|
it('fails if captchaCode is provided when captcha not needed', async () => {
|
|
2522
|
-
meeting.attrs.meetingInfoProvider = {
|
|
2971
|
+
meeting.attrs.meetingInfoProvider = {
|
|
2972
|
+
fetchMeetingInfo: sinon.stub().resolves({body: FAKE_MEETING_INFO}),
|
|
2973
|
+
};
|
|
2523
2974
|
meeting.requiredCaptcha = null;
|
|
2524
2975
|
meeting.destination = FAKE_DESTINATION;
|
|
2525
2976
|
meeting.destinationType = FAKE_TYPE;
|
|
2526
2977
|
|
|
2527
|
-
await assert.isRejected(
|
|
2528
|
-
|
|
2529
|
-
|
|
2978
|
+
await assert.isRejected(
|
|
2979
|
+
meeting.fetchMeetingInfo({
|
|
2980
|
+
captchaCode: FAKE_CAPTCHA_CODE,
|
|
2981
|
+
}),
|
|
2982
|
+
Error,
|
|
2983
|
+
'fetchMeetingInfo() called with captchaCode when captcha was not required'
|
|
2984
|
+
);
|
|
2530
2985
|
|
|
2531
2986
|
assert.notCalled(meeting.attrs.meetingInfoProvider.fetchMeetingInfo);
|
|
2532
2987
|
});
|
|
2533
2988
|
|
|
2534
2989
|
it('fails if password is provided when not required', async () => {
|
|
2535
|
-
meeting.attrs.meetingInfoProvider = {
|
|
2990
|
+
meeting.attrs.meetingInfoProvider = {
|
|
2991
|
+
fetchMeetingInfo: sinon.stub().resolves({body: FAKE_MEETING_INFO}),
|
|
2992
|
+
};
|
|
2536
2993
|
meeting.passwordStatus = PASSWORD_STATUS.NOT_REQUIRED;
|
|
2537
2994
|
meeting.destination = FAKE_DESTINATION;
|
|
2538
2995
|
meeting.destinationType = FAKE_TYPE;
|
|
2539
2996
|
|
|
2540
|
-
await assert.isRejected(
|
|
2541
|
-
|
|
2542
|
-
|
|
2997
|
+
await assert.isRejected(
|
|
2998
|
+
meeting.fetchMeetingInfo({
|
|
2999
|
+
password: FAKE_PASSWORD,
|
|
3000
|
+
}),
|
|
3001
|
+
Error,
|
|
3002
|
+
'fetchMeetingInfo() called with password when password was not required'
|
|
3003
|
+
);
|
|
2543
3004
|
|
|
2544
3005
|
assert.notCalled(meeting.attrs.meetingInfoProvider.fetchMeetingInfo);
|
|
2545
3006
|
});
|
|
@@ -2548,15 +3009,26 @@ describe('plugin-meetings', () => {
|
|
|
2548
3009
|
meeting.destination = FAKE_DESTINATION;
|
|
2549
3010
|
meeting.destinationType = FAKE_TYPE;
|
|
2550
3011
|
meeting.attrs.meetingInfoProvider = {
|
|
2551
|
-
fetchMeetingInfo: sinon
|
|
3012
|
+
fetchMeetingInfo: sinon
|
|
3013
|
+
.stub()
|
|
3014
|
+
.throws(new MeetingInfoV2PasswordError(403004, FAKE_MEETING_INFO)),
|
|
2552
3015
|
};
|
|
2553
3016
|
|
|
2554
3017
|
await assert.isRejected(meeting.fetchMeetingInfo({}), PasswordError);
|
|
2555
3018
|
|
|
2556
|
-
assert.calledWith(
|
|
3019
|
+
assert.calledWith(
|
|
3020
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
3021
|
+
FAKE_DESTINATION,
|
|
3022
|
+
FAKE_TYPE,
|
|
3023
|
+
null,
|
|
3024
|
+
null
|
|
3025
|
+
);
|
|
2557
3026
|
|
|
2558
3027
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
2559
|
-
assert.equal(
|
|
3028
|
+
assert.equal(
|
|
3029
|
+
meeting.meetingInfoFailureReason,
|
|
3030
|
+
MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD
|
|
3031
|
+
);
|
|
2560
3032
|
assert.equal(meeting.requiredCaptcha, null);
|
|
2561
3033
|
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.REQUIRED);
|
|
2562
3034
|
});
|
|
@@ -2565,25 +3037,38 @@ describe('plugin-meetings', () => {
|
|
|
2565
3037
|
meeting.destination = FAKE_DESTINATION;
|
|
2566
3038
|
meeting.destinationType = FAKE_TYPE;
|
|
2567
3039
|
meeting.attrs.meetingInfoProvider = {
|
|
2568
|
-
fetchMeetingInfo: sinon
|
|
3040
|
+
fetchMeetingInfo: sinon
|
|
3041
|
+
.stub()
|
|
3042
|
+
.throws(new MeetingInfoV2CaptchaError(423005, FAKE_SDK_CAPTCHA_INFO)),
|
|
2569
3043
|
};
|
|
2570
3044
|
meeting.requiredCaptcha = null;
|
|
2571
3045
|
|
|
2572
|
-
await assert.isRejected(
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
3046
|
+
await assert.isRejected(
|
|
3047
|
+
meeting.fetchMeetingInfo({
|
|
3048
|
+
password: 'aaa',
|
|
3049
|
+
}),
|
|
3050
|
+
CaptchaError
|
|
3051
|
+
);
|
|
2577
3052
|
|
|
3053
|
+
assert.calledWith(
|
|
3054
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
3055
|
+
FAKE_DESTINATION,
|
|
3056
|
+
FAKE_TYPE,
|
|
3057
|
+
'aaa',
|
|
3058
|
+
null
|
|
3059
|
+
);
|
|
2578
3060
|
|
|
2579
3061
|
assert.deepEqual(meeting.meetingInfo, {});
|
|
2580
|
-
assert.equal(
|
|
3062
|
+
assert.equal(
|
|
3063
|
+
meeting.meetingInfoFailureReason,
|
|
3064
|
+
MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD
|
|
3065
|
+
);
|
|
2581
3066
|
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.REQUIRED);
|
|
2582
3067
|
assert.deepEqual(meeting.requiredCaptcha, {
|
|
2583
3068
|
captchaId: FAKE_CAPTCHA_ID,
|
|
2584
3069
|
verificationImageURL: FAKE_CAPTCHA_IMAGE_URL,
|
|
2585
3070
|
verificationAudioURL: FAKE_CAPTCHA_AUDIO_URL,
|
|
2586
|
-
refreshURL: FAKE_CAPTCHA_REFRESH_URL
|
|
3071
|
+
refreshURL: FAKE_CAPTCHA_REFRESH_URL,
|
|
2587
3072
|
});
|
|
2588
3073
|
});
|
|
2589
3074
|
|
|
@@ -2591,15 +3076,27 @@ describe('plugin-meetings', () => {
|
|
|
2591
3076
|
meeting.destination = FAKE_DESTINATION;
|
|
2592
3077
|
meeting.destinationType = FAKE_TYPE;
|
|
2593
3078
|
meeting.attrs.meetingInfoProvider = {
|
|
2594
|
-
fetchMeetingInfo: sinon
|
|
3079
|
+
fetchMeetingInfo: sinon
|
|
3080
|
+
.stub()
|
|
3081
|
+
.throws(new MeetingInfoV2CaptchaError(423005, FAKE_SDK_CAPTCHA_INFO)),
|
|
2595
3082
|
};
|
|
2596
3083
|
meeting.requiredCaptcha = FAKE_SDK_CAPTCHA_INFO;
|
|
2597
3084
|
|
|
2598
|
-
await assert.isRejected(
|
|
2599
|
-
|
|
2600
|
-
|
|
3085
|
+
await assert.isRejected(
|
|
3086
|
+
meeting.fetchMeetingInfo({
|
|
3087
|
+
password: 'aaa',
|
|
3088
|
+
captchaCode: 'bbb',
|
|
3089
|
+
}),
|
|
3090
|
+
CaptchaError
|
|
3091
|
+
);
|
|
2601
3092
|
|
|
2602
|
-
assert.calledWith(
|
|
3093
|
+
assert.calledWith(
|
|
3094
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
3095
|
+
FAKE_DESTINATION,
|
|
3096
|
+
FAKE_TYPE,
|
|
3097
|
+
'aaa',
|
|
3098
|
+
{code: 'bbb', id: FAKE_CAPTCHA_ID}
|
|
3099
|
+
);
|
|
2603
3100
|
|
|
2604
3101
|
assert.deepEqual(meeting.meetingInfo, {});
|
|
2605
3102
|
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA);
|
|
@@ -2611,20 +3108,24 @@ describe('plugin-meetings', () => {
|
|
|
2611
3108
|
meeting.destination = FAKE_DESTINATION;
|
|
2612
3109
|
meeting.destinationType = FAKE_TYPE;
|
|
2613
3110
|
meeting.attrs.meetingInfoProvider = {
|
|
2614
|
-
fetchMeetingInfo: sinon.stub().resolves(
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
}
|
|
2619
|
-
)
|
|
3111
|
+
fetchMeetingInfo: sinon.stub().resolves({
|
|
3112
|
+
statusCode: 200,
|
|
3113
|
+
body: FAKE_MEETING_INFO,
|
|
3114
|
+
}),
|
|
2620
3115
|
};
|
|
2621
3116
|
meeting.passwordStatus = PASSWORD_STATUS.REQUIRED;
|
|
2622
3117
|
|
|
2623
3118
|
await meeting.fetchMeetingInfo({
|
|
2624
|
-
password: 'aaa'
|
|
3119
|
+
password: 'aaa',
|
|
2625
3120
|
});
|
|
2626
3121
|
|
|
2627
|
-
assert.calledWith(
|
|
3122
|
+
assert.calledWith(
|
|
3123
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
3124
|
+
FAKE_DESTINATION,
|
|
3125
|
+
FAKE_TYPE,
|
|
3126
|
+
'aaa',
|
|
3127
|
+
null
|
|
3128
|
+
);
|
|
2628
3129
|
|
|
2629
3130
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
2630
3131
|
assert.equal(meeting.meetingInfoFailureReason, MEETING_INFO_FAILURE_REASON.NONE);
|
|
@@ -2638,36 +3139,50 @@ describe('plugin-meetings', () => {
|
|
|
2638
3139
|
const refreshedCaptcha = {
|
|
2639
3140
|
captchaID: FAKE_WBXAPPAPI_CAPTCHA_INFO.captchaID,
|
|
2640
3141
|
verificationImageURL: FAKE_WBXAPPAPI_CAPTCHA_INFO.verificationImageURL,
|
|
2641
|
-
verificationAudioURL: FAKE_WBXAPPAPI_CAPTCHA_INFO.verificationAudioURL
|
|
3142
|
+
verificationAudioURL: FAKE_WBXAPPAPI_CAPTCHA_INFO.verificationAudioURL,
|
|
2642
3143
|
};
|
|
2643
3144
|
|
|
2644
3145
|
meeting.attrs.meetingInfoProvider = {
|
|
2645
|
-
fetchMeetingInfo: sinon
|
|
3146
|
+
fetchMeetingInfo: sinon
|
|
3147
|
+
.stub()
|
|
3148
|
+
.throws(new MeetingInfoV2PasswordError(403004, FAKE_MEETING_INFO)),
|
|
2646
3149
|
};
|
|
2647
|
-
meeting.meetingRequest.refreshCaptcha = sinon.stub().returns(
|
|
2648
|
-
{
|
|
2649
|
-
body: refreshedCaptcha
|
|
2650
|
-
}
|
|
2651
|
-
)
|
|
3150
|
+
meeting.meetingRequest.refreshCaptcha = sinon.stub().returns(
|
|
3151
|
+
Promise.resolve({
|
|
3152
|
+
body: refreshedCaptcha,
|
|
3153
|
+
})
|
|
3154
|
+
);
|
|
2652
3155
|
meeting.passwordStatus = PASSWORD_STATUS.REQUIRED;
|
|
2653
3156
|
meeting.requiredCaptcha = FAKE_SDK_CAPTCHA_INFO;
|
|
2654
3157
|
meeting.destination = FAKE_DESTINATION;
|
|
2655
3158
|
meeting.destinationType = FAKE_TYPE;
|
|
2656
3159
|
|
|
2657
|
-
await assert.isRejected(
|
|
2658
|
-
|
|
2659
|
-
|
|
3160
|
+
await assert.isRejected(
|
|
3161
|
+
meeting.fetchMeetingInfo({
|
|
3162
|
+
password: 'aaa',
|
|
3163
|
+
captchaCode: 'bbb',
|
|
3164
|
+
})
|
|
3165
|
+
);
|
|
2660
3166
|
|
|
2661
|
-
assert.calledWith(
|
|
3167
|
+
assert.calledWith(
|
|
3168
|
+
meeting.attrs.meetingInfoProvider.fetchMeetingInfo,
|
|
3169
|
+
FAKE_DESTINATION,
|
|
3170
|
+
FAKE_TYPE,
|
|
3171
|
+
'aaa',
|
|
3172
|
+
{code: 'bbb', id: FAKE_CAPTCHA_ID}
|
|
3173
|
+
);
|
|
2662
3174
|
|
|
2663
3175
|
assert.deepEqual(meeting.meetingInfo, FAKE_MEETING_INFO);
|
|
2664
|
-
assert.equal(
|
|
3176
|
+
assert.equal(
|
|
3177
|
+
meeting.meetingInfoFailureReason,
|
|
3178
|
+
MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD
|
|
3179
|
+
);
|
|
2665
3180
|
assert.equal(meeting.passwordStatus, PASSWORD_STATUS.REQUIRED);
|
|
2666
3181
|
assert.deepEqual(meeting.requiredCaptcha, {
|
|
2667
3182
|
captchaId: refreshedCaptcha.captchaID,
|
|
2668
3183
|
verificationImageURL: refreshedCaptcha.verificationImageURL,
|
|
2669
3184
|
verificationAudioURL: refreshedCaptcha.verificationAudioURL,
|
|
2670
|
-
refreshURL: FAKE_SDK_CAPTCHA_INFO.refreshURL // refresh url doesn't change
|
|
3185
|
+
refreshURL: FAKE_SDK_CAPTCHA_INFO.refreshURL, // refresh url doesn't change
|
|
2671
3186
|
});
|
|
2672
3187
|
});
|
|
2673
3188
|
});
|
|
@@ -2677,48 +3192,56 @@ describe('plugin-meetings', () => {
|
|
|
2677
3192
|
assert.isRejected(meeting.refreshCaptcha(), Error);
|
|
2678
3193
|
});
|
|
2679
3194
|
it('sends correct request to captcha service refresh url', async () => {
|
|
2680
|
-
const REFRESH_URL =
|
|
2681
|
-
|
|
3195
|
+
const REFRESH_URL =
|
|
3196
|
+
'https://something.webex.com/captchaservice/v1/captchas/refresh?blablabla=something&captchaID=xxx';
|
|
3197
|
+
const EXPECTED_REFRESH_URL =
|
|
3198
|
+
'https://something.webex.com/captchaservice/v1/captchas/refresh?blablabla=something&captchaID=xxx&siteFullName=something.webex.com';
|
|
2682
3199
|
|
|
2683
3200
|
const FAKE_SDK_CAPTCHA_INFO = {
|
|
2684
3201
|
captchaId: 'some id',
|
|
2685
3202
|
verificationImageURL: 'some image url',
|
|
2686
3203
|
verificationAudioURL: 'some audio url',
|
|
2687
|
-
refreshURL: REFRESH_URL
|
|
3204
|
+
refreshURL: REFRESH_URL,
|
|
2688
3205
|
};
|
|
2689
3206
|
|
|
2690
3207
|
const FAKE_REFRESHED_CAPTCHA = {
|
|
2691
3208
|
captchaID: 'some id',
|
|
2692
3209
|
verificationImageURL: 'some image url',
|
|
2693
|
-
verificationAudioURL: 'some audio url'
|
|
3210
|
+
verificationAudioURL: 'some audio url',
|
|
2694
3211
|
};
|
|
2695
3212
|
|
|
2696
3213
|
// setup the meeting so that a captcha is required
|
|
2697
3214
|
meeting.attrs.meetingInfoProvider = {
|
|
2698
|
-
fetchMeetingInfo: sinon
|
|
3215
|
+
fetchMeetingInfo: sinon
|
|
3216
|
+
.stub()
|
|
3217
|
+
.throws(new MeetingInfoV2CaptchaError(423005, FAKE_SDK_CAPTCHA_INFO)),
|
|
2699
3218
|
};
|
|
2700
3219
|
|
|
2701
|
-
await assert.isRejected(
|
|
2702
|
-
|
|
2703
|
-
|
|
3220
|
+
await assert.isRejected(
|
|
3221
|
+
meeting.fetchMeetingInfo({
|
|
3222
|
+
password: '',
|
|
3223
|
+
}),
|
|
3224
|
+
CaptchaError
|
|
3225
|
+
);
|
|
2704
3226
|
|
|
2705
3227
|
assert.deepEqual(meeting.requiredCaptcha, FAKE_SDK_CAPTCHA_INFO);
|
|
2706
|
-
meeting.meetingRequest.refreshCaptcha = sinon
|
|
3228
|
+
meeting.meetingRequest.refreshCaptcha = sinon
|
|
3229
|
+
.stub()
|
|
3230
|
+
.returns(Promise.resolve({body: FAKE_REFRESHED_CAPTCHA}));
|
|
2707
3231
|
|
|
2708
3232
|
// test the captcha refresh
|
|
2709
3233
|
await meeting.refreshCaptcha();
|
|
2710
3234
|
|
|
2711
|
-
assert.calledWith(meeting.meetingRequest.refreshCaptcha,
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
});
|
|
3235
|
+
assert.calledWith(meeting.meetingRequest.refreshCaptcha, {
|
|
3236
|
+
captchaRefreshUrl: EXPECTED_REFRESH_URL,
|
|
3237
|
+
captchaId: FAKE_SDK_CAPTCHA_INFO.captchaId,
|
|
3238
|
+
});
|
|
2716
3239
|
|
|
2717
3240
|
assert.deepEqual(meeting.requiredCaptcha, {
|
|
2718
3241
|
captchaId: FAKE_REFRESHED_CAPTCHA.captchaID,
|
|
2719
3242
|
verificationImageURL: FAKE_REFRESHED_CAPTCHA.verificationImageURL,
|
|
2720
3243
|
verificationAudioURL: FAKE_REFRESHED_CAPTCHA.verificationAudioURL,
|
|
2721
|
-
refreshURL: FAKE_SDK_CAPTCHA_INFO.refreshURL // refresh url doesn't change
|
|
3244
|
+
refreshURL: FAKE_SDK_CAPTCHA_INFO.refreshURL, // refresh url doesn't change
|
|
2722
3245
|
});
|
|
2723
3246
|
});
|
|
2724
3247
|
});
|
|
@@ -2732,7 +3255,7 @@ describe('plugin-meetings', () => {
|
|
|
2732
3255
|
assert(Metrics.sendBehavioralMetric.calledOnce);
|
|
2733
3256
|
assert.calledWith(
|
|
2734
3257
|
Metrics.sendBehavioralMetric,
|
|
2735
|
-
BEHAVIORAL_METRICS.VERIFY_PASSWORD_SUCCESS
|
|
3258
|
+
BEHAVIORAL_METRICS.VERIFY_PASSWORD_SUCCESS
|
|
2736
3259
|
);
|
|
2737
3260
|
assert.equal(result.isPasswordValid, true);
|
|
2738
3261
|
assert.equal(result.requiredCaptcha, null);
|
|
@@ -2807,7 +3330,9 @@ describe('plugin-meetings', () => {
|
|
|
2807
3330
|
sandbox = sinon.createSandbox();
|
|
2808
3331
|
meeting.meetingFiniteStateMachine.ring();
|
|
2809
3332
|
meeting.meetingFiniteStateMachine.join();
|
|
2810
|
-
meeting.meetingRequest.endMeetingForAll = sinon
|
|
3333
|
+
meeting.meetingRequest.endMeetingForAll = sinon
|
|
3334
|
+
.stub()
|
|
3335
|
+
.returns(Promise.resolve({body: 'test'}));
|
|
2811
3336
|
meeting.locusInfo.onFullLocus = sinon.stub().returns(true);
|
|
2812
3337
|
meeting.closeLocalStream = sinon.stub().returns(Promise.resolve());
|
|
2813
3338
|
meeting.closeLocalShare = sinon.stub().returns(Promise.resolve());
|
|
@@ -2821,6 +3346,7 @@ describe('plugin-meetings', () => {
|
|
|
2821
3346
|
meeting.unsetRemoteStream = sinon.stub().returns(true);
|
|
2822
3347
|
meeting.unsetPeerConnections = sinon.stub().returns(true);
|
|
2823
3348
|
meeting.logger.error = sinon.stub().returns(true);
|
|
3349
|
+
meeting.updateLLMConnection = sinon.stub().returns(Promise.resolve());
|
|
2824
3350
|
|
|
2825
3351
|
// A meeting needs to be joined to end
|
|
2826
3352
|
meeting.meetingState = 'ACTIVE';
|
|
@@ -2859,7 +3385,11 @@ describe('plugin-meetings', () => {
|
|
|
2859
3385
|
sandbox.stub(meeting.mediaProperties, 'unsetMediaTracks');
|
|
2860
3386
|
|
|
2861
3387
|
sandbox.stub(meeting.reconnectionManager, 'reconnectMedia').returns(Promise.resolve());
|
|
2862
|
-
sandbox
|
|
3388
|
+
sandbox
|
|
3389
|
+
.stub(MeetingUtil, 'joinMeeting')
|
|
3390
|
+
.returns(
|
|
3391
|
+
Promise.resolve(MeetingUtil.parseLocusJoin({body: {locus, mediaConnections: []}}))
|
|
3392
|
+
);
|
|
2863
3393
|
});
|
|
2864
3394
|
|
|
2865
3395
|
afterEach(() => {
|
|
@@ -2870,8 +3400,7 @@ describe('plugin-meetings', () => {
|
|
|
2870
3400
|
it('should throw an error if resourceId not passed', async () => {
|
|
2871
3401
|
try {
|
|
2872
3402
|
await meeting.moveTo();
|
|
2873
|
-
}
|
|
2874
|
-
catch (err) {
|
|
3403
|
+
} catch (err) {
|
|
2875
3404
|
assert.instanceOf(err, ParameterError);
|
|
2876
3405
|
assert.equal(err.sdkMessage, 'Cannot move call without a resourceId.');
|
|
2877
3406
|
}
|
|
@@ -2888,17 +3417,17 @@ describe('plugin-meetings', () => {
|
|
|
2888
3417
|
share: true,
|
|
2889
3418
|
share_audio: false,
|
|
2890
3419
|
video: false,
|
|
2891
|
-
whiteboard: false
|
|
3420
|
+
whiteboard: false,
|
|
2892
3421
|
},
|
|
2893
3422
|
tx: {
|
|
2894
3423
|
audio: false,
|
|
2895
3424
|
share: false,
|
|
2896
3425
|
share_audio: false,
|
|
2897
3426
|
video: false,
|
|
2898
|
-
whiteboard: false
|
|
2899
|
-
}
|
|
2900
|
-
}
|
|
2901
|
-
}
|
|
3427
|
+
whiteboard: false,
|
|
3428
|
+
},
|
|
3429
|
+
},
|
|
3430
|
+
},
|
|
2902
3431
|
});
|
|
2903
3432
|
assert.calledWithMatch(Metrics.postEvent, {event: eventType.MOVE_MEDIA});
|
|
2904
3433
|
});
|
|
@@ -2907,17 +3436,19 @@ describe('plugin-meetings', () => {
|
|
|
2907
3436
|
sinon.spy(MeetingUtil, 'joinMeetingOptions');
|
|
2908
3437
|
await meeting.moveTo('resourceId');
|
|
2909
3438
|
|
|
2910
|
-
assert.calledWith(MeetingUtil.joinMeetingOptions, meeting, {
|
|
3439
|
+
assert.calledWith(MeetingUtil.joinMeetingOptions, meeting, {
|
|
3440
|
+
resourceId: 'resourceId',
|
|
3441
|
+
moveToResource: true,
|
|
3442
|
+
});
|
|
2911
3443
|
});
|
|
2912
3444
|
|
|
2913
3445
|
it('should reconnectMedia after DX joins after moveTo', async () => {
|
|
2914
3446
|
await meeting.moveTo('resourceId');
|
|
2915
3447
|
|
|
2916
|
-
|
|
2917
3448
|
await meeting.locusInfo.emitScoped(
|
|
2918
3449
|
{
|
|
2919
3450
|
file: 'locus-info',
|
|
2920
|
-
function: 'updateSelf'
|
|
3451
|
+
function: 'updateSelf',
|
|
2921
3452
|
},
|
|
2922
3453
|
'SELF_OBSERVING'
|
|
2923
3454
|
);
|
|
@@ -2933,36 +3464,30 @@ describe('plugin-meetings', () => {
|
|
|
2933
3464
|
assert.called(meeting.mediaProperties.setMediaDirection);
|
|
2934
3465
|
assert.called(meeting.mediaProperties.unsetMediaTracks);
|
|
2935
3466
|
|
|
2936
|
-
assert.calledWith(meeting.reconnectionManager.reconnectMedia,
|
|
2937
|
-
{
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
});
|
|
3467
|
+
assert.calledWith(meeting.reconnectionManager.reconnectMedia, {
|
|
3468
|
+
mediaDirection: {
|
|
3469
|
+
sendVideo: false,
|
|
3470
|
+
receiveVideo: false,
|
|
3471
|
+
sendAudio: false,
|
|
3472
|
+
receiveAudio: false,
|
|
3473
|
+
sendShare: false,
|
|
3474
|
+
receiveShare: true,
|
|
3475
|
+
},
|
|
3476
|
+
});
|
|
2947
3477
|
});
|
|
2948
3478
|
|
|
2949
3479
|
it('should throw an error if moveTo call fails', async () => {
|
|
2950
3480
|
MeetingUtil.joinMeeting = sinon.stub().returns(Promise.reject());
|
|
2951
3481
|
try {
|
|
2952
3482
|
await meeting.moveTo('resourceId');
|
|
2953
|
-
}
|
|
2954
|
-
catch {
|
|
3483
|
+
} catch {
|
|
2955
3484
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
2956
|
-
assert.calledWith(
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
reason: sinon.match.any,
|
|
2963
|
-
stack: sinon.match.any
|
|
2964
|
-
}
|
|
2965
|
-
);
|
|
3485
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.MOVE_TO_FAILURE, {
|
|
3486
|
+
correlation_id: meeting.correlationId,
|
|
3487
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
3488
|
+
reason: sinon.match.any,
|
|
3489
|
+
stack: sinon.match.any,
|
|
3490
|
+
});
|
|
2966
3491
|
}
|
|
2967
3492
|
Metrics.sendBehavioralMetric.reset();
|
|
2968
3493
|
meeting.reconnectionManager.reconnectMedia = sinon.stub().returns(Promise.reject());
|
|
@@ -2972,23 +3497,18 @@ describe('plugin-meetings', () => {
|
|
|
2972
3497
|
await meeting.locusInfo.emitScoped(
|
|
2973
3498
|
{
|
|
2974
3499
|
file: 'locus-info',
|
|
2975
|
-
function: 'updateSelf'
|
|
3500
|
+
function: 'updateSelf',
|
|
2976
3501
|
},
|
|
2977
3502
|
'SELF_OBSERVING'
|
|
2978
3503
|
);
|
|
2979
|
-
}
|
|
2980
|
-
catch {
|
|
3504
|
+
} catch {
|
|
2981
3505
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
2982
|
-
assert.calledWith(
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
reason: sinon.match.any,
|
|
2989
|
-
stack: sinon.match.any
|
|
2990
|
-
}
|
|
2991
|
-
);
|
|
3506
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.MOVE_TO_FAILURE, {
|
|
3507
|
+
correlation_id: meeting.correlationId,
|
|
3508
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
3509
|
+
reason: sinon.match.any,
|
|
3510
|
+
stack: sinon.match.any,
|
|
3511
|
+
});
|
|
2992
3512
|
}
|
|
2993
3513
|
});
|
|
2994
3514
|
});
|
|
@@ -2998,7 +3518,11 @@ describe('plugin-meetings', () => {
|
|
|
2998
3518
|
|
|
2999
3519
|
beforeEach(() => {
|
|
3000
3520
|
sandbox = sinon.createSandbox();
|
|
3001
|
-
sandbox
|
|
3521
|
+
sandbox
|
|
3522
|
+
.stub(MeetingUtil, 'joinMeeting')
|
|
3523
|
+
.returns(
|
|
3524
|
+
Promise.resolve(MeetingUtil.parseLocusJoin({body: {locus, mediaConnections: []}}))
|
|
3525
|
+
);
|
|
3002
3526
|
sandbox.stub(MeetingUtil, 'leaveMeeting').returns(Promise.resolve());
|
|
3003
3527
|
});
|
|
3004
3528
|
|
|
@@ -3010,8 +3534,7 @@ describe('plugin-meetings', () => {
|
|
|
3010
3534
|
it('should throw an error if resourceId not passed', async () => {
|
|
3011
3535
|
try {
|
|
3012
3536
|
await meeting.moveFrom();
|
|
3013
|
-
}
|
|
3014
|
-
catch (err) {
|
|
3537
|
+
} catch (err) {
|
|
3015
3538
|
assert.instanceOf(err, ParameterError);
|
|
3016
3539
|
|
|
3017
3540
|
assert.equal(err.sdkMessage, 'Cannot move call without a resourceId.');
|
|
@@ -3032,35 +3555,193 @@ describe('plugin-meetings', () => {
|
|
|
3032
3555
|
assert.calledWith(MeetingUtil.leaveMeeting, meeting, {
|
|
3033
3556
|
resourceId: 'resourceId',
|
|
3034
3557
|
correlationId: meeting.correlationId,
|
|
3035
|
-
moveMeeting: true
|
|
3558
|
+
moveMeeting: true,
|
|
3036
3559
|
});
|
|
3037
3560
|
|
|
3038
3561
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
3039
|
-
assert.calledWith(
|
|
3040
|
-
Metrics.sendBehavioralMetric,
|
|
3041
|
-
BEHAVIORAL_METRICS.MOVE_FROM_SUCCESS,
|
|
3042
|
-
);
|
|
3562
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.MOVE_FROM_SUCCESS);
|
|
3043
3563
|
});
|
|
3044
3564
|
|
|
3045
3565
|
it('should throw an error if moveFrom call fails', async () => {
|
|
3046
3566
|
MeetingUtil.joinMeeting = sinon.stub().returns(Promise.reject());
|
|
3047
3567
|
try {
|
|
3048
3568
|
await meeting.moveFrom('resourceId');
|
|
3049
|
-
}
|
|
3050
|
-
catch {
|
|
3569
|
+
} catch {
|
|
3051
3570
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
3052
|
-
assert.calledWith(
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3571
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.MOVE_FROM_FAILURE, {
|
|
3572
|
+
correlation_id: meeting.correlationId,
|
|
3573
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
3574
|
+
reason: sinon.match.any,
|
|
3575
|
+
stack: sinon.match.any,
|
|
3576
|
+
});
|
|
3577
|
+
}
|
|
3578
|
+
});
|
|
3579
|
+
});
|
|
3580
|
+
describe('Local tracks publishing', () => {
|
|
3581
|
+
let audioTrack;
|
|
3582
|
+
let videoTrack;
|
|
3583
|
+
let videoShareTrack;
|
|
3584
|
+
let createMuteStateStub;
|
|
3585
|
+
|
|
3586
|
+
beforeEach(() => {
|
|
3587
|
+
audioTrack = {
|
|
3588
|
+
id: 'audio track',
|
|
3589
|
+
getSettings: sinon.stub().returns({}),
|
|
3590
|
+
};
|
|
3591
|
+
videoTrack = {
|
|
3592
|
+
id: 'video track',
|
|
3593
|
+
getSettings: sinon.stub().returns({}),
|
|
3594
|
+
};
|
|
3595
|
+
videoShareTrack = {
|
|
3596
|
+
id: 'share track',
|
|
3597
|
+
addEventListener: sinon.stub(),
|
|
3598
|
+
removeEventListener: sinon.stub(),
|
|
3599
|
+
getSettings: sinon.stub().returns({}),
|
|
3600
|
+
};
|
|
3601
|
+
meeting.requestScreenShareFloor = sinon.stub().resolves({});
|
|
3602
|
+
meeting.releaseScreenShareFloor = sinon.stub().resolves({});
|
|
3603
|
+
meeting.mediaProperties.mediaDirection = {sendAudio: false, sendVideo: false, sendShare: false};
|
|
3604
|
+
meeting.mediaProperties.webrtcMediaConnection = {
|
|
3605
|
+
publishTrack: sinon.stub().resolves({}),
|
|
3606
|
+
unpublishTrack: sinon.stub().resolves({}),
|
|
3607
|
+
};
|
|
3608
|
+
|
|
3609
|
+
createMuteStateStub = sinon.stub(MuteStateModule, 'createMuteState').returns({id: 'fake mute state instance'});
|
|
3610
|
+
})
|
|
3611
|
+
describe('#publishTracks', () => {
|
|
3612
|
+
it('fails if there is no media connection', async () => {
|
|
3613
|
+
meeting.mediaProperties.webrtcMediaConnection = undefined;
|
|
3614
|
+
await assert.isRejected(meeting.publishTracks({audio: {id: 'some audio track'}}));
|
|
3615
|
+
});
|
|
3616
|
+
|
|
3617
|
+
const checkAudioPublished = () => {
|
|
3618
|
+
assert.calledWith(createMuteStateStub, 'audio', meeting, meeting.mediaProperties.mediaDirection);
|
|
3619
|
+
assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, audioTrack, 'main');
|
|
3620
|
+
assert.equal(meeting.mediaProperties.audioTrack, audioTrack);
|
|
3621
|
+
assert.equal(meeting.mediaProperties.mediaDirection.sendAudio, true);
|
|
3062
3622
|
}
|
|
3623
|
+
|
|
3624
|
+
const checkVideoPublished = () => {
|
|
3625
|
+
assert.calledWith(createMuteStateStub, 'video', meeting, meeting.mediaProperties.mediaDirection);
|
|
3626
|
+
assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, videoTrack, 'main');
|
|
3627
|
+
assert.equal(meeting.mediaProperties.videoTrack, videoTrack);
|
|
3628
|
+
assert.equal(meeting.mediaProperties.mediaDirection.sendVideo, true);
|
|
3629
|
+
}
|
|
3630
|
+
|
|
3631
|
+
const checkScreenShareVideoPublished = () => {
|
|
3632
|
+
assert.calledOnce(meeting.requestScreenShareFloor);
|
|
3633
|
+
assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.publishTrack, videoShareTrack, 'slides');
|
|
3634
|
+
assert.equal(meeting.mediaProperties.shareTrack, videoShareTrack);
|
|
3635
|
+
assert.equal(meeting.mediaProperties.mediaDirection.sendShare, true);
|
|
3636
|
+
}
|
|
3637
|
+
|
|
3638
|
+
it('requests screen share floor and publishes the screen share video track', async () => {
|
|
3639
|
+
await meeting.publishTracks({screenShare: {video: videoShareTrack}});
|
|
3640
|
+
|
|
3641
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.publishTrack);
|
|
3642
|
+
checkScreenShareVideoPublished();
|
|
3643
|
+
});
|
|
3644
|
+
|
|
3645
|
+
it('creates MuteState instance and publishes the track for main audio', async () => {
|
|
3646
|
+
await meeting.publishTracks({microphone: audioTrack});
|
|
3647
|
+
|
|
3648
|
+
assert.calledOnce(createMuteStateStub);
|
|
3649
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.publishTrack);
|
|
3650
|
+
checkAudioPublished();
|
|
3651
|
+
});
|
|
3652
|
+
|
|
3653
|
+
it('creates MuteState instance and publishes the track for main video', async () => {
|
|
3654
|
+
await meeting.publishTracks({camera: videoTrack});
|
|
3655
|
+
|
|
3656
|
+
assert.calledOnce(createMuteStateStub);
|
|
3657
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.publishTrack);
|
|
3658
|
+
checkVideoPublished();
|
|
3659
|
+
});
|
|
3660
|
+
|
|
3661
|
+
it('publishes audio, video and screen share together', async () => {
|
|
3662
|
+
await meeting.publishTracks({
|
|
3663
|
+
microphone: audioTrack,
|
|
3664
|
+
camera: videoTrack,
|
|
3665
|
+
screenShare: {
|
|
3666
|
+
video: videoShareTrack,
|
|
3667
|
+
}
|
|
3668
|
+
});
|
|
3669
|
+
|
|
3670
|
+
assert.calledTwice(createMuteStateStub);
|
|
3671
|
+
assert.calledThrice(meeting.mediaProperties.webrtcMediaConnection.publishTrack);
|
|
3672
|
+
checkAudioPublished();
|
|
3673
|
+
checkVideoPublished();
|
|
3674
|
+
checkScreenShareVideoPublished();
|
|
3675
|
+
})
|
|
3063
3676
|
});
|
|
3677
|
+
|
|
3678
|
+
describe('unpublishTracks', () => {
|
|
3679
|
+
beforeEach(async () => {
|
|
3680
|
+
await meeting.publishTracks({
|
|
3681
|
+
microphone: audioTrack,
|
|
3682
|
+
camera: videoTrack,
|
|
3683
|
+
screenShare: {video: videoShareTrack}
|
|
3684
|
+
});
|
|
3685
|
+
});
|
|
3686
|
+
|
|
3687
|
+
const checkAudioUnpublished = () => {
|
|
3688
|
+
assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack, audioTrack, 'main');
|
|
3689
|
+
|
|
3690
|
+
assert.equal(meeting.mediaProperties.audioTrack, null);
|
|
3691
|
+
assert.equal(meeting.mediaProperties.mediaDirection.sendAudio, false);
|
|
3692
|
+
};
|
|
3693
|
+
|
|
3694
|
+
const checkVideoUnpublished = () => {
|
|
3695
|
+
assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack, videoTrack, 'main');
|
|
3696
|
+
|
|
3697
|
+
assert.equal(meeting.mediaProperties.videoTrack, null);
|
|
3698
|
+
assert.equal(meeting.mediaProperties.mediaDirection.sendVideo, false);
|
|
3699
|
+
}
|
|
3700
|
+
|
|
3701
|
+
const checkScreenShareVideoUnpublished = () => {
|
|
3702
|
+
assert.calledWith(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack, videoShareTrack, 'slides');
|
|
3703
|
+
|
|
3704
|
+
assert.calledOnce(meeting.requestScreenShareFloor);
|
|
3705
|
+
|
|
3706
|
+
assert.equal(meeting.mediaProperties.shareTrack, null);
|
|
3707
|
+
assert.equal(meeting.mediaProperties.mediaDirection.sendShare, false);
|
|
3708
|
+
}
|
|
3709
|
+
|
|
3710
|
+
it('fails if there is no media connection', async () => {
|
|
3711
|
+
meeting.mediaProperties.webrtcMediaConnection = undefined;
|
|
3712
|
+
await assert.isRejected(meeting.unpublishTracks([audioTrack, videoTrack, videoShareTrack]));
|
|
3713
|
+
});
|
|
3714
|
+
|
|
3715
|
+
it('un-publishes the tracks correctly (all 3 together)', async () => {
|
|
3716
|
+
await meeting.unpublishTracks([audioTrack, videoTrack, videoShareTrack]);
|
|
3717
|
+
|
|
3718
|
+
assert.calledThrice(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack);
|
|
3719
|
+
checkAudioUnpublished();
|
|
3720
|
+
checkVideoUnpublished();
|
|
3721
|
+
checkScreenShareVideoUnpublished();
|
|
3722
|
+
});
|
|
3723
|
+
|
|
3724
|
+
it('un-publishes the audio track correctly', async () => {
|
|
3725
|
+
await meeting.unpublishTracks([audioTrack]);
|
|
3726
|
+
|
|
3727
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack);
|
|
3728
|
+
checkAudioUnpublished();
|
|
3729
|
+
});
|
|
3730
|
+
|
|
3731
|
+
it('un-publishes the video track correctly', async () => {
|
|
3732
|
+
await meeting.unpublishTracks([videoTrack]);
|
|
3733
|
+
|
|
3734
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack);
|
|
3735
|
+
checkVideoUnpublished();
|
|
3736
|
+
})
|
|
3737
|
+
|
|
3738
|
+
it('un-publishes the screen share video track correctly', async () => {
|
|
3739
|
+
await meeting.unpublishTracks([videoShareTrack]);
|
|
3740
|
+
|
|
3741
|
+
assert.calledOnce(meeting.mediaProperties.webrtcMediaConnection.unpublishTrack);
|
|
3742
|
+
checkScreenShareVideoUnpublished();
|
|
3743
|
+
})
|
|
3744
|
+
})
|
|
3064
3745
|
});
|
|
3065
3746
|
});
|
|
3066
3747
|
|
|
@@ -3127,7 +3808,9 @@ describe('plugin-meetings', () => {
|
|
|
3127
3808
|
meeting.config.reconnection.enabled = true;
|
|
3128
3809
|
meeting.currentMediaStatus = {audio: true};
|
|
3129
3810
|
meeting.reconnectionManager = new ReconnectionManager(meeting);
|
|
3130
|
-
meeting.reconnectionManager.reconnect = sinon
|
|
3811
|
+
meeting.reconnectionManager.reconnect = sinon
|
|
3812
|
+
.stub()
|
|
3813
|
+
.returns(Promise.reject(new Error()));
|
|
3131
3814
|
meeting.reconnectionManager.reset = sinon.stub().returns(true);
|
|
3132
3815
|
});
|
|
3133
3816
|
|
|
@@ -3152,7 +3835,7 @@ describe('plugin-meetings', () => {
|
|
|
3152
3835
|
correlation_id: meeting.correlationId,
|
|
3153
3836
|
locus_id: meeting.locusUrl.split('/').pop(),
|
|
3154
3837
|
reason: sinon.match.any,
|
|
3155
|
-
stack: sinon.match.any
|
|
3838
|
+
stack: sinon.match.any,
|
|
3156
3839
|
}
|
|
3157
3840
|
);
|
|
3158
3841
|
});
|
|
@@ -3164,7 +3847,7 @@ describe('plugin-meetings', () => {
|
|
|
3164
3847
|
sinon.match.instanceOf(Meeting),
|
|
3165
3848
|
{file: 'meeting/index', function: 'reconnect'},
|
|
3166
3849
|
EVENTS.REQUEST_UPLOAD_LOGS,
|
|
3167
|
-
sinon.match.instanceOf(Meeting)
|
|
3850
|
+
sinon.match.instanceOf(Meeting)
|
|
3168
3851
|
);
|
|
3169
3852
|
});
|
|
3170
3853
|
|
|
@@ -3241,6 +3924,7 @@ describe('plugin-meetings', () => {
|
|
|
3241
3924
|
});
|
|
3242
3925
|
describe('#setLocalShareTrack', () => {
|
|
3243
3926
|
it('should trigger a media:ready event with local share stream', () => {
|
|
3927
|
+
let registeredListener = null;
|
|
3244
3928
|
const track = {
|
|
3245
3929
|
getSettings: sinon.stub().returns({
|
|
3246
3930
|
aspectRatio: '1.7',
|
|
@@ -3248,16 +3932,17 @@ describe('plugin-meetings', () => {
|
|
|
3248
3932
|
height: 1980,
|
|
3249
3933
|
width: 1080,
|
|
3250
3934
|
displaySurface: true,
|
|
3251
|
-
cursor: true
|
|
3252
|
-
})
|
|
3935
|
+
cursor: true,
|
|
3936
|
+
}),
|
|
3937
|
+
addEventListener: sinon.stub().callsFake((event, listener) => {
|
|
3938
|
+
registeredListener = listener;
|
|
3939
|
+
}),
|
|
3253
3940
|
};
|
|
3254
|
-
const getVideoTracks = sinon.stub().returns([track]);
|
|
3255
3941
|
|
|
3256
3942
|
meeting.mediaProperties.setLocalShareTrack = sinon.stub().returns(true);
|
|
3257
|
-
meeting.mediaProperties.shareTrack = {getVideoTracks, getSettings: track.getSettings};
|
|
3258
3943
|
meeting.stopShare = sinon.stub().resolves(true);
|
|
3259
3944
|
meeting.mediaProperties.mediaDirection = {};
|
|
3260
|
-
meeting.setLocalShareTrack(
|
|
3945
|
+
meeting.setLocalShareTrack(track);
|
|
3261
3946
|
assert.calledTwice(TriggerProxy.trigger);
|
|
3262
3947
|
assert.calledWith(
|
|
3263
3948
|
TriggerProxy.trigger,
|
|
@@ -3267,7 +3952,8 @@ describe('plugin-meetings', () => {
|
|
|
3267
3952
|
);
|
|
3268
3953
|
assert.calledOnce(meeting.mediaProperties.setLocalShareTrack);
|
|
3269
3954
|
assert.equal(meeting.mediaProperties.localStream, undefined);
|
|
3270
|
-
|
|
3955
|
+
assert.isNotNull(registeredListener);
|
|
3956
|
+
registeredListener();
|
|
3271
3957
|
assert.calledOnce(meeting.stopShare);
|
|
3272
3958
|
});
|
|
3273
3959
|
});
|
|
@@ -3281,33 +3967,51 @@ describe('plugin-meetings', () => {
|
|
|
3281
3967
|
// mock the on() method and store all the listeners
|
|
3282
3968
|
on: sinon.stub().callsFake((event, listener) => {
|
|
3283
3969
|
eventListeners[event] = listener;
|
|
3284
|
-
})
|
|
3970
|
+
}),
|
|
3285
3971
|
};
|
|
3286
3972
|
});
|
|
3287
3973
|
|
|
3288
3974
|
it('should register for all the correct RoapMediaConnection events', () => {
|
|
3289
3975
|
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[
|
|
3976
|
+
assert.isFunction(eventListeners[Event.ROAP_STARTED]);
|
|
3977
|
+
assert.isFunction(eventListeners[Event.ROAP_DONE]);
|
|
3978
|
+
assert.isFunction(eventListeners[Event.ROAP_FAILURE]);
|
|
3979
|
+
assert.isFunction(eventListeners[Event.ROAP_MESSAGE_TO_SEND]);
|
|
3980
|
+
assert.isFunction(eventListeners[Event.REMOTE_TRACK_ADDED]);
|
|
3981
|
+
assert.isFunction(eventListeners[Event.CONNECTION_STATE_CHANGED]);
|
|
3296
3982
|
});
|
|
3297
3983
|
|
|
3298
3984
|
it('should trigger a media:ready event when REMOTE_TRACK_ADDED is fired', () => {
|
|
3299
3985
|
meeting.setupMediaConnectionListeners();
|
|
3300
|
-
eventListeners[
|
|
3986
|
+
eventListeners[Event.REMOTE_TRACK_ADDED]({
|
|
3987
|
+
track: 'track',
|
|
3988
|
+
type: RemoteTrackType.AUDIO,
|
|
3989
|
+
});
|
|
3301
3990
|
assert.equal(TriggerProxy.trigger.getCall(1).args[2], 'media:ready');
|
|
3302
|
-
assert.deepEqual(TriggerProxy.trigger.getCall(1).args[3], {
|
|
3991
|
+
assert.deepEqual(TriggerProxy.trigger.getCall(1).args[3], {
|
|
3992
|
+
type: 'remoteAudio',
|
|
3993
|
+
stream: true,
|
|
3994
|
+
});
|
|
3303
3995
|
|
|
3304
|
-
eventListeners[
|
|
3996
|
+
eventListeners[Event.REMOTE_TRACK_ADDED]({
|
|
3997
|
+
track: 'track',
|
|
3998
|
+
type: RemoteTrackType.VIDEO,
|
|
3999
|
+
});
|
|
3305
4000
|
assert.equal(TriggerProxy.trigger.getCall(2).args[2], 'media:ready');
|
|
3306
|
-
assert.deepEqual(TriggerProxy.trigger.getCall(2).args[3], {
|
|
4001
|
+
assert.deepEqual(TriggerProxy.trigger.getCall(2).args[3], {
|
|
4002
|
+
type: 'remoteVideo',
|
|
4003
|
+
stream: true,
|
|
4004
|
+
});
|
|
3307
4005
|
|
|
3308
|
-
eventListeners[
|
|
4006
|
+
eventListeners[Event.REMOTE_TRACK_ADDED]({
|
|
4007
|
+
track: 'track',
|
|
4008
|
+
type: RemoteTrackType.SCREENSHARE_VIDEO,
|
|
4009
|
+
});
|
|
3309
4010
|
assert.equal(TriggerProxy.trigger.getCall(3).args[2], 'media:ready');
|
|
3310
|
-
assert.deepEqual(TriggerProxy.trigger.getCall(3).args[3], {
|
|
4011
|
+
assert.deepEqual(TriggerProxy.trigger.getCall(3).args[3], {
|
|
4012
|
+
type: 'remoteShare',
|
|
4013
|
+
stream: true,
|
|
4014
|
+
});
|
|
3311
4015
|
});
|
|
3312
4016
|
|
|
3313
4017
|
describe('should send correct metrics for ROAP_FAILURE event', () => {
|
|
@@ -3321,10 +4025,19 @@ describe('plugin-meetings', () => {
|
|
|
3321
4025
|
|
|
3322
4026
|
const checkMetricSent = (event) => {
|
|
3323
4027
|
assert.calledOnce(Metrics.postEvent);
|
|
3324
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
4028
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
4029
|
+
event,
|
|
4030
|
+
meetingId: meeting.id,
|
|
4031
|
+
data: {canProceed: false},
|
|
4032
|
+
});
|
|
3325
4033
|
};
|
|
3326
4034
|
|
|
3327
|
-
const checkBehavioralMetricSent = (
|
|
4035
|
+
const checkBehavioralMetricSent = (
|
|
4036
|
+
metricName,
|
|
4037
|
+
expectedCode,
|
|
4038
|
+
expectedReason,
|
|
4039
|
+
expectedMetadataType
|
|
4040
|
+
) => {
|
|
3328
4041
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
3329
4042
|
assert.calledWith(
|
|
3330
4043
|
Metrics.sendBehavioralMetric,
|
|
@@ -3333,65 +4046,101 @@ describe('plugin-meetings', () => {
|
|
|
3333
4046
|
code: expectedCode,
|
|
3334
4047
|
correlation_id: meeting.correlationId,
|
|
3335
4048
|
reason: expectedReason,
|
|
3336
|
-
stack: sinon.match.any
|
|
4049
|
+
stack: sinon.match.any,
|
|
3337
4050
|
},
|
|
3338
4051
|
{
|
|
3339
|
-
type: expectedMetadataType
|
|
4052
|
+
type: expectedMetadataType,
|
|
3340
4053
|
}
|
|
3341
4054
|
);
|
|
3342
4055
|
};
|
|
3343
4056
|
|
|
3344
4057
|
it('should send metrics for SdpOfferCreationError error', () => {
|
|
3345
|
-
const fakeError = new
|
|
4058
|
+
const fakeError = new Errors.SdpOfferCreationError(fakeErrorMessage, {
|
|
4059
|
+
name: fakeErrorName,
|
|
4060
|
+
cause: {name: fakeRootCauseName},
|
|
4061
|
+
});
|
|
3346
4062
|
|
|
3347
|
-
eventListeners[
|
|
4063
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3348
4064
|
|
|
3349
4065
|
checkMetricSent(eventType.LOCAL_SDP_GENERATED);
|
|
3350
|
-
checkBehavioralMetricSent(
|
|
4066
|
+
checkBehavioralMetricSent(
|
|
4067
|
+
BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
|
|
4068
|
+
Errors.ErrorCode.SdpOfferCreationError,
|
|
4069
|
+
fakeErrorMessage,
|
|
4070
|
+
fakeRootCauseName
|
|
4071
|
+
);
|
|
3351
4072
|
});
|
|
3352
4073
|
|
|
3353
4074
|
it('should send metrics for SdpOfferHandlingError error', () => {
|
|
3354
|
-
const fakeError = new
|
|
4075
|
+
const fakeError = new Errors.SdpOfferHandlingError(fakeErrorMessage, {
|
|
4076
|
+
name: fakeErrorName,
|
|
4077
|
+
cause: {name: fakeRootCauseName},
|
|
4078
|
+
});
|
|
3355
4079
|
|
|
3356
|
-
eventListeners[
|
|
4080
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3357
4081
|
|
|
3358
4082
|
checkMetricSent(eventType.REMOTE_SDP_RECEIVED);
|
|
3359
|
-
checkBehavioralMetricSent(
|
|
4083
|
+
checkBehavioralMetricSent(
|
|
4084
|
+
BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
|
|
4085
|
+
Errors.ErrorCode.SdpOfferHandlingError,
|
|
4086
|
+
fakeErrorMessage,
|
|
4087
|
+
fakeRootCauseName
|
|
4088
|
+
);
|
|
3360
4089
|
});
|
|
3361
4090
|
|
|
3362
4091
|
it('should send metrics for SdpAnswerHandlingError error', () => {
|
|
3363
|
-
const fakeError = new
|
|
4092
|
+
const fakeError = new Errors.SdpAnswerHandlingError(fakeErrorMessage, {
|
|
4093
|
+
name: fakeErrorName,
|
|
4094
|
+
cause: {name: fakeRootCauseName},
|
|
4095
|
+
});
|
|
3364
4096
|
|
|
3365
|
-
eventListeners[
|
|
4097
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3366
4098
|
|
|
3367
4099
|
checkMetricSent(eventType.REMOTE_SDP_RECEIVED);
|
|
3368
|
-
checkBehavioralMetricSent(
|
|
4100
|
+
checkBehavioralMetricSent(
|
|
4101
|
+
BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE,
|
|
4102
|
+
Errors.ErrorCode.SdpAnswerHandlingError,
|
|
4103
|
+
fakeErrorMessage,
|
|
4104
|
+
fakeRootCauseName
|
|
4105
|
+
);
|
|
3369
4106
|
});
|
|
3370
4107
|
|
|
3371
4108
|
it('should send metrics for SdpError error', () => {
|
|
3372
4109
|
// SdpError is usually without a cause
|
|
3373
|
-
const fakeError = new
|
|
4110
|
+
const fakeError = new Errors.SdpError(fakeErrorMessage, {name: fakeErrorName});
|
|
3374
4111
|
|
|
3375
|
-
eventListeners[
|
|
4112
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3376
4113
|
|
|
3377
4114
|
checkMetricSent(eventType.LOCAL_SDP_GENERATED);
|
|
3378
4115
|
// expectedMetadataType is the error name in this case
|
|
3379
|
-
checkBehavioralMetricSent(
|
|
4116
|
+
checkBehavioralMetricSent(
|
|
4117
|
+
BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE,
|
|
4118
|
+
Errors.ErrorCode.SdpError,
|
|
4119
|
+
fakeErrorMessage,
|
|
4120
|
+
fakeErrorName
|
|
4121
|
+
);
|
|
3380
4122
|
});
|
|
3381
4123
|
|
|
3382
4124
|
it('should send metrics for IceGatheringError error', () => {
|
|
3383
4125
|
// IceGatheringError is usually without a cause
|
|
3384
|
-
const fakeError = new
|
|
4126
|
+
const fakeError = new Errors.IceGatheringError(fakeErrorMessage, {
|
|
4127
|
+
name: fakeErrorName,
|
|
4128
|
+
});
|
|
3385
4129
|
|
|
3386
|
-
eventListeners[
|
|
4130
|
+
eventListeners[Event.ROAP_FAILURE](fakeError);
|
|
3387
4131
|
|
|
3388
4132
|
checkMetricSent(eventType.LOCAL_SDP_GENERATED);
|
|
3389
4133
|
// expectedMetadataType is the error name in this case
|
|
3390
|
-
checkBehavioralMetricSent(
|
|
4134
|
+
checkBehavioralMetricSent(
|
|
4135
|
+
BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE,
|
|
4136
|
+
Errors.ErrorCode.IceGatheringError,
|
|
4137
|
+
fakeErrorMessage,
|
|
4138
|
+
fakeErrorName
|
|
4139
|
+
);
|
|
3391
4140
|
});
|
|
3392
4141
|
});
|
|
3393
4142
|
|
|
3394
|
-
describe('handles
|
|
4143
|
+
describe('handles Event.ROAP_MESSAGE_TO_SEND correctly', () => {
|
|
3395
4144
|
let sendRoapOKStub;
|
|
3396
4145
|
let sendRoapMediaRequestStub;
|
|
3397
4146
|
let sendRoapAnswerStub;
|
|
@@ -3399,7 +4148,9 @@ describe('plugin-meetings', () => {
|
|
|
3399
4148
|
|
|
3400
4149
|
beforeEach(() => {
|
|
3401
4150
|
sendRoapOKStub = sinon.stub(meeting.roap, 'sendRoapOK').resolves({});
|
|
3402
|
-
sendRoapMediaRequestStub = sinon
|
|
4151
|
+
sendRoapMediaRequestStub = sinon
|
|
4152
|
+
.stub(meeting.roap, 'sendRoapMediaRequest')
|
|
4153
|
+
.resolves({});
|
|
3403
4154
|
sendRoapAnswerStub = sinon.stub(meeting.roap, 'sendRoapAnswer').resolves({});
|
|
3404
4155
|
sendRoapErrorStub = sinon.stub(meeting.roap, 'sendRoapError').resolves({});
|
|
3405
4156
|
|
|
@@ -3407,106 +4158,140 @@ describe('plugin-meetings', () => {
|
|
|
3407
4158
|
});
|
|
3408
4159
|
|
|
3409
4160
|
it('handles OK message correctly', () => {
|
|
3410
|
-
eventListeners[
|
|
4161
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
4162
|
+
roapMessage: {messageType: 'OK', seq: 1},
|
|
4163
|
+
});
|
|
3411
4164
|
|
|
3412
4165
|
assert.calledOnce(Metrics.postEvent);
|
|
3413
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
4166
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
4167
|
+
event: eventType.REMOTE_SDP_RECEIVED,
|
|
4168
|
+
meetingId: meeting.id,
|
|
4169
|
+
});
|
|
3414
4170
|
|
|
3415
4171
|
assert.calledOnce(sendRoapOKStub);
|
|
3416
|
-
assert.calledWith(sendRoapOKStub, {
|
|
4172
|
+
assert.calledWith(sendRoapOKStub, {
|
|
4173
|
+
seq: 1,
|
|
4174
|
+
mediaId: meeting.mediaId,
|
|
4175
|
+
correlationId: meeting.correlationId,
|
|
4176
|
+
});
|
|
3417
4177
|
});
|
|
3418
4178
|
|
|
3419
4179
|
it('handles OFFER message correctly', () => {
|
|
3420
|
-
eventListeners[
|
|
4180
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3421
4181
|
roapMessage: {
|
|
3422
4182
|
messageType: 'OFFER',
|
|
3423
4183
|
seq: 1,
|
|
3424
4184
|
sdp: 'fake sdp',
|
|
3425
4185
|
tieBreaker: 12345,
|
|
3426
|
-
}
|
|
4186
|
+
},
|
|
3427
4187
|
});
|
|
3428
4188
|
|
|
3429
4189
|
assert.calledOnce(Metrics.postEvent);
|
|
3430
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
4190
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
4191
|
+
event: eventType.LOCAL_SDP_GENERATED,
|
|
4192
|
+
meetingId: meeting.id,
|
|
4193
|
+
});
|
|
3431
4194
|
|
|
3432
4195
|
assert.calledOnce(sendRoapMediaRequestStub);
|
|
3433
4196
|
assert.calledWith(sendRoapMediaRequestStub, {
|
|
3434
|
-
seq: 1,
|
|
4197
|
+
seq: 1,
|
|
4198
|
+
sdp: 'fake sdp',
|
|
4199
|
+
tieBreaker: 12345,
|
|
4200
|
+
meeting,
|
|
4201
|
+
reconnect: false,
|
|
3435
4202
|
});
|
|
3436
4203
|
});
|
|
3437
4204
|
|
|
3438
4205
|
it('handles ANSWER message correctly', () => {
|
|
3439
|
-
eventListeners[
|
|
4206
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3440
4207
|
roapMessage: {
|
|
3441
4208
|
messageType: 'ANSWER',
|
|
3442
4209
|
seq: 10,
|
|
3443
4210
|
sdp: 'fake sdp answer',
|
|
3444
4211
|
tieBreaker: 12345,
|
|
3445
|
-
}
|
|
4212
|
+
},
|
|
3446
4213
|
});
|
|
3447
4214
|
|
|
3448
4215
|
assert.calledOnce(Metrics.postEvent);
|
|
3449
|
-
assert.calledWithMatch(Metrics.postEvent, {
|
|
4216
|
+
assert.calledWithMatch(Metrics.postEvent, {
|
|
4217
|
+
event: eventType.REMOTE_SDP_RECEIVED,
|
|
4218
|
+
meetingId: meeting.id,
|
|
4219
|
+
});
|
|
3450
4220
|
|
|
3451
4221
|
assert.calledOnce(sendRoapAnswerStub);
|
|
3452
4222
|
assert.calledWith(sendRoapAnswerStub, {
|
|
3453
|
-
seq: 10,
|
|
4223
|
+
seq: 10,
|
|
4224
|
+
sdp: 'fake sdp answer',
|
|
4225
|
+
mediaId: meeting.mediaId,
|
|
4226
|
+
correlationId: meeting.correlationId,
|
|
3454
4227
|
});
|
|
3455
4228
|
});
|
|
3456
4229
|
|
|
3457
4230
|
it('sends metrics if fails to send roap ANSWER message', async () => {
|
|
3458
4231
|
sendRoapAnswerStub.rejects(new Error('sending answer failed'));
|
|
3459
4232
|
|
|
3460
|
-
await eventListeners[
|
|
4233
|
+
await eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3461
4234
|
roapMessage: {
|
|
3462
4235
|
messageType: 'ANSWER',
|
|
3463
4236
|
seq: 10,
|
|
3464
4237
|
sdp: 'fake sdp answer',
|
|
3465
4238
|
tieBreaker: 12345,
|
|
3466
|
-
}
|
|
4239
|
+
},
|
|
3467
4240
|
});
|
|
3468
4241
|
await testUtils.flushPromises();
|
|
3469
4242
|
|
|
3470
4243
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
3471
|
-
assert.calledWithMatch(
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
4244
|
+
assert.calledWithMatch(
|
|
4245
|
+
Metrics.sendBehavioralMetric,
|
|
4246
|
+
BEHAVIORAL_METRICS.ROAP_ANSWER_FAILURE,
|
|
4247
|
+
{
|
|
4248
|
+
correlation_id: meeting.correlationId,
|
|
4249
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
4250
|
+
reason: 'sending answer failed',
|
|
4251
|
+
}
|
|
4252
|
+
);
|
|
3476
4253
|
});
|
|
3477
4254
|
|
|
3478
|
-
[
|
|
4255
|
+
[ErrorType.CONFLICT, ErrorType.DOUBLECONFLICT].forEach((errorType) =>
|
|
3479
4256
|
it(`handles ERROR message indicating glare condition correctly (errorType=${errorType})`, () => {
|
|
3480
|
-
eventListeners[
|
|
4257
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3481
4258
|
roapMessage: {
|
|
3482
4259
|
messageType: 'ERROR',
|
|
3483
4260
|
seq: 10,
|
|
3484
4261
|
errorType,
|
|
3485
4262
|
tieBreaker: 12345,
|
|
3486
|
-
}
|
|
4263
|
+
},
|
|
3487
4264
|
});
|
|
3488
4265
|
|
|
3489
4266
|
assert.calledOnce(Metrics.sendBehavioralMetric);
|
|
3490
|
-
assert.calledWithMatch(
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
4267
|
+
assert.calledWithMatch(
|
|
4268
|
+
Metrics.sendBehavioralMetric,
|
|
4269
|
+
BEHAVIORAL_METRICS.ROAP_GLARE_CONDITION,
|
|
4270
|
+
{
|
|
4271
|
+
correlation_id: meeting.correlationId,
|
|
4272
|
+
locus_id: meeting.locusUrl.split('/').pop(),
|
|
4273
|
+
sequence: 10,
|
|
4274
|
+
}
|
|
4275
|
+
);
|
|
3495
4276
|
|
|
3496
4277
|
assert.calledOnce(sendRoapErrorStub);
|
|
3497
4278
|
assert.calledWith(sendRoapErrorStub, {
|
|
3498
|
-
seq: 10,
|
|
4279
|
+
seq: 10,
|
|
4280
|
+
errorType,
|
|
4281
|
+
mediaId: meeting.mediaId,
|
|
4282
|
+
correlationId: meeting.correlationId,
|
|
3499
4283
|
});
|
|
3500
|
-
})
|
|
4284
|
+
})
|
|
4285
|
+
);
|
|
3501
4286
|
|
|
3502
4287
|
it('handles ERROR message indicating other errors correctly', () => {
|
|
3503
|
-
eventListeners[
|
|
4288
|
+
eventListeners[Event.ROAP_MESSAGE_TO_SEND]({
|
|
3504
4289
|
roapMessage: {
|
|
3505
4290
|
messageType: 'ERROR',
|
|
3506
4291
|
seq: 10,
|
|
3507
|
-
errorType:
|
|
4292
|
+
errorType: ErrorType.FAILED,
|
|
3508
4293
|
tieBreaker: 12345,
|
|
3509
|
-
}
|
|
4294
|
+
},
|
|
3510
4295
|
});
|
|
3511
4296
|
|
|
3512
4297
|
assert.notCalled(Metrics.sendBehavioralMetric);
|
|
@@ -3514,9 +4299,9 @@ describe('plugin-meetings', () => {
|
|
|
3514
4299
|
assert.calledOnce(sendRoapErrorStub);
|
|
3515
4300
|
assert.calledWith(sendRoapErrorStub, {
|
|
3516
4301
|
seq: 10,
|
|
3517
|
-
errorType:
|
|
4302
|
+
errorType: ErrorType.FAILED,
|
|
3518
4303
|
mediaId: meeting.mediaId,
|
|
3519
|
-
correlationId: meeting.correlationId
|
|
4304
|
+
correlationId: meeting.correlationId,
|
|
3520
4305
|
});
|
|
3521
4306
|
});
|
|
3522
4307
|
});
|
|
@@ -3550,6 +4335,83 @@ describe('plugin-meetings', () => {
|
|
|
3550
4335
|
);
|
|
3551
4336
|
done();
|
|
3552
4337
|
});
|
|
4338
|
+
|
|
4339
|
+
it('listens to the breakouts changed event', () => {
|
|
4340
|
+
meeting.breakouts.updateBreakoutSessions = sinon.stub();
|
|
4341
|
+
|
|
4342
|
+
const payload = 'payload';
|
|
4343
|
+
|
|
4344
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'SELF_MEETING_BREAKOUTS_CHANGED', payload);
|
|
4345
|
+
|
|
4346
|
+
assert.calledOnceWithExactly(meeting.breakouts.updateBreakoutSessions, payload);
|
|
4347
|
+
assert.calledWith(
|
|
4348
|
+
TriggerProxy.trigger,
|
|
4349
|
+
meeting,
|
|
4350
|
+
{file: 'meeting/index', function: 'setUpLocusInfoSelfListener'},
|
|
4351
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
4352
|
+
);
|
|
4353
|
+
});
|
|
4354
|
+
});
|
|
4355
|
+
|
|
4356
|
+
describe('#setUpBreakoutsListener', () => {
|
|
4357
|
+
it('listens to the closing event from breakouts and triggers the closing event', () => {
|
|
4358
|
+
TriggerProxy.trigger.reset();
|
|
4359
|
+
meeting.breakouts.trigger('BREAKOUTS_CLOSING');
|
|
4360
|
+
|
|
4361
|
+
assert.calledWith(
|
|
4362
|
+
TriggerProxy.trigger,
|
|
4363
|
+
meeting,
|
|
4364
|
+
{file: 'meeting/index', function: 'setUpBreakoutsListener'},
|
|
4365
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_CLOSING
|
|
4366
|
+
);
|
|
4367
|
+
});
|
|
4368
|
+
|
|
4369
|
+
it('listens to the message event from breakouts and triggers the message event', () => {
|
|
4370
|
+
TriggerProxy.trigger.reset();
|
|
4371
|
+
|
|
4372
|
+
const messageEvent = 'message';
|
|
4373
|
+
|
|
4374
|
+
meeting.breakouts.trigger('MESSAGE', messageEvent);
|
|
4375
|
+
|
|
4376
|
+
assert.calledWith(
|
|
4377
|
+
TriggerProxy.trigger,
|
|
4378
|
+
meeting,
|
|
4379
|
+
{file: 'meeting/index', function: 'setUpBreakoutsListener'},
|
|
4380
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_MESSAGE,
|
|
4381
|
+
messageEvent
|
|
4382
|
+
);
|
|
4383
|
+
});
|
|
4384
|
+
|
|
4385
|
+
it('listens to the members update event from breakouts and triggers the breakouts update event', () => {
|
|
4386
|
+
TriggerProxy.trigger.reset();
|
|
4387
|
+
meeting.breakouts.trigger('MEMBERS_UPDATE');
|
|
4388
|
+
|
|
4389
|
+
assert.calledWith(
|
|
4390
|
+
TriggerProxy.trigger,
|
|
4391
|
+
meeting,
|
|
4392
|
+
{file: 'meeting/index', function: 'setUpBreakoutsListener'},
|
|
4393
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
4394
|
+
);
|
|
4395
|
+
});
|
|
4396
|
+
});
|
|
4397
|
+
|
|
4398
|
+
describe('#setupLocusControlsListener', () => {
|
|
4399
|
+
it('listens to the locus breakouts update event', () => {
|
|
4400
|
+
const locus = {
|
|
4401
|
+
breakout: 'breakout'
|
|
4402
|
+
};
|
|
4403
|
+
|
|
4404
|
+
meeting.breakouts.updateBreakout = sinon.stub();
|
|
4405
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'CONTROLS_MEETING_BREAKOUT_UPDATED', locus);
|
|
4406
|
+
|
|
4407
|
+
assert.calledOnceWithExactly(meeting.breakouts.updateBreakout, locus.breakout);
|
|
4408
|
+
assert.calledWith(
|
|
4409
|
+
TriggerProxy.trigger,
|
|
4410
|
+
meeting,
|
|
4411
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
4412
|
+
EVENT_TRIGGERS.MEETING_BREAKOUTS_UPDATE
|
|
4413
|
+
);
|
|
4414
|
+
});
|
|
3553
4415
|
});
|
|
3554
4416
|
|
|
3555
4417
|
describe('#setUpLocusUrlListener', () => {
|
|
@@ -3557,21 +4419,57 @@ describe('plugin-meetings', () => {
|
|
|
3557
4419
|
const newLocusUrl = 'newLocusUrl/12345';
|
|
3558
4420
|
|
|
3559
4421
|
meeting.members = {locusUrlUpdate: sinon.stub().returns(Promise.resolve(test1))};
|
|
4422
|
+
meeting.recordingController = {setLocusUrl: sinon.stub().returns(undefined)};
|
|
4423
|
+
meeting.controlsOptionsManager = {setLocusUrl: sinon.stub().returns(undefined)};
|
|
4424
|
+
|
|
4425
|
+
meeting.breakouts.locusUrlUpdate = sinon.stub();
|
|
3560
4426
|
|
|
3561
4427
|
meeting.locusInfo.emit({function: 'test', file: 'test'}, 'LOCUS_INFO_UPDATE_URL', newLocusUrl);
|
|
3562
4428
|
assert.calledWith(
|
|
3563
4429
|
meeting.members.locusUrlUpdate,
|
|
3564
4430
|
newLocusUrl
|
|
3565
4431
|
);
|
|
4432
|
+
assert.calledOnceWithExactly(meeting.breakouts.locusUrlUpdate, newLocusUrl);
|
|
4433
|
+
assert.calledWith(meeting.members.locusUrlUpdate, newLocusUrl);
|
|
4434
|
+
assert.calledWith(meeting.recordingController.setLocusUrl, newLocusUrl);
|
|
4435
|
+
assert.calledWith(meeting.controlsOptionsManager.setLocusUrl, newLocusUrl);
|
|
3566
4436
|
assert.equal(meeting.locusUrl, newLocusUrl);
|
|
3567
4437
|
assert(meeting.locusId, '12345');
|
|
3568
4438
|
done();
|
|
3569
4439
|
});
|
|
3570
4440
|
});
|
|
4441
|
+
|
|
4442
|
+
describe('#setUpLocusServicesListener', () => {
|
|
4443
|
+
it('listens to the locus services update event', (done) => {
|
|
4444
|
+
const newLocusServices = {
|
|
4445
|
+
services: {
|
|
4446
|
+
record: {
|
|
4447
|
+
url: 'url',
|
|
4448
|
+
}
|
|
4449
|
+
},
|
|
4450
|
+
};
|
|
4451
|
+
|
|
4452
|
+
meeting.recordingController = {setServiceUrl: sinon.stub().returns(undefined), setSessionId: sinon.stub().returns(undefined)};
|
|
4453
|
+
|
|
4454
|
+
meeting.locusInfo.emit(
|
|
4455
|
+
{function: 'test', file: 'test'},
|
|
4456
|
+
'LINKS_SERVICES',
|
|
4457
|
+
newLocusServices
|
|
4458
|
+
);
|
|
4459
|
+
|
|
4460
|
+
assert.calledWith(meeting.recordingController.setServiceUrl, newLocusServices.services.record.url);
|
|
4461
|
+
assert.calledOnce(meeting.recordingController.setSessionId);
|
|
4462
|
+
done();
|
|
4463
|
+
});
|
|
4464
|
+
});
|
|
3571
4465
|
describe('#setUpLocusInfoMediaInactiveListener', () => {
|
|
3572
4466
|
it('listens to disconnect due to un activity ', (done) => {
|
|
3573
4467
|
TriggerProxy.trigger.reset();
|
|
3574
|
-
meeting.locusInfo.emit(
|
|
4468
|
+
meeting.locusInfo.emit(
|
|
4469
|
+
{function: 'test', file: 'test'},
|
|
4470
|
+
EVENTS.DISCONNECT_DUE_TO_INACTIVITY,
|
|
4471
|
+
{reason: 'inactive'}
|
|
4472
|
+
);
|
|
3575
4473
|
assert.calledTwice(TriggerProxy.trigger);
|
|
3576
4474
|
|
|
3577
4475
|
assert.calledWith(
|
|
@@ -3598,7 +4496,11 @@ describe('plugin-meetings', () => {
|
|
|
3598
4496
|
sinon.stub(meeting, 'reconnect');
|
|
3599
4497
|
|
|
3600
4498
|
meeting.config.reconnection.autoRejoin = true;
|
|
3601
|
-
meeting.locusInfo.emit(
|
|
4499
|
+
meeting.locusInfo.emit(
|
|
4500
|
+
{function: 'test', file: 'test'},
|
|
4501
|
+
EVENTS.DISCONNECT_DUE_TO_INACTIVITY,
|
|
4502
|
+
{reason: 'inactive'}
|
|
4503
|
+
);
|
|
3602
4504
|
assert.calledOnce(TriggerProxy.trigger);
|
|
3603
4505
|
|
|
3604
4506
|
assert.calledWith(
|
|
@@ -3623,7 +4525,10 @@ describe('plugin-meetings', () => {
|
|
|
3623
4525
|
sinon.stub(meeting.reconnectionManager, 'cleanUp');
|
|
3624
4526
|
sinon.spy(MeetingUtil, 'cleanUp');
|
|
3625
4527
|
|
|
3626
|
-
meeting.locusInfo.emit({function: 'test', file: 'test'}, EVENTS.DESTROY_MEETING, {
|
|
4528
|
+
meeting.locusInfo.emit({function: 'test', file: 'test'}, EVENTS.DESTROY_MEETING, {
|
|
4529
|
+
shouldLeave: false,
|
|
4530
|
+
reason: 'ended',
|
|
4531
|
+
});
|
|
3627
4532
|
assert.calledOnce(TriggerProxy.trigger);
|
|
3628
4533
|
assert.calledOnce(MeetingUtil.cleanUp);
|
|
3629
4534
|
assert.calledWith(
|
|
@@ -3631,12 +4536,12 @@ describe('plugin-meetings', () => {
|
|
|
3631
4536
|
meeting,
|
|
3632
4537
|
{
|
|
3633
4538
|
file: 'meeting/index',
|
|
3634
|
-
function: 'setUpLocusInfoMeetingListener'
|
|
4539
|
+
function: 'setUpLocusInfoMeetingListener',
|
|
3635
4540
|
},
|
|
3636
4541
|
EVENTS.DESTROY_MEETING,
|
|
3637
4542
|
{
|
|
3638
4543
|
reason: 'ended',
|
|
3639
|
-
meetingId: meeting.id
|
|
4544
|
+
meetingId: meeting.id,
|
|
3640
4545
|
}
|
|
3641
4546
|
);
|
|
3642
4547
|
done();
|
|
@@ -3656,22 +4561,36 @@ describe('plugin-meetings', () => {
|
|
|
3656
4561
|
sandbox = null;
|
|
3657
4562
|
});
|
|
3658
4563
|
|
|
3659
|
-
describe('#
|
|
3660
|
-
it('should have #
|
|
3661
|
-
assert.exists(meeting.
|
|
4564
|
+
describe('#releaseScreenShareFloor', () => {
|
|
4565
|
+
it('should have #releaseScreenShareFloor', () => {
|
|
4566
|
+
assert.exists(meeting.releaseScreenShareFloor);
|
|
3662
4567
|
});
|
|
3663
4568
|
beforeEach(() => {
|
|
3664
|
-
meeting.
|
|
4569
|
+
meeting.selfId = 'some self id';
|
|
4570
|
+
meeting.locusInfo.mediaShares = [
|
|
4571
|
+
{name: 'content', url: url1, floor: {beneficiary: {id: meeting.selfId}}},
|
|
4572
|
+
];
|
|
3665
4573
|
meeting.locusInfo.self = {url: url2};
|
|
4574
|
+
meeting.mediaProperties = {mediaDirection: {sendShare: true}};
|
|
3666
4575
|
meeting.meetingRequest.changeMeetingFloor = sinon.stub().returns(Promise.resolve());
|
|
3667
4576
|
});
|
|
3668
|
-
it('should call
|
|
3669
|
-
const share = meeting.
|
|
4577
|
+
it('should call changeMeetingFloor()', async () => {
|
|
4578
|
+
const share = meeting.releaseScreenShareFloor();
|
|
3670
4579
|
|
|
3671
4580
|
assert.exists(share.then);
|
|
3672
4581
|
await share;
|
|
3673
4582
|
assert.calledOnce(meeting.meetingRequest.changeMeetingFloor);
|
|
3674
4583
|
});
|
|
4584
|
+
it('should not call changeMeetingFloor() if someone else already has the floor', async () => {
|
|
4585
|
+
// change selfId so that it doesn't match the beneficiary id from meeting.locusInfo.mediaShares
|
|
4586
|
+
meeting.selfId = 'new self id';
|
|
4587
|
+
|
|
4588
|
+
const share = meeting.releaseScreenShareFloor();
|
|
4589
|
+
|
|
4590
|
+
assert.exists(share.then);
|
|
4591
|
+
await share;
|
|
4592
|
+
assert.notCalled(meeting.meetingRequest.changeMeetingFloor);
|
|
4593
|
+
});
|
|
3675
4594
|
});
|
|
3676
4595
|
|
|
3677
4596
|
describe('#setSipUri', () => {
|
|
@@ -3753,8 +4672,8 @@ describe('plugin-meetings', () => {
|
|
|
3753
4672
|
permissionToken: 'abc',
|
|
3754
4673
|
sipMeetingUri: test1,
|
|
3755
4674
|
sipUrl: test1,
|
|
3756
|
-
owner: test2
|
|
3757
|
-
}
|
|
4675
|
+
owner: test2,
|
|
4676
|
+
},
|
|
3758
4677
|
};
|
|
3759
4678
|
|
|
3760
4679
|
meeting.parseMeetingInfo(FAKE_MEETING_INFO);
|
|
@@ -3765,7 +4684,7 @@ describe('plugin-meetings', () => {
|
|
|
3765
4684
|
meetingNumber: '12345',
|
|
3766
4685
|
meetingJoinUrl: url2,
|
|
3767
4686
|
owner: test2,
|
|
3768
|
-
permissionToken: 'abc'
|
|
4687
|
+
permissionToken: 'abc',
|
|
3769
4688
|
};
|
|
3770
4689
|
|
|
3771
4690
|
checkParseMeetingInfo(expectedInfoToParse);
|
|
@@ -3779,8 +4698,8 @@ describe('plugin-meetings', () => {
|
|
|
3779
4698
|
info: {
|
|
3780
4699
|
webExMeetingId: 'locusMeetingId',
|
|
3781
4700
|
sipUri: 'locusSipUri',
|
|
3782
|
-
owner: 'locusOwner'
|
|
3783
|
-
}
|
|
4701
|
+
owner: 'locusOwner',
|
|
4702
|
+
},
|
|
3784
4703
|
};
|
|
3785
4704
|
const FAKE_MEETING_INFO = {
|
|
3786
4705
|
body: {
|
|
@@ -3791,8 +4710,8 @@ describe('plugin-meetings', () => {
|
|
|
3791
4710
|
permissionToken: 'abc',
|
|
3792
4711
|
sipMeetingUri: test1,
|
|
3793
4712
|
sipUrl: test1,
|
|
3794
|
-
owner: test2
|
|
3795
|
-
}
|
|
4713
|
+
owner: test2,
|
|
4714
|
+
},
|
|
3796
4715
|
};
|
|
3797
4716
|
|
|
3798
4717
|
meeting.parseMeetingInfo(FAKE_MEETING_INFO, FAKE_LOCUS_MEETING);
|
|
@@ -3803,7 +4722,7 @@ describe('plugin-meetings', () => {
|
|
|
3803
4722
|
meetingNumber: 'locusMeetingId',
|
|
3804
4723
|
meetingJoinUrl: url2,
|
|
3805
4724
|
owner: 'locusOwner',
|
|
3806
|
-
permissionToken: 'abc'
|
|
4725
|
+
permissionToken: 'abc',
|
|
3807
4726
|
};
|
|
3808
4727
|
|
|
3809
4728
|
checkParseMeetingInfo(expectedInfoToParse);
|
|
@@ -3820,8 +4739,8 @@ describe('plugin-meetings', () => {
|
|
|
3820
4739
|
permissionToken: 'abc',
|
|
3821
4740
|
sipMeetingUri: test1,
|
|
3822
4741
|
sipUrl: test1,
|
|
3823
|
-
owner: test2
|
|
3824
|
-
}
|
|
4742
|
+
owner: test2,
|
|
4743
|
+
},
|
|
3825
4744
|
};
|
|
3826
4745
|
|
|
3827
4746
|
meeting.parseMeetingInfo(FAKE_MEETING_INFO);
|
|
@@ -3832,7 +4751,7 @@ describe('plugin-meetings', () => {
|
|
|
3832
4751
|
meetingNumber: '12345',
|
|
3833
4752
|
meetingJoinUrl: url2,
|
|
3834
4753
|
owner: test2,
|
|
3835
|
-
permissionToken: 'abc'
|
|
4754
|
+
permissionToken: 'abc',
|
|
3836
4755
|
};
|
|
3837
4756
|
|
|
3838
4757
|
checkParseMeetingInfo(expectedInfoToParse);
|
|
@@ -3850,8 +4769,8 @@ describe('plugin-meetings', () => {
|
|
|
3850
4769
|
permissionToken: 'abc',
|
|
3851
4770
|
sipMeetingUri: test1,
|
|
3852
4771
|
sipUrl: test1,
|
|
3853
|
-
owner: test2
|
|
3854
|
-
}
|
|
4772
|
+
owner: test2,
|
|
4773
|
+
},
|
|
3855
4774
|
};
|
|
3856
4775
|
|
|
3857
4776
|
meeting.parseMeetingInfo(FAKE_MEETING_INFO, FAKE_STRING_DESTINATION);
|
|
@@ -3862,7 +4781,7 @@ describe('plugin-meetings', () => {
|
|
|
3862
4781
|
meetingNumber: '12345',
|
|
3863
4782
|
meetingJoinUrl: url2,
|
|
3864
4783
|
owner: test2,
|
|
3865
|
-
permissionToken: 'abc'
|
|
4784
|
+
permissionToken: 'abc',
|
|
3866
4785
|
};
|
|
3867
4786
|
|
|
3868
4787
|
checkParseMeetingInfo(expectedInfoToParse);
|
|
@@ -3878,7 +4797,11 @@ describe('plugin-meetings', () => {
|
|
|
3878
4797
|
meeting.type = 'CALL';
|
|
3879
4798
|
meeting.parseLocus({url: url1, participants: [{id: uuid1}], self: {id: uuid2}});
|
|
3880
4799
|
assert.calledOnce(meeting.setLocus);
|
|
3881
|
-
assert.calledWith(meeting.setLocus, {
|
|
4800
|
+
assert.calledWith(meeting.setLocus, {
|
|
4801
|
+
url: url1,
|
|
4802
|
+
participants: [{id: uuid1}],
|
|
4803
|
+
self: {id: uuid2},
|
|
4804
|
+
});
|
|
3882
4805
|
assert.calledOnce(MeetingUtil.getLocusPartner);
|
|
3883
4806
|
assert.calledWith(MeetingUtil.getLocusPartner, [{id: uuid1}], {id: uuid2});
|
|
3884
4807
|
assert.deepEqual(meeting.partner, {person: {sipUrl: uuid3}});
|
|
@@ -3927,7 +4850,7 @@ describe('plugin-meetings', () => {
|
|
|
3927
4850
|
meeting,
|
|
3928
4851
|
{
|
|
3929
4852
|
file: 'meeting/index',
|
|
3930
|
-
function: 'setUpLocusInfoAssignHostListener'
|
|
4853
|
+
function: 'setUpLocusInfoAssignHostListener',
|
|
3931
4854
|
},
|
|
3932
4855
|
'meeting:actionsUpdate',
|
|
3933
4856
|
meeting.inMeetingActions.get()
|
|
@@ -3946,30 +4869,47 @@ describe('plugin-meetings', () => {
|
|
|
3946
4869
|
let inMeetingActionsSetSpy;
|
|
3947
4870
|
let canUserLockSpy;
|
|
3948
4871
|
let canUserUnlockSpy;
|
|
3949
|
-
let
|
|
4872
|
+
let canUserStartSpy;
|
|
3950
4873
|
let canUserStopSpy;
|
|
3951
4874
|
let canUserPauseSpy;
|
|
3952
4875
|
let canUserResumeSpy;
|
|
4876
|
+
let canSetMuteOnEntrySpy;
|
|
4877
|
+
let canUnsetMuteOnEntrySpy;
|
|
4878
|
+
let canSetDisallowUnmuteSpy;
|
|
4879
|
+
let canUnsetDisallowUnmuteSpy;
|
|
3953
4880
|
let canUserRaiseHandSpy;
|
|
3954
4881
|
let bothLeaveAndEndMeetingAvailableSpy;
|
|
3955
4882
|
let canUserLowerAllHandsSpy;
|
|
3956
4883
|
let canUserLowerSomeoneElsesHandSpy;
|
|
3957
4884
|
let waitingForOthersToJoinSpy;
|
|
4885
|
+
let handleDataChannelUrlChangeSpy;
|
|
4886
|
+
let canEnableReactionsSpy;
|
|
4887
|
+
let canSendReactionsSpy;
|
|
3958
4888
|
|
|
3959
4889
|
beforeEach(() => {
|
|
3960
4890
|
locusInfoOnSpy = sinon.spy(meeting.locusInfo, 'on');
|
|
3961
4891
|
canUserLockSpy = sinon.spy(MeetingUtil, 'canUserLock');
|
|
3962
4892
|
canUserUnlockSpy = sinon.spy(MeetingUtil, 'canUserUnlock');
|
|
3963
|
-
|
|
3964
|
-
canUserStopSpy = sinon.spy(
|
|
3965
|
-
canUserPauseSpy = sinon.spy(
|
|
3966
|
-
canUserResumeSpy = sinon.spy(
|
|
4893
|
+
canUserStartSpy = sinon.spy(RecordingUtil, 'canUserStart');
|
|
4894
|
+
canUserStopSpy = sinon.spy(RecordingUtil, 'canUserStop');
|
|
4895
|
+
canUserPauseSpy = sinon.spy(RecordingUtil, 'canUserPause');
|
|
4896
|
+
canUserResumeSpy = sinon.spy(RecordingUtil, 'canUserResume');
|
|
4897
|
+
canSetMuteOnEntrySpy = sinon.spy(ControlsOptionsUtil, 'canSetMuteOnEntry');
|
|
4898
|
+
canUnsetMuteOnEntrySpy = sinon.spy(ControlsOptionsUtil, 'canUnsetMuteOnEntry');
|
|
4899
|
+
canSetDisallowUnmuteSpy = sinon.spy(ControlsOptionsUtil, 'canSetDisallowUnmute');
|
|
4900
|
+
canUnsetDisallowUnmuteSpy = sinon.spy(ControlsOptionsUtil, 'canUnsetDisallowUnmute');
|
|
3967
4901
|
inMeetingActionsSetSpy = sinon.spy(meeting.inMeetingActions, 'set');
|
|
3968
4902
|
canUserRaiseHandSpy = sinon.spy(MeetingUtil, 'canUserRaiseHand');
|
|
3969
4903
|
canUserLowerAllHandsSpy = sinon.spy(MeetingUtil, 'canUserLowerAllHands');
|
|
3970
|
-
bothLeaveAndEndMeetingAvailableSpy = sinon.spy(
|
|
4904
|
+
bothLeaveAndEndMeetingAvailableSpy = sinon.spy(
|
|
4905
|
+
MeetingUtil,
|
|
4906
|
+
'bothLeaveAndEndMeetingAvailable'
|
|
4907
|
+
);
|
|
3971
4908
|
canUserLowerSomeoneElsesHandSpy = sinon.spy(MeetingUtil, 'canUserLowerSomeoneElsesHand');
|
|
3972
4909
|
waitingForOthersToJoinSpy = sinon.spy(MeetingUtil, 'waitingForOthersToJoin');
|
|
4910
|
+
handleDataChannelUrlChangeSpy = sinon.spy(meeting, 'handleDataChannelUrlChange');
|
|
4911
|
+
canEnableReactionsSpy = sinon.spy(MeetingUtil, 'canEnableReactions');
|
|
4912
|
+
canSendReactionsSpy = sinon.spy(MeetingUtil, 'canSendReactions');
|
|
3973
4913
|
});
|
|
3974
4914
|
|
|
3975
4915
|
afterEach(() => {
|
|
@@ -3978,7 +4918,6 @@ describe('plugin-meetings', () => {
|
|
|
3978
4918
|
waitingForOthersToJoinSpy.restore();
|
|
3979
4919
|
});
|
|
3980
4920
|
|
|
3981
|
-
|
|
3982
4921
|
it('registers the correct MEETING_INFO_UPDATED event', () => {
|
|
3983
4922
|
meeting.setUpLocusInfoMeetingInfoListener();
|
|
3984
4923
|
|
|
@@ -3991,30 +4930,38 @@ describe('plugin-meetings', () => {
|
|
|
3991
4930
|
|
|
3992
4931
|
const payload = {
|
|
3993
4932
|
info: {
|
|
3994
|
-
userDisplayHints: ['LOCK_CONTROL_UNLOCK']
|
|
3995
|
-
|
|
4933
|
+
userDisplayHints: ['LOCK_CONTROL_UNLOCK'],
|
|
4934
|
+
datachannelUrl: 'some url',
|
|
4935
|
+
},
|
|
3996
4936
|
};
|
|
3997
4937
|
|
|
3998
4938
|
callback(payload);
|
|
3999
4939
|
|
|
4000
4940
|
assert.calledWith(canUserLockSpy, payload.info.userDisplayHints);
|
|
4001
4941
|
assert.calledWith(canUserUnlockSpy, payload.info.userDisplayHints);
|
|
4002
|
-
assert.calledWith(
|
|
4942
|
+
assert.calledWith(canUserStartSpy, payload.info.userDisplayHints);
|
|
4003
4943
|
assert.calledWith(canUserStopSpy, payload.info.userDisplayHints);
|
|
4004
4944
|
assert.calledWith(canUserPauseSpy, payload.info.userDisplayHints);
|
|
4005
4945
|
assert.calledWith(canUserResumeSpy, payload.info.userDisplayHints);
|
|
4946
|
+
assert.calledWith(canSetMuteOnEntrySpy, payload.info.userDisplayHints);
|
|
4947
|
+
assert.calledWith(canUnsetMuteOnEntrySpy, payload.info.userDisplayHints);
|
|
4948
|
+
assert.calledWith(canSetDisallowUnmuteSpy, payload.info.userDisplayHints);
|
|
4949
|
+
assert.calledWith(canUnsetDisallowUnmuteSpy, payload.info.userDisplayHints);
|
|
4006
4950
|
assert.calledWith(canUserRaiseHandSpy, payload.info.userDisplayHints);
|
|
4007
4951
|
assert.calledWith(bothLeaveAndEndMeetingAvailableSpy, payload.info.userDisplayHints);
|
|
4008
4952
|
assert.calledWith(canUserLowerAllHandsSpy, payload.info.userDisplayHints);
|
|
4009
4953
|
assert.calledWith(canUserLowerSomeoneElsesHandSpy, payload.info.userDisplayHints);
|
|
4010
4954
|
assert.calledWith(waitingForOthersToJoinSpy, payload.info.userDisplayHints);
|
|
4955
|
+
assert.calledWith(handleDataChannelUrlChangeSpy, payload.info.datachannelUrl);
|
|
4956
|
+
assert.calledWith(canEnableReactionsSpy, null, payload.info.userDisplayHints);
|
|
4957
|
+
assert.calledWith(canSendReactionsSpy, null, payload.info.userDisplayHints);
|
|
4011
4958
|
|
|
4012
4959
|
assert.calledWith(
|
|
4013
4960
|
TriggerProxy.trigger,
|
|
4014
4961
|
meeting,
|
|
4015
4962
|
{
|
|
4016
4963
|
file: 'meeting/index',
|
|
4017
|
-
function: 'setUpLocusInfoMeetingInfoListener'
|
|
4964
|
+
function: 'setUpLocusInfoMeetingInfoListener',
|
|
4018
4965
|
},
|
|
4019
4966
|
'meeting:actionsUpdate',
|
|
4020
4967
|
meeting.inMeetingActions.get()
|
|
@@ -4028,6 +4975,123 @@ describe('plugin-meetings', () => {
|
|
|
4028
4975
|
});
|
|
4029
4976
|
});
|
|
4030
4977
|
|
|
4978
|
+
describe('#handleDataChannelUrlChange', () => {
|
|
4979
|
+
let updateLLMConnectionSpy;
|
|
4980
|
+
|
|
4981
|
+
beforeEach(() => {
|
|
4982
|
+
updateLLMConnectionSpy = sinon.spy(meeting, 'updateLLMConnection');
|
|
4983
|
+
});
|
|
4984
|
+
|
|
4985
|
+
const check = async (url, expectedCalled) => {
|
|
4986
|
+
meeting.handleDataChannelUrlChange(url);
|
|
4987
|
+
|
|
4988
|
+
assert.notCalled(updateLLMConnectionSpy);
|
|
4989
|
+
|
|
4990
|
+
await testUtils.waitUntil(0);
|
|
4991
|
+
|
|
4992
|
+
if (expectedCalled) {
|
|
4993
|
+
assert.calledWith(updateLLMConnectionSpy);
|
|
4994
|
+
} else {
|
|
4995
|
+
assert.notCalled(updateLLMConnectionSpy);
|
|
4996
|
+
}
|
|
4997
|
+
};
|
|
4998
|
+
|
|
4999
|
+
it('calls deferred updateLLMConnection if datachannelURL is set and the enableAutomaticLLM is true', async () => {
|
|
5000
|
+
meeting.config.enableAutomaticLLM = true;
|
|
5001
|
+
check('some url', true);
|
|
5002
|
+
});
|
|
5003
|
+
|
|
5004
|
+
it('does not call updateLLMConnection if datachannelURL is undefined', async () => {
|
|
5005
|
+
meeting.config.enableAutomaticLLM = true;
|
|
5006
|
+
check(undefined, false);
|
|
5007
|
+
});
|
|
5008
|
+
|
|
5009
|
+
it('does not call updateLLMConnection if enableAutomaticLLM is false', async () => {
|
|
5010
|
+
check('some url', false);
|
|
5011
|
+
});
|
|
5012
|
+
});
|
|
5013
|
+
|
|
5014
|
+
describe('#updateLLMConnection', () => {
|
|
5015
|
+
beforeEach(() => {
|
|
5016
|
+
webex.internal.llm.isConnected = sinon.stub().returns(false);
|
|
5017
|
+
webex.internal.llm.getLocusUrl = sinon.stub();
|
|
5018
|
+
webex.internal.llm.registerAndConnect = sinon
|
|
5019
|
+
.stub()
|
|
5020
|
+
.returns(Promise.resolve('something'));
|
|
5021
|
+
webex.internal.llm.disconnectLLM = sinon.stub().returns(Promise.resolve());
|
|
5022
|
+
});
|
|
5023
|
+
|
|
5024
|
+
it('does not connect if the call is not joined yet', async () => {
|
|
5025
|
+
meeting.joinedWith = {state: 'any other state'};
|
|
5026
|
+
webex.internal.llm.getLocusUrl.returns('a url');
|
|
5027
|
+
|
|
5028
|
+
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
5029
|
+
|
|
5030
|
+
const result = await meeting.updateLLMConnection();
|
|
5031
|
+
|
|
5032
|
+
assert.notCalled(webex.internal.llm.registerAndConnect);
|
|
5033
|
+
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
5034
|
+
assert.equal(result, undefined);
|
|
5035
|
+
});
|
|
5036
|
+
|
|
5037
|
+
it('returns undefined if llm is already connected and the locus url is unchanged', async () => {
|
|
5038
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
5039
|
+
webex.internal.llm.isConnected.returns(true);
|
|
5040
|
+
webex.internal.llm.getLocusUrl.returns('a url');
|
|
5041
|
+
|
|
5042
|
+
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
5043
|
+
|
|
5044
|
+
const result = await meeting.updateLLMConnection();
|
|
5045
|
+
|
|
5046
|
+
assert.notCalled(webex.internal.llm.registerAndConnect);
|
|
5047
|
+
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
5048
|
+
assert.equal(result, undefined);
|
|
5049
|
+
});
|
|
5050
|
+
|
|
5051
|
+
it('connects if not already connected', async () => {
|
|
5052
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
5053
|
+
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
5054
|
+
|
|
5055
|
+
const result = await meeting.updateLLMConnection();
|
|
5056
|
+
|
|
5057
|
+
assert.notCalled(webex.internal.llm.disconnectLLM);
|
|
5058
|
+
assert.calledWith(webex.internal.llm.registerAndConnect, 'a url', 'a datachannel url');
|
|
5059
|
+
assert.equal(result, 'something');
|
|
5060
|
+
});
|
|
5061
|
+
|
|
5062
|
+
it('disconnects if first if the locus url has changed', async () => {
|
|
5063
|
+
meeting.joinedWith = {state: 'JOINED'};
|
|
5064
|
+
webex.internal.llm.isConnected.returns(true);
|
|
5065
|
+
webex.internal.llm.getLocusUrl.returns('a url');
|
|
5066
|
+
|
|
5067
|
+
meeting.locusInfo = {url: 'a different url', info: {datachannelUrl: 'a datachannel url'}};
|
|
5068
|
+
|
|
5069
|
+
const result = await meeting.updateLLMConnection();
|
|
5070
|
+
|
|
5071
|
+
assert.calledWith(webex.internal.llm.disconnectLLM);
|
|
5072
|
+
assert.calledWith(
|
|
5073
|
+
webex.internal.llm.registerAndConnect,
|
|
5074
|
+
'a different url',
|
|
5075
|
+
'a datachannel url'
|
|
5076
|
+
);
|
|
5077
|
+
assert.equal(result, 'something');
|
|
5078
|
+
});
|
|
5079
|
+
|
|
5080
|
+
it('disconnects when the state is not JOINED', async () => {
|
|
5081
|
+
meeting.joinedWith = {state: 'any other state'};
|
|
5082
|
+
webex.internal.llm.isConnected.returns(true);
|
|
5083
|
+
webex.internal.llm.getLocusUrl.returns('a url');
|
|
5084
|
+
|
|
5085
|
+
meeting.locusInfo = {url: 'a url', info: {datachannelUrl: 'a datachannel url'}};
|
|
5086
|
+
|
|
5087
|
+
const result = await meeting.updateLLMConnection();
|
|
5088
|
+
|
|
5089
|
+
assert.calledWith(webex.internal.llm.disconnectLLM);
|
|
5090
|
+
assert.notCalled(webex.internal.llm.registerAndConnect);
|
|
5091
|
+
assert.equal(result, undefined);
|
|
5092
|
+
});
|
|
5093
|
+
});
|
|
5094
|
+
|
|
4031
5095
|
describe('#setLocus', () => {
|
|
4032
5096
|
beforeEach(() => {
|
|
4033
5097
|
meeting.locusInfo.initialSetup = sinon.stub().returns(true);
|
|
@@ -4039,7 +5103,7 @@ describe('plugin-meetings', () => {
|
|
|
4039
5103
|
locusId: uuid1,
|
|
4040
5104
|
selfId: uuid2,
|
|
4041
5105
|
mediaId: uuid3,
|
|
4042
|
-
host: {id: uuid4}
|
|
5106
|
+
host: {id: uuid4},
|
|
4043
5107
|
});
|
|
4044
5108
|
assert.calledOnce(meeting.locusInfo.initialSetup);
|
|
4045
5109
|
assert.calledWith(meeting.locusInfo.initialSetup, {
|
|
@@ -4048,7 +5112,7 @@ describe('plugin-meetings', () => {
|
|
|
4048
5112
|
locusId: uuid1,
|
|
4049
5113
|
selfId: uuid2,
|
|
4050
5114
|
mediaId: uuid3,
|
|
4051
|
-
host: {id: uuid4}
|
|
5115
|
+
host: {id: uuid4},
|
|
4052
5116
|
});
|
|
4053
5117
|
assert.equal(meeting.mediaConnections, test1);
|
|
4054
5118
|
assert.equal(meeting.locusUrl, url1);
|
|
@@ -4097,7 +5161,7 @@ describe('plugin-meetings', () => {
|
|
|
4097
5161
|
});
|
|
4098
5162
|
it('should send the whiteboard share', async () => {
|
|
4099
5163
|
const whiteboardShare = meeting.startWhiteboardShare({
|
|
4100
|
-
channelUrl: url2
|
|
5164
|
+
channelUrl: url2,
|
|
4101
5165
|
});
|
|
4102
5166
|
|
|
4103
5167
|
assert.exists(whiteboardShare.then);
|
|
@@ -4137,18 +5201,35 @@ describe('plugin-meetings', () => {
|
|
|
4137
5201
|
const USER_IDS = {
|
|
4138
5202
|
ME: '9528d952-e4de-46cf-8157-fd4823b98377',
|
|
4139
5203
|
REMOTE_A: '5be7e7b0-b304-48da-8083-83bd72b5300d',
|
|
4140
|
-
REMOTE_B: 'd4d102a1-17ce-4e17-9b08-bded3de467e4'
|
|
5204
|
+
REMOTE_B: 'd4d102a1-17ce-4e17-9b08-bded3de467e4',
|
|
4141
5205
|
};
|
|
4142
5206
|
|
|
4143
5207
|
const RESOURCE_URLS = {
|
|
4144
|
-
WHITEBOARD_A:
|
|
4145
|
-
|
|
5208
|
+
WHITEBOARD_A:
|
|
5209
|
+
'https://board-a.wbx2.com/board/api/v1/channels/49cfb550-5517-11eb-a2af-1b9e4bc3da13',
|
|
5210
|
+
WHITEBOARD_B:
|
|
5211
|
+
'https://board-a.wbx2.com/board/api/v1/channels/977a7330-54f4-11eb-b1ef-91f5eefc7bf3',
|
|
4146
5212
|
};
|
|
4147
5213
|
|
|
4148
|
-
const generateContent = (beneficiaryId = null, disposition = null) => ({
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
5214
|
+
const generateContent = (beneficiaryId = null, disposition = null) => ({
|
|
5215
|
+
beneficiaryId,
|
|
5216
|
+
disposition,
|
|
5217
|
+
});
|
|
5218
|
+
const generateWhiteboard = (
|
|
5219
|
+
beneficiaryId = null,
|
|
5220
|
+
disposition = null,
|
|
5221
|
+
resourceUrl = null
|
|
5222
|
+
) => ({beneficiaryId, disposition, resourceUrl});
|
|
5223
|
+
|
|
5224
|
+
const generateData = (
|
|
5225
|
+
payload,
|
|
5226
|
+
isGranting,
|
|
5227
|
+
isContent,
|
|
5228
|
+
beneficiaryId,
|
|
5229
|
+
resourceUrl,
|
|
5230
|
+
isAccepting,
|
|
5231
|
+
otherBeneficiaryId
|
|
5232
|
+
) => {
|
|
4152
5233
|
const newPayload = cloneDeep(payload);
|
|
4153
5234
|
|
|
4154
5235
|
newPayload.previous = cloneDeep(payload.current);
|
|
@@ -4159,15 +5240,15 @@ describe('plugin-meetings', () => {
|
|
|
4159
5240
|
eventName: EVENT_TRIGGERS.MEMBERS_CONTENT_UPDATE,
|
|
4160
5241
|
eventPayload: {
|
|
4161
5242
|
activeSharingId: null,
|
|
4162
|
-
endedSharingId: null
|
|
4163
|
-
}
|
|
4164
|
-
}
|
|
5243
|
+
endedSharingId: null,
|
|
5244
|
+
},
|
|
5245
|
+
},
|
|
4165
5246
|
};
|
|
4166
5247
|
|
|
4167
5248
|
let shareStatus = null;
|
|
4168
5249
|
const activeSharingId = {
|
|
4169
5250
|
whiteboard: null,
|
|
4170
|
-
content: null
|
|
5251
|
+
content: null,
|
|
4171
5252
|
};
|
|
4172
5253
|
|
|
4173
5254
|
if (isGranting) {
|
|
@@ -4177,68 +5258,72 @@ describe('plugin-meetings', () => {
|
|
|
4177
5258
|
|
|
4178
5259
|
if (isEqual(newPayload.current, newPayload.previous)) {
|
|
4179
5260
|
eventTrigger.member = null;
|
|
4180
|
-
}
|
|
4181
|
-
else {
|
|
5261
|
+
} else {
|
|
4182
5262
|
if (newPayload.current.whiteboard.beneficiaryId) {
|
|
4183
5263
|
if (newPayload.current.whiteboard.disposition === FLOOR_ACTION.GRANTED) {
|
|
4184
5264
|
newPayload.current.whiteboard.disposition = FLOOR_ACTION.RELEASED;
|
|
4185
5265
|
eventTrigger.share.push({
|
|
4186
5266
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_WHITEBOARD,
|
|
4187
|
-
functionName: 'stopWhiteboardShare'
|
|
5267
|
+
functionName: 'stopWhiteboardShare',
|
|
4188
5268
|
});
|
|
4189
|
-
eventTrigger.member.eventPayload.endedSharingId =
|
|
5269
|
+
eventTrigger.member.eventPayload.endedSharingId =
|
|
5270
|
+
newPayload.current.whiteboard.beneficiaryId;
|
|
4190
5271
|
}
|
|
4191
5272
|
}
|
|
4192
5273
|
|
|
4193
5274
|
if (newPayload.previous.content.beneficiaryId) {
|
|
4194
|
-
if (
|
|
5275
|
+
if (
|
|
5276
|
+
newPayload.previous.content.beneficiaryId !==
|
|
5277
|
+
newPayload.current.content.beneficiaryId
|
|
5278
|
+
) {
|
|
4195
5279
|
if (newPayload.previous.content.beneficiaryId === USER_IDS.ME) {
|
|
4196
5280
|
eventTrigger.share.push({
|
|
4197
5281
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
4198
|
-
functionName: '
|
|
5282
|
+
functionName: 'localShare',
|
|
4199
5283
|
});
|
|
4200
|
-
}
|
|
4201
|
-
else if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
5284
|
+
} else if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
4202
5285
|
eventTrigger.share.push({
|
|
4203
5286
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_REMOTE,
|
|
4204
|
-
functionName: 'remoteShare'
|
|
5287
|
+
functionName: 'remoteShare',
|
|
4205
5288
|
});
|
|
4206
5289
|
}
|
|
4207
|
-
eventTrigger.member.eventPayload.endedSharingId =
|
|
5290
|
+
eventTrigger.member.eventPayload.endedSharingId =
|
|
5291
|
+
newPayload.previous.content.beneficiaryId;
|
|
4208
5292
|
}
|
|
4209
5293
|
}
|
|
4210
5294
|
|
|
4211
5295
|
if (isAccepting) {
|
|
4212
5296
|
eventTrigger.share.push({
|
|
4213
5297
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_WHITEBOARD,
|
|
4214
|
-
functionName: 'stopWhiteboardShare'
|
|
5298
|
+
functionName: 'stopWhiteboardShare',
|
|
4215
5299
|
});
|
|
4216
5300
|
}
|
|
4217
5301
|
|
|
4218
5302
|
if (beneficiaryId === USER_IDS.ME) {
|
|
4219
5303
|
eventTrigger.share.push({
|
|
4220
5304
|
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_LOCAL,
|
|
4221
|
-
functionName: 'share'
|
|
5305
|
+
functionName: 'share',
|
|
4222
5306
|
});
|
|
4223
|
-
}
|
|
4224
|
-
else {
|
|
5307
|
+
} else {
|
|
4225
5308
|
eventTrigger.share.push({
|
|
4226
5309
|
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
|
4227
5310
|
functionName: 'remoteShare',
|
|
4228
|
-
eventPayload: {memberId: beneficiaryId}
|
|
5311
|
+
eventPayload: {memberId: beneficiaryId},
|
|
4229
5312
|
});
|
|
4230
5313
|
}
|
|
4231
5314
|
}
|
|
4232
5315
|
|
|
4233
5316
|
if (beneficiaryId === USER_IDS.ME) {
|
|
4234
5317
|
shareStatus = SHARE_STATUS.LOCAL_SHARE_ACTIVE;
|
|
4235
|
-
}
|
|
4236
|
-
else {
|
|
5318
|
+
} else {
|
|
4237
5319
|
shareStatus = SHARE_STATUS.REMOTE_SHARE_ACTIVE;
|
|
4238
5320
|
}
|
|
4239
|
-
}
|
|
4240
|
-
|
|
4241
|
-
|
|
5321
|
+
} else {
|
|
5322
|
+
newPayload.current.whiteboard = generateWhiteboard(
|
|
5323
|
+
beneficiaryId,
|
|
5324
|
+
FLOOR_ACTION.GRANTED,
|
|
5325
|
+
resourceUrl
|
|
5326
|
+
);
|
|
4242
5327
|
|
|
4243
5328
|
if (newPayload.current.content.beneficiaryId) {
|
|
4244
5329
|
if (newPayload.current.content.disposition === FLOOR_ACTION.GRANTED) {
|
|
@@ -4246,41 +5331,48 @@ describe('plugin-meetings', () => {
|
|
|
4246
5331
|
if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
4247
5332
|
eventTrigger.share.push({
|
|
4248
5333
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
4249
|
-
functionName: '
|
|
5334
|
+
functionName: 'localShare',
|
|
4250
5335
|
});
|
|
4251
|
-
}
|
|
4252
|
-
else {
|
|
5336
|
+
} else {
|
|
4253
5337
|
eventTrigger.share.push({
|
|
4254
5338
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_REMOTE,
|
|
4255
|
-
functionName: 'remoteShare'
|
|
5339
|
+
functionName: 'remoteShare',
|
|
4256
5340
|
});
|
|
4257
5341
|
}
|
|
4258
5342
|
|
|
4259
|
-
eventTrigger.member.eventPayload.endedSharingId =
|
|
5343
|
+
eventTrigger.member.eventPayload.endedSharingId =
|
|
5344
|
+
newPayload.current.content.beneficiaryId;
|
|
4260
5345
|
}
|
|
4261
5346
|
}
|
|
4262
5347
|
|
|
4263
5348
|
if (newPayload.previous.content.beneficiaryId) {
|
|
4264
|
-
if (
|
|
5349
|
+
if (
|
|
5350
|
+
newPayload.previous.content.beneficiaryId !==
|
|
5351
|
+
newPayload.current.content.beneficiaryId
|
|
5352
|
+
) {
|
|
4265
5353
|
if (newPayload.previous.content.beneficiaryId === USER_IDS.ME) {
|
|
4266
5354
|
eventTrigger.share.push({
|
|
4267
5355
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
4268
|
-
functionName: '
|
|
5356
|
+
functionName: 'localShare',
|
|
4269
5357
|
});
|
|
4270
|
-
}
|
|
4271
|
-
else if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
5358
|
+
} else if (newPayload.current.content.beneficiaryId === USER_IDS.ME) {
|
|
4272
5359
|
eventTrigger.share.push({
|
|
4273
5360
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_REMOTE,
|
|
4274
|
-
functionName: 'remoteShare'
|
|
5361
|
+
functionName: 'remoteShare',
|
|
4275
5362
|
});
|
|
4276
5363
|
}
|
|
4277
|
-
eventTrigger.member.eventPayload.endedSharingId =
|
|
5364
|
+
eventTrigger.member.eventPayload.endedSharingId =
|
|
5365
|
+
newPayload.previous.content.beneficiaryId;
|
|
4278
5366
|
}
|
|
4279
5367
|
}
|
|
4280
5368
|
|
|
4281
5369
|
if (newPayload.previous.whiteboard.beneficiaryId) {
|
|
4282
|
-
if (
|
|
4283
|
-
|
|
5370
|
+
if (
|
|
5371
|
+
newPayload.previous.whiteboard.beneficiaryId !==
|
|
5372
|
+
newPayload.current.whiteboard.beneficiaryId
|
|
5373
|
+
) {
|
|
5374
|
+
eventTrigger.member.eventPayload.endedSharingId =
|
|
5375
|
+
newPayload.previous.whiteboard.beneficiaryId;
|
|
4284
5376
|
}
|
|
4285
5377
|
}
|
|
4286
5378
|
|
|
@@ -4289,7 +5381,7 @@ describe('plugin-meetings', () => {
|
|
|
4289
5381
|
eventTrigger.share.push({
|
|
4290
5382
|
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
|
|
4291
5383
|
functionName: 'startWhiteboardShare',
|
|
4292
|
-
eventPayload: {resourceUrl, memberId: beneficiaryId}
|
|
5384
|
+
eventPayload: {resourceUrl, memberId: beneficiaryId},
|
|
4293
5385
|
});
|
|
4294
5386
|
|
|
4295
5387
|
shareStatus = SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
|
@@ -4298,8 +5390,7 @@ describe('plugin-meetings', () => {
|
|
|
4298
5390
|
if (eventTrigger.member) {
|
|
4299
5391
|
eventTrigger.member.eventPayload.activeSharingId = beneficiaryId;
|
|
4300
5392
|
}
|
|
4301
|
-
}
|
|
4302
|
-
else {
|
|
5393
|
+
} else {
|
|
4303
5394
|
eventTrigger.member.eventPayload.endedSharingId = beneficiaryId;
|
|
4304
5395
|
|
|
4305
5396
|
if (isContent) {
|
|
@@ -4308,19 +5399,17 @@ describe('plugin-meetings', () => {
|
|
|
4308
5399
|
if (beneficiaryId === USER_IDS.ME) {
|
|
4309
5400
|
eventTrigger.share.push({
|
|
4310
5401
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
|
|
4311
|
-
functionName: '
|
|
5402
|
+
functionName: 'localShare',
|
|
4312
5403
|
});
|
|
4313
|
-
}
|
|
4314
|
-
else {
|
|
5404
|
+
} else {
|
|
4315
5405
|
eventTrigger.share.push({
|
|
4316
5406
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_REMOTE,
|
|
4317
|
-
functionName: 'remoteShare'
|
|
5407
|
+
functionName: 'remoteShare',
|
|
4318
5408
|
});
|
|
4319
5409
|
}
|
|
4320
5410
|
|
|
4321
5411
|
shareStatus = SHARE_STATUS.NO_SHARE;
|
|
4322
|
-
}
|
|
4323
|
-
else {
|
|
5412
|
+
} else {
|
|
4324
5413
|
newPayload.current.whiteboard.disposition = FLOOR_ACTION.RELEASED;
|
|
4325
5414
|
|
|
4326
5415
|
if (isAccepting) {
|
|
@@ -4330,15 +5419,14 @@ describe('plugin-meetings', () => {
|
|
|
4330
5419
|
eventTrigger.share.push({
|
|
4331
5420
|
eventName: EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
|
|
4332
5421
|
functionName: 'startWhiteboardShare',
|
|
4333
|
-
eventPayload: {resourceUrl, memberId: beneficiaryId}
|
|
5422
|
+
eventPayload: {resourceUrl, memberId: beneficiaryId},
|
|
4334
5423
|
});
|
|
4335
5424
|
|
|
4336
5425
|
shareStatus = SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
|
4337
|
-
}
|
|
4338
|
-
else {
|
|
5426
|
+
} else {
|
|
4339
5427
|
eventTrigger.share.push({
|
|
4340
5428
|
eventName: EVENT_TRIGGERS.MEETING_STOPPED_SHARING_WHITEBOARD,
|
|
4341
|
-
functionName: 'stopWhiteboardShare'
|
|
5429
|
+
functionName: 'stopWhiteboardShare',
|
|
4342
5430
|
});
|
|
4343
5431
|
|
|
4344
5432
|
shareStatus = SHARE_STATUS.NO_SHARE;
|
|
@@ -4347,22 +5435,24 @@ describe('plugin-meetings', () => {
|
|
|
4347
5435
|
}
|
|
4348
5436
|
|
|
4349
5437
|
return {
|
|
4350
|
-
payload: newPayload,
|
|
5438
|
+
payload: newPayload,
|
|
5439
|
+
eventTrigger,
|
|
5440
|
+
shareStatus,
|
|
5441
|
+
activeSharingId,
|
|
4351
5442
|
};
|
|
4352
5443
|
};
|
|
4353
5444
|
|
|
4354
5445
|
const blankPayload = {
|
|
4355
5446
|
previous: {
|
|
4356
5447
|
content: generateContent(),
|
|
4357
|
-
whiteboard: generateWhiteboard()
|
|
5448
|
+
whiteboard: generateWhiteboard(),
|
|
4358
5449
|
},
|
|
4359
5450
|
current: {
|
|
4360
5451
|
content: generateContent(),
|
|
4361
|
-
whiteboard: generateWhiteboard()
|
|
4362
|
-
}
|
|
5452
|
+
whiteboard: generateWhiteboard(),
|
|
5453
|
+
},
|
|
4363
5454
|
};
|
|
4364
5455
|
|
|
4365
|
-
|
|
4366
5456
|
const payloadTestHelper = (data) => {
|
|
4367
5457
|
assert.equal(meeting.shareStatus, SHARE_STATUS.NO_SHARE);
|
|
4368
5458
|
|
|
@@ -4370,23 +5460,33 @@ describe('plugin-meetings', () => {
|
|
|
4370
5460
|
let callCounter = 1;
|
|
4371
5461
|
|
|
4372
5462
|
data.forEach((d, index) => {
|
|
4373
|
-
meeting.locusInfo.emit(
|
|
5463
|
+
meeting.locusInfo.emit(
|
|
5464
|
+
{function: 'test', file: 'test'},
|
|
5465
|
+
EVENTS.LOCUS_INFO_UPDATE_MEDIA_SHARES,
|
|
5466
|
+
d.payload
|
|
5467
|
+
);
|
|
4374
5468
|
|
|
4375
5469
|
assert.equal(meeting.shareStatus, data[index].shareStatus);
|
|
4376
5470
|
|
|
4377
|
-
callCounter +=
|
|
5471
|
+
callCounter +=
|
|
5472
|
+
data[index].eventTrigger.share.length + (data[index].eventTrigger.member ? 1 : 0);
|
|
4378
5473
|
|
|
4379
5474
|
assert.callCount(TriggerProxy.trigger, callCounter);
|
|
4380
5475
|
|
|
4381
|
-
assert.equal(
|
|
4382
|
-
|
|
5476
|
+
assert.equal(
|
|
5477
|
+
meeting.members.mediaShareWhiteboardId,
|
|
5478
|
+
data[index].activeSharingId.whiteboard
|
|
5479
|
+
);
|
|
5480
|
+
assert.equal(
|
|
5481
|
+
meeting.members.mediaShareContentId,
|
|
5482
|
+
data[index].activeSharingId.content
|
|
5483
|
+
);
|
|
4383
5484
|
});
|
|
4384
5485
|
|
|
4385
5486
|
assert.callCount(TriggerProxy.trigger, callCounter);
|
|
4386
5487
|
|
|
4387
5488
|
// Start with 1 to ignore members:update trigger
|
|
4388
5489
|
|
|
4389
|
-
|
|
4390
5490
|
let i = 1;
|
|
4391
5491
|
let offset = 2;
|
|
4392
5492
|
|
|
@@ -4398,21 +5498,24 @@ describe('plugin-meetings', () => {
|
|
|
4398
5498
|
for (let idx = 0; idx < share.length; idx += 1) {
|
|
4399
5499
|
const shareCallArgs = TriggerProxy.trigger.getCall(i + idx).args;
|
|
4400
5500
|
const {functionName, eventName, eventPayload} = share[idx];
|
|
4401
|
-
const fileName =
|
|
5501
|
+
const fileName =
|
|
5502
|
+
functionName === 'remoteShare' ? 'meetings/index' : 'meeting/index';
|
|
4402
5503
|
|
|
4403
5504
|
assert.deepEqual(shareCallArgs[1], {
|
|
4404
5505
|
file: fileName,
|
|
4405
|
-
function: functionName
|
|
5506
|
+
function: functionName,
|
|
4406
5507
|
});
|
|
4407
5508
|
|
|
4408
|
-
|
|
4409
5509
|
assert.equal(shareCallArgs[2], eventName);
|
|
4410
5510
|
|
|
4411
5511
|
if (functionName === 'startWhiteboardShare') {
|
|
4412
5512
|
assert.deepEqual(shareCallArgs[3], eventPayload);
|
|
4413
5513
|
}
|
|
4414
5514
|
|
|
4415
|
-
if (
|
|
5515
|
+
if (
|
|
5516
|
+
functionName === 'remoteShare' &&
|
|
5517
|
+
eventName === EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE
|
|
5518
|
+
) {
|
|
4416
5519
|
assert.deepEqual(shareCallArgs[3], eventPayload);
|
|
4417
5520
|
}
|
|
4418
5521
|
}
|
|
@@ -4423,7 +5526,7 @@ describe('plugin-meetings', () => {
|
|
|
4423
5526
|
|
|
4424
5527
|
assert.deepEqual(memberCallArgs[1], {
|
|
4425
5528
|
file: 'members',
|
|
4426
|
-
function: 'locusMediaSharesUpdate'
|
|
5529
|
+
function: 'locusMediaSharesUpdate',
|
|
4427
5530
|
});
|
|
4428
5531
|
assert.equal(memberCallArgs[2], member.eventName);
|
|
4429
5532
|
|
|
@@ -4437,9 +5540,8 @@ describe('plugin-meetings', () => {
|
|
|
4437
5540
|
|
|
4438
5541
|
if (share.length + 1 > offset) {
|
|
4439
5542
|
offset = (offset + share.length + 1) / 2;
|
|
4440
|
-
}
|
|
4441
|
-
|
|
4442
|
-
offset = (share.length + 1) + 0.5;
|
|
5543
|
+
} else if (share.length + 1 < offset) {
|
|
5544
|
+
offset = share.length + 1 + 0.5;
|
|
4443
5545
|
}
|
|
4444
5546
|
}
|
|
4445
5547
|
};
|
|
@@ -4450,40 +5552,100 @@ describe('plugin-meetings', () => {
|
|
|
4450
5552
|
|
|
4451
5553
|
describe('Whiteboard A --> Whiteboard B', () => {
|
|
4452
5554
|
it('Scenario #1: you share both whiteboards', () => {
|
|
4453
|
-
const data1 = generateData(
|
|
4454
|
-
|
|
5555
|
+
const data1 = generateData(
|
|
5556
|
+
blankPayload,
|
|
5557
|
+
true,
|
|
5558
|
+
false,
|
|
5559
|
+
USER_IDS.ME,
|
|
5560
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5561
|
+
);
|
|
5562
|
+
const data2 = generateData(
|
|
5563
|
+
data1.payload,
|
|
5564
|
+
true,
|
|
5565
|
+
false,
|
|
5566
|
+
USER_IDS.ME,
|
|
5567
|
+
RESOURCE_URLS.WHITEBOARD_B
|
|
5568
|
+
);
|
|
4455
5569
|
const data3 = generateData(data2.payload, false, false, USER_IDS.ME);
|
|
4456
5570
|
|
|
4457
5571
|
payloadTestHelper([data1, data2, data3]);
|
|
4458
5572
|
});
|
|
4459
5573
|
|
|
4460
5574
|
it('Scenario #2: you share whiteboard A and remote person A shares whiteboard B', () => {
|
|
4461
|
-
const data1 = generateData(
|
|
4462
|
-
|
|
5575
|
+
const data1 = generateData(
|
|
5576
|
+
blankPayload,
|
|
5577
|
+
true,
|
|
5578
|
+
false,
|
|
5579
|
+
USER_IDS.ME,
|
|
5580
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5581
|
+
);
|
|
5582
|
+
const data2 = generateData(
|
|
5583
|
+
data1.payload,
|
|
5584
|
+
true,
|
|
5585
|
+
false,
|
|
5586
|
+
USER_IDS.REMOTE_A,
|
|
5587
|
+
RESOURCE_URLS.WHITEBOARD_B
|
|
5588
|
+
);
|
|
4463
5589
|
const data3 = generateData(data2.payload, false, false, USER_IDS.REMOTE_A);
|
|
4464
5590
|
|
|
4465
5591
|
payloadTestHelper([data1, data2, data3]);
|
|
4466
5592
|
});
|
|
4467
5593
|
|
|
4468
5594
|
it('Scenario #3: remote person A shares whiteboard A and you share whiteboard B', () => {
|
|
4469
|
-
const data1 = generateData(
|
|
4470
|
-
|
|
5595
|
+
const data1 = generateData(
|
|
5596
|
+
blankPayload,
|
|
5597
|
+
true,
|
|
5598
|
+
false,
|
|
5599
|
+
USER_IDS.REMOTE_A,
|
|
5600
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5601
|
+
);
|
|
5602
|
+
const data2 = generateData(
|
|
5603
|
+
data1.payload,
|
|
5604
|
+
true,
|
|
5605
|
+
false,
|
|
5606
|
+
USER_IDS.ME,
|
|
5607
|
+
RESOURCE_URLS.WHITEBOARD_B
|
|
5608
|
+
);
|
|
4471
5609
|
const data3 = generateData(data2.payload, false, false, USER_IDS.ME);
|
|
4472
5610
|
|
|
4473
5611
|
payloadTestHelper([data1, data2, data3]);
|
|
4474
5612
|
});
|
|
4475
5613
|
|
|
4476
5614
|
it('Scenario #4: remote person A shares both whiteboards', () => {
|
|
4477
|
-
const data1 = generateData(
|
|
4478
|
-
|
|
5615
|
+
const data1 = generateData(
|
|
5616
|
+
blankPayload,
|
|
5617
|
+
true,
|
|
5618
|
+
false,
|
|
5619
|
+
USER_IDS.REMOTE_A,
|
|
5620
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5621
|
+
);
|
|
5622
|
+
const data2 = generateData(
|
|
5623
|
+
data1.payload,
|
|
5624
|
+
true,
|
|
5625
|
+
false,
|
|
5626
|
+
USER_IDS.REMOTE_A,
|
|
5627
|
+
RESOURCE_URLS.WHITEBOARD_B
|
|
5628
|
+
);
|
|
4479
5629
|
const data3 = generateData(data2.payload, false, false, USER_IDS.REMOTE_A);
|
|
4480
5630
|
|
|
4481
5631
|
payloadTestHelper([data1, data2, data3]);
|
|
4482
5632
|
});
|
|
4483
5633
|
|
|
4484
5634
|
it('Scenario #5: remote person A shares whiteboard A and remote person B shares whiteboard B', () => {
|
|
4485
|
-
const data1 = generateData(
|
|
4486
|
-
|
|
5635
|
+
const data1 = generateData(
|
|
5636
|
+
blankPayload,
|
|
5637
|
+
true,
|
|
5638
|
+
false,
|
|
5639
|
+
USER_IDS.REMOTE_A,
|
|
5640
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5641
|
+
);
|
|
5642
|
+
const data2 = generateData(
|
|
5643
|
+
data1.payload,
|
|
5644
|
+
true,
|
|
5645
|
+
false,
|
|
5646
|
+
USER_IDS.REMOTE_B,
|
|
5647
|
+
RESOURCE_URLS.WHITEBOARD_B
|
|
5648
|
+
);
|
|
4487
5649
|
const data3 = generateData(data2.payload, false, false, USER_IDS.REMOTE_B);
|
|
4488
5650
|
|
|
4489
5651
|
payloadTestHelper([data1, data2, data3]);
|
|
@@ -4492,45 +5654,155 @@ describe('plugin-meetings', () => {
|
|
|
4492
5654
|
|
|
4493
5655
|
describe('Whiteboard A --> Desktop', () => {
|
|
4494
5656
|
it('Scenario #1: you share whiteboard and then share desktop', () => {
|
|
4495
|
-
const data1 = generateData(
|
|
4496
|
-
|
|
4497
|
-
|
|
5657
|
+
const data1 = generateData(
|
|
5658
|
+
blankPayload,
|
|
5659
|
+
true,
|
|
5660
|
+
false,
|
|
5661
|
+
USER_IDS.ME,
|
|
5662
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5663
|
+
);
|
|
5664
|
+
const data2 = generateData(
|
|
5665
|
+
data1.payload,
|
|
5666
|
+
false,
|
|
5667
|
+
false,
|
|
5668
|
+
USER_IDS.ME,
|
|
5669
|
+
RESOURCE_URLS.WHITEBOARD_A,
|
|
5670
|
+
true,
|
|
5671
|
+
USER_IDS.ME
|
|
5672
|
+
);
|
|
5673
|
+
const data3 = generateData(
|
|
5674
|
+
data2.payload,
|
|
5675
|
+
true,
|
|
5676
|
+
true,
|
|
5677
|
+
USER_IDS.ME,
|
|
5678
|
+
undefined,
|
|
5679
|
+
true,
|
|
5680
|
+
USER_IDS.ME
|
|
5681
|
+
);
|
|
4498
5682
|
const data4 = generateData(data3.payload, false, true, USER_IDS.ME);
|
|
4499
5683
|
|
|
4500
5684
|
payloadTestHelper([data1, data2, data3, data4]);
|
|
4501
5685
|
});
|
|
4502
5686
|
|
|
4503
5687
|
it('Scenario #2: you share whiteboard A and remote person A shares desktop', () => {
|
|
4504
|
-
const data1 = generateData(
|
|
4505
|
-
|
|
4506
|
-
|
|
5688
|
+
const data1 = generateData(
|
|
5689
|
+
blankPayload,
|
|
5690
|
+
true,
|
|
5691
|
+
false,
|
|
5692
|
+
USER_IDS.ME,
|
|
5693
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5694
|
+
);
|
|
5695
|
+
const data2 = generateData(
|
|
5696
|
+
data1.payload,
|
|
5697
|
+
false,
|
|
5698
|
+
false,
|
|
5699
|
+
USER_IDS.ME,
|
|
5700
|
+
RESOURCE_URLS.WHITEBOARD_A,
|
|
5701
|
+
true,
|
|
5702
|
+
USER_IDS.REMOTE_A
|
|
5703
|
+
);
|
|
5704
|
+
const data3 = generateData(
|
|
5705
|
+
data2.payload,
|
|
5706
|
+
true,
|
|
5707
|
+
true,
|
|
5708
|
+
USER_IDS.REMOTE_A,
|
|
5709
|
+
undefined,
|
|
5710
|
+
true,
|
|
5711
|
+
USER_IDS.ME
|
|
5712
|
+
);
|
|
4507
5713
|
const data4 = generateData(data3.payload, false, true, USER_IDS.REMOTE_A);
|
|
4508
5714
|
|
|
4509
5715
|
payloadTestHelper([data1, data2, data3, data4]);
|
|
4510
5716
|
});
|
|
4511
5717
|
|
|
4512
5718
|
it('Scenario #3: remote person A shares whiteboard and you share desktop', () => {
|
|
4513
|
-
const data1 = generateData(
|
|
4514
|
-
|
|
4515
|
-
|
|
5719
|
+
const data1 = generateData(
|
|
5720
|
+
blankPayload,
|
|
5721
|
+
true,
|
|
5722
|
+
false,
|
|
5723
|
+
USER_IDS.REMOTE_A,
|
|
5724
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5725
|
+
);
|
|
5726
|
+
const data2 = generateData(
|
|
5727
|
+
data1.payload,
|
|
5728
|
+
false,
|
|
5729
|
+
false,
|
|
5730
|
+
USER_IDS.REMOTE_A,
|
|
5731
|
+
RESOURCE_URLS.WHITEBOARD_A,
|
|
5732
|
+
true,
|
|
5733
|
+
USER_IDS.ME
|
|
5734
|
+
);
|
|
5735
|
+
const data3 = generateData(
|
|
5736
|
+
data2.payload,
|
|
5737
|
+
true,
|
|
5738
|
+
true,
|
|
5739
|
+
USER_IDS.ME,
|
|
5740
|
+
undefined,
|
|
5741
|
+
true,
|
|
5742
|
+
USER_IDS.REMOTE_A
|
|
5743
|
+
);
|
|
4516
5744
|
const data4 = generateData(data3.payload, false, true, USER_IDS.ME);
|
|
4517
5745
|
|
|
4518
5746
|
payloadTestHelper([data1, data2, data3, data4]);
|
|
4519
5747
|
});
|
|
4520
5748
|
|
|
4521
5749
|
it('Scenario #4: remote person A shares whiteboard and then shares desktop', () => {
|
|
4522
|
-
const data1 = generateData(
|
|
4523
|
-
|
|
4524
|
-
|
|
5750
|
+
const data1 = generateData(
|
|
5751
|
+
blankPayload,
|
|
5752
|
+
true,
|
|
5753
|
+
false,
|
|
5754
|
+
USER_IDS.REMOTE_A,
|
|
5755
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5756
|
+
);
|
|
5757
|
+
const data2 = generateData(
|
|
5758
|
+
data1.payload,
|
|
5759
|
+
false,
|
|
5760
|
+
false,
|
|
5761
|
+
USER_IDS.REMOTE_A,
|
|
5762
|
+
RESOURCE_URLS.WHITEBOARD_A,
|
|
5763
|
+
true,
|
|
5764
|
+
USER_IDS.REMOTE_A
|
|
5765
|
+
);
|
|
5766
|
+
const data3 = generateData(
|
|
5767
|
+
data2.payload,
|
|
5768
|
+
true,
|
|
5769
|
+
true,
|
|
5770
|
+
USER_IDS.REMOTE_A,
|
|
5771
|
+
undefined,
|
|
5772
|
+
true,
|
|
5773
|
+
USER_IDS.REMOTE_A
|
|
5774
|
+
);
|
|
4525
5775
|
const data4 = generateData(data3.payload, false, true, USER_IDS.REMOTE_A);
|
|
4526
5776
|
|
|
4527
5777
|
payloadTestHelper([data1, data2, data3, data4]);
|
|
4528
5778
|
});
|
|
4529
5779
|
|
|
4530
5780
|
it('Scenario #5: remote person A shares whiteboard and remote person B shares desktop', () => {
|
|
4531
|
-
const data1 = generateData(
|
|
4532
|
-
|
|
4533
|
-
|
|
5781
|
+
const data1 = generateData(
|
|
5782
|
+
blankPayload,
|
|
5783
|
+
true,
|
|
5784
|
+
false,
|
|
5785
|
+
USER_IDS.REMOTE_A,
|
|
5786
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5787
|
+
);
|
|
5788
|
+
const data2 = generateData(
|
|
5789
|
+
data1.payload,
|
|
5790
|
+
false,
|
|
5791
|
+
false,
|
|
5792
|
+
USER_IDS.REMOTE_A,
|
|
5793
|
+
RESOURCE_URLS.WHITEBOARD_A,
|
|
5794
|
+
true,
|
|
5795
|
+
USER_IDS.REMOTE_B
|
|
5796
|
+
);
|
|
5797
|
+
const data3 = generateData(
|
|
5798
|
+
data2.payload,
|
|
5799
|
+
true,
|
|
5800
|
+
true,
|
|
5801
|
+
USER_IDS.REMOTE_B,
|
|
5802
|
+
undefined,
|
|
5803
|
+
true,
|
|
5804
|
+
USER_IDS.REMOTE_A
|
|
5805
|
+
);
|
|
4534
5806
|
const data4 = generateData(data3.payload, false, true, USER_IDS.REMOTE_B);
|
|
4535
5807
|
|
|
4536
5808
|
payloadTestHelper([data1, data2, data3, data4]);
|
|
@@ -4540,7 +5812,13 @@ describe('plugin-meetings', () => {
|
|
|
4540
5812
|
describe('Desktop --> Whiteboard A', () => {
|
|
4541
5813
|
it('Scenario #1: you share desktop and then share whiteboard', () => {
|
|
4542
5814
|
const data1 = generateData(blankPayload, true, true, USER_IDS.ME);
|
|
4543
|
-
const data2 = generateData(
|
|
5815
|
+
const data2 = generateData(
|
|
5816
|
+
data1.payload,
|
|
5817
|
+
true,
|
|
5818
|
+
false,
|
|
5819
|
+
USER_IDS.ME,
|
|
5820
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5821
|
+
);
|
|
4544
5822
|
const data3 = generateData(data2.payload, false, false, USER_IDS.ME);
|
|
4545
5823
|
|
|
4546
5824
|
payloadTestHelper([data1, data2, data3]);
|
|
@@ -4548,7 +5826,13 @@ describe('plugin-meetings', () => {
|
|
|
4548
5826
|
|
|
4549
5827
|
it('Scenario #2: you share desktop and remote person A shares whiteboard', () => {
|
|
4550
5828
|
const data1 = generateData(blankPayload, true, true, USER_IDS.ME);
|
|
4551
|
-
const data2 = generateData(
|
|
5829
|
+
const data2 = generateData(
|
|
5830
|
+
data1.payload,
|
|
5831
|
+
true,
|
|
5832
|
+
false,
|
|
5833
|
+
USER_IDS.REMOTE_A,
|
|
5834
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5835
|
+
);
|
|
4552
5836
|
const data3 = generateData(data2.payload, false, false, USER_IDS.REMOTE_A);
|
|
4553
5837
|
|
|
4554
5838
|
payloadTestHelper([data1, data2, data3]);
|
|
@@ -4556,7 +5840,13 @@ describe('plugin-meetings', () => {
|
|
|
4556
5840
|
|
|
4557
5841
|
it('Scenario #3: remote person A shares desktop and you share whiteboard', () => {
|
|
4558
5842
|
const data1 = generateData(blankPayload, true, true, USER_IDS.REMOTE_A);
|
|
4559
|
-
const data2 = generateData(
|
|
5843
|
+
const data2 = generateData(
|
|
5844
|
+
data1.payload,
|
|
5845
|
+
true,
|
|
5846
|
+
false,
|
|
5847
|
+
USER_IDS.REMOTE_A,
|
|
5848
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5849
|
+
);
|
|
4560
5850
|
const data3 = generateData(data2.payload, false, false, USER_IDS.REMOTE_A);
|
|
4561
5851
|
|
|
4562
5852
|
payloadTestHelper([data1, data2, data3]);
|
|
@@ -4564,7 +5854,13 @@ describe('plugin-meetings', () => {
|
|
|
4564
5854
|
|
|
4565
5855
|
it('Scenario #4: remote person A shares desktop and then shares whiteboard', () => {
|
|
4566
5856
|
const data1 = generateData(blankPayload, true, true, USER_IDS.REMOTE_A);
|
|
4567
|
-
const data2 = generateData(
|
|
5857
|
+
const data2 = generateData(
|
|
5858
|
+
data1.payload,
|
|
5859
|
+
true,
|
|
5860
|
+
false,
|
|
5861
|
+
USER_IDS.ME,
|
|
5862
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5863
|
+
);
|
|
4568
5864
|
const data3 = generateData(data2.payload, false, false, USER_IDS.ME);
|
|
4569
5865
|
|
|
4570
5866
|
payloadTestHelper([data1, data2, data3]);
|
|
@@ -4572,7 +5868,13 @@ describe('plugin-meetings', () => {
|
|
|
4572
5868
|
|
|
4573
5869
|
it('Scenario #5: remote person A shares desktop and remote person B shares whiteboard', () => {
|
|
4574
5870
|
const data1 = generateData(blankPayload, true, true, USER_IDS.REMOTE_A);
|
|
4575
|
-
const data2 = generateData(
|
|
5871
|
+
const data2 = generateData(
|
|
5872
|
+
data1.payload,
|
|
5873
|
+
true,
|
|
5874
|
+
false,
|
|
5875
|
+
USER_IDS.REMOTE_A,
|
|
5876
|
+
RESOURCE_URLS.WHITEBOARD_A
|
|
5877
|
+
);
|
|
4576
5878
|
const data3 = generateData(data2.payload, false, false, USER_IDS.REMOTE_A);
|
|
4577
5879
|
|
|
4578
5880
|
payloadTestHelper([data1, data2, data3]);
|
|
@@ -4648,17 +5950,21 @@ describe('plugin-meetings', () => {
|
|
|
4648
5950
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4649
5951
|
meeting.joinedWith = {
|
|
4650
5952
|
keepAliveUrl: defaultKeepAliveUrl,
|
|
4651
|
-
keepAliveSecs: defaultKeepAliveSecs
|
|
5953
|
+
keepAliveSecs: defaultKeepAliveSecs,
|
|
4652
5954
|
};
|
|
4653
5955
|
meeting.startKeepAlive();
|
|
4654
5956
|
assert.isNumber(meeting.keepAliveTimerId.id);
|
|
4655
5957
|
await testUtils.flushPromises();
|
|
4656
5958
|
assert.notCalled(meeting.meetingRequest.keepAlive);
|
|
4657
5959
|
await progressTime(defaultExpectedInterval);
|
|
4658
|
-
assert.calledOnceWithExactly(meeting.meetingRequest.keepAlive, {
|
|
5960
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.keepAlive, {
|
|
5961
|
+
keepAliveUrl: defaultKeepAliveUrl,
|
|
5962
|
+
});
|
|
4659
5963
|
await progressTime(defaultExpectedInterval);
|
|
4660
5964
|
assert.calledTwice(meeting.meetingRequest.keepAlive);
|
|
4661
|
-
assert.alwaysCalledWithExactly(meeting.meetingRequest.keepAlive, {
|
|
5965
|
+
assert.alwaysCalledWithExactly(meeting.meetingRequest.keepAlive, {
|
|
5966
|
+
keepAliveUrl: defaultKeepAliveUrl,
|
|
5967
|
+
});
|
|
4662
5968
|
});
|
|
4663
5969
|
it('startKeepAlive handles existing keepAliveTimerId', async () => {
|
|
4664
5970
|
meeting.meetingRequest.keepAlive = sinon.stub().returns(Promise.resolve());
|
|
@@ -4667,7 +5973,7 @@ describe('plugin-meetings', () => {
|
|
|
4667
5973
|
meeting.keepAliveTimerId = 7;
|
|
4668
5974
|
meeting.joinedWith = {
|
|
4669
5975
|
keepAliveUrl: defaultKeepAliveUrl,
|
|
4670
|
-
keepAliveSecs: defaultKeepAliveSecs
|
|
5976
|
+
keepAliveSecs: defaultKeepAliveSecs,
|
|
4671
5977
|
};
|
|
4672
5978
|
meeting.startKeepAlive();
|
|
4673
5979
|
assert.equal(meeting.keepAliveTimerId, 7);
|
|
@@ -4680,7 +5986,7 @@ describe('plugin-meetings', () => {
|
|
|
4680
5986
|
|
|
4681
5987
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4682
5988
|
meeting.joinedWith = {
|
|
4683
|
-
keepAliveSecs: defaultKeepAliveSecs
|
|
5989
|
+
keepAliveSecs: defaultKeepAliveSecs,
|
|
4684
5990
|
};
|
|
4685
5991
|
meeting.startKeepAlive();
|
|
4686
5992
|
assert.isNull(meeting.keepAliveTimerId);
|
|
@@ -4693,7 +5999,7 @@ describe('plugin-meetings', () => {
|
|
|
4693
5999
|
|
|
4694
6000
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4695
6001
|
meeting.joinedWith = {
|
|
4696
|
-
keepAliveUrl: defaultKeepAliveUrl
|
|
6002
|
+
keepAliveUrl: defaultKeepAliveUrl,
|
|
4697
6003
|
};
|
|
4698
6004
|
meeting.startKeepAlive();
|
|
4699
6005
|
assert.isNull(meeting.keepAliveTimerId);
|
|
@@ -4707,7 +6013,7 @@ describe('plugin-meetings', () => {
|
|
|
4707
6013
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4708
6014
|
meeting.joinedWith = {
|
|
4709
6015
|
keepAliveUrl: defaultKeepAliveUrl,
|
|
4710
|
-
keepAliveSecs: 1
|
|
6016
|
+
keepAliveSecs: 1,
|
|
4711
6017
|
};
|
|
4712
6018
|
meeting.startKeepAlive();
|
|
4713
6019
|
assert.isNull(meeting.keepAliveTimerId);
|
|
@@ -4720,14 +6026,16 @@ describe('plugin-meetings', () => {
|
|
|
4720
6026
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4721
6027
|
meeting.joinedWith = {
|
|
4722
6028
|
keepAliveUrl: defaultKeepAliveUrl,
|
|
4723
|
-
keepAliveSecs: defaultKeepAliveSecs
|
|
6029
|
+
keepAliveSecs: defaultKeepAliveSecs,
|
|
4724
6030
|
};
|
|
4725
6031
|
meeting.startKeepAlive();
|
|
4726
6032
|
assert.isNumber(meeting.keepAliveTimerId.id);
|
|
4727
6033
|
await testUtils.flushPromises();
|
|
4728
6034
|
assert.notCalled(meeting.meetingRequest.keepAlive);
|
|
4729
6035
|
await progressTime(defaultExpectedInterval);
|
|
4730
|
-
assert.calledOnceWithExactly(meeting.meetingRequest.keepAlive, {
|
|
6036
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.keepAlive, {
|
|
6037
|
+
keepAliveUrl: defaultKeepAliveUrl,
|
|
6038
|
+
});
|
|
4731
6039
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4732
6040
|
await progressTime(defaultExpectedInterval);
|
|
4733
6041
|
assert.calledOnce(meeting.meetingRequest.keepAlive);
|
|
@@ -4757,12 +6065,14 @@ describe('plugin-meetings', () => {
|
|
|
4757
6065
|
assert.isNull(meeting.keepAliveTimerId);
|
|
4758
6066
|
meeting.joinedWith = {
|
|
4759
6067
|
keepAliveUrl: defaultKeepAliveUrl,
|
|
4760
|
-
keepAliveSecs: defaultKeepAliveSecs
|
|
6068
|
+
keepAliveSecs: defaultKeepAliveSecs,
|
|
4761
6069
|
};
|
|
4762
6070
|
meeting.startKeepAlive();
|
|
4763
6071
|
assert.isNumber(meeting.keepAliveTimerId.id);
|
|
4764
6072
|
await progressTime(defaultExpectedInterval);
|
|
4765
|
-
assert.calledOnceWithExactly(meeting.meetingRequest.keepAlive, {
|
|
6073
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.keepAlive, {
|
|
6074
|
+
keepAliveUrl: defaultKeepAliveUrl,
|
|
6075
|
+
});
|
|
4766
6076
|
|
|
4767
6077
|
meeting.stopKeepAlive();
|
|
4768
6078
|
assert.isNull(meeting.keepAliveTimerId);
|
|
@@ -4774,6 +6084,164 @@ describe('plugin-meetings', () => {
|
|
|
4774
6084
|
meeting.stopKeepAlive();
|
|
4775
6085
|
});
|
|
4776
6086
|
});
|
|
6087
|
+
|
|
6088
|
+
describe('#sendReaction', () => {
|
|
6089
|
+
it('should have #sendReaction', () => {
|
|
6090
|
+
assert.exists(meeting.sendReaction);
|
|
6091
|
+
});
|
|
6092
|
+
|
|
6093
|
+
beforeEach(() => {
|
|
6094
|
+
meeting.meetingRequest.sendReaction = sinon.stub().returns(Promise.resolve());
|
|
6095
|
+
});
|
|
6096
|
+
|
|
6097
|
+
it('should send reaction with the right data and return a promise', async () => {
|
|
6098
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: 'Fake URL'}};
|
|
6099
|
+
|
|
6100
|
+
const reactionPromise = meeting.sendReaction('thumb_down', 'light');
|
|
6101
|
+
|
|
6102
|
+
assert.exists(reactionPromise.then);
|
|
6103
|
+
await reactionPromise;
|
|
6104
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.sendReaction, {
|
|
6105
|
+
reactionChannelUrl: 'Fake URL',
|
|
6106
|
+
reaction: {
|
|
6107
|
+
type: 'thumb_down',
|
|
6108
|
+
codepoints: '1F44E',
|
|
6109
|
+
shortcodes: ':thumbsdown:',
|
|
6110
|
+
tone: {
|
|
6111
|
+
type: 'light_skin_tone',
|
|
6112
|
+
codepoints: '1F3FB',
|
|
6113
|
+
shortcodes: ':skin-tone-2:',
|
|
6114
|
+
},
|
|
6115
|
+
},
|
|
6116
|
+
participantId: meeting.members.selfId,
|
|
6117
|
+
});
|
|
6118
|
+
});
|
|
6119
|
+
|
|
6120
|
+
it('should fail sending a reaction if data channel is undefined', async () => {
|
|
6121
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: undefined}};
|
|
6122
|
+
|
|
6123
|
+
await assert.isRejected(
|
|
6124
|
+
meeting.sendReaction('thumb_down', 'light'),
|
|
6125
|
+
Error,
|
|
6126
|
+
'Error sending reaction, service url not found.'
|
|
6127
|
+
);
|
|
6128
|
+
|
|
6129
|
+
assert.notCalled(meeting.meetingRequest.sendReaction);
|
|
6130
|
+
});
|
|
6131
|
+
|
|
6132
|
+
it('should fail sending a reaction if reactionType is invalid ', async () => {
|
|
6133
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: 'Fake URL'}};
|
|
6134
|
+
|
|
6135
|
+
await assert.isRejected(
|
|
6136
|
+
meeting.sendReaction('invalid_reaction', 'light'),
|
|
6137
|
+
Error,
|
|
6138
|
+
'invalid_reaction is not a valid reaction.'
|
|
6139
|
+
);
|
|
6140
|
+
|
|
6141
|
+
assert.notCalled(meeting.meetingRequest.sendReaction);
|
|
6142
|
+
});
|
|
6143
|
+
|
|
6144
|
+
it('should send a reaction with default skin tone if provided skinToneType is invalid ', async () => {
|
|
6145
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: 'Fake URL'}};
|
|
6146
|
+
|
|
6147
|
+
const reactionPromise = meeting.sendReaction('thumb_down', 'invalid_skin_tone');
|
|
6148
|
+
|
|
6149
|
+
assert.exists(reactionPromise.then);
|
|
6150
|
+
await reactionPromise;
|
|
6151
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.sendReaction, {
|
|
6152
|
+
reactionChannelUrl: 'Fake URL',
|
|
6153
|
+
reaction: {
|
|
6154
|
+
type: 'thumb_down',
|
|
6155
|
+
codepoints: '1F44E',
|
|
6156
|
+
shortcodes: ':thumbsdown:',
|
|
6157
|
+
tone: {type: 'normal_skin_tone', codepoints: '', shortcodes: ''},
|
|
6158
|
+
},
|
|
6159
|
+
participantId: meeting.members.selfId,
|
|
6160
|
+
});
|
|
6161
|
+
});
|
|
6162
|
+
|
|
6163
|
+
it('should send a reaction with default skin tone if none provided', async () => {
|
|
6164
|
+
meeting.locusInfo.controls = {reactions: {reactionChannelUrl: 'Fake URL'}};
|
|
6165
|
+
|
|
6166
|
+
const reactionPromise = meeting.sendReaction('thumb_down');
|
|
6167
|
+
|
|
6168
|
+
assert.exists(reactionPromise.then);
|
|
6169
|
+
await reactionPromise;
|
|
6170
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.sendReaction, {
|
|
6171
|
+
reactionChannelUrl: 'Fake URL',
|
|
6172
|
+
reaction: {
|
|
6173
|
+
type: 'thumb_down',
|
|
6174
|
+
codepoints: '1F44E',
|
|
6175
|
+
shortcodes: ':thumbsdown:',
|
|
6176
|
+
tone: {type: 'normal_skin_tone', codepoints: '', shortcodes: ''},
|
|
6177
|
+
},
|
|
6178
|
+
participantId: meeting.members.selfId,
|
|
6179
|
+
});
|
|
6180
|
+
});
|
|
6181
|
+
});
|
|
6182
|
+
describe('#toggleReactions', () => {
|
|
6183
|
+
it('should have #toggleReactions', () => {
|
|
6184
|
+
assert.exists(meeting.toggleReactions);
|
|
6185
|
+
});
|
|
6186
|
+
|
|
6187
|
+
beforeEach(() => {
|
|
6188
|
+
meeting.meetingRequest.toggleReactions = sinon.stub().returns(Promise.resolve());
|
|
6189
|
+
});
|
|
6190
|
+
|
|
6191
|
+
it('should toggle the reactions with the right data and return a promise', async () => {
|
|
6192
|
+
meeting.locusUrl = 'locusUrl';
|
|
6193
|
+
meeting.locusInfo.controls = {reactions: {enabled: false}};
|
|
6194
|
+
|
|
6195
|
+
const togglePromise = meeting.toggleReactions(true);
|
|
6196
|
+
|
|
6197
|
+
assert.exists(togglePromise.then);
|
|
6198
|
+
await togglePromise;
|
|
6199
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.toggleReactions, {
|
|
6200
|
+
locusUrl: 'locusUrl',
|
|
6201
|
+
enable: true,
|
|
6202
|
+
requestingParticipantId: meeting.members.selfId,
|
|
6203
|
+
});
|
|
6204
|
+
});
|
|
6205
|
+
|
|
6206
|
+
it('should resolve immediately if already enabled', async () => {
|
|
6207
|
+
meeting.locusUrl = 'locusUrl';
|
|
6208
|
+
meeting.locusInfo.controls = {reactions: {enabled: true}};
|
|
6209
|
+
|
|
6210
|
+
const togglePromise = meeting.toggleReactions(true);
|
|
6211
|
+
|
|
6212
|
+
const response = await togglePromise;
|
|
6213
|
+
|
|
6214
|
+
assert.equal(response, 'Reactions are already enabled.');
|
|
6215
|
+
assert.notCalled(meeting.meetingRequest.toggleReactions);
|
|
6216
|
+
});
|
|
6217
|
+
|
|
6218
|
+
it('should resolve immediately if already disabled', async () => {
|
|
6219
|
+
meeting.locusUrl = 'locusUrl';
|
|
6220
|
+
meeting.locusInfo.controls = {reactions: {enabled: false}};
|
|
6221
|
+
|
|
6222
|
+
const togglePromise = meeting.toggleReactions(false);
|
|
6223
|
+
|
|
6224
|
+
const response = await togglePromise;
|
|
6225
|
+
|
|
6226
|
+
assert.equal(response, 'Reactions are already disabled.');
|
|
6227
|
+
assert.notCalled(meeting.meetingRequest.toggleReactions);
|
|
6228
|
+
});
|
|
6229
|
+
|
|
6230
|
+
it('should toggle reactions on if controls is undefined and enable = true', async () => {
|
|
6231
|
+
meeting.locusUrl = 'locusUrl';
|
|
6232
|
+
meeting.locusInfo.controls = undefined;
|
|
6233
|
+
|
|
6234
|
+
const togglePromise = meeting.toggleReactions(true);
|
|
6235
|
+
|
|
6236
|
+
assert.exists(togglePromise.then);
|
|
6237
|
+
await togglePromise;
|
|
6238
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.toggleReactions, {
|
|
6239
|
+
locusUrl: 'locusUrl',
|
|
6240
|
+
enable: true,
|
|
6241
|
+
requestingParticipantId: meeting.members.selfId,
|
|
6242
|
+
});
|
|
6243
|
+
});
|
|
6244
|
+
});
|
|
4777
6245
|
});
|
|
4778
6246
|
});
|
|
4779
6247
|
});
|