@webex/plugin-meetings 3.0.0-beta.39 → 3.0.0-beta.391
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 +58 -8
- 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 +94 -15
- package/dist/breakouts/breakout.js.map +1 -1
- package/dist/breakouts/events.js +45 -0
- package/dist/breakouts/events.js.map +1 -0
- package/dist/breakouts/index.js +671 -81
- package/dist/breakouts/index.js.map +1 -1
- package/dist/breakouts/utils.js +45 -1
- package/dist/breakouts/utils.js.map +1 -1
- package/dist/common/errors/no-meeting-info.js +51 -0
- package/dist/common/errors/no-meeting-info.js.map +1 -0
- package/dist/common/errors/reclaim-host-role-errors.js +158 -0
- package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
- package/dist/common/errors/webex-errors.js +48 -7
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/common/logs/logger-proxy.js +1 -1
- package/dist/common/logs/logger-proxy.js.map +1 -1
- package/dist/common/logs/request.js +5 -1
- package/dist/common/logs/request.js.map +1 -1
- package/dist/common/queue.js +24 -9
- package/dist/common/queue.js.map +1 -1
- package/dist/config.js +5 -10
- package/dist/config.js.map +1 -1
- package/dist/constants.js +242 -33
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +14 -2
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.js +109 -15
- package/dist/controls-options-manager/index.js.map +1 -1
- 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 +309 -18
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/index.js +110 -2
- package/dist/index.js.map +1 -1
- package/dist/interceptors/index.js +15 -0
- package/dist/interceptors/index.js.map +1 -0
- package/dist/interceptors/locusRetry.js +93 -0
- package/dist/interceptors/locusRetry.js.map +1 -0
- package/dist/interpretation/collection.js +23 -0
- package/dist/interpretation/collection.js.map +1 -0
- package/dist/interpretation/index.js +380 -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 +91 -2
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +386 -62
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js +7 -1
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js +71 -1
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.js +249 -72
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +89 -14
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +65 -102
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +73 -124
- package/dist/media/properties.js.map +1 -1
- package/dist/mediaQualityMetrics/config.js +135 -330
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +86 -2
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +4075 -2827
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +292 -0
- package/dist/meeting/locusMediaRequest.js.map +1 -0
- package/dist/meeting/muteState.js +224 -136
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +177 -152
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +672 -417
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/index.js +73 -7
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +192 -51
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/util.js +1 -1
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +36 -36
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +39 -0
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +484 -119
- 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 +2 -0
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +73 -7
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +58 -0
- 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 +132 -25
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js +10 -0
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +102 -6
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +106 -38
- 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 +326 -232
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +18 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +1 -446
- package/dist/metrics/index.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +223 -32
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +10 -0
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +39 -36
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +3 -1
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +76 -5
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +366 -104
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +255 -0
- package/dist/multistream/sendSlotManager.js.map +1 -0
- package/dist/reachability/clusterReachability.js +356 -0
- package/dist/reachability/clusterReachability.js.map +1 -0
- package/dist/reachability/index.js +263 -390
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +6 -4
- package/dist/reachability/request.js.map +1 -1
- package/dist/reachability/util.js +29 -0
- package/dist/reachability/util.js.map +1 -0
- package/dist/reconnection-manager/index.js +266 -202
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/index.js +21 -2
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.js +9 -8
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js +51 -28
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +48 -64
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +220 -70
- 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 +179 -0
- package/dist/rtcMetrics/index.js.map +1 -0
- package/dist/statsAnalyzer/index.js +357 -295
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +296 -156
- package/dist/statsAnalyzer/mqaUtil.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/events.d.ts +8 -0
- package/dist/types/breakouts/utils.d.ts +14 -0
- package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
- package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
- package/dist/types/common/errors/webex-errors.d.ts +25 -1
- package/dist/types/common/logs/request.d.ts +2 -0
- package/dist/types/common/queue.d.ts +9 -7
- package/dist/types/config.d.ts +2 -7
- package/dist/types/constants.d.ts +203 -31
- package/dist/types/controls-options-manager/enums.d.ts +11 -1
- package/dist/types/controls-options-manager/index.d.ts +17 -1
- package/dist/types/controls-options-manager/types.d.ts +43 -0
- package/dist/types/controls-options-manager/util.d.ts +1 -7
- package/dist/types/index.d.ts +6 -5
- package/dist/types/interceptors/index.d.ts +2 -0
- package/dist/types/interceptors/locusRetry.d.ts +27 -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/index.d.ts +57 -4
- package/dist/types/locus-info/parser.d.ts +66 -6
- package/dist/types/media/index.d.ts +2 -0
- package/dist/types/media/properties.d.ts +34 -49
- package/dist/types/mediaQualityMetrics/config.d.ts +99 -223
- package/dist/types/meeting/in-meeting-actions.d.ts +86 -2
- package/dist/types/meeting/index.d.ts +567 -496
- package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
- package/dist/types/meeting/muteState.d.ts +93 -25
- package/dist/types/meeting/request.d.ts +64 -43
- package/dist/types/meeting/util.d.ts +117 -1
- package/dist/types/meeting-info/index.d.ts +13 -1
- package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
- package/dist/types/meetings/collection.d.ts +17 -0
- package/dist/types/meetings/index.d.ts +113 -21
- package/dist/types/meetings/meetings.types.d.ts +4 -0
- package/dist/types/member/index.d.ts +14 -0
- package/dist/types/member/types.d.ts +32 -0
- package/dist/types/members/collection.d.ts +5 -0
- package/dist/types/members/index.d.ts +35 -2
- package/dist/types/members/request.d.ts +73 -9
- package/dist/types/members/types.d.ts +25 -0
- package/dist/types/members/util.d.ts +214 -1
- package/dist/types/metrics/constants.d.ts +17 -0
- package/dist/types/metrics/index.d.ts +4 -111
- package/dist/types/multistream/mediaRequestManager.d.ts +72 -3
- package/dist/types/multistream/receiveSlot.d.ts +7 -3
- package/dist/types/multistream/receiveSlotManager.d.ts +14 -4
- package/dist/types/multistream/remoteMedia.d.ts +3 -31
- package/dist/types/multistream/remoteMediaGroup.d.ts +2 -9
- package/dist/types/multistream/remoteMediaManager.d.ts +62 -2
- package/dist/types/multistream/sendSlotManager.d.ts +70 -0
- package/dist/types/reachability/clusterReachability.d.ts +109 -0
- package/dist/types/reachability/index.d.ts +60 -95
- package/dist/types/reachability/request.d.ts +3 -1
- package/dist/types/reachability/util.d.ts +8 -0
- package/dist/types/reconnection-manager/index.d.ts +19 -0
- package/dist/types/recording-controller/index.d.ts +15 -1
- package/dist/types/recording-controller/util.d.ts +5 -4
- package/dist/types/roap/index.d.ts +2 -1
- package/dist/types/roap/request.d.ts +9 -8
- package/dist/types/roap/turnDiscovery.d.ts +39 -5
- package/dist/types/rtcMetrics/constants.d.ts +4 -0
- package/dist/types/rtcMetrics/index.d.ts +61 -0
- package/dist/types/statsAnalyzer/index.d.ts +34 -12
- package/dist/types/statsAnalyzer/mqaUtil.d.ts +28 -4
- package/dist/types/webinar/collection.d.ts +16 -0
- package/dist/types/webinar/index.d.ts +5 -0
- package/dist/webinar/collection.js +44 -0
- package/dist/webinar/collection.js.map +1 -0
- package/dist/webinar/index.js +69 -0
- package/dist/webinar/index.js.map +1 -0
- package/package.json +22 -19
- 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 +35 -11
- package/src/breakouts/breakout.ts +67 -9
- package/src/breakouts/events.ts +56 -0
- package/src/breakouts/index.ts +558 -59
- package/src/breakouts/utils.ts +42 -0
- package/src/common/errors/no-meeting-info.ts +24 -0
- package/src/common/errors/reclaim-host-role-errors.ts +134 -0
- package/src/common/errors/webex-errors.ts +44 -2
- package/src/common/logs/logger-proxy.ts +1 -1
- package/src/common/logs/request.ts +5 -1
- package/src/common/queue.ts +22 -8
- package/src/config.ts +4 -9
- package/src/constants.ts +229 -21
- package/src/controls-options-manager/enums.ts +12 -0
- package/src/controls-options-manager/index.ts +116 -21
- package/src/controls-options-manager/types.ts +59 -0
- package/src/controls-options-manager/util.ts +294 -14
- package/src/index.ts +44 -0
- package/src/interceptors/index.ts +3 -0
- package/src/interceptors/locusRetry.ts +67 -0
- package/src/interpretation/README.md +60 -0
- package/src/interpretation/collection.ts +19 -0
- package/src/interpretation/index.ts +349 -0
- package/src/interpretation/siLanguage.ts +18 -0
- package/src/locus-info/controlsUtils.ts +108 -0
- package/src/locus-info/index.ts +417 -59
- package/src/locus-info/infoUtils.ts +10 -2
- package/src/locus-info/mediaSharesUtils.ts +80 -0
- package/src/locus-info/parser.ts +258 -47
- package/src/locus-info/selfUtils.ts +81 -5
- package/src/media/index.ts +100 -108
- package/src/media/properties.ts +88 -117
- package/src/mediaQualityMetrics/config.ts +103 -238
- package/src/meeting/in-meeting-actions.ts +171 -3
- package/src/meeting/index.ts +3411 -2435
- package/src/meeting/locusMediaRequest.ts +313 -0
- package/src/meeting/muteState.ts +223 -136
- package/src/meeting/request.ts +155 -120
- package/src/meeting/util.ts +685 -395
- package/src/meeting-info/index.ts +81 -8
- package/src/meeting-info/meeting-info-v2.ts +170 -14
- package/src/meeting-info/util.ts +1 -1
- package/src/meeting-info/utilv2.ts +23 -23
- package/src/meetings/collection.ts +33 -0
- package/src/meetings/index.ts +507 -127
- package/src/meetings/meetings.types.ts +12 -0
- package/src/meetings/request.ts +2 -0
- package/src/meetings/util.ts +81 -12
- package/src/member/index.ts +58 -0
- package/src/member/types.ts +38 -0
- package/src/member/util.ts +141 -25
- package/src/members/collection.ts +8 -0
- package/src/members/index.ts +134 -8
- package/src/members/request.ts +97 -17
- package/src/members/types.ts +29 -0
- package/src/members/util.ts +333 -240
- package/src/metrics/constants.ts +17 -0
- package/src/metrics/index.ts +1 -469
- package/src/multistream/mediaRequestManager.ts +271 -56
- package/src/multistream/receiveSlot.ts +11 -4
- package/src/multistream/receiveSlotManager.ts +34 -24
- package/src/multistream/remoteMedia.ts +5 -3
- package/src/multistream/remoteMediaGroup.ts +78 -0
- package/src/multistream/remoteMediaManager.ts +248 -44
- package/src/multistream/sendSlotManager.ts +199 -0
- package/src/reachability/clusterReachability.ts +320 -0
- package/src/reachability/index.ts +229 -346
- package/src/reachability/request.ts +8 -4
- package/src/reachability/util.ts +24 -0
- package/src/reconnection-manager/index.ts +128 -97
- package/src/recording-controller/index.ts +20 -3
- package/src/recording-controller/util.ts +26 -9
- package/src/roap/index.ts +52 -23
- package/src/roap/request.ts +48 -67
- package/src/roap/turnDiscovery.ts +147 -49
- package/src/rtcMetrics/constants.ts +3 -0
- package/src/rtcMetrics/index.ts +166 -0
- package/src/statsAnalyzer/index.ts +457 -416
- package/src/statsAnalyzer/mqaUtil.ts +317 -170
- package/src/webinar/collection.ts +31 -0
- package/src/webinar/index.ts +62 -0
- package/test/integration/spec/converged-space-meetings.js +60 -3
- package/test/integration/spec/journey.js +320 -261
- package/test/integration/spec/space-meeting.js +76 -3
- package/test/unit/spec/annotation/index.ts +418 -0
- package/test/unit/spec/breakouts/breakout.ts +118 -28
- package/test/unit/spec/breakouts/events.ts +89 -0
- package/test/unit/spec/breakouts/index.ts +1349 -114
- package/test/unit/spec/breakouts/utils.js +52 -1
- package/test/unit/spec/common/queue.js +31 -2
- package/test/unit/spec/controls-options-manager/index.js +163 -0
- package/test/unit/spec/controls-options-manager/util.js +576 -60
- package/test/unit/spec/fixture/locus.js +1 -0
- package/test/unit/spec/interceptors/locusRetry.ts +131 -0
- package/test/unit/spec/interpretation/collection.ts +15 -0
- package/test/unit/spec/interpretation/index.ts +625 -0
- package/test/unit/spec/interpretation/siLanguage.ts +28 -0
- package/test/unit/spec/locus-info/controlsUtils.js +316 -43
- package/test/unit/spec/locus-info/index.js +1363 -37
- package/test/unit/spec/locus-info/infoUtils.js +37 -15
- package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
- package/test/unit/spec/locus-info/mediaSharesUtils.ts +41 -0
- package/test/unit/spec/locus-info/parser.js +116 -35
- package/test/unit/spec/locus-info/selfConstant.js +27 -4
- package/test/unit/spec/locus-info/selfUtils.js +208 -17
- package/test/unit/spec/media/index.ts +173 -81
- package/test/unit/spec/media/properties.ts +2 -2
- package/test/unit/spec/meeting/in-meeting-actions.ts +85 -3
- package/test/unit/spec/meeting/index.js +6821 -2172
- package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
- package/test/unit/spec/meeting/muteState.js +402 -212
- package/test/unit/spec/meeting/request.js +473 -54
- package/test/unit/spec/meeting/utils.js +773 -67
- package/test/unit/spec/meeting-info/index.js +300 -0
- package/test/unit/spec/meeting-info/meetinginfov2.js +526 -5
- package/test/unit/spec/meeting-info/utilv2.js +21 -0
- package/test/unit/spec/meetings/collection.js +26 -0
- package/test/unit/spec/meetings/index.js +1415 -213
- package/test/unit/spec/meetings/utils.js +229 -2
- package/test/unit/spec/member/index.js +61 -6
- package/test/unit/spec/member/util.js +510 -34
- package/test/unit/spec/members/index.js +432 -1
- package/test/unit/spec/members/request.js +206 -27
- package/test/unit/spec/members/utils.js +210 -0
- package/test/unit/spec/metrics/index.js +1 -50
- package/test/unit/spec/multistream/mediaRequestManager.ts +781 -114
- package/test/unit/spec/multistream/receiveSlot.ts +9 -1
- package/test/unit/spec/multistream/receiveSlotManager.ts +32 -30
- package/test/unit/spec/multistream/remoteMedia.ts +2 -0
- package/test/unit/spec/multistream/remoteMediaGroup.ts +345 -0
- package/test/unit/spec/multistream/remoteMediaManager.ts +525 -0
- package/test/unit/spec/multistream/sendSlotManager.ts +274 -0
- package/test/unit/spec/reachability/clusterReachability.ts +279 -0
- package/test/unit/spec/reachability/index.ts +551 -14
- package/test/unit/spec/reachability/request.js +3 -1
- package/test/unit/spec/reachability/util.ts +40 -0
- package/test/unit/spec/reconnection-manager/index.js +171 -11
- package/test/unit/spec/recording-controller/index.js +294 -218
- package/test/unit/spec/recording-controller/util.js +223 -96
- package/test/unit/spec/roap/index.ts +180 -83
- package/test/unit/spec/roap/request.ts +100 -62
- package/test/unit/spec/roap/turnDiscovery.ts +388 -96
- package/test/unit/spec/rtcMetrics/index.ts +122 -0
- package/test/unit/spec/stats-analyzer/index.js +1252 -12
- package/test/unit/spec/webinar/collection.ts +13 -0
- package/test/unit/spec/webinar/index.ts +60 -0
- package/test/utils/integrationTestUtils.js +46 -0
- package/test/utils/testUtils.js +0 -57
- package/test/utils/webex-test-users.js +12 -4
- package/dist/metrics/config.js +0 -289
- package/dist/metrics/config.js.map +0 -1
- package/dist/types/metrics/config.d.ts +0 -169
- package/src/index.js +0 -18
- package/src/metrics/config.ts +0 -485
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import 'jsdom-global/register';
|
|
5
5
|
|
|
6
|
+
// Polyfill for crypto: https://github.com/jsdom/jsdom/issues/1612#issuecomment-663210638
|
|
7
|
+
import {Crypto} from '@peculiar/webcrypto';
|
|
8
|
+
global.crypto = new Crypto();
|
|
9
|
+
|
|
6
10
|
import Device from '@webex/internal-plugin-device';
|
|
7
11
|
import Mercury from '@webex/internal-plugin-mercury';
|
|
8
12
|
import {assert} from '@webex/test-helper-chai';
|
|
@@ -11,14 +15,16 @@ import sinon from 'sinon';
|
|
|
11
15
|
import uuid from 'uuid';
|
|
12
16
|
import StaticConfig from '@webex/plugin-meetings/src/common/config';
|
|
13
17
|
import TriggerProxy from '@webex/plugin-meetings/src/common/events/trigger-proxy';
|
|
18
|
+
import LoggerProxy from '@webex/plugin-meetings/src/common/logs/logger-proxy';
|
|
14
19
|
import LoggerConfig from '@webex/plugin-meetings/src/common/logs/logger-config';
|
|
15
|
-
import Meeting from '@webex/plugin-meetings/src/meeting';
|
|
20
|
+
import Meeting, {CallStateForMetrics} from '@webex/plugin-meetings/src/meeting';
|
|
16
21
|
import MeetingUtil from '@webex/plugin-meetings/src/meeting/util';
|
|
17
22
|
import Meetings from '@webex/plugin-meetings/src/meetings';
|
|
18
23
|
import MeetingCollection from '@webex/plugin-meetings/src/meetings/collection';
|
|
19
24
|
import MeetingsUtil from '@webex/plugin-meetings/src/meetings/util';
|
|
20
25
|
import PersonalMeetingRoom from '@webex/plugin-meetings/src/personal-meeting-room';
|
|
21
26
|
import Reachability from '@webex/plugin-meetings/src/reachability';
|
|
27
|
+
import Metrics from '@webex/plugin-meetings/src/metrics';
|
|
22
28
|
|
|
23
29
|
import testUtils from '../../../utils/testUtils';
|
|
24
30
|
import {
|
|
@@ -29,6 +35,12 @@ import {
|
|
|
29
35
|
LOCUSINFO,
|
|
30
36
|
EVENT_TRIGGERS,
|
|
31
37
|
} from '../../../../src/constants';
|
|
38
|
+
import CaptchaError from '@webex/plugin-meetings/src/common/errors/captcha-error';
|
|
39
|
+
import {forEach} from 'lodash';
|
|
40
|
+
import PasswordError from '@webex/plugin-meetings/src/common/errors/password-error';
|
|
41
|
+
import PermissionError from '@webex/plugin-meetings/src/common/errors/permission';
|
|
42
|
+
import {NoiseReductionEffect, VirtualBackgroundEffect} from '@webex/media-helpers';
|
|
43
|
+
import NoMeetingInfoError from '../../../../src/common/errors/no-meeting-info';
|
|
32
44
|
|
|
33
45
|
describe('plugin-meetings', () => {
|
|
34
46
|
const logger = {
|
|
@@ -40,6 +52,8 @@ describe('plugin-meetings', () => {
|
|
|
40
52
|
debug: () => {},
|
|
41
53
|
};
|
|
42
54
|
|
|
55
|
+
let triggerProxyStub;
|
|
56
|
+
|
|
43
57
|
beforeEach(() => {
|
|
44
58
|
StaticConfig.set({
|
|
45
59
|
bandwidth: {
|
|
@@ -51,7 +65,7 @@ describe('plugin-meetings', () => {
|
|
|
51
65
|
verboseEvents: true,
|
|
52
66
|
enable: false,
|
|
53
67
|
});
|
|
54
|
-
|
|
68
|
+
triggerProxyStub = sinon.stub(TriggerProxy, 'trigger').returns(true);
|
|
55
69
|
});
|
|
56
70
|
|
|
57
71
|
let webex;
|
|
@@ -60,6 +74,7 @@ describe('plugin-meetings', () => {
|
|
|
60
74
|
let url1;
|
|
61
75
|
let test1;
|
|
62
76
|
let test2;
|
|
77
|
+
let locusInfo;
|
|
63
78
|
|
|
64
79
|
describe('meetings index', () => {
|
|
65
80
|
beforeEach(() => {
|
|
@@ -69,6 +84,10 @@ describe('plugin-meetings', () => {
|
|
|
69
84
|
uri1 = `test-${uuid.v4()}@example.com`;
|
|
70
85
|
test1 = `test-${uuid.v4()}`;
|
|
71
86
|
test2 = `test2-${uuid.v4()}`;
|
|
87
|
+
locusInfo = {
|
|
88
|
+
parse: sinon.stub().returns(true),
|
|
89
|
+
updateMainSessionLocusCache: sinon.stub(),
|
|
90
|
+
};
|
|
72
91
|
webex = new MockWebex({
|
|
73
92
|
children: {
|
|
74
93
|
device: Device,
|
|
@@ -151,6 +170,10 @@ describe('plugin-meetings', () => {
|
|
|
151
170
|
webex.emit('ready');
|
|
152
171
|
});
|
|
153
172
|
|
|
173
|
+
afterEach(() => {
|
|
174
|
+
sinon.restore();
|
|
175
|
+
});
|
|
176
|
+
|
|
154
177
|
it('has a webex instance with a meetings property', () => {
|
|
155
178
|
assert.exists(webex, 'webex was initialized with children');
|
|
156
179
|
assert.exists(webex.meetings, 'meetings child was set up on the webex instance');
|
|
@@ -217,30 +240,15 @@ describe('plugin-meetings', () => {
|
|
|
217
240
|
});
|
|
218
241
|
});
|
|
219
242
|
|
|
220
|
-
describe('#
|
|
221
|
-
it('should have
|
|
222
|
-
assert.equal(typeof webex.meetings.
|
|
243
|
+
describe('#_toggleTcpReachability', () => {
|
|
244
|
+
it('should have _toggleTcpReachability', () => {
|
|
245
|
+
assert.equal(typeof webex.meetings._toggleTcpReachability, 'function');
|
|
223
246
|
});
|
|
224
247
|
|
|
225
248
|
describe('success', () => {
|
|
226
|
-
it('should update meetings to do
|
|
227
|
-
webex.meetings.
|
|
228
|
-
assert.equal(webex.meetings.config.experimental.
|
|
229
|
-
|
|
230
|
-
webex.meetings._toggleTurnDiscovery(false);
|
|
231
|
-
assert.equal(webex.meetings.config.experimental.enableTurnDiscovery, false);
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
describe('failure', () => {
|
|
236
|
-
it('should not accept non boolean input', () => {
|
|
237
|
-
const currentEnableTurnDiscovery = webex.meetings.config.experimental.enableTurnDiscovery;
|
|
238
|
-
|
|
239
|
-
webex.meetings._toggleTurnDiscovery('test');
|
|
240
|
-
assert.equal(
|
|
241
|
-
webex.meetings.config.experimental.enableAdhocMeetings,
|
|
242
|
-
currentEnableTurnDiscovery
|
|
243
|
-
);
|
|
249
|
+
it('should update meetings to do TCP reachability', () => {
|
|
250
|
+
webex.meetings._toggleTcpReachability(true);
|
|
251
|
+
assert.equal(webex.meetings.config.experimental.enableTcpReachability, true);
|
|
244
252
|
});
|
|
245
253
|
});
|
|
246
254
|
});
|
|
@@ -338,37 +346,110 @@ describe('plugin-meetings', () => {
|
|
|
338
346
|
});
|
|
339
347
|
});
|
|
340
348
|
|
|
349
|
+
describe('virtual background effect', () => {
|
|
350
|
+
beforeEach(() => {
|
|
351
|
+
webex.credentials = {
|
|
352
|
+
supertoken: {
|
|
353
|
+
access_token: 'fake_token',
|
|
354
|
+
},
|
|
355
|
+
};
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('creates background effect', async () => {
|
|
359
|
+
const result = await webex.meetings.createVirtualBackgroundEffect();
|
|
360
|
+
|
|
361
|
+
assert.exists(result);
|
|
362
|
+
assert.instanceOf(result, VirtualBackgroundEffect);
|
|
363
|
+
assert.containsAllKeys(result, ['loadModel', 'isEnabled', 'options']);
|
|
364
|
+
assert.deepEqual(result.options, {
|
|
365
|
+
mode: 'BLUR',
|
|
366
|
+
blurStrength: 'STRONG',
|
|
367
|
+
generator: 'worker',
|
|
368
|
+
quality: 'LOW',
|
|
369
|
+
authToken: 'fake_token',
|
|
370
|
+
mirror: false,
|
|
371
|
+
});
|
|
372
|
+
assert.exists(result.enable);
|
|
373
|
+
assert.exists(result.disable);
|
|
374
|
+
assert.exists(result.dispose);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('creates background effect with custom options passed', async () => {
|
|
378
|
+
const effectOptions = {
|
|
379
|
+
generator: 'local',
|
|
380
|
+
frameRate: 45,
|
|
381
|
+
mode: 'IMAGE',
|
|
382
|
+
mirror: false,
|
|
383
|
+
quality: 'HIGH',
|
|
384
|
+
blurStrength: 'STRONG',
|
|
385
|
+
bgImageUrl: 'https://test.webex.com/landscape.5a535788.jpg',
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
const result = await webex.meetings.createVirtualBackgroundEffect(effectOptions);
|
|
389
|
+
|
|
390
|
+
assert.exists(result);
|
|
391
|
+
assert.instanceOf(result, VirtualBackgroundEffect);
|
|
392
|
+
assert.containsAllKeys(result, ['loadModel', 'isEnabled', 'options']);
|
|
393
|
+
assert.deepEqual(result.options, {...effectOptions, authToken: 'fake_token'});
|
|
394
|
+
assert.exists(result.enable);
|
|
395
|
+
assert.exists(result.disable);
|
|
396
|
+
assert.exists(result.dispose);
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
describe('noise reduction effect', () => {
|
|
401
|
+
beforeEach(() => {
|
|
402
|
+
webex.credentials = {
|
|
403
|
+
supertoken: {
|
|
404
|
+
access_token: 'fake_token',
|
|
405
|
+
},
|
|
406
|
+
};
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
it('creates noise reduction effect', async () => {
|
|
410
|
+
const result = await webex.meetings.createNoiseReductionEffect({audioContext: {}});
|
|
411
|
+
|
|
412
|
+
assert.exists(result);
|
|
413
|
+
assert.instanceOf(result, NoiseReductionEffect);
|
|
414
|
+
assert.containsAllKeys(result, ['audioContext', 'isEnabled', 'isReady', 'options']);
|
|
415
|
+
assert.deepEqual(result.options, {
|
|
416
|
+
authToken: 'fake_token',
|
|
417
|
+
audioContext: {},
|
|
418
|
+
});
|
|
419
|
+
assert.exists(result.enable);
|
|
420
|
+
assert.exists(result.disable);
|
|
421
|
+
assert.exists(result.dispose);
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
it('creates noise reduction effect with custom options passed', async () => {
|
|
425
|
+
const effectOptions = {
|
|
426
|
+
audioContext: {},
|
|
427
|
+
mode: 'WORKLET',
|
|
428
|
+
env: 'prod',
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
const result = await webex.meetings.createNoiseReductionEffect(effectOptions);
|
|
432
|
+
|
|
433
|
+
assert.exists(result);
|
|
434
|
+
assert.instanceOf(result, NoiseReductionEffect);
|
|
435
|
+
assert.containsAllKeys(result, ['audioContext', 'isEnabled', 'isReady', 'options']);
|
|
436
|
+
assert.deepEqual(result.options, {...effectOptions, authToken: 'fake_token'});
|
|
437
|
+
assert.exists(result.enable);
|
|
438
|
+
assert.exists(result.disable);
|
|
439
|
+
assert.exists(result.dispose);
|
|
440
|
+
});
|
|
441
|
+
});
|
|
442
|
+
|
|
341
443
|
describe('gets', () => {
|
|
342
444
|
describe('#getReachability', () => {
|
|
343
445
|
it('should have #getReachability', () => {
|
|
344
446
|
assert.exists(webex.meetings.getReachability);
|
|
345
447
|
});
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
const reachability = webex.meetings.getReachability();
|
|
349
|
-
|
|
350
|
-
assert.notExists(
|
|
351
|
-
reachability,
|
|
352
|
-
'reachability is undefined because #setReachability has not been called'
|
|
353
|
-
);
|
|
354
|
-
});
|
|
355
|
-
});
|
|
356
|
-
describe('after #setReachability', () => {
|
|
357
|
-
beforeEach(() => {
|
|
358
|
-
webex.meetings.setReachability();
|
|
359
|
-
const reachabilityMocker = webex.meetings.getReachability();
|
|
360
|
-
|
|
361
|
-
sinon.stub(reachabilityMocker, 'gatherReachability').returns(true);
|
|
362
|
-
});
|
|
363
|
-
it('gets the reachability data instance from webex.meetings', () => {
|
|
364
|
-
const reachability = webex.meetings.getReachability();
|
|
448
|
+
it('gets the reachability data instance from webex.meetings', () => {
|
|
449
|
+
const reachability = webex.meetings.getReachability();
|
|
365
450
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
'reachability is defined because #setReachability has been called'
|
|
369
|
-
);
|
|
370
|
-
assert.instanceOf(reachability, Reachability, 'should be a reachability instance');
|
|
371
|
-
});
|
|
451
|
+
assert.exists(reachability, 'reachability is defined');
|
|
452
|
+
assert.instanceOf(reachability, Reachability, 'should be a reachability instance');
|
|
372
453
|
});
|
|
373
454
|
});
|
|
374
455
|
describe('#getPersonalMeetingRoom', () => {
|
|
@@ -430,6 +511,27 @@ describe('plugin-meetings', () => {
|
|
|
430
511
|
it('should have #syncMeetings', () => {
|
|
431
512
|
assert.exists(webex.meetings.syncMeetings);
|
|
432
513
|
});
|
|
514
|
+
it('should do nothing and return a resolved promise if unverified guest', async () => {
|
|
515
|
+
webex.meetings.request.getActiveMeetings = sinon.stub().returns(
|
|
516
|
+
Promise.resolve({
|
|
517
|
+
loci: [
|
|
518
|
+
{
|
|
519
|
+
url: url1,
|
|
520
|
+
},
|
|
521
|
+
],
|
|
522
|
+
})
|
|
523
|
+
);
|
|
524
|
+
webex.credentials.isUnverifiedGuest = true;
|
|
525
|
+
LoggerProxy.logger.info = sinon.stub();
|
|
526
|
+
|
|
527
|
+
await webex.meetings.syncMeetings();
|
|
528
|
+
|
|
529
|
+
assert.notCalled(webex.meetings.request.getActiveMeetings);
|
|
530
|
+
assert.calledWith(
|
|
531
|
+
LoggerProxy.logger.info,
|
|
532
|
+
'Meetings:index#syncMeetings --> skipping meeting sync as unverified guest'
|
|
533
|
+
);
|
|
534
|
+
});
|
|
433
535
|
describe('succesful requests', () => {
|
|
434
536
|
beforeEach(() => {
|
|
435
537
|
webex.meetings.request.getActiveMeetings = sinon.stub().returns(
|
|
@@ -443,21 +545,16 @@ describe('plugin-meetings', () => {
|
|
|
443
545
|
);
|
|
444
546
|
});
|
|
445
547
|
describe('when meeting is returned', () => {
|
|
446
|
-
let parse;
|
|
447
|
-
|
|
448
548
|
beforeEach(() => {
|
|
449
|
-
parse = sinon.stub().returns(true);
|
|
450
549
|
webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
|
|
451
|
-
locusInfo
|
|
452
|
-
parse,
|
|
453
|
-
},
|
|
550
|
+
locusInfo,
|
|
454
551
|
});
|
|
455
552
|
});
|
|
456
553
|
it('tests the sync meeting calls for existing meeting', async () => {
|
|
457
554
|
await webex.meetings.syncMeetings();
|
|
458
555
|
assert.calledOnce(webex.meetings.request.getActiveMeetings);
|
|
459
556
|
assert.calledOnce(webex.meetings.meetingCollection.getByKey);
|
|
460
|
-
assert.calledOnce(parse);
|
|
557
|
+
assert.calledOnce(locusInfo.parse);
|
|
461
558
|
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
|
|
462
559
|
});
|
|
463
560
|
});
|
|
@@ -470,6 +567,7 @@ describe('plugin-meetings', () => {
|
|
|
470
567
|
webex.meetings.create = sinon.stub().returns(
|
|
471
568
|
Promise.resolve({
|
|
472
569
|
locusInfo: {
|
|
570
|
+
...locusInfo,
|
|
473
571
|
initialSetup,
|
|
474
572
|
},
|
|
475
573
|
})
|
|
@@ -478,7 +576,7 @@ describe('plugin-meetings', () => {
|
|
|
478
576
|
it('tests the sync meeting calls for not existing meeting', async () => {
|
|
479
577
|
await webex.meetings.syncMeetings();
|
|
480
578
|
assert.calledOnce(webex.meetings.request.getActiveMeetings);
|
|
481
|
-
assert.callCount(webex.meetings.meetingCollection.getByKey,
|
|
579
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
|
|
482
580
|
assert.calledOnce(initialSetup);
|
|
483
581
|
assert.calledOnce(webex.meetings.create);
|
|
484
582
|
assert.calledWith(webex.meetings.request.getActiveMeetings);
|
|
@@ -495,46 +593,71 @@ describe('plugin-meetings', () => {
|
|
|
495
593
|
});
|
|
496
594
|
});
|
|
497
595
|
});
|
|
498
|
-
describe('
|
|
499
|
-
let initialSetup;
|
|
500
|
-
let parse;
|
|
596
|
+
describe('when destroying meeting is needed', () => {
|
|
501
597
|
let destroySpy;
|
|
502
598
|
|
|
599
|
+
const meetingCollectionMeetings = {
|
|
600
|
+
stillValidLocusMeeting: {
|
|
601
|
+
locusUrl: 'still-valid-locus-url',
|
|
602
|
+
sendCallAnalyzerMetrics: sinon.stub(),
|
|
603
|
+
},
|
|
604
|
+
noLongerValidLocusMeeting: {
|
|
605
|
+
locusUrl: 'no-longer-valid-locus-url',
|
|
606
|
+
sendCallAnalyzerMetrics: sinon.stub(),
|
|
607
|
+
},
|
|
608
|
+
otherNonLocusMeeting1: {
|
|
609
|
+
locusUrl: null,
|
|
610
|
+
sendCallAnalyzerMetrics: sinon.stub(),
|
|
611
|
+
},
|
|
612
|
+
otherNonLocusMeeting2: {
|
|
613
|
+
locusUrl: undefined,
|
|
614
|
+
sendCallAnalyzerMetrics: sinon.stub(),
|
|
615
|
+
},
|
|
616
|
+
};
|
|
617
|
+
|
|
503
618
|
beforeEach(() => {
|
|
504
619
|
destroySpy = sinon.spy(webex.meetings, 'destroy');
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
locusInfo: {
|
|
509
|
-
parse,
|
|
510
|
-
},
|
|
511
|
-
sendCallAnalyzerMetrics: sinon.stub(),
|
|
512
|
-
});
|
|
513
|
-
webex.meetings.meetingCollection.getAll = sinon.stub().returns({
|
|
514
|
-
meetingutk: {
|
|
515
|
-
locusUrl: 'fdfdjfdhj',
|
|
516
|
-
sendCallAnalyzerMetrics: sinon.stub(),
|
|
517
|
-
},
|
|
518
|
-
});
|
|
519
|
-
webex.meetings.create = sinon.stub().returns(
|
|
520
|
-
Promise.resolve({
|
|
521
|
-
locusInfo: {
|
|
522
|
-
initialSetup,
|
|
523
|
-
},
|
|
524
|
-
sendCallAnalyzerMetrics: sinon.stub(),
|
|
525
|
-
})
|
|
526
|
-
);
|
|
620
|
+
webex.meetings.meetingCollection.getAll = sinon
|
|
621
|
+
.stub()
|
|
622
|
+
.returns(meetingCollectionMeetings);
|
|
527
623
|
webex.meetings.request.getActiveMeetings = sinon.stub().returns(
|
|
528
624
|
Promise.resolve({
|
|
529
|
-
loci: [],
|
|
625
|
+
loci: [{url: 'still-valid-locus-url'}],
|
|
530
626
|
})
|
|
531
627
|
);
|
|
532
628
|
MeetingUtil.cleanUp = sinon.stub().returns(Promise.resolve());
|
|
533
629
|
});
|
|
534
|
-
|
|
630
|
+
|
|
631
|
+
it('destroy any meeting that has no active locus url if keepOnlyLocusMeetings is not defined', async () => {
|
|
535
632
|
await webex.meetings.syncMeetings();
|
|
536
633
|
assert.calledOnce(webex.meetings.request.getActiveMeetings);
|
|
537
|
-
assert.calledOnce(
|
|
634
|
+
assert.calledOnce(webex.meetings.meetingCollection.getAll);
|
|
635
|
+
assert.calledWith(destroySpy, meetingCollectionMeetings.noLongerValidLocusMeeting);
|
|
636
|
+
assert.calledWith(destroySpy, meetingCollectionMeetings.otherNonLocusMeeting1);
|
|
637
|
+
assert.calledWith(destroySpy, meetingCollectionMeetings.otherNonLocusMeeting2);
|
|
638
|
+
assert.callCount(destroySpy, 3);
|
|
639
|
+
|
|
640
|
+
assert.callCount(MeetingUtil.cleanUp, 3);
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
it('destroy any meeting that has no active locus url if keepOnlyLocusMeetings === true', async () => {
|
|
644
|
+
await webex.meetings.syncMeetings({keepOnlyLocusMeetings: true});
|
|
645
|
+
assert.calledOnce(webex.meetings.request.getActiveMeetings);
|
|
646
|
+
assert.calledOnce(webex.meetings.meetingCollection.getAll);
|
|
647
|
+
assert.calledWith(destroySpy, meetingCollectionMeetings.noLongerValidLocusMeeting);
|
|
648
|
+
assert.calledWith(destroySpy, meetingCollectionMeetings.otherNonLocusMeeting1);
|
|
649
|
+
assert.calledWith(destroySpy, meetingCollectionMeetings.otherNonLocusMeeting2);
|
|
650
|
+
assert.callCount(destroySpy, 3);
|
|
651
|
+
|
|
652
|
+
assert.callCount(MeetingUtil.cleanUp, 3);
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
it('destroy any LOCUS meetings that have no active locus url if keepOnlyLocusMeetings === false', async () => {
|
|
656
|
+
await webex.meetings.syncMeetings({keepOnlyLocusMeetings: false});
|
|
657
|
+
assert.calledOnce(webex.meetings.request.getActiveMeetings);
|
|
658
|
+
assert.calledOnce(webex.meetings.meetingCollection.getAll);
|
|
659
|
+
assert.calledWith(destroySpy, meetingCollectionMeetings.noLongerValidLocusMeeting);
|
|
660
|
+
assert.callCount(destroySpy, 1);
|
|
538
661
|
|
|
539
662
|
assert.calledOnce(MeetingUtil.cleanUp);
|
|
540
663
|
});
|
|
@@ -574,14 +697,139 @@ describe('plugin-meetings', () => {
|
|
|
574
697
|
});
|
|
575
698
|
});
|
|
576
699
|
|
|
700
|
+
const FAKE_USE_RANDOM_DELAY = true;
|
|
701
|
+
const correlationId = 'my-correlationId';
|
|
702
|
+
const callStateForMetrics = {
|
|
703
|
+
correlationId: 'my-correlationId2',
|
|
704
|
+
joinTrigger: 'my-join-trigger',
|
|
705
|
+
loginType: 'my-login-type',
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
it('should call setCallStateForMetrics on any pre-existing meeting', async () => {
|
|
709
|
+
const fakeMeeting = {setCallStateForMetrics: sinon.mock()};
|
|
710
|
+
webex.meetings.meetingCollection.getByKey = sinon.stub().returns(fakeMeeting);
|
|
711
|
+
await webex.meetings.create(
|
|
712
|
+
test1,
|
|
713
|
+
test2,
|
|
714
|
+
FAKE_USE_RANDOM_DELAY,
|
|
715
|
+
{},
|
|
716
|
+
correlationId,
|
|
717
|
+
true,
|
|
718
|
+
callStateForMetrics
|
|
719
|
+
);
|
|
720
|
+
assert.calledOnceWithExactly(fakeMeeting.setCallStateForMetrics, {
|
|
721
|
+
...callStateForMetrics,
|
|
722
|
+
correlationId,
|
|
723
|
+
});
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
const checkCallCreateMeeting = async (createParameters, createMeetingParameters) => {
|
|
727
|
+
const create = webex.meetings.create(...createParameters);
|
|
728
|
+
|
|
729
|
+
assert.exists(create.then);
|
|
730
|
+
await create;
|
|
731
|
+
assert.calledOnce(webex.meetings.createMeeting);
|
|
732
|
+
assert.calledWith(webex.meetings.createMeeting, ...createMeetingParameters);
|
|
733
|
+
};
|
|
734
|
+
|
|
577
735
|
it('calls createMeeting and returns its promise', async () => {
|
|
578
|
-
|
|
579
|
-
|
|
736
|
+
await checkCallCreateMeeting(
|
|
737
|
+
[test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, true],
|
|
738
|
+
[test1, test2, FAKE_USE_RANDOM_DELAY, {}, {correlationId}, true]
|
|
739
|
+
);
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
it('calls createMeeting, pass the meeting info param and returns its promise', async () => {
|
|
743
|
+
const meetingInfo = {};
|
|
744
|
+
await checkCallCreateMeeting(
|
|
745
|
+
[test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, true, undefined, meetingInfo],
|
|
746
|
+
[test1, test2, FAKE_USE_RANDOM_DELAY, {}, {correlationId}, true, meetingInfo]
|
|
747
|
+
);
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
it('calls createMeeting, pass the meeting info and meetingLookupURL param and returns its promise', async () => {
|
|
751
|
+
const meetingInfo = {};
|
|
752
|
+
await checkCallCreateMeeting(
|
|
753
|
+
[
|
|
754
|
+
test1,
|
|
755
|
+
test2,
|
|
756
|
+
FAKE_USE_RANDOM_DELAY,
|
|
757
|
+
{},
|
|
758
|
+
correlationId,
|
|
759
|
+
true,
|
|
760
|
+
undefined,
|
|
761
|
+
meetingInfo,
|
|
762
|
+
'meetingLookupURL',
|
|
763
|
+
],
|
|
764
|
+
[
|
|
765
|
+
test1,
|
|
766
|
+
test2,
|
|
767
|
+
FAKE_USE_RANDOM_DELAY,
|
|
768
|
+
{},
|
|
769
|
+
{correlationId},
|
|
770
|
+
true,
|
|
771
|
+
meetingInfo,
|
|
772
|
+
'meetingLookupURL',
|
|
773
|
+
]
|
|
774
|
+
);
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
it('calls createMeeting when failOnMissingMeetinginfo is undefined and returns its promise', async () => {
|
|
778
|
+
await checkCallCreateMeeting(
|
|
779
|
+
[test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, undefined],
|
|
780
|
+
[test1, test2, FAKE_USE_RANDOM_DELAY, {}, {correlationId}, false]
|
|
781
|
+
);
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
it('calls createMeeting when failOnMissingMeetinginfo is false and returns its promise', async () => {
|
|
785
|
+
await checkCallCreateMeeting(
|
|
786
|
+
[test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, false],
|
|
787
|
+
[test1, test2, FAKE_USE_RANDOM_DELAY, {}, {correlationId}, false]
|
|
788
|
+
);
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
it('calls createMeeting with callStateForMetrics and returns its promise', async () => {
|
|
792
|
+
await checkCallCreateMeeting(
|
|
793
|
+
[test1, test2, FAKE_USE_RANDOM_DELAY, {}, undefined, true, callStateForMetrics],
|
|
794
|
+
[test1, test2, FAKE_USE_RANDOM_DELAY, {}, callStateForMetrics, true]
|
|
795
|
+
);
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
it('calls createMeeting with callStateForMetrics overwritten with correlationId and returns its promise', async () => {
|
|
799
|
+
await checkCallCreateMeeting(
|
|
800
|
+
[test1, test2, FAKE_USE_RANDOM_DELAY, {}, correlationId, true, callStateForMetrics],
|
|
801
|
+
[test1, test2, FAKE_USE_RANDOM_DELAY, {}, {...callStateForMetrics, correlationId}, true]
|
|
802
|
+
);
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
it('calls createMeeting with extra info params and returns its promise', async () => {
|
|
806
|
+
const FAKE_USE_RANDOM_DELAY = false;
|
|
807
|
+
const correlationId = 'my-correlationId';
|
|
808
|
+
|
|
809
|
+
const FAKE_INFO_EXTRA_PARAMS = {
|
|
810
|
+
mtid: 'm9fe0afd8c435e892afcce9ea25b97046',
|
|
811
|
+
joinTXId: 'TSmrX61wNF',
|
|
812
|
+
};
|
|
813
|
+
const create = webex.meetings.create(
|
|
814
|
+
test1,
|
|
815
|
+
test2,
|
|
816
|
+
FAKE_USE_RANDOM_DELAY,
|
|
817
|
+
FAKE_INFO_EXTRA_PARAMS,
|
|
818
|
+
correlationId
|
|
819
|
+
);
|
|
580
820
|
|
|
581
821
|
assert.exists(create.then);
|
|
582
822
|
await create;
|
|
583
823
|
assert.calledOnce(webex.meetings.createMeeting);
|
|
584
|
-
assert.calledWith(
|
|
824
|
+
assert.calledWith(
|
|
825
|
+
webex.meetings.createMeeting,
|
|
826
|
+
test1,
|
|
827
|
+
test2,
|
|
828
|
+
FAKE_USE_RANDOM_DELAY,
|
|
829
|
+
FAKE_INFO_EXTRA_PARAMS,
|
|
830
|
+
{correlationId},
|
|
831
|
+
false
|
|
832
|
+
);
|
|
585
833
|
});
|
|
586
834
|
|
|
587
835
|
it('creates a new meeting when a scheduled meeting exists in the conversation', async () => {
|
|
@@ -677,45 +925,51 @@ describe('plugin-meetings', () => {
|
|
|
677
925
|
});
|
|
678
926
|
describe('#handleLocusEvent', () => {
|
|
679
927
|
describe('there was a meeting', () => {
|
|
680
|
-
let parse;
|
|
681
|
-
|
|
682
928
|
beforeEach(() => {
|
|
683
|
-
parse = sinon.stub().returns(true);
|
|
684
929
|
webex.meetings.meetingCollection.getByKey = sinon.stub().returns({
|
|
685
|
-
locusInfo
|
|
686
|
-
parse,
|
|
687
|
-
},
|
|
930
|
+
locusInfo,
|
|
688
931
|
});
|
|
689
932
|
});
|
|
690
|
-
it('should parse the meeting info', () => {
|
|
933
|
+
it('should parse the meeting info and update main session locus cache', () => {
|
|
934
|
+
sinon.stub(MeetingsUtil, 'isBreakoutLocusDTO').returns(false);
|
|
691
935
|
webex.meetings.handleLocusEvent({
|
|
692
936
|
locusUrl: url1,
|
|
693
937
|
});
|
|
694
938
|
assert.calledOnce(webex.meetings.meetingCollection.getByKey);
|
|
695
939
|
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
|
|
696
|
-
assert.calledOnce(parse);
|
|
940
|
+
assert.calledOnce(locusInfo.parse);
|
|
941
|
+
assert.calledOnce(locusInfo.updateMainSessionLocusCache);
|
|
697
942
|
assert.calledWith(
|
|
698
|
-
parse,
|
|
943
|
+
locusInfo.parse,
|
|
699
944
|
{
|
|
700
|
-
locusInfo
|
|
701
|
-
parse,
|
|
702
|
-
},
|
|
945
|
+
locusInfo,
|
|
703
946
|
},
|
|
704
947
|
{
|
|
705
948
|
locusUrl: url1,
|
|
706
949
|
}
|
|
707
950
|
);
|
|
708
951
|
});
|
|
952
|
+
|
|
953
|
+
it('should not update main session locus cache', () => {
|
|
954
|
+
sinon.stub(MeetingsUtil, 'isBreakoutLocusDTO').returns(true);
|
|
955
|
+
webex.meetings.handleLocusEvent({
|
|
956
|
+
locusUrl: url1,
|
|
957
|
+
});
|
|
958
|
+
assert.notCalled(locusInfo.updateMainSessionLocusCache);
|
|
959
|
+
});
|
|
709
960
|
});
|
|
710
961
|
describe('there was not a meeting', () => {
|
|
711
962
|
let initialSetup;
|
|
963
|
+
const webExMeetingId = '123456';
|
|
712
964
|
|
|
713
965
|
beforeEach(() => {
|
|
714
966
|
initialSetup = sinon.stub().returns(true);
|
|
715
967
|
webex.meetings.meetingCollection.getByKey = sinon.stub().returns(undefined);
|
|
716
968
|
webex.meetings.create = sinon.stub().returns(
|
|
717
969
|
Promise.resolve({
|
|
970
|
+
id: 'meeting-id',
|
|
718
971
|
locusInfo: {
|
|
972
|
+
...locusInfo,
|
|
719
973
|
initialSetup,
|
|
720
974
|
},
|
|
721
975
|
})
|
|
@@ -735,12 +989,20 @@ describe('plugin-meetings', () => {
|
|
|
735
989
|
callbackAddress: uri1,
|
|
736
990
|
},
|
|
737
991
|
},
|
|
992
|
+
info: {
|
|
993
|
+
webExMeetingId,
|
|
994
|
+
},
|
|
738
995
|
},
|
|
739
996
|
eventType: 'locus.difference',
|
|
740
997
|
locusUrl: url1,
|
|
741
998
|
});
|
|
742
|
-
assert.callCount(webex.meetings.meetingCollection.getByKey,
|
|
999
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 6);
|
|
743
1000
|
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
|
|
1001
|
+
assert.calledWith(
|
|
1002
|
+
webex.meetings.meetingCollection.getByKey,
|
|
1003
|
+
'meetingNumber',
|
|
1004
|
+
webExMeetingId
|
|
1005
|
+
);
|
|
744
1006
|
assert.calledOnce(initialSetup);
|
|
745
1007
|
assert.calledWith(initialSetup, {
|
|
746
1008
|
id: uuid1,
|
|
@@ -754,6 +1016,9 @@ describe('plugin-meetings', () => {
|
|
|
754
1016
|
callbackAddress: uri1,
|
|
755
1017
|
},
|
|
756
1018
|
},
|
|
1019
|
+
info: {
|
|
1020
|
+
webExMeetingId,
|
|
1021
|
+
},
|
|
757
1022
|
});
|
|
758
1023
|
});
|
|
759
1024
|
it('should setup the meeting by difference event without replaces', async () => {
|
|
@@ -765,12 +1030,20 @@ describe('plugin-meetings', () => {
|
|
|
765
1030
|
callbackAddress: uri1,
|
|
766
1031
|
},
|
|
767
1032
|
},
|
|
1033
|
+
info: {
|
|
1034
|
+
webExMeetingId,
|
|
1035
|
+
},
|
|
768
1036
|
},
|
|
769
1037
|
eventType: 'locus.difference',
|
|
770
1038
|
locusUrl: url1,
|
|
771
1039
|
});
|
|
772
|
-
assert.callCount(webex.meetings.meetingCollection.getByKey,
|
|
1040
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
|
|
773
1041
|
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
|
|
1042
|
+
assert.calledWith(
|
|
1043
|
+
webex.meetings.meetingCollection.getByKey,
|
|
1044
|
+
'meetingNumber',
|
|
1045
|
+
webExMeetingId
|
|
1046
|
+
);
|
|
774
1047
|
assert.calledOnce(initialSetup);
|
|
775
1048
|
assert.calledWith(initialSetup, {
|
|
776
1049
|
id: uuid1,
|
|
@@ -779,8 +1052,44 @@ describe('plugin-meetings', () => {
|
|
|
779
1052
|
callbackAddress: uri1,
|
|
780
1053
|
},
|
|
781
1054
|
},
|
|
1055
|
+
info: {
|
|
1056
|
+
webExMeetingId,
|
|
1057
|
+
},
|
|
1058
|
+
});
|
|
1059
|
+
});
|
|
1060
|
+
|
|
1061
|
+
it('sends client event correctly on finally', async () => {
|
|
1062
|
+
webex.meetings.getMeetingByType = sinon.stub().returns(true);
|
|
1063
|
+
|
|
1064
|
+
await webex.meetings.handleLocusEvent({
|
|
1065
|
+
locus: {
|
|
1066
|
+
id: uuid1,
|
|
1067
|
+
self: {
|
|
1068
|
+
callBackInfo: {
|
|
1069
|
+
callbackAddress: uri1,
|
|
1070
|
+
},
|
|
1071
|
+
},
|
|
1072
|
+
info: {
|
|
1073
|
+
webExMeetingId,
|
|
1074
|
+
},
|
|
1075
|
+
},
|
|
1076
|
+
eventType: 'locus.difference',
|
|
1077
|
+
locusUrl: url1,
|
|
1078
|
+
});
|
|
1079
|
+
|
|
1080
|
+
await testUtils.flushPromises();
|
|
1081
|
+
|
|
1082
|
+
assert.calledWith(webex.internal.newMetrics.submitClientEvent, {
|
|
1083
|
+
name: 'client.call.remote-started',
|
|
1084
|
+
payload: {
|
|
1085
|
+
trigger: 'mercury-event',
|
|
1086
|
+
},
|
|
1087
|
+
options: {
|
|
1088
|
+
meetingId: 'meeting-id',
|
|
1089
|
+
},
|
|
782
1090
|
});
|
|
783
1091
|
});
|
|
1092
|
+
|
|
784
1093
|
it('should setup the meeting by a not difference event', async () => {
|
|
785
1094
|
await webex.meetings.handleLocusEvent({
|
|
786
1095
|
locus: {
|
|
@@ -790,12 +1099,20 @@ describe('plugin-meetings', () => {
|
|
|
790
1099
|
callbackAddress: uri1,
|
|
791
1100
|
},
|
|
792
1101
|
},
|
|
1102
|
+
info: {
|
|
1103
|
+
webExMeetingId,
|
|
1104
|
+
},
|
|
793
1105
|
},
|
|
794
1106
|
eventType: test1,
|
|
795
1107
|
locusUrl: url1,
|
|
796
1108
|
});
|
|
797
|
-
assert.callCount(webex.meetings.meetingCollection.getByKey,
|
|
1109
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
|
|
798
1110
|
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
|
|
1111
|
+
assert.calledWith(
|
|
1112
|
+
webex.meetings.meetingCollection.getByKey,
|
|
1113
|
+
'meetingNumber',
|
|
1114
|
+
webExMeetingId
|
|
1115
|
+
);
|
|
799
1116
|
assert.calledOnce(initialSetup);
|
|
800
1117
|
assert.calledWith(initialSetup, {
|
|
801
1118
|
id: uuid1,
|
|
@@ -804,6 +1121,9 @@ describe('plugin-meetings', () => {
|
|
|
804
1121
|
callbackAddress: uri1,
|
|
805
1122
|
},
|
|
806
1123
|
},
|
|
1124
|
+
info: {
|
|
1125
|
+
webExMeetingId,
|
|
1126
|
+
},
|
|
807
1127
|
});
|
|
808
1128
|
});
|
|
809
1129
|
|
|
@@ -826,7 +1146,7 @@ describe('plugin-meetings', () => {
|
|
|
826
1146
|
|
|
827
1147
|
it('should not try to match USM meetings by conversation url', async () => {
|
|
828
1148
|
await webex.meetings.handleLocusEvent(generateFakeLocusData(true));
|
|
829
|
-
assert.callCount(webex.meetings.meetingCollection.getByKey,
|
|
1149
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
|
|
830
1150
|
assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, [
|
|
831
1151
|
'locusUrl',
|
|
832
1152
|
url1,
|
|
@@ -843,7 +1163,7 @@ describe('plugin-meetings', () => {
|
|
|
843
1163
|
});
|
|
844
1164
|
it('should try to match non-USM meetings by conversation url', async () => {
|
|
845
1165
|
await webex.meetings.handleLocusEvent(generateFakeLocusData(false));
|
|
846
|
-
assert.callCount(webex.meetings.meetingCollection.getByKey,
|
|
1166
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
|
|
847
1167
|
assert.deepEqual(webex.meetings.meetingCollection.getByKey.getCall(0).args, [
|
|
848
1168
|
'locusUrl',
|
|
849
1169
|
url1,
|
|
@@ -874,6 +1194,10 @@ describe('plugin-meetings', () => {
|
|
|
874
1194
|
});
|
|
875
1195
|
describe('successful MeetingInfo.#fetchMeetingInfo', () => {
|
|
876
1196
|
let clock, setTimeoutSpy, fakeMeetingStartTimeString, FAKE_TIME_TO_START;
|
|
1197
|
+
const FAKE_INFO_EXTRA_PARAMS = {
|
|
1198
|
+
mtid: 'm9fe0afd8c435e892afcce9ea25b97046',
|
|
1199
|
+
joinTXId: 'TSmrX61wNF',
|
|
1200
|
+
};
|
|
877
1201
|
|
|
878
1202
|
beforeEach(() => {
|
|
879
1203
|
clock = sinon.useFakeTimers();
|
|
@@ -903,13 +1227,37 @@ describe('plugin-meetings', () => {
|
|
|
903
1227
|
meeting,
|
|
904
1228
|
destination,
|
|
905
1229
|
type,
|
|
906
|
-
|
|
1230
|
+
extraParams = {},
|
|
1231
|
+
expectedMeetingData = {},
|
|
1232
|
+
sendCAevents = false,
|
|
1233
|
+
injectMeetingInfo = false
|
|
907
1234
|
) => {
|
|
908
|
-
|
|
1235
|
+
if (injectMeetingInfo) {
|
|
1236
|
+
assert.notCalled(webex.meetings.meetingInfo.fetchMeetingInfo);
|
|
1237
|
+
} else {
|
|
1238
|
+
assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
|
|
1239
|
+
}
|
|
1240
|
+
|
|
909
1241
|
assert.calledOnce(MeetingsUtil.getMeetingAddedType);
|
|
910
1242
|
assert.notCalled(setTimeoutSpy);
|
|
911
|
-
assert.
|
|
912
|
-
|
|
1243
|
+
assert.callCount(TriggerProxy.trigger, 5);
|
|
1244
|
+
|
|
1245
|
+
if (injectMeetingInfo) {
|
|
1246
|
+
assert.notCalled(webex.meetings.meetingInfo.fetchMeetingInfo);
|
|
1247
|
+
} else {
|
|
1248
|
+
assert.calledWith(
|
|
1249
|
+
webex.meetings.meetingInfo.fetchMeetingInfo,
|
|
1250
|
+
destination,
|
|
1251
|
+
type,
|
|
1252
|
+
null,
|
|
1253
|
+
null,
|
|
1254
|
+
undefined,
|
|
1255
|
+
undefined,
|
|
1256
|
+
extraParams,
|
|
1257
|
+
{meetingId: meeting.id, sendCAevents}
|
|
1258
|
+
);
|
|
1259
|
+
}
|
|
1260
|
+
|
|
913
1261
|
assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
|
|
914
1262
|
|
|
915
1263
|
if (expectedMeetingData.permissionToken) {
|
|
@@ -918,6 +1266,21 @@ describe('plugin-meetings', () => {
|
|
|
918
1266
|
if (expectedMeetingData.meetingJoinUrl) {
|
|
919
1267
|
assert.equal(meeting.meetingJoinUrl, expectedMeetingData.meetingJoinUrl);
|
|
920
1268
|
}
|
|
1269
|
+
if (expectedMeetingData.correlationId) {
|
|
1270
|
+
assert.equal(meeting.correlationId, expectedMeetingData.correlationId);
|
|
1271
|
+
}
|
|
1272
|
+
if (expectedMeetingData.callStateForMetrics) {
|
|
1273
|
+
assert.deepEqual(
|
|
1274
|
+
meeting.callStateForMetrics,
|
|
1275
|
+
expectedMeetingData.callStateForMetrics
|
|
1276
|
+
);
|
|
1277
|
+
}
|
|
1278
|
+
if (expectedMeetingData.meetingLookupUrl) {
|
|
1279
|
+
assert.equal(
|
|
1280
|
+
meeting.meetingInfo.meetingLookupUrl,
|
|
1281
|
+
expectedMeetingData.meetingLookupUrl
|
|
1282
|
+
);
|
|
1283
|
+
}
|
|
921
1284
|
assert.equal(meeting.destination, destination);
|
|
922
1285
|
assert.equal(meeting.destinationType, type);
|
|
923
1286
|
assert.calledWith(
|
|
@@ -947,107 +1310,207 @@ describe('plugin-meetings', () => {
|
|
|
947
1310
|
const expectedMeetingData = {
|
|
948
1311
|
permissionToken: 'PT',
|
|
949
1312
|
meetingJoinUrl: 'meetingJoinUrl',
|
|
1313
|
+
correlationId: meeting.id,
|
|
950
1314
|
};
|
|
951
1315
|
|
|
952
|
-
checkCreateWithoutDelay(
|
|
1316
|
+
checkCreateWithoutDelay(
|
|
1317
|
+
meeting,
|
|
1318
|
+
'test destination',
|
|
1319
|
+
'test type',
|
|
1320
|
+
{},
|
|
1321
|
+
expectedMeetingData
|
|
1322
|
+
);
|
|
953
1323
|
});
|
|
954
1324
|
|
|
955
|
-
it('
|
|
956
|
-
const
|
|
957
|
-
const expectedMeetingData = {
|
|
1325
|
+
it('accepts injected meeting info', async () => {
|
|
1326
|
+
const meetingInfo = {
|
|
958
1327
|
permissionToken: 'PT',
|
|
959
1328
|
meetingJoinUrl: 'meetingJoinUrl',
|
|
960
1329
|
};
|
|
961
1330
|
|
|
962
|
-
|
|
1331
|
+
const meeting = await webex.meetings.createMeeting(
|
|
1332
|
+
'test destination',
|
|
1333
|
+
'test type',
|
|
1334
|
+
false,
|
|
1335
|
+
{},
|
|
1336
|
+
undefined,
|
|
1337
|
+
false,
|
|
1338
|
+
meetingInfo
|
|
1339
|
+
);
|
|
1340
|
+
|
|
1341
|
+
const expectedMeetingData = {
|
|
1342
|
+
...meetingInfo,
|
|
1343
|
+
correlationId: meeting.id,
|
|
1344
|
+
};
|
|
1345
|
+
|
|
1346
|
+
checkCreateWithoutDelay(
|
|
963
1347
|
meeting,
|
|
964
|
-
|
|
965
|
-
'
|
|
1348
|
+
'test destination',
|
|
1349
|
+
'test type',
|
|
1350
|
+
{},
|
|
1351
|
+
expectedMeetingData,
|
|
1352
|
+
false,
|
|
1353
|
+
true
|
|
966
1354
|
);
|
|
967
|
-
checkCreateWithoutDelay(meeting, 'test destination', 'test type', expectedMeetingData);
|
|
968
1355
|
});
|
|
969
1356
|
|
|
970
|
-
it('
|
|
971
|
-
const
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
info: {
|
|
975
|
-
webExMeetingId: 'locusMeetingId',
|
|
976
|
-
sipUri: 'locusSipUri',
|
|
977
|
-
owner: 'locusOwner',
|
|
978
|
-
},
|
|
979
|
-
meeting: {
|
|
980
|
-
startTime: fakeMeetingStartTimeString,
|
|
981
|
-
},
|
|
982
|
-
fullState: {
|
|
983
|
-
active: false,
|
|
984
|
-
},
|
|
1357
|
+
it('accepts injected meeting info with meeting lookup url', async () => {
|
|
1358
|
+
const meetingInfo = {
|
|
1359
|
+
permissionToken: 'PT',
|
|
1360
|
+
meetingJoinUrl: 'meetingJoinUrl',
|
|
985
1361
|
};
|
|
986
1362
|
|
|
987
1363
|
const meeting = await webex.meetings.createMeeting(
|
|
988
|
-
|
|
1364
|
+
'test destination',
|
|
989
1365
|
'test type',
|
|
990
|
-
|
|
1366
|
+
false,
|
|
1367
|
+
{},
|
|
1368
|
+
undefined,
|
|
1369
|
+
false,
|
|
1370
|
+
meetingInfo,
|
|
1371
|
+
'meetingLookupUrl'
|
|
991
1372
|
);
|
|
992
1373
|
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
assert.notCalled(webex.meetings.meetingInfo.fetchMeetingInfo);
|
|
999
|
-
assert.calledOnce(setTimeoutSpy);
|
|
1000
|
-
|
|
1001
|
-
// Parse meeting info with locus object
|
|
1002
|
-
assert.equal(meeting.conversationUrl, 'locusConvURL');
|
|
1003
|
-
assert.equal(meeting.locusUrl, 'locusUrl');
|
|
1004
|
-
assert.equal(meeting.sipUri, 'locusSipUri');
|
|
1005
|
-
assert.equal(meeting.meetingNumber, 'locusMeetingId');
|
|
1006
|
-
assert.isUndefined(meeting.meetingJoinUrl);
|
|
1007
|
-
assert.equal(meeting.owner, 'locusOwner');
|
|
1008
|
-
assert.isUndefined(meeting.permissionToken);
|
|
1009
|
-
|
|
1010
|
-
// Add meeting and send trigger
|
|
1011
|
-
assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
|
|
1012
|
-
assert.calledTwice(TriggerProxy.trigger);
|
|
1013
|
-
assert.calledWith(
|
|
1014
|
-
TriggerProxy.trigger,
|
|
1015
|
-
sinon.match.instanceOf(Meetings),
|
|
1016
|
-
{
|
|
1017
|
-
file: 'meetings',
|
|
1018
|
-
function: 'createMeeting',
|
|
1019
|
-
},
|
|
1020
|
-
'meeting:added',
|
|
1021
|
-
{
|
|
1022
|
-
meeting: sinon.match.instanceOf(Meeting),
|
|
1023
|
-
type: 'test meeting added type',
|
|
1024
|
-
}
|
|
1025
|
-
);
|
|
1374
|
+
const expectedMeetingData = {
|
|
1375
|
+
...meetingInfo,
|
|
1376
|
+
meetingLookupUrl: 'meetingLookupUrl',
|
|
1377
|
+
correlationId: meeting.id,
|
|
1378
|
+
};
|
|
1026
1379
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1380
|
+
checkCreateWithoutDelay(
|
|
1381
|
+
meeting,
|
|
1382
|
+
'test destination',
|
|
1383
|
+
'test type',
|
|
1384
|
+
{},
|
|
1385
|
+
expectedMeetingData,
|
|
1386
|
+
false,
|
|
1387
|
+
true
|
|
1033
1388
|
);
|
|
1389
|
+
});
|
|
1034
1390
|
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1391
|
+
[undefined, FAKE_INFO_EXTRA_PARAMS].forEach((infoExtraParams) => {
|
|
1392
|
+
const infoExtraParamsProvided = infoExtraParams !== undefined;
|
|
1393
|
+
|
|
1394
|
+
it(`creates the meeting from a successful meeting info fetch meeting resolve testing${
|
|
1395
|
+
infoExtraParamsProvided ? ' with infoExtraParams' : ''
|
|
1396
|
+
}`, async () => {
|
|
1397
|
+
const meeting = await webex.meetings.createMeeting(
|
|
1398
|
+
'test destination',
|
|
1399
|
+
'test type',
|
|
1400
|
+
false,
|
|
1401
|
+
infoExtraParams
|
|
1402
|
+
);
|
|
1403
|
+
const expectedMeetingData = {
|
|
1404
|
+
permissionToken: 'PT',
|
|
1405
|
+
meetingJoinUrl: 'meetingJoinUrl',
|
|
1406
|
+
};
|
|
1407
|
+
|
|
1408
|
+
assert.instanceOf(
|
|
1409
|
+
meeting,
|
|
1410
|
+
Meeting,
|
|
1411
|
+
'createMeeting should eventually resolve to a Meeting Object'
|
|
1412
|
+
);
|
|
1413
|
+
checkCreateWithoutDelay(
|
|
1414
|
+
meeting,
|
|
1415
|
+
'test destination',
|
|
1416
|
+
'test type',
|
|
1417
|
+
infoExtraParamsProvided ? infoExtraParams : {},
|
|
1418
|
+
expectedMeetingData
|
|
1419
|
+
);
|
|
1420
|
+
});
|
|
1044
1421
|
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1422
|
+
it(`creates the meeting from a successful meeting info fetch with random delay${
|
|
1423
|
+
infoExtraParamsProvided ? ' with infoExtraParams' : ''
|
|
1424
|
+
}`, async () => {
|
|
1425
|
+
const FAKE_LOCUS_MEETING = {
|
|
1426
|
+
conversationUrl: 'locusConvURL',
|
|
1427
|
+
url: 'locusUrl',
|
|
1428
|
+
info: {
|
|
1429
|
+
webExMeetingId: 'locusMeetingId',
|
|
1430
|
+
sipUri: 'locusSipUri',
|
|
1431
|
+
owner: 'locusOwner',
|
|
1432
|
+
},
|
|
1433
|
+
meeting: {
|
|
1434
|
+
startTime: fakeMeetingStartTimeString,
|
|
1435
|
+
},
|
|
1436
|
+
fullState: {
|
|
1437
|
+
active: false,
|
|
1438
|
+
},
|
|
1439
|
+
};
|
|
1440
|
+
|
|
1441
|
+
const meeting = await webex.meetings.createMeeting(
|
|
1442
|
+
FAKE_LOCUS_MEETING,
|
|
1443
|
+
'test type',
|
|
1444
|
+
true,
|
|
1445
|
+
infoExtraParams
|
|
1446
|
+
);
|
|
1447
|
+
|
|
1448
|
+
assert.instanceOf(
|
|
1449
|
+
meeting,
|
|
1450
|
+
Meeting,
|
|
1451
|
+
'createMeeting should eventually resolve to a Meeting Object'
|
|
1452
|
+
);
|
|
1453
|
+
assert.notCalled(webex.meetings.meetingInfo.fetchMeetingInfo);
|
|
1454
|
+
assert.calledOnce(setTimeoutSpy);
|
|
1455
|
+
|
|
1456
|
+
// Parse meeting info with locus object
|
|
1457
|
+
assert.equal(meeting.conversationUrl, 'locusConvURL');
|
|
1458
|
+
assert.equal(meeting.locusUrl, 'locusUrl');
|
|
1459
|
+
assert.equal(meeting.sipUri, 'locusSipUri');
|
|
1460
|
+
assert.equal(meeting.meetingNumber, 'locusMeetingId');
|
|
1461
|
+
assert.isUndefined(meeting.meetingJoinUrl);
|
|
1462
|
+
assert.equal(meeting.owner, 'locusOwner');
|
|
1463
|
+
assert.isUndefined(meeting.permissionToken);
|
|
1464
|
+
|
|
1465
|
+
// Add meeting and send trigger
|
|
1466
|
+
assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
|
|
1467
|
+
assert.calledTwice(TriggerProxy.trigger);
|
|
1468
|
+
assert.calledWith(
|
|
1469
|
+
TriggerProxy.trigger,
|
|
1470
|
+
sinon.match.instanceOf(Meetings),
|
|
1471
|
+
{
|
|
1472
|
+
file: 'meetings',
|
|
1473
|
+
function: 'createMeeting',
|
|
1474
|
+
},
|
|
1475
|
+
'meeting:added',
|
|
1476
|
+
{
|
|
1477
|
+
meeting: sinon.match.instanceOf(Meeting),
|
|
1478
|
+
type: 'test meeting added type',
|
|
1479
|
+
}
|
|
1480
|
+
);
|
|
1481
|
+
|
|
1482
|
+
// When timer expires
|
|
1483
|
+
clock.tick(FAKE_TIME_TO_START);
|
|
1484
|
+
await testUtils.flushPromises();
|
|
1485
|
+
|
|
1486
|
+
assert.calledWith(
|
|
1487
|
+
webex.meetings.meetingInfo.fetchMeetingInfo,
|
|
1488
|
+
FAKE_LOCUS_MEETING,
|
|
1489
|
+
'test type',
|
|
1490
|
+
null,
|
|
1491
|
+
null,
|
|
1492
|
+
undefined,
|
|
1493
|
+
undefined,
|
|
1494
|
+
infoExtraParamsProvided ? infoExtraParams : {}
|
|
1495
|
+
);
|
|
1496
|
+
|
|
1497
|
+
// Parse meeting info is called again with new meeting info
|
|
1498
|
+
await testUtils.flushPromises();
|
|
1499
|
+
assert.equal(meeting.conversationUrl, 'locusConvURL');
|
|
1500
|
+
assert.equal(meeting.locusUrl, 'locusUrl');
|
|
1501
|
+
assert.equal(meeting.sipUri, 'locusSipUri');
|
|
1502
|
+
assert.equal(meeting.meetingNumber, 'locusMeetingId');
|
|
1503
|
+
assert.equal(meeting.meetingJoinUrl, 'meetingJoinUrl');
|
|
1504
|
+
assert.equal(meeting.owner, 'locusOwner');
|
|
1505
|
+
assert.equal(meeting.permissionToken, 'PT');
|
|
1506
|
+
|
|
1507
|
+
assert.calledWith(
|
|
1508
|
+
TriggerProxy.trigger,
|
|
1509
|
+
meeting,
|
|
1510
|
+
{file: 'meetings', function: 'fetchMeetingInfo'},
|
|
1511
|
+
'meeting:meetingInfoAvailable'
|
|
1512
|
+
);
|
|
1513
|
+
});
|
|
1051
1514
|
});
|
|
1052
1515
|
|
|
1053
1516
|
it('creates the meeting from a successful meeting info fetch that has no random delay because it is active', async () => {
|
|
@@ -1147,6 +1610,61 @@ describe('plugin-meetings', () => {
|
|
|
1147
1610
|
);
|
|
1148
1611
|
checkCreateWithoutDelay(meeting, FAKE_LOCUS_MEETING, 'test type');
|
|
1149
1612
|
});
|
|
1613
|
+
|
|
1614
|
+
it('creates meeting with the correlationId provided', async () => {
|
|
1615
|
+
const meeting = await webex.meetings.createMeeting(
|
|
1616
|
+
'test destination',
|
|
1617
|
+
'test type',
|
|
1618
|
+
false,
|
|
1619
|
+
{},
|
|
1620
|
+
{correlationId: 'my-correlationId'}
|
|
1621
|
+
);
|
|
1622
|
+
|
|
1623
|
+
const expectedMeetingData = {
|
|
1624
|
+
correlationId: 'my-correlationId',
|
|
1625
|
+
};
|
|
1626
|
+
|
|
1627
|
+
checkCreateWithoutDelay(
|
|
1628
|
+
meeting,
|
|
1629
|
+
'test destination',
|
|
1630
|
+
'test type',
|
|
1631
|
+
{},
|
|
1632
|
+
expectedMeetingData,
|
|
1633
|
+
true
|
|
1634
|
+
);
|
|
1635
|
+
});
|
|
1636
|
+
|
|
1637
|
+
it('creates meeting with the callStateForMetrics provided', async () => {
|
|
1638
|
+
const meeting = await webex.meetings.createMeeting(
|
|
1639
|
+
'test destination',
|
|
1640
|
+
'test type',
|
|
1641
|
+
false,
|
|
1642
|
+
{},
|
|
1643
|
+
{
|
|
1644
|
+
correlationId: 'my-correlationId',
|
|
1645
|
+
joinTrigger: 'my-join-trigger',
|
|
1646
|
+
loginType: 'my-login-type',
|
|
1647
|
+
}
|
|
1648
|
+
);
|
|
1649
|
+
|
|
1650
|
+
const expectedMeetingData = {
|
|
1651
|
+
correlationId: 'my-correlationId',
|
|
1652
|
+
callStateForMetrics: {
|
|
1653
|
+
correlationId: 'my-correlationId',
|
|
1654
|
+
joinTrigger: 'my-join-trigger',
|
|
1655
|
+
loginType: 'my-login-type',
|
|
1656
|
+
},
|
|
1657
|
+
};
|
|
1658
|
+
|
|
1659
|
+
checkCreateWithoutDelay(
|
|
1660
|
+
meeting,
|
|
1661
|
+
'test destination',
|
|
1662
|
+
'test type',
|
|
1663
|
+
{},
|
|
1664
|
+
expectedMeetingData,
|
|
1665
|
+
true
|
|
1666
|
+
);
|
|
1667
|
+
});
|
|
1150
1668
|
});
|
|
1151
1669
|
|
|
1152
1670
|
describe('rejected MeetingInfo.#fetchMeetingInfo', () => {
|
|
@@ -1156,38 +1674,130 @@ describe('plugin-meetings', () => {
|
|
|
1156
1674
|
webex.meetings.meetingInfo.fetchMeetingInfo = sinon
|
|
1157
1675
|
.stub()
|
|
1158
1676
|
.returns(Promise.reject(new Error('test')));
|
|
1677
|
+
webex.meetings.destroy = sinon.stub().returns(Promise.resolve());
|
|
1678
|
+
webex.meetings.createMeeting = sinon.spy(webex.meetings.createMeeting);
|
|
1159
1679
|
});
|
|
1680
|
+
|
|
1681
|
+
const checkCreateMeetingWithNoMeetingInfo = async (failOnMissingMeetingInfo, destroy) => {
|
|
1682
|
+
try {
|
|
1683
|
+
const meeting = await webex.meetings.createMeeting(
|
|
1684
|
+
'test destination',
|
|
1685
|
+
'test type',
|
|
1686
|
+
undefined,
|
|
1687
|
+
undefined,
|
|
1688
|
+
undefined,
|
|
1689
|
+
failOnMissingMeetingInfo
|
|
1690
|
+
);
|
|
1691
|
+
|
|
1692
|
+
assert.instanceOf(
|
|
1693
|
+
meeting,
|
|
1694
|
+
Meeting,
|
|
1695
|
+
'createMeeting should eventually resolve to a Meeting Object'
|
|
1696
|
+
);
|
|
1697
|
+
assert.calledOnce(webex.meetings.meetingInfo.fetchMeetingInfo);
|
|
1698
|
+
assert.calledOnce(MeetingsUtil.getMeetingAddedType);
|
|
1699
|
+
assert.calledThrice(TriggerProxy.trigger);
|
|
1700
|
+
assert.calledWith(
|
|
1701
|
+
webex.meetings.meetingInfo.fetchMeetingInfo,
|
|
1702
|
+
'test destination',
|
|
1703
|
+
'test type'
|
|
1704
|
+
);
|
|
1705
|
+
|
|
1706
|
+
if (destroy) {
|
|
1707
|
+
assert.calledWith(
|
|
1708
|
+
webex.meetings.destroy,
|
|
1709
|
+
sinon.match.instanceOf(Meeting),
|
|
1710
|
+
'MISSING_MEETING_INFO'
|
|
1711
|
+
);
|
|
1712
|
+
assert.notCalled(MeetingsUtil.getMeetingAddedType);
|
|
1713
|
+
assert.notCalled(TriggerProxy.trigger);
|
|
1714
|
+
assert.throw(webex.meetings.createMeeting, 'meeting information not found');
|
|
1715
|
+
} else {
|
|
1716
|
+
assert.notCalled(webex.meetings.destroy);
|
|
1717
|
+
assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
|
|
1718
|
+
assert.calledWith(
|
|
1719
|
+
TriggerProxy.trigger,
|
|
1720
|
+
sinon.match.instanceOf(Meetings),
|
|
1721
|
+
{
|
|
1722
|
+
file: 'meetings',
|
|
1723
|
+
function: 'createMeeting',
|
|
1724
|
+
},
|
|
1725
|
+
'meeting:added',
|
|
1726
|
+
{
|
|
1727
|
+
meeting: sinon.match.instanceOf(Meeting),
|
|
1728
|
+
type: 'test meeting added type',
|
|
1729
|
+
}
|
|
1730
|
+
);
|
|
1731
|
+
}
|
|
1732
|
+
} catch (err) {
|
|
1733
|
+
assert.instanceOf(err, NoMeetingInfoError);
|
|
1734
|
+
}
|
|
1735
|
+
};
|
|
1736
|
+
|
|
1160
1737
|
it('creates the meeting from a rejected meeting info fetch', async () => {
|
|
1161
|
-
|
|
1738
|
+
checkCreateMeetingWithNoMeetingInfo(false, false);
|
|
1739
|
+
});
|
|
1162
1740
|
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
assert.calledWith(
|
|
1172
|
-
webex.meetings.meetingInfo.fetchMeetingInfo,
|
|
1173
|
-
'test destination',
|
|
1174
|
-
'test type'
|
|
1175
|
-
);
|
|
1176
|
-
assert.calledWith(MeetingsUtil.getMeetingAddedType, 'test type');
|
|
1177
|
-
assert.calledWith(
|
|
1178
|
-
TriggerProxy.trigger,
|
|
1179
|
-
sinon.match.instanceOf(Meetings),
|
|
1741
|
+
it('creates the meeting from a rejected meeting info fetch and destroys it if failOnMissingMeetingInfo', async () => {
|
|
1742
|
+
checkCreateMeetingWithNoMeetingInfo(true, true);
|
|
1743
|
+
});
|
|
1744
|
+
});
|
|
1745
|
+
|
|
1746
|
+
describe('rejected MeetingInfo.#fetchMeetingInfo - does not log for known Error types', () => {
|
|
1747
|
+
forEach(
|
|
1748
|
+
[
|
|
1180
1749
|
{
|
|
1181
|
-
|
|
1182
|
-
|
|
1750
|
+
error: new CaptchaError(),
|
|
1751
|
+
debugLogMessage:
|
|
1752
|
+
'Meetings:index#createMeeting --> Debug CaptchaError: Captcha is required. fetching /meetingInfo for creation.',
|
|
1183
1753
|
},
|
|
1184
|
-
'meeting:added',
|
|
1185
1754
|
{
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1755
|
+
error: new PasswordError(),
|
|
1756
|
+
debugLogMessage:
|
|
1757
|
+
'Meetings:index#createMeeting --> Debug PasswordError: Password is required, please use verifyPassword() fetching /meetingInfo for creation.',
|
|
1758
|
+
},
|
|
1759
|
+
{
|
|
1760
|
+
error: new PermissionError(),
|
|
1761
|
+
debugLogMessage:
|
|
1762
|
+
'Meetings:index#createMeeting --> Debug PermissionError: Not allowed to execute the function, some properties on server, or local client state do not allow you to complete this action. fetching /meetingInfo for creation.',
|
|
1763
|
+
},
|
|
1764
|
+
{
|
|
1765
|
+
error: new Error(),
|
|
1766
|
+
infoLogMessage: true,
|
|
1767
|
+
debugLogMessage:
|
|
1768
|
+
'Meetings:index#createMeeting --> Debug Error fetching /meetingInfo for creation.',
|
|
1769
|
+
},
|
|
1770
|
+
],
|
|
1771
|
+
({error, debugLogMessage, infoLogMessage}) => {
|
|
1772
|
+
it('creates the meeting from a rejected meeting info fetch', async () => {
|
|
1773
|
+
webex.meetings.meetingInfo.fetchMeetingInfo = sinon
|
|
1774
|
+
.stub()
|
|
1775
|
+
.returns(Promise.reject(error));
|
|
1776
|
+
|
|
1777
|
+
LoggerProxy.logger.debug = sinon.stub();
|
|
1778
|
+
LoggerProxy.logger.info = sinon.stub();
|
|
1779
|
+
|
|
1780
|
+
const meeting = await webex.meetings.createMeeting('test destination', 'test type');
|
|
1781
|
+
|
|
1782
|
+
assert.instanceOf(
|
|
1783
|
+
meeting,
|
|
1784
|
+
Meeting,
|
|
1785
|
+
'createMeeting should eventually resolve to a Meeting Object'
|
|
1786
|
+
);
|
|
1787
|
+
|
|
1788
|
+
assert.calledWith(LoggerProxy.logger.debug, debugLogMessage);
|
|
1789
|
+
|
|
1790
|
+
if (infoLogMessage) {
|
|
1791
|
+
assert.calledWith(
|
|
1792
|
+
LoggerProxy.logger.info,
|
|
1793
|
+
'Meetings:index#createMeeting --> Info Unable to fetch meeting info for test destination.'
|
|
1794
|
+
);
|
|
1795
|
+
} else {
|
|
1796
|
+
assert.notCalled(LoggerProxy.logger.info);
|
|
1797
|
+
}
|
|
1798
|
+
});
|
|
1799
|
+
}
|
|
1800
|
+
);
|
|
1191
1801
|
});
|
|
1192
1802
|
});
|
|
1193
1803
|
});
|
|
@@ -1267,6 +1877,8 @@ describe('plugin-meetings', () => {
|
|
|
1267
1877
|
});
|
|
1268
1878
|
|
|
1269
1879
|
describe('#fetchUserPreferredWebexSite', () => {
|
|
1880
|
+
let loggerProxySpy;
|
|
1881
|
+
|
|
1270
1882
|
it('should call request.getMeetingPreferences to get the preferred webex site ', async () => {
|
|
1271
1883
|
assert.isDefined(webex.meetings.preferredWebexSite);
|
|
1272
1884
|
await webex.meetings.fetchUserPreferredWebexSite();
|
|
@@ -1274,7 +1886,22 @@ describe('plugin-meetings', () => {
|
|
|
1274
1886
|
assert.equal(webex.meetings.preferredWebexSite, 'go.webex.com');
|
|
1275
1887
|
});
|
|
1276
1888
|
|
|
1889
|
+
const setup = ({user} = {}) => {
|
|
1890
|
+
loggerProxySpy = sinon.spy(LoggerProxy.logger, 'error');
|
|
1891
|
+
|
|
1892
|
+
Object.assign(webex.internal, {
|
|
1893
|
+
services: {
|
|
1894
|
+
getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
|
|
1895
|
+
},
|
|
1896
|
+
user: {
|
|
1897
|
+
get: sinon.stub().returns(Promise.resolve(user)),
|
|
1898
|
+
},
|
|
1899
|
+
});
|
|
1900
|
+
};
|
|
1901
|
+
|
|
1277
1902
|
it('should not fail if UserPreferred info is not fetched ', async () => {
|
|
1903
|
+
setup();
|
|
1904
|
+
|
|
1278
1905
|
Object.assign(webex.internal, {
|
|
1279
1906
|
services: {
|
|
1280
1907
|
getMeetingPreferences: sinon.stub().returns(Promise.resolve({})),
|
|
@@ -1284,6 +1911,63 @@ describe('plugin-meetings', () => {
|
|
|
1284
1911
|
await webex.meetings.fetchUserPreferredWebexSite().then(() => {
|
|
1285
1912
|
assert.equal(webex.meetings.preferredWebexSite, '');
|
|
1286
1913
|
});
|
|
1914
|
+
assert.calledOnceWithExactly(
|
|
1915
|
+
loggerProxySpy,
|
|
1916
|
+
'Failed to fetch preferred site from user - no site will be set'
|
|
1917
|
+
);
|
|
1918
|
+
});
|
|
1919
|
+
|
|
1920
|
+
it('should fall back to fetching the site from the user', async () => {
|
|
1921
|
+
setup({
|
|
1922
|
+
user: {
|
|
1923
|
+
userPreferences: {
|
|
1924
|
+
userPreferencesItems: {
|
|
1925
|
+
preferredWebExSite: 'site.webex.com',
|
|
1926
|
+
},
|
|
1927
|
+
},
|
|
1928
|
+
},
|
|
1929
|
+
});
|
|
1930
|
+
|
|
1931
|
+
await webex.meetings.fetchUserPreferredWebexSite();
|
|
1932
|
+
|
|
1933
|
+
assert.equal(webex.meetings.preferredWebexSite, 'site.webex.com');
|
|
1934
|
+
assert.notCalled(loggerProxySpy);
|
|
1935
|
+
});
|
|
1936
|
+
|
|
1937
|
+
forEach(
|
|
1938
|
+
[
|
|
1939
|
+
{user: undefined},
|
|
1940
|
+
{user: {userPreferences: {}}},
|
|
1941
|
+
{user: {userPreferences: {userPreferencesItems: {}}}},
|
|
1942
|
+
{user: {userPreferences: {userPreferencesItems: {preferredWebExSite: undefined}}}},
|
|
1943
|
+
],
|
|
1944
|
+
({user}) => {
|
|
1945
|
+
it(`should handle invalid user data ${user}`, async () => {
|
|
1946
|
+
setup({user});
|
|
1947
|
+
|
|
1948
|
+
await webex.meetings.fetchUserPreferredWebexSite();
|
|
1949
|
+
|
|
1950
|
+
assert.equal(webex.meetings.preferredWebexSite, '');
|
|
1951
|
+
assert.calledOnceWithExactly(
|
|
1952
|
+
loggerProxySpy,
|
|
1953
|
+
'Failed to fetch preferred site from user - no site will be set'
|
|
1954
|
+
);
|
|
1955
|
+
});
|
|
1956
|
+
}
|
|
1957
|
+
);
|
|
1958
|
+
|
|
1959
|
+
it('should handle a get user failure', async () => {
|
|
1960
|
+
setup();
|
|
1961
|
+
|
|
1962
|
+
webex.internal.user.get.rejects(new Error());
|
|
1963
|
+
|
|
1964
|
+
await webex.meetings.fetchUserPreferredWebexSite();
|
|
1965
|
+
|
|
1966
|
+
assert.equal(webex.meetings.preferredWebexSite, '');
|
|
1967
|
+
assert.calledOnceWithExactly(
|
|
1968
|
+
loggerProxySpy,
|
|
1969
|
+
'Failed to fetch preferred site from user - no site will be set'
|
|
1970
|
+
);
|
|
1287
1971
|
});
|
|
1288
1972
|
});
|
|
1289
1973
|
});
|
|
@@ -1368,5 +2052,523 @@ describe('plugin-meetings', () => {
|
|
|
1368
2052
|
);
|
|
1369
2053
|
});
|
|
1370
2054
|
});
|
|
2055
|
+
|
|
2056
|
+
describe('#isNeedHandleMainLocus', () => {
|
|
2057
|
+
let meeting;
|
|
2058
|
+
let newLocus;
|
|
2059
|
+
beforeEach(() => {
|
|
2060
|
+
meeting = {
|
|
2061
|
+
controls: {},
|
|
2062
|
+
self: {},
|
|
2063
|
+
};
|
|
2064
|
+
newLocus = {
|
|
2065
|
+
controls: {},
|
|
2066
|
+
self: {},
|
|
2067
|
+
};
|
|
2068
|
+
});
|
|
2069
|
+
afterEach(() => {
|
|
2070
|
+
sinon.restore();
|
|
2071
|
+
});
|
|
2072
|
+
it('check normal case will return true', () => {
|
|
2073
|
+
sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns(null);
|
|
2074
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
2075
|
+
const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
|
|
2076
|
+
assert.equal(result, true);
|
|
2077
|
+
assert.calledWith(
|
|
2078
|
+
LoggerProxy.logger.log,
|
|
2079
|
+
'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
|
|
2080
|
+
);
|
|
2081
|
+
});
|
|
2082
|
+
|
|
2083
|
+
it('check self joined and joined on this device, return true', () => {
|
|
2084
|
+
sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns(null);
|
|
2085
|
+
newLocus.self.state = 'JOINED';
|
|
2086
|
+
sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
|
|
2087
|
+
|
|
2088
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
2089
|
+
const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
|
|
2090
|
+
assert.equal(result, true);
|
|
2091
|
+
assert.calledWith(
|
|
2092
|
+
LoggerProxy.logger.log,
|
|
2093
|
+
'Meetings:index#isNeedHandleMainLocus --> self this device shown as JOINED in the main session'
|
|
2094
|
+
);
|
|
2095
|
+
});
|
|
2096
|
+
|
|
2097
|
+
it('if newLocus replaceAt time is expired, then return false', () => {
|
|
2098
|
+
sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({
|
|
2099
|
+
joinedWith: {
|
|
2100
|
+
replaces: [
|
|
2101
|
+
{
|
|
2102
|
+
replaceAt: '2023-03-27T02:17:02.506Z',
|
|
2103
|
+
},
|
|
2104
|
+
],
|
|
2105
|
+
},
|
|
2106
|
+
});
|
|
2107
|
+
newLocus.self.state = 'JOINED';
|
|
2108
|
+
sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(true);
|
|
2109
|
+
sinon.stub(MeetingsUtil, 'getThisDevice').returns({
|
|
2110
|
+
replaces: [
|
|
2111
|
+
{
|
|
2112
|
+
replaceAt: '2023-03-27T02:17:01.506Z',
|
|
2113
|
+
},
|
|
2114
|
+
],
|
|
2115
|
+
});
|
|
2116
|
+
|
|
2117
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
2118
|
+
const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
|
|
2119
|
+
assert.equal(result, false);
|
|
2120
|
+
assert.calledWith(
|
|
2121
|
+
LoggerProxy.logger.log,
|
|
2122
|
+
`Meetings:index#isNeedHandleMainLocus --> this is expired main joined status locus_dto replacedAt 2023-03-27T02:17:01.506Z bo replacedAt 2023-03-27T02:17:02.506Z`
|
|
2123
|
+
);
|
|
2124
|
+
});
|
|
2125
|
+
|
|
2126
|
+
it('check current is in breakout join with this device, return false', () => {
|
|
2127
|
+
sinon.stub(webex.meetings.meetingCollection, 'getActiveBreakoutLocus').returns({
|
|
2128
|
+
joinedWith: {
|
|
2129
|
+
correlationId: '111',
|
|
2130
|
+
},
|
|
2131
|
+
});
|
|
2132
|
+
newLocus.controls.breakout = {url: 'url'};
|
|
2133
|
+
meeting.correlationId = '111';
|
|
2134
|
+
|
|
2135
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
2136
|
+
const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
|
|
2137
|
+
assert.equal(result, false);
|
|
2138
|
+
assert.calledWith(
|
|
2139
|
+
LoggerProxy.logger.log,
|
|
2140
|
+
`Meetings:index#isNeedHandleMainLocus --> there is active breakout session and joined on this device, and don't need to handle main session: url`
|
|
2141
|
+
);
|
|
2142
|
+
});
|
|
2143
|
+
|
|
2144
|
+
it('check self is moved and removed, return false', () => {
|
|
2145
|
+
webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
|
|
2146
|
+
newLocus.self.state = 'LEFT';
|
|
2147
|
+
newLocus.self.reason = 'MOVED';
|
|
2148
|
+
newLocus.self.removed = true;
|
|
2149
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
2150
|
+
const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
|
|
2151
|
+
assert.equal(result, false);
|
|
2152
|
+
assert.calledWith(
|
|
2153
|
+
LoggerProxy.logger.log,
|
|
2154
|
+
'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
|
|
2155
|
+
);
|
|
2156
|
+
});
|
|
2157
|
+
|
|
2158
|
+
it('check self is moved and device resource removed, return false', () => {
|
|
2159
|
+
webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
|
|
2160
|
+
newLocus.self.state = 'LEFT';
|
|
2161
|
+
newLocus.self.reason = 'MOVED';
|
|
2162
|
+
sinon.stub(MeetingsUtil, 'getThisDevice').returns({
|
|
2163
|
+
state: 'LEFT',
|
|
2164
|
+
reason: 'MOVED',
|
|
2165
|
+
});
|
|
2166
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
2167
|
+
const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
|
|
2168
|
+
assert.equal(result, false);
|
|
2169
|
+
assert.calledWith(
|
|
2170
|
+
LoggerProxy.logger.log,
|
|
2171
|
+
'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
|
|
2172
|
+
);
|
|
2173
|
+
});
|
|
2174
|
+
|
|
2175
|
+
it('check self is joined but device resource removed, return false', () => {
|
|
2176
|
+
webex.meetings.meetingCollection.getActiveBreakoutLocus = sinon.stub().returns(null);
|
|
2177
|
+
sinon.stub(MeetingsUtil, 'joinedOnThisDevice').returns(false);
|
|
2178
|
+
newLocus.self.state = 'JOINED';
|
|
2179
|
+
sinon.stub(MeetingsUtil, 'getThisDevice').returns({
|
|
2180
|
+
state: 'LEFT',
|
|
2181
|
+
reason: 'MOVED',
|
|
2182
|
+
});
|
|
2183
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
2184
|
+
const result = webex.meetings.isNeedHandleMainLocus(meeting, newLocus);
|
|
2185
|
+
assert.equal(result, false);
|
|
2186
|
+
assert.calledWith(
|
|
2187
|
+
LoggerProxy.logger.log,
|
|
2188
|
+
'Meetings:index#isNeedHandleMainLocus --> self device left&moved in main locus with self joined status, not need to handle'
|
|
2189
|
+
);
|
|
2190
|
+
});
|
|
2191
|
+
});
|
|
2192
|
+
|
|
2193
|
+
describe('#isNeedHandleLocusDTO', () => {
|
|
2194
|
+
let meeting;
|
|
2195
|
+
let newLocus;
|
|
2196
|
+
beforeEach(() => {
|
|
2197
|
+
meeting = {
|
|
2198
|
+
controls: {},
|
|
2199
|
+
self: {},
|
|
2200
|
+
};
|
|
2201
|
+
newLocus = {
|
|
2202
|
+
controls: {},
|
|
2203
|
+
self: {},
|
|
2204
|
+
};
|
|
2205
|
+
});
|
|
2206
|
+
afterEach(() => {
|
|
2207
|
+
sinon.restore();
|
|
2208
|
+
});
|
|
2209
|
+
it('initial DTO , joined breakout session, return true', () => {
|
|
2210
|
+
newLocus.controls.breakout = {
|
|
2211
|
+
sessionType: 'BREAKOUT',
|
|
2212
|
+
};
|
|
2213
|
+
newLocus.self.state = 'JOINED';
|
|
2214
|
+
newLocus.fullState = {
|
|
2215
|
+
active: true,
|
|
2216
|
+
};
|
|
2217
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
2218
|
+
const result = webex.meetings.isNeedHandleLocusDTO(null, newLocus);
|
|
2219
|
+
assert.equal(result, true);
|
|
2220
|
+
assert.calledWith(
|
|
2221
|
+
LoggerProxy.logger.log,
|
|
2222
|
+
`Meetings:index#isNeedHandleLocusDTO --> the first breakout session locusDTO active status: true`
|
|
2223
|
+
);
|
|
2224
|
+
});
|
|
2225
|
+
it('others go to check isNeedHandleMainLocus', () => {
|
|
2226
|
+
newLocus.controls.breakout = {
|
|
2227
|
+
sessionType: 'MAIN',
|
|
2228
|
+
};
|
|
2229
|
+
newLocus.self.state = 'JOINED';
|
|
2230
|
+
|
|
2231
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
2232
|
+
const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
|
|
2233
|
+
assert.equal(result, true);
|
|
2234
|
+
assert.calledWith(
|
|
2235
|
+
LoggerProxy.logger.log,
|
|
2236
|
+
'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
|
|
2237
|
+
);
|
|
2238
|
+
});
|
|
2239
|
+
it('joined breakout session, self status is moved, return false', () => {
|
|
2240
|
+
newLocus.controls.breakout = {
|
|
2241
|
+
sessionType: 'BREAKOUT',
|
|
2242
|
+
};
|
|
2243
|
+
newLocus.self.state = 'LEFT';
|
|
2244
|
+
newLocus.self.reason = 'MOVED';
|
|
2245
|
+
|
|
2246
|
+
LoggerProxy.logger.log = sinon.stub();
|
|
2247
|
+
const result = webex.meetings.isNeedHandleLocusDTO(meeting, newLocus);
|
|
2248
|
+
assert.equal(result, false);
|
|
2249
|
+
});
|
|
2250
|
+
});
|
|
2251
|
+
|
|
2252
|
+
describe('#getCorrespondingMeetingByLocus', () => {
|
|
2253
|
+
let locus;
|
|
2254
|
+
let mockReturnMeeting = {meeting: 'meeting1'};
|
|
2255
|
+
const mockGetByKey = (keyWillReturnMeeting) => {
|
|
2256
|
+
webex.meetings.meetingCollection.getByKey = sinon.stub().callsFake((key) => {
|
|
2257
|
+
if (key === keyWillReturnMeeting) {
|
|
2258
|
+
return mockReturnMeeting;
|
|
2259
|
+
}
|
|
2260
|
+
return null;
|
|
2261
|
+
});
|
|
2262
|
+
};
|
|
2263
|
+
|
|
2264
|
+
beforeEach(() => {
|
|
2265
|
+
locus = {
|
|
2266
|
+
controls: {},
|
|
2267
|
+
self: {
|
|
2268
|
+
callbackInfo: {
|
|
2269
|
+
callbackAddress: 'address1',
|
|
2270
|
+
},
|
|
2271
|
+
},
|
|
2272
|
+
info: {
|
|
2273
|
+
webExMeetingId: '123456',
|
|
2274
|
+
isUnifiedSpaceMeeting: false,
|
|
2275
|
+
},
|
|
2276
|
+
conversationUrl: 'conversationUrl1',
|
|
2277
|
+
};
|
|
2278
|
+
|
|
2279
|
+
sinon.stub(MeetingsUtil, 'checkForCorrelationId').returns('correlationId1');
|
|
2280
|
+
});
|
|
2281
|
+
afterEach(() => {
|
|
2282
|
+
sinon.restore();
|
|
2283
|
+
});
|
|
2284
|
+
it('check the calls when no meeting found in meetingCollection', () => {
|
|
2285
|
+
mockGetByKey();
|
|
2286
|
+
const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
|
|
2287
|
+
assert.isNull(result);
|
|
2288
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
|
|
2289
|
+
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
|
|
2290
|
+
assert.calledWith(
|
|
2291
|
+
webex.meetings.meetingCollection.getByKey,
|
|
2292
|
+
'correlationId',
|
|
2293
|
+
'correlationId1'
|
|
2294
|
+
);
|
|
2295
|
+
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
|
|
2296
|
+
assert.calledWith(
|
|
2297
|
+
webex.meetings.meetingCollection.getByKey,
|
|
2298
|
+
'conversationUrl',
|
|
2299
|
+
'conversationUrl1'
|
|
2300
|
+
);
|
|
2301
|
+
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', '123456');
|
|
2302
|
+
});
|
|
2303
|
+
|
|
2304
|
+
it('not try getByKey "conversationUrl" when isUnifiedSpaceMeeting is true', () => {
|
|
2305
|
+
mockGetByKey();
|
|
2306
|
+
locus.info.isUnifiedSpaceMeeting = true;
|
|
2307
|
+
const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
|
|
2308
|
+
assert.isNull(result);
|
|
2309
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
|
|
2310
|
+
});
|
|
2311
|
+
|
|
2312
|
+
it('check the calls when meeting found by key: locusUrl', () => {
|
|
2313
|
+
mockGetByKey('locusUrl');
|
|
2314
|
+
const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
|
|
2315
|
+
assert.deepEqual(result, mockReturnMeeting);
|
|
2316
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 1);
|
|
2317
|
+
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
|
|
2318
|
+
});
|
|
2319
|
+
|
|
2320
|
+
it('check the calls when meeting found by key: correlationId', () => {
|
|
2321
|
+
mockGetByKey('correlationId');
|
|
2322
|
+
const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
|
|
2323
|
+
assert.deepEqual(result, mockReturnMeeting);
|
|
2324
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 2);
|
|
2325
|
+
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
|
|
2326
|
+
assert.calledWith(
|
|
2327
|
+
webex.meetings.meetingCollection.getByKey,
|
|
2328
|
+
'correlationId',
|
|
2329
|
+
'correlationId1'
|
|
2330
|
+
);
|
|
2331
|
+
});
|
|
2332
|
+
|
|
2333
|
+
it('check the calls when meeting found by key: sipUri', () => {
|
|
2334
|
+
mockGetByKey('sipUri');
|
|
2335
|
+
const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
|
|
2336
|
+
assert.deepEqual(result, mockReturnMeeting);
|
|
2337
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 3);
|
|
2338
|
+
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
|
|
2339
|
+
assert.calledWith(
|
|
2340
|
+
webex.meetings.meetingCollection.getByKey,
|
|
2341
|
+
'correlationId',
|
|
2342
|
+
'correlationId1'
|
|
2343
|
+
);
|
|
2344
|
+
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
|
|
2345
|
+
});
|
|
2346
|
+
|
|
2347
|
+
it('check the calls when meeting found by key: conversationUrl', () => {
|
|
2348
|
+
mockGetByKey('conversationUrl');
|
|
2349
|
+
const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
|
|
2350
|
+
assert.deepEqual(result, mockReturnMeeting);
|
|
2351
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 4);
|
|
2352
|
+
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
|
|
2353
|
+
assert.calledWith(
|
|
2354
|
+
webex.meetings.meetingCollection.getByKey,
|
|
2355
|
+
'correlationId',
|
|
2356
|
+
'correlationId1'
|
|
2357
|
+
);
|
|
2358
|
+
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
|
|
2359
|
+
assert.calledWith(
|
|
2360
|
+
webex.meetings.meetingCollection.getByKey,
|
|
2361
|
+
'conversationUrl',
|
|
2362
|
+
'conversationUrl1'
|
|
2363
|
+
);
|
|
2364
|
+
});
|
|
2365
|
+
|
|
2366
|
+
it('check the calls when meeting found by key: meetingNumber', () => {
|
|
2367
|
+
mockGetByKey('meetingNumber');
|
|
2368
|
+
const result = webex.meetings.getCorrespondingMeetingByLocus({locus, locusUrl: url1});
|
|
2369
|
+
assert.deepEqual(result, mockReturnMeeting);
|
|
2370
|
+
assert.callCount(webex.meetings.meetingCollection.getByKey, 5);
|
|
2371
|
+
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'locusUrl', url1);
|
|
2372
|
+
assert.calledWith(
|
|
2373
|
+
webex.meetings.meetingCollection.getByKey,
|
|
2374
|
+
'correlationId',
|
|
2375
|
+
'correlationId1'
|
|
2376
|
+
);
|
|
2377
|
+
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'sipUri', 'address1');
|
|
2378
|
+
assert.calledWith(
|
|
2379
|
+
webex.meetings.meetingCollection.getByKey,
|
|
2380
|
+
'conversationUrl',
|
|
2381
|
+
'conversationUrl1'
|
|
2382
|
+
);
|
|
2383
|
+
assert.calledWith(webex.meetings.meetingCollection.getByKey, 'meetingNumber', '123456');
|
|
2384
|
+
});
|
|
2385
|
+
});
|
|
2386
|
+
|
|
2387
|
+
describe('#sortLocusArrayToUpdate', () => {
|
|
2388
|
+
let lociArray;
|
|
2389
|
+
let mainLocus;
|
|
2390
|
+
let breakoutLocus;
|
|
2391
|
+
beforeEach(() => {
|
|
2392
|
+
mainLocus = {
|
|
2393
|
+
url: 'mainUrl1',
|
|
2394
|
+
controls: {
|
|
2395
|
+
breakout: {
|
|
2396
|
+
sessionType: 'MAIN',
|
|
2397
|
+
url: 'breakoutUnifiedUrl1',
|
|
2398
|
+
},
|
|
2399
|
+
},
|
|
2400
|
+
};
|
|
2401
|
+
breakoutLocus = {
|
|
2402
|
+
url: 'breakoutUrl1',
|
|
2403
|
+
controls: {
|
|
2404
|
+
breakout: {
|
|
2405
|
+
sessionType: 'BREAKOUT',
|
|
2406
|
+
url: 'breakoutUnifiedUrl1',
|
|
2407
|
+
},
|
|
2408
|
+
},
|
|
2409
|
+
};
|
|
2410
|
+
lociArray = [mainLocus, breakoutLocus];
|
|
2411
|
+
|
|
2412
|
+
sinon.stub(MeetingsUtil, 'isValidBreakoutLocus').callsFake((locus) => {
|
|
2413
|
+
return locus.url === 'breakoutUrl1';
|
|
2414
|
+
});
|
|
2415
|
+
});
|
|
2416
|
+
afterEach(() => {
|
|
2417
|
+
sinon.restore();
|
|
2418
|
+
});
|
|
2419
|
+
|
|
2420
|
+
it('if both main and breakout locus is in array for non-exist meeting, return main locus to create first', () => {
|
|
2421
|
+
webex.meetings.meetingCollection.getByKey = sinon.stub().returns(undefined);
|
|
2422
|
+
const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
|
|
2423
|
+
assert.deepEqual(result, [mainLocus]);
|
|
2424
|
+
assert.deepEqual(webex.meetings.breakoutLocusForHandleLater, [breakoutLocus]);
|
|
2425
|
+
});
|
|
2426
|
+
|
|
2427
|
+
it('if both main and breakout locus is in array for an exist meeting, return all locus', () => {
|
|
2428
|
+
webex.meetings.meetingCollection.getByKey = sinon.stub().returns({});
|
|
2429
|
+
const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
|
|
2430
|
+
assert.deepEqual(result, [mainLocus, breakoutLocus]);
|
|
2431
|
+
assert.deepEqual(webex.meetings.breakoutLocusForHandleLater, []);
|
|
2432
|
+
});
|
|
2433
|
+
|
|
2434
|
+
it('if the breakout locus has no associated main locus, return all', () => {
|
|
2435
|
+
webex.meetings.meetingCollection.getByKey = sinon.stub().returns({});
|
|
2436
|
+
breakoutLocus.controls.breakout.url = 'testUrl';
|
|
2437
|
+
const result = webex.meetings.sortLocusArrayToUpdate(lociArray);
|
|
2438
|
+
assert.deepEqual(result, [mainLocus, breakoutLocus]);
|
|
2439
|
+
});
|
|
2440
|
+
});
|
|
2441
|
+
|
|
2442
|
+
describe('#checkHandleBreakoutLocus', () => {
|
|
2443
|
+
let breakoutLocus;
|
|
2444
|
+
beforeEach(() => {
|
|
2445
|
+
breakoutLocus = {
|
|
2446
|
+
url: 'breakoutUrl1',
|
|
2447
|
+
controls: {
|
|
2448
|
+
breakout: {
|
|
2449
|
+
sessionType: 'BREAKOUT',
|
|
2450
|
+
url: 'breakoutUnifiedUrl1',
|
|
2451
|
+
},
|
|
2452
|
+
},
|
|
2453
|
+
};
|
|
2454
|
+
|
|
2455
|
+
webex.meetings.handleLocusEvent = sinon.stub();
|
|
2456
|
+
});
|
|
2457
|
+
afterEach(() => {
|
|
2458
|
+
sinon.restore();
|
|
2459
|
+
});
|
|
2460
|
+
it('do nothing if new created locus is null/no cached breakouts for updating', () => {
|
|
2461
|
+
webex.meetings.checkHandleBreakoutLocus(null);
|
|
2462
|
+
webex.meetings.breakoutLocusForHandleLater = null;
|
|
2463
|
+
webex.meetings.checkHandleBreakoutLocus({});
|
|
2464
|
+
webex.meetings.breakoutLocusForHandleLater = [];
|
|
2465
|
+
webex.meetings.checkHandleBreakoutLocus({});
|
|
2466
|
+
assert.notCalled(webex.meetings.handleLocusEvent);
|
|
2467
|
+
});
|
|
2468
|
+
|
|
2469
|
+
it('do nothing if new created locus is breakout locus', () => {
|
|
2470
|
+
webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
|
|
2471
|
+
webex.meetings.checkHandleBreakoutLocus(breakoutLocus);
|
|
2472
|
+
assert.notCalled(webex.meetings.handleLocusEvent);
|
|
2473
|
+
});
|
|
2474
|
+
|
|
2475
|
+
it('do nothing if no cached locus is associated with the new created locus', () => {
|
|
2476
|
+
webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
|
|
2477
|
+
webex.meetings.checkHandleBreakoutLocus({
|
|
2478
|
+
controls: {
|
|
2479
|
+
breakout: {
|
|
2480
|
+
sessionType: 'MAIN',
|
|
2481
|
+
url: 'breakoutUnifiedUrl2',
|
|
2482
|
+
},
|
|
2483
|
+
},
|
|
2484
|
+
});
|
|
2485
|
+
assert.notCalled(webex.meetings.handleLocusEvent);
|
|
2486
|
+
});
|
|
2487
|
+
|
|
2488
|
+
it('update the cached breakout locus which associate the new created locus', () => {
|
|
2489
|
+
webex.meetings.breakoutLocusForHandleLater = [breakoutLocus];
|
|
2490
|
+
webex.meetings.checkHandleBreakoutLocus({
|
|
2491
|
+
controls: {
|
|
2492
|
+
breakout: {
|
|
2493
|
+
sessionType: 'MAIN',
|
|
2494
|
+
url: 'breakoutUnifiedUrl1',
|
|
2495
|
+
},
|
|
2496
|
+
},
|
|
2497
|
+
});
|
|
2498
|
+
assert.calledWith(webex.meetings.handleLocusEvent, {
|
|
2499
|
+
locus: breakoutLocus,
|
|
2500
|
+
locusUrl: breakoutLocus.url,
|
|
2501
|
+
});
|
|
2502
|
+
});
|
|
2503
|
+
});
|
|
2504
|
+
|
|
2505
|
+
describe('uploading of logs', () => {
|
|
2506
|
+
let metricsSpy;
|
|
2507
|
+
let meeting;
|
|
2508
|
+
|
|
2509
|
+
beforeEach(async () => {
|
|
2510
|
+
webex.meetings.config.autoUploadLogs = true;
|
|
2511
|
+
webex.meetings.loggerRequest.uploadLogs = sinon.stub().resolves();
|
|
2512
|
+
|
|
2513
|
+
sinon.stub(webex.meetings.meetingInfo, 'fetchInfoOptions').resolves({});
|
|
2514
|
+
sinon.stub(webex.meetings.meetingInfo, 'fetchMeetingInfo').resolves({});
|
|
2515
|
+
|
|
2516
|
+
triggerProxyStub.restore();
|
|
2517
|
+
|
|
2518
|
+
metricsSpy = sinon.stub(Metrics, 'sendBehavioralMetric');
|
|
2519
|
+
|
|
2520
|
+
meeting = await webex.meetings.create('test');
|
|
2521
|
+
|
|
2522
|
+
meeting.locusId = 'locus id';
|
|
2523
|
+
meeting.correlationId = 'correlation id';
|
|
2524
|
+
meeting.locusInfo = {
|
|
2525
|
+
fullState: {lastActive: 'last active', sessionId: 'locus session id'},
|
|
2526
|
+
info: {webExMeetingId: 'meeting id'},
|
|
2527
|
+
};
|
|
2528
|
+
});
|
|
2529
|
+
|
|
2530
|
+
afterEach(() => {
|
|
2531
|
+
sinon.restore();
|
|
2532
|
+
});
|
|
2533
|
+
|
|
2534
|
+
it('sends metrics on success', async () => {
|
|
2535
|
+
await meeting.uploadLogs();
|
|
2536
|
+
|
|
2537
|
+
await testUtils.flushPromises();
|
|
2538
|
+
|
|
2539
|
+
assert.calledOnceWithExactly(metricsSpy, 'js_sdk_upload_logs_success', {
|
|
2540
|
+
callStart: 'last active',
|
|
2541
|
+
correlationId: 'correlation id',
|
|
2542
|
+
feedbackId: 'correlation id',
|
|
2543
|
+
locusId: 'locus id',
|
|
2544
|
+
meetingId: 'meeting id',
|
|
2545
|
+
autoupload: true,
|
|
2546
|
+
locussessionid: 'locus session id',
|
|
2547
|
+
});
|
|
2548
|
+
});
|
|
2549
|
+
|
|
2550
|
+
it('sends metrics on failure', async () => {
|
|
2551
|
+
webex.meetings.loggerRequest.uploadLogs.rejects(new Error('fake error'));
|
|
2552
|
+
|
|
2553
|
+
await meeting.uploadLogs();
|
|
2554
|
+
|
|
2555
|
+
await testUtils.flushPromises();
|
|
2556
|
+
|
|
2557
|
+
assert.calledOnceWithExactly(
|
|
2558
|
+
metricsSpy,
|
|
2559
|
+
'js_sdk_upload_logs_failure',
|
|
2560
|
+
sinon.match({
|
|
2561
|
+
callStart: 'last active',
|
|
2562
|
+
correlationId: 'correlation id',
|
|
2563
|
+
feedbackId: 'correlation id',
|
|
2564
|
+
locusId: 'locus id',
|
|
2565
|
+
meetingId: 'meeting id',
|
|
2566
|
+
reason: 'fake error',
|
|
2567
|
+
autoupload: true,
|
|
2568
|
+
locussessionid: 'locus session id',
|
|
2569
|
+
})
|
|
2570
|
+
);
|
|
2571
|
+
});
|
|
2572
|
+
});
|
|
1371
2573
|
});
|
|
1372
2574
|
});
|