Remove more usages of singleton store getter in favour of contexts (#34099)

* Expose SDKContextClass via window for debugging

* Remove stores from window if they are exposed via sdkContext

* Avoid usages of global store instance where React context is accessible

* Remove more usages of singleton store getter in favour of contexts

* Remove more usages of singleton store getter in favour of contexts

* Fix tests by adding SDKContext.Provider

* Fix tests by adding SDKContext.Provider

* Fix tests by adding SDKContext.Provider

* Fix tests by adding SDKContext.Provider

* Fix tests

* Fix tests

* Fix tests

* Iterate

* Fix bad merge

* Iterate

* Fix tests

* Iterate

* Iterate

* Iterate

* Iterate

* Iterate

* Improve coverage

* Improve coverage
This commit is contained in:
Michael Telatynski
2026-07-14 12:58:34 +00:00
committed by GitHub
parent 9575b236c0
commit b5fd249e38
52 changed files with 666 additions and 331 deletions
@@ -12,8 +12,9 @@ import { screen, render, waitFor } from "jest-matrix-react";
import { mocked } from "jest-mock";
import FilePanel from "../../../../src/components/structures/FilePanel";
import { mkEvent, stubClient } from "../../../test-utils";
import { clientAndSDKContextRenderOptions, mkEvent, stubClient } from "../../../test-utils";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import { SDKContextClass } from "../../../../src/contexts/SDKContextClass.ts";
jest.mock("matrix-js-sdk/src/matrix", () => ({
...jest.requireActual("matrix-js-sdk/src/matrix"),
@@ -38,7 +39,10 @@ describe("FilePanel", () => {
room.getOrCreateFilteredTimelineSet = jest.fn().mockReturnValue(timelineSet);
mocked(cli.getRoom).mockReturnValue(room);
const { asFragment } = render(<FilePanel roomId={room.roomId} onClose={jest.fn()} />);
const { asFragment } = render(
<FilePanel roomId={room.roomId} onClose={jest.fn()} />,
clientAndSDKContextRenderOptions(cli, SDKContextClass.instance),
);
await waitFor(() => {
expect(screen.getByText("No files visible in this room")).toBeInTheDocument();
});
@@ -65,6 +69,7 @@ describe("FilePanel", () => {
filePanel = ref;
}}
/>,
clientAndSDKContextRenderOptions(cli, SDKContextClass.instance),
);
await screen.findByText("No files visible in this room");
@@ -46,6 +46,7 @@ import Modal from "../../../../src/Modal";
import { SETTINGS } from "../../../../src/settings/Settings";
import ToastStore from "../../../../src/stores/ToastStore";
import { ModuleApi } from "../../../../src/modules/Api";
import { fireEvent } from "@testing-library/dom";
describe("<LoggedInView />", () => {
const userId = "@alice:domain.org";
@@ -67,6 +68,8 @@ describe("<LoggedInView />", () => {
on: jest.fn(),
},
getAuthMetadata: jest.fn().mockRejectedValue(new Error("Legacy auth")),
hasLazyLoadMembersEnabled: jest.fn(),
isInitialSyncComplete: jest.fn(),
});
const mediaHandler = new MediaHandler(mockClient);
const mockSdkContext = new TestSDKContext();
@@ -555,4 +558,11 @@ describe("<LoggedInView />", () => {
expect(container.querySelector(".mx_SpacePanel")).toBeInTheDocument();
});
});
it("should handle KeyBindingAction.ToggleRoomSidePanel", async () => {
getComponent({ page_type: "room_view" });
jest.spyOn(mockSdkContext.rightPanelStore, "togglePanel");
fireEvent.keyDown(document.body, { key: ".", code: "Period", ctrlKey: true, keyCode: 190 });
expect(mockSdkContext.rightPanelStore.togglePanel).toHaveBeenCalledWith(null);
});
});
@@ -21,6 +21,7 @@ import {
RoomMember,
RoomStateEvent,
SearchResult,
User,
} from "matrix-js-sdk/src/matrix";
import { type CryptoApi, CryptoEvent, UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
import { KnownMembership } from "matrix-js-sdk/src/types";
@@ -1132,6 +1133,54 @@ describe("RoomView", () => {
});
});
it("should handle Action.ViewUser", async () => {
await mountRoomView();
jest.spyOn(stores.rightPanelStore, "setCards");
const member = new User("@user:server");
defaultDispatcher.dispatch(
{
action: Action.ViewUser,
member,
},
true,
);
expect(stores.rightPanelStore.setCards).toHaveBeenCalledWith([
{ phase: RightPanelPhases.RoomSummary },
{ phase: RightPanelPhases.MemberList },
{ phase: RightPanelPhases.MemberInfo, state: { member } },
]);
});
it("should handle Action.ViewUser with push", async () => {
await mountRoomView();
jest.spyOn(stores.rightPanelStore, "pushCard");
const member = new User("@user:server");
defaultDispatcher.dispatch(
{
action: Action.ViewUser,
member,
push: true,
},
true,
);
expect(stores.rightPanelStore.pushCard).toHaveBeenCalledWith({
phase: RightPanelPhases.MemberInfo,
state: { member },
});
});
it("should handle Action.View3pidInvite", async () => {
await mountRoomView();
jest.spyOn(stores.rightPanelStore, "showOrHidePhase");
defaultDispatcher.dispatch(
{
action: Action.View3pidInvite,
},
true,
);
expect(stores.rightPanelStore.showOrHidePhase).toHaveBeenCalledWith("MemberList");
});
describe("when there is a RoomView", () => {
const widget1Id = "widget1";
const widget2Id = "widget2";
@@ -10,7 +10,7 @@ import { mocked, type MockedObject } from "jest-mock";
import { type MatrixClient, MatrixEvent, Preset, Room } from "matrix-js-sdk/src/matrix";
import { render, cleanup, screen, fireEvent, waitFor, act } from "jest-matrix-react";
import { stubClient, mockPlatformPeg, unmockPlatformPeg, withClientContextRenderOptions } from "../../../test-utils";
import { stubClient, mockPlatformPeg, unmockPlatformPeg, clientAndSDKContextRenderOptions } from "../../../test-utils";
import { RightPanelPhases } from "../../../../src/stores/right-panel/RightPanelStorePhases";
import SpaceRoomView from "../../../../src/components/structures/SpaceRoomView.tsx";
import ResizeNotifier from "../../../../src/utils/ResizeNotifier.ts";
@@ -101,7 +101,7 @@ describe("SpaceRoomView", () => {
onRejectButtonClicked={jest.fn()}
justCreatedOpts={justCreatedOpts}
/>,
withClientContextRenderOptions(cli),
clientAndSDKContextRenderOptions(cli, SDKContextClass.instance),
);
return spaceRoomView;
};
@@ -24,10 +24,18 @@ import { _t } from "../../../../src/languageHandler";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalinks";
import ResizeNotifier from "../../../../src/utils/ResizeNotifier";
import { createTestClient, getRoomContext, mkRoom, mockPlatformPeg, stubClient } from "../../../test-utils";
import {
clientAndSDKContextRenderOptions,
createTestClient,
getRoomContext,
mkRoom,
mockPlatformPeg,
stubClient,
} from "../../../test-utils";
import { mkThread } from "../../../test-utils/threads";
import { ScopedRoomContextProvider } from "../../../../src/contexts/ScopedRoomContext.tsx";
import type { RoomContextType } from "../../../../src/contexts/RoomContext.ts";
import { SDKContextClass } from "../../../../src/contexts/SDKContextClass.ts";
jest.mock("../../../../src/utils/Feedback");
@@ -215,7 +223,10 @@ describe("ThreadPanel", () => {
myThreads!.addLiveEvent(mixedThread.rootEvent, { addToState: true });
myThreads!.addLiveEvent(ownThread.rootEvent, { addToState: true });
const renderResult = render(<TestThreadPanel />);
const renderResult = render(
<TestThreadPanel />,
clientAndSDKContextRenderOptions(createTestClient(), SDKContextClass.instance),
);
await waitFor(() => expect(renderResult.container.querySelector(".mx_AutoHideScrollbar")).toBeFalsy());
await waitFor(() => {
const events = findEvents(renderResult.container);
@@ -260,7 +271,10 @@ describe("ThreadPanel", () => {
const [allThreads] = room.threadsTimelineSets;
allThreads!.addLiveEvent(otherThread.rootEvent, { addToState: true });
const renderResult = render(<TestThreadPanel />);
const renderResult = render(
<TestThreadPanel />,
clientAndSDKContextRenderOptions(createTestClient(), SDKContextClass.instance),
);
await waitFor(() => expect(renderResult.container.querySelector(".mx_AutoHideScrollbar")).toBeFalsy());
await waitFor(() => {
const events = findEvents(renderResult.container);