Remove even more dead code

This commit is contained in:
Robin
2025-10-22 23:27:38 -04:00
parent 5245b22d80
commit 6be7749091
7 changed files with 4 additions and 381 deletions

View File

@@ -81,6 +81,7 @@ vi.mock("../rtcSessionHelpers", async (importOriginal) => {
// TODO: perhaps there is a more elegant way to manage the type import here?
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
const orig = await importOriginal<typeof import("../rtcSessionHelpers")>();
// TODO: leaveRTCSession no longer exists! Tests need adapting.
return { ...orig, enterRTCSession, leaveRTCSession };
});

View File

@@ -1,155 +0,0 @@
/*
Copyright 2023, 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { vi, type Mocked, test, expect } from "vitest";
import { type RoomState } from "matrix-js-sdk";
import { PosthogAnalytics } from "../../src/analytics/PosthogAnalytics";
import { checkForParallelCalls } from "../../src/room/checkForParallelCalls";
import { withFakeTimers } from "../utils/test";
const withMockedPosthog = (
continuation: (posthog: Mocked<PosthogAnalytics>) => void,
): void => {
const posthog = vi.mocked({
trackEvent: vi.fn(),
} as unknown as PosthogAnalytics);
const instanceSpy = vi
.spyOn(PosthogAnalytics, "instance", "get")
.mockReturnValue(posthog);
try {
continuation(posthog);
} finally {
instanceSpy.mockRestore();
}
};
const mockRoomState = (
groupCallMemberContents: Record<string, unknown>[],
): RoomState => {
const stateEvents = groupCallMemberContents.map((content) => ({
getContent: (): Record<string, unknown> => content,
}));
return { getStateEvents: () => stateEvents } as unknown as RoomState;
};
test("checkForParallelCalls does nothing if all participants are in the same call", () => {
withFakeTimers(() => {
withMockedPosthog((posthog) => {
const roomState = mockRoomState([
{
"m.calls": [
{
"m.call_id": "1",
"m.devices": [
{
device_id: "Element Call",
session_id: "a",
expires_ts: Date.now() + 1000,
},
],
},
{
"m.call_id": null, // invalid
"m.devices": [
{
device_id: "Element Android",
session_id: "a",
expires_ts: Date.now() + 1000,
},
],
},
null, // invalid
],
},
{
"m.calls": [
{
"m.call_id": "1",
"m.devices": [
{
device_id: "Element Desktop",
session_id: "a",
expires_ts: Date.now() + 1000,
},
],
},
],
},
]);
checkForParallelCalls(roomState);
expect(posthog.trackEvent).not.toHaveBeenCalled();
});
});
});
test("checkForParallelCalls sends diagnostics to PostHog if there is a split-brain", () => {
withFakeTimers(() => {
withMockedPosthog((posthog) => {
const roomState = mockRoomState([
{
"m.calls": [
{
"m.call_id": "1",
"m.devices": [
{
device_id: "Element Call",
session_id: "a",
expires_ts: Date.now() + 1000,
},
],
},
{
"m.call_id": "2",
"m.devices": [
{
device_id: "Element Android",
session_id: "a",
expires_ts: Date.now() + 1000,
},
],
},
],
},
{
"m.calls": [
{
"m.call_id": "1",
"m.devices": [
{
device_id: "Element Desktop",
session_id: "a",
expires_ts: Date.now() + 1000,
},
],
},
{
"m.call_id": "2",
"m.devices": [
{
device_id: "Element Call",
session_id: "a",
expires_ts: Date.now() - 1000,
},
],
},
],
},
]);
checkForParallelCalls(roomState);
expect(posthog.trackEvent).toHaveBeenCalledWith({
eventName: "ParallelCalls",
participantsPerCall: {
"1": 2,
"2": 1,
},
});
});
});
});

View File

@@ -1,55 +0,0 @@
/*
Copyright 2023, 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { EventType, type RoomState } from "matrix-js-sdk";
import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
function isObject(x: unknown): x is Record<string, unknown> {
return typeof x === "object" && x !== null;
}
/**
* Checks the state of a room for multiple calls happening in parallel, sending
* the details to PostHog if that is indeed what's happening. (This is unwanted
* as it indicates a split-brain scenario.)
*/
export function checkForParallelCalls(state: RoomState): void {
const now = Date.now();
const participantsPerCall = new Map<string, number>();
// For each participant in each call, increment the participant count
for (const e of state.getStateEvents(EventType.GroupCallMemberPrefix)) {
const content = e.getContent<Record<string, unknown>>();
const calls: unknown[] = Array.isArray(content["m.calls"])
? content["m.calls"]
: [];
for (const call of calls) {
if (isObject(call) && typeof call["m.call_id"] === "string") {
const devices: unknown[] = Array.isArray(call["m.devices"])
? call["m.devices"]
: [];
for (const device of devices) {
if (isObject(device) && (device["expires_ts"] as number) > now) {
const participantCount =
participantsPerCall.get(call["m.call_id"]) ?? 0;
participantsPerCall.set(call["m.call_id"], participantCount + 1);
}
}
}
}
}
if (participantsPerCall.size > 1) {
PosthogAnalytics.instance.trackEvent({
eventName: "ParallelCalls",
participantsPerCall: Object.fromEntries(participantsPerCall),
});
}
}

View File

@@ -6,13 +6,12 @@ Please see LICENSE in the repository root for full details.
*/
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import { expect, onTestFinished, test, vi } from "vitest";
import { expect, test, vi } from "vitest";
import { AutoDiscovery } from "matrix-js-sdk/lib/autodiscovery";
import EventEmitter from "events";
import { enterRTCSession, leaveRTCSession } from "../src/rtcSessionHelpers";
import { enterRTCSession } from "../src/rtcSessionHelpers";
import { mockConfig } from "./utils/test";
import { ElementWidgetActions, widget } from "./widget";
const USE_MUTI_SFU = false;
const getUrlParams = vi.hoisted(() => vi.fn(() => ({})));
@@ -116,47 +115,6 @@ test("It joins the correct Session", async () => {
);
});
async function testLeaveRTCSession(
cause: "user" | "error",
expectClose: boolean,
): Promise<void> {
vi.clearAllMocks();
const session = { leaveRoomSession: vi.fn() } as unknown as MatrixRTCSession;
await leaveRTCSession(session, cause);
expect(session.leaveRoomSession).toHaveBeenCalled();
expect(widget!.api.transport.send).toHaveBeenCalledWith(
ElementWidgetActions.HangupCall,
expect.anything(),
);
if (expectClose) {
expect(widget!.api.transport.send).toHaveBeenCalledWith(
ElementWidgetActions.Close,
expect.anything(),
);
expect(widget!.api.transport.stop).toHaveBeenCalled();
} else {
expect(widget!.api.transport.send).not.toHaveBeenCalledWith(
ElementWidgetActions.Close,
expect.anything(),
);
expect(widget!.api.transport.stop).not.toHaveBeenCalled();
}
}
test("leaveRTCSession closes the widget on a normal hangup", async () => {
await testLeaveRTCSession("user", true);
});
test("leaveRTCSession doesn't close the widget on a fatal error", async () => {
await testLeaveRTCSession("error", false);
});
test("leaveRTCSession doesn't close the widget when returning to lobby", async () => {
getUrlParams.mockReturnValue({ returnToLobby: true });
onTestFinished(() => void getUrlParams.mockReset());
await testLeaveRTCSession("user", false);
});
test("It should not fail with configuration error if homeserver config has livekit url but not fallback", async () => {
mockConfig({});
vi.spyOn(AutoDiscovery, "getRawClientConfig").mockResolvedValue({

View File

@@ -16,7 +16,7 @@ import { AutoDiscovery } from "matrix-js-sdk/lib/autodiscovery";
import { PosthogAnalytics } from "./analytics/PosthogAnalytics";
import { Config } from "./config/Config";
import { ElementWidgetActions, widget, type WidgetHelpers } from "./widget";
import { ElementWidgetActions, widget } from "./widget";
import { MatrixRTCTransportMissingError } from "./utils/errors";
import { getUrlParams } from "./UrlParams";
import { getSFUConfigWithOpenID } from "./livekit/openIDSFU.ts";
@@ -159,49 +159,3 @@ export async function enterRTCSession(
}
}
}
const widgetPostHangupProcedure = async (
widget: WidgetHelpers,
cause: "user" | "error",
promiseBeforeHangup?: Promise<unknown>,
): Promise<void> => {
try {
await widget.api.setAlwaysOnScreen(false);
} catch (e) {
logger.error("Failed to set call widget `alwaysOnScreen` to false", e);
}
// Wait for any last bits before hanging up.
await promiseBeforeHangup;
// We send the hangup event after the memberships have been updated
// calling leaveRTCSession.
// We need to wait because this makes the client hosting this widget killing the IFrame.
try {
await widget.api.transport.send(ElementWidgetActions.HangupCall, {});
} catch (e) {
logger.error("Failed to send hangup action", e);
}
// On a normal user hangup we can shut down and close the widget. But if an
// error occurs we should keep the widget open until the user reads it.
if (cause === "user" && !getUrlParams().returnToLobby) {
try {
await widget.api.transport.send(ElementWidgetActions.Close, {});
} catch (e) {
logger.error("Failed to send close action", e);
}
widget.api.transport.stop();
}
};
export async function leaveRTCSession(
rtcSession: MatrixRTCSession,
cause: "user" | "error",
promiseBeforeHangup?: Promise<unknown>,
): Promise<void> {
await rtcSession.leaveRoomSession();
if (widget) {
await widgetPostHangupProcedure(widget, cause, promiseBeforeHangup);
} else {
await promiseBeforeHangup;
}
}

View File

@@ -1,51 +0,0 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { it, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import { type ReactElement, useCallback } from "react";
import userEvent from "@testing-library/user-event";
import { BrowserRouter } from "react-router-dom";
import { GroupCallErrorBoundary } from "./room/GroupCallErrorBoundary";
import { useErrorBoundary } from "./useErrorBoundary";
import { ConnectionLostError } from "./utils/errors";
it("should show async error", async () => {
const user = userEvent.setup();
const TestComponent = (): ReactElement => {
const { showErrorBoundary } = useErrorBoundary();
const onClick = useCallback((): void => {
showErrorBoundary(new ConnectionLostError());
}, [showErrorBoundary]);
return (
<div>
<h1>HELLO</h1>
<button onClick={onClick}>Click me</button>
</div>
);
};
render(
<BrowserRouter>
<GroupCallErrorBoundary widget={null} recoveryActionHandler={vi.fn()}>
<TestComponent />
</GroupCallErrorBoundary>
</BrowserRouter>,
);
await user.click(screen.getByRole("button", { name: "Click me" }));
await screen.findByText("Connection lost");
await user.click(screen.getByRole("button", { name: "Reconnect" }));
await screen.findByText("HELLO");
});

View File

@@ -1,29 +0,0 @@
/*
Copyright 2023, 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { useMemo, useState } from "react";
export type UseErrorBoundaryApi = {
showErrorBoundary: (error: Error) => void;
};
export function useErrorBoundary(): UseErrorBoundaryApi {
const [error, setError] = useState<Error | null>(null);
const memoized: UseErrorBoundaryApi = useMemo(
() => ({
showErrorBoundary: (error: Error) => setError(error),
}),
[],
);
if (error) {
throw error;
}
return memoized;
}