mirror of
https://github.com/vector-im/element-call.git
synced 2026-02-26 05:17:04 +00:00
Lint: fix all the lint errors
This commit is contained in:
@@ -7,7 +7,6 @@ Please see LICENSE in the repository root for full details.
|
||||
|
||||
import { afterEach, beforeEach, expect, it, vi } from "vitest";
|
||||
import { render } from "@testing-library/react";
|
||||
import { type CallMembership } from "matrix-js-sdk/lib/matrixrtc";
|
||||
import {
|
||||
getTrackReferenceId,
|
||||
type TrackReference,
|
||||
@@ -15,11 +14,19 @@ import {
|
||||
import { type RemoteAudioTrack } from "livekit-client";
|
||||
import { type ReactNode } from "react";
|
||||
import { useTracks } from "@livekit/components-react";
|
||||
import { of } from "rxjs";
|
||||
|
||||
import { testAudioContext } from "../useAudioContext.test";
|
||||
import * as MediaDevicesContext from "../MediaDevicesContext";
|
||||
import { LivekitRoomAudioRenderer } from "./MatrixAudioRenderer";
|
||||
import { mockMediaDevices, mockTrack } from "../utils/test";
|
||||
import {
|
||||
mockLivekitRoom,
|
||||
mockMatrixRoomMember,
|
||||
mockMediaDevices,
|
||||
mockRtcMembership,
|
||||
mockTrack
|
||||
} from "../utils/test";
|
||||
|
||||
|
||||
export const TestAudioContextConstructor = vi.fn(() => testAudioContext);
|
||||
|
||||
@@ -52,10 +59,26 @@ const tracks = [mockTrack("test:123")];
|
||||
vi.mocked(useTracks).mockReturnValue(tracks);
|
||||
|
||||
it("should render for member", () => {
|
||||
// TODO this is duplicated test setup in all tests
|
||||
const localRtcMember = mockRtcMembership("@carol:example.org", "CCCC");
|
||||
const carol = mockMatrixRoomMember(localRtcMember);
|
||||
const p = {
|
||||
id: "test:123",
|
||||
participant: undefined,
|
||||
member: carol
|
||||
}
|
||||
const livekitRoom = mockLivekitRoom(
|
||||
{},
|
||||
{
|
||||
remoteParticipants$: of([]),
|
||||
},
|
||||
);
|
||||
const { container, queryAllByTestId } = render(
|
||||
<MediaDevicesProvider value={mockMediaDevices({})}>
|
||||
<LivekitRoomAudioRenderer
|
||||
members={[{ sender: "test", deviceId: "123" }] as CallMembership[]}
|
||||
participants={[p]}
|
||||
livekitRoom={livekitRoom}
|
||||
url={""}
|
||||
/>
|
||||
</MediaDevicesProvider>,
|
||||
);
|
||||
@@ -64,12 +87,29 @@ it("should render for member", () => {
|
||||
});
|
||||
|
||||
it("should not render without member", () => {
|
||||
const memberships = [
|
||||
{ sender: "othermember", deviceId: "123" },
|
||||
] as CallMembership[];
|
||||
// const memberships = [
|
||||
// { sender: "othermember", deviceId: "123" },
|
||||
// ] as CallMembership[];
|
||||
const localRtcMember = mockRtcMembership("@carol:example.org", "CCCC");
|
||||
const carol = mockMatrixRoomMember(localRtcMember);
|
||||
const p = {
|
||||
id: "test:123",
|
||||
participant: undefined,
|
||||
member: carol
|
||||
}
|
||||
const livekitRoom = mockLivekitRoom(
|
||||
{},
|
||||
{
|
||||
remoteParticipants$: of([]),
|
||||
},
|
||||
);
|
||||
const { container, queryAllByTestId } = render(
|
||||
<MediaDevicesProvider value={mockMediaDevices({})}>
|
||||
<LivekitRoomAudioRenderer members={memberships} />
|
||||
<LivekitRoomAudioRenderer
|
||||
participants={[p]}
|
||||
livekitRoom={livekitRoom}
|
||||
url={""}
|
||||
/>
|
||||
</MediaDevicesProvider>,
|
||||
);
|
||||
expect(container).toBeTruthy();
|
||||
@@ -77,10 +117,25 @@ it("should not render without member", () => {
|
||||
});
|
||||
|
||||
it("should not setup audioContext gain and pan if there is no need to.", () => {
|
||||
const localRtcMember = mockRtcMembership("@carol:example.org", "CCCC");
|
||||
const carol = mockMatrixRoomMember(localRtcMember);
|
||||
const p = {
|
||||
id: "test:123",
|
||||
participant: undefined,
|
||||
member: carol
|
||||
}
|
||||
const livekitRoom = mockLivekitRoom(
|
||||
{},
|
||||
{
|
||||
remoteParticipants$: of([]),
|
||||
},
|
||||
);
|
||||
render(
|
||||
<MediaDevicesProvider value={mockMediaDevices({})}>
|
||||
<LivekitRoomAudioRenderer
|
||||
members={[{ sender: "test", deviceId: "123" }] as CallMembership[]}
|
||||
participants={[p]}
|
||||
livekitRoom={livekitRoom}
|
||||
url={""}
|
||||
/>
|
||||
</MediaDevicesProvider>,
|
||||
);
|
||||
@@ -100,11 +155,25 @@ it("should setup audioContext gain and pan", () => {
|
||||
pan: 1,
|
||||
volume: 0.1,
|
||||
});
|
||||
const localRtcMember = mockRtcMembership("@carol:example.org", "CCCC");
|
||||
const carol = mockMatrixRoomMember(localRtcMember);
|
||||
const p = {
|
||||
id: "test:123",
|
||||
participant: undefined,
|
||||
member: carol
|
||||
}
|
||||
const livekitRoom = mockLivekitRoom(
|
||||
{},
|
||||
{
|
||||
remoteParticipants$: of([]),
|
||||
},
|
||||
);
|
||||
render(
|
||||
<MediaDevicesProvider value={mockMediaDevices({})}>
|
||||
<LivekitRoomAudioRenderer
|
||||
members={[{ sender: "test", deviceId: "123" }] as CallMembership[]}
|
||||
/>
|
||||
participants={[p]}
|
||||
url={""}
|
||||
livekitRoom={livekitRoom} />
|
||||
</MediaDevicesProvider>,
|
||||
);
|
||||
|
||||
|
||||
@@ -33,7 +33,9 @@ export interface MatrixAudioRendererProps {
|
||||
* that are not expected to be in the rtc session.
|
||||
*/
|
||||
participants: {
|
||||
participant: Participant;
|
||||
id: string;
|
||||
// TODO it appears to be optional as per InCallView? but what does that mean here? a rtc member not yet joined in livekit?
|
||||
participant: Participant | undefined;
|
||||
member: RoomMember;
|
||||
}[];
|
||||
/**
|
||||
@@ -82,7 +84,7 @@ export function LivekitRoomAudioRenderer({
|
||||
if (loggedInvalidIdentities.current.has(identity)) return;
|
||||
logger.warn(
|
||||
`[MatrixAudioRenderer] Audio track ${identity} from ${url} has no matching matrix call member`,
|
||||
`current members: ${participants.map((p) => p.participant.identity)}`,
|
||||
`current members: ${participants.map((p) => p.participant?.identity)}`,
|
||||
`track will not get rendered`,
|
||||
);
|
||||
loggedInvalidIdentities.current.add(identity);
|
||||
|
||||
@@ -11,7 +11,6 @@ Please see LICENSE in the repository root for full details.
|
||||
// dependency references.
|
||||
import "matrix-js-sdk/lib/browser-index";
|
||||
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import "./index.css";
|
||||
import { logger } from "matrix-js-sdk/lib/logger";
|
||||
|
||||
@@ -155,7 +155,8 @@ test("plays one sound when a hand is raised", () => {
|
||||
|
||||
act(() => {
|
||||
handRaisedSubject$.next({
|
||||
[bobRtcMember.callId]: {
|
||||
// TODO: What is this string supposed to be?
|
||||
[`${bobRtcMember.sender}:${bobRtcMember.deviceId}`]: {
|
||||
time: new Date(),
|
||||
membershipEventId: "",
|
||||
reactionEventId: "",
|
||||
|
||||
@@ -26,7 +26,6 @@ import { type RelationsContainer } from "matrix-js-sdk/lib/models/relations-cont
|
||||
import { useState } from "react";
|
||||
import { TooltipProvider } from "@vector-im/compound-web";
|
||||
|
||||
import { type MuteStates } from "./MuteStates";
|
||||
import { prefetchSounds } from "../soundUtils";
|
||||
import { useAudioContext } from "../useAudioContext";
|
||||
import { ActiveCall } from "./InCallView";
|
||||
@@ -47,6 +46,7 @@ import { ProcessorProvider } from "../livekit/TrackProcessorContext";
|
||||
import { MediaDevicesContext } from "../MediaDevicesContext";
|
||||
import { HeaderStyle } from "../UrlParams";
|
||||
import { constant } from "../state/Behavior";
|
||||
import { type MuteStates } from "../state/MuteStates.ts";
|
||||
|
||||
vi.mock("../soundUtils");
|
||||
vi.mock("../useAudioContext");
|
||||
@@ -150,7 +150,7 @@ function createGroupCallView(
|
||||
const muteState = {
|
||||
audio: { enabled: false },
|
||||
video: { enabled: false },
|
||||
} as MuteStates;
|
||||
} as unknown as MuteStates;
|
||||
const { getByText } = render(
|
||||
<BrowserRouter>
|
||||
<TooltipProvider>
|
||||
@@ -164,9 +164,10 @@ function createGroupCallView(
|
||||
skipLobby={false}
|
||||
header={HeaderStyle.Standard}
|
||||
rtcSession={rtcSession as unknown as MatrixRTCSession}
|
||||
isJoined={joined}
|
||||
muteStates={muteState}
|
||||
widget={widget}
|
||||
joined={true}
|
||||
setJoined={function(value: boolean): void { }}
|
||||
/>
|
||||
</ProcessorProvider>
|
||||
</MediaDevicesContext>
|
||||
|
||||
@@ -24,7 +24,6 @@ import { TooltipProvider } from "@vector-im/compound-web";
|
||||
import { RoomContext, useLocalParticipant } from "@livekit/components-react";
|
||||
import { RoomAndToDeviceEvents } from "matrix-js-sdk/lib/matrixrtc/RoomAndToDeviceKeyTransport";
|
||||
|
||||
import { type MuteStates } from "./MuteStates";
|
||||
import { InCallView } from "./InCallView";
|
||||
import {
|
||||
mockLivekitRoom,
|
||||
@@ -48,6 +47,7 @@ import { useRoomEncryptionSystem } from "../e2ee/sharedKeyManagement";
|
||||
import { LivekitRoomAudioRenderer } from "../livekit/MatrixAudioRenderer";
|
||||
import { MediaDevicesContext } from "../MediaDevicesContext";
|
||||
import { HeaderStyle } from "../UrlParams";
|
||||
import { type MuteStates } from "../state/MuteStates.ts";
|
||||
|
||||
// vi.hoisted(() => {
|
||||
// localStorage = {} as unknown as Storage;
|
||||
@@ -136,7 +136,7 @@ function createInCallView(): RenderResult & {
|
||||
const muteState = {
|
||||
audio: { enabled: false },
|
||||
video: { enabled: false },
|
||||
} as MuteStates;
|
||||
} as unknown as MuteStates;
|
||||
const livekitRoom = mockLivekitRoom(
|
||||
{
|
||||
localParticipant,
|
||||
@@ -176,11 +176,6 @@ function createInCallView(): RenderResult & {
|
||||
},
|
||||
}}
|
||||
matrixRoom={room}
|
||||
livekitRoom={livekitRoom}
|
||||
participantCount={0}
|
||||
onLeft={function (): void {
|
||||
throw new Error("Function not implemented.");
|
||||
}}
|
||||
onShareClick={null}
|
||||
/>
|
||||
</RoomContext>
|
||||
|
||||
@@ -23,7 +23,7 @@ import useMeasure from "react-use-measure";
|
||||
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
|
||||
import classNames from "classnames";
|
||||
import { BehaviorSubject, map } from "rxjs";
|
||||
import { useObservable, useObservableEagerState } from "observable-hooks";
|
||||
import { useObservable } from "observable-hooks";
|
||||
import { logger } from "matrix-js-sdk/lib/logger";
|
||||
import { RoomAndToDeviceEvents } from "matrix-js-sdk/lib/matrixrtc/RoomAndToDeviceKeyTransport";
|
||||
import {
|
||||
@@ -112,7 +112,6 @@ import { prefetchSounds } from "../soundUtils";
|
||||
import { useAudioContext } from "../useAudioContext";
|
||||
import ringtoneMp3 from "../sound/ringtone.mp3?url";
|
||||
import ringtoneOgg from "../sound/ringtone.ogg?url";
|
||||
import { ConnectionLostError } from "../utils/errors.ts";
|
||||
import { useTrackProcessorObservable$ } from "../livekit/TrackProcessorContext.tsx";
|
||||
|
||||
const maxTapDurationMs = 400;
|
||||
@@ -206,7 +205,8 @@ export const InCallView: FC<InCallViewProps> = ({
|
||||
useReactionsSender();
|
||||
|
||||
useWakeLock();
|
||||
const connectionState = useObservableEagerState(vm.livekitConnectionState$);
|
||||
// TODO multi-sfu This is unused now??
|
||||
// const connectionState = useObservableEagerState(vm.livekitConnectionState$);
|
||||
|
||||
// annoyingly we don't get the disconnection reason this way,
|
||||
// only by listening for the emitted event
|
||||
|
||||
@@ -5,12 +5,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { expect, describe, it, vi, beforeAll } from "vitest";
|
||||
import { expect, describe, it, beforeAll } from "vitest";
|
||||
import { render } from "@testing-library/react";
|
||||
|
||||
import { type MatrixInfo, VideoPreview } from "./VideoPreview";
|
||||
import { E2eeType } from "../e2ee/e2eeType";
|
||||
import { mockMuteStates } from "../utils/test";
|
||||
|
||||
describe("VideoPreview", () => {
|
||||
const matrixInfo: MatrixInfo = {
|
||||
@@ -42,7 +41,7 @@ describe("VideoPreview", () => {
|
||||
const { queryByRole } = render(
|
||||
<VideoPreview
|
||||
matrixInfo={matrixInfo}
|
||||
muteStates={mockMuteStates()}
|
||||
videoEnabled={true}
|
||||
videoTrack={null}
|
||||
children={<></>}
|
||||
/>,
|
||||
@@ -54,7 +53,7 @@ describe("VideoPreview", () => {
|
||||
const { queryByRole } = render(
|
||||
<VideoPreview
|
||||
matrixInfo={matrixInfo}
|
||||
muteStates={mockMuteStates()}
|
||||
videoEnabled={true}
|
||||
videoTrack={null}
|
||||
children={<></>}
|
||||
/>,
|
||||
|
||||
@@ -23,37 +23,38 @@ vi.mock("./widget", () => ({
|
||||
...actualWidget,
|
||||
widget: {
|
||||
api: {
|
||||
setAlwaysOnScreen: (): void => {},
|
||||
transport: { send: vi.fn(), reply: vi.fn(), stop: vi.fn() },
|
||||
setAlwaysOnScreen: (): void => {
|
||||
},
|
||||
transport: { send: vi.fn(), reply: vi.fn(), stop: vi.fn() }
|
||||
},
|
||||
lazyActions: new EventEmitter(),
|
||||
},
|
||||
lazyActions: new EventEmitter()
|
||||
}
|
||||
}));
|
||||
|
||||
test("It joins the correct Session", async () => {
|
||||
const focusFromOlderMembership = {
|
||||
type: "livekit",
|
||||
livekit_service_url: "http://my-oldest-member-service-url.com",
|
||||
livekit_alias: "my-oldest-member-service-alias",
|
||||
livekit_alias: "my-oldest-member-service-alias"
|
||||
};
|
||||
|
||||
const focusConfigFromWellKnown = {
|
||||
type: "livekit",
|
||||
livekit_service_url: "http://my-well-known-service-url.com",
|
||||
livekit_service_url: "http://my-well-known-service-url.com"
|
||||
};
|
||||
const focusConfigFromWellKnown2 = {
|
||||
type: "livekit",
|
||||
livekit_service_url: "http://my-well-known-service-url2.com",
|
||||
livekit_service_url: "http://my-well-known-service-url2.com"
|
||||
};
|
||||
const clientWellKnown = {
|
||||
"org.matrix.msc4143.rtc_foci": [
|
||||
focusConfigFromWellKnown,
|
||||
focusConfigFromWellKnown2,
|
||||
],
|
||||
focusConfigFromWellKnown2
|
||||
]
|
||||
};
|
||||
|
||||
mockConfig({
|
||||
livekit: { livekit_service_url: "http://my-default-service-url.com" },
|
||||
livekit: { livekit_service_url: "http://my-default-service-url.com" }
|
||||
});
|
||||
|
||||
vi.spyOn(AutoDiscovery, "getRawClientConfig").mockImplementation(
|
||||
@@ -62,7 +63,7 @@ test("It joins the correct Session", async () => {
|
||||
return Promise.resolve(clientWellKnown);
|
||||
}
|
||||
return Promise.resolve({});
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const mockedSession = vi.mocked({
|
||||
@@ -74,58 +75,64 @@ test("It joins the correct Session", async () => {
|
||||
access_token: "ACCCESS_TOKEN",
|
||||
token_type: "Bearer",
|
||||
matrix_server_name: "localhost",
|
||||
expires_in: 10000,
|
||||
}),
|
||||
},
|
||||
expires_in: 10000
|
||||
})
|
||||
}
|
||||
},
|
||||
memberships: [],
|
||||
getFocusInUse: vi.fn().mockReturnValue(focusFromOlderMembership),
|
||||
getOldestMembership: vi.fn().mockReturnValue({
|
||||
getPreferredFoci: vi.fn().mockReturnValue([focusFromOlderMembership]),
|
||||
getPreferredFoci: vi.fn().mockReturnValue([focusFromOlderMembership])
|
||||
}),
|
||||
joinRoomSession: vi.fn(),
|
||||
joinRoomSession: vi.fn()
|
||||
}) as unknown as MatrixRTCSession;
|
||||
await enterRTCSession(mockedSession, false);
|
||||
|
||||
await enterRTCSession(mockedSession, {
|
||||
livekit_alias: "roomId",
|
||||
livekit_service_url: "http://my-well-known-service-url.com",
|
||||
type: "livekit"
|
||||
},
|
||||
true);
|
||||
|
||||
expect(mockedSession.joinRoomSession).toHaveBeenLastCalledWith(
|
||||
[
|
||||
{
|
||||
livekit_alias: "my-oldest-member-service-alias",
|
||||
livekit_service_url: "http://my-oldest-member-service-url.com",
|
||||
type: "livekit",
|
||||
type: "livekit"
|
||||
},
|
||||
{
|
||||
livekit_alias: "roomId",
|
||||
livekit_service_url: "http://my-well-known-service-url.com",
|
||||
type: "livekit",
|
||||
type: "livekit"
|
||||
},
|
||||
{
|
||||
livekit_alias: "roomId",
|
||||
livekit_service_url: "http://my-well-known-service-url2.com",
|
||||
type: "livekit",
|
||||
type: "livekit"
|
||||
},
|
||||
{
|
||||
livekit_alias: "roomId",
|
||||
livekit_service_url: "http://my-default-service-url.com",
|
||||
type: "livekit",
|
||||
},
|
||||
type: "livekit"
|
||||
}
|
||||
],
|
||||
{
|
||||
focus_selection: "oldest_membership",
|
||||
type: "livekit",
|
||||
type: "livekit"
|
||||
},
|
||||
{
|
||||
manageMediaKeys: false,
|
||||
useLegacyMemberEvents: false,
|
||||
useNewMembershipManager: true,
|
||||
useExperimentalToDeviceTransport: false,
|
||||
},
|
||||
useExperimentalToDeviceTransport: false
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
async function testLeaveRTCSession(
|
||||
cause: "user" | "error",
|
||||
expectClose: boolean,
|
||||
expectClose: boolean
|
||||
): Promise<void> {
|
||||
vi.clearAllMocks();
|
||||
const session = { leaveRoomSession: vi.fn() } as unknown as MatrixRTCSession;
|
||||
@@ -133,18 +140,18 @@ async function testLeaveRTCSession(
|
||||
expect(session.leaveRoomSession).toHaveBeenCalled();
|
||||
expect(widget!.api.transport.send).toHaveBeenCalledWith(
|
||||
ElementWidgetActions.HangupCall,
|
||||
expect.anything(),
|
||||
expect.anything()
|
||||
);
|
||||
if (expectClose) {
|
||||
expect(widget!.api.transport.send).toHaveBeenCalledWith(
|
||||
ElementWidgetActions.Close,
|
||||
expect.anything(),
|
||||
expect.anything()
|
||||
);
|
||||
expect(widget!.api.transport.stop).toHaveBeenCalled();
|
||||
} else {
|
||||
expect(widget!.api.transport.send).not.toHaveBeenCalledWith(
|
||||
ElementWidgetActions.Close,
|
||||
expect.anything(),
|
||||
expect.anything()
|
||||
);
|
||||
expect(widget!.api.transport.stop).not.toHaveBeenCalled();
|
||||
}
|
||||
@@ -172,16 +179,24 @@ test("It fails with configuration error if no live kit url config is set in fall
|
||||
room: {
|
||||
roomId: "roomId",
|
||||
client: {
|
||||
getDomain: vi.fn().mockReturnValue("example.org"),
|
||||
},
|
||||
getDomain: vi.fn().mockReturnValue("example.org")
|
||||
}
|
||||
},
|
||||
memberships: [],
|
||||
getFocusInUse: vi.fn(),
|
||||
joinRoomSession: vi.fn(),
|
||||
joinRoomSession: vi.fn()
|
||||
}) as unknown as MatrixRTCSession;
|
||||
|
||||
await expect(enterRTCSession(mockedSession, false)).rejects.toThrowError(
|
||||
expect.objectContaining({ code: ErrorCode.MISSING_MATRIX_RTC_FOCUS }),
|
||||
await expect(enterRTCSession(
|
||||
mockedSession,
|
||||
{
|
||||
livekit_alias: "roomId",
|
||||
livekit_service_url: "http://my-well-known-service-url.com",
|
||||
type: "livekit"
|
||||
},
|
||||
true
|
||||
)).rejects.toThrowError(
|
||||
expect.objectContaining({ code: ErrorCode.MISSING_MATRIX_RTC_TRANSPORT })
|
||||
);
|
||||
});
|
||||
|
||||
@@ -191,9 +206,9 @@ test("It should not fail with configuration error if homeserver config has livek
|
||||
"org.matrix.msc4143.rtc_foci": [
|
||||
{
|
||||
type: "livekit",
|
||||
livekit_service_url: "http://my-well-known-service-url.com",
|
||||
},
|
||||
],
|
||||
livekit_service_url: "http://my-well-known-service-url.com"
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const mockedSession = vi.mocked({
|
||||
@@ -205,14 +220,19 @@ test("It should not fail with configuration error if homeserver config has livek
|
||||
access_token: "ACCCESS_TOKEN",
|
||||
token_type: "Bearer",
|
||||
matrix_server_name: "localhost",
|
||||
expires_in: 10000,
|
||||
}),
|
||||
},
|
||||
expires_in: 10000
|
||||
})
|
||||
}
|
||||
},
|
||||
memberships: [],
|
||||
getFocusInUse: vi.fn(),
|
||||
joinRoomSession: vi.fn(),
|
||||
joinRoomSession: vi.fn()
|
||||
}) as unknown as MatrixRTCSession;
|
||||
|
||||
await enterRTCSession(mockedSession, false);
|
||||
await enterRTCSession(mockedSession, {
|
||||
livekit_alias: "roomId",
|
||||
livekit_service_url: "http://my-well-known-service-url.com",
|
||||
type: "livekit"
|
||||
},
|
||||
true);
|
||||
});
|
||||
|
||||
@@ -9,12 +9,13 @@ import {
|
||||
catchError,
|
||||
from,
|
||||
map,
|
||||
Observable,
|
||||
type Observable,
|
||||
of,
|
||||
startWith,
|
||||
switchMap,
|
||||
startWith
|
||||
} from "rxjs";
|
||||
|
||||
// TODO where are all the comments? ::cry::
|
||||
// There used to be an unitialized state!, a state might not start in loading
|
||||
export type Async<A> =
|
||||
| { state: "loading" }
|
||||
| { state: "error"; value: Error }
|
||||
@@ -24,21 +25,22 @@ export const loading: Async<never> = { state: "loading" };
|
||||
export function error(value: Error): Async<never> {
|
||||
return { state: "error", value };
|
||||
}
|
||||
|
||||
export function ready<A>(value: A): Async<A> {
|
||||
return { state: "ready", value };
|
||||
}
|
||||
|
||||
export function async<A>(promise: Promise<A>): Observable<Async<A>> {
|
||||
export function async$<A>(promise: Promise<A>): Observable<Async<A>> {
|
||||
return from(promise).pipe(
|
||||
map(ready),
|
||||
startWith(loading),
|
||||
catchError((e) => of(error(e))),
|
||||
catchError((e: unknown) => of(error(e as Error ?? new Error("Unknown error")))),
|
||||
);
|
||||
}
|
||||
|
||||
export function mapAsync<A, B>(
|
||||
async: Async<A>,
|
||||
project: (value: A) => B,
|
||||
project: (value: A) => B
|
||||
): Async<B> {
|
||||
return async.state === "ready" ? ready(project(async.value)) : async;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ import {
|
||||
type ECConnectionState,
|
||||
} from "../livekit/useECConnectionState";
|
||||
import { E2eeType } from "../e2ee/e2eeType";
|
||||
import type { RaisedHandInfo } from "../reactions";
|
||||
import type { RaisedHandInfo, ReactionInfo } from "../reactions";
|
||||
import {
|
||||
alice,
|
||||
aliceDoppelganger,
|
||||
@@ -95,6 +95,7 @@ import { ObservableScope } from "./ObservableScope";
|
||||
import { MediaDevices } from "./MediaDevices";
|
||||
import { getValue } from "../utils/observable";
|
||||
import { type Behavior, constant } from "./Behavior";
|
||||
import type { ProcessorState } from "../livekit/TrackProcessorContext.tsx";
|
||||
|
||||
const getUrlParams = vi.hoisted(() => vi.fn(() => ({})));
|
||||
vi.mock("../UrlParams", () => ({ getUrlParams }));
|
||||
@@ -341,6 +342,7 @@ function withCallViewModel(
|
||||
.mockImplementation((_room, _eventType) => of());
|
||||
const muteStates = mockMuteStates();
|
||||
const raisedHands$ = new BehaviorSubject<Record<string, RaisedHandInfo>>({});
|
||||
const reactions$ = new BehaviorSubject<Record<string, ReactionInfo>>({});
|
||||
|
||||
const vm = new CallViewModel(
|
||||
rtcSession as unknown as MatrixRTCSession,
|
||||
@@ -349,7 +351,8 @@ function withCallViewModel(
|
||||
muteStates,
|
||||
options,
|
||||
raisedHands$,
|
||||
new BehaviorSubject({}),
|
||||
reactions$,
|
||||
new BehaviorSubject<ProcessorState>({ processor: undefined, supported: undefined }),
|
||||
);
|
||||
|
||||
onTestFinished(() => {
|
||||
|
||||
@@ -132,7 +132,7 @@ import { getUrlParams } from "../UrlParams";
|
||||
import { type ProcessorState } from "../livekit/TrackProcessorContext";
|
||||
import { ElementWidgetActions, widget } from "../widget";
|
||||
import { PublishConnection } from "./PublishConnection.ts";
|
||||
import { type Async, async, mapAsync, ready } from "./Async";
|
||||
import { type Async, async$, mapAsync, ready } from "./Async";
|
||||
|
||||
export interface CallViewModelOptions {
|
||||
encryptionSystem: EncryptionSystem;
|
||||
@@ -520,7 +520,7 @@ export class CallViewModel extends ViewModel {
|
||||
joined
|
||||
? combineLatest(
|
||||
[
|
||||
async(this.preferredTransport),
|
||||
async$(this.preferredTransport),
|
||||
this.memberships$,
|
||||
multiSfu.value$,
|
||||
],
|
||||
@@ -1953,7 +1953,10 @@ export class CallViewModel extends ViewModel {
|
||||
.subscribe(({ start, stop }) => {
|
||||
for (const c of stop) {
|
||||
logger.info(`Disconnecting from ${c.localTransport.livekit_service_url}`);
|
||||
c.stop();
|
||||
c.stop().catch((err) => {
|
||||
// TODO: better error handling
|
||||
logger.error("MuteState: handler error", err);
|
||||
});;
|
||||
}
|
||||
for (const c of start) {
|
||||
c.start().then(
|
||||
|
||||
@@ -6,7 +6,6 @@ Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { afterEach, describe, expect, it, type Mock, type MockedObject, vi } from "vitest";
|
||||
import type { CallMembership, LivekitTransport } from "matrix-js-sdk/lib/matrixrtc";
|
||||
import { BehaviorSubject, of } from "rxjs";
|
||||
import {
|
||||
ConnectionState,
|
||||
@@ -18,8 +17,8 @@ import {
|
||||
import fetchMock from "fetch-mock";
|
||||
import EventEmitter from "events";
|
||||
import { type IOpenIDToken } from "matrix-js-sdk";
|
||||
import { type BackgroundOptions, type ProcessorWrapper } from "@livekit/track-processors";
|
||||
|
||||
import type { CallMembership, LivekitTransport } from "matrix-js-sdk/lib/matrixrtc";
|
||||
import { type ConnectionOpts, type FocusConnectionState, RemoteConnection } from "./Connection.ts";
|
||||
import { ObservableScope } from "./ObservableScope.ts";
|
||||
import { type OpenIDClientParts } from "../livekit/openIDSFU.ts";
|
||||
@@ -29,7 +28,6 @@ import { mockMediaDevices, mockMuteStates } from "../utils/test.ts";
|
||||
import type { ProcessorState } from "../livekit/TrackProcessorContext.tsx";
|
||||
import { type MuteStates } from "./MuteStates.ts";
|
||||
|
||||
|
||||
let testScope: ObservableScope;
|
||||
|
||||
let client: MockedObject<OpenIDClientParts>;
|
||||
@@ -551,7 +549,7 @@ describe("Publishing participants observations", () => {
|
||||
});
|
||||
|
||||
|
||||
it("should be scoped to parent scope", async () => {
|
||||
it("should be scoped to parent scope", (): void => {
|
||||
setupTest();
|
||||
|
||||
const connection = setupRemoteConnection();
|
||||
@@ -613,7 +611,7 @@ describe("PublishConnection", () => {
|
||||
let roomFactoryMock: Mock<() => LivekitRoom>;
|
||||
let muteStates: MockedObject<MuteStates>;
|
||||
|
||||
function setUpPublishConnection() {
|
||||
function setUpPublishConnection(): void {
|
||||
setupTest();
|
||||
|
||||
roomFactoryMock = vi.fn().mockReturnValue(fakeLivekitRoom);
|
||||
@@ -673,9 +671,13 @@ describe("PublishConnection", () => {
|
||||
}
|
||||
};
|
||||
|
||||
// TODO understand what is wrong with our mocking that requires ts-expect-error
|
||||
const fakeDevices = mockMediaDevices({
|
||||
// @ts-expect-error Mocking only
|
||||
audioInput,
|
||||
// @ts-expect-error Mocking only
|
||||
videoInput,
|
||||
// @ts-expect-error Mocking only
|
||||
audioOutput
|
||||
});
|
||||
|
||||
|
||||
@@ -88,7 +88,10 @@ class MuteState<Label, Selected> {
|
||||
} else {
|
||||
subscriber.next(enabled);
|
||||
syncing = true;
|
||||
sync();
|
||||
sync().catch((err) => {
|
||||
// TODO: better error handling
|
||||
logger.error("MuteState: handler error", err);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -97,7 +100,10 @@ class MuteState<Label, Selected> {
|
||||
latestDesired = desired;
|
||||
if (syncing === false) {
|
||||
syncing = true;
|
||||
sync();
|
||||
sync().catch((err) => {
|
||||
// TODO: better error handling
|
||||
logger.error("MuteState: handler error", err);
|
||||
});
|
||||
}
|
||||
});
|
||||
return (): void => s.unsubscribe();
|
||||
@@ -132,6 +138,7 @@ class MuteState<Label, Selected> {
|
||||
) {}
|
||||
}
|
||||
|
||||
// TODO there is another MuteStates in src/room/MuteStates.tsx ?? why
|
||||
export class MuteStates {
|
||||
public readonly audio = new MuteState(
|
||||
this.scope,
|
||||
|
||||
@@ -19,7 +19,7 @@ import { type ComponentProps } from "react";
|
||||
|
||||
import { MediaView } from "./MediaView";
|
||||
import { EncryptionStatus } from "../state/MediaViewModel";
|
||||
import { mockLocalParticipant } from "../utils/test";
|
||||
import { mockLocalParticipant, mockMatrixRoomMember, mockRtcMembership } from "../utils/test";
|
||||
|
||||
describe("MediaView", () => {
|
||||
const participant = mockLocalParticipant({});
|
||||
@@ -45,7 +45,10 @@ describe("MediaView", () => {
|
||||
mirror: false,
|
||||
unencryptedWarning: false,
|
||||
video: trackReference,
|
||||
member: undefined,
|
||||
member: mockMatrixRoomMember(
|
||||
mockRtcMembership("@alice:example.org", "CCCC"),
|
||||
{ name: "some name" },
|
||||
),
|
||||
localParticipant: false,
|
||||
focusable: true,
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
import { map, type Observable, of, type SchedulerLike } from "rxjs";
|
||||
import { type RunHelpers, TestScheduler } from "rxjs/testing";
|
||||
import { expect, vi, vitest } from "vitest";
|
||||
import { expect, type MockedObject, vi, vitest } from "vitest";
|
||||
import {
|
||||
type RoomMember,
|
||||
type Room as MatrixRoom,
|
||||
@@ -205,6 +205,9 @@ export function mockMatrixRoomMember(
|
||||
return {
|
||||
...mockEmitter(),
|
||||
userId: rtcMembership.sender,
|
||||
getMxcAvatarUrl(): string | undefined {
|
||||
return undefined;
|
||||
},
|
||||
...member,
|
||||
} as RoomMember;
|
||||
}
|
||||
@@ -416,13 +419,13 @@ export const deviceStub = {
|
||||
select(): void {},
|
||||
};
|
||||
|
||||
export function mockMediaDevices(data: Partial<MediaDevices>): MediaDevices {
|
||||
return {
|
||||
export function mockMediaDevices(data: Partial<MediaDevices>): MockedObject<MediaDevices> {
|
||||
return vi.mocked<MediaDevices>({
|
||||
audioInput: deviceStub,
|
||||
audioOutput: deviceStub,
|
||||
videoInput: deviceStub,
|
||||
...data,
|
||||
} as MediaDevices;
|
||||
} as MediaDevices);
|
||||
}
|
||||
|
||||
export function mockMuteStates(
|
||||
|
||||
Reference in New Issue
Block a user