1
0
mirror of https://github.com/matrix-org/matrix-react-sdk.git synced 2025-07-28 15:22:05 +03:00

Use new matrixRTC calling (#11792)

* initial

Signed-off-by: Timo K <toger5@hotmail.de>

* cleanup1

Signed-off-by: Timo K <toger5@hotmail.de>

* bring back call timer

Signed-off-by: Timo K <toger5@hotmail.de>

* more cleanup and test removals

Signed-off-by: Timo K <toger5@hotmail.de>

* remove event

Signed-off-by: Timo K <toger5@hotmail.de>

* cleanups and minor fixes

Signed-off-by: Timo K <toger5@hotmail.de>

* add matrixRTC to stubClient

Signed-off-by: Timo K <toger5@hotmail.de>

* update tests (some got removed)
The removal is a consequence of EW now doing less call logic.
More logic is done by the js sdk (MatrixRTCSession)
And therefore in EC itself.

Signed-off-by: Timo K <toger5@hotmail.de>

* cleanups

Signed-off-by: Timo K <toger5@hotmail.de>

* mock the session

Signed-off-by: Timo K <toger5@hotmail.de>

* lint

Signed-off-by: Timo K <toger5@hotmail.de>

* remove GroupCallDuration

Signed-off-by: Timo K <toger5@hotmail.de>

* review and fixing tests

Signed-off-by: Timo K <toger5@hotmail.de>

---------

Signed-off-by: Timo K <toger5@hotmail.de>
This commit is contained in:
Timo
2023-10-30 16:14:27 +01:00
committed by GitHub
parent c4852dd216
commit 860764c057
13 changed files with 176 additions and 255 deletions

View File

@ -17,16 +17,14 @@ limitations under the License.
import EventEmitter from "events";
import { mocked } from "jest-mock";
import { waitFor } from "@testing-library/react";
import {
RoomType,
Room,
RoomEvent,
MatrixEvent,
RoomStateEvent,
PendingEventOrdering,
GroupCallIntent,
} from "matrix-js-sdk/src/matrix";
import { RoomType, Room, RoomEvent, MatrixEvent, RoomStateEvent, PendingEventOrdering } from "matrix-js-sdk/src/matrix";
import { Widget } from "matrix-widget-api";
// eslint-disable-next-line no-restricted-imports
import { MatrixRTCSessionManagerEvents } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSessionManager";
// eslint-disable-next-line no-restricted-imports
import { CallMembership } from "matrix-js-sdk/src/matrixrtc/CallMembership";
// eslint-disable-next-line no-restricted-imports
import { MatrixRTCSession, MatrixRTCSessionEvent } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import type { Mocked } from "jest-mock";
import type { MatrixClient, IMyDevice, RoomMember } from "matrix-js-sdk/src/matrix";
@ -96,9 +94,16 @@ const setUpClientRoomAndStores = (): {
return null;
}
});
jest.spyOn(room, "getMyMembership").mockReturnValue("join");
client.getRoom.mockImplementation((roomId) => (roomId === room.roomId ? room : null));
client.getRoom.mockImplementation((roomId) => (roomId === room.roomId ? room : null));
client.matrixRTC.getRoomSession.mockImplementation((roomId) => {
const session = new EventEmitter() as MatrixRTCSession;
session.memberships = [];
return session;
});
client.getRooms.mockReturnValue([room]);
client.getUserId.mockReturnValue(alice.userId);
client.getDeviceId.mockReturnValue("alices_device");
@ -576,11 +581,9 @@ describe("ElementCall", () => {
let client: Mocked<MatrixClient>;
let room: Room;
let alice: RoomMember;
let bob: RoomMember;
let carol: RoomMember;
beforeEach(() => {
({ client, room, alice, bob, carol } = setUpClientRoomAndStores());
({ client, room, alice } = setUpClientRoomAndStores());
});
afterEach(() => cleanUpClientRoomAndStores(client, room));
@ -595,15 +598,14 @@ describe("ElementCall", () => {
expect(Call.get(room)).toBeInstanceOf(ElementCall);
});
it("ignores terminated calls", async () => {
await ElementCall.create(room);
it("finds ongoing calls that are created by the session manager", async () => {
// There is an existing session created by another user in this room.
client.matrixRTC.getRoomSession.mockReturnValue({
on: (ev: any, fn: any) => {},
memberships: [{ fakeVal: "fake membership" }],
} as unknown as MatrixRTCSession);
const call = Call.get(room);
if (!(call instanceof ElementCall)) throw new Error("Failed to create call");
// Terminate the call
await call.groupCall.terminate();
expect(Call.get(room)).toBeNull();
});
it("passes font settings through widget URL", async () => {
@ -731,10 +733,6 @@ describe("ElementCall", () => {
afterEach(() => cleanUpCallAndWidget(call, widget, audioMutedSpy, videoMutedSpy));
it("has prompt intent", () => {
expect(call.groupCall.intent).toBe(GroupCallIntent.Prompt);
});
it("connects muted", async () => {
expect(call.connectionState).toBe(ConnectionState.Disconnected);
audioMutedSpy.mockReturnValue(true);
@ -828,57 +826,6 @@ describe("ElementCall", () => {
expect(call.connectionState).toBe(ConnectionState.Disconnected);
});
it("tracks participants in room state", async () => {
expect(call.participants).toEqual(new Map());
// A participant with multiple devices (should only show up once)
await client.sendStateEvent(
room.roomId,
ElementCall.MEMBER_EVENT_TYPE.name,
{
"m.calls": [
{
"m.call_id": call.groupCall.groupCallId,
"m.devices": [
{ device_id: "bobweb", session_id: "1", feeds: [], expires_ts: 1000 * 60 * 10 },
{ device_id: "bobdesktop", session_id: "1", feeds: [], expires_ts: 1000 * 60 * 10 },
],
},
],
},
bob.userId,
);
// A participant with an expired device (should not show up)
await client.sendStateEvent(
room.roomId,
ElementCall.MEMBER_EVENT_TYPE.name,
{
"m.calls": [
{
"m.call_id": call.groupCall.groupCallId,
"m.devices": [
{ device_id: "carolandroid", session_id: "1", feeds: [], expires_ts: -1000 * 60 },
],
},
],
},
carol.userId,
);
// Now, stub out client.sendStateEvent so we can test our local echo
client.sendStateEvent.mockReset();
await call.connect();
expect(call.participants).toEqual(
new Map([
[alice, new Set(["alices_device"])],
[bob, new Set(["bobweb", "bobdesktop"])],
]),
);
await call.disconnect();
expect(call.participants).toEqual(new Map([[bob, new Set(["bobweb", "bobdesktop"])]]));
});
it("tracks layout", async () => {
await call.connect();
expect(call.layout).toBe(Layout.Tile);
@ -924,14 +871,11 @@ describe("ElementCall", () => {
it("emits events when participants change", async () => {
const onParticipants = jest.fn();
call.session.memberships = [{ sender: alice.userId, deviceId: "alices_device" } as CallMembership];
call.on(CallEvent.Participants, onParticipants);
call.session.emit(MatrixRTCSessionEvent.MembershipsChanged, [], []);
await call.connect();
await call.disconnect();
expect(onParticipants.mock.calls).toEqual([
[new Map([[alice, new Set(["alices_device"])]]), new Map()],
[new Map(), new Map([[alice, new Set(["alices_device"])]])],
]);
expect(onParticipants.mock.calls).toEqual([[new Map([[alice, new Set(["alices_device"])]]), new Map()]]);
call.off(CallEvent.Participants, onParticipants);
});
@ -954,60 +898,19 @@ describe("ElementCall", () => {
call.off(CallEvent.Layout, onLayout);
});
it("ends the call immediately if we're the last participant to leave", async () => {
it("ends the call immediately if the session ended", async () => {
await call.connect();
const onDestroy = jest.fn();
call.on(CallEvent.Destroy, onDestroy);
await call.disconnect();
expect(onDestroy).toHaveBeenCalled();
call.off(CallEvent.Destroy, onDestroy);
});
it("ends the call after a random delay if the last participant leaves without ending it", async () => {
// Bob connects
await client.sendStateEvent(
// this will be called automatically
// disconnect -> widget sends state event -> session manager notices no-one left
client.matrixRTC.emit(
MatrixRTCSessionManagerEvents.SessionEnded,
room.roomId,
ElementCall.MEMBER_EVENT_TYPE.name,
{
"m.calls": [
{
"m.call_id": call.groupCall.groupCallId,
"m.devices": [
{ device_id: "bobweb", session_id: "1", feeds: [], expires_ts: 1000 * 60 * 10 },
],
},
],
},
bob.userId,
{} as unknown as MatrixRTCSession,
);
const onDestroy = jest.fn();
call.on(CallEvent.Destroy, onDestroy);
// Bob disconnects
await client.sendStateEvent(
room.roomId,
ElementCall.MEMBER_EVENT_TYPE.name,
{
"m.calls": [
{
"m.call_id": call.groupCall.groupCallId,
"m.devices": [],
},
],
},
bob.userId,
);
// Nothing should happen for at least a second, to give Bob a chance
// to end the call on his own
jest.advanceTimersByTime(1000);
expect(onDestroy).not.toHaveBeenCalled();
// Within 10 seconds, our client should end the call on behalf of Bob
jest.advanceTimersByTime(9000);
expect(onDestroy).toHaveBeenCalled();
call.off(CallEvent.Destroy, onDestroy);
});
@ -1040,10 +943,6 @@ describe("ElementCall", () => {
afterEach(() => cleanUpCallAndWidget(call, widget, audioMutedSpy, videoMutedSpy));
it("has room intent", () => {
expect(call.groupCall.intent).toBe(GroupCallIntent.Room);
});
it("doesn't end the call when the last participant leaves", async () => {
await call.connect();
const onDestroy = jest.fn();