@webex/plugin-meetings 3.0.0-beta.2 → 3.0.0-beta.200
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/README.md +45 -7
- package/UPGRADING.md +9 -9
- package/browsers.js +19 -24
- package/dist/annotation/annotation.types.js +7 -0
- package/dist/annotation/annotation.types.js.map +1 -0
- package/dist/annotation/constants.js +49 -0
- package/dist/annotation/constants.js.map +1 -0
- package/dist/annotation/index.js +342 -0
- package/dist/annotation/index.js.map +1 -0
- package/dist/breakouts/breakout.js +216 -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/edit-lock-error.js +52 -0
- package/dist/breakouts/edit-lock-error.js.map +1 -0
- package/dist/breakouts/events.js +45 -0
- package/dist/breakouts/events.js.map +1 -0
- package/dist/breakouts/index.js +1048 -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 +67 -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 +9 -43
- 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 +28 -23
- package/dist/common/queue.js.map +1 -1
- package/dist/config.js +8 -13
- package/dist/config.js.map +1 -1
- package/dist/constants.js +250 -66
- 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 +27 -0
- package/dist/controls-options-manager/enums.js.map +1 -0
- package/dist/controls-options-manager/index.js +297 -0
- package/dist/controls-options-manager/index.js.map +1 -0
- package/dist/controls-options-manager/types.js +7 -0
- package/dist/controls-options-manager/types.js.map +1 -0
- package/dist/controls-options-manager/util.js +319 -0
- package/dist/controls-options-manager/util.js.map +1 -0
- package/dist/index.js +108 -17
- package/dist/index.js.map +1 -1
- package/dist/interpretation/collection.js +23 -0
- package/dist/interpretation/collection.js.map +1 -0
- package/dist/interpretation/index.js +366 -0
- package/dist/interpretation/index.js.map +1 -0
- package/dist/interpretation/siLanguage.js +25 -0
- package/dist/interpretation/siLanguage.js.map +1 -0
- package/dist/locus-info/controlsUtils.js +101 -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 +532 -240
- 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 +54 -38
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.js +284 -154
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +110 -92
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +95 -226
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +99 -194
- 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/in-meeting-actions.js +83 -14
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +3478 -3563
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +291 -0
- package/dist/meeting/locusMediaRequest.js.map +1 -0
- package/dist/meeting/muteState.js +247 -183
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +344 -344
- 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 +529 -588
- 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 +62 -39
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +328 -283
- 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 +156 -232
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +26 -19
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +795 -574
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.js +7 -0
- package/dist/meetings/meetings.types.js.map +1 -0
- package/dist/meetings/request.js +26 -41
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +186 -155
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +126 -85
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js +25 -0
- package/dist/member/types.js.map +1 -0
- package/dist/member/util.js +147 -88
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js +13 -12
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +178 -204
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +113 -68
- package/dist/members/request.js.map +1 -1
- package/dist/members/types.js +15 -0
- package/dist/members/types.js.map +1 -0
- package/dist/members/util.js +314 -260
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +4 -7
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +11 -558
- package/dist/metrics/index.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +264 -50
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +58 -65
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +76 -95
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +62 -76
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +66 -43
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +502 -442
- 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 +192 -191
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +15 -23
- 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 +384 -476
- 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 +363 -0
- package/dist/recording-controller/index.js.map +1 -0
- package/dist/recording-controller/util.js +64 -0
- package/dist/recording-controller/util.js.map +1 -0
- package/dist/roap/index.js +58 -91
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +137 -135
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +148 -100
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/rtcMetrics/constants.js +12 -0
- package/dist/rtcMetrics/constants.js.map +1 -0
- package/dist/rtcMetrics/index.js +115 -0
- package/dist/rtcMetrics/index.js.map +1 -0
- package/dist/statsAnalyzer/global.js +1 -95
- package/dist/statsAnalyzer/global.js.map +1 -1
- package/dist/statsAnalyzer/index.js +385 -460
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +143 -87
- 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/annotation/annotation.types.d.ts +42 -0
- package/dist/types/annotation/constants.d.ts +31 -0
- package/dist/types/annotation/index.d.ts +117 -0
- package/dist/types/breakouts/breakout.d.ts +8 -0
- package/dist/types/breakouts/collection.d.ts +5 -0
- package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
- package/dist/types/breakouts/events.d.ts +8 -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 +15 -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 +34 -0
- package/dist/types/config.d.ts +72 -0
- package/dist/types/constants.d.ts +1016 -0
- package/dist/types/controls-options-manager/constants.d.ts +4 -0
- package/dist/types/controls-options-manager/enums.d.ts +15 -0
- package/dist/types/controls-options-manager/index.d.ts +136 -0
- package/dist/types/controls-options-manager/types.d.ts +43 -0
- package/dist/types/controls-options-manager/util.d.ts +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/interpretation/collection.d.ts +5 -0
- package/dist/types/interpretation/index.d.ts +5 -0
- package/dist/types/interpretation/siLanguage.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 +322 -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 +271 -0
- package/dist/types/locus-info/selfUtils.d.ts +2 -0
- package/dist/types/media/index.d.ts +34 -0
- package/dist/types/media/properties.d.ts +93 -0
- package/dist/types/media/util.d.ts +2 -0
- package/dist/types/mediaQualityMetrics/config.d.ts +365 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +153 -0
- package/dist/types/meeting/index.d.ts +1471 -0
- package/dist/types/meeting/locusMediaRequest.d.ts +70 -0
- package/dist/types/meeting/muteState.d.ts +184 -0
- package/dist/types/meeting/request.d.ts +257 -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 +78 -0
- package/dist/types/meeting-info/collection.d.ts +20 -0
- package/dist/types/meeting-info/index.d.ts +62 -0
- package/dist/types/meeting-info/meeting-info-v2.d.ts +122 -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 +31 -0
- package/dist/types/meetings/index.d.ts +367 -0
- package/dist/types/meetings/meetings.types.d.ts +4 -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 +159 -0
- package/dist/types/member/types.d.ts +32 -0
- package/dist/types/member/util.d.ts +2 -0
- package/dist/types/members/collection.d.ts +29 -0
- package/dist/types/members/index.d.ts +353 -0
- package/dist/types/members/request.d.ts +114 -0
- package/dist/types/members/types.d.ts +24 -0
- package/dist/types/members/util.d.ts +210 -0
- package/dist/types/metrics/constants.d.ts +55 -0
- package/dist/types/metrics/index.d.ts +45 -0
- package/dist/types/multistream/mediaRequestManager.d.ts +118 -0
- package/dist/types/multistream/receiveSlot.d.ts +68 -0
- package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
- package/dist/types/multistream/remoteMedia.d.ts +72 -0
- package/dist/types/multistream/remoteMediaGroup.d.ts +47 -0
- package/dist/types/multistream/remoteMediaManager.d.ts +277 -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 +152 -0
- package/dist/types/reachability/request.d.ts +37 -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 +126 -0
- package/dist/types/recording-controller/enums.d.ts +7 -0
- package/dist/types/recording-controller/index.d.ts +208 -0
- package/dist/types/recording-controller/util.d.ts +14 -0
- package/dist/types/roap/index.d.ts +77 -0
- package/dist/types/roap/request.d.ts +36 -0
- package/dist/types/roap/turnDiscovery.d.ts +91 -0
- package/dist/types/rtcMetrics/constants.d.ts +4 -0
- package/dist/types/rtcMetrics/index.d.ts +46 -0
- package/dist/types/statsAnalyzer/global.d.ts +36 -0
- package/dist/types/statsAnalyzer/index.d.ts +200 -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 +29 -21
- package/src/annotation/annotation.types.ts +50 -0
- package/src/annotation/constants.ts +36 -0
- package/src/annotation/index.ts +328 -0
- package/src/breakouts/README.md +220 -0
- package/src/breakouts/breakout.ts +188 -0
- package/src/breakouts/collection.ts +19 -0
- package/src/breakouts/edit-lock-error.ts +25 -0
- package/src/breakouts/events.ts +56 -0
- package/src/breakouts/index.ts +925 -0
- package/src/breakouts/request.ts +55 -0
- package/src/breakouts/utils.ts +57 -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} +14 -9
- 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 +22 -9
- package/src/{config.js → config.ts} +17 -17
- package/src/constants.ts +197 -22
- package/src/controls-options-manager/constants.ts +5 -0
- package/src/controls-options-manager/enums.ts +18 -0
- package/src/controls-options-manager/index.ts +278 -0
- package/src/controls-options-manager/types.ts +59 -0
- package/src/controls-options-manager/util.ts +300 -0
- package/src/index.ts +39 -0
- package/src/interpretation/README.md +60 -0
- package/src/interpretation/collection.ts +19 -0
- package/src/interpretation/index.ts +332 -0
- package/src/interpretation/siLanguage.ts +18 -0
- package/src/locus-info/controlsUtils.ts +222 -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} +518 -111
- package/src/locus-info/{infoUtils.js → infoUtils.ts} +19 -8
- package/src/locus-info/{mediaSharesUtils.js → mediaSharesUtils.ts} +65 -17
- package/src/locus-info/{parser.js → parser.ts} +271 -98
- package/src/locus-info/{selfUtils.js → selfUtils.ts} +199 -68
- package/src/media/index.ts +456 -0
- package/src/media/{properties.js → properties.ts} +80 -102
- package/src/media/{util.js → util.ts} +2 -2
- package/src/mediaQualityMetrics/config.ts +384 -0
- package/src/meeting/in-meeting-actions.ts +171 -3
- package/src/meeting/index.ts +7070 -0
- package/src/meeting/locusMediaRequest.ts +309 -0
- package/src/meeting/muteState.ts +450 -0
- package/src/meeting/{request.js → request.ts} +354 -214
- package/src/meeting/request.type.ts +13 -0
- package/src/meeting/{state.js → state.ts} +50 -35
- package/src/meeting/util.ts +615 -0
- package/src/meeting-info/{collection.js → collection.ts} +6 -2
- package/src/meeting-info/index.ts +183 -0
- package/src/meeting-info/meeting-info-v2.ts +407 -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} +77 -60
- package/src/meetings/{collection.js → collection.ts} +26 -3
- package/src/meetings/index.ts +1467 -0
- package/src/meetings/meetings.types.ts +12 -0
- package/src/meetings/{request.js → request.ts} +34 -25
- package/src/meetings/{util.js → util.ts} +137 -36
- package/src/member/{index.js → index.ts} +151 -56
- package/src/member/types.ts +38 -0
- package/src/member/util.ts +383 -0
- package/src/members/{collection.js → collection.ts} +10 -2
- package/src/members/{index.js → index.ts} +323 -145
- package/src/members/request.ts +255 -0
- package/src/members/types.ts +28 -0
- package/src/members/util.ts +339 -0
- package/src/metrics/{constants.js → constants.ts} +2 -6
- package/src/metrics/index.ts +73 -0
- package/src/multistream/mediaRequestManager.ts +337 -61
- package/src/multistream/receiveSlot.ts +69 -26
- package/src/multistream/receiveSlotManager.ts +66 -42
- package/src/multistream/remoteMedia.ts +40 -5
- package/src/multistream/remoteMediaGroup.ts +63 -3
- package/src/multistream/remoteMediaManager.ts +263 -66
- 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} +157 -94
- package/src/reachability/request.ts +46 -35
- 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} +254 -136
- package/src/recording-controller/enums.ts +8 -0
- package/src/recording-controller/index.ts +333 -0
- package/src/recording-controller/util.ts +75 -0
- package/src/roap/{index.js → index.ts} +86 -78
- package/src/roap/request.ts +163 -0
- package/src/roap/turnDiscovery.ts +111 -49
- package/src/rtcMetrics/constants.ts +3 -0
- package/src/rtcMetrics/index.ts +96 -0
- package/src/statsAnalyzer/global.ts +37 -0
- package/src/statsAnalyzer/index.ts +1272 -0
- package/src/statsAnalyzer/mqaUtil.ts +291 -0
- package/src/transcription/{index.js → index.ts} +46 -39
- package/test/integration/spec/converged-space-meetings.js +233 -0
- package/test/integration/spec/journey.js +804 -526
- package/test/integration/spec/space-meeting.js +391 -204
- package/test/integration/spec/transcription.js +7 -8
- package/test/unit/spec/annotation/index.ts +418 -0
- package/test/unit/spec/breakouts/breakout.ts +237 -0
- package/test/unit/spec/breakouts/collection.ts +15 -0
- package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
- package/test/unit/spec/breakouts/events.ts +89 -0
- package/test/unit/spec/breakouts/index.ts +1790 -0
- package/test/unit/spec/breakouts/request.ts +104 -0
- package/test/unit/spec/breakouts/utils.js +72 -0
- package/test/unit/spec/common/browser-detection.js +9 -28
- package/test/unit/spec/common/queue.js +31 -2
- package/test/unit/spec/controls-options-manager/index.js +287 -0
- package/test/unit/spec/controls-options-manager/util.js +582 -0
- package/test/unit/spec/fixture/locus.js +93 -90
- package/test/unit/spec/interpretation/collection.ts +15 -0
- package/test/unit/spec/interpretation/index.ts +589 -0
- package/test/unit/spec/interpretation/siLanguage.ts +28 -0
- package/test/unit/spec/locus-info/controlsUtils.js +325 -32
- package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
- package/test/unit/spec/locus-info/index.js +1176 -18
- 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/mediaSharesUtils.ts +22 -0
- package/test/unit/spec/locus-info/parser.js +65 -31
- package/test/unit/spec/locus-info/selfConstant.js +120 -103
- package/test/unit/spec/locus-info/selfUtils.js +296 -12
- package/test/unit/spec/media/index.ts +162 -68
- package/test/unit/spec/media/properties.ts +9 -9
- package/test/unit/spec/meeting/in-meeting-actions.ts +82 -3
- package/test/unit/spec/meeting/index.js +4569 -1773
- package/test/unit/spec/meeting/locusMediaRequest.ts +436 -0
- package/test/unit/spec/meeting/muteState.js +382 -211
- package/test/unit/spec/meeting/request.js +444 -78
- package/test/unit/spec/meeting/utils.js +517 -192
- package/test/unit/spec/meeting-info/index.js +181 -0
- package/test/unit/spec/meeting-info/meetinginfov2.js +481 -76
- 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 +131 -74
- package/test/unit/spec/meetings/collection.js +15 -1
- package/test/unit/spec/meetings/index.js +1254 -330
- package/test/unit/spec/meetings/utils.js +220 -14
- package/test/unit/spec/member/index.js +58 -5
- package/test/unit/spec/member/util.js +494 -26
- package/test/unit/spec/members/index.js +423 -55
- package/test/unit/spec/members/request.js +228 -40
- package/test/unit/spec/members/utils.js +191 -4
- package/test/unit/spec/metrics/index.js +12 -66
- package/test/unit/spec/multistream/mediaRequestManager.ts +1013 -106
- package/test/unit/spec/multistream/receiveSlot.ts +77 -18
- package/test/unit/spec/multistream/receiveSlotManager.ts +69 -39
- package/test/unit/spec/multistream/remoteMedia.ts +40 -2
- package/test/unit/spec/multistream/remoteMediaGroup.ts +271 -5
- package/test/unit/spec/multistream/remoteMediaManager.ts +730 -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 +176 -27
- package/test/unit/spec/reachability/request.js +66 -0
- package/test/unit/spec/reconnection-manager/index.js +155 -9
- package/test/unit/spec/recording-controller/index.js +307 -0
- package/test/unit/spec/recording-controller/util.js +229 -0
- package/test/unit/spec/roap/index.ts +28 -52
- package/test/unit/spec/roap/request.ts +225 -0
- package/test/unit/spec/roap/turnDiscovery.ts +92 -50
- package/test/unit/spec/rtcMetrics/index.ts +60 -0
- package/test/unit/spec/stats-analyzer/index.js +116 -60
- package/test/utils/cmr.js +44 -42
- package/test/utils/constants.js +9 -0
- package/test/utils/integrationTestUtils.js +46 -0
- package/test/utils/testUtils.js +63 -99
- 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/meeting/effectsState.js +0 -327
- package/dist/meeting/effectsState.js.map +0 -1
- package/dist/metrics/config.js +0 -301
- package/dist/metrics/config.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/index.js +0 -15
- package/src/locus-info/controlsUtils.js +0 -102
- package/src/media/index.js +0 -459
- package/src/media/internal-media-core-wrapper.ts +0 -9
- package/src/mediaQualityMetrics/config.js +0 -382
- package/src/meeting/effectsState.js +0 -205
- package/src/meeting/index.js +0 -6284
- package/src/meeting/muteState.js +0 -318
- package/src/meeting/util.js +0 -506
- package/src/meeting-info/index.js +0 -131
- package/src/meeting-info/meeting-info-v2.js +0 -255
- package/src/meetings/index.js +0 -1015
- package/src/member/util.js +0 -254
- package/src/members/request.js +0 -131
- package/src/members/util.js +0 -258
- package/src/metrics/config.js +0 -324
- package/src/metrics/index.js +0 -530
- 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/meeting/effectsState.js +0 -291
- 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
|
@@ -3,6 +3,7 @@ import sinon from 'sinon';
|
|
|
3
3
|
import {cloneDeep} from 'lodash';
|
|
4
4
|
import {assert} from '@webex/test-helper-chai';
|
|
5
5
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
6
|
+
import testUtils from '../../../utils/testUtils';
|
|
6
7
|
import Meetings from '@webex/plugin-meetings';
|
|
7
8
|
import LocusInfo from '@webex/plugin-meetings/src/locus-info';
|
|
8
9
|
import SelfUtils from '@webex/plugin-meetings/src/locus-info/selfUtils';
|
|
@@ -16,9 +17,14 @@ import {
|
|
|
16
17
|
LOCUSEVENT,
|
|
17
18
|
EVENTS,
|
|
18
19
|
DISPLAY_HINTS,
|
|
20
|
+
_CALL_,
|
|
21
|
+
LOCUS,
|
|
22
|
+
MEETING_STATE,
|
|
23
|
+
_MEETING_,
|
|
19
24
|
} from '../../../../src/constants';
|
|
20
25
|
|
|
21
26
|
import {self, selfWithInactivity} from './selfConstant';
|
|
27
|
+
import uuid from 'uuid';
|
|
22
28
|
|
|
23
29
|
describe('plugin-meetings', () => {
|
|
24
30
|
describe('LocusInfo index', () => {
|
|
@@ -66,8 +72,12 @@ describe('plugin-meetings', () => {
|
|
|
66
72
|
|
|
67
73
|
beforeEach('setup new controls', () => {
|
|
68
74
|
newControls = {
|
|
75
|
+
disallowUnmute: {enabled: true},
|
|
69
76
|
lock: {},
|
|
70
77
|
meetingFull: {},
|
|
78
|
+
muteOnEntry: {enabled: true},
|
|
79
|
+
raiseHand: {enabled: true},
|
|
80
|
+
reactions: {enabled: true, showDisplayNameWithReactions: true},
|
|
71
81
|
record: {
|
|
72
82
|
recording: false,
|
|
73
83
|
paused: false,
|
|
@@ -76,12 +86,14 @@ describe('plugin-meetings', () => {
|
|
|
76
86
|
modifiedBy: 'George Kittle',
|
|
77
87
|
},
|
|
78
88
|
},
|
|
79
|
-
shareControl: {},
|
|
89
|
+
shareControl: {control: 'example-value'},
|
|
80
90
|
transcribe: {},
|
|
91
|
+
viewTheParticipantList: {enabled: true},
|
|
81
92
|
meetingContainer: {
|
|
82
93
|
meetingContainerUrl: 'http://new-url.com',
|
|
83
94
|
},
|
|
84
95
|
entryExitTone: {enabled: true, mode: 'foo'},
|
|
96
|
+
video: {enabled: true},
|
|
85
97
|
};
|
|
86
98
|
});
|
|
87
99
|
|
|
@@ -95,6 +107,97 @@ describe('plugin-meetings', () => {
|
|
|
95
107
|
assert.equal(locusInfo.controls, newControls);
|
|
96
108
|
});
|
|
97
109
|
|
|
110
|
+
it('should trigger the CONTROLS_MUTE_ON_ENTRY_CHANGED event when necessary', () => {
|
|
111
|
+
locusInfo.controls = {};
|
|
112
|
+
locusInfo.emitScoped = sinon.stub();
|
|
113
|
+
locusInfo.updateControls(newControls);
|
|
114
|
+
|
|
115
|
+
assert.calledWith(
|
|
116
|
+
locusInfo.emitScoped,
|
|
117
|
+
{file: 'locus-info', function: 'updateControls'},
|
|
118
|
+
LOCUSINFO.EVENTS.CONTROLS_MUTE_ON_ENTRY_CHANGED,
|
|
119
|
+
{state: newControls.muteOnEntry}
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should trigger the CONTROLS_SHARE_CONTROL_CHANGED event when necessary', () => {
|
|
124
|
+
locusInfo.controls = {};
|
|
125
|
+
locusInfo.emitScoped = sinon.stub();
|
|
126
|
+
locusInfo.updateControls(newControls);
|
|
127
|
+
|
|
128
|
+
assert.calledWith(
|
|
129
|
+
locusInfo.emitScoped,
|
|
130
|
+
{file: 'locus-info', function: 'updateControls'},
|
|
131
|
+
LOCUSINFO.EVENTS.CONTROLS_SHARE_CONTROL_CHANGED,
|
|
132
|
+
{state: newControls.shareControl}
|
|
133
|
+
);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('should trigger the CONTROLS_DISALLOW_UNMUTE_CHANGED event when necessary', () => {
|
|
137
|
+
locusInfo.controls = {};
|
|
138
|
+
locusInfo.emitScoped = sinon.stub();
|
|
139
|
+
locusInfo.updateControls(newControls);
|
|
140
|
+
|
|
141
|
+
assert.calledWith(
|
|
142
|
+
locusInfo.emitScoped,
|
|
143
|
+
{file: 'locus-info', function: 'updateControls'},
|
|
144
|
+
LOCUSINFO.EVENTS.CONTROLS_DISALLOW_UNMUTE_CHANGED,
|
|
145
|
+
{state: newControls.disallowUnmute}
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('should trigger the CONTROLS_REACTIONS_CHANGED event when necessary', () => {
|
|
150
|
+
locusInfo.controls = {};
|
|
151
|
+
locusInfo.emitScoped = sinon.stub();
|
|
152
|
+
locusInfo.updateControls(newControls);
|
|
153
|
+
|
|
154
|
+
assert.calledWith(
|
|
155
|
+
locusInfo.emitScoped,
|
|
156
|
+
{file: 'locus-info', function: 'updateControls'},
|
|
157
|
+
LOCUSINFO.EVENTS.CONTROLS_REACTIONS_CHANGED,
|
|
158
|
+
{state: newControls.reactions}
|
|
159
|
+
);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('should trigger the CONTROLS_VIEW_THE_PARTICIPANTS_LIST_CHANGED event when necessary', () => {
|
|
163
|
+
locusInfo.controls = {};
|
|
164
|
+
locusInfo.emitScoped = sinon.stub();
|
|
165
|
+
locusInfo.updateControls(newControls);
|
|
166
|
+
|
|
167
|
+
assert.calledWith(
|
|
168
|
+
locusInfo.emitScoped,
|
|
169
|
+
{file: 'locus-info', function: 'updateControls'},
|
|
170
|
+
LOCUSINFO.EVENTS.CONTROLS_VIEW_THE_PARTICIPANTS_LIST_CHANGED,
|
|
171
|
+
{state: newControls.viewTheParticipantList}
|
|
172
|
+
);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('should trigger the CONTROLS_RAISE_HAND_CHANGED event when necessary', () => {
|
|
176
|
+
locusInfo.controls = {};
|
|
177
|
+
locusInfo.emitScoped = sinon.stub();
|
|
178
|
+
locusInfo.updateControls(newControls);
|
|
179
|
+
|
|
180
|
+
assert.calledWith(
|
|
181
|
+
locusInfo.emitScoped,
|
|
182
|
+
{file: 'locus-info', function: 'updateControls'},
|
|
183
|
+
LOCUSINFO.EVENTS.CONTROLS_RAISE_HAND_CHANGED,
|
|
184
|
+
{state: newControls.raiseHand}
|
|
185
|
+
);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('should trigger the CONTROLS_VIDEO_CHANGED event when necessary', () => {
|
|
189
|
+
locusInfo.controls = {};
|
|
190
|
+
locusInfo.emitScoped = sinon.stub();
|
|
191
|
+
locusInfo.updateControls(newControls);
|
|
192
|
+
|
|
193
|
+
assert.calledWith(
|
|
194
|
+
locusInfo.emitScoped,
|
|
195
|
+
{file: 'locus-info', function: 'updateControls'},
|
|
196
|
+
LOCUSINFO.EVENTS.CONTROLS_VIDEO_CHANGED,
|
|
197
|
+
{state: newControls.video}
|
|
198
|
+
);
|
|
199
|
+
});
|
|
200
|
+
|
|
98
201
|
it('should not trigger the CONTROLS_RECORDING_UPDATED event', () => {
|
|
99
202
|
locusInfo.controls = {};
|
|
100
203
|
locusInfo.emitScoped = sinon.stub();
|
|
@@ -277,6 +380,48 @@ describe('plugin-meetings', () => {
|
|
|
277
380
|
);
|
|
278
381
|
});
|
|
279
382
|
|
|
383
|
+
it('should update the breakout state', () => {
|
|
384
|
+
locusInfo.emitScoped = sinon.stub();
|
|
385
|
+
let tmpStub = sinon.stub(SelfUtils, 'getReplacedBreakoutMoveId').returns('breakoutMoveId');
|
|
386
|
+
newControls.breakout = {breakout: {}};
|
|
387
|
+
let selfInfo = {};
|
|
388
|
+
|
|
389
|
+
locusInfo.updateControls(newControls, selfInfo);
|
|
390
|
+
|
|
391
|
+
assert.calledWith(
|
|
392
|
+
locusInfo.emitScoped,
|
|
393
|
+
{
|
|
394
|
+
file: 'locus-info',
|
|
395
|
+
function: 'updateControls',
|
|
396
|
+
},
|
|
397
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_BREAKOUT_UPDATED,
|
|
398
|
+
{
|
|
399
|
+
breakout: newControls.breakout,
|
|
400
|
+
}
|
|
401
|
+
);
|
|
402
|
+
tmpStub.restore();
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it('should update the interpretation state', () => {
|
|
406
|
+
locusInfo.emitScoped = sinon.stub();
|
|
407
|
+
newControls.interpretation = {siLanguages: [{languageCode: 20, languageName: 'en'}]};
|
|
408
|
+
let selfInfo = {};
|
|
409
|
+
|
|
410
|
+
locusInfo.updateControls(newControls, selfInfo);
|
|
411
|
+
|
|
412
|
+
assert.calledWith(
|
|
413
|
+
locusInfo.emitScoped,
|
|
414
|
+
{
|
|
415
|
+
file: 'locus-info',
|
|
416
|
+
function: 'updateControls',
|
|
417
|
+
},
|
|
418
|
+
LOCUSINFO.EVENTS.CONTROLS_MEETING_INTERPRETATION_UPDATED,
|
|
419
|
+
{
|
|
420
|
+
interpretation: newControls.interpretation,
|
|
421
|
+
}
|
|
422
|
+
);
|
|
423
|
+
});
|
|
424
|
+
|
|
280
425
|
it('should update the transcript state', () => {
|
|
281
426
|
locusInfo.emitScoped = sinon.stub();
|
|
282
427
|
locusInfo.controls = {
|
|
@@ -398,6 +543,39 @@ describe('plugin-meetings', () => {
|
|
|
398
543
|
assert.notEqual(x.args[1], LOCUSINFO.EVENTS.CONTROLS_ENTRY_EXIT_TONE_UPDATED);
|
|
399
544
|
});
|
|
400
545
|
});
|
|
546
|
+
|
|
547
|
+
it('should update videoEnabled when changed', () => {
|
|
548
|
+
locusInfo.controls = {};
|
|
549
|
+
|
|
550
|
+
locusInfo.emitScoped = sinon.stub();
|
|
551
|
+
locusInfo.updateControls(newControls);
|
|
552
|
+
|
|
553
|
+
assert.calledWith(
|
|
554
|
+
locusInfo.emitScoped,
|
|
555
|
+
{
|
|
556
|
+
file: 'locus-info',
|
|
557
|
+
function: 'updateControls',
|
|
558
|
+
},
|
|
559
|
+
LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED,
|
|
560
|
+
{unmuteAllowed: true}
|
|
561
|
+
);
|
|
562
|
+
|
|
563
|
+
assert.equal(mockMeeting.unmuteVideoAllowed, true);
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
it('should not update videoEnabled when unchanged', () => {
|
|
567
|
+
locusInfo.controls = {videoEnabled: true};
|
|
568
|
+
|
|
569
|
+
locusInfo.emitScoped = sinon.stub();
|
|
570
|
+
locusInfo.updateControls(newControls);
|
|
571
|
+
|
|
572
|
+
locusInfo.emitScoped.getCalls().forEach((x) => {
|
|
573
|
+
// check that no calls in emitScoped are for SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED
|
|
574
|
+
assert.notEqual(x.args[1], LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED);
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
assert.equal(mockMeeting.unmuteVideoAllowed, undefined);
|
|
578
|
+
});
|
|
401
579
|
});
|
|
402
580
|
|
|
403
581
|
describe('#updateParticipants()', () => {
|
|
@@ -451,6 +629,7 @@ describe('plugin-meetings', () => {
|
|
|
451
629
|
selfIdentity: '123',
|
|
452
630
|
selfId: '2',
|
|
453
631
|
hostId: '3',
|
|
632
|
+
isReplace: undefined,
|
|
454
633
|
}
|
|
455
634
|
);
|
|
456
635
|
// note: in a real use case, recordingId, selfId, and hostId would all be the same
|
|
@@ -458,6 +637,43 @@ describe('plugin-meetings', () => {
|
|
|
458
637
|
// are being correctly grabbed from locusInfo.parsedLocus within updateParticipants
|
|
459
638
|
});
|
|
460
639
|
|
|
640
|
+
it('should call with breakout control info', () => {
|
|
641
|
+
locusInfo.parsedLocus = {
|
|
642
|
+
controls: {
|
|
643
|
+
record: {
|
|
644
|
+
modifiedBy: '1',
|
|
645
|
+
},
|
|
646
|
+
},
|
|
647
|
+
self: {
|
|
648
|
+
selfIdentity: '123',
|
|
649
|
+
selfId: '2',
|
|
650
|
+
},
|
|
651
|
+
host: {
|
|
652
|
+
hostId: '3',
|
|
653
|
+
},
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
locusInfo.emitScoped = sinon.stub();
|
|
657
|
+
locusInfo.updateParticipants({}, true);
|
|
658
|
+
|
|
659
|
+
assert.calledWith(
|
|
660
|
+
locusInfo.emitScoped,
|
|
661
|
+
{
|
|
662
|
+
file: 'locus-info',
|
|
663
|
+
function: 'updateParticipants',
|
|
664
|
+
},
|
|
665
|
+
EVENTS.LOCUS_INFO_UPDATE_PARTICIPANTS,
|
|
666
|
+
{
|
|
667
|
+
participants: {},
|
|
668
|
+
recordingId: '1',
|
|
669
|
+
selfIdentity: '123',
|
|
670
|
+
selfId: '2',
|
|
671
|
+
hostId: '3',
|
|
672
|
+
isReplace: true,
|
|
673
|
+
}
|
|
674
|
+
);
|
|
675
|
+
});
|
|
676
|
+
|
|
461
677
|
it('should update the deltaParticipants object', () => {
|
|
462
678
|
const prev = locusInfo.deltaParticipants;
|
|
463
679
|
|
|
@@ -664,6 +880,122 @@ describe('plugin-meetings', () => {
|
|
|
664
880
|
);
|
|
665
881
|
});
|
|
666
882
|
|
|
883
|
+
describe('SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED', () => {
|
|
884
|
+
it('should emit event when video muted on entry', () => {
|
|
885
|
+
// usually "previous self" is just undefined when we get first self from locus
|
|
886
|
+
locusInfo.self = undefined;
|
|
887
|
+
const selfWithMutedByOthers = cloneDeep(self);
|
|
888
|
+
|
|
889
|
+
// remoteVideoMuted
|
|
890
|
+
selfWithMutedByOthers.controls.video.muted = true;
|
|
891
|
+
|
|
892
|
+
locusInfo.webex.internal.device.url = self.deviceUrl;
|
|
893
|
+
locusInfo.emitScoped = sinon.stub();
|
|
894
|
+
locusInfo.updateSelf(selfWithMutedByOthers, []);
|
|
895
|
+
|
|
896
|
+
assert.calledWith(
|
|
897
|
+
locusInfo.emitScoped,
|
|
898
|
+
{
|
|
899
|
+
file: 'locus-info',
|
|
900
|
+
function: 'updateSelf',
|
|
901
|
+
},
|
|
902
|
+
LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED,
|
|
903
|
+
{muted: true}
|
|
904
|
+
);
|
|
905
|
+
|
|
906
|
+
// but sometimes "previous self" is defined, but without controls.audio.muted, so we test this here:
|
|
907
|
+
locusInfo.self = cloneDeep(self);
|
|
908
|
+
locusInfo.self.controls.video = {};
|
|
909
|
+
|
|
910
|
+
locusInfo.updateSelf(selfWithMutedByOthers, []);
|
|
911
|
+
assert.calledWith(
|
|
912
|
+
locusInfo.emitScoped,
|
|
913
|
+
{
|
|
914
|
+
file: 'locus-info',
|
|
915
|
+
function: 'updateSelf',
|
|
916
|
+
},
|
|
917
|
+
LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED,
|
|
918
|
+
{muted: true}
|
|
919
|
+
);
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
it('should not emit event when not muted on entry', () => {
|
|
923
|
+
locusInfo.self = undefined;
|
|
924
|
+
const selfWithMutedByOthersFalse = cloneDeep(self);
|
|
925
|
+
|
|
926
|
+
selfWithMutedByOthersFalse.controls.video.muted = false;
|
|
927
|
+
|
|
928
|
+
locusInfo.webex.internal.device.url = self.deviceUrl;
|
|
929
|
+
locusInfo.emitScoped = sinon.stub();
|
|
930
|
+
locusInfo.updateSelf(selfWithMutedByOthersFalse, []);
|
|
931
|
+
|
|
932
|
+
// we might get some calls to emitScoped, but we need to check that none of them are for SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED
|
|
933
|
+
locusInfo.emitScoped.getCalls().forEach((x) => {
|
|
934
|
+
assert.notEqual(x.args[1], LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED);
|
|
935
|
+
});
|
|
936
|
+
});
|
|
937
|
+
|
|
938
|
+
it('should emit event when remoteVideoMuted changed', () => {
|
|
939
|
+
locusInfo.self = self;
|
|
940
|
+
const selfWithMutedByOthers = cloneDeep(self);
|
|
941
|
+
|
|
942
|
+
selfWithMutedByOthers.controls.video.muted = true;
|
|
943
|
+
|
|
944
|
+
locusInfo.webex.internal.device.url = self.deviceUrl;
|
|
945
|
+
locusInfo.emitScoped = sinon.stub();
|
|
946
|
+
locusInfo.updateSelf(selfWithMutedByOthers, []);
|
|
947
|
+
|
|
948
|
+
assert.calledWith(
|
|
949
|
+
locusInfo.emitScoped,
|
|
950
|
+
{
|
|
951
|
+
file: 'locus-info',
|
|
952
|
+
function: 'updateSelf',
|
|
953
|
+
},
|
|
954
|
+
LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED,
|
|
955
|
+
{muted: true}
|
|
956
|
+
);
|
|
957
|
+
});
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
it('should trigger SELF_MEETING_BREAKOUTS_CHANGED when breakouts changed', () => {
|
|
961
|
+
locusInfo.self = self;
|
|
962
|
+
const selfWithBreakoutsChanged = cloneDeep(self);
|
|
963
|
+
|
|
964
|
+
selfWithBreakoutsChanged.controls.breakout.sessions.active[0].name = 'new name';
|
|
965
|
+
|
|
966
|
+
locusInfo.emitScoped = sinon.stub();
|
|
967
|
+
locusInfo.updateSelf(selfWithBreakoutsChanged, []);
|
|
968
|
+
|
|
969
|
+
assert.calledWith(
|
|
970
|
+
locusInfo.emitScoped,
|
|
971
|
+
{
|
|
972
|
+
file: 'locus-info',
|
|
973
|
+
function: 'updateSelf',
|
|
974
|
+
},
|
|
975
|
+
LOCUSINFO.EVENTS.SELF_MEETING_BREAKOUTS_CHANGED,
|
|
976
|
+
{
|
|
977
|
+
breakoutSessions: {
|
|
978
|
+
active: [
|
|
979
|
+
{
|
|
980
|
+
name: 'new name',
|
|
981
|
+
groupId: '0e73abb8-5584-49d8-be8d-806d2a8247ca',
|
|
982
|
+
sessionId: '1cf41ab1-2e57-4d95-b7e9-5613acddfb0f',
|
|
983
|
+
sessionType: 'BREAKOUT',
|
|
984
|
+
},
|
|
985
|
+
],
|
|
986
|
+
allowed: [
|
|
987
|
+
{
|
|
988
|
+
name: 'Breakout session 2',
|
|
989
|
+
groupId: '0e73abb8-5584-49d8-be8d-806d2a8247ca',
|
|
990
|
+
sessionId: '1cf41ab1-2e57-4d95-b7e9-5613acddfb0f',
|
|
991
|
+
sessionType: 'BREAKOUT',
|
|
992
|
+
},
|
|
993
|
+
],
|
|
994
|
+
},
|
|
995
|
+
}
|
|
996
|
+
);
|
|
997
|
+
});
|
|
998
|
+
|
|
667
999
|
it('should trigger SELF_REMOTE_MUTE_STATUS_UPDATED if muted and disallowUnmute changed', () => {
|
|
668
1000
|
locusInfo.self = self;
|
|
669
1001
|
const selfWithMutedByOthersAndDissalowUnmute = cloneDeep(self);
|
|
@@ -735,6 +1067,8 @@ describe('plugin-meetings', () => {
|
|
|
735
1067
|
const selfWithRequestedToUnmute = cloneDeep(self);
|
|
736
1068
|
|
|
737
1069
|
selfWithRequestedToUnmute.controls.audio.requestedToUnmute = true;
|
|
1070
|
+
selfWithRequestedToUnmute.controls.audio.lastModifiedRequestedToUnmute =
|
|
1071
|
+
'2023-06-16T19:25:04.369Z';
|
|
738
1072
|
|
|
739
1073
|
locusInfo.webex.internal.device.url = self.deviceUrl;
|
|
740
1074
|
locusInfo.emitScoped = sinon.stub();
|
|
@@ -889,6 +1223,88 @@ describe('plugin-meetings', () => {
|
|
|
889
1223
|
{isSharingBlocked: true}
|
|
890
1224
|
);
|
|
891
1225
|
});
|
|
1226
|
+
|
|
1227
|
+
it('should trigger SELF_ROLES_CHANGED if self roles changed', () => {
|
|
1228
|
+
locusInfo.self = self;
|
|
1229
|
+
locusInfo.emitScoped = sinon.stub();
|
|
1230
|
+
const sampleNewSelf = cloneDeep(self);
|
|
1231
|
+
sampleNewSelf.controls.role.roles = [{type: 'COHOST', hasRole: true}];
|
|
1232
|
+
|
|
1233
|
+
locusInfo.updateSelf(sampleNewSelf, []);
|
|
1234
|
+
|
|
1235
|
+
assert.calledWith(
|
|
1236
|
+
locusInfo.emitScoped,
|
|
1237
|
+
{
|
|
1238
|
+
file: 'locus-info',
|
|
1239
|
+
function: 'updateSelf',
|
|
1240
|
+
},
|
|
1241
|
+
LOCUSINFO.EVENTS.SELF_ROLES_CHANGED,
|
|
1242
|
+
{oldRoles: ['PRESENTER'], newRoles: ['COHOST']}
|
|
1243
|
+
);
|
|
1244
|
+
});
|
|
1245
|
+
|
|
1246
|
+
it('should not trigger SELF_ROLES_CHANGED if self roles not changed', () => {
|
|
1247
|
+
locusInfo.self = self;
|
|
1248
|
+
locusInfo.emitScoped = sinon.stub();
|
|
1249
|
+
const sampleNewSelf = cloneDeep(self);
|
|
1250
|
+
sampleNewSelf.controls.role.roles = [{type: 'PRESENTER', hasRole: true}];
|
|
1251
|
+
|
|
1252
|
+
locusInfo.updateSelf(sampleNewSelf, []);
|
|
1253
|
+
|
|
1254
|
+
assert.neverCalledWith(
|
|
1255
|
+
locusInfo.emitScoped,
|
|
1256
|
+
{
|
|
1257
|
+
file: 'locus-info',
|
|
1258
|
+
function: 'updateSelf',
|
|
1259
|
+
},
|
|
1260
|
+
LOCUSINFO.EVENTS.SELF_ROLES_CHANGED,
|
|
1261
|
+
{oldRoles: ['PRESENTER'], newRoles: ['PRESENTER']}
|
|
1262
|
+
);
|
|
1263
|
+
});
|
|
1264
|
+
|
|
1265
|
+
it('should trigger SELF_MEETING_INTERPRETATION_CHANGED if self interpretation info changed', () => {
|
|
1266
|
+
locusInfo.self = self;
|
|
1267
|
+
locusInfo.emitScoped = sinon.stub();
|
|
1268
|
+
const sampleNewSelf = cloneDeep(self);
|
|
1269
|
+
sampleNewSelf.controls.interpretation.targetLanguage = 'it';
|
|
1270
|
+
|
|
1271
|
+
locusInfo.updateSelf(sampleNewSelf, []);
|
|
1272
|
+
|
|
1273
|
+
assert.calledWith(
|
|
1274
|
+
locusInfo.emitScoped,
|
|
1275
|
+
{
|
|
1276
|
+
file: 'locus-info',
|
|
1277
|
+
function: 'updateSelf',
|
|
1278
|
+
},
|
|
1279
|
+
LOCUSINFO.EVENTS.SELF_MEETING_INTERPRETATION_CHANGED,
|
|
1280
|
+
{
|
|
1281
|
+
interpretation: sampleNewSelf.controls.interpretation,
|
|
1282
|
+
selfParticipantId: self.id,
|
|
1283
|
+
}
|
|
1284
|
+
);
|
|
1285
|
+
});
|
|
1286
|
+
|
|
1287
|
+
it('should not trigger SELF_MEETING_INTERPRETATION_CHANGED if self interpretation info not changed', () => {
|
|
1288
|
+
locusInfo.self = self;
|
|
1289
|
+
locusInfo.emitScoped = sinon.stub();
|
|
1290
|
+
const sampleNewSelf = cloneDeep(self);
|
|
1291
|
+
sampleNewSelf.controls.interpretation.targetLanguage = 'cn'; // same with previous one
|
|
1292
|
+
|
|
1293
|
+
locusInfo.updateSelf(sampleNewSelf, []);
|
|
1294
|
+
|
|
1295
|
+
assert.neverCalledWith(
|
|
1296
|
+
locusInfo.emitScoped,
|
|
1297
|
+
{
|
|
1298
|
+
file: 'locus-info',
|
|
1299
|
+
function: 'updateSelf',
|
|
1300
|
+
},
|
|
1301
|
+
LOCUSINFO.EVENTS.SELF_MEETING_INTERPRETATION_CHANGED,
|
|
1302
|
+
{
|
|
1303
|
+
interpretation: sampleNewSelf.controls.interpretation,
|
|
1304
|
+
selfParticipantId: self.id,
|
|
1305
|
+
}
|
|
1306
|
+
);
|
|
1307
|
+
});
|
|
892
1308
|
});
|
|
893
1309
|
|
|
894
1310
|
describe('#updateMeetingInfo', () => {
|
|
@@ -967,19 +1383,36 @@ describe('plugin-meetings', () => {
|
|
|
967
1383
|
|
|
968
1384
|
if (expected) {
|
|
969
1385
|
assert.calledWith(...expectedArgs);
|
|
970
|
-
}
|
|
971
|
-
else {
|
|
1386
|
+
} else {
|
|
972
1387
|
assert.neverCalledWith(...expectedArgs);
|
|
973
1388
|
}
|
|
974
1389
|
locusInfo.emitScoped.resetHistory();
|
|
975
1390
|
};
|
|
976
1391
|
|
|
977
|
-
|
|
978
|
-
const
|
|
979
|
-
|
|
980
|
-
|
|
1392
|
+
const checkMeetingInfoUpdatedCalledForRoles = (expected) => {
|
|
1393
|
+
const expectedArgs = [
|
|
1394
|
+
locusInfo.emitScoped,
|
|
1395
|
+
{
|
|
1396
|
+
file: 'locus-info',
|
|
1397
|
+
function: 'updateMeetingInfo',
|
|
1398
|
+
},
|
|
1399
|
+
LOCUSINFO.EVENTS.MEETING_INFO_UPDATED,
|
|
1400
|
+
];
|
|
981
1401
|
|
|
982
|
-
|
|
1402
|
+
if (expected) {
|
|
1403
|
+
assert.calledWith(...expectedArgs);
|
|
1404
|
+
} else {
|
|
1405
|
+
assert.neverCalledWith(...expectedArgs);
|
|
1406
|
+
}
|
|
1407
|
+
locusInfo.emitScoped.resetHistory();
|
|
1408
|
+
};
|
|
1409
|
+
|
|
1410
|
+
it('emits MEETING_INFO_UPDATED if the info changes', () => {
|
|
1411
|
+
const initialInfo = cloneDeep(meetingInfo);
|
|
1412
|
+
|
|
1413
|
+
locusInfo.emitScoped = sinon.stub();
|
|
1414
|
+
|
|
1415
|
+
// set the info initially as locusInfo.info starts as undefined
|
|
983
1416
|
locusInfo.updateMeetingInfo(initialInfo, self);
|
|
984
1417
|
|
|
985
1418
|
// since it was initially undefined, this should trigger the event
|
|
@@ -999,6 +1432,16 @@ describe('plugin-meetings', () => {
|
|
|
999
1432
|
|
|
1000
1433
|
// since the info is the same it should not call trigger the event
|
|
1001
1434
|
checkMeetingInfoUpdatedCalled(false);
|
|
1435
|
+
|
|
1436
|
+
// update it with the same info, but roles changed
|
|
1437
|
+
const updateSelf = cloneDeep(self);
|
|
1438
|
+
updateSelf?.controls?.role?.roles.push({
|
|
1439
|
+
type: 'COHOST',
|
|
1440
|
+
hasRole: true,
|
|
1441
|
+
});
|
|
1442
|
+
locusInfo.updateMeetingInfo(newInfo, updateSelf);
|
|
1443
|
+
// since the info is the same but roles changed, it should call trigger the event
|
|
1444
|
+
checkMeetingInfoUpdatedCalledForRoles(true);
|
|
1002
1445
|
});
|
|
1003
1446
|
|
|
1004
1447
|
it('gets roles from self if available', () => {
|
|
@@ -1104,6 +1547,8 @@ describe('plugin-meetings', () => {
|
|
|
1104
1547
|
fakeLocus = {
|
|
1105
1548
|
meeting: true,
|
|
1106
1549
|
participants: true,
|
|
1550
|
+
url: 'newLocusUrl',
|
|
1551
|
+
syncUrl: 'newSyncUrl',
|
|
1107
1552
|
};
|
|
1108
1553
|
});
|
|
1109
1554
|
|
|
@@ -1148,6 +1593,55 @@ describe('plugin-meetings', () => {
|
|
|
1148
1593
|
assert.isFunction(locusParser.onDeltaAction);
|
|
1149
1594
|
});
|
|
1150
1595
|
|
|
1596
|
+
it('#updateLocusInfo ignores breakout LEFT message', () => {
|
|
1597
|
+
const newLocus = {
|
|
1598
|
+
self: {
|
|
1599
|
+
reason: 'MOVED',
|
|
1600
|
+
state: 'LEFT',
|
|
1601
|
+
},
|
|
1602
|
+
};
|
|
1603
|
+
|
|
1604
|
+
locusInfo.updateControls = sinon.stub();
|
|
1605
|
+
locusInfo.updateConversationUrl = sinon.stub();
|
|
1606
|
+
locusInfo.updateCreated = sinon.stub();
|
|
1607
|
+
locusInfo.updateFullState = sinon.stub();
|
|
1608
|
+
locusInfo.updateHostInfo = sinon.stub();
|
|
1609
|
+
locusInfo.updateMeetingInfo = sinon.stub();
|
|
1610
|
+
locusInfo.updateMediaShares = sinon.stub();
|
|
1611
|
+
locusInfo.updateParticipantsUrl = sinon.stub();
|
|
1612
|
+
locusInfo.updateReplace = sinon.stub();
|
|
1613
|
+
locusInfo.updateSelf = sinon.stub();
|
|
1614
|
+
locusInfo.updateLocusUrl = sinon.stub();
|
|
1615
|
+
locusInfo.updateAclUrl = sinon.stub();
|
|
1616
|
+
locusInfo.updateBasequence = sinon.stub();
|
|
1617
|
+
locusInfo.updateSequence = sinon.stub();
|
|
1618
|
+
locusInfo.updateMemberShip = sinon.stub();
|
|
1619
|
+
locusInfo.updateIdentifiers = sinon.stub();
|
|
1620
|
+
locusInfo.updateEmbeddedApps = sinon.stub();
|
|
1621
|
+
locusInfo.compareAndUpdate = sinon.stub();
|
|
1622
|
+
|
|
1623
|
+
locusInfo.updateLocusInfo(newLocus);
|
|
1624
|
+
|
|
1625
|
+
assert.notCalled(locusInfo.updateControls);
|
|
1626
|
+
assert.notCalled(locusInfo.updateConversationUrl);
|
|
1627
|
+
assert.notCalled(locusInfo.updateCreated);
|
|
1628
|
+
assert.notCalled(locusInfo.updateFullState);
|
|
1629
|
+
assert.notCalled(locusInfo.updateHostInfo);
|
|
1630
|
+
assert.notCalled(locusInfo.updateMeetingInfo);
|
|
1631
|
+
assert.notCalled(locusInfo.updateMediaShares);
|
|
1632
|
+
assert.notCalled(locusInfo.updateParticipantsUrl);
|
|
1633
|
+
assert.notCalled(locusInfo.updateReplace);
|
|
1634
|
+
assert.notCalled(locusInfo.updateSelf);
|
|
1635
|
+
assert.notCalled(locusInfo.updateLocusUrl);
|
|
1636
|
+
assert.notCalled(locusInfo.updateAclUrl);
|
|
1637
|
+
assert.notCalled(locusInfo.updateBasequence);
|
|
1638
|
+
assert.notCalled(locusInfo.updateSequence);
|
|
1639
|
+
assert.notCalled(locusInfo.updateMemberShip);
|
|
1640
|
+
assert.notCalled(locusInfo.updateIdentifiers);
|
|
1641
|
+
assert.notCalled(locusInfo.updateEmbeddedApps);
|
|
1642
|
+
assert.notCalled(locusInfo.compareAndUpdate);
|
|
1643
|
+
});
|
|
1644
|
+
|
|
1151
1645
|
it('onFullLocus() updates the working-copy of locus parser', () => {
|
|
1152
1646
|
const eventType = 'fakeEvent';
|
|
1153
1647
|
|
|
@@ -1156,12 +1650,39 @@ describe('plugin-meetings', () => {
|
|
|
1156
1650
|
sandbox.stub(locusInfo, 'updateParticipants');
|
|
1157
1651
|
sandbox.stub(locusInfo, 'isMeetingActive');
|
|
1158
1652
|
sandbox.stub(locusInfo, 'handleOneOnOneEvent');
|
|
1653
|
+
sandbox.stub(locusParser, 'isNewFullLocus').returns(true);
|
|
1159
1654
|
|
|
1160
1655
|
locusInfo.onFullLocus(fakeLocus, eventType);
|
|
1161
1656
|
|
|
1162
1657
|
assert.equal(fakeLocus, locusParser.workingCopy);
|
|
1163
1658
|
});
|
|
1164
1659
|
|
|
1660
|
+
it('onFullLocus() does not do anything if the incoming full locus DTO is old', () => {
|
|
1661
|
+
const eventType = 'fakeEvent';
|
|
1662
|
+
|
|
1663
|
+
locusParser.workingCopy = {};
|
|
1664
|
+
|
|
1665
|
+
const oldWorkingCopy = locusParser.workingCopy;
|
|
1666
|
+
|
|
1667
|
+
const spies = [
|
|
1668
|
+
sandbox.stub(locusInfo, 'updateParticipantDeltas'),
|
|
1669
|
+
sandbox.stub(locusInfo, 'updateLocusInfo'),
|
|
1670
|
+
sandbox.stub(locusInfo, 'updateParticipants'),
|
|
1671
|
+
sandbox.stub(locusInfo, 'isMeetingActive'),
|
|
1672
|
+
sandbox.stub(locusInfo, 'handleOneOnOneEvent'),
|
|
1673
|
+
];
|
|
1674
|
+
|
|
1675
|
+
sandbox.stub(locusParser, 'isNewFullLocus').returns(false);
|
|
1676
|
+
|
|
1677
|
+
locusInfo.onFullLocus(fakeLocus, eventType);
|
|
1678
|
+
|
|
1679
|
+
spies.forEach((spy) => {
|
|
1680
|
+
assert.notCalled(spy);
|
|
1681
|
+
});
|
|
1682
|
+
|
|
1683
|
+
assert.equal(oldWorkingCopy, locusParser.workingCopy);
|
|
1684
|
+
});
|
|
1685
|
+
|
|
1165
1686
|
it('onDeltaAction applies locus delta data to meeting', () => {
|
|
1166
1687
|
const action = 'fake action';
|
|
1167
1688
|
const parsedLoci = 'fake loci';
|
|
@@ -1188,33 +1709,82 @@ describe('plugin-meetings', () => {
|
|
|
1188
1709
|
assert.calledWith(meeting.locusInfo.onDeltaLocus, fakeLocus);
|
|
1189
1710
|
});
|
|
1190
1711
|
|
|
1191
|
-
it('applyLocusDeltaData gets
|
|
1712
|
+
it('applyLocusDeltaData gets delta locus on DESYNC action if we have a syncUrl', () => {
|
|
1192
1713
|
const {DESYNC} = LocusDeltaParser.loci;
|
|
1714
|
+
const fakeDeltaLocus = {id: 'fake delta locus'};
|
|
1193
1715
|
const meeting = {
|
|
1194
1716
|
meetingRequest: {
|
|
1195
|
-
|
|
1717
|
+
getLocusDTO: sandbox.stub().resolves({body: fakeDeltaLocus}),
|
|
1196
1718
|
},
|
|
1197
1719
|
locusInfo: {
|
|
1720
|
+
handleLocusDelta: sandbox.stub(),
|
|
1721
|
+
},
|
|
1722
|
+
locusUrl: 'oldLocusUrl',
|
|
1723
|
+
};
|
|
1724
|
+
|
|
1725
|
+
locusInfo.locusParser.workingCopy = {
|
|
1726
|
+
syncUrl: 'oldSyncUrl',
|
|
1727
|
+
};
|
|
1728
|
+
|
|
1729
|
+
// Since we have a promise inside a function we want to test that's not returned,
|
|
1730
|
+
// we will wait and stub it's last function to resolve this waiting promise.
|
|
1731
|
+
// Also ensures .handleLocusDelta() is called before .resume()
|
|
1732
|
+
return new Promise((resolve) => {
|
|
1733
|
+
locusInfo.locusParser.resume = sandbox.stub().callsFake(() => resolve());
|
|
1734
|
+
locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
|
|
1735
|
+
}).then(() => {
|
|
1736
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {url: 'oldSyncUrl'});
|
|
1737
|
+
|
|
1738
|
+
assert.calledOnceWithExactly(meeting.locusInfo.handleLocusDelta, fakeDeltaLocus, meeting);
|
|
1739
|
+
assert.calledOnce(locusInfo.locusParser.resume);
|
|
1740
|
+
});
|
|
1741
|
+
});
|
|
1742
|
+
|
|
1743
|
+
it('applyLocusDeltaData gets delta locus on DESYNC action if we have a syncUrl (empty response body)', () => {
|
|
1744
|
+
const {DESYNC} = LocusDeltaParser.loci;
|
|
1745
|
+
const meeting = {
|
|
1746
|
+
meetingRequest: {
|
|
1747
|
+
getLocusDTO: sandbox.stub().resolves({body: {}}),
|
|
1748
|
+
},
|
|
1749
|
+
locusInfo: {
|
|
1750
|
+
handleLocusDelta: sandbox.stub(),
|
|
1198
1751
|
onFullLocus: sandbox.stub(),
|
|
1199
1752
|
},
|
|
1753
|
+
locusUrl: 'oldLocusUrl',
|
|
1754
|
+
};
|
|
1755
|
+
|
|
1756
|
+
locusInfo.locusParser.workingCopy = {
|
|
1757
|
+
syncUrl: 'oldSyncUrl',
|
|
1200
1758
|
};
|
|
1201
1759
|
|
|
1202
|
-
|
|
1203
|
-
|
|
1760
|
+
// Since we have a promise inside a function we want to test that's not returned,
|
|
1761
|
+
// we will wait and stub it's last function to resolve this waiting promise.
|
|
1762
|
+
return new Promise((resolve) => {
|
|
1763
|
+
locusInfo.locusParser.resume = sandbox.stub().callsFake(() => resolve());
|
|
1764
|
+
locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
|
|
1765
|
+
}).then(() => {
|
|
1766
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {url: 'oldSyncUrl'});
|
|
1204
1767
|
|
|
1205
|
-
|
|
1768
|
+
assert.notCalled(meeting.locusInfo.handleLocusDelta);
|
|
1769
|
+
assert.notCalled(meeting.locusInfo.onFullLocus);
|
|
1770
|
+
assert.calledOnce(locusInfo.locusParser.resume);
|
|
1771
|
+
});
|
|
1206
1772
|
});
|
|
1207
1773
|
|
|
1208
|
-
it('
|
|
1774
|
+
it('applyLocusDeltaData gets full locus on DESYNC action if we do not have a syncUrl', () => {
|
|
1209
1775
|
const {DESYNC} = LocusDeltaParser.loci;
|
|
1776
|
+
const fakeFullLocusDto = {id: 'fake full locus dto'};
|
|
1210
1777
|
const meeting = {
|
|
1211
1778
|
meetingRequest: {
|
|
1212
|
-
|
|
1779
|
+
getLocusDTO: sandbox.stub().resolves({body: fakeFullLocusDto}),
|
|
1780
|
+
},
|
|
1781
|
+
locusInfo: {
|
|
1782
|
+
onFullLocus: sandbox.stub(),
|
|
1213
1783
|
},
|
|
1214
|
-
|
|
1784
|
+
locusUrl: 'oldLocusUrl',
|
|
1215
1785
|
};
|
|
1216
1786
|
|
|
1217
|
-
locusInfo.
|
|
1787
|
+
locusInfo.locusParser.workingCopy = {}; // no syncUrl
|
|
1218
1788
|
|
|
1219
1789
|
// Since we have a promise inside a function we want to test that's not returned,
|
|
1220
1790
|
// we will wait and stub it's last function to resolve this waiting promise.
|
|
@@ -1223,10 +1793,201 @@ describe('plugin-meetings', () => {
|
|
|
1223
1793
|
locusInfo.locusParser.resume = sandbox.stub().callsFake(() => resolve());
|
|
1224
1794
|
locusInfo.applyLocusDeltaData(DESYNC, fakeLocus, meeting);
|
|
1225
1795
|
}).then(() => {
|
|
1226
|
-
assert.
|
|
1796
|
+
assert.calledOnceWithExactly(meeting.meetingRequest.getLocusDTO, {url: 'oldLocusUrl'});
|
|
1797
|
+
|
|
1798
|
+
assert.calledOnceWithExactly(meeting.locusInfo.onFullLocus, fakeFullLocusDto);
|
|
1227
1799
|
assert.calledOnce(locusInfo.locusParser.resume);
|
|
1228
1800
|
});
|
|
1229
1801
|
});
|
|
1802
|
+
|
|
1803
|
+
it('onDeltaLocus handle delta data', () => {
|
|
1804
|
+
fakeLocus.participants = {};
|
|
1805
|
+
const fakeBreakout = {
|
|
1806
|
+
sessionId: 'sessionId',
|
|
1807
|
+
groupId: 'groupId',
|
|
1808
|
+
};
|
|
1809
|
+
|
|
1810
|
+
fakeLocus.controls = {
|
|
1811
|
+
breakout: fakeBreakout,
|
|
1812
|
+
};
|
|
1813
|
+
locusInfo.controls = {
|
|
1814
|
+
breakout: {
|
|
1815
|
+
sessionId: 'sessionId',
|
|
1816
|
+
groupId: 'groupId',
|
|
1817
|
+
},
|
|
1818
|
+
};
|
|
1819
|
+
locusInfo.updateParticipants = sinon.stub();
|
|
1820
|
+
locusInfo.onDeltaLocus(fakeLocus);
|
|
1821
|
+
assert.calledWith(locusInfo.updateParticipants, {}, false);
|
|
1822
|
+
|
|
1823
|
+
fakeLocus.controls.breakout.sessionId = 'sessionId2';
|
|
1824
|
+
locusInfo.onDeltaLocus(fakeLocus);
|
|
1825
|
+
assert.calledWith(locusInfo.updateParticipants, {}, true);
|
|
1826
|
+
});
|
|
1827
|
+
});
|
|
1828
|
+
|
|
1829
|
+
describe('#updateLocusCache', () => {
|
|
1830
|
+
it('cache it if income locus is main session locus', () => {
|
|
1831
|
+
const locus = {url: 'url'};
|
|
1832
|
+
locusInfo.mainSessionLocusCache = null;
|
|
1833
|
+
locusInfo.updateLocusCache(locus);
|
|
1834
|
+
|
|
1835
|
+
assert.deepEqual(locusInfo.mainSessionLocusCache, locus);
|
|
1836
|
+
});
|
|
1837
|
+
|
|
1838
|
+
it('not cache it if income locus is breakout session locus', () => {
|
|
1839
|
+
const locus = {url: 'url', controls: {breakout: {sessionType: 'BREAKOUT'}}};
|
|
1840
|
+
locusInfo.mainSessionLocusCache = null;
|
|
1841
|
+
locusInfo.updateLocusCache(locus);
|
|
1842
|
+
|
|
1843
|
+
assert.isNull(locusInfo.mainSessionLocusCache);
|
|
1844
|
+
});
|
|
1845
|
+
});
|
|
1846
|
+
|
|
1847
|
+
describe('#getTheLocusToUpdate', () => {
|
|
1848
|
+
it('return the cache locus if return to main session', () => {
|
|
1849
|
+
locusInfo.mainSessionLocusCache = {url: 'url'};
|
|
1850
|
+
locusInfo.controls = {
|
|
1851
|
+
breakout: {
|
|
1852
|
+
sessionType: 'BREAKOUT',
|
|
1853
|
+
},
|
|
1854
|
+
};
|
|
1855
|
+
const newLocus = {
|
|
1856
|
+
controls: {
|
|
1857
|
+
breakout: {
|
|
1858
|
+
sessionType: 'MAIN',
|
|
1859
|
+
},
|
|
1860
|
+
},
|
|
1861
|
+
};
|
|
1862
|
+
|
|
1863
|
+
assert.deepEqual(locusInfo.getTheLocusToUpdate(newLocus), {url: 'url'});
|
|
1864
|
+
});
|
|
1865
|
+
|
|
1866
|
+
it('return the new locus if return to main session but no cache', () => {
|
|
1867
|
+
locusInfo.mainSessionLocusCache = null;
|
|
1868
|
+
locusInfo.controls = {
|
|
1869
|
+
breakout: {
|
|
1870
|
+
sessionType: 'BREAKOUT',
|
|
1871
|
+
},
|
|
1872
|
+
};
|
|
1873
|
+
const newLocus = {
|
|
1874
|
+
controls: {
|
|
1875
|
+
breakout: {
|
|
1876
|
+
sessionType: 'MAIN',
|
|
1877
|
+
},
|
|
1878
|
+
},
|
|
1879
|
+
};
|
|
1880
|
+
|
|
1881
|
+
assert.deepEqual(locusInfo.getTheLocusToUpdate(newLocus), newLocus);
|
|
1882
|
+
});
|
|
1883
|
+
|
|
1884
|
+
it('return the new locus if not return to main session', () => {
|
|
1885
|
+
locusInfo.mainSessionLocusCache = {url: 'url'};
|
|
1886
|
+
locusInfo.controls = {
|
|
1887
|
+
breakout: {
|
|
1888
|
+
sessionType: 'MAIN',
|
|
1889
|
+
},
|
|
1890
|
+
};
|
|
1891
|
+
const newLocus = {
|
|
1892
|
+
controls: {
|
|
1893
|
+
breakout: {
|
|
1894
|
+
sessionType: 'BREAKOUT',
|
|
1895
|
+
},
|
|
1896
|
+
},
|
|
1897
|
+
};
|
|
1898
|
+
|
|
1899
|
+
assert.deepEqual(locusInfo.getTheLocusToUpdate(newLocus), newLocus);
|
|
1900
|
+
});
|
|
1901
|
+
});
|
|
1902
|
+
|
|
1903
|
+
describe('#mergeParticipants', () => {
|
|
1904
|
+
let participants;
|
|
1905
|
+
let sourceParticipants;
|
|
1906
|
+
beforeEach(() => {
|
|
1907
|
+
participants = [{id: '111', status: 'JOINED'}, {id: '222'}];
|
|
1908
|
+
sourceParticipants = [{id: '111', status: 'LEFT'}, {id: '333'}];
|
|
1909
|
+
});
|
|
1910
|
+
|
|
1911
|
+
it('merge the participants, replace it by id if exist in old array', () => {
|
|
1912
|
+
const result = locusInfo.mergeParticipants(participants, sourceParticipants);
|
|
1913
|
+
assert.deepEqual(result, [{id: '111', status: 'LEFT'}, {id: '222'}, {id: '333'}]);
|
|
1914
|
+
});
|
|
1915
|
+
|
|
1916
|
+
it('return new participants if previous participants is empty', () => {
|
|
1917
|
+
const result = locusInfo.mergeParticipants([], sourceParticipants);
|
|
1918
|
+
assert.deepEqual(result, sourceParticipants);
|
|
1919
|
+
});
|
|
1920
|
+
|
|
1921
|
+
it('return new participants if previous participants is null/undefined', () => {
|
|
1922
|
+
let result = locusInfo.mergeParticipants(null, sourceParticipants);
|
|
1923
|
+
assert.deepEqual(result, sourceParticipants);
|
|
1924
|
+
|
|
1925
|
+
result = locusInfo.mergeParticipants(undefined, sourceParticipants);
|
|
1926
|
+
assert.deepEqual(result, sourceParticipants);
|
|
1927
|
+
});
|
|
1928
|
+
|
|
1929
|
+
it('return previous participants if new participants is empty', () => {
|
|
1930
|
+
const result = locusInfo.mergeParticipants(participants, []);
|
|
1931
|
+
assert.deepEqual(result, participants);
|
|
1932
|
+
});
|
|
1933
|
+
|
|
1934
|
+
it('return previous participants if new participants is null/undefined', () => {
|
|
1935
|
+
let result = locusInfo.mergeParticipants(participants, null);
|
|
1936
|
+
assert.deepEqual(result, participants);
|
|
1937
|
+
|
|
1938
|
+
result = locusInfo.mergeParticipants(participants, undefined);
|
|
1939
|
+
assert.deepEqual(result, participants);
|
|
1940
|
+
});
|
|
1941
|
+
});
|
|
1942
|
+
|
|
1943
|
+
describe('#updateMainSessionLocusCache', () => {
|
|
1944
|
+
let cachedLocus;
|
|
1945
|
+
let newLocus;
|
|
1946
|
+
beforeEach(() => {
|
|
1947
|
+
cachedLocus = {
|
|
1948
|
+
controls: {},
|
|
1949
|
+
participants: [],
|
|
1950
|
+
info: {webExMeetingId: 'testId1', topic: 'test'},
|
|
1951
|
+
};
|
|
1952
|
+
newLocus = {
|
|
1953
|
+
self: {},
|
|
1954
|
+
participants: [{id: '111'}],
|
|
1955
|
+
info: {testId: 'testId2', webExMeetingName: 'hello'},
|
|
1956
|
+
};
|
|
1957
|
+
});
|
|
1958
|
+
it('shallow merge new locus into cache', () => {
|
|
1959
|
+
locusInfo.mainSessionLocusCache = cachedLocus;
|
|
1960
|
+
locusInfo.updateMainSessionLocusCache(newLocus);
|
|
1961
|
+
|
|
1962
|
+
assert.deepEqual(locusInfo.mainSessionLocusCache, {
|
|
1963
|
+
controls: {},
|
|
1964
|
+
participants: [{id: '111'}],
|
|
1965
|
+
info: {testId: 'testId2', webExMeetingName: 'hello'},
|
|
1966
|
+
self: {},
|
|
1967
|
+
});
|
|
1968
|
+
});
|
|
1969
|
+
|
|
1970
|
+
it('cache new locus if no cache before', () => {
|
|
1971
|
+
locusInfo.mainSessionLocusCache = null;
|
|
1972
|
+
locusInfo.updateMainSessionLocusCache(newLocus);
|
|
1973
|
+
|
|
1974
|
+
assert.deepEqual(locusInfo.mainSessionLocusCache, newLocus);
|
|
1975
|
+
});
|
|
1976
|
+
|
|
1977
|
+
it('do nothing if new locus is null', () => {
|
|
1978
|
+
locusInfo.mainSessionLocusCache = cachedLocus;
|
|
1979
|
+
locusInfo.updateMainSessionLocusCache(null);
|
|
1980
|
+
|
|
1981
|
+
assert.deepEqual(locusInfo.mainSessionLocusCache, cachedLocus);
|
|
1982
|
+
});
|
|
1983
|
+
});
|
|
1984
|
+
|
|
1985
|
+
describe('#clearMainSessionLocusCache', () => {
|
|
1986
|
+
it('clear main session locus cache', () => {
|
|
1987
|
+
locusInfo.mainSessionLocusCache = {controls: {}};
|
|
1988
|
+
locusInfo.clearMainSessionLocusCache();
|
|
1989
|
+
assert.isNull(locusInfo.mainSessionLocusCache);
|
|
1990
|
+
});
|
|
1230
1991
|
});
|
|
1231
1992
|
|
|
1232
1993
|
describe('#handleOneonOneEvent', () => {
|
|
@@ -1269,5 +2030,402 @@ describe('plugin-meetings', () => {
|
|
|
1269
2030
|
);
|
|
1270
2031
|
});
|
|
1271
2032
|
});
|
|
2033
|
+
|
|
2034
|
+
describe('#isMeetingActive', () => {
|
|
2035
|
+
it('sends client event correctly for state = inactive', () => {
|
|
2036
|
+
locusInfo.parsedLocus = {
|
|
2037
|
+
fullState: {
|
|
2038
|
+
type: _CALL_,
|
|
2039
|
+
},
|
|
2040
|
+
};
|
|
2041
|
+
|
|
2042
|
+
locusInfo.fullState = {
|
|
2043
|
+
state: LOCUS.STATE.INACTIVE,
|
|
2044
|
+
};
|
|
2045
|
+
|
|
2046
|
+
locusInfo.isMeetingActive();
|
|
2047
|
+
|
|
2048
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
2049
|
+
name: 'client.call.remote-ended',
|
|
2050
|
+
options: {
|
|
2051
|
+
meetingId: locusInfo.meetingId,
|
|
2052
|
+
},
|
|
2053
|
+
});
|
|
2054
|
+
});
|
|
2055
|
+
|
|
2056
|
+
it('sends client event correctly for state = PARTNER_LEFT', () => {
|
|
2057
|
+
locusInfo.getLocusPartner = sinon.stub().returns({state: MEETING_STATE.STATES.LEFT});
|
|
2058
|
+
locusInfo.parsedLocus = {
|
|
2059
|
+
fullState: {
|
|
2060
|
+
type: _CALL_,
|
|
2061
|
+
},
|
|
2062
|
+
self: {
|
|
2063
|
+
state: MEETING_STATE.STATES.DECLINED,
|
|
2064
|
+
},
|
|
2065
|
+
};
|
|
2066
|
+
locusInfo.isMeetingActive();
|
|
2067
|
+
|
|
2068
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
2069
|
+
name: 'client.call.remote-ended',
|
|
2070
|
+
options: {
|
|
2071
|
+
meetingId: locusInfo.meetingId,
|
|
2072
|
+
},
|
|
2073
|
+
});
|
|
2074
|
+
});
|
|
2075
|
+
|
|
2076
|
+
it('sends client event correctly for state = SELF_LEFT', () => {
|
|
2077
|
+
locusInfo.getLocusPartner = sinon.stub().returns({state: MEETING_STATE.STATES.LEFT});
|
|
2078
|
+
locusInfo.parsedLocus = {
|
|
2079
|
+
fullState: {
|
|
2080
|
+
type: _CALL_,
|
|
2081
|
+
},
|
|
2082
|
+
self: {
|
|
2083
|
+
state: MEETING_STATE.STATES.LEFT,
|
|
2084
|
+
},
|
|
2085
|
+
};
|
|
2086
|
+
|
|
2087
|
+
locusInfo.isMeetingActive();
|
|
2088
|
+
|
|
2089
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
2090
|
+
name: 'client.call.remote-ended',
|
|
2091
|
+
options: {
|
|
2092
|
+
meetingId: locusInfo.meetingId,
|
|
2093
|
+
},
|
|
2094
|
+
});
|
|
2095
|
+
});
|
|
2096
|
+
|
|
2097
|
+
it('sends client event correctly for state = MEETING_INACTIVE_TERMINATING', () => {
|
|
2098
|
+
locusInfo.getLocusPartner = sinon.stub().returns({state: MEETING_STATE.STATES.LEFT});
|
|
2099
|
+
locusInfo.parsedLocus = {
|
|
2100
|
+
fullState: {
|
|
2101
|
+
type: _MEETING_,
|
|
2102
|
+
},
|
|
2103
|
+
};
|
|
2104
|
+
|
|
2105
|
+
locusInfo.fullState = {
|
|
2106
|
+
state: LOCUS.STATE.INACTIVE,
|
|
2107
|
+
};
|
|
2108
|
+
|
|
2109
|
+
locusInfo.isMeetingActive();
|
|
2110
|
+
|
|
2111
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
2112
|
+
name: 'client.call.remote-ended',
|
|
2113
|
+
options: {
|
|
2114
|
+
meetingId: locusInfo.meetingId,
|
|
2115
|
+
},
|
|
2116
|
+
});
|
|
2117
|
+
});
|
|
2118
|
+
|
|
2119
|
+
it('sends client event correctly for state = FULLSTATE_REMOVED', () => {
|
|
2120
|
+
locusInfo.getLocusPartner = sinon.stub().returns({state: MEETING_STATE.STATES.LEFT});
|
|
2121
|
+
locusInfo.parsedLocus = {
|
|
2122
|
+
fullState: {
|
|
2123
|
+
type: _MEETING_,
|
|
2124
|
+
},
|
|
2125
|
+
};
|
|
2126
|
+
|
|
2127
|
+
locusInfo.fullState = {
|
|
2128
|
+
removed: true,
|
|
2129
|
+
};
|
|
2130
|
+
|
|
2131
|
+
locusInfo.isMeetingActive();
|
|
2132
|
+
|
|
2133
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
2134
|
+
name: 'client.call.remote-ended',
|
|
2135
|
+
options: {
|
|
2136
|
+
meetingId: locusInfo.meetingId,
|
|
2137
|
+
},
|
|
2138
|
+
});
|
|
2139
|
+
});
|
|
2140
|
+
});
|
|
2141
|
+
|
|
2142
|
+
// semi-integration tests that use real LocusInfo with real Parser
|
|
2143
|
+
// and test various scenarios related to handling out-of-order Locus delta events
|
|
2144
|
+
describe('handling of out-of-order Locus delta events', () => {
|
|
2145
|
+
let clock;
|
|
2146
|
+
|
|
2147
|
+
const generateDeltaEvent = (base, sequence) => {
|
|
2148
|
+
return {
|
|
2149
|
+
baseSequence: {
|
|
2150
|
+
rangeStart: 0,
|
|
2151
|
+
rangeEnd: 0,
|
|
2152
|
+
entries: [base],
|
|
2153
|
+
},
|
|
2154
|
+
sequence: {
|
|
2155
|
+
rangeStart: 0,
|
|
2156
|
+
rangeEnd: 0,
|
|
2157
|
+
entries: [sequence],
|
|
2158
|
+
},
|
|
2159
|
+
syncUrl: `fake sync url for sequence ${sequence}`,
|
|
2160
|
+
self: {
|
|
2161
|
+
person: {
|
|
2162
|
+
id: 'test person id',
|
|
2163
|
+
},
|
|
2164
|
+
},
|
|
2165
|
+
};
|
|
2166
|
+
};
|
|
2167
|
+
|
|
2168
|
+
// a list of example delta events, sorted by time and each event is based on the previous one
|
|
2169
|
+
const deltaEvents = [
|
|
2170
|
+
generateDeltaEvent(10, 20), // 0
|
|
2171
|
+
generateDeltaEvent(20, 30), // 1
|
|
2172
|
+
generateDeltaEvent(30, 40), // 2
|
|
2173
|
+
generateDeltaEvent(40, 50), // 3
|
|
2174
|
+
generateDeltaEvent(50, 60), // 4
|
|
2175
|
+
generateDeltaEvent(60, 70), // 5
|
|
2176
|
+
generateDeltaEvent(70, 80), // 6
|
|
2177
|
+
generateDeltaEvent(80, 90), // 7
|
|
2178
|
+
generateDeltaEvent(90, 100), // 8
|
|
2179
|
+
];
|
|
2180
|
+
|
|
2181
|
+
let updateLocusInfoStub; // we use this stub to verify that an event has been fully processed
|
|
2182
|
+
let syncRequestStub;
|
|
2183
|
+
|
|
2184
|
+
beforeEach(() => {
|
|
2185
|
+
clock = sinon.useFakeTimers();
|
|
2186
|
+
|
|
2187
|
+
sinon.stub(locusInfo, 'updateParticipantDeltas');
|
|
2188
|
+
sinon.stub(locusInfo, 'updateParticipants');
|
|
2189
|
+
sinon.stub(locusInfo, 'isMeetingActive'),
|
|
2190
|
+
sinon.stub(locusInfo, 'handleOneOnOneEvent'),
|
|
2191
|
+
(updateLocusInfoStub = sinon.stub(locusInfo, 'updateLocusInfo'));
|
|
2192
|
+
syncRequestStub = sinon.stub().resolves({body: {}});
|
|
2193
|
+
|
|
2194
|
+
mockMeeting.locusInfo = locusInfo;
|
|
2195
|
+
mockMeeting.locusUrl = 'fake locus url';
|
|
2196
|
+
mockMeeting.meetingRequest = {
|
|
2197
|
+
getLocusDTO: syncRequestStub,
|
|
2198
|
+
};
|
|
2199
|
+
|
|
2200
|
+
locusInfo.onFullLocus({
|
|
2201
|
+
sequence: {
|
|
2202
|
+
rangeStart: 0,
|
|
2203
|
+
rangeEnd: 0,
|
|
2204
|
+
entries: [10],
|
|
2205
|
+
},
|
|
2206
|
+
self: {
|
|
2207
|
+
person: {
|
|
2208
|
+
id: 'test person id',
|
|
2209
|
+
},
|
|
2210
|
+
},
|
|
2211
|
+
});
|
|
2212
|
+
|
|
2213
|
+
updateLocusInfoStub.resetHistory();
|
|
2214
|
+
});
|
|
2215
|
+
|
|
2216
|
+
afterEach(() => {
|
|
2217
|
+
clock.restore();
|
|
2218
|
+
});
|
|
2219
|
+
|
|
2220
|
+
it('queues out-of-order deltas until it receives a correct delta', () => {
|
|
2221
|
+
// send some out-of-order deltas
|
|
2222
|
+
locusInfo.handleLocusDelta(deltaEvents[1], mockMeeting);
|
|
2223
|
+
locusInfo.handleLocusDelta(deltaEvents[4], mockMeeting);
|
|
2224
|
+
|
|
2225
|
+
// they should be queued and not processed
|
|
2226
|
+
assert.notCalled(updateLocusInfoStub);
|
|
2227
|
+
|
|
2228
|
+
// now one of the missing ones, but not the one SDK is really waiting for
|
|
2229
|
+
locusInfo.handleLocusDelta(deltaEvents[2], mockMeeting);
|
|
2230
|
+
|
|
2231
|
+
// still nothing should be processed
|
|
2232
|
+
assert.notCalled(updateLocusInfoStub);
|
|
2233
|
+
|
|
2234
|
+
// now send the one SDK is waiting for
|
|
2235
|
+
locusInfo.handleLocusDelta(deltaEvents[0], mockMeeting);
|
|
2236
|
+
|
|
2237
|
+
// so deltaEvents with indexes 1,2,3 can be processed, but 5 still not, because 4 is missing
|
|
2238
|
+
assert.callCount(updateLocusInfoStub, 3);
|
|
2239
|
+
assert.calledWith(updateLocusInfoStub.getCall(0), deltaEvents[0]);
|
|
2240
|
+
assert.calledWith(updateLocusInfoStub.getCall(1), deltaEvents[1]);
|
|
2241
|
+
assert.calledWith(updateLocusInfoStub.getCall(2), deltaEvents[2]);
|
|
2242
|
+
|
|
2243
|
+
updateLocusInfoStub.resetHistory();
|
|
2244
|
+
|
|
2245
|
+
// now send deltaEvents[4]
|
|
2246
|
+
locusInfo.handleLocusDelta(deltaEvents[3], mockMeeting);
|
|
2247
|
+
|
|
2248
|
+
// and verify deltaEvents[4] and deltaEvents[5] have been processed
|
|
2249
|
+
assert.callCount(updateLocusInfoStub, 2);
|
|
2250
|
+
assert.calledWith(updateLocusInfoStub.getCall(0), deltaEvents[3]);
|
|
2251
|
+
assert.calledWith(updateLocusInfoStub.getCall(1), deltaEvents[4]);
|
|
2252
|
+
});
|
|
2253
|
+
|
|
2254
|
+
it('handles out-of-order deltas correctly even if all arrive in reverse order', () => {
|
|
2255
|
+
// send a bunch deltas in reverse order
|
|
2256
|
+
for (let i = 4; i >= 0; i--) {
|
|
2257
|
+
locusInfo.handleLocusDelta(deltaEvents[i], mockMeeting);
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2260
|
+
// they should be queued and then processed in correct order
|
|
2261
|
+
assert.callCount(updateLocusInfoStub, 5);
|
|
2262
|
+
assert.calledWith(updateLocusInfoStub.getCall(0), deltaEvents[0]);
|
|
2263
|
+
assert.calledWith(updateLocusInfoStub.getCall(1), deltaEvents[1]);
|
|
2264
|
+
assert.calledWith(updateLocusInfoStub.getCall(2), deltaEvents[2]);
|
|
2265
|
+
assert.calledWith(updateLocusInfoStub.getCall(3), deltaEvents[3]);
|
|
2266
|
+
assert.calledWith(updateLocusInfoStub.getCall(4), deltaEvents[4]);
|
|
2267
|
+
});
|
|
2268
|
+
|
|
2269
|
+
it('sends a sync request using syncUrl if it receives at least 1 delta event and processes later deltas after sync correctly', async () => {
|
|
2270
|
+
// the test first sends an initial "good" delta
|
|
2271
|
+
const initialDeltaIdx = 0;
|
|
2272
|
+
const initialDelta = deltaEvents[initialDeltaIdx];
|
|
2273
|
+
|
|
2274
|
+
// then it sends a bunch of out-of-order deltas (at least 6 to trigger a sync), last one being lastOooDelta
|
|
2275
|
+
const firstOooDeltaIdx = 2;
|
|
2276
|
+
const lastOooDeltaIdx = 7;
|
|
2277
|
+
const lastOooDelta = deltaEvents[lastOooDeltaIdx];
|
|
2278
|
+
|
|
2279
|
+
// and finally, after the sync it sends another "good" delta
|
|
2280
|
+
const goodDeltaAfterSync = deltaEvents[8];
|
|
2281
|
+
|
|
2282
|
+
const deltaLocusFromSyncResponse = {
|
|
2283
|
+
baseSequence: {
|
|
2284
|
+
rangeStart: 0,
|
|
2285
|
+
rangeEnd: 0,
|
|
2286
|
+
entries: [initialDelta.sequence.entries[0]],
|
|
2287
|
+
},
|
|
2288
|
+
sequence: {
|
|
2289
|
+
rangeStart: 0,
|
|
2290
|
+
rangeEnd: 0,
|
|
2291
|
+
entries: [lastOooDelta.sequence.entries[0]],
|
|
2292
|
+
},
|
|
2293
|
+
syncUrl: `fake sync url for sequence ${lastOooDelta.sequence.entries[0]}`,
|
|
2294
|
+
self: {
|
|
2295
|
+
person: {
|
|
2296
|
+
id: 'test person id',
|
|
2297
|
+
},
|
|
2298
|
+
},
|
|
2299
|
+
};
|
|
2300
|
+
|
|
2301
|
+
syncRequestStub.resolves({
|
|
2302
|
+
body: deltaLocusFromSyncResponse,
|
|
2303
|
+
});
|
|
2304
|
+
|
|
2305
|
+
// send one correct delta so that SDK has the syncUrl
|
|
2306
|
+
locusInfo.handleLocusDelta(initialDelta, mockMeeting);
|
|
2307
|
+
|
|
2308
|
+
updateLocusInfoStub.resetHistory();
|
|
2309
|
+
|
|
2310
|
+
// send 6 out-of-order deltas to trigger a sync (we're skipping deltaEvents[1])
|
|
2311
|
+
for (let i = firstOooDeltaIdx; i <= lastOooDeltaIdx; i++) {
|
|
2312
|
+
locusInfo.handleLocusDelta(deltaEvents[i], mockMeeting);
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
await testUtils.flushPromises();
|
|
2316
|
+
|
|
2317
|
+
// check that sync was done using the correct syncUrl
|
|
2318
|
+
assert.calledOnceWithExactly(syncRequestStub, {url: initialDelta.syncUrl});
|
|
2319
|
+
assert.calledOnceWithExactly(updateLocusInfoStub, deltaLocusFromSyncResponse);
|
|
2320
|
+
|
|
2321
|
+
updateLocusInfoStub.resetHistory();
|
|
2322
|
+
|
|
2323
|
+
// now send another delta - a good one, it should be processed as normal
|
|
2324
|
+
locusInfo.handleLocusDelta(goodDeltaAfterSync, mockMeeting);
|
|
2325
|
+
|
|
2326
|
+
assert.calledOnceWithExactly(updateLocusInfoStub, goodDeltaAfterSync);
|
|
2327
|
+
});
|
|
2328
|
+
|
|
2329
|
+
it('does a sync if blocked on out-of-order deltas for too long', async () => {
|
|
2330
|
+
// stub random so that the timer fires after 12500 ms
|
|
2331
|
+
sinon.stub(Math, 'random').returns(0.5);
|
|
2332
|
+
|
|
2333
|
+
const oooDelta = deltaEvents[3];
|
|
2334
|
+
|
|
2335
|
+
// setup the stubs so that the sync request receives a full DTO with the sequence equal to the out-of-order delta we simulate
|
|
2336
|
+
const fullLocus = {
|
|
2337
|
+
sequence: oooDelta.sequence,
|
|
2338
|
+
};
|
|
2339
|
+
syncRequestStub.resolves({
|
|
2340
|
+
body: fullLocus,
|
|
2341
|
+
});
|
|
2342
|
+
|
|
2343
|
+
// send an out-of-order delta
|
|
2344
|
+
locusInfo.handleLocusDelta(oooDelta, mockMeeting);
|
|
2345
|
+
|
|
2346
|
+
await clock.tickAsync(12499);
|
|
2347
|
+
await testUtils.flushPromises();
|
|
2348
|
+
assert.notCalled(syncRequestStub);
|
|
2349
|
+
assert.notCalled(updateLocusInfoStub);
|
|
2350
|
+
|
|
2351
|
+
await clock.tickAsync(1);
|
|
2352
|
+
await testUtils.flushPromises();
|
|
2353
|
+
|
|
2354
|
+
assert.calledOnceWithExactly(syncRequestStub, {url: mockMeeting.locusUrl});
|
|
2355
|
+
assert.calledOnceWithExactly(updateLocusInfoStub, fullLocus);
|
|
2356
|
+
});
|
|
2357
|
+
|
|
2358
|
+
it('does a sync if out-of-order deltas queue becomes too big', async () => {
|
|
2359
|
+
// setup the stubs so that the sync request receives a full DTO with the sequence equal to the out-of-order delta we simulate
|
|
2360
|
+
const fullLocus = {
|
|
2361
|
+
sequence: deltaEvents[6].sequence,
|
|
2362
|
+
};
|
|
2363
|
+
syncRequestStub.resolves({
|
|
2364
|
+
body: fullLocus,
|
|
2365
|
+
});
|
|
2366
|
+
|
|
2367
|
+
// send 5 deltas, starting from deltaEvents[1] so that SDK is blocked waiting for deltaEvents[0]
|
|
2368
|
+
for (let i = 0; i < 5; i++) {
|
|
2369
|
+
locusInfo.handleLocusDelta(deltaEvents[i + 1], mockMeeting);
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
// nothing should happen, SDK should still be waiting for deltaEvents[0]
|
|
2373
|
+
assert.notCalled(syncRequestStub);
|
|
2374
|
+
assert.notCalled(updateLocusInfoStub);
|
|
2375
|
+
|
|
2376
|
+
// now send one more out-of-order delta to trigger a sync request
|
|
2377
|
+
locusInfo.handleLocusDelta(deltaEvents[6], mockMeeting);
|
|
2378
|
+
|
|
2379
|
+
await testUtils.flushPromises();
|
|
2380
|
+
|
|
2381
|
+
// check sync was done
|
|
2382
|
+
assert.calledOnceWithExactly(syncRequestStub, {url: mockMeeting.locusUrl});
|
|
2383
|
+
assert.calledOnceWithExactly(updateLocusInfoStub, fullLocus);
|
|
2384
|
+
});
|
|
2385
|
+
|
|
2386
|
+
it('processes delta events that are not included in sync response', async () => {
|
|
2387
|
+
// this test sends a bunch of out-of-order deltas, this triggers a sync
|
|
2388
|
+
// but the full locus response doesn't include the last 2 deltas received, so
|
|
2389
|
+
// we check that these 2 deltas are also processed after sync response
|
|
2390
|
+
const fullLocusFromSyncResponse = {
|
|
2391
|
+
baseSequence: {
|
|
2392
|
+
rangeStart: 0,
|
|
2393
|
+
rangeEnd: 0,
|
|
2394
|
+
entries: [deltaEvents[0].sequence.entries[0]],
|
|
2395
|
+
},
|
|
2396
|
+
sequence: {
|
|
2397
|
+
rangeStart: 0,
|
|
2398
|
+
rangeEnd: 0,
|
|
2399
|
+
entries: [deltaEvents[5].sequence.entries[0]],
|
|
2400
|
+
},
|
|
2401
|
+
syncUrl: `fake sync url for sequence ${deltaEvents[5].sequence.entries[0]}`,
|
|
2402
|
+
self: {
|
|
2403
|
+
person: {
|
|
2404
|
+
id: 'test person id',
|
|
2405
|
+
},
|
|
2406
|
+
},
|
|
2407
|
+
};
|
|
2408
|
+
|
|
2409
|
+
syncRequestStub.resolves({
|
|
2410
|
+
body: fullLocusFromSyncResponse,
|
|
2411
|
+
});
|
|
2412
|
+
|
|
2413
|
+
// send at least 6 out-of-order deltas to trigger a sync (we're skipping deltaEvents[0])
|
|
2414
|
+
for (let i = 1; i <= 7; i++) {
|
|
2415
|
+
locusInfo.handleLocusDelta(deltaEvents[i], mockMeeting);
|
|
2416
|
+
}
|
|
2417
|
+
|
|
2418
|
+
await testUtils.flushPromises();
|
|
2419
|
+
|
|
2420
|
+
// check that sync was done
|
|
2421
|
+
assert.calledOnceWithExactly(syncRequestStub, {url: mockMeeting.locusUrl});
|
|
2422
|
+
|
|
2423
|
+
// and that remaining deltas from the queue that were not included in full Locus were also processed
|
|
2424
|
+
assert.callCount(updateLocusInfoStub, 3);
|
|
2425
|
+
assert.calledWith(updateLocusInfoStub.getCall(0), fullLocusFromSyncResponse);
|
|
2426
|
+
assert.calledWith(updateLocusInfoStub.getCall(1), deltaEvents[6]);
|
|
2427
|
+
assert.calledWith(updateLocusInfoStub.getCall(2), deltaEvents[7]);
|
|
2428
|
+
});
|
|
2429
|
+
});
|
|
1272
2430
|
});
|
|
1273
2431
|
});
|