Remove LegacyCallHandler singleton (#34086)
* Remove dead code * Remove LegacyCallHandler singleton Route via SDKContext to cut import cycles * Remove unused setting * Fix tests * Fix tests * Cascade SDKContext through PersistedElement * Improve coverage * Iterate * Improve coverage * Improve coverage
This commit is contained in:
@@ -40,6 +40,7 @@ import SettingsStore from "../../src/settings/SettingsStore";
|
||||
import { UIFeature } from "../../src/settings/UIFeature";
|
||||
import { createAudioContext } from "../../src/audio/compat";
|
||||
import * as ManagedHybrid from "../../src/widgets/ManagedHybrid";
|
||||
import { TestSDKContext } from "./TestSDKContext.ts";
|
||||
|
||||
jest.mock("../../src/Modal");
|
||||
|
||||
@@ -165,7 +166,7 @@ describe("LegacyCallHandler", () => {
|
||||
});
|
||||
};
|
||||
|
||||
callHandler = new LegacyCallHandler();
|
||||
callHandler = new LegacyCallHandler(new TestSDKContext());
|
||||
callHandler.start();
|
||||
|
||||
mocked(getFunctionalMembers).mockReturnValue([FUNCTIONAL_USER]);
|
||||
@@ -238,8 +239,6 @@ describe("LegacyCallHandler", () => {
|
||||
callHandler.stop();
|
||||
// @ts-ignore
|
||||
DMRoomMap.setShared(null);
|
||||
// @ts-ignore
|
||||
window.mxLegacyCallHandler = null;
|
||||
MatrixClientPeg.unset();
|
||||
|
||||
document.body.removeChild(audioElement);
|
||||
@@ -373,7 +372,7 @@ describe("LegacyCallHandler without third party protocols", () => {
|
||||
};
|
||||
|
||||
mocked(createAudioContext).mockReturnValue(mockAudioContext as unknown as AudioContext);
|
||||
callHandler = new LegacyCallHandler();
|
||||
callHandler = new LegacyCallHandler(new TestSDKContext());
|
||||
callHandler.start();
|
||||
|
||||
const nativeRoomAlice = mkStubDM(NATIVE_ROOM_ALICE, NATIVE_ALICE);
|
||||
@@ -423,8 +422,6 @@ describe("LegacyCallHandler without third party protocols", () => {
|
||||
callHandler.stop();
|
||||
// @ts-ignore
|
||||
DMRoomMap.setShared(null);
|
||||
// @ts-ignore
|
||||
window.mxLegacyCallHandler = null;
|
||||
MatrixClientPeg.unset();
|
||||
|
||||
document.body.removeChild(audioElement);
|
||||
|
||||
@@ -18,6 +18,7 @@ import { type SpaceStoreClass } from "../../src/stores/spaces/SpaceStore";
|
||||
import { type WidgetLayoutStore } from "../../src/stores/widgets/WidgetLayoutStore";
|
||||
import { type WidgetPermissionStore } from "../../src/stores/widgets/WidgetPermissionStore";
|
||||
import type WidgetStore from "../../src/stores/WidgetStore";
|
||||
import type LegacyCallHandler from "../../src/LegacyCallHandler.tsx";
|
||||
|
||||
/**
|
||||
* A class which provides the same API as SDKContextClass but adds additional unsafe setters which can
|
||||
@@ -34,6 +35,7 @@ export class TestSDKContext extends SDKContextClass {
|
||||
declare public _PosthogAnalytics?: PosthogAnalytics;
|
||||
declare public _SlidingSyncManager?: SlidingSyncManager;
|
||||
declare public _SpaceStore?: SpaceStoreClass;
|
||||
declare public _LegacyCallHandler?: LegacyCallHandler;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@@ -6,12 +6,13 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type MatrixClient, type MatrixEvent, EventType } from "matrix-js-sdk/src/matrix";
|
||||
import { type MatrixClient, MatrixEvent, EventType } from "matrix-js-sdk/src/matrix";
|
||||
import { CallState } from "matrix-js-sdk/src/webrtc/call";
|
||||
|
||||
import { stubClient } from "../../../test-utils";
|
||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||
import LegacyCallEventGrouper from "../../../../src/components/structures/LegacyCallEventGrouper";
|
||||
import { SDKContextClass } from "../../../../src/contexts/SDKContextClass.ts";
|
||||
|
||||
const MY_USER_ID = "@me:here";
|
||||
const THEIR_USER_ID = "@they:here";
|
||||
@@ -145,4 +146,83 @@ describe("LegacyCallEventGrouper", () => {
|
||||
|
||||
expect(grouper.isVoice).toBe(false);
|
||||
});
|
||||
|
||||
it("should be able to answer call", () => {
|
||||
const grouper = new LegacyCallEventGrouper();
|
||||
grouper.add(
|
||||
new MatrixEvent({
|
||||
content: {
|
||||
call_id: "callId",
|
||||
},
|
||||
type: EventType.CallInvite,
|
||||
sender: THEIR_USER_ID,
|
||||
room_id: "!room:server",
|
||||
}),
|
||||
);
|
||||
|
||||
jest.spyOn(SDKContextClass.instance.legacyCallHandler, "answerCall");
|
||||
grouper.answerCall();
|
||||
expect(SDKContextClass.instance.legacyCallHandler.answerCall).toHaveBeenCalledWith("!room:server");
|
||||
});
|
||||
|
||||
it("should be able to reject call", () => {
|
||||
const grouper = new LegacyCallEventGrouper();
|
||||
grouper.add(
|
||||
new MatrixEvent({
|
||||
content: {
|
||||
call_id: "callId",
|
||||
},
|
||||
type: EventType.CallInvite,
|
||||
sender: THEIR_USER_ID,
|
||||
room_id: "!room:server",
|
||||
}),
|
||||
);
|
||||
|
||||
jest.spyOn(SDKContextClass.instance.legacyCallHandler, "hangupOrReject");
|
||||
grouper.rejectCall();
|
||||
expect(SDKContextClass.instance.legacyCallHandler.hangupOrReject).toHaveBeenCalledWith("!room:server", true);
|
||||
});
|
||||
|
||||
it("should be able to callback call", () => {
|
||||
const grouper = new LegacyCallEventGrouper();
|
||||
grouper.add(
|
||||
new MatrixEvent({
|
||||
content: {
|
||||
call_id: "callId",
|
||||
},
|
||||
type: EventType.CallHangup,
|
||||
sender: THEIR_USER_ID,
|
||||
room_id: "!room:server",
|
||||
}),
|
||||
);
|
||||
|
||||
jest.spyOn(SDKContextClass.instance.legacyCallHandler, "placeCall");
|
||||
grouper.callBack();
|
||||
expect(SDKContextClass.instance.legacyCallHandler.placeCall).toHaveBeenCalledWith("!room:server", "video");
|
||||
});
|
||||
|
||||
it("should be able to toggle call silenced", () => {
|
||||
const grouper = new LegacyCallEventGrouper();
|
||||
grouper.add(
|
||||
new MatrixEvent({
|
||||
content: {
|
||||
call_id: "callId",
|
||||
},
|
||||
type: EventType.CallHangup,
|
||||
sender: THEIR_USER_ID,
|
||||
room_id: "!room:server",
|
||||
}),
|
||||
);
|
||||
|
||||
jest.spyOn(SDKContextClass.instance.legacyCallHandler, "unSilenceCall");
|
||||
jest.spyOn(SDKContextClass.instance.legacyCallHandler, "silenceCall");
|
||||
|
||||
jest.spyOn(SDKContextClass.instance.legacyCallHandler, "isCallSilenced").mockReturnValue(false);
|
||||
grouper.toggleSilenced();
|
||||
expect(SDKContextClass.instance.legacyCallHandler.silenceCall).toHaveBeenCalledWith("callId");
|
||||
|
||||
jest.spyOn(SDKContextClass.instance.legacyCallHandler, "isCallSilenced").mockReturnValue(true);
|
||||
grouper.toggleSilenced();
|
||||
expect(SDKContextClass.instance.legacyCallHandler.unSilenceCall).toHaveBeenCalledWith("callId");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -46,7 +46,6 @@ import {
|
||||
} from "../../../test-utils";
|
||||
import * as leaveRoomUtils from "../../../../src/utils/leave-behaviour";
|
||||
import { OidcClientError } from "../../../../src/utils/oidc/error";
|
||||
import LegacyCallHandler from "../../../../src/LegacyCallHandler";
|
||||
import { CallStore } from "../../../../src/stores/CallStore";
|
||||
import { type Call } from "../../../../src/models/Call";
|
||||
import { PosthogAnalytics } from "../../../../src/PosthogAnalytics";
|
||||
@@ -1109,7 +1108,7 @@ describe("<MatrixChat />", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
// stub out various cleanup functions
|
||||
jest.spyOn(LegacyCallHandler.instance, "hangupAllCalls")
|
||||
jest.spyOn(SDKContextClass.instance.legacyCallHandler, "hangupAllCalls")
|
||||
.mockClear()
|
||||
.mockImplementation(() => {});
|
||||
jest.spyOn(PosthogAnalytics.instance, "logout").mockImplementation(() => {});
|
||||
@@ -1134,7 +1133,7 @@ describe("<MatrixChat />", () => {
|
||||
it("should hangup all legacy calls", async () => {
|
||||
await getComponentAndWaitForReady();
|
||||
await dispatchLogoutAndWait();
|
||||
expect(LegacyCallHandler.instance.hangupAllCalls).toHaveBeenCalled();
|
||||
expect(SDKContextClass.instance.legacyCallHandler.hangupAllCalls).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should disconnect all calls", async () => {
|
||||
|
||||
@@ -39,7 +39,7 @@ import { WidgetMessagingStore } from "../../../../../src/stores/widgets/WidgetMe
|
||||
import { ModuleRunner } from "../../../../../src/modules/ModuleRunner";
|
||||
import { ModuleApi } from "../../../../../src/modules/Api";
|
||||
import { RoomPermalinkCreator } from "../../../../../src/utils/permalinks/Permalinks";
|
||||
import { SDKContextClass } from "../../../../../src/contexts/SDKContextClass";
|
||||
import { TestSDKContext } from "../../../TestSDKContext.ts";
|
||||
|
||||
jest.mock("../../../../../src/stores/OwnProfileStore", () => ({
|
||||
OwnProfileStore: {
|
||||
@@ -56,7 +56,7 @@ const realGetValue = SettingsStore.getValue;
|
||||
|
||||
describe("AppTile", () => {
|
||||
let cli: MatrixClient;
|
||||
let sdkContext: SDKContextClass;
|
||||
let sdkContext: TestSDKContext;
|
||||
let r1: Room;
|
||||
let r2: Room;
|
||||
const resizeNotifier = new ResizeNotifier();
|
||||
@@ -118,18 +118,19 @@ describe("AppTile", () => {
|
||||
beforeEach(async () => {
|
||||
// Do not carry across settings from previous tests
|
||||
SettingsStore.reset();
|
||||
sdkContext = new SDKContextClass();
|
||||
sdkContext = new TestSDKContext();
|
||||
sdkContext._client = cli;
|
||||
// @ts-ignore
|
||||
await WidgetMessagingStore.instance.onReady();
|
||||
|
||||
// Wake up various stores we rely on
|
||||
WidgetLayoutStore.instance.useUnitTestClient(cli);
|
||||
sdkContext.widgetLayoutStore.useUnitTestClient(cli);
|
||||
// @ts-ignore
|
||||
await WidgetLayoutStore.instance.onReady();
|
||||
await sdkContext.widgetLayoutStore.onReady();
|
||||
|
||||
RightPanelStore.instance.useUnitTestClient(cli);
|
||||
sdkContext.rightPanelStore.useUnitTestClient(cli);
|
||||
// @ts-ignore
|
||||
await RightPanelStore.instance.onReady();
|
||||
await sdkContext.rightPanelStore.onReady();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
@@ -162,13 +163,12 @@ describe("AppTile", () => {
|
||||
|
||||
// Run initial render with room 1, and also running lifecycle methods
|
||||
const renderResult = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<RightPanel
|
||||
room={r1}
|
||||
resizeNotifier={resizeNotifier}
|
||||
permalinkCreator={new RoomPermalinkCreator(r1, r1.roomId)}
|
||||
/>
|
||||
</MatrixClientContext.Provider>,
|
||||
<RightPanel
|
||||
room={r1}
|
||||
resizeNotifier={resizeNotifier}
|
||||
permalinkCreator={new RoomPermalinkCreator(r1, r1.roomId)}
|
||||
/>,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
act(() =>
|
||||
dis.dispatch({
|
||||
@@ -232,13 +232,12 @@ describe("AppTile", () => {
|
||||
|
||||
// Run initial render with room 1, and also running lifecycle methods
|
||||
const renderResult = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<RightPanel
|
||||
room={r1}
|
||||
resizeNotifier={resizeNotifier}
|
||||
permalinkCreator={new RoomPermalinkCreator(r1, r1.roomId)}
|
||||
/>
|
||||
</MatrixClientContext.Provider>,
|
||||
<RightPanel
|
||||
room={r1}
|
||||
resizeNotifier={resizeNotifier}
|
||||
permalinkCreator={new RoomPermalinkCreator(r1, r1.roomId)}
|
||||
/>,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
act(() =>
|
||||
dis.dispatch({
|
||||
@@ -341,6 +340,47 @@ describe("AppTile", () => {
|
||||
expect(ActiveWidgetStore.instance.isLive("1", "r1")).toBe(true);
|
||||
});
|
||||
|
||||
it("should hangup Jitsi call when room is left", async () => {
|
||||
const app: IApp = {
|
||||
id: "3",
|
||||
eventId: "jitsi1",
|
||||
roomId: "r2",
|
||||
type: MatrixWidgetType.JitsiMeet,
|
||||
url: "https://jitsi.example.com",
|
||||
name: "Jitsi Conference",
|
||||
creatorUserId: cli.getSafeUserId(),
|
||||
avatar_url: undefined,
|
||||
};
|
||||
|
||||
const { queryByRole, getByText } = render(
|
||||
<AppTile key={app.id} app={app} room={r2} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
await waitForElementToBeRemoved(() => queryByRole("progressbar"));
|
||||
|
||||
expect(getByText("Jitsi Conference")).toBeInTheDocument();
|
||||
|
||||
// Switch to room 1
|
||||
dis.dispatch(
|
||||
{
|
||||
action: Action.ViewRoom,
|
||||
room_id: "r1",
|
||||
},
|
||||
true,
|
||||
);
|
||||
jest.spyOn(ActiveWidgetStore.instance, "getWidgetPersistence").mockReturnValue(true);
|
||||
jest.spyOn(sdkContext.legacyCallHandler, "hangupCallApp");
|
||||
dis.dispatch(
|
||||
{
|
||||
action: Action.AfterLeaveRoom,
|
||||
room_id: "r2",
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
expect(sdkContext.legacyCallHandler.hangupCallApp).toHaveBeenCalledWith(app.roomId);
|
||||
});
|
||||
|
||||
describe("for a pinned widget", () => {
|
||||
let moveToContainerSpy: jest.SpyInstance<void, [room: Room, widget: IWidget, toContainer: Container]>;
|
||||
beforeEach(async () => {
|
||||
@@ -349,9 +389,8 @@ describe("AppTile", () => {
|
||||
|
||||
it("should render", async () => {
|
||||
const renderResult = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<AppTile key={app1.id} app={app1} room={r1} />
|
||||
</MatrixClientContext.Provider>,
|
||||
<AppTile key={app1.id} app={app1} room={r1} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
await waitForElementToBeRemoved(() => renderResult.queryByRole("progressbar"));
|
||||
const { asFragment } = renderResult;
|
||||
@@ -361,9 +400,8 @@ describe("AppTile", () => {
|
||||
|
||||
it("should not display the »Popout widget« button", async () => {
|
||||
const renderResult = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<AppTile key={app1.id} app={app1} room={r1} />
|
||||
</MatrixClientContext.Provider>,
|
||||
<AppTile key={app1.id} app={app1} room={r1} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
await waitForElementToBeRemoved(() => renderResult.queryByRole("progressbar"));
|
||||
expect(renderResult.queryByLabelText("Popout widget")).not.toBeInTheDocument();
|
||||
@@ -371,20 +409,34 @@ describe("AppTile", () => {
|
||||
|
||||
it("clicking 'minimise' should send the widget to the right", async () => {
|
||||
const renderResult = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<AppTile key={app1.id} app={app1} room={r1} />
|
||||
</MatrixClientContext.Provider>,
|
||||
<AppTile key={app1.id} app={app1} room={r1} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
await waitForElementToBeRemoved(() => renderResult.queryByRole("progressbar"));
|
||||
await userEvent.click(renderResult.getByLabelText("Minimise"));
|
||||
expect(moveToContainerSpy).toHaveBeenCalledWith(r1, app1, "right");
|
||||
});
|
||||
|
||||
it("should close right panel timeline when minimising widget", async () => {
|
||||
const renderResult = render(
|
||||
<AppTile key={app1.id} app={app1} room={r1} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
await waitForElementToBeRemoved(() => renderResult.queryByRole("progressbar"));
|
||||
|
||||
jest.spyOn(sdkContext.rightPanelStore, "currentCardForRoom").mockReturnValue({
|
||||
phase: RightPanelPhases.Timeline,
|
||||
});
|
||||
jest.spyOn(sdkContext.rightPanelStore, "popCard");
|
||||
|
||||
await userEvent.click(renderResult.getByLabelText("Minimise"));
|
||||
expect(sdkContext.rightPanelStore.popCard).toHaveBeenCalledWith(r1.roomId);
|
||||
});
|
||||
|
||||
it("clicking 'maximise' should send the widget to the center", async () => {
|
||||
const renderResult = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<AppTile key={app1.id} app={app1} room={r1} />
|
||||
</MatrixClientContext.Provider>,
|
||||
<AppTile key={app1.id} app={app1} room={r1} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
await waitForElementToBeRemoved(() => renderResult.queryByRole("progressbar"));
|
||||
await userEvent.click(renderResult.getByLabelText("Maximise"));
|
||||
@@ -400,9 +452,8 @@ describe("AppTile", () => {
|
||||
|
||||
// userId and creatorUserId are different
|
||||
const { container, asFragment, queryByRole } = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<AppTile key={app1.id} app={app1} room={r1} userId="@user1" creatorUserId="@userAnother" />
|
||||
</MatrixClientContext.Provider>,
|
||||
<AppTile key={app1.id} app={app1} room={r1} userId="@user1" creatorUserId="@userAnother" />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
expect(container.querySelector(".mx_Spinner")).toBeFalsy();
|
||||
expect(queryByRole("button", { name: "Continue" })).toBeInTheDocument();
|
||||
@@ -418,9 +469,8 @@ describe("AppTile", () => {
|
||||
|
||||
// userId and creatorUserId are different
|
||||
const renderResult = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<AppTile key={app1.id} app={app1} room={r1} userId="@user1" creatorUserId="@userAnother" />
|
||||
</MatrixClientContext.Provider>,
|
||||
<AppTile key={app1.id} app={app1} room={r1} userId="@user1" creatorUserId="@userAnother" />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
await waitForElementToBeRemoved(() => renderResult.queryByRole("progressbar"));
|
||||
|
||||
@@ -440,9 +490,8 @@ describe("AppTile", () => {
|
||||
|
||||
// userId and creatorUserId are different so legacy path would show "Continue"
|
||||
const renderResult = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<AppTile key={app1.id} app={app1} room={r1} userId="@user1" creatorUserId="@userAnother" />
|
||||
</MatrixClientContext.Provider>,
|
||||
<AppTile key={app1.id} app={app1} room={r1} userId="@user1" creatorUserId="@userAnother" />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
|
||||
// The new API runs async in componentDidMount, so wait for it to take effect
|
||||
@@ -466,9 +515,8 @@ describe("AppTile", () => {
|
||||
|
||||
it("clicking 'un-maximise' should send the widget to the top", async () => {
|
||||
const renderResult = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<AppTile key={app1.id} app={app1} room={r1} />
|
||||
</MatrixClientContext.Provider>,
|
||||
<AppTile key={app1.id} app={app1} room={r1} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
await waitForElementToBeRemoved(() => renderResult.queryByRole("progressbar"));
|
||||
await userEvent.click(renderResult.getByLabelText("Un-maximise"));
|
||||
@@ -496,9 +544,8 @@ describe("AppTile", () => {
|
||||
|
||||
it("should display the »Popout widget« button", async () => {
|
||||
const renderResult = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<AppTile key={app1.id} app={app1} room={r1} />
|
||||
</MatrixClientContext.Provider>,
|
||||
<AppTile key={app1.id} app={app1} room={r1} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
await waitForElementToBeRemoved(() => renderResult.queryByRole("progressbar"));
|
||||
expect(renderResult.getByLabelText("Popout widget")).toBeInTheDocument();
|
||||
@@ -509,9 +556,8 @@ describe("AppTile", () => {
|
||||
describe("for a persistent app", () => {
|
||||
it("should render", async () => {
|
||||
const { asFragment, queryByRole } = render(
|
||||
<MatrixClientContext.Provider value={cli}>
|
||||
<AppTile key={app1.id} app={app1} room={r1} fullWidth={true} miniMode={true} showMenubar={false} />
|
||||
</MatrixClientContext.Provider>,
|
||||
<AppTile key={app1.id} app={app1} room={r1} fullWidth={true} miniMode={true} showMenubar={false} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
await waitForElementToBeRemoved(() => queryByRole("progressbar"));
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
|
||||
@@ -46,7 +46,6 @@ import { ScopedRoomContextProvider } from "../../../../../../src/contexts/Scoped
|
||||
import RoomContext, { type RoomContextType } from "../../../../../../src/contexts/RoomContext";
|
||||
import RightPanelStore from "../../../../../../src/stores/right-panel/RightPanelStore";
|
||||
import { RightPanelPhases } from "../../../../../../src/stores/right-panel/RightPanelStorePhases";
|
||||
import LegacyCallHandler from "../../../../../../src/LegacyCallHandler";
|
||||
import SettingsStore from "../../../../../../src/settings/SettingsStore";
|
||||
import SdkConfig from "../../../../../../src/SdkConfig";
|
||||
import dispatcher from "../../../../../../src/dispatcher/dispatcher";
|
||||
@@ -60,6 +59,7 @@ import WidgetStore, { type IApp } from "../../../../../../src/stores/WidgetStore
|
||||
import { UIFeature } from "../../../../../../src/settings/UIFeature";
|
||||
import { SettingLevel } from "../../../../../../src/settings/SettingLevel";
|
||||
import { ElementCallMemberEventType } from "../../../../../../src/call-types";
|
||||
import { SDKContextClass } from "../../../../../../src/contexts/SDKContextClass.ts";
|
||||
|
||||
jest.mock("../../../../../../src/utils/ShieldUtils");
|
||||
jest.mock("../../../../../../src/hooks/right-panel/useCurrentPhase", () => ({
|
||||
@@ -365,7 +365,7 @@ describe("RoomHeader", () => {
|
||||
expect(voiceButton).not.toHaveAttribute("aria-disabled", "true");
|
||||
expect(videoButton).not.toHaveAttribute("aria-disabled", "true");
|
||||
|
||||
const placeCallSpy = jest.spyOn(LegacyCallHandler.instance, "placeCall");
|
||||
const placeCallSpy = jest.spyOn(SDKContextClass.instance.legacyCallHandler, "placeCall");
|
||||
|
||||
await user.click(voiceButton);
|
||||
expect(placeCallSpy).toHaveBeenLastCalledWith(room.roomId, CallType.Voice);
|
||||
@@ -376,7 +376,7 @@ describe("RoomHeader", () => {
|
||||
|
||||
it("you can't call if there's already a call", () => {
|
||||
mockRoomMembers(room, 2);
|
||||
jest.spyOn(LegacyCallHandler.instance, "getCallForRoom").mockReturnValue(
|
||||
jest.spyOn(SDKContextClass.instance.legacyCallHandler, "getCallForRoom").mockReturnValue(
|
||||
// The JS-SDK does not export the class `MatrixCall` only the type
|
||||
{} as MatrixCall,
|
||||
);
|
||||
@@ -508,7 +508,7 @@ describe("RoomHeader", () => {
|
||||
|
||||
it("disables calling if there's a jitsi call", () => {
|
||||
mockRoomMembers(room, 2);
|
||||
jest.spyOn(LegacyCallHandler.instance, "getCallForRoom").mockReturnValue(
|
||||
jest.spyOn(SDKContextClass.instance.legacyCallHandler, "getCallForRoom").mockReturnValue(
|
||||
// The JS-SDK does not export the class `MatrixCall` only the type
|
||||
{} as MatrixCall,
|
||||
);
|
||||
@@ -532,7 +532,7 @@ describe("RoomHeader", () => {
|
||||
expect(voiceButton).not.toHaveAttribute("aria-disabled", "true");
|
||||
expect(videoButton).not.toHaveAttribute("aria-disabled", "true");
|
||||
|
||||
const placeCallSpy = jest.spyOn(LegacyCallHandler.instance, "placeCall");
|
||||
const placeCallSpy = jest.spyOn(SDKContextClass.instance.legacyCallHandler, "placeCall");
|
||||
await user.click(voiceButton);
|
||||
expect(placeCallSpy).toHaveBeenLastCalledWith(room.roomId, CallType.Voice);
|
||||
|
||||
@@ -554,7 +554,7 @@ describe("RoomHeader", () => {
|
||||
const videoButton = screen.getByRole("button", { name: "Video call" });
|
||||
expect(videoButton).not.toHaveAttribute("aria-disabled", "true");
|
||||
|
||||
const placeCallSpy = jest.spyOn(LegacyCallHandler.instance, "placeCall");
|
||||
const placeCallSpy = jest.spyOn(SDKContextClass.instance.legacyCallHandler, "placeCall");
|
||||
await user.click(videoButton);
|
||||
expect(placeCallSpy).toHaveBeenLastCalledWith(room.roomId, CallType.Video);
|
||||
});
|
||||
|
||||
+10
-1
@@ -15,6 +15,8 @@ import { shouldShowComponent } from "../../../../../../src/customisations/helper
|
||||
import { MetaSpace } from "../../../../../../src/stores/spaces";
|
||||
import { LandmarkNavigation } from "../../../../../../src/accessibility/LandmarkNavigation";
|
||||
import { ReleaseAnnouncementStore } from "../../../../../../src/stores/ReleaseAnnouncementStore";
|
||||
import { clientAndSDKContextRenderOptions, createTestClient } from "../../../../../test-utils";
|
||||
import { TestSDKContext } from "../../../../TestSDKContext.ts";
|
||||
|
||||
jest.mock("../../../../../../src/customisations/helpers/UIComponents", () => ({
|
||||
shouldShowComponent: jest.fn(),
|
||||
@@ -34,8 +36,15 @@ jest.mock("../../../../../../src/accessibility/LandmarkNavigation", () => ({
|
||||
jest.spyOn(ReleaseAnnouncementStore.instance, "getReleaseAnnouncement").mockReturnValue(null);
|
||||
|
||||
describe("<RoomListPanel />", () => {
|
||||
const client = createTestClient();
|
||||
const sdkContext = new TestSDKContext();
|
||||
sdkContext._client = client;
|
||||
|
||||
function renderComponent() {
|
||||
return render(<RoomListPanel activeSpace={MetaSpace.Home} />);
|
||||
return render(
|
||||
<RoomListPanel activeSpace={MetaSpace.Home} />,
|
||||
clientAndSDKContextRenderOptions(client, sdkContext),
|
||||
);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
+7
-3
@@ -12,7 +12,8 @@ import { mocked } from "jest-mock";
|
||||
import { RoomListSearch } from "../../../../../../src/components/views/rooms/RoomListPanel/RoomListSearch";
|
||||
import { MetaSpace } from "../../../../../../src/stores/spaces";
|
||||
import { shouldShowComponent } from "../../../../../../src/customisations/helpers/UIComponents";
|
||||
import LegacyCallHandler from "../../../../../../src/LegacyCallHandler";
|
||||
import { SDKContextClass } from "../../../../../../src/contexts/SDKContextClass.ts";
|
||||
import { clientAndSDKContextRenderOptions, createTestClient } from "../../../../../test-utils";
|
||||
|
||||
jest.mock("../../../../../../src/customisations/helpers/UIComponents", () => ({
|
||||
shouldShowComponent: jest.fn(),
|
||||
@@ -20,13 +21,16 @@ jest.mock("../../../../../../src/customisations/helpers/UIComponents", () => ({
|
||||
|
||||
describe("<RoomListSearch />", () => {
|
||||
function renderComponent(activeSpace = MetaSpace.Home) {
|
||||
return render(<RoomListSearch activeSpace={activeSpace} />);
|
||||
return render(
|
||||
<RoomListSearch activeSpace={activeSpace} />,
|
||||
clientAndSDKContextRenderOptions(createTestClient(), SDKContextClass.instance),
|
||||
);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
// By default, we consider shouldShowComponent(UIComponent.ExploreRooms) should return true
|
||||
mocked(shouldShowComponent).mockReturnValue(true);
|
||||
jest.spyOn(LegacyCallHandler.instance, "getSupportsPstnProtocol").mockReturnValue(false);
|
||||
jest.spyOn(SDKContextClass.instance.legacyCallHandler, "getSupportsPstnProtocol").mockReturnValue(false);
|
||||
});
|
||||
|
||||
it("renders", () => {
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
MockedCall,
|
||||
setupAsyncStoreWithClient,
|
||||
useMockMediaDevices,
|
||||
clientAndSDKContextRenderOptions,
|
||||
} from "../../../../test-utils";
|
||||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||
import { CallView as _CallView } from "../../../../../src/components/views/voip/CallView";
|
||||
@@ -33,6 +34,7 @@ import { WidgetMessagingStore } from "../../../../../src/stores/widgets/WidgetMe
|
||||
import { CallStore } from "../../../../../src/stores/CallStore";
|
||||
import DMRoomMap from "../../../../../src/utils/DMRoomMap";
|
||||
import { type WidgetMessaging } from "../../../../../src/stores/widgets/WidgetMessaging";
|
||||
import { TestSDKContext } from "../../../TestSDKContext.ts";
|
||||
|
||||
const CallView = wrapInMatrixClientContext(_CallView);
|
||||
|
||||
@@ -41,6 +43,7 @@ describe("CallView", () => {
|
||||
jest.spyOn(HTMLMediaElement.prototype, "play").mockImplementation(async () => {});
|
||||
|
||||
let client: Mocked<MatrixClient>;
|
||||
let sdkContext: TestSDKContext;
|
||||
let room: Room;
|
||||
let alice: RoomMember;
|
||||
let call: MockedCall;
|
||||
@@ -51,6 +54,8 @@ describe("CallView", () => {
|
||||
|
||||
stubClient();
|
||||
client = mocked(MatrixClientPeg.safeGet());
|
||||
sdkContext = new TestSDKContext();
|
||||
sdkContext._client = client;
|
||||
DMRoomMap.makeShared(client);
|
||||
|
||||
room = new Room("!1:example.org", client, "@alice:example.org", {
|
||||
@@ -88,7 +93,10 @@ describe("CallView", () => {
|
||||
});
|
||||
|
||||
const renderView = async (role: string | undefined = undefined): Promise<void> => {
|
||||
render(<CallView room={room} resizing={false} role={role} onClose={() => {}} />);
|
||||
render(
|
||||
<CallView room={room} resizing={false} role={role} onClose={() => {}} />,
|
||||
clientAndSDKContextRenderOptions(client, sdkContext),
|
||||
);
|
||||
await act(() => Promise.resolve()); // Let effects settle
|
||||
};
|
||||
|
||||
|
||||
@@ -6,16 +6,21 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
import { render, fireEvent } from "jest-matrix-react";
|
||||
import { type MatrixCall } from "matrix-js-sdk/src/matrix";
|
||||
import { type CallFeed } from "matrix-js-sdk/src/webrtc/callFeed";
|
||||
import { SDPStreamMetadataPurpose } from "matrix-js-sdk/src/webrtc/callEventTypes";
|
||||
|
||||
import LegacyCallView from "../../../../../src/components/views/voip/LegacyCallView";
|
||||
import { stubClient } from "../../../../test-utils";
|
||||
import { clientAndSDKContextRenderOptions, createTestClient, stubClient } from "../../../../test-utils";
|
||||
import DMRoomMap from "../../../../../src/utils/DMRoomMap";
|
||||
import { TestSDKContext } from "../../../TestSDKContext.ts";
|
||||
|
||||
describe("LegacyCallView", () => {
|
||||
const cli = stubClient();
|
||||
const sdkContext = new TestSDKContext();
|
||||
sdkContext._client = cli;
|
||||
|
||||
it("should exit full screen on unmount", () => {
|
||||
const element = document.createElement("div");
|
||||
// @ts-expect-error
|
||||
@@ -35,7 +40,10 @@ describe("LegacyCallView", () => {
|
||||
isScreensharing: jest.fn().mockReturnValue(false),
|
||||
} as unknown as MatrixCall;
|
||||
|
||||
const { unmount } = render(<LegacyCallView call={call} sidebarShown={false} />);
|
||||
const { unmount } = render(
|
||||
<LegacyCallView call={call} sidebarShown={false} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
expect(document.exitFullscreen).not.toHaveBeenCalled();
|
||||
unmount();
|
||||
expect(document.exitFullscreen).toHaveBeenCalled();
|
||||
@@ -75,7 +83,10 @@ describe("LegacyCallView", () => {
|
||||
getUserIdForRoomId: jest.fn().mockReturnValue("test-user"),
|
||||
} as unknown as DMRoomMap);
|
||||
|
||||
const { container, rerender } = render(<LegacyCallView call={call} sidebarShown={true} />);
|
||||
const { container, rerender } = render(
|
||||
<LegacyCallView call={call} sidebarShown={true} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
expect(container.querySelector(".mx_LegacyCallViewSidebar")).toBeTruthy();
|
||||
rerender(<LegacyCallView call={call} sidebarShown={true} />);
|
||||
expect(container.querySelector(".mx_LegacyCallViewSidebar")).toBeTruthy();
|
||||
@@ -98,7 +109,102 @@ describe("LegacyCallView", () => {
|
||||
getUserIdForRoomId: jest.fn().mockReturnValue("test-user"),
|
||||
} as unknown as DMRoomMap);
|
||||
|
||||
const { container } = render(<LegacyCallView call={call} sidebarShown={false} pipMode={true} />);
|
||||
const { container } = render(
|
||||
<LegacyCallView call={call} sidebarShown={false} pipMode={true} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
expect(container.querySelector(".mx_LegacyCallViewButtons_button_sidebar")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("should allow user to resume held call", async () => {
|
||||
const client = createTestClient();
|
||||
const sdkContext = new TestSDKContext();
|
||||
sdkContext._client = client;
|
||||
|
||||
const call = {
|
||||
roomId: "test-room",
|
||||
on: jest.fn(),
|
||||
removeListener: jest.fn(),
|
||||
getFeeds: jest.fn().mockReturnValue(
|
||||
[{ local: true }, { local: false }, { local: true, screenshare: true }].map(
|
||||
(x, i) =>
|
||||
({
|
||||
stream: { id: "test-" + i },
|
||||
addListener: jest.fn(),
|
||||
removeListener: jest.fn(),
|
||||
getMember: jest.fn(),
|
||||
isAudioMuted: jest.fn().mockReturnValue(true),
|
||||
isVideoMuted: jest.fn().mockReturnValue(true),
|
||||
isLocal: jest.fn().mockReturnValue(x.local),
|
||||
purpose: x.screenshare && SDPStreamMetadataPurpose.Screenshare,
|
||||
}) as unknown as CallFeed,
|
||||
),
|
||||
),
|
||||
isLocalOnHold: jest.fn().mockReturnValue(false),
|
||||
isRemoteOnHold: jest.fn().mockReturnValue(true),
|
||||
isMicrophoneMuted: jest.fn().mockReturnValue(true),
|
||||
isLocalVideoMuted: jest.fn().mockReturnValue(true),
|
||||
isScreensharing: jest.fn().mockReturnValue(true),
|
||||
noIncomingFeeds: jest.fn().mockReturnValue(false),
|
||||
opponentSupportsSDPStreamMetadata: jest.fn().mockReturnValue(true),
|
||||
getOpponentMember: jest.fn(),
|
||||
} as unknown as MatrixCall;
|
||||
|
||||
jest.spyOn(sdkContext.legacyCallHandler, "roomIdForCall").mockReturnValue(call.roomId);
|
||||
jest.spyOn(sdkContext.legacyCallHandler, "setActiveCallRoomId");
|
||||
|
||||
const { getByText } = render(
|
||||
<LegacyCallView call={call} sidebarShown />,
|
||||
clientAndSDKContextRenderOptions(client, sdkContext),
|
||||
);
|
||||
fireEvent.click(getByText("Resume"));
|
||||
|
||||
expect(sdkContext.legacyCallHandler.setActiveCallRoomId).toHaveBeenCalledWith(call.roomId);
|
||||
});
|
||||
|
||||
it("should allow user to hangup call", async () => {
|
||||
const client = createTestClient();
|
||||
const sdkContext = new TestSDKContext();
|
||||
sdkContext._client = client;
|
||||
|
||||
const call = {
|
||||
roomId: "test-room",
|
||||
on: jest.fn(),
|
||||
removeListener: jest.fn(),
|
||||
getFeeds: jest.fn().mockReturnValue(
|
||||
[{ local: true }, { local: false }, { local: true, screenshare: true }].map(
|
||||
(x, i) =>
|
||||
({
|
||||
stream: { id: "test-" + i },
|
||||
addListener: jest.fn(),
|
||||
removeListener: jest.fn(),
|
||||
getMember: jest.fn(),
|
||||
isAudioMuted: jest.fn().mockReturnValue(true),
|
||||
isVideoMuted: jest.fn().mockReturnValue(true),
|
||||
isLocal: jest.fn().mockReturnValue(x.local),
|
||||
purpose: x.screenshare && SDPStreamMetadataPurpose.Screenshare,
|
||||
}) as unknown as CallFeed,
|
||||
),
|
||||
),
|
||||
isLocalOnHold: jest.fn().mockReturnValue(false),
|
||||
isRemoteOnHold: jest.fn().mockReturnValue(false),
|
||||
isMicrophoneMuted: jest.fn().mockReturnValue(true),
|
||||
isLocalVideoMuted: jest.fn().mockReturnValue(true),
|
||||
isScreensharing: jest.fn().mockReturnValue(true),
|
||||
noIncomingFeeds: jest.fn().mockReturnValue(false),
|
||||
opponentSupportsSDPStreamMetadata: jest.fn().mockReturnValue(true),
|
||||
getOpponentMember: jest.fn(),
|
||||
} as unknown as MatrixCall;
|
||||
|
||||
jest.spyOn(sdkContext.legacyCallHandler, "roomIdForCall").mockReturnValue(call.roomId);
|
||||
jest.spyOn(sdkContext.legacyCallHandler, "hangupOrReject");
|
||||
|
||||
const { getByLabelText } = render(
|
||||
<LegacyCallView call={call} sidebarShown />,
|
||||
clientAndSDKContextRenderOptions(client, sdkContext),
|
||||
);
|
||||
fireEvent.click(getByLabelText("Hangup"));
|
||||
|
||||
expect(sdkContext.legacyCallHandler.hangupOrReject).toHaveBeenCalledWith(call.roomId);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,29 +12,29 @@ import { CallEventHandlerEvent } from "matrix-js-sdk/src/webrtc/callEventHandler
|
||||
|
||||
import LegacyCallView from "../../../../../src/components/views/voip/LegacyCallView";
|
||||
import LegacyCallViewForRoom from "../../../../../src/components/views/voip/LegacyCallViewForRoom";
|
||||
import { mkStubRoom, stubClient } from "../../../../test-utils";
|
||||
import { clientAndSDKContextRenderOptions, mkStubRoom, stubClient } from "../../../../test-utils";
|
||||
import DMRoomMap from "../../../../../src/utils/DMRoomMap";
|
||||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||
import LegacyCallHandler from "../../../../../src/LegacyCallHandler";
|
||||
import { SDKContext } from "../../../../../src/contexts/SDKContext";
|
||||
import { SDKContextClass } from "../../../../../src/contexts/SDKContextClass";
|
||||
import { TestSDKContext } from "../../../TestSDKContext.ts";
|
||||
|
||||
jest.mock("../../../../../src/components/views/voip/LegacyCallView", () => jest.fn(() => "LegacyCallView"));
|
||||
|
||||
describe("LegacyCallViewForRoom", () => {
|
||||
const LegacyCallViewMock = LegacyCallView as unknown as jest.Mock;
|
||||
let sdkContext: SDKContextClass;
|
||||
let sdkContext: TestSDKContext;
|
||||
|
||||
beforeEach(() => {
|
||||
stubClient();
|
||||
sdkContext = new SDKContextClass();
|
||||
sdkContext = new TestSDKContext();
|
||||
sdkContext._client = stubClient();
|
||||
LegacyCallViewMock.mockClear();
|
||||
});
|
||||
|
||||
it("should remember sidebar state, defaulting to shown", async () => {
|
||||
const callHandler = new LegacyCallHandler();
|
||||
const callHandler = new LegacyCallHandler(sdkContext);
|
||||
callHandler.start();
|
||||
jest.spyOn(LegacyCallHandler, "instance", "get").mockImplementation(() => callHandler);
|
||||
sdkContext._LegacyCallHandler = callHandler;
|
||||
|
||||
const call = new MatrixCall({
|
||||
client: MatrixClientPeg.safeGet(),
|
||||
@@ -49,7 +49,10 @@ describe("LegacyCallViewForRoom", () => {
|
||||
const cli = MatrixClientPeg.safeGet();
|
||||
cli.emit(CallEventHandlerEvent.Incoming, call);
|
||||
|
||||
const { rerender } = render(<LegacyCallViewForRoom roomId={call.roomId} />);
|
||||
const { rerender } = render(
|
||||
<LegacyCallViewForRoom roomId={call.roomId} />,
|
||||
clientAndSDKContextRenderOptions(cli, sdkContext),
|
||||
);
|
||||
|
||||
let props = LegacyCallViewMock.mock.lastCall![0];
|
||||
expect(props.sidebarShown).toBeTruthy(); // Sidebar defaults to shown
|
||||
@@ -84,9 +87,7 @@ describe("LegacyCallViewForRoom", () => {
|
||||
addListener: jest.fn(),
|
||||
removeListener: jest.fn(),
|
||||
};
|
||||
jest.spyOn(LegacyCallHandler, "instance", "get").mockImplementation(
|
||||
() => callHandler as unknown as LegacyCallHandler,
|
||||
);
|
||||
sdkContext._LegacyCallHandler = callHandler as unknown as LegacyCallHandler;
|
||||
|
||||
jest.spyOn(sdkContext.resizeNotifier, "startResizing");
|
||||
jest.spyOn(sdkContext.resizeNotifier, "stopResizing");
|
||||
|
||||
@@ -14,9 +14,9 @@ import { type MatrixClient, Room } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import * as AvatarModule from "../../../../../src/Avatar";
|
||||
import VideoFeed from "../../../../../src/components/views/voip/VideoFeed";
|
||||
import { stubClient, useMockedCalls } from "../../../../test-utils";
|
||||
import type LegacyCallHandler from "../../../../../src/LegacyCallHandler";
|
||||
import { clientAndSDKContextRenderOptions, stubClient, useMockedCalls } from "../../../../test-utils";
|
||||
import DMRoomMap from "../../../../../src/utils/DMRoomMap";
|
||||
import { TestSDKContext } from "../../../TestSDKContext.ts";
|
||||
|
||||
const FAKE_AVATAR_URL = "http://fakeurl.dummy/fake.png";
|
||||
|
||||
@@ -24,9 +24,12 @@ describe("VideoFeed", () => {
|
||||
useMockedCalls();
|
||||
|
||||
let client: MatrixClient;
|
||||
let sdkContext: TestSDKContext;
|
||||
|
||||
beforeAll(() => {
|
||||
client = stubClient();
|
||||
sdkContext = new TestSDKContext();
|
||||
sdkContext._client = client;
|
||||
(AvatarModule as any).avatarUrlForRoom = jest.fn().mockReturnValue(FAKE_AVATAR_URL);
|
||||
|
||||
const dmRoomMap = new DMRoomMap(client);
|
||||
@@ -39,9 +42,7 @@ describe("VideoFeed", () => {
|
||||
});
|
||||
|
||||
it("Displays the room avatar when no video is available", () => {
|
||||
window.mxLegacyCallHandler = {
|
||||
roomIdForCall: jest.fn().mockReturnValue("!this:room.here"),
|
||||
} as unknown as LegacyCallHandler;
|
||||
jest.spyOn(sdkContext.legacyCallHandler, "roomIdForCall").mockReturnValue("!this:room.here");
|
||||
|
||||
const mockCall = {
|
||||
room: new Room("!room:example.com", client, client.getSafeUserId()),
|
||||
@@ -53,7 +54,10 @@ describe("VideoFeed", () => {
|
||||
addListener: jest.fn(),
|
||||
removeListener: jest.fn(),
|
||||
};
|
||||
render(<VideoFeed feed={feed as unknown as CallFeed} call={mockCall as unknown as MatrixCall} />);
|
||||
render(
|
||||
<VideoFeed feed={feed as unknown as CallFeed} call={mockCall as unknown as MatrixCall} />,
|
||||
clientAndSDKContextRenderOptions(client, sdkContext),
|
||||
);
|
||||
const avatarImg = screen.getByRole("presentation");
|
||||
expect(avatarImg).toHaveAttribute("src", FAKE_AVATAR_URL);
|
||||
});
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
setupAsyncStoreWithClient,
|
||||
resetAsyncStoreWithClient,
|
||||
mkEvent,
|
||||
clientAndSDKContextRenderOptions,
|
||||
} from "../../test-utils";
|
||||
import defaultDispatcher from "../../../src/dispatcher/dispatcher";
|
||||
import { Action } from "../../../src/dispatcher/actions";
|
||||
@@ -47,9 +48,10 @@ import {
|
||||
getNotificationEventSendTs,
|
||||
IncomingCallToast,
|
||||
} from "../../../src/toasts/IncomingCallToast";
|
||||
import LegacyCallHandler, { AudioID } from "../../../src/LegacyCallHandler";
|
||||
import { AudioID } from "../../../src/LegacyCallHandler";
|
||||
import { CallEvent } from "../../../src/models/Call";
|
||||
import { type WidgetMessaging } from "../../../src/stores/widgets/WidgetMessaging";
|
||||
import { TestSDKContext } from "../TestSDKContext.ts";
|
||||
|
||||
function makeNotificationEvent(room: Room, content: IContent = {}): MatrixEvent {
|
||||
const ts = Date.now();
|
||||
@@ -76,6 +78,7 @@ describe("IncomingCallToast", () => {
|
||||
useMockedCalls();
|
||||
|
||||
let client: Mocked<MatrixClient>;
|
||||
let sdkContext: TestSDKContext;
|
||||
let room: Room;
|
||||
|
||||
let alice: RoomMember;
|
||||
@@ -92,6 +95,8 @@ describe("IncomingCallToast", () => {
|
||||
beforeEach(async () => {
|
||||
stubClient();
|
||||
client = mocked(MatrixClientPeg.safeGet());
|
||||
sdkContext = new TestSDKContext();
|
||||
sdkContext._client = client;
|
||||
|
||||
const audio = document.createElement("audio");
|
||||
audio.id = AudioID.Ring;
|
||||
@@ -146,6 +151,7 @@ describe("IncomingCallToast", () => {
|
||||
notificationEvent={notificationEvent}
|
||||
toastKey={getIncomingCallToastKey(callId, room.roomId)}
|
||||
/>,
|
||||
clientAndSDKContextRenderOptions(client, sdkContext),
|
||||
);
|
||||
return callId;
|
||||
};
|
||||
@@ -196,8 +202,11 @@ describe("IncomingCallToast", () => {
|
||||
|
||||
it("start ringing on ring notify event", () => {
|
||||
const notificationEvent = makeNotificationEvent(room, { notification_type: "ring" });
|
||||
const playMock = jest.spyOn(LegacyCallHandler.instance, "play");
|
||||
render(<IncomingCallToast notificationEvent={notificationEvent} toastKey="" />);
|
||||
const playMock = jest.spyOn(sdkContext.legacyCallHandler, "play");
|
||||
render(
|
||||
<IncomingCallToast notificationEvent={notificationEvent} toastKey="" />,
|
||||
clientAndSDKContextRenderOptions(client, sdkContext),
|
||||
);
|
||||
expect(playMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
@@ -10,10 +10,15 @@ import { LOCAL_NOTIFICATION_SETTINGS_PREFIX, MatrixEvent, Room } from "matrix-js
|
||||
import { MatrixCall } from "matrix-js-sdk/src/webrtc/call";
|
||||
import React from "react";
|
||||
|
||||
import LegacyCallHandler from "../../../src/LegacyCallHandler";
|
||||
import IncomingLegacyCallToast from "../../../src/toasts/IncomingLegacyCallToast";
|
||||
import DMRoomMap from "../../../src/utils/DMRoomMap";
|
||||
import { getMockClientWithEventEmitter, mockClientMethodsServer, mockClientMethodsUser } from "../../test-utils";
|
||||
import {
|
||||
clientAndSDKContextRenderOptions,
|
||||
getMockClientWithEventEmitter,
|
||||
mockClientMethodsServer,
|
||||
mockClientMethodsUser,
|
||||
} from "../../test-utils";
|
||||
import { SDKContextClass } from "../../../src/contexts/SDKContextClass.ts";
|
||||
|
||||
describe("<IncomingLegacyCallToast />", () => {
|
||||
const userId = "@alice:server.org";
|
||||
@@ -41,16 +46,24 @@ describe("<IncomingLegacyCallToast />", () => {
|
||||
jest.clearAllMocks();
|
||||
mockClient.getAccountData.mockReturnValue(undefined);
|
||||
mockClient.getRoom.mockReturnValue(mockRoom);
|
||||
// @ts-ignore
|
||||
SDKContextClass.instance._client = mockClient;
|
||||
});
|
||||
|
||||
it("renders when silence button when call is not silenced", () => {
|
||||
const { getByLabelText } = render(getComponent());
|
||||
const { getByLabelText } = render(
|
||||
getComponent(),
|
||||
clientAndSDKContextRenderOptions(mockClient, SDKContextClass.instance),
|
||||
);
|
||||
expect(getByLabelText("Silence call")).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders sound on button when call is silenced", () => {
|
||||
LegacyCallHandler.instance.silenceCall(call.callId);
|
||||
const { getByLabelText } = render(getComponent());
|
||||
SDKContextClass.instance.legacyCallHandler.silenceCall(call.callId);
|
||||
const { getByLabelText } = render(
|
||||
getComponent(),
|
||||
clientAndSDKContextRenderOptions(mockClient, SDKContextClass.instance),
|
||||
);
|
||||
expect(getByLabelText("Sound on")).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -66,7 +79,10 @@ describe("<IncomingLegacyCallToast />", () => {
|
||||
});
|
||||
}
|
||||
});
|
||||
const { getByLabelText } = render(getComponent());
|
||||
const { getByLabelText } = render(
|
||||
getComponent(),
|
||||
clientAndSDKContextRenderOptions(mockClient, SDKContextClass.instance),
|
||||
);
|
||||
expect(getByLabelText("Notifications silenced")).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ import { shouldShowComponent } from "../../../src/customisations/helpers/UICompo
|
||||
import defaultDispatcher from "../../../src/dispatcher/dispatcher";
|
||||
import { Action } from "../../../src/dispatcher/actions";
|
||||
import LegacyCallHandler, { LegacyCallHandlerEvent } from "../../../src/LegacyCallHandler";
|
||||
import { TestSDKContext } from "../../unit-tests/TestSDKContext.ts";
|
||||
|
||||
jest.mock("../../../src/customisations/helpers/UIComponents", () => ({
|
||||
shouldShowComponent: jest.fn(),
|
||||
@@ -23,9 +24,12 @@ jest.mock("../../../src/PosthogTrackers", () => ({
|
||||
}));
|
||||
|
||||
describe("RoomListSearchViewModel", () => {
|
||||
const context = new TestSDKContext();
|
||||
|
||||
beforeEach(() => {
|
||||
mocked(shouldShowComponent).mockReturnValue(true);
|
||||
jest.spyOn(LegacyCallHandler.instance, "getSupportsPstnProtocol").mockReturnValue(false);
|
||||
context._LegacyCallHandler = new LegacyCallHandler(context);
|
||||
jest.spyOn(context._LegacyCallHandler, "getSupportsPstnProtocol").mockReturnValue(false);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -35,35 +39,50 @@ describe("RoomListSearchViewModel", () => {
|
||||
describe("snapshot", () => {
|
||||
it("should show explore button in Home space when UIComponent.ExploreRooms is enabled", () => {
|
||||
mocked(shouldShowComponent).mockReturnValue(true);
|
||||
const vm = new RoomListSearchViewModel({ activeSpace: MetaSpace.Home });
|
||||
const vm = new RoomListSearchViewModel({
|
||||
activeSpace: MetaSpace.Home,
|
||||
legacyCallHandler: context.legacyCallHandler,
|
||||
});
|
||||
|
||||
expect(vm.getSnapshot().displayExploreButton).toBe(true);
|
||||
});
|
||||
|
||||
it("should hide explore button when not in Home space", () => {
|
||||
mocked(shouldShowComponent).mockReturnValue(true);
|
||||
const vm = new RoomListSearchViewModel({ activeSpace: MetaSpace.VideoRooms });
|
||||
const vm = new RoomListSearchViewModel({
|
||||
activeSpace: MetaSpace.VideoRooms,
|
||||
legacyCallHandler: context.legacyCallHandler,
|
||||
});
|
||||
|
||||
expect(vm.getSnapshot().displayExploreButton).toBe(false);
|
||||
});
|
||||
|
||||
it("should hide explore button when UIComponent.ExploreRooms is disabled", () => {
|
||||
mocked(shouldShowComponent).mockReturnValue(false);
|
||||
const vm = new RoomListSearchViewModel({ activeSpace: MetaSpace.Home });
|
||||
const vm = new RoomListSearchViewModel({
|
||||
activeSpace: MetaSpace.Home,
|
||||
legacyCallHandler: context.legacyCallHandler,
|
||||
});
|
||||
|
||||
expect(vm.getSnapshot().displayExploreButton).toBe(false);
|
||||
});
|
||||
|
||||
it("should show dial button when PSTN protocol is supported", () => {
|
||||
jest.spyOn(LegacyCallHandler.instance, "getSupportsPstnProtocol").mockReturnValue(true);
|
||||
const vm = new RoomListSearchViewModel({ activeSpace: MetaSpace.Home });
|
||||
jest.spyOn(context.legacyCallHandler, "getSupportsPstnProtocol").mockReturnValue(true);
|
||||
const vm = new RoomListSearchViewModel({
|
||||
activeSpace: MetaSpace.Home,
|
||||
legacyCallHandler: context.legacyCallHandler,
|
||||
});
|
||||
|
||||
expect(vm.getSnapshot().displayDialButton).toBe(true);
|
||||
});
|
||||
|
||||
it("should hide dial button when PSTN protocol is not supported", () => {
|
||||
jest.spyOn(LegacyCallHandler.instance, "getSupportsPstnProtocol").mockReturnValue(false);
|
||||
const vm = new RoomListSearchViewModel({ activeSpace: MetaSpace.Home });
|
||||
jest.spyOn(context.legacyCallHandler, "getSupportsPstnProtocol").mockReturnValue(false);
|
||||
const vm = new RoomListSearchViewModel({
|
||||
activeSpace: MetaSpace.Home,
|
||||
legacyCallHandler: context.legacyCallHandler,
|
||||
});
|
||||
|
||||
expect(vm.getSnapshot().displayDialButton).toBe(false);
|
||||
});
|
||||
@@ -72,7 +91,10 @@ describe("RoomListSearchViewModel", () => {
|
||||
describe("actions", () => {
|
||||
it("should fire OpenSpotlight action when onSearchClick is called", () => {
|
||||
const fireSpy = jest.spyOn(defaultDispatcher, "fire");
|
||||
const vm = new RoomListSearchViewModel({ activeSpace: MetaSpace.Home });
|
||||
const vm = new RoomListSearchViewModel({
|
||||
activeSpace: MetaSpace.Home,
|
||||
legacyCallHandler: context.legacyCallHandler,
|
||||
});
|
||||
|
||||
vm.onSearchClick();
|
||||
expect(fireSpy).toHaveBeenCalledWith(Action.OpenSpotlight);
|
||||
@@ -80,7 +102,10 @@ describe("RoomListSearchViewModel", () => {
|
||||
|
||||
it("should fire OpenDialPad action when onDialPadClick is called", () => {
|
||||
const fireSpy = jest.spyOn(defaultDispatcher, "fire");
|
||||
const vm = new RoomListSearchViewModel({ activeSpace: MetaSpace.Home });
|
||||
const vm = new RoomListSearchViewModel({
|
||||
activeSpace: MetaSpace.Home,
|
||||
legacyCallHandler: context.legacyCallHandler,
|
||||
});
|
||||
|
||||
vm.onDialPadClick();
|
||||
expect(fireSpy).toHaveBeenCalledWith(Action.OpenDialPad);
|
||||
@@ -88,7 +113,10 @@ describe("RoomListSearchViewModel", () => {
|
||||
|
||||
it("should fire ViewRoomDirectory action and track interaction when onExploreClick is called", () => {
|
||||
const fireSpy = jest.spyOn(defaultDispatcher, "fire");
|
||||
const vm = new RoomListSearchViewModel({ activeSpace: MetaSpace.Home });
|
||||
const vm = new RoomListSearchViewModel({
|
||||
activeSpace: MetaSpace.Home,
|
||||
legacyCallHandler: context.legacyCallHandler,
|
||||
});
|
||||
|
||||
const mockEvent = {} as React.MouseEvent<HTMLButtonElement>;
|
||||
vm.onExploreClick(mockEvent);
|
||||
@@ -98,14 +126,17 @@ describe("RoomListSearchViewModel", () => {
|
||||
});
|
||||
|
||||
it("should update snapshot when PSTN protocol support changes", () => {
|
||||
jest.spyOn(LegacyCallHandler.instance, "getSupportsPstnProtocol").mockReturnValue(false);
|
||||
const vm = new RoomListSearchViewModel({ activeSpace: MetaSpace.Home });
|
||||
jest.spyOn(context.legacyCallHandler, "getSupportsPstnProtocol").mockReturnValue(false);
|
||||
const vm = new RoomListSearchViewModel({
|
||||
activeSpace: MetaSpace.Home,
|
||||
legacyCallHandler: context.legacyCallHandler,
|
||||
});
|
||||
|
||||
expect(vm.getSnapshot().displayDialButton).toBe(false);
|
||||
|
||||
// Simulate PSTN protocol support change
|
||||
jest.spyOn(LegacyCallHandler.instance, "getSupportsPstnProtocol").mockReturnValue(true);
|
||||
LegacyCallHandler.instance.emit(LegacyCallHandlerEvent.ProtocolSupport);
|
||||
jest.spyOn(context.legacyCallHandler, "getSupportsPstnProtocol").mockReturnValue(true);
|
||||
context.legacyCallHandler.emit(LegacyCallHandlerEvent.ProtocolSupport);
|
||||
|
||||
expect(vm.getSnapshot().displayDialButton).toBe(true);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user