mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-06-10 02:21:19 +03:00
* send expected peer connections to posthog. (based on roomState event) * add tests * change GroupCallStats initialized * prettier * more test and catch for promise * seperate the participant logic in a summary extend function Signed-off-by: Timo K <toger5@hotmail.de> * remove unused Signed-off-by: Timo K <toger5@hotmail.de> * rename summaryStatsReportGatherer to "Reporter" for the summary stats there is only one instance because there is only one summary. Since we dont have a list of gatherers it this class only reports. Hence we rename it to be a reporter. Signed-off-by: Timo K <toger5@hotmail.de> * review Signed-off-by: Timo K <toger5@hotmail.de> * Update src/webrtc/stats/groupCallStats.ts Co-authored-by: Robin <robin@robin.town> * revert rename Signed-off-by: Timo K <toger5@hotmail.de> * Update all non-major dependencies (#3433) * Update all non-major dependencies * Remove name wrap-ansi-cjs * Remove name string-width-cjs --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> * Update definitelyTyped (#3430) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> * Export FALLBACK_ICE_SERVER (#3429) * Add an integration test for verification (#3436) * Move existing crypto integ tests into a subdirectory * Factor out some common bits from `crypto.spec.ts` * Integration test for device verification * Ignore generated file in prettier * Always show a summary after Jest tests (#3440) ... because it is otherwise impossible to see what failed. * Use correct /v3 prefix for /refresh (#3016) * Add tests to ensure /v3/refresh is called + automatic /v1 retry * Request /refresh with v3 prefix, and quietly fall back to v1 * Add tests checking re-raising errors * Update spec/unit/login.spec.ts * Update comment Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> --------- Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> * Update Mutual Rooms (MSC2666) support (#3381) * update mutual rooms support * clarify docs and switch eslint comment with todo * please the holy linter * change query variable names around * add mock tests and fix issue * ye holy linter * GHA: build and cypress-test a copy of element-web after each push (#3412) * Build a copy of element-web after each push * Run cypress after each build of element-web * Fix downstream-artifacts build (#3443) * Fix downstream-artifacts build * Update cypress.yml * Fix edge cases around 2nd order relations and threads (#3437) * Fix tests oversimplifying threads fixtures * Check for unsigned thread_id in MatrixEvent::threadRootId * Fix threads order being racy * Make Sonar happier * Iterate * Make sliding sync linearize processing of sync requests (#3442) * Make sliding sync linearize processing of sync requests * Iterate * Iterate * Iterate * Iterate * Disable downstream artifacts build for develop branch (#3444) * Export thread-related types from SDK (#3447) * Export thread-related types from SDK * address PR feedback * Integration test for QR code verification (#3439) * Integration test for QR code verification Followup to https://github.com/matrix-org/matrix-js-sdk/pull/3436: another integration test, this time using the QR code flow * Use Object.defineProperty, and restore afterwards Apparently global.crypto exists in some environments * apply ts-ignore * remove stray comment * Update spec/integ/crypto/verification.spec.ts * Add `getShowSasCallbacks`, `getShowQrCodeCallbacks` to VerifierBase (#3422) * Add `getShowSasCallbacks`, `getShowQrCodeCallbacks` to VerifierBase ... to avoid some type-casting * Integration test for QR code verification Followup to https://github.com/matrix-org/matrix-js-sdk/pull/3436: another integration test, this time using the QR code flow * Rename method ... it turns out not to be used quite as I thought. * tests for new methods * Use Object.defineProperty, and restore afterwards Apparently global.crypto exists in some environments * apply ts-ignore * More test coverage * fix bad merge * Fix changelog_head.py script to be Python 3 compatible * Prepare changelog for v25.2.0-rc.1 * v25.2.0-rc.1 * Fix tsconfig-build.json * Prepare changelog for v25.2.0-rc.2 * v25.2.0-rc.2 * Fix docs deployment * Prepare changelog for v25.2.0-rc.3 * v25.2.0-rc.3 * Prepare changelog for v25.2.0-rc.4 * v25.2.0-rc.4 * [Backport staging] Attempt a potential workaround for stuck notifs (#3387) Co-authored-by: Andy Balaam <andy.balaam@matrix.org> * Prepare changelog for v25.2.0-rc.5 * v25.2.0-rc.5 * [Backport staging] Fix mark as unread button (#3401) Co-authored-by: Michael Weimann <michaelw@matrix.org> * Prepare changelog for v26.0.0-rc.1 * v26.0.0-rc.1 * Prepare changelog for v26.0.0 * v26.0.0 * Resetting package fields for development * use cli.canSupport to determine intentional mentions support (#3445) * use cli.canSupport to determine intentional mentions support * more specific comment * Update src/client.ts Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --------- Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> * git fixup Signed-off-by: Timo K <toger5@hotmail.de> * import updates Signed-off-by: Timo K <toger5@hotmail.de> * dont revert enricos change Signed-off-by: Timo K <toger5@hotmail.de> * temp rename for lowercase * lowercase --------- Signed-off-by: Timo K <toger5@hotmail.de> Co-authored-by: Robin <robin@robin.town> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Co-authored-by: David Lee <david@david-lee.net> Co-authored-by: Jonathan de Jong <jonathan@automatia.nl> Co-authored-by: Stanislav Demydiuk <stas-demydiuk@users.noreply.github.com> Co-authored-by: ElementRobot <releases@riot.im> Co-authored-by: Andy Balaam <andy.balaam@matrix.org> Co-authored-by: Michael Weimann <michaelw@matrix.org> Co-authored-by: Kerry <kerrya@element.io>
704 lines
26 KiB
TypeScript
704 lines
26 KiB
TypeScript
/*
|
|
Copyright 2023 The Matrix.org Foundation C.I.C.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
import { SummaryStatsReportGatherer } from "../../../../src/webrtc/stats/summaryStatsReportGatherer";
|
|
import { StatsReportEmitter } from "../../../../src/webrtc/stats/statsReportEmitter";
|
|
import { groupCallParticipantsFourOtherDevices } from "../../../test-utils/webrtc";
|
|
|
|
describe("SummaryStatsReportGatherer", () => {
|
|
let reporter: SummaryStatsReportGatherer;
|
|
let emitter: StatsReportEmitter;
|
|
beforeEach(() => {
|
|
emitter = new StatsReportEmitter();
|
|
emitter.emitSummaryStatsReport = jest.fn();
|
|
reporter = new SummaryStatsReportGatherer(emitter);
|
|
});
|
|
|
|
describe("build Summary Stats Report", () => {
|
|
it("should do nothing if summary list empty", async () => {
|
|
reporter.build([]);
|
|
expect(emitter.emitSummaryStatsReport).not.toHaveBeenCalled();
|
|
});
|
|
it("should do nothing if a summary stats element collection the is first time", async () => {
|
|
reporter.build([
|
|
{
|
|
isFirstCollection: true,
|
|
receivedMedia: 10,
|
|
receivedAudioMedia: 4,
|
|
receivedVideoMedia: 6,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 100,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
]);
|
|
expect(emitter.emitSummaryStatsReport).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("should trigger new summary report", async () => {
|
|
const summary = [
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 10,
|
|
receivedAudioMedia: 4,
|
|
receivedVideoMedia: 6,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 100,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 13,
|
|
receivedAudioMedia: 0,
|
|
receivedVideoMedia: 13,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 5,
|
|
totalAudio: 100,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 0,
|
|
receivedAudioMedia: 0,
|
|
receivedVideoMedia: 0,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 10,
|
|
totalAudio: 100,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 15,
|
|
receivedAudioMedia: 6,
|
|
receivedVideoMedia: 9,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 100,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
];
|
|
reporter.build(summary);
|
|
expect(emitter.emitSummaryStatsReport).toHaveBeenCalledWith({
|
|
percentageReceivedMedia: 0.5,
|
|
percentageReceivedAudioMedia: 0.5,
|
|
percentageReceivedVideoMedia: 0.75,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
peerConnections: 4,
|
|
percentageConcealedAudio: 0.0375,
|
|
});
|
|
});
|
|
|
|
it("as received video Media, although video was not received, but because video muted", async () => {
|
|
const summary = [
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 10,
|
|
receivedAudioMedia: 10,
|
|
receivedVideoMedia: 0,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 1,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
];
|
|
reporter.build(summary);
|
|
expect(emitter.emitSummaryStatsReport).toHaveBeenCalledWith({
|
|
percentageReceivedMedia: 1,
|
|
percentageReceivedAudioMedia: 1,
|
|
percentageReceivedVideoMedia: 1,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
peerConnections: 1,
|
|
percentageConcealedAudio: 0,
|
|
});
|
|
});
|
|
|
|
it("as received no video Media, because only on video was muted", async () => {
|
|
const summary = [
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 10,
|
|
receivedAudioMedia: 10,
|
|
receivedVideoMedia: 0,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 2,
|
|
muted: 1,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
];
|
|
reporter.build(summary);
|
|
expect(emitter.emitSummaryStatsReport).toHaveBeenCalledWith({
|
|
percentageReceivedMedia: 0,
|
|
percentageReceivedAudioMedia: 1,
|
|
percentageReceivedVideoMedia: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
peerConnections: 1,
|
|
percentageConcealedAudio: 0,
|
|
});
|
|
});
|
|
|
|
it("as received no audio Media, although audio not received and audio muted", async () => {
|
|
const summary = [
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 100,
|
|
receivedAudioMedia: 0,
|
|
receivedVideoMedia: 100,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 1,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
];
|
|
reporter.build(summary);
|
|
expect(emitter.emitSummaryStatsReport).toHaveBeenCalledWith({
|
|
percentageReceivedMedia: 0,
|
|
percentageReceivedAudioMedia: 0,
|
|
percentageReceivedVideoMedia: 1,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
peerConnections: 1,
|
|
percentageConcealedAudio: 0,
|
|
});
|
|
});
|
|
|
|
it("should find max jitter and max packet loss", async () => {
|
|
const summary = [
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 1,
|
|
receivedAudioMedia: 1,
|
|
receivedVideoMedia: 1,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 1,
|
|
receivedAudioMedia: 1,
|
|
receivedVideoMedia: 1,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 20,
|
|
maxPacketLoss: 5,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 1,
|
|
receivedAudioMedia: 1,
|
|
receivedVideoMedia: 1,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 5,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 5,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 1,
|
|
receivedAudioMedia: 1,
|
|
receivedVideoMedia: 1,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 5,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 40,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
];
|
|
reporter.build(summary);
|
|
expect(emitter.emitSummaryStatsReport).toHaveBeenCalledWith({
|
|
percentageReceivedMedia: 1,
|
|
percentageReceivedAudioMedia: 1,
|
|
percentageReceivedVideoMedia: 1,
|
|
maxJitter: 20,
|
|
maxPacketLoss: 40,
|
|
peerConnections: 4,
|
|
percentageConcealedAudio: 0,
|
|
});
|
|
});
|
|
|
|
it("as received video Media, if no audio track received should count as received Media", async () => {
|
|
const summary = [
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 10,
|
|
receivedAudioMedia: 0,
|
|
receivedVideoMedia: 10,
|
|
audioTrackSummary: {
|
|
count: 0,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
];
|
|
reporter.build(summary);
|
|
expect(emitter.emitSummaryStatsReport).toHaveBeenCalledWith({
|
|
percentageReceivedMedia: 1,
|
|
percentageReceivedAudioMedia: 1,
|
|
percentageReceivedVideoMedia: 1,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
peerConnections: 1,
|
|
percentageConcealedAudio: 0,
|
|
});
|
|
});
|
|
|
|
it("as received audio Media, if no video track received should count as received Media", async () => {
|
|
const summary = [
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 1,
|
|
receivedAudioMedia: 22,
|
|
receivedVideoMedia: 0,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 0,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
];
|
|
reporter.build(summary);
|
|
expect(emitter.emitSummaryStatsReport).toHaveBeenCalledWith({
|
|
percentageReceivedMedia: 1,
|
|
percentageReceivedAudioMedia: 1,
|
|
percentageReceivedVideoMedia: 1,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
peerConnections: 1,
|
|
percentageConcealedAudio: 0,
|
|
});
|
|
});
|
|
|
|
it("as received no media at all, as received Media", async () => {
|
|
const summary = [
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 0,
|
|
receivedAudioMedia: 0,
|
|
receivedVideoMedia: 0,
|
|
audioTrackSummary: {
|
|
count: 0,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 0,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
];
|
|
reporter.build(summary);
|
|
expect(emitter.emitSummaryStatsReport).toHaveBeenCalledWith({
|
|
percentageReceivedMedia: 1,
|
|
percentageReceivedAudioMedia: 1,
|
|
percentageReceivedVideoMedia: 1,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
peerConnections: 1,
|
|
percentageConcealedAudio: 0,
|
|
});
|
|
});
|
|
|
|
it("should filter the first time summery stats", async () => {
|
|
const summary = [
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 1,
|
|
receivedAudioMedia: 1,
|
|
receivedVideoMedia: 1,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
{
|
|
isFirstCollection: true,
|
|
receivedMedia: 1,
|
|
receivedAudioMedia: 1,
|
|
receivedVideoMedia: 1,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 20,
|
|
maxPacketLoss: 5,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 1,
|
|
receivedAudioMedia: 1,
|
|
receivedVideoMedia: 1,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 5,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 5,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 1,
|
|
receivedAudioMedia: 1,
|
|
receivedVideoMedia: 1,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 5,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 40,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
];
|
|
reporter.build(summary);
|
|
expect(emitter.emitSummaryStatsReport).toHaveBeenCalledWith({
|
|
percentageReceivedMedia: 1,
|
|
percentageReceivedAudioMedia: 1,
|
|
percentageReceivedVideoMedia: 1,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 40,
|
|
peerConnections: 4,
|
|
percentageConcealedAudio: 0,
|
|
});
|
|
});
|
|
it("should report missing peer connections", async () => {
|
|
const summary = [
|
|
{
|
|
isFirstCollection: true,
|
|
receivedMedia: 1,
|
|
receivedAudioMedia: 1,
|
|
receivedVideoMedia: 1,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 20,
|
|
maxPacketLoss: 5,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 0,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
{
|
|
isFirstCollection: false,
|
|
receivedMedia: 1,
|
|
receivedAudioMedia: 1,
|
|
receivedVideoMedia: 1,
|
|
audioTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 5,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
videoTrackSummary: {
|
|
count: 1,
|
|
muted: 0,
|
|
maxJitter: 0,
|
|
maxPacketLoss: 40,
|
|
concealedAudio: 0,
|
|
totalAudio: 0,
|
|
},
|
|
},
|
|
];
|
|
reporter.build(summary);
|
|
expect(emitter.emitSummaryStatsReport).toHaveBeenCalledWith({
|
|
percentageReceivedMedia: 1,
|
|
percentageReceivedAudioMedia: 1,
|
|
percentageReceivedVideoMedia: 1,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 40,
|
|
peerConnections: 2,
|
|
percentageConcealedAudio: 0,
|
|
});
|
|
});
|
|
});
|
|
describe("extend Summary Stats Report", () => {
|
|
it("should extend the report with the appropriate data based on a user map", async () => {
|
|
const summary = {
|
|
percentageReceivedMedia: 1,
|
|
percentageReceivedAudioMedia: 1,
|
|
percentageReceivedVideoMedia: 1,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 40,
|
|
peerConnections: 4,
|
|
percentageConcealedAudio: 0,
|
|
};
|
|
SummaryStatsReportGatherer.extendSummaryReport(summary, groupCallParticipantsFourOtherDevices);
|
|
expect(summary).toStrictEqual({
|
|
percentageReceivedMedia: 1,
|
|
percentageReceivedAudioMedia: 1,
|
|
percentageReceivedVideoMedia: 1,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 40,
|
|
peerConnections: 4,
|
|
percentageConcealedAudio: 0,
|
|
opponentUsersInCall: 1,
|
|
opponentDevicesInCall: 4,
|
|
diffDevicesToPeerConnections: 0,
|
|
ratioPeerConnectionToDevices: 1,
|
|
});
|
|
});
|
|
it("should extend the report data based on a user map", async () => {
|
|
const summary = {
|
|
percentageReceivedMedia: 1,
|
|
percentageReceivedAudioMedia: 1,
|
|
percentageReceivedVideoMedia: 1,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 40,
|
|
peerConnections: 4,
|
|
percentageConcealedAudio: 0,
|
|
};
|
|
SummaryStatsReportGatherer.extendSummaryReport(summary, new Map());
|
|
expect(summary).toStrictEqual({
|
|
percentageReceivedMedia: 1,
|
|
percentageReceivedAudioMedia: 1,
|
|
percentageReceivedVideoMedia: 1,
|
|
maxJitter: 2,
|
|
maxPacketLoss: 40,
|
|
peerConnections: 4,
|
|
percentageConcealedAudio: 0,
|
|
opponentUsersInCall: 0,
|
|
opponentDevicesInCall: 0,
|
|
diffDevicesToPeerConnections: -4,
|
|
ratioPeerConnectionToDevices: 0,
|
|
});
|
|
});
|
|
});
|
|
});
|