From dcf7e87799e319b852bced3bc027fb4e79a31fef Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Thu, 6 Nov 2025 10:38:27 +0000 Subject: [PATCH] Cleanup tests --- spec/unit/matrixrtc/CallMembership.spec.ts | 70 ++++++-- spec/unit/matrixrtc/LivekitTransport.spec.ts | 5 +- spec/unit/matrixrtc/MatrixRTCSession.spec.ts | 165 +++++++++++------- .../matrixrtc/MatrixRTCSessionManager.spec.ts | 77 +++++--- spec/unit/matrixrtc/MembershipManager.spec.ts | 25 +-- spec/unit/matrixrtc/mocks.ts | 58 ++++-- 6 files changed, 273 insertions(+), 127 deletions(-) diff --git a/spec/unit/matrixrtc/CallMembership.spec.ts b/spec/unit/matrixrtc/CallMembership.spec.ts index f2d12880c..7b10828c1 100644 --- a/spec/unit/matrixrtc/CallMembership.spec.ts +++ b/spec/unit/matrixrtc/CallMembership.spec.ts @@ -16,14 +16,14 @@ limitations under the License. import { SessionMembershipData } from "../../../src/matrixrtc/membership/legacy"; import { EventType, type MatrixEvent } from "../../../src"; -import { - CallMembership, - DEFAULT_EXPIRE_DURATION, -} from "../../../src/matrixrtc/CallMembership"; +import { CallMembership, DEFAULT_EXPIRE_DURATION } from "../../../src/matrixrtc/CallMembership"; import { sessionMembershipTemplate } from "./mocks"; import { RtcMembershipData } from "../../../src/matrixrtc/membership/rtc"; -function makeMockEvent(eventType: EventType.RTCMembership|EventType.GroupCallMemberPrefix, originTs = 0): MatrixEvent { +function makeMockEvent( + eventType: EventType.RTCMembership | EventType.GroupCallMemberPrefix, + originTs = 0, +): MatrixEvent { return { getTs: jest.fn().mockReturnValue(originTs), getSender: jest.fn().mockReturnValue("@alice:example.org"), @@ -54,24 +54,36 @@ describe("CallMembership", () => { it("rejects membership with no device_id", () => { expect(() => { - new CallMembership(makeMockEvent(EventType.GroupCallMemberPrefix), Object.assign({}, membershipTemplate, { device_id: undefined })); + new CallMembership( + makeMockEvent(EventType.GroupCallMemberPrefix), + Object.assign({}, membershipTemplate, { device_id: undefined }), + ); }).toThrow(); }); it("rejects membership with no call_id", () => { expect(() => { - new CallMembership(makeMockEvent(EventType.GroupCallMemberPrefix), Object.assign({}, membershipTemplate, { call_id: undefined })); + new CallMembership( + makeMockEvent(EventType.GroupCallMemberPrefix), + Object.assign({}, membershipTemplate, { call_id: undefined }), + ); }).toThrow(); }); it("allow membership with no scope", () => { expect(() => { - new CallMembership(makeMockEvent(EventType.GroupCallMemberPrefix), Object.assign({}, membershipTemplate, { scope: undefined })); + new CallMembership( + makeMockEvent(EventType.GroupCallMemberPrefix), + Object.assign({}, membershipTemplate, { scope: undefined }), + ); }).not.toThrow(); }); it("uses event timestamp if no created_ts", () => { - const membership = new CallMembership(makeMockEvent(EventType.GroupCallMemberPrefix, 12345), membershipTemplate); + const membership = new CallMembership( + makeMockEvent(EventType.GroupCallMemberPrefix, 12345), + membershipTemplate, + ); expect(membership.createdTs()).toEqual(12345); }); @@ -104,7 +116,10 @@ describe("CallMembership", () => { describe("getTransport", () => { const mockFocus = { type: "this_is_a_mock_focus" }; - const oldestMembership = new CallMembership(makeMockEvent(EventType.GroupCallMemberPrefix), membershipTemplate); + const oldestMembership = new CallMembership( + makeMockEvent(EventType.GroupCallMemberPrefix), + membershipTemplate, + ); it("gets the correct active transport with oldest_membership", () => { const membership = new CallMembership(makeMockEvent(EventType.GroupCallMemberPrefix), { ...membershipTemplate, @@ -193,23 +208,35 @@ describe("CallMembership", () => { it("rejects membership with no slot_id", () => { expect(() => { - new CallMembership(makeMockEvent(EventType.RTCMembership), { ...membershipTemplate, slot_id: undefined }); + new CallMembership(makeMockEvent(EventType.RTCMembership), { + ...membershipTemplate, + slot_id: undefined, + }); }).toThrow(); }); it("rejects membership with invalid slot_id", () => { expect(() => { - new CallMembership(makeMockEvent(EventType.RTCMembership), { ...membershipTemplate, slot_id: "invalid_slot_id" }); + new CallMembership(makeMockEvent(EventType.RTCMembership), { + ...membershipTemplate, + slot_id: "invalid_slot_id", + }); }).toThrow(); }); it("accepts membership with valid slot_id", () => { expect(() => { - new CallMembership(makeMockEvent(EventType.RTCMembership), { ...membershipTemplate, slot_id: "m.call#" }); + new CallMembership(makeMockEvent(EventType.RTCMembership), { + ...membershipTemplate, + slot_id: "m.call#", + }); }).not.toThrow(); }); it("rejects membership with no application", () => { expect(() => { - new CallMembership(makeMockEvent(EventType.RTCMembership), { ...membershipTemplate, application: undefined }); + new CallMembership(makeMockEvent(EventType.RTCMembership), { + ...membershipTemplate, + application: undefined, + }); }).toThrow(); }); @@ -224,13 +251,19 @@ describe("CallMembership", () => { it("rejects membership with no member", () => { expect(() => { - new CallMembership(makeMockEvent(EventType.RTCMembership), { ...membershipTemplate, member: undefined }); + new CallMembership(makeMockEvent(EventType.RTCMembership), { + ...membershipTemplate, + member: undefined, + }); }).toThrow(); }); it("rejects membership with incorrect member", () => { expect(() => { - new CallMembership(makeMockEvent(EventType.RTCMembership), { ...membershipTemplate, member: { i: "test" } }); + new CallMembership(makeMockEvent(EventType.RTCMembership), { + ...membershipTemplate, + member: { i: "test" }, + }); }).toThrow(); expect(() => { new CallMembership(makeMockEvent(EventType.RTCMembership), { @@ -276,7 +309,10 @@ describe("CallMembership", () => { }); }).not.toThrow(); expect(() => { - new CallMembership(makeMockEvent(EventType.RTCMembership), { ...membershipTemplate, msc4354_sticky_key: undefined }); + new CallMembership(makeMockEvent(EventType.RTCMembership), { + ...membershipTemplate, + msc4354_sticky_key: undefined, + }); }).toThrow(); expect(() => { new CallMembership(makeMockEvent(EventType.RTCMembership), { diff --git a/spec/unit/matrixrtc/LivekitTransport.spec.ts b/spec/unit/matrixrtc/LivekitTransport.spec.ts index 94e82af8f..6a444f98f 100644 --- a/spec/unit/matrixrtc/LivekitTransport.spec.ts +++ b/spec/unit/matrixrtc/LivekitTransport.spec.ts @@ -14,10 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { - isLivekitTransport, - isLivekitTransportConfig, -} from "../../../src/matrixrtc/LivekitTransport"; +import { isLivekitTransport, isLivekitTransportConfig } from "../../../src/matrixrtc/LivekitTransport"; describe("LivekitFocus", () => { it("isLivekitFocus", () => { diff --git a/spec/unit/matrixrtc/MatrixRTCSession.spec.ts b/spec/unit/matrixrtc/MatrixRTCSession.spec.ts index 99d6aa51b..afa6da7bb 100644 --- a/spec/unit/matrixrtc/MatrixRTCSession.spec.ts +++ b/spec/unit/matrixrtc/MatrixRTCSession.spec.ts @@ -36,7 +36,6 @@ import { type MembershipData, mockRoomState, mockRTCEvent, - testStickyDurationMs, } from "./mocks"; import { RTCEncryptionManager } from "../../../src/matrixrtc/RTCEncryptionManager.ts"; import { RoomStickyEventsEvent, type StickyMatrixEvent } from "../../../src/models/room-sticky-events.ts"; @@ -98,7 +97,9 @@ describe("MatrixRTCSession", () => { "sessionForSlot listenForSticky=$listenForStickyEvents listenForMemberStateEvents=$listenForMemberStateEvents testCreateSticky=$testCreateSticky", (testConfig) => { it(`will ${testConfig.listenForMemberStateEvents ? "" : "NOT"} throw if the room does not have any state stored`, () => { - const membershipTemplate = testConfig.testCreateSticky ? rtcMembershipTemplate : sessionMembershipTemplate; + const membershipTemplate = testConfig.testCreateSticky + ? rtcMembershipTemplate + : sessionMembershipTemplate; const mockRoom = makeMockRoom([membershipTemplate], testConfig.testCreateSticky); mockRoom.getLiveTimeline.mockReturnValue({ getState: jest.fn().mockReturnValue(undefined), @@ -117,7 +118,9 @@ describe("MatrixRTCSession", () => { }); it("creates a room-scoped session from room state", () => { - const membershipTemplate = testConfig.testCreateSticky ? rtcMembershipTemplate : sessionMembershipTemplate; + const membershipTemplate = testConfig.testCreateSticky + ? rtcMembershipTemplate + : sessionMembershipTemplate; const mockRoom = makeMockRoom([membershipTemplate], testConfig.testCreateSticky); sess = MatrixRTCSession.sessionForSlot( @@ -136,14 +139,16 @@ describe("MatrixRTCSession", () => { }); it("ignores memberships where application is not m.call", () => { - const testMembership = testConfig.testCreateSticky ? { - ...rtcMembershipTemplate, - slot_id: "not-m.call#", - application: { - ...rtcMembershipTemplate.application, - type: "not-m.call", - }, - } : { ...sessionMembershipTemplate, application: "not-m.call#" } + const testMembership = testConfig.testCreateSticky + ? { + ...rtcMembershipTemplate, + slot_id: "not-m.call#", + application: { + ...rtcMembershipTemplate.application, + type: "not-m.call", + }, + } + : { ...sessionMembershipTemplate, application: "not-m.call#" }; const mockRoom = makeMockRoom([testMembership], testConfig.testCreateSticky); const sess = MatrixRTCSession.sessionForSlot( client, @@ -155,14 +160,16 @@ describe("MatrixRTCSession", () => { }); it("ignores memberships where callId is not empty", () => { - const testMembership = testConfig.testCreateSticky ? { - ...rtcMembershipTemplate, - slot_id: "m.call#foobar", - application: { - ...rtcMembershipTemplate.application, - "m.call.id": "foobar" - }, - } : { ...sessionMembershipTemplate, application: "m.call", call_id: "foobar" } + const testMembership = testConfig.testCreateSticky + ? { + ...rtcMembershipTemplate, + slot_id: "m.call#foobar", + application: { + ...rtcMembershipTemplate.application, + "m.call.id": "foobar", + }, + } + : { ...sessionMembershipTemplate, application: "m.call", call_id: "foobar" }; const mockRoom = makeMockRoom([testMembership], testConfig.testCreateSticky); const sess = MatrixRTCSession.sessionForSlot( client, @@ -175,21 +182,29 @@ describe("MatrixRTCSession", () => { it("ignores expired memberships events", () => { jest.useFakeTimers(); - const expiredMembership = testConfig.testCreateSticky ? { - ...rtcMembershipTemplate, - slot_id: "m.call#foobar", - member: { - ...rtcMembershipTemplate.member, - claimed_device_id: "EXPIRED", - }, - application: { - ...rtcMembershipTemplate.application, - "m.call.id": "foobar" - }, - __test_sticky_expiry: 3000, - } : { ...sessionMembershipTemplate, device_id: "EXPIRED", expires: 3000 } + const expiredMembership = testConfig.testCreateSticky + ? { + ...rtcMembershipTemplate, + slot_id: "m.call#foobar", + member: { + ...rtcMembershipTemplate.member, + claimed_device_id: "EXPIRED", + }, + application: { + ...rtcMembershipTemplate.application, + "m.call.id": "foobar", + }, + __test_sticky_expiry: 3000, + } + : { ...sessionMembershipTemplate, device_id: "EXPIRED", expires: 3000 }; jest.setSystemTime(0); - const mockRoom = makeMockRoom([testConfig.testCreateSticky ? rtcMembershipTemplate : sessionMembershipTemplate, expiredMembership], testConfig.testCreateSticky); + const mockRoom = makeMockRoom( + [ + testConfig.testCreateSticky ? rtcMembershipTemplate : sessionMembershipTemplate, + expiredMembership, + ], + testConfig.testCreateSticky, + ); jest.advanceTimersByTime(3000); sess = MatrixRTCSession.sessionForSlot( @@ -204,7 +219,10 @@ describe("MatrixRTCSession", () => { }); it("ignores memberships events of members not in the room", () => { - const mockRoom = makeMockRoom([sessionMembershipTemplate], testConfig.testCreateSticky); + const membershipTemplate = testConfig.testCreateSticky + ? rtcMembershipTemplate + : sessionMembershipTemplate; + const mockRoom = makeMockRoom([membershipTemplate], testConfig.testCreateSticky); mockRoom.hasMembershipState.mockImplementation((state) => state === KnownMembership.Join); sess = MatrixRTCSession.sessionForSlot( client, @@ -217,7 +235,10 @@ describe("MatrixRTCSession", () => { it("ignores memberships events with no sender", () => { // Force the sender to be undefined. - const mockRoom = makeMockRoom([{ ...sessionMembershipTemplate, user_id: "" }], testConfig.testCreateSticky); + const membershipTemplate = testConfig.testCreateSticky + ? { ...rtcMembershipTemplate, member: { claimed_user_id: "" } } + : { ...sessionMembershipTemplate, user_id: "" }; + const mockRoom = makeMockRoom([membershipTemplate], testConfig.testCreateSticky); mockRoom.hasMembershipState.mockImplementation((state) => state === KnownMembership.Join); sess = MatrixRTCSession.sessionForSlot( client, @@ -231,19 +252,21 @@ describe("MatrixRTCSession", () => { it("honours created_ts", () => { jest.useFakeTimers(); jest.setSystemTime(500); - const expiredMembership = testConfig.testCreateSticky ? { - ...rtcMembershipTemplate, - slot_id: "m.call#foobar", - member: { - ...rtcMembershipTemplate.member, - claimed_device_id: "EXPIRED", - }, - application: { - ...rtcMembershipTemplate.application, - "m.call.id": "foobar" - }, - __test_sticky_expiry: 1500, - } : { ...sessionMembershipTemplate, device_id: "EXPIRED", created_ts: 500, expires: 1000 }; + const expiredMembership = testConfig.testCreateSticky + ? { + ...rtcMembershipTemplate, + slot_id: "m.call#", + member: { + ...rtcMembershipTemplate.member, + claimed_device_id: "EXPIRED", + }, + application: { + ...rtcMembershipTemplate.application, + "m.call.id": "", + }, + __test_sticky_expiry: 1000, + } + : { ...sessionMembershipTemplate, device_id: "EXPIRED", created_ts: 500, expires: 1000 }; const mockRoom = makeMockRoom([expiredMembership], testConfig.testCreateSticky); sess = MatrixRTCSession.sessionForSlot( client, @@ -251,6 +274,7 @@ describe("MatrixRTCSession", () => { callSession, testConfig.createWithDefaults ? undefined : testConfig, ); + expect(sess.memberships[0]).toBeDefined(); expect(sess?.memberships[0].getAbsoluteExpiry()).toEqual(1500); jest.useRealTimers(); }); @@ -275,7 +299,10 @@ describe("MatrixRTCSession", () => { getLocalAge: jest.fn().mockReturnValue(0), } as unknown as MatrixEvent; const mockRoom = makeMockRoom([]); - mockRoom.getLiveTimeline().getState(Direction.Forward)?.events.set(EventType.GroupCallMemberPrefix, new Map([[EventType.GroupCallMemberPrefix, event]])); + mockRoom + .getLiveTimeline() + .getState(Direction.Forward) + ?.events.set(EventType.GroupCallMemberPrefix, new Map([[EventType.GroupCallMemberPrefix, event]])); sess = MatrixRTCSession.sessionForSlot( client, mockRoom, @@ -294,7 +321,10 @@ describe("MatrixRTCSession", () => { getLocalAge: jest.fn().mockReturnValue(0), } as unknown as MatrixEvent; const mockRoom = makeMockRoom([]); - mockRoom.getLiveTimeline().getState(Direction.Forward)?.events.set(EventType.GroupCallMemberPrefix, new Map([[EventType.GroupCallMemberPrefix, event]])); + mockRoom + .getLiveTimeline() + .getState(Direction.Forward) + ?.events.set(EventType.GroupCallMemberPrefix, new Map([[EventType.GroupCallMemberPrefix, event]])); sess = MatrixRTCSession.sessionForSlot( client, mockRoom, @@ -305,9 +335,16 @@ describe("MatrixRTCSession", () => { }); it("ignores memberships with no device_id", () => { - const testMembership = Object.assign({}, sessionMembershipTemplate); - (testMembership.device_id as string | undefined) = undefined; - const mockRoom = makeMockRoom([testMembership]); + const membershipTemplate = testConfig.testCreateSticky + ? { + ...rtcMembershipTemplate, + member: { + ...rtcMembershipTemplate.member, + claimed_device_id: undefined, + }, + } + : { ...sessionMembershipTemplate, device_id: undefined }; + const mockRoom = makeMockRoom([membershipTemplate]); const sess = MatrixRTCSession.sessionForSlot( client, mockRoom, @@ -317,9 +354,13 @@ describe("MatrixRTCSession", () => { expect(sess.memberships).toHaveLength(0); }); - it("ignores memberships with no call_id", () => { - const testMembership = Object.assign({}, sessionMembershipTemplate); - (testMembership.call_id as string | undefined) = undefined; + it("ignores memberships with a different slot description", () => { + const testMembership = testConfig.testCreateSticky + ? { + ...rtcMembershipTemplate, + slot_id: "m.call#fibble", + } + : { ...sessionMembershipTemplate, call_id: undefined }; const mockRoom = makeMockRoom([testMembership]); sess = MatrixRTCSession.sessionForSlot( client, @@ -401,7 +442,7 @@ describe("MatrixRTCSession", () => { expect(sess?.slotDescription.id).toEqual(""); }); - it.skip("handles an incoming sticky event to an existing session", () => { + it("handles an incoming sticky event to an existing session", () => { const mockRoom = makeMockRoom([sessionMembershipTemplate], false, callSession, true); const stickyUserId = "@stickyev:user.example"; @@ -703,7 +744,10 @@ describe("MatrixRTCSession", () => { // Simulate a join, including the update to the room state sess!.joinRoomSession([mockFocus], mockFocus, { notificationType: "ring" }); await Promise.race([sentStateEvent, new Promise((resolve) => setTimeout(resolve, 5000))]); - mockRoomState(mockRoom, [sessionMembershipTemplate, { ...sessionMembershipTemplate, user_id: client.getUserId()! }]); + mockRoomState(mockRoom, [ + sessionMembershipTemplate, + { ...sessionMembershipTemplate, user_id: client.getUserId()! }, + ]); sess!.onRTCSessionMemberUpdate(); expect(client.sendEvent).not.toHaveBeenCalled(); @@ -717,7 +761,10 @@ describe("MatrixRTCSession", () => { // from someone else, starting the call before our own state event has been sent mockRoomState(mockRoom, [sessionMembershipTemplate]); sess!.onRTCSessionMemberUpdate(); - mockRoomState(mockRoom, [sessionMembershipTemplate, { ...sessionMembershipTemplate, user_id: client.getUserId()! }]); + mockRoomState(mockRoom, [ + sessionMembershipTemplate, + { ...sessionMembershipTemplate, user_id: client.getUserId()! }, + ]); sess!.onRTCSessionMemberUpdate(); // We assume that the responsibility to send a notification, if any, lies with the other diff --git a/spec/unit/matrixrtc/MatrixRTCSessionManager.spec.ts b/spec/unit/matrixrtc/MatrixRTCSessionManager.spec.ts index e35e04031..90a93ae06 100644 --- a/spec/unit/matrixrtc/MatrixRTCSessionManager.spec.ts +++ b/spec/unit/matrixrtc/MatrixRTCSessionManager.spec.ts @@ -17,7 +17,14 @@ limitations under the License. import { ClientEvent, EventTimeline, MatrixClient, type Room } from "../../../src"; import { RoomStateEvent } from "../../../src/models/room-state"; import { MatrixRTCSessionManager, MatrixRTCSessionManagerEvents } from "../../../src/matrixrtc/MatrixRTCSessionManager"; -import { makeMockRoom, type MembershipData, sessionMembershipTemplate, mockRoomState, mockRTCEvent, rtcMembershipTemplate } from "./mocks"; +import { + makeMockRoom, + type MembershipData, + sessionMembershipTemplate, + mockRoomState, + mockRTCEvent, + rtcMembershipTemplate, +} from "./mocks"; import { logger } from "../../../src/logger"; import { slotDescriptionToId } from "../../../src/matrixrtc"; @@ -111,29 +118,49 @@ describe.each([{ eventKind: "sticky" }, { eventKind: "memberState" }])( try { // Create a session for applicaation m.other, we ignore this session because it has the wrong application type. - const room1MembershipData: MembershipData[] = eventKind === "sticky" ? [{ ...membershipTemplate, application: { - ...rtcMembershipTemplate.application, - type: "m.call" - }}] : [{ ...membershipTemplate, application: "m.call" }]; - const room1 = makeMockRoom(room1MembershipData, eventKind === "sticky", { application: "m.call", id: ""}); + const room1MembershipData: MembershipData[] = + eventKind === "sticky" + ? [ + { + ...membershipTemplate, + application: { + ...rtcMembershipTemplate.application, + type: "m.call", + }, + }, + ] + : [{ ...membershipTemplate, application: "m.call" }]; + const room1 = makeMockRoom(room1MembershipData, eventKind === "sticky", { + application: "m.call", + id: "", + }); jest.spyOn(client, "getRooms").mockReturnValue([room1]); client.emit(ClientEvent.Room, room1); expect(onStarted).not.toHaveBeenCalled(); onStarted.mockClear(); // Create a session for applicaation m.notCall. We expect this call to be tracked because it has a call_id - const room2MembershipData: MembershipData[] = eventKind === "sticky" ? [ - { ...membershipTemplate, application: { - ...rtcMembershipTemplate.application, - type: slotDescription.application, - }, slot_id: slotDescriptionToId(slotDescription) }, - ] : [{ - ...membershipTemplate, - application: slotDescription.application, - call_id: slotDescription.id, - }]; + const room2MembershipData: MembershipData[] = + eventKind === "sticky" + ? [ + { + ...membershipTemplate, + application: { + ...rtcMembershipTemplate.application, + type: slotDescription.application, + }, + slot_id: slotDescriptionToId(slotDescription), + }, + ] + : [ + { + ...membershipTemplate, + application: slotDescription.application, + call_id: slotDescription.id, + }, + ]; const room2 = makeMockRoom(room2MembershipData, eventKind === "sticky", slotDescription); - console.log({room2: room2.roomId}) + console.log({ room2: room2.roomId }); jest.spyOn(client, "getRooms").mockReturnValue([room1, room2]); client.emit(ClientEvent.Room, room2); expect(onStarted).toHaveBeenCalled(); @@ -158,10 +185,18 @@ describe.each([{ eventKind: "sticky" }, { eventKind: "memberState" }])( it("Doesn't fire event if unrelated sessions ends", () => { const onEnded = jest.fn(); client.matrixRTC.on(MatrixRTCSessionManagerEvents.SessionEnded, onEnded); - const membership: MembershipData[] = eventKind === "sticky" ? [{ ...membershipTemplate, application: { - ...rtcMembershipTemplate.application, - type: "m.other_app", - }}] : [{ ...membershipTemplate, application: "m.other_app" }]; + const membership: MembershipData[] = + eventKind === "sticky" + ? [ + { + ...membershipTemplate, + application: { + ...rtcMembershipTemplate.application, + type: "m.other_app", + }, + }, + ] + : [{ ...membershipTemplate, application: "m.other_app" }]; const room1 = makeMockRoom(membership, eventKind === "sticky"); jest.spyOn(client, "getRooms").mockReturnValue([room1]); jest.spyOn(client, "getRoom").mockReturnValue(room1); diff --git a/spec/unit/matrixrtc/MembershipManager.spec.ts b/spec/unit/matrixrtc/MembershipManager.spec.ts index 11b430318..78fc005d0 100644 --- a/spec/unit/matrixrtc/MembershipManager.spec.ts +++ b/spec/unit/matrixrtc/MembershipManager.spec.ts @@ -25,11 +25,7 @@ import { type Room, MAX_STICKY_DURATION_MS, } from "../../../src"; -import { - MembershipManagerEvent, - Status, - type Transport, -} from "../../../src/matrixrtc"; +import { MembershipManagerEvent, Status, type Transport } from "../../../src/matrixrtc"; import { makeMockClient, makeMockRoom, sessionMembershipTemplate, mockCallMembership, type MockClient } from "./mocks"; import { LegacyMembershipManager, StickyEventMembershipManager } from "../../../src/matrixrtc/MembershipManager.ts"; import { SessionMembershipData } from "../../../src/matrixrtc/membership/legacy.ts"; @@ -98,13 +94,12 @@ describe("MembershipManager", () => { // There is no need to clean up mocks since we will recreate the client. }); describe("LegacyMembershipManager", () => { - beforeEach(() => { // Provide a default mock that is like the default "non error" server behaviour. (client._unstable_sendDelayedStateEvent as Mock).mockResolvedValue({ delay_id: "id" }); (client._unstable_updateDelayedEvent as Mock).mockResolvedValue(undefined); (client.sendStateEvent as Mock).mockResolvedValue({ event_id: "id" }); - }) + }); describe("isActivated()", () => { it("defaults to false", () => { @@ -124,7 +119,9 @@ describe("MembershipManager", () => { it("sends a membership event and schedules delayed leave when joining a call", async () => { // Spys/Mocks - const updateDelayedEventHandle = createAsyncHandle(client._unstable_updateDelayedEvent as Mock); + const updateDelayedEventHandle = createAsyncHandle( + client._unstable_updateDelayedEvent as Mock, + ); // Test const memberManager = new LegacyMembershipManager(undefined, room, client, callSession); @@ -308,7 +305,12 @@ describe("MembershipManager", () => { expect(client._unstable_sendDelayedStateEvent).toHaveBeenCalledTimes(2); }); it("uses delayedLeaveEventDelayMs from config", () => { - const manager = new LegacyMembershipManager({ delayedLeaveEventDelayMs: 123456 }, room, client, callSession); + const manager = new LegacyMembershipManager( + { delayedLeaveEventDelayMs: 123456 }, + room, + client, + callSession, + ); manager.join([focus]); expect(client._unstable_sendDelayedStateEvent).toHaveBeenCalledWith( room.roomId, @@ -867,7 +869,10 @@ describe("MembershipManager", () => { const manager = new LegacyMembershipManager({}, room, client, callSession); manager.join([]); expect(manager.isActivated()).toEqual(true); - const membership = mockCallMembership({ ...sessionMembershipTemplate, user_id: client.getUserId()! }, room.roomId); + const membership = mockCallMembership( + { ...sessionMembershipTemplate, user_id: client.getUserId()! }, + room.roomId, + ); await manager.onRTCSessionMemberUpdate([membership]); await manager.updateCallIntent("video"); expect(client.sendStateEvent).toHaveBeenCalledTimes(2); diff --git a/spec/unit/matrixrtc/mocks.ts b/spec/unit/matrixrtc/mocks.ts index b18bad758..02518378d 100644 --- a/spec/unit/matrixrtc/mocks.ts +++ b/spec/unit/matrixrtc/mocks.ts @@ -20,7 +20,12 @@ import { type Mocked } from "jest-mock"; import { EventType, type Room, RoomEvent, type MatrixClient, type MatrixEvent } from "../../../src"; import { CallMembership } from "../../../src/matrixrtc/CallMembership"; import { secureRandomString } from "../../../src/randomstring"; -import { DefaultCallApplicationDescription, RtcSlotEventContent, SlotDescription, slotDescriptionToId } from "../../../src/matrixrtc"; +import { + DefaultCallApplicationDescription, + RtcSlotEventContent, + SlotDescription, + slotDescriptionToId, +} from "../../../src/matrixrtc"; import { mkMatrixEvent } from "../../../src/testing"; import type { SessionMembershipData } from "../../../src/matrixrtc/membership/legacy"; import type { RtcMembershipData } from "../../../src/matrixrtc/membership/rtc"; @@ -50,17 +55,17 @@ export const sessionMembershipTemplate: SessionMembershipData & { user_id: strin ], }; -export const rtcMembershipTemplate: RtcMembershipData&{user_id: string, __test_sticky_expiry?: number} = { +export const rtcMembershipTemplate: RtcMembershipData & { user_id: string; __test_sticky_expiry?: number } = { slot_id: "m.call#", application: { - type: "m.call", - "m.call.id": "" + "type": "m.call", + "m.call.id": "", }, user_id: "@mock:user.example", member: { claimed_user_id: "@mock:user.example", claimed_device_id: "AAAAAAA", - id: "ea2MaingeeMo" + id: "ea2MaingeeMo", }, sticky_key: "ea2MaingeeMo", rtc_transports: [ @@ -78,7 +83,6 @@ export const rtcMembershipTemplate: RtcMembershipData&{user_id: string, __test_s versions: [], }; - export type MockClient = Pick< MatrixClient, | "getUserId" @@ -116,7 +120,11 @@ export function makeMockRoom( ): Mocked void }> { const roomId = secureRandomString(8); // Caching roomState here so it does not get recreated when calling `getLiveTimeline.getState()` - const roomState = makeMockRoomState(useStickyEvents ? [] : membershipData, roomId, addRTCSlot ? slotDescription : undefined); + const roomState = makeMockRoomState( + useStickyEvents ? [] : membershipData, + roomId, + addRTCSlot ? slotDescription : undefined, + ); const ts = Date.now(); const room = Object.assign(new EventEmitter(), { roomId: roomId, @@ -128,7 +136,16 @@ export function makeMockRoom( _unstable_getStickyEvents: jest .fn() .mockImplementation(() => - useStickyEvents ? membershipData.map((m) => mockRTCEvent(m, roomId, (m as typeof rtcMembershipTemplate).__test_sticky_expiry ?? testStickyDurationMs, ts)) : [], + useStickyEvents + ? membershipData.map((m) => + mockRTCEvent( + m, + roomId, + (m as typeof rtcMembershipTemplate).__test_sticky_expiry ?? testStickyDurationMs, + ts, + ), + ) + : [], ) as any, }); return Object.assign(room, { @@ -143,7 +160,7 @@ function makeMockRoomState(membershipData: MembershipData[], roomId: string, slo const data = e.getContent() as SessionMembershipData; return [`_${e.sender?.userId}_${data.device_id}`]; }); - let slotEvent: MatrixEvent|undefined; + let slotEvent: MatrixEvent | undefined; if (slotDescription) { // Add a slot @@ -181,18 +198,27 @@ function makeMockRoomState(membershipData: MembershipData[], roomId: string, slo values: () => events, }, ], - ...(slotEvent ? [[EventType.RTCSlot, { - size: () => true, - has: (stateKey: string) => slotEvent.getStateKey() === stateKey, - get: (stateKey: string) => slotEvent.getStateKey() === stateKey ? slotEvent : undefined, - values: () => [slotEvent], - }]] : []), + ...(slotEvent + ? [ + [ + EventType.RTCSlot, + { + size: () => true, + has: (stateKey: string) => slotEvent.getStateKey() === stateKey, + get: (stateKey: string) => (slotEvent.getStateKey() === stateKey ? slotEvent : undefined), + values: () => [slotEvent], + }, + ], + ] + : []), ] as any), }; } export function mockRoomState(room: Room, membershipData: MembershipData[], slotDescription?: SlotDescription): void { - room.getLiveTimeline().getState = jest.fn().mockReturnValue(makeMockRoomState(membershipData, room.roomId, slotDescription)); + room.getLiveTimeline().getState = jest + .fn() + .mockReturnValue(makeMockRoomState(membershipData, room.roomId, slotDescription)); } export function makeMockEvent(