mirror of
https://github.com/Novaloop-AG/healthchat-web.git
synced 2026-11-06 06:28:27 +00:00
MVVM userinfo basic component (#30305)
* feat: mvvm userinfo basic component * test: mvvm userinfobasic component * chore: apply review. rename views, add comment and move some codes * chore(review): move openDM method into viewmodel
This commit is contained in:
@@ -28,24 +28,16 @@ import {
|
||||
type CryptoApi,
|
||||
} from "matrix-js-sdk/src/crypto-api";
|
||||
|
||||
import UserInfo, {
|
||||
disambiguateDevices,
|
||||
getPowerLevels,
|
||||
UserOptionsSection,
|
||||
} from "../../../../../src/components/views/right_panel/UserInfo";
|
||||
import dis from "../../../../../src/dispatcher/dispatcher";
|
||||
import UserInfo, { disambiguateDevices } from "../../../../../src/components/views/right_panel/UserInfo";
|
||||
import { getPowerLevels } from "../../../../../src/components/viewmodels/right_panel/user_info/UserInfoBasicViewModel";
|
||||
import { RightPanelPhases } from "../../../../../src/stores/right-panel/RightPanelStorePhases";
|
||||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
||||
import MultiInviter from "../../../../../src/utils/MultiInviter";
|
||||
import Modal from "../../../../../src/Modal";
|
||||
import { DirectoryMember, startDmOnFirstMessage } from "../../../../../src/utils/direct-messages";
|
||||
import { clearAllModals, flushPromises } from "../../../../test-utils";
|
||||
import ErrorDialog from "../../../../../src/components/views/dialogs/ErrorDialog";
|
||||
import { shouldShowComponent } from "../../../../../src/customisations/helpers/UIComponents";
|
||||
import { UIComponent } from "../../../../../src/settings/UIFeature";
|
||||
import { Action } from "../../../../../src/dispatcher/actions";
|
||||
import { ShareDialog } from "../../../../../src/components/views/dialogs/ShareDialog";
|
||||
|
||||
jest.mock("../../../../../src/utils/direct-messages", () => ({
|
||||
...jest.requireActual("../../../../../src/utils/direct-messages"),
|
||||
@@ -449,216 +441,6 @@ describe("<UserInfo />", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("<UserOptionsSection />", () => {
|
||||
const member = new RoomMember(defaultRoomId, defaultUserId);
|
||||
const defaultProps = { member, canInvite: false, isSpace: false };
|
||||
|
||||
const renderComponent = (props = {}) => {
|
||||
const Wrapper = (wrapperProps = {}) => {
|
||||
return <MatrixClientContext.Provider value={mockClient} {...wrapperProps} />;
|
||||
};
|
||||
|
||||
return render(<UserOptionsSection {...defaultProps} {...props} />, {
|
||||
wrapper: Wrapper,
|
||||
});
|
||||
};
|
||||
|
||||
const inviteSpy = jest.spyOn(MultiInviter.prototype, "invite");
|
||||
|
||||
beforeEach(() => {
|
||||
inviteSpy.mockReset();
|
||||
mockClient.setIgnoredUsers.mockClear();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await clearAllModals();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
inviteSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("always shows share user button and clicking it should produce a ShareDialog", async () => {
|
||||
const spy = jest.spyOn(Modal, "createDialog");
|
||||
|
||||
renderComponent();
|
||||
await userEvent.click(screen.getByRole("button", { name: "Share profile" }));
|
||||
|
||||
expect(spy).toHaveBeenCalledWith(ShareDialog, { target: defaultProps.member });
|
||||
});
|
||||
|
||||
it("does not show ignore or direct message buttons when member userId matches client userId", () => {
|
||||
mockClient.getSafeUserId.mockReturnValueOnce(member.userId);
|
||||
mockClient.getUserId.mockReturnValueOnce(member.userId);
|
||||
renderComponent();
|
||||
|
||||
expect(screen.queryByRole("button", { name: /ignore/i })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: /message/i })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows direct message and mention buttons when member userId does not match client userId", () => {
|
||||
// call to client.getUserId returns undefined, which will not match member.userId
|
||||
renderComponent();
|
||||
|
||||
expect(screen.getByRole("button", { name: "Send message" })).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Mention" })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("mention button fires ComposerInsert Action", async () => {
|
||||
renderComponent();
|
||||
|
||||
const button = screen.getByRole("button", { name: "Mention" });
|
||||
await userEvent.click(button);
|
||||
expect(dis.dispatch).toHaveBeenCalledWith({
|
||||
action: Action.ComposerInsert,
|
||||
timelineRenderingType: "Room",
|
||||
userId: "@user:example.com",
|
||||
});
|
||||
});
|
||||
|
||||
it("when call to client.getRoom is null, shows disabled read receipt button", () => {
|
||||
mockClient.getRoom.mockReturnValueOnce(null);
|
||||
renderComponent();
|
||||
|
||||
expect(screen.queryByRole("button", { name: "Jump to read receipt" })).toBeDisabled();
|
||||
});
|
||||
|
||||
it("when call to client.getRoom is non-null and room.getEventReadUpTo is null, shows disabled read receipt button", () => {
|
||||
mockRoom.getEventReadUpTo.mockReturnValueOnce(null);
|
||||
mockClient.getRoom.mockReturnValueOnce(mockRoom);
|
||||
renderComponent();
|
||||
|
||||
expect(screen.queryByRole("button", { name: "Jump to read receipt" })).toBeDisabled();
|
||||
});
|
||||
|
||||
it("when calls to client.getRoom and room.getEventReadUpTo are non-null, shows read receipt button", () => {
|
||||
mockRoom.getEventReadUpTo.mockReturnValueOnce("1234");
|
||||
mockClient.getRoom.mockReturnValueOnce(mockRoom);
|
||||
renderComponent();
|
||||
|
||||
expect(screen.getByRole("button", { name: "Jump to read receipt" })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("clicking the read receipt button calls dispatch with correct event_id", async () => {
|
||||
const mockEventId = "1234";
|
||||
mockRoom.getEventReadUpTo.mockReturnValue(mockEventId);
|
||||
mockClient.getRoom.mockReturnValue(mockRoom);
|
||||
renderComponent();
|
||||
|
||||
const readReceiptButton = screen.getByRole("button", { name: "Jump to read receipt" });
|
||||
|
||||
expect(readReceiptButton).toBeInTheDocument();
|
||||
await userEvent.click(readReceiptButton);
|
||||
expect(dis.dispatch).toHaveBeenCalledWith({
|
||||
action: "view_room",
|
||||
event_id: mockEventId,
|
||||
highlighted: true,
|
||||
metricsTrigger: undefined,
|
||||
room_id: "!fkfk",
|
||||
});
|
||||
|
||||
mockRoom.getEventReadUpTo.mockReset();
|
||||
mockClient.getRoom.mockReset();
|
||||
});
|
||||
|
||||
it("firing the read receipt event handler with a null event_id calls dispatch with undefined not null", async () => {
|
||||
const mockEventId = "1234";
|
||||
// the first call is the check to see if we should render the button, second call is
|
||||
// when the button is clicked
|
||||
mockRoom.getEventReadUpTo.mockReturnValueOnce(mockEventId).mockReturnValueOnce(null);
|
||||
mockClient.getRoom.mockReturnValue(mockRoom);
|
||||
renderComponent();
|
||||
|
||||
const readReceiptButton = screen.getByRole("button", { name: "Jump to read receipt" });
|
||||
|
||||
expect(readReceiptButton).toBeInTheDocument();
|
||||
await userEvent.click(readReceiptButton);
|
||||
expect(dis.dispatch).toHaveBeenCalledWith({
|
||||
action: "view_room",
|
||||
event_id: undefined,
|
||||
highlighted: true,
|
||||
metricsTrigger: undefined,
|
||||
room_id: "!fkfk",
|
||||
});
|
||||
|
||||
mockClient.getRoom.mockReset();
|
||||
});
|
||||
|
||||
it("does not show the invite button when canInvite is false", () => {
|
||||
renderComponent();
|
||||
expect(screen.queryByRole("button", { name: /invite/i })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows the invite button when canInvite is true", () => {
|
||||
renderComponent({ canInvite: true });
|
||||
expect(screen.getByRole("button", { name: /invite/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("clicking the invite button will call MultiInviter.invite", async () => {
|
||||
// to save mocking, we will reject the call to .invite
|
||||
const mockErrorMessage = new Error("test error message");
|
||||
inviteSpy.mockRejectedValue(mockErrorMessage);
|
||||
|
||||
// render the component and click the button
|
||||
renderComponent({ canInvite: true });
|
||||
const inviteButton = screen.getByRole("button", { name: /invite/i });
|
||||
expect(inviteButton).toBeInTheDocument();
|
||||
await userEvent.click(inviteButton);
|
||||
|
||||
// check that we have called .invite
|
||||
expect(inviteSpy).toHaveBeenCalledWith([member.userId]);
|
||||
|
||||
// check that the test error message is displayed
|
||||
await expect(screen.findByText(mockErrorMessage.message)).resolves.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("if calling .invite throws something strange, show default error message", async () => {
|
||||
inviteSpy.mockRejectedValue({ this: "could be anything" });
|
||||
|
||||
// render the component and click the button
|
||||
renderComponent({ canInvite: true });
|
||||
const inviteButton = screen.getByRole("button", { name: /invite/i });
|
||||
expect(inviteButton).toBeInTheDocument();
|
||||
await userEvent.click(inviteButton);
|
||||
|
||||
// check that the default test error message is displayed
|
||||
await expect(screen.findByText(/operation failed/i)).resolves.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each([
|
||||
["for a RoomMember", member, member.getMxcAvatarUrl()],
|
||||
["for a User", defaultUser, defaultUser.avatarUrl],
|
||||
])(
|
||||
"clicking »message« %s should start a DM",
|
||||
async (test: string, member: RoomMember | User, expectedAvatarUrl: string | undefined) => {
|
||||
const deferred = Promise.withResolvers<string>();
|
||||
mocked(startDmOnFirstMessage).mockReturnValue(deferred.promise);
|
||||
|
||||
renderComponent({ member });
|
||||
await userEvent.click(screen.getByRole("button", { name: "Send message" }));
|
||||
|
||||
// Checking the attribute, because the button is a DIV and toBeDisabled() does not work.
|
||||
expect(screen.getByRole("button", { name: "Send message" })).toBeDisabled();
|
||||
|
||||
expect(startDmOnFirstMessage).toHaveBeenCalledWith(mockClient, [
|
||||
new DirectoryMember({
|
||||
user_id: member.userId,
|
||||
display_name: member.rawDisplayName,
|
||||
avatar_url: expectedAvatarUrl,
|
||||
}),
|
||||
]);
|
||||
|
||||
await act(async () => {
|
||||
deferred.resolve("!dm:example.com");
|
||||
await flushPromises();
|
||||
});
|
||||
|
||||
// Checking the attribute, because the button is a DIV and toBeDisabled() does not work.
|
||||
expect(screen.getByRole("button", { name: "Send message" })).not.toBeDisabled();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("disambiguateDevices", () => {
|
||||
it("does not add ambiguous key to unique names", () => {
|
||||
const initialDevices = [
|
||||
|
||||
Reference in New Issue
Block a user