From d2299b22f4336f4af665fc0ad841a54b666c50be Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Thu, 11 Dec 2025 15:09:17 +0000 Subject: [PATCH] Loads more tests --- .../localMember/LocalTransport.test.ts | 193 ++++++++++-------- 1 file changed, 111 insertions(+), 82 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalTransport.test.ts b/src/state/CallViewModel/localMember/LocalTransport.test.ts index 04a44fde..26148948 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.test.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.test.ts @@ -5,7 +5,15 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { + afterEach, + beforeEach, + describe, + expect, + it, + MockedObject, + vi, +} from "vitest"; import { type CallMembership } from "matrix-js-sdk/lib/matrixrtc"; import { BehaviorSubject } from "rxjs"; @@ -18,6 +26,8 @@ import { FailToGetOpenIdToken, } from "../../../utils/errors"; import * as openIDSFU from "../../../livekit/openIDSFU"; +import { customLivekitUrl } from "../../../settings/settings"; +import fetchMock from "fetch-mock"; describe("LocalTransport", () => { let scope: ObservableScope; @@ -26,28 +36,6 @@ describe("LocalTransport", () => { }); afterEach(() => scope.end()); - it("throws if config is missing", async () => { - const localTransport$ = createLocalTransport$({ - scope, - roomId: "!room:example.org", - useOldestMember$: constant(false), - memberships$: constant(new Epoch([])), - client: { - getDomain: () => "", - // eslint-disable-next-line @typescript-eslint/naming-convention - _unstable_getRTCTransports: async () => Promise.resolve([]), - // These won't be called in this error path but satisfy the type - getOpenIdToken: vi.fn(), - getDeviceId: vi.fn(), - }, - }); - await flushPromises(); - - expect(() => localTransport$.value).toThrow( - new MatrixRTCTransportMissingError(""), - ); - }); - it("throws FailToGetOpenIdToken when OpenID fetch fails", async () => { // Provide a valid config so makeTransportInternal resolves a transport const scope = new ObservableScope(); @@ -90,43 +78,6 @@ describe("LocalTransport", () => { expect(() => localTransport$.value).toThrow(expectedError); }); - it("emits preferred transport after OpenID resolves", async () => { - // Use config so transport discovery succeeds, but delay OpenID JWT fetch - mockConfig({ - livekit: { livekit_service_url: "https://lk.example.org" }, - }); - - const openIdResolver = Promise.withResolvers(); - - vi.spyOn(openIDSFU, "getSFUConfigWithOpenID").mockReturnValue( - openIdResolver.promise, - ); - - const localTransport$ = createLocalTransport$({ - scope, - roomId: "!room:example.org", - useOldestMember$: constant(false), - memberships$: constant(new Epoch([])), - client: { - getDomain: () => "", - // eslint-disable-next-line @typescript-eslint/naming-convention - _unstable_getRTCTransports: async () => Promise.resolve([]), - getOpenIdToken: vi.fn(), - getDeviceId: vi.fn(), - }, - }); - - openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" }); - expect(localTransport$.value).toBe(null); - await flushPromises(); - // final - expect(localTransport$.value).toStrictEqual({ - livekit_alias: "!room:example.org", - livekit_service_url: "https://lk.example.org", - type: "livekit", - }); - }); - it("updates local transport when oldest member changes", async () => { // Use config so transport discovery succeeds, but delay OpenID JWT fetch mockConfig({ @@ -164,40 +115,118 @@ describe("LocalTransport", () => { }); }); - it("supports getting a transport from the backend", async () => { - // Use config so transport discovery succeeds, but delay OpenID JWT fetch - const memberships$ = new BehaviorSubject(new Epoch([])); - const openIdResolver = Promise.withResolvers(); + type LocalTransportProps = Parameters[0]; - vi.spyOn(openIDSFU, "getSFUConfigWithOpenID").mockReturnValue( - openIdResolver.promise, - ); + describe("transport configuration mechanisms", () => { + let localTransportOpts: LocalTransportProps & { + client: MockedObject; + }; + let openIdResolver: PromiseWithResolvers; + beforeEach(() => { + mockConfig({}); + customLivekitUrl.setValue(customLivekitUrl.defaultValue); + localTransportOpts = { + scope, + roomId: "!room:example.org", + useOldestMember$: constant(false), + memberships$: constant(new Epoch([])), + client: { + getDomain: vi.fn().mockReturnValue(""), + // eslint-disable-next-line @typescript-eslint/naming-convention + _unstable_getRTCTransports: vi.fn().mockResolvedValue([]), + getOpenIdToken: vi.fn(), + getDeviceId: vi.fn(), + }, + }; + openIdResolver = Promise.withResolvers(); + vi.spyOn(openIDSFU, "getSFUConfigWithOpenID").mockReturnValue( + openIdResolver.promise, + ); + }); + afterEach(() => { + fetchMock.reset(); + }); + + it("supports getting transport via application config", async () => { + mockConfig({ + livekit: { livekit_service_url: "https://lk.example.org" }, + }); + const localTransport$ = createLocalTransport$(localTransportOpts); + openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" }); + expect(localTransport$.value).toBe(null); + await flushPromises(); + expect(localTransport$.value).toStrictEqual({ + livekit_alias: "!room:example.org", + livekit_service_url: "https://lk.example.org", + type: "livekit", + }); + }); + it("supports getting transport via user settings", async () => { + customLivekitUrl.setValue("https://lk.example.org"); + const localTransport$ = createLocalTransport$(localTransportOpts); + openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" }); + expect(localTransport$.value).toBe(null); + await flushPromises(); + expect(localTransport$.value).toStrictEqual({ + livekit_alias: "!room:example.org", + livekit_service_url: "https://lk.example.org", + type: "livekit", + }); + }); + it("supports getting transport via backend", async () => { + localTransportOpts.client._unstable_getRTCTransports.mockResolvedValue([ + { type: "livekit", livekit_service_url: "https://lk.example.org" }, + ]); + const localTransport$ = createLocalTransport$(localTransportOpts); + openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" }); + expect(localTransport$.value).toBe(null); + await flushPromises(); + expect(localTransport$.value).toStrictEqual({ + livekit_alias: "!room:example.org", + livekit_service_url: "https://lk.example.org", + type: "livekit", + }); + }); + it("supports getting transport via well-known", async () => { + localTransportOpts.client.getDomain.mockReturnValue("example.org"); + fetchMock.getOnce("https://example.org/.well-known/matrix/client", { + "org.matrix.msc4143.rtc_foci": [ + { type: "livekit", livekit_service_url: "https://lk.example.org" }, + ], + }); + const localTransport$ = createLocalTransport$(localTransportOpts); + openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" }); + expect(localTransport$.value).toBe(null); + await flushPromises(); + expect(localTransport$.value).toStrictEqual({ + livekit_alias: "!room:example.org", + livekit_service_url: "https://lk.example.org", + type: "livekit", + }); + expect(fetchMock.done()).toEqual(true); + }); + }); + + it("throws if no options are available", async () => { const localTransport$ = createLocalTransport$({ scope, roomId: "!room:example.org", - useOldestMember$: constant(true), - memberships$, + useOldestMember$: constant(false), + memberships$: constant(new Epoch([])), client: { getDomain: () => "", // eslint-disable-next-line @typescript-eslint/naming-convention - _unstable_getRTCTransports: async () => - Promise.resolve([ - { type: "livekit", livekit_service_url: "https://lk.example.org" }, - ]), + _unstable_getRTCTransports: async () => Promise.resolve([]), + // These won't be called in this error path but satisfy the type getOpenIdToken: vi.fn(), getDeviceId: vi.fn(), }, }); - - openIdResolver.resolve({ url: "https://lk.example.org", jwt: "jwt" }); - expect(localTransport$.value).toBe(null); await flushPromises(); - // final - expect(localTransport$.value).toStrictEqual({ - livekit_alias: "!room:example.org", - livekit_service_url: "https://lk.example.org", - type: "livekit", - }); + + expect(() => localTransport$.value).toThrow( + new MatrixRTCTransportMissingError(""), + ); }); });