@webex/plugin-meetings 2.59.2 → 2.59.3
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/constants.d.ts +2 -0
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -1
- package/dist/meeting/index.js +32 -15
- package/dist/meeting/index.js.map +1 -1
- package/dist/metrics/constants.d.ts +2 -0
- package/dist/metrics/constants.js +2 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/statsAnalyzer/global.d.ts +2 -0
- package/dist/statsAnalyzer/global.js +4 -2
- package/dist/statsAnalyzer/global.js.map +1 -1
- package/dist/statsAnalyzer/index.d.ts +2 -0
- package/dist/statsAnalyzer/index.js +43 -3
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/package.json +19 -19
- package/src/constants.ts +2 -0
- package/src/meeting/index.ts +29 -0
- package/src/metrics/constants.ts +2 -0
- package/src/statsAnalyzer/global.ts +2 -0
- package/src/statsAnalyzer/index.ts +69 -5
- package/test/unit/spec/meeting/index.js +77 -6
- package/test/unit/spec/stats-analyzer/index.js +101 -18
|
@@ -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',
|
|
@@ -517,7 +519,7 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
517
519
|
|
|
518
520
|
if (currentValue - previousValue > 0) {
|
|
519
521
|
newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STARTED : EVENTS.REMOTE_MEDIA_STARTED;
|
|
520
|
-
} else if (currentValue === previousValue && currentValue
|
|
522
|
+
} else if (currentValue === previousValue && currentValue >= 0) {
|
|
521
523
|
newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STOPPED : EVENTS.REMOTE_MEDIA_STOPPED;
|
|
522
524
|
}
|
|
523
525
|
|
|
@@ -632,14 +634,25 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
632
634
|
LoggerProxy.logger.info(
|
|
633
635
|
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets sent`
|
|
634
636
|
);
|
|
635
|
-
} else {
|
|
637
|
+
} else if (this.lastEmittedStartStopEvent[mediaType].local !== EVENTS.LOCAL_MEDIA_STOPPED) {
|
|
636
638
|
if (
|
|
637
639
|
currentStats.framesEncoded === previousStats.framesEncoded ||
|
|
638
640
|
currentStats.framesEncoded === 0
|
|
639
641
|
) {
|
|
642
|
+
this.lastEmittedStartStopEvent[mediaType].local = EVENTS.NO_VIDEO_ENCODED;
|
|
640
643
|
LoggerProxy.logger.info(
|
|
641
644
|
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} Frames Encoded`
|
|
642
645
|
);
|
|
646
|
+
this.emit(
|
|
647
|
+
{
|
|
648
|
+
file: 'statsAnalyzer',
|
|
649
|
+
function: 'compareLastStatsResult',
|
|
650
|
+
},
|
|
651
|
+
EVENTS.NO_VIDEO_ENCODED,
|
|
652
|
+
{
|
|
653
|
+
mediaType,
|
|
654
|
+
}
|
|
655
|
+
);
|
|
643
656
|
}
|
|
644
657
|
|
|
645
658
|
if (
|
|
@@ -651,8 +664,28 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
651
664
|
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} Frames sent`
|
|
652
665
|
);
|
|
653
666
|
}
|
|
654
|
-
}
|
|
655
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
|
+
}
|
|
656
689
|
this.emitStartStopEvents(
|
|
657
690
|
mediaType,
|
|
658
691
|
previousStats.framesSent,
|
|
@@ -728,14 +761,25 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
728
761
|
LoggerProxy.logger.info(
|
|
729
762
|
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets sent`
|
|
730
763
|
);
|
|
731
|
-
} else {
|
|
764
|
+
} else if (this.lastEmittedStartStopEvent[mediaType].local !== EVENTS.LOCAL_MEDIA_STOPPED) {
|
|
732
765
|
if (
|
|
733
766
|
currentStats.framesEncoded === previousStats.framesEncoded ||
|
|
734
767
|
currentStats.framesEncoded === 0
|
|
735
768
|
) {
|
|
769
|
+
this.lastEmittedStartStopEvent[mediaType].local = EVENTS.NO_VIDEO_ENCODED;
|
|
736
770
|
LoggerProxy.logger.info(
|
|
737
771
|
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames getting encoded`
|
|
738
772
|
);
|
|
773
|
+
this.emit(
|
|
774
|
+
{
|
|
775
|
+
file: 'statsAnalyzer',
|
|
776
|
+
function: 'compareLastStatsResult',
|
|
777
|
+
},
|
|
778
|
+
EVENTS.NO_VIDEO_ENCODED,
|
|
779
|
+
{
|
|
780
|
+
mediaType,
|
|
781
|
+
}
|
|
782
|
+
);
|
|
739
783
|
}
|
|
740
784
|
|
|
741
785
|
if (
|
|
@@ -747,6 +791,27 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
747
791
|
`StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames sent`
|
|
748
792
|
);
|
|
749
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
|
+
}
|
|
750
815
|
}
|
|
751
816
|
|
|
752
817
|
// TODO:need to check receive share value
|
|
@@ -902,7 +967,6 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
902
967
|
|
|
903
968
|
this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
|
|
904
969
|
this.statsResults[mediaType].bytesSent = kilobytes;
|
|
905
|
-
|
|
906
970
|
this.statsResults[mediaType][sendrecvType].framesEncoded =
|
|
907
971
|
result.framesEncoded - this.statsResults.internal[mediaType][sendrecvType].framesEncoded;
|
|
908
972
|
this.statsResults[mediaType][sendrecvType].keyFramesEncoded =
|
|
@@ -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
|
});
|
|
@@ -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(() => {
|
|
@@ -325,31 +347,92 @@ describe('plugin-meetings', () => {
|
|
|
325
347
|
});
|
|
326
348
|
it('processes track results and populate statsResults.resolutions object when type is outbound-rtp with video', async () => {
|
|
327
349
|
await startStatsAnalyzer({expected: {receiveVideo: true}});
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
frameHeight: 720,
|
|
331
|
-
frameWidth: 1280,
|
|
332
|
-
packetsLost: 11,
|
|
333
|
-
framesSent: 105,
|
|
334
|
-
hugeFramesSent: 1,
|
|
335
|
-
rttThreshold: 501,
|
|
336
|
-
jitterThreshold: 501,
|
|
337
|
-
jitterBufferDelay: 288.131459,
|
|
338
|
-
jitterBufferEmittedCount: 4013,
|
|
339
|
-
trackIdentifier: '6bbf5506-6a7e-4397-951c-c05b72ab0ace',
|
|
340
|
-
};
|
|
341
|
-
await statsAnalyzer.parseGetStatsResult(statusResultInboundRTP, 'video');
|
|
350
|
+
|
|
351
|
+
await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'video');
|
|
342
352
|
checkStats('outbound-rtp');
|
|
343
353
|
});
|
|
344
354
|
|
|
345
355
|
it('doesnot processes track results with audio', async () => {
|
|
346
356
|
await startStatsAnalyzer({expected: {receiveAudio: true}});
|
|
347
|
-
|
|
348
|
-
type: 'outbound-rtp',
|
|
349
|
-
};
|
|
350
|
-
await statsAnalyzer.parseGetStatsResult(statusResultInboundRTP, 'audio');
|
|
357
|
+
await statsAnalyzer.parseGetStatsResult(statusResultOutboundRTP, 'audio');
|
|
351
358
|
assert.deepEqual(statsAnalyzer.statsResults.resolutions.audio, undefined);
|
|
352
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
|
+
});
|
|
353
436
|
});
|
|
354
437
|
});
|
|
355
438
|
});
|