You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-07-31 15:24:23 +03:00
Add a few new GroupCall
tests (#2678)
Co-authored-by: Robin <robin@robin.town>
This commit is contained in:
@ -33,6 +33,7 @@ import { ReEmitter } from "../../src/ReEmitter";
|
|||||||
import { SyncState } from "../../src/sync";
|
import { SyncState } from "../../src/sync";
|
||||||
import { CallEvent, CallEventHandlerMap, MatrixCall } from "../../src/webrtc/call";
|
import { CallEvent, CallEventHandlerMap, MatrixCall } from "../../src/webrtc/call";
|
||||||
import { CallEventHandlerEvent, CallEventHandlerEventHandlerMap } from "../../src/webrtc/callEventHandler";
|
import { CallEventHandlerEvent, CallEventHandlerEventHandlerMap } from "../../src/webrtc/callEventHandler";
|
||||||
|
import { CallFeed } from "../../src/webrtc/callFeed";
|
||||||
import { GroupCallEventHandlerMap } from "../../src/webrtc/groupCall";
|
import { GroupCallEventHandlerMap } from "../../src/webrtc/groupCall";
|
||||||
import { GroupCallEventHandlerEvent } from "../../src/webrtc/groupCallEventHandler";
|
import { GroupCallEventHandlerEvent } from "../../src/webrtc/groupCallEventHandler";
|
||||||
import { IScreensharingOpts, MediaHandler } from "../../src/webrtc/mediaHandler";
|
import { IScreensharingOpts, MediaHandler } from "../../src/webrtc/mediaHandler";
|
||||||
@ -384,6 +385,20 @@ export class MockCallMatrixClient extends TypedEventEmitter<EmittedEvents, Emitt
|
|||||||
typed(): MatrixClient { return this as unknown as MatrixClient; }
|
typed(): MatrixClient { return this as unknown as MatrixClient; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class MockCallFeed {
|
||||||
|
constructor(
|
||||||
|
public userId: string,
|
||||||
|
public stream: MockMediaStream,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
measureVolumeActivity(val: boolean) {}
|
||||||
|
dispose() {}
|
||||||
|
|
||||||
|
typed(): CallFeed {
|
||||||
|
return this as unknown as CallFeed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function installWebRTCMocks() {
|
export function installWebRTCMocks() {
|
||||||
global.navigator = {
|
global.navigator = {
|
||||||
mediaDevices: new MockMediaDevices().typed(),
|
mediaDevices: new MockMediaDevices().typed(),
|
||||||
|
@ -27,6 +27,7 @@ import { GroupCall, GroupCallEvent } from "../../../src/webrtc/groupCall";
|
|||||||
import { MatrixClient } from "../../../src/client";
|
import { MatrixClient } from "../../../src/client";
|
||||||
import {
|
import {
|
||||||
installWebRTCMocks,
|
installWebRTCMocks,
|
||||||
|
MockCallFeed,
|
||||||
MockCallMatrixClient,
|
MockCallMatrixClient,
|
||||||
MockMediaStream,
|
MockMediaStream,
|
||||||
MockMediaStreamTrack,
|
MockMediaStreamTrack,
|
||||||
@ -115,6 +116,8 @@ class MockCall {
|
|||||||
setAudioVideoMuted: jest.fn<void, [boolean, boolean]>(),
|
setAudioVideoMuted: jest.fn<void, [boolean, boolean]>(),
|
||||||
stream: new MockMediaStream("stream"),
|
stream: new MockMediaStream("stream"),
|
||||||
};
|
};
|
||||||
|
public remoteUsermediaFeed: CallFeed;
|
||||||
|
public remoteScreensharingFeed: CallFeed;
|
||||||
|
|
||||||
public reject = jest.fn<void, []>();
|
public reject = jest.fn<void, []>();
|
||||||
public answerWithCallFeeds = jest.fn<void, [CallFeed[]]>();
|
public answerWithCallFeeds = jest.fn<void, [CallFeed[]]>();
|
||||||
@ -157,6 +160,14 @@ describe('Group Call', function() {
|
|||||||
groupCall = new GroupCall(mockClient, room, GroupCallType.Video, false, GroupCallIntent.Prompt);
|
groupCall = new GroupCall(mockClient, room, GroupCallType.Video, false, GroupCallIntent.Prompt);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not initialize local call feed, if it already is", async () => {
|
||||||
|
await groupCall.initLocalCallFeed();
|
||||||
|
jest.spyOn(groupCall, "initLocalCallFeed");
|
||||||
|
await groupCall.enter();
|
||||||
|
|
||||||
|
expect(groupCall.initLocalCallFeed).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it("sends state event to room when creating", async () => {
|
it("sends state event to room when creating", async () => {
|
||||||
await groupCall.create();
|
await groupCall.create();
|
||||||
|
|
||||||
@ -280,6 +291,119 @@ describe('Group Call', function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("call feeds changing", () => {
|
||||||
|
let call: MockCall;
|
||||||
|
const currentFeed = new MockCallFeed(FAKE_USER_ID_1, new MockMediaStream("current"));
|
||||||
|
const newFeed = new MockCallFeed(FAKE_USER_ID_1, new MockMediaStream("new"));
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
jest.spyOn(currentFeed, "dispose");
|
||||||
|
jest.spyOn(newFeed, "measureVolumeActivity");
|
||||||
|
|
||||||
|
jest.spyOn(groupCall, "emit");
|
||||||
|
|
||||||
|
call = new MockCall(room.roomId, groupCall.groupCallId);
|
||||||
|
|
||||||
|
await groupCall.create();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ignores changes, if we can't get user id of opponent", async () => {
|
||||||
|
const call = new MockCall(room.roomId, groupCall.groupCallId);
|
||||||
|
jest.spyOn(call, "getOpponentMember").mockReturnValue({ userId: undefined });
|
||||||
|
|
||||||
|
// @ts-ignore Mock
|
||||||
|
expect(() => groupCall.onCallFeedsChanged(call)).toThrowError();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("usermedia feeds", () => {
|
||||||
|
it("adds new usermedia feed", async () => {
|
||||||
|
call.remoteUsermediaFeed = newFeed.typed();
|
||||||
|
// @ts-ignore Mock
|
||||||
|
groupCall.onCallFeedsChanged(call);
|
||||||
|
|
||||||
|
expect(groupCall.userMediaFeeds).toStrictEqual([newFeed]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("replaces usermedia feed", async () => {
|
||||||
|
groupCall.userMediaFeeds = [currentFeed.typed()];
|
||||||
|
|
||||||
|
call.remoteUsermediaFeed = newFeed.typed();
|
||||||
|
// @ts-ignore Mock
|
||||||
|
groupCall.onCallFeedsChanged(call);
|
||||||
|
|
||||||
|
expect(groupCall.userMediaFeeds).toStrictEqual([newFeed]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("removes usermedia feed", async () => {
|
||||||
|
groupCall.userMediaFeeds = [currentFeed.typed()];
|
||||||
|
|
||||||
|
// @ts-ignore Mock
|
||||||
|
groupCall.onCallFeedsChanged(call);
|
||||||
|
|
||||||
|
expect(groupCall.userMediaFeeds).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("screenshare feeds", () => {
|
||||||
|
it("adds new screenshare feed", async () => {
|
||||||
|
call.remoteScreensharingFeed = newFeed.typed();
|
||||||
|
// @ts-ignore Mock
|
||||||
|
groupCall.onCallFeedsChanged(call);
|
||||||
|
|
||||||
|
expect(groupCall.screenshareFeeds).toStrictEqual([newFeed]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("replaces screenshare feed", async () => {
|
||||||
|
groupCall.screenshareFeeds = [currentFeed.typed()];
|
||||||
|
|
||||||
|
call.remoteScreensharingFeed = newFeed.typed();
|
||||||
|
// @ts-ignore Mock
|
||||||
|
groupCall.onCallFeedsChanged(call);
|
||||||
|
|
||||||
|
expect(groupCall.screenshareFeeds).toStrictEqual([newFeed]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("removes screenshare feed", async () => {
|
||||||
|
groupCall.screenshareFeeds = [currentFeed.typed()];
|
||||||
|
|
||||||
|
// @ts-ignore Mock
|
||||||
|
groupCall.onCallFeedsChanged(call);
|
||||||
|
|
||||||
|
expect(groupCall.screenshareFeeds).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("feed replacing", () => {
|
||||||
|
it("replaces usermedia feed", async () => {
|
||||||
|
groupCall.userMediaFeeds = [currentFeed.typed()];
|
||||||
|
|
||||||
|
// @ts-ignore Mock
|
||||||
|
groupCall.replaceUserMediaFeed(currentFeed, newFeed);
|
||||||
|
|
||||||
|
const newFeeds = [newFeed];
|
||||||
|
|
||||||
|
expect(groupCall.userMediaFeeds).toStrictEqual(newFeeds);
|
||||||
|
expect(currentFeed.dispose).toHaveBeenCalled();
|
||||||
|
expect(newFeed.measureVolumeActivity).toHaveBeenCalledWith(true);
|
||||||
|
expect(groupCall.emit).toHaveBeenCalledWith(GroupCallEvent.UserMediaFeedsChanged, newFeeds);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("replaces screenshare feed", async () => {
|
||||||
|
groupCall.screenshareFeeds = [currentFeed.typed()];
|
||||||
|
|
||||||
|
// @ts-ignore Mock
|
||||||
|
groupCall.replaceScreenshareFeed(currentFeed, newFeed);
|
||||||
|
|
||||||
|
const newFeeds = [newFeed];
|
||||||
|
|
||||||
|
expect(groupCall.screenshareFeeds).toStrictEqual(newFeeds);
|
||||||
|
expect(currentFeed.dispose).toHaveBeenCalled();
|
||||||
|
expect(newFeed.measureVolumeActivity).toHaveBeenCalledWith(true);
|
||||||
|
expect(groupCall.emit).toHaveBeenCalledWith(GroupCallEvent.ScreenshareFeedsChanged, newFeeds);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("PTT calls", () => {
|
describe("PTT calls", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
// replace groupcall with a PTT one
|
// replace groupcall with a PTT one
|
||||||
@ -801,6 +925,19 @@ describe('Group Call', function() {
|
|||||||
expect(newMockCall.answerWithCallFeeds).toHaveBeenCalled();
|
expect(newMockCall.answerWithCallFeeds).toHaveBeenCalled();
|
||||||
expect(groupCall.calls).toEqual([newMockCall]);
|
expect(groupCall.calls).toEqual([newMockCall]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("starts to process incoming calls when we've entered", async () => {
|
||||||
|
// First we leave the call since we have already entered
|
||||||
|
groupCall.leave();
|
||||||
|
|
||||||
|
const call = new MockCall(room.roomId, groupCall.groupCallId);
|
||||||
|
mockClient.callEventHandler.calls = new Map<string, MatrixCall>([
|
||||||
|
[call.callId, call.typed()],
|
||||||
|
]);
|
||||||
|
await groupCall.enter();
|
||||||
|
|
||||||
|
expect(call.answerWithCallFeeds).toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("screensharing", () => {
|
describe("screensharing", () => {
|
||||||
@ -885,10 +1022,29 @@ describe('Group Call', function() {
|
|||||||
]));
|
]));
|
||||||
|
|
||||||
expect(groupCall.screenshareFeeds).toHaveLength(1);
|
expect(groupCall.screenshareFeeds).toHaveLength(1);
|
||||||
expect(groupCall.getScreenshareFeedByUserId(call.invitee)).toBeDefined();
|
expect(groupCall.getScreenshareFeedByUserId(call.invitee!)).toBeDefined();
|
||||||
|
|
||||||
groupCall.terminate();
|
groupCall.terminate();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("cleans up screensharing when terminating", async () => {
|
||||||
|
// @ts-ignore Mock
|
||||||
|
jest.spyOn(groupCall, "removeScreenshareFeed");
|
||||||
|
jest.spyOn(mockClient.getMediaHandler(), "stopScreensharingStream");
|
||||||
|
|
||||||
|
await groupCall.setScreensharingEnabled(true);
|
||||||
|
|
||||||
|
const screensharingFeed = groupCall.localScreenshareFeed;
|
||||||
|
|
||||||
|
groupCall.terminate();
|
||||||
|
|
||||||
|
expect(mockClient.getMediaHandler()!.stopScreensharingStream).toHaveBeenCalledWith(
|
||||||
|
screensharingFeed!.stream,
|
||||||
|
);
|
||||||
|
// @ts-ignore Mock
|
||||||
|
expect(groupCall.removeScreenshareFeed).toHaveBeenCalledWith(screensharingFeed);
|
||||||
|
expect(groupCall.localScreenshareFeed).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("active speaker events", () => {
|
describe("active speaker events", () => {
|
||||||
|
Reference in New Issue
Block a user