@webex/plugin-meetings 2.59.4-next.1 → 2.59.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common/browser-detection.d.ts +9 -0
- package/dist/common/browser-detection.js +2 -2
- package/dist/common/browser-detection.js.map +1 -1
- package/dist/common/collection.d.ts +48 -0
- package/dist/common/collection.js +2 -2
- package/dist/common/collection.js.map +1 -1
- package/dist/common/config.d.ts +2 -0
- package/dist/common/errors/captcha-error.d.ts +15 -0
- package/dist/common/errors/intent-to-join.d.ts +16 -0
- package/dist/common/errors/join-meeting.d.ts +17 -0
- package/dist/common/errors/media.d.ts +15 -0
- package/dist/common/errors/parameter.d.ts +15 -0
- package/dist/common/errors/password-error.d.ts +15 -0
- package/dist/common/errors/permission.d.ts +14 -0
- package/dist/common/errors/reconnection-in-progress.d.ts +9 -0
- package/dist/common/errors/reconnection.d.ts +15 -0
- package/dist/common/errors/stats.d.ts +15 -0
- package/dist/common/errors/webex-errors.d.ts +81 -0
- package/dist/common/errors/webex-meetings-error.d.ts +20 -0
- package/dist/common/events/events-scope.d.ts +17 -0
- package/dist/common/events/events.d.ts +12 -0
- package/dist/common/events/trigger-proxy.d.ts +2 -0
- package/dist/common/events/util.d.ts +2 -0
- package/dist/common/logs/logger-config.d.ts +2 -0
- package/dist/common/logs/logger-proxy.d.ts +2 -0
- package/dist/common/logs/request.d.ts +34 -0
- package/dist/common/queue.d.ts +32 -0
- package/dist/config.d.ts +73 -0
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +926 -0
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/constants.d.ts +4 -0
- package/dist/controls-options-manager/enums.d.ts +5 -0
- package/dist/controls-options-manager/index.d.ts +120 -0
- package/dist/controls-options-manager/index.js +2 -2
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/util.d.ts +7 -0
- package/dist/index.d.ts +4 -0
- package/dist/locus-info/controlsUtils.d.ts +2 -0
- package/dist/locus-info/controlsUtils.js +6 -6
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/embeddedAppsUtils.d.ts +2 -0
- package/dist/locus-info/fullState.d.ts +2 -0
- package/dist/locus-info/hostUtils.d.ts +2 -0
- package/dist/locus-info/index.d.ts +269 -0
- package/dist/locus-info/index.js +18 -18
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.d.ts +2 -0
- package/dist/locus-info/mediaSharesUtils.d.ts +2 -0
- package/dist/locus-info/parser.d.ts +212 -0
- package/dist/locus-info/parser.js +2 -2
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.d.ts +2 -0
- package/dist/media/index.d.ts +32 -0
- package/dist/media/properties.d.ts +108 -0
- package/dist/media/util.d.ts +2 -0
- package/dist/mediaQualityMetrics/config.d.ts +233 -0
- package/dist/meeting/effectsState.d.ts +42 -0
- package/dist/meeting/in-meeting-actions.d.ts +79 -0
- package/dist/meeting/index.d.ts +1621 -0
- package/dist/meeting/index.js +51 -28
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.d.ts +116 -0
- package/dist/meeting/request.d.ts +255 -0
- package/dist/meeting/request.js +2 -2
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/state.d.ts +9 -0
- package/dist/meeting/util.d.ts +2 -0
- package/dist/meeting/util.js +4 -4
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/collection.d.ts +20 -0
- package/dist/meeting-info/collection.js +2 -2
- package/dist/meeting-info/collection.js.map +1 -1
- package/dist/meeting-info/index.d.ts +57 -0
- package/dist/meeting-info/meeting-info-v2.d.ts +93 -0
- package/dist/meeting-info/request.d.ts +22 -0
- package/dist/meeting-info/util.d.ts +2 -0
- package/dist/meeting-info/utilv2.d.ts +2 -0
- package/dist/meetings/collection.d.ts +23 -0
- package/dist/meetings/collection.js +2 -2
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.d.ts +296 -0
- package/dist/meetings/request.d.ts +27 -0
- package/dist/meetings/util.d.ts +18 -0
- package/dist/member/index.d.ts +147 -0
- package/dist/member/member.types.d.ts +11 -0
- package/dist/member/util.d.ts +2 -0
- package/dist/members/collection.d.ts +24 -0
- package/dist/members/index.d.ts +298 -0
- package/dist/members/index.js +2 -2
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.d.ts +50 -0
- package/dist/members/util.d.ts +2 -0
- package/dist/metrics/config.d.ts +169 -0
- package/dist/metrics/constants.d.ts +59 -0
- package/dist/metrics/constants.js +2 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.d.ts +152 -0
- package/dist/metrics/index.js +2 -2
- package/dist/metrics/index.js.map +1 -1
- package/dist/networkQualityMonitor/index.d.ts +70 -0
- package/dist/peer-connection-manager/index.d.ts +6 -0
- package/dist/peer-connection-manager/util.d.ts +6 -0
- package/dist/personal-meeting-room/index.d.ts +47 -0
- package/dist/personal-meeting-room/request.d.ts +14 -0
- package/dist/personal-meeting-room/util.d.ts +2 -0
- package/dist/reachability/index.d.ts +139 -0
- package/dist/reachability/index.js +2 -9
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.d.ts +35 -0
- package/dist/reactions/reactions.d.ts +4 -0
- package/dist/reactions/reactions.type.d.ts +32 -0
- package/dist/reconnection-manager/index.d.ts +112 -0
- package/dist/recording-controller/enums.d.ts +7 -0
- package/dist/recording-controller/index.d.ts +193 -0
- package/dist/recording-controller/util.d.ts +13 -0
- package/dist/roap/collection.d.ts +10 -0
- package/dist/roap/handler.d.ts +47 -0
- package/dist/roap/index.d.ts +116 -0
- package/dist/roap/index.js +13 -12
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.d.ts +35 -0
- package/dist/roap/state.d.ts +9 -0
- package/dist/roap/turnDiscovery.d.ts +81 -0
- package/dist/roap/turnDiscovery.js +130 -44
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/roap/util.d.ts +2 -0
- package/dist/statsAnalyzer/global.d.ts +118 -0
- package/dist/statsAnalyzer/global.js +4 -12
- package/dist/statsAnalyzer/global.js.map +1 -1
- package/dist/statsAnalyzer/index.d.ts +193 -0
- package/dist/statsAnalyzer/index.js +56 -14
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.d.ts +22 -0
- package/dist/statsAnalyzer/mqaUtil.js +15 -15
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/transcription/index.d.ts +64 -0
- package/package.json +21 -22
- package/src/config.ts +2 -2
- package/src/constants.ts +2 -0
- package/src/meeting/index.ts +35 -0
- package/src/metrics/constants.ts +2 -0
- package/src/roap/index.ts +14 -10
- package/src/roap/turnDiscovery.ts +48 -20
- package/src/statsAnalyzer/global.ts +2 -10
- package/src/statsAnalyzer/index.ts +80 -17
- package/test/unit/spec/meeting/index.js +77 -6
- package/test/unit/spec/roap/index.ts +84 -80
- package/test/unit/spec/roap/turnDiscovery.ts +21 -0
- package/test/unit/spec/stats-analyzer/index.js +151 -0
|
@@ -25,6 +25,8 @@ import {
|
|
|
25
25
|
|
|
26
26
|
export const EVENTS = {
|
|
27
27
|
MEDIA_QUALITY: 'MEDIA_QUALITY',
|
|
28
|
+
NO_FRAMES_SENT: 'NO_FRAMES_SENT',
|
|
29
|
+
NO_VIDEO_ENCODED: 'NO_VIDEO_ENCODED',
|
|
28
30
|
LOCAL_MEDIA_STARTED: 'LOCAL_MEDIA_STARTED',
|
|
29
31
|
LOCAL_MEDIA_STOPPED: 'LOCAL_MEDIA_STOPPED',
|
|
30
32
|
REMOTE_MEDIA_STARTED: 'REMOTE_MEDIA_STARTED',
|
|
@@ -420,9 +422,6 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
420
422
|
case 'inbound-rtp':
|
|
421
423
|
this.processInboundRTPResult(getStatsResult, type);
|
|
422
424
|
break;
|
|
423
|
-
case 'track':
|
|
424
|
-
this.processTrackResult(getStatsResult, type);
|
|
425
|
-
break;
|
|
426
425
|
case 'remote-inbound-rtp':
|
|
427
426
|
case 'remote-outbound-rtp':
|
|
428
427
|
// @ts-ignore
|
|
@@ -520,7 +519,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
520
519
|
|
|
521
520
|
if (currentValue - previousValue > 0) {
|
|
522
521
|
newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STARTED : EVENTS.REMOTE_MEDIA_STARTED;
|
|
523
|
-
} else if (currentValue === previousValue && currentValue
|
|
522
|
+
} else if (currentValue === previousValue && currentValue >= 0) {
|
|
524
523
|
newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STOPPED : EVENTS.REMOTE_MEDIA_STOPPED;
|
|
525
524
|
}
|
|
526
525
|
|
|
@@ -635,14 +634,25 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
635
634
|
LoggerProxy.logger.info(
|
|
636
635
|
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets sent`
|
|
637
636
|
);
|
|
638
|
-
} else {
|
|
637
|
+
} else if (this.lastEmittedStartStopEvent[mediaType].local !== EVENTS.LOCAL_MEDIA_STOPPED) {
|
|
639
638
|
if (
|
|
640
639
|
currentStats.framesEncoded === previousStats.framesEncoded ||
|
|
641
640
|
currentStats.framesEncoded === 0
|
|
642
641
|
) {
|
|
642
|
+
this.lastEmittedStartStopEvent[mediaType].local = EVENTS.NO_VIDEO_ENCODED;
|
|
643
643
|
LoggerProxy.logger.info(
|
|
644
644
|
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} Frames Encoded`
|
|
645
645
|
);
|
|
646
|
+
this.emit(
|
|
647
|
+
{
|
|
648
|
+
file: 'statsAnalyzer',
|
|
649
|
+
function: 'compareLastStatsResult',
|
|
650
|
+
},
|
|
651
|
+
EVENTS.NO_VIDEO_ENCODED,
|
|
652
|
+
{
|
|
653
|
+
mediaType,
|
|
654
|
+
}
|
|
655
|
+
);
|
|
646
656
|
}
|
|
647
657
|
|
|
648
658
|
if (
|
|
@@ -654,8 +664,28 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
654
664
|
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} Frames sent`
|
|
655
665
|
);
|
|
656
666
|
}
|
|
657
|
-
}
|
|
658
667
|
|
|
668
|
+
// Video is encoded but frames are not sent
|
|
669
|
+
if (
|
|
670
|
+
currentStats.framesEncoded !== previousStats.framesEncoded &&
|
|
671
|
+
(currentStats.framesSent === previousStats.framesSent || currentStats.framesSent === 0)
|
|
672
|
+
) {
|
|
673
|
+
this.lastEmittedStartStopEvent[mediaType].local = EVENTS.NO_FRAMES_SENT;
|
|
674
|
+
LoggerProxy.logger.info(
|
|
675
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames sent even though frames are encoded`
|
|
676
|
+
);
|
|
677
|
+
this.emit(
|
|
678
|
+
{
|
|
679
|
+
file: 'statsAnalyzer',
|
|
680
|
+
function: 'compareLastStatsResult',
|
|
681
|
+
},
|
|
682
|
+
EVENTS.NO_FRAMES_SENT,
|
|
683
|
+
{
|
|
684
|
+
mediaType,
|
|
685
|
+
}
|
|
686
|
+
);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
659
689
|
this.emitStartStopEvents(
|
|
660
690
|
mediaType,
|
|
661
691
|
previousStats.framesSent,
|
|
@@ -731,14 +761,25 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
731
761
|
LoggerProxy.logger.info(
|
|
732
762
|
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets sent`
|
|
733
763
|
);
|
|
734
|
-
} else {
|
|
764
|
+
} else if (this.lastEmittedStartStopEvent[mediaType].local !== EVENTS.LOCAL_MEDIA_STOPPED) {
|
|
735
765
|
if (
|
|
736
766
|
currentStats.framesEncoded === previousStats.framesEncoded ||
|
|
737
767
|
currentStats.framesEncoded === 0
|
|
738
768
|
) {
|
|
769
|
+
this.lastEmittedStartStopEvent[mediaType].local = EVENTS.NO_VIDEO_ENCODED;
|
|
739
770
|
LoggerProxy.logger.info(
|
|
740
771
|
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames getting encoded`
|
|
741
772
|
);
|
|
773
|
+
this.emit(
|
|
774
|
+
{
|
|
775
|
+
file: 'statsAnalyzer',
|
|
776
|
+
function: 'compareLastStatsResult',
|
|
777
|
+
},
|
|
778
|
+
EVENTS.NO_VIDEO_ENCODED,
|
|
779
|
+
{
|
|
780
|
+
mediaType,
|
|
781
|
+
}
|
|
782
|
+
);
|
|
742
783
|
}
|
|
743
784
|
|
|
744
785
|
if (
|
|
@@ -750,6 +791,27 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
750
791
|
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames sent`
|
|
751
792
|
);
|
|
752
793
|
}
|
|
794
|
+
|
|
795
|
+
// Share video is encoded but frames are not sent
|
|
796
|
+
if (
|
|
797
|
+
currentStats.framesEncoded !== previousStats.framesEncoded &&
|
|
798
|
+
(currentStats.framesSent === previousStats.framesSent || currentStats.framesSent === 0)
|
|
799
|
+
) {
|
|
800
|
+
this.lastEmittedStartStopEvent[mediaType].local = EVENTS.NO_FRAMES_SENT;
|
|
801
|
+
LoggerProxy.logger.info(
|
|
802
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} Frames sent even though frames are being encoded`
|
|
803
|
+
);
|
|
804
|
+
this.emit(
|
|
805
|
+
{
|
|
806
|
+
file: 'statsAnalyzer',
|
|
807
|
+
function: 'compareLastStatsResult',
|
|
808
|
+
},
|
|
809
|
+
EVENTS.NO_FRAMES_SENT,
|
|
810
|
+
{
|
|
811
|
+
mediaType,
|
|
812
|
+
}
|
|
813
|
+
);
|
|
814
|
+
}
|
|
753
815
|
}
|
|
754
816
|
|
|
755
817
|
// TODO:need to check receive share value
|
|
@@ -881,6 +943,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
881
943
|
const mediaType = type || STATS.AUDIO_CORRELATE;
|
|
882
944
|
const sendrecvType = STATS.SEND_DIRECTION;
|
|
883
945
|
|
|
946
|
+
this.processTrackResult(result, type, sendrecvType);
|
|
884
947
|
if (result.bytesSent) {
|
|
885
948
|
let kilobytes = 0;
|
|
886
949
|
|
|
@@ -904,7 +967,6 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
904
967
|
|
|
905
968
|
this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
|
|
906
969
|
this.statsResults[mediaType].bytesSent = kilobytes;
|
|
907
|
-
|
|
908
970
|
this.statsResults[mediaType][sendrecvType].framesEncoded =
|
|
909
971
|
result.framesEncoded - this.statsResults.internal[mediaType][sendrecvType].framesEncoded;
|
|
910
972
|
this.statsResults[mediaType][sendrecvType].keyFramesEncoded =
|
|
@@ -955,6 +1017,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
955
1017
|
const mediaType = type || STATS.AUDIO_CORRELATE;
|
|
956
1018
|
const sendrecvType = STATS.RECEIVE_DIRECTION;
|
|
957
1019
|
|
|
1020
|
+
this.processTrackResult(result, type, sendrecvType);
|
|
958
1021
|
if (result.bytesReceived) {
|
|
959
1022
|
let kilobytes = 0;
|
|
960
1023
|
|
|
@@ -1158,29 +1221,29 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1158
1221
|
* @private
|
|
1159
1222
|
* @param {*} result
|
|
1160
1223
|
* @param {*} mediaType
|
|
1224
|
+
* @param {*} sendrecvType
|
|
1161
1225
|
* @returns {void}
|
|
1162
1226
|
* @memberof StatsAnalyzer
|
|
1163
1227
|
*/
|
|
1164
|
-
private processTrackResult(result: any, mediaType: any) {
|
|
1165
|
-
if (!result ||
|
|
1228
|
+
private processTrackResult(result: any, mediaType: any, sendrecvType: any) {
|
|
1229
|
+
if (!result || mediaType === STATS.AUDIO_CORRELATE) {
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1232
|
+
if (result.type !== 'inbound-rtp' && result.type !== 'outbound-rtp') {
|
|
1166
1233
|
return;
|
|
1167
1234
|
}
|
|
1168
|
-
if (result.type !== 'track') return;
|
|
1169
|
-
|
|
1170
|
-
const sendrecvType =
|
|
1171
|
-
result.remoteSource === true ? STATS.RECEIVE_DIRECTION : STATS.SEND_DIRECTION;
|
|
1172
|
-
|
|
1173
1235
|
if (result.frameWidth && result.frameHeight) {
|
|
1174
1236
|
this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;
|
|
1175
1237
|
this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;
|
|
1176
|
-
this.statsResults.resolutions[mediaType][sendrecvType].framesSent = result.framesSent;
|
|
1177
|
-
this.statsResults.resolutions[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;
|
|
1178
1238
|
}
|
|
1179
1239
|
|
|
1180
1240
|
if (sendrecvType === STATS.RECEIVE_DIRECTION) {
|
|
1181
1241
|
this.statsResults.resolutions[mediaType][sendrecvType].framesReceived = result.framesReceived;
|
|
1182
1242
|
this.statsResults.resolutions[mediaType][sendrecvType].framesDecoded = result.framesDecoded;
|
|
1183
1243
|
this.statsResults.resolutions[mediaType][sendrecvType].framesDropped = result.framesDropped;
|
|
1244
|
+
} else if (sendrecvType === STATS.SEND_DIRECTION) {
|
|
1245
|
+
this.statsResults.resolutions[mediaType][sendrecvType].framesSent = result.framesSent;
|
|
1246
|
+
this.statsResults.resolutions[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;
|
|
1184
1247
|
}
|
|
1185
1248
|
|
|
1186
1249
|
if (result.trackIdentifier && mediaType !== STATS.AUDIO_CORRELATE) {
|
|
@@ -1329,6 +1329,71 @@ describe('plugin-meetings', () => {
|
|
|
1329
1329
|
data: {intervalData: fakeData, networkType: 'wifi'},
|
|
1330
1330
|
});
|
|
1331
1331
|
});
|
|
1332
|
+
it('NO_FRAMES_SENT triggers "meeting:noFramesSent" event and sends metrics', async () => {
|
|
1333
|
+
meeting.mediaProperties.mediaDirection = {sendVideo: true};
|
|
1334
|
+
statsAnalyzerStub.emit(
|
|
1335
|
+
{file: 'test', function: 'test'},
|
|
1336
|
+
StatsAnalyzerModule.EVENTS.NO_FRAMES_SENT,
|
|
1337
|
+
{mediaType: 'video'}
|
|
1338
|
+
);
|
|
1339
|
+
|
|
1340
|
+
assert.calledWith(
|
|
1341
|
+
TriggerProxy.trigger,
|
|
1342
|
+
sinon.match.instanceOf(Meeting),
|
|
1343
|
+
{
|
|
1344
|
+
file: 'meeting/index',
|
|
1345
|
+
function: 'compareLastStatsResult',
|
|
1346
|
+
},
|
|
1347
|
+
EVENT_TRIGGERS.MEETING_NO_FRAMES_SENT,
|
|
1348
|
+
{
|
|
1349
|
+
mediaType: 'video',
|
|
1350
|
+
}
|
|
1351
|
+
);
|
|
1352
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.NO_FRAMES_SENT);
|
|
1353
|
+
});
|
|
1354
|
+
it('NO_FRAMES_SENT triggers "meeting:noFramesSent" event and sends metrics for share', async () => {
|
|
1355
|
+
meeting.mediaProperties.mediaDirection = {sendShare: true};
|
|
1356
|
+
statsAnalyzerStub.emit(
|
|
1357
|
+
{file: 'test', function: 'test'},
|
|
1358
|
+
StatsAnalyzerModule.EVENTS.NO_FRAMES_SENT,
|
|
1359
|
+
{mediaType: 'share'}
|
|
1360
|
+
);
|
|
1361
|
+
|
|
1362
|
+
assert.calledWith(
|
|
1363
|
+
TriggerProxy.trigger,
|
|
1364
|
+
sinon.match.instanceOf(Meeting),
|
|
1365
|
+
{
|
|
1366
|
+
file: 'meeting/index',
|
|
1367
|
+
function: 'compareLastStatsResult',
|
|
1368
|
+
},
|
|
1369
|
+
EVENT_TRIGGERS.MEETING_NO_FRAMES_SENT,
|
|
1370
|
+
{
|
|
1371
|
+
mediaType: 'share',
|
|
1372
|
+
}
|
|
1373
|
+
);
|
|
1374
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.NO_FRAMES_SENT);
|
|
1375
|
+
});
|
|
1376
|
+
it('NO_VIDEO_ENCODED triggers "meeting:noVideoEncoded" event and sends metrics', async () => {
|
|
1377
|
+
statsAnalyzerStub.emit(
|
|
1378
|
+
{file: 'test', function: 'test'},
|
|
1379
|
+
StatsAnalyzerModule.EVENTS.NO_VIDEO_ENCODED,
|
|
1380
|
+
{mediaType: 'video'}
|
|
1381
|
+
);
|
|
1382
|
+
|
|
1383
|
+
assert.calledWith(
|
|
1384
|
+
TriggerProxy.trigger,
|
|
1385
|
+
sinon.match.instanceOf(Meeting),
|
|
1386
|
+
{
|
|
1387
|
+
file: 'meeting/index',
|
|
1388
|
+
function: 'compareLastStatsResult',
|
|
1389
|
+
},
|
|
1390
|
+
EVENT_TRIGGERS.MEETING_NO_VIDEO_ENCODED,
|
|
1391
|
+
{
|
|
1392
|
+
mediaType: 'video',
|
|
1393
|
+
}
|
|
1394
|
+
);
|
|
1395
|
+
assert.calledWith(Metrics.sendBehavioralMetric, BEHAVIORAL_METRICS.NO_VIDEO_ENCODED);
|
|
1396
|
+
});
|
|
1332
1397
|
});
|
|
1333
1398
|
});
|
|
1334
1399
|
describe('#acknowledge', () => {
|
|
@@ -3605,14 +3670,17 @@ describe('plugin-meetings', () => {
|
|
|
3605
3670
|
describe('#setUpLocusServicesListener', () => {
|
|
3606
3671
|
it('listens to the locus services update event', (done) => {
|
|
3607
3672
|
const newLocusServices = {
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
}
|
|
3673
|
+
services: {
|
|
3674
|
+
record: {
|
|
3675
|
+
url: 'url',
|
|
3612
3676
|
},
|
|
3677
|
+
},
|
|
3613
3678
|
};
|
|
3614
3679
|
|
|
3615
|
-
meeting.recordingController = {
|
|
3680
|
+
meeting.recordingController = {
|
|
3681
|
+
setServiceUrl: sinon.stub().returns(undefined),
|
|
3682
|
+
setSessionId: sinon.stub().returns(undefined),
|
|
3683
|
+
};
|
|
3616
3684
|
|
|
3617
3685
|
meeting.locusInfo.emit(
|
|
3618
3686
|
{function: 'test', file: 'test'},
|
|
@@ -3620,7 +3688,10 @@ describe('plugin-meetings', () => {
|
|
|
3620
3688
|
newLocusServices
|
|
3621
3689
|
);
|
|
3622
3690
|
|
|
3623
|
-
assert.calledWith(
|
|
3691
|
+
assert.calledWith(
|
|
3692
|
+
meeting.recordingController.setServiceUrl,
|
|
3693
|
+
newLocusServices.services.record.url
|
|
3694
|
+
);
|
|
3624
3695
|
assert.calledOnce(meeting.recordingController.setSessionId);
|
|
3625
3696
|
done();
|
|
3626
3697
|
});
|
|
@@ -41,88 +41,92 @@ describe('Roap', () => {
|
|
|
41
41
|
describe('sendRoapMediaRequest', () => {
|
|
42
42
|
let sendRoapStub;
|
|
43
43
|
let roapHandlerSubmitStub;
|
|
44
|
-
|
|
45
|
-
const meeting = {
|
|
46
|
-
id: 'some meeting id',
|
|
47
|
-
correlationId: 'correlation id',
|
|
48
|
-
selfUrl: 'self url',
|
|
49
|
-
mediaId: 'media id',
|
|
50
|
-
audio:{
|
|
51
|
-
isLocallyMuted: () => true,
|
|
52
|
-
},
|
|
53
|
-
video:{
|
|
54
|
-
isLocallyMuted: () => false,
|
|
55
|
-
},
|
|
56
|
-
setRoapSeq: sinon.stub(),
|
|
57
|
-
config: {experimental: {enableTurnDiscovery: false}},
|
|
58
|
-
};
|
|
44
|
+
let meeting;
|
|
59
45
|
|
|
60
46
|
beforeEach(() => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
47
|
+
meeting = {
|
|
48
|
+
id: 'some meeting id',
|
|
49
|
+
correlationId: 'correlation id',
|
|
50
|
+
selfUrl: 'self url',
|
|
51
|
+
mediaId: 'media id',
|
|
52
|
+
audio: {
|
|
53
|
+
isLocallyMuted: () => true,
|
|
54
|
+
},
|
|
55
|
+
video: {
|
|
56
|
+
isLocallyMuted: () => false,
|
|
57
|
+
},
|
|
58
|
+
setRoapSeq: sinon.stub(),
|
|
59
|
+
config: {experimental: {enableTurnDiscovery: false}},
|
|
60
|
+
webex: {meetings: {reachability: {isAnyClusterReachable: () => true}}},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
sendRoapStub = sinon.stub(RoapRequest.prototype, 'sendRoap').resolves({});
|
|
65
|
+
roapHandlerSubmitStub = sinon.stub(RoapHandler.prototype, 'submit');
|
|
66
|
+
meeting.setRoapSeq.resetHistory();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
afterEach(() => {
|
|
70
|
+
sinon.restore();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
[
|
|
74
|
+
{reconnect: true, turnDiscoverySkipped: false, expectEmptyMediaId: false},
|
|
75
|
+
{reconnect: true, turnDiscoverySkipped: true, expectEmptyMediaId: true},
|
|
76
|
+
{reconnect: false, turnDiscoverySkipped: false, expectEmptyMediaId: false},
|
|
77
|
+
{reconnect: false, turnDiscoverySkipped: true, expectEmptyMediaId: false},
|
|
78
|
+
].forEach(({reconnect, turnDiscoverySkipped, expectEmptyMediaId}) =>
|
|
79
|
+
it(`sends roap OFFER with ${expectEmptyMediaId ? 'empty ' : ''}mediaId when ${
|
|
80
|
+
reconnect ? '' : 'not '
|
|
81
|
+
}reconnecting and TURN discovery is ${
|
|
82
|
+
turnDiscoverySkipped ? 'skipped' : 'not skipped'
|
|
83
|
+
}`, async () => {
|
|
84
|
+
const roap = new Roap({}, {parent: 'fake'});
|
|
85
|
+
|
|
86
|
+
sinon.stub(roap.turnDiscovery, 'isSkipped').resolves(turnDiscoverySkipped);
|
|
87
|
+
|
|
88
|
+
await roap.sendRoapMediaRequest({
|
|
89
|
+
meeting,
|
|
90
|
+
sdp: 'sdp',
|
|
91
|
+
reconnect,
|
|
92
|
+
roapSeq: 1,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const expectedRoapMessage = {
|
|
96
|
+
messageType: 'OFFER',
|
|
97
|
+
sdps: ['sdp'],
|
|
98
|
+
version: '2',
|
|
99
|
+
seq: 2,
|
|
100
|
+
tieBreaker: 4294967294,
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
assert.calledOnce(sendRoapStub);
|
|
104
|
+
assert.calledWith(sendRoapStub, {
|
|
105
|
+
roapMessage: expectedRoapMessage,
|
|
106
|
+
correlationId: meeting.correlationId,
|
|
107
|
+
locusSelfUrl: meeting.selfUrl,
|
|
108
|
+
mediaId: expectEmptyMediaId ? '' : meeting.mediaId,
|
|
109
|
+
audioMuted: meeting.audio?.isLocallyMuted(),
|
|
110
|
+
videoMuted: meeting.video?.isLocallyMuted(),
|
|
111
|
+
meetingId: meeting.id,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
assert.calledTwice(roapHandlerSubmitStub);
|
|
115
|
+
assert.calledWith(roapHandlerSubmitStub, {
|
|
116
|
+
type: ROAP.SEND_ROAP_MSG,
|
|
117
|
+
msg: expectedRoapMessage,
|
|
118
|
+
correlationId: meeting.correlationId,
|
|
119
|
+
});
|
|
120
|
+
assert.calledWith(roapHandlerSubmitStub, {
|
|
121
|
+
type: ROAP.SEND_ROAP_MSG_SUCCESS,
|
|
122
|
+
seq: 2,
|
|
123
|
+
correlationId: meeting.correlationId,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
assert.calledOnce(meeting.setRoapSeq);
|
|
127
|
+
assert.calledWith(meeting.setRoapSeq, 2);
|
|
128
|
+
})
|
|
129
|
+
);
|
|
64
130
|
});
|
|
65
|
-
|
|
66
|
-
afterEach(() => {
|
|
67
|
-
sinon.restore();
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
[
|
|
71
|
-
{reconnect: true, enableTurnDiscovery: true, expectEmptyMediaId: false},
|
|
72
|
-
{reconnect: true, enableTurnDiscovery: false, expectEmptyMediaId: true},
|
|
73
|
-
{reconnect: false, enableTurnDiscovery: true, expectEmptyMediaId: false},
|
|
74
|
-
{reconnect: false, enableTurnDiscovery: false, expectEmptyMediaId: false},
|
|
75
|
-
].forEach(({reconnect, enableTurnDiscovery, expectEmptyMediaId}) =>
|
|
76
|
-
it(`sends roap OFFER with ${expectEmptyMediaId ? 'empty ' : ''}mediaId when ${
|
|
77
|
-
reconnect ? '' : 'not '
|
|
78
|
-
}reconnecting and TURN discovery is ${
|
|
79
|
-
enableTurnDiscovery ? 'enabled' : 'disabled'
|
|
80
|
-
}`, async () => {
|
|
81
|
-
meeting.config.experimental.enableTurnDiscovery = enableTurnDiscovery;
|
|
82
|
-
|
|
83
|
-
const roap = new Roap({}, {parent: 'fake'});
|
|
84
|
-
|
|
85
|
-
await roap.sendRoapMediaRequest({
|
|
86
|
-
meeting,
|
|
87
|
-
sdp: 'sdp',
|
|
88
|
-
reconnect,
|
|
89
|
-
roapSeq: 1,
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
const expectedRoapMessage = {
|
|
93
|
-
messageType: 'OFFER',
|
|
94
|
-
sdps: ['sdp'],
|
|
95
|
-
version: '2',
|
|
96
|
-
seq: 2,
|
|
97
|
-
tieBreaker: 4294967294,
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
assert.calledOnce(sendRoapStub);
|
|
101
|
-
assert.calledWith(sendRoapStub, {
|
|
102
|
-
roapMessage: expectedRoapMessage,
|
|
103
|
-
correlationId: meeting.correlationId,
|
|
104
|
-
locusSelfUrl: meeting.selfUrl,
|
|
105
|
-
mediaId: expectEmptyMediaId ? '' : meeting.mediaId,
|
|
106
|
-
audioMuted: meeting.audio?.isLocallyMuted(),
|
|
107
|
-
videoMuted: meeting.video?.isLocallyMuted(),
|
|
108
|
-
meetingId: meeting.id,
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
assert.calledTwice(roapHandlerSubmitStub);
|
|
112
|
-
assert.calledWith(roapHandlerSubmitStub, {
|
|
113
|
-
type: ROAP.SEND_ROAP_MSG,
|
|
114
|
-
msg: expectedRoapMessage,
|
|
115
|
-
correlationId: meeting.correlationId,
|
|
116
|
-
});
|
|
117
|
-
assert.calledWith(roapHandlerSubmitStub, {
|
|
118
|
-
type: ROAP.SEND_ROAP_MSG_SUCCESS,
|
|
119
|
-
seq: 2,
|
|
120
|
-
correlationId: meeting.correlationId,
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
assert.calledOnce(meeting.setRoapSeq);
|
|
124
|
-
assert.calledWith(meeting.setRoapSeq, 2);
|
|
125
|
-
})
|
|
126
|
-
);
|
|
127
131
|
});
|
|
128
132
|
});
|
|
@@ -352,6 +352,27 @@ describe('TurnDiscovery', () => {
|
|
|
352
352
|
});
|
|
353
353
|
});
|
|
354
354
|
|
|
355
|
+
describe('isSkipped', () => {
|
|
356
|
+
[
|
|
357
|
+
{enabledInConfig: true, isAnyClusterReachable: true, expectedIsSkipped: true},
|
|
358
|
+
{enabledInConfig: true, isAnyClusterReachable: false, expectedIsSkipped: false},
|
|
359
|
+
{enabledInConfig: false, isAnyClusterReachable: true, expectedIsSkipped: true},
|
|
360
|
+
{enabledInConfig: false, isAnyClusterReachable: false, expectedIsSkipped: true},
|
|
361
|
+
].forEach(({enabledInConfig, isAnyClusterReachable, expectedIsSkipped}) => {
|
|
362
|
+
it(`returns ${expectedIsSkipped} when TURN discovery is ${enabledInConfig ? '' : 'not '} enabled in config and isAnyClusterReachable() returns ${isAnyClusterReachable ? 'true' : 'false'}`, async () => {
|
|
363
|
+
testMeeting.config.experimental.enableTurnDiscovery = enabledInConfig;
|
|
364
|
+
|
|
365
|
+
sinon.stub(testMeeting.webex.meetings.reachability, 'isAnyClusterReachable').resolves(isAnyClusterReachable);
|
|
366
|
+
|
|
367
|
+
const td = new TurnDiscovery(mockRoapRequest);
|
|
368
|
+
|
|
369
|
+
const isSkipped = await td.isSkipped(testMeeting);
|
|
370
|
+
|
|
371
|
+
assert.equal(isSkipped, expectedIsSkipped);
|
|
372
|
+
})
|
|
373
|
+
})
|
|
374
|
+
})
|
|
375
|
+
|
|
355
376
|
describe('handleTurnDiscoveryResponse', () => {
|
|
356
377
|
it("doesn't do anything if turn discovery was not started", () => {
|
|
357
378
|
const td = new TurnDiscovery(mockRoapRequest);
|
|
@@ -82,6 +82,22 @@ describe('plugin-meetings', () => {
|
|
|
82
82
|
let pc;
|
|
83
83
|
let networkQualityMonitor;
|
|
84
84
|
let statsAnalyzer;
|
|
85
|
+
const statusResultOutboundRTP = {
|
|
86
|
+
type: 'outbound-rtp',
|
|
87
|
+
frameHeight: 720,
|
|
88
|
+
frameWidth: 1280,
|
|
89
|
+
packetsLost: 11,
|
|
90
|
+
framesSent: 105,
|
|
91
|
+
hugeFramesSent: 1,
|
|
92
|
+
framesEncoded: 102,
|
|
93
|
+
rttThreshold: 501,
|
|
94
|
+
jitterThreshold: 501,
|
|
95
|
+
jitterBufferDelay: 288.131459,
|
|
96
|
+
jitterBufferEmittedCount: 4013,
|
|
97
|
+
trackIdentifier: '6bbf5506-6a7e-4397-951c-c05b72ab0ace',
|
|
98
|
+
bytesSent: 1233,
|
|
99
|
+
totalPacketsSent: 100,
|
|
100
|
+
};
|
|
85
101
|
|
|
86
102
|
let receivedEventsData = {
|
|
87
103
|
local: {},
|
|
@@ -177,6 +193,12 @@ describe('plugin-meetings', () => {
|
|
|
177
193
|
statsAnalyzer.on(EVENTS.REMOTE_MEDIA_STOPPED, (data) => {
|
|
178
194
|
receivedEventsData.remote.stopped = data;
|
|
179
195
|
});
|
|
196
|
+
statsAnalyzer.on(EVENTS.NO_FRAMES_SENT, (data) => {
|
|
197
|
+
receivedEventsData.noFramesSent = data;
|
|
198
|
+
});
|
|
199
|
+
statsAnalyzer.on(EVENTS.NO_VIDEO_ENCODED, (data) => {
|
|
200
|
+
receivedEventsData.noVideoEncoded = data;
|
|
201
|
+
});
|
|
180
202
|
});
|
|
181
203
|
|
|
182
204
|
afterEach(() => {
|
|
@@ -282,6 +304,135 @@ describe('plugin-meetings', () => {
|
|
|
282
304
|
|
|
283
305
|
checkReceivedEvent({expected: {remote: {stopped: {type: 'video'}}}});
|
|
284
306
|
});
|
|
307
|
+
|
|
308
|
+
const checkStats = (type) => {
|
|
309
|
+
const statsResult = {
|
|
310
|
+
height: 720,
|
|
311
|
+
width: 1280,
|
|
312
|
+
jitterBufferDelay: 288.131459,
|
|
313
|
+
jitterBufferEmittedCount: 4013,
|
|
314
|
+
trackIdentifier: '6bbf5506-6a7e-4397-951c-c05b72ab0ace',
|
|
315
|
+
avgJitterDelay: 0.07179951632195365,
|
|
316
|
+
};
|
|
317
|
+
if (type === 'inbound-rtp') {
|
|
318
|
+
statsResult.framesDecoded = 4013;
|
|
319
|
+
statsResult.framesDropped = 0;
|
|
320
|
+
statsResult.framesReceived = 4016;
|
|
321
|
+
assert.deepEqual(statsAnalyzer.statsResults.resolutions.video.recv, statsResult);
|
|
322
|
+
} else if (type === 'outbound-rtp') {
|
|
323
|
+
statsResult.framesSent = 105;
|
|
324
|
+
statsResult.hugeFramesSent = 1;
|
|
325
|
+
assert.deepEqual(statsAnalyzer.statsResults.resolutions.video.send, statsResult);
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
it('processes track results and populate statsResults.resolutions object when type is inbound-rtp with video', async () => {
|
|
330
|
+
await startStatsAnalyzer({expected: {receiveVideo: true}});
|
|
331
|
+
const statusResultInboundRTP = {
|
|
332
|
+
type: 'inbound-rtp',
|
|
333
|
+
frameHeight: 720,
|
|
334
|
+
frameWidth: 1280,
|
|
335
|
+
packetsLost: 11,
|
|
336
|
+
rttThreshold: 501,
|
|
337
|
+
jitterThreshold: 501,
|
|
338
|
+
framesDecoded: 4013,
|
|
339
|
+
framesDropped: 0,
|
|
340
|
+
framesReceived: 4016,
|
|
341
|
+
jitterBufferDelay: 288.131459,
|
|
342
|
+
jitterBufferEmittedCount: 4013,
|
|
343
|
+
trackIdentifier: '6bbf5506-6a7e-4397-951c-c05b72ab0ace',
|
|
344
|
+
};
|
|
345
|
+
await statsAnalyzer.parseGetStatsResult(statusResultInboundRTP, 'video');
|
|
346
|
+
checkStats('inbound-rtp');
|
|
347
|
+
});
|
|
348
|
+
it('processes track results and populate statsResults.resolutions object when type is outbound-rtp with video', async () => {
|
|
349
|
+
await startStatsAnalyzer({expected: {receiveVideo: true}});
|
|
350
|
+
|
|
351
|
+
await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'video');
|
|
352
|
+
checkStats('outbound-rtp');
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it('doesnot processes track results with audio', async () => {
|
|
356
|
+
await startStatsAnalyzer({expected: {receiveAudio: true}});
|
|
357
|
+
await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'audio');
|
|
358
|
+
assert.deepEqual(statsAnalyzer.statsResults.resolutions.audio, undefined);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it('emits NO_FRAMES_ENCODED when frames are not being encoded', async () => {
|
|
362
|
+
const expected = {mediaType: 'video'};
|
|
363
|
+
await startStatsAnalyzer({expected: {sendVideo: true}});
|
|
364
|
+
|
|
365
|
+
statsAnalyzer.lastStatsResults.video.send = {framesEncoded: 102, totalPacketsSent: 106};
|
|
366
|
+
|
|
367
|
+
await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'video');
|
|
368
|
+
|
|
369
|
+
statsAnalyzer.compareLastStatsResult();
|
|
370
|
+
assert.deepEqual(receivedEventsData.noVideoEncoded, expected);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it('emits NO_FRAMES_SENT when frames are not being sent but frames are being encoded', async () => {
|
|
374
|
+
await startStatsAnalyzer({expected: {sendVideo: true}});
|
|
375
|
+
|
|
376
|
+
const expected = {mediaType: 'video'};
|
|
377
|
+
|
|
378
|
+
statsAnalyzer.lastStatsResults.video.send = {
|
|
379
|
+
framesEncoded: 10,
|
|
380
|
+
framesSent: 105,
|
|
381
|
+
totalPacketsSent: 106,
|
|
382
|
+
};
|
|
383
|
+
await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'video');
|
|
384
|
+
|
|
385
|
+
statsAnalyzer.compareLastStatsResult();
|
|
386
|
+
assert.deepEqual(receivedEventsData.noFramesSent, expected);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('doesnot emits NO_FRAMES_SENT when last emitted event is LOCAL_MEDIA_STOPPED', async () => {
|
|
390
|
+
statsAnalyzer.lastEmittedStartStopEvent.video.local = EVENTS.LOCAL_MEDIA_STOPPED;
|
|
391
|
+
|
|
392
|
+
await startStatsAnalyzer({expected: {sendVideo: true}});
|
|
393
|
+
await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'video');
|
|
394
|
+
|
|
395
|
+
statsAnalyzer.compareLastStatsResult();
|
|
396
|
+
assert.deepEqual(receivedEventsData.noFramesSent, undefined);
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
it('emits NO_FRAMES_ENCODED when frames are not being encoded for share', async () => {
|
|
400
|
+
const expected = {mediaType: 'share'};
|
|
401
|
+
await startStatsAnalyzer({expected: {sendShare: true}});
|
|
402
|
+
|
|
403
|
+
statsAnalyzer.lastStatsResults.share.send = {framesEncoded: 102, totalPacketsSent: 106};
|
|
404
|
+
|
|
405
|
+
await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'share');
|
|
406
|
+
|
|
407
|
+
statsAnalyzer.compareLastStatsResult();
|
|
408
|
+
assert.deepEqual(receivedEventsData.noVideoEncoded, expected);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it('emits NO_FRAMES_SENT when frames are not being sent but frames are being encoded for share', async () => {
|
|
412
|
+
const expected = {mediaType: 'share'};
|
|
413
|
+
await startStatsAnalyzer({expected: {sendShare: true}});
|
|
414
|
+
|
|
415
|
+
statsAnalyzer.lastStatsResults.share.send = {
|
|
416
|
+
framesEncoded: 10,
|
|
417
|
+
framesSent: 105,
|
|
418
|
+
totalPacketsSent: 106,
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'share');
|
|
422
|
+
|
|
423
|
+
statsAnalyzer.compareLastStatsResult();
|
|
424
|
+
assert.deepEqual(receivedEventsData.noFramesSent, expected);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it('doesnot emits NO_FRAMES_SENT when last emitted event is LOCAL_MEDIA_STOPPED for share', async () => {
|
|
428
|
+
statsAnalyzer.lastEmittedStartStopEvent.video.local = EVENTS.LOCAL_MEDIA_STOPPED;
|
|
429
|
+
|
|
430
|
+
await startStatsAnalyzer({expected: {sendShare: true}});
|
|
431
|
+
await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'share');
|
|
432
|
+
|
|
433
|
+
statsAnalyzer.compareLastStatsResult();
|
|
434
|
+
assert.deepEqual(receivedEventsData.noFramesSent, undefined);
|
|
435
|
+
});
|
|
285
436
|
});
|
|
286
437
|
});
|
|
287
438
|
});
|