Cover the subscriber token path, widget fallback and server names

This commit is contained in:
Johannes Marbach
2026-10-12 21:28:04 +02:00
parent 8d1ed31b0b
commit ee7dcdee7e
3 changed files with 201 additions and 4 deletions
+30
View File
@@ -169,6 +169,36 @@ describe("getSFUConfig", () => {
});
});
it("should use the default endpoint when subscribing", async () => {
fetchMock.post("https://sfu.example.org/get_token", (url, opts) => {
const body = JSON.parse(opts.body as string);
expect(body).toMatchObject({
room_id: "!example_room_id",
slot_id: "m.call#ROOM",
member: {
id: ownMemberMock.memberId,
claimed_user_id: ownMemberMock.userId,
claimed_device_id: ownMemberMock.deviceId,
},
});
return { status: 200, body: { url: serviceUrl, jwt: testJWTToken } };
});
const config = await getSFUConfig({ ...params, role: "subscriber" });
expect(config.jwt).toBe(testJWTToken);
expect(fetchMock.called("https://sfu.example.org/sfu/get")).toBe(false);
});
it("should fail when subscribing if the default endpoint is missing", async () => {
// Nothing but the catch-all 404 answers the default endpoint. Subscribers
// must not fall back to the legacy endpoint, which would hand them a
// legacy identity.
await expect(
getSFUConfig({ ...params, role: "subscriber" }),
).rejects.toThrow(FailToGetOpenIdToken);
expect(fetchMock.called("https://sfu.example.org/get_token")).toBe(true);
expect(fetchMock.called("https://sfu.example.org/sfu/get")).toBe(false);
});
it("should retry fetching the openid token", async () => {
let count = 0;
matrixClient.getOpenIdToken.mockImplementation(async () => {
+63 -4
View File
@@ -1,16 +1,25 @@
/*
Copyright 2025 Element Creations Ltd.
Copyright 2025, 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { describe, expect, it, vi } from "vitest";
import { MatrixRTCSessionEvent } from "matrix-js-sdk/lib/matrixrtc";
import {
MatrixRTCSessionEvent,
type Transport,
type UnstableLivekitTransport,
} from "matrix-js-sdk/lib/matrixrtc";
import { EventEmitter } from "events";
import { createKeyRotationSuppressed$ } from "./SessionBehaviors";
import { testScope } from "../utils/test";
import {
createKeyRotationSuppressed$,
membershipsAndTransports$,
} from "./SessionBehaviors";
import { Epoch } from "./ObservableScope";
import { constant } from "./Behavior";
import { mockRtcMembership, testScope } from "../utils/test";
describe("SessionBehaviors", () => {
describe("createKeyRotationSuppressed$", () => {
@@ -38,4 +47,54 @@ describe("SessionBehaviors", () => {
expect(keyRotationSuppressed$.value).toBe(false);
});
});
describe("membershipsAndTransports$", () => {
const serviceTransport: UnstableLivekitTransport = {
type: "livekit",
livekit_service_url: "https://lk.example.org",
};
const urlTransport: UnstableLivekitTransport = {
type: "livekit",
url: "wss://sfu.sample.com",
};
it("locates each member's transport on the member's homeserver", () => {
const bob = mockRtcMembership("@bob:example.org", "DEV000", {
fociPreferred: [serviceTransport],
});
const carl = mockRtcMembership("@carl:sample.com", "DEV111", {
fociPreferred: [urlTransport],
});
const { membershipsWithTransport$, transports$ } =
membershipsAndTransports$(
testScope(),
constant(new Epoch([bob, carl])),
);
expect(transports$.value.value).toEqual([
{ transport: serviceTransport, serverName: "example.org" },
{ transport: urlTransport, serverName: "sample.com" },
]);
expect(
membershipsWithTransport$.value.value.map(
(m) => m.transport?.serverName,
),
).toEqual(["example.org", "sample.com"]);
});
it("leaves out members without a LiveKit transport", () => {
const dave = mockRtcMembership("@dave:example.org", "DEV222", {
fociPreferred: [{ type: "something-else" } as Transport],
});
const { membershipsWithTransport$, transports$ } =
membershipsAndTransports$(testScope(), constant(new Epoch([dave])));
expect(transports$.value.value).toEqual([]);
expect(membershipsWithTransport$.value.value).toEqual([
{ membership: dave, transport: undefined },
]);
});
});
});