set disabled state on invite to room button in memberlist (#11893)
This commit is contained in:
parent
2f0eb8fb05
commit
20fd1111c8
2 changed files with 127 additions and 37 deletions
|
@ -28,7 +28,6 @@ import {
|
||||||
RoomStateEvent,
|
RoomStateEvent,
|
||||||
User,
|
User,
|
||||||
UserEvent,
|
UserEvent,
|
||||||
JoinRule,
|
|
||||||
EventType,
|
EventType,
|
||||||
ClientEvent,
|
ClientEvent,
|
||||||
} from "matrix-js-sdk/src/matrix";
|
} from "matrix-js-sdk/src/matrix";
|
||||||
|
@ -54,6 +53,8 @@ import { shouldShowComponent } from "../../../customisations/helpers/UIComponent
|
||||||
import { UIComponent } from "../../../settings/UIFeature";
|
import { UIComponent } from "../../../settings/UIFeature";
|
||||||
import PosthogTrackers from "../../../PosthogTrackers";
|
import PosthogTrackers from "../../../PosthogTrackers";
|
||||||
import { SDKContext } from "../../../contexts/SDKContext";
|
import { SDKContext } from "../../../contexts/SDKContext";
|
||||||
|
import { canInviteTo } from "../../../utils/room/canInviteTo";
|
||||||
|
import { inviteToRoom } from "../../../utils/room/inviteToRoom";
|
||||||
|
|
||||||
const INITIAL_LOAD_NUM_MEMBERS = 30;
|
const INITIAL_LOAD_NUM_MEMBERS = 30;
|
||||||
const INITIAL_LOAD_NUM_INVITED = 5;
|
const INITIAL_LOAD_NUM_INVITED = 5;
|
||||||
|
@ -132,9 +133,7 @@ export default class MemberList extends React.Component<IProps, IState> {
|
||||||
const cli = MatrixClientPeg.safeGet();
|
const cli = MatrixClientPeg.safeGet();
|
||||||
const room = cli.getRoom(this.props.roomId);
|
const room = cli.getRoom(this.props.roomId);
|
||||||
|
|
||||||
return (
|
return !!room && canInviteTo(room);
|
||||||
!!room?.canInvite(cli.getSafeUserId()) || !!(room?.isSpaceRoom() && room.getJoinRule() === JoinRule.Public)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getMembersState(invitedMembers: Array<RoomMember>, joinedMembers: Array<RoomMember>): IState {
|
private getMembersState(invitedMembers: Array<RoomMember>, joinedMembers: Array<RoomMember>): IState {
|
||||||
|
@ -365,32 +364,25 @@ export default class MemberList extends React.Component<IProps, IState> {
|
||||||
let inviteButton: JSX.Element | undefined;
|
let inviteButton: JSX.Element | undefined;
|
||||||
|
|
||||||
if (room?.getMyMembership() === "join" && shouldShowComponent(UIComponent.InviteUsers)) {
|
if (room?.getMyMembership() === "join" && shouldShowComponent(UIComponent.InviteUsers)) {
|
||||||
let inviteButtonText = _t("room|invite_this_room");
|
const inviteButtonText = room.isSpaceRoom() ? _t("space|invite_this_space") : _t("room|invite_this_room");
|
||||||
if (room.isSpaceRoom()) {
|
|
||||||
inviteButtonText = _t("space|invite_this_space");
|
const button = (
|
||||||
}
|
<Button
|
||||||
|
size="sm"
|
||||||
|
kind="secondary"
|
||||||
|
className="mx_MemberList_invite"
|
||||||
|
onClick={this.onInviteButtonClick}
|
||||||
|
disabled={!this.state.canInvite}
|
||||||
|
>
|
||||||
|
<UserAddIcon width="1em" height="1em" />
|
||||||
|
{inviteButtonText}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
|
||||||
if (this.state.canInvite) {
|
if (this.state.canInvite) {
|
||||||
inviteButton = (
|
inviteButton = button;
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
kind="secondary"
|
|
||||||
className="mx_MemberList_invite"
|
|
||||||
onClick={this.onInviteButtonClick}
|
|
||||||
>
|
|
||||||
<UserAddIcon width="1em" height="1em" />
|
|
||||||
{inviteButtonText}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
inviteButton = (
|
inviteButton = <Tooltip label={_t("member_list|invite_button_no_perms_tooltip")}>{button}</Tooltip>;
|
||||||
<Tooltip label={_t("member_list|invite_button_no_perms_tooltip")}>
|
|
||||||
<Button size="sm" kind="secondary" className="mx_MemberList_invite" onClick={() => {}}>
|
|
||||||
<UserAddIcon width="1em" height="1em" />
|
|
||||||
{inviteButtonText}
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,15 +446,9 @@ export default class MemberList extends React.Component<IProps, IState> {
|
||||||
private onInviteButtonClick = (ev: ButtonEvent): void => {
|
private onInviteButtonClick = (ev: ButtonEvent): void => {
|
||||||
PosthogTrackers.trackInteraction("WebRightPanelMemberListInviteButton", ev);
|
PosthogTrackers.trackInteraction("WebRightPanelMemberListInviteButton", ev);
|
||||||
|
|
||||||
if (MatrixClientPeg.safeGet().isGuest()) {
|
const cli = MatrixClientPeg.safeGet();
|
||||||
dis.dispatch({ action: "require_registration" });
|
const room = cli.getRoom(this.props.roomId)!;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// open the room inviter
|
inviteToRoom(room);
|
||||||
dis.dispatch({
|
|
||||||
action: "view_invite",
|
|
||||||
roomId: this.props.roomId,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,21 +16,37 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { act, render, RenderResult, screen } from "@testing-library/react";
|
import { act, fireEvent, render, RenderResult, screen } from "@testing-library/react";
|
||||||
import { Room, MatrixClient, RoomState, RoomMember, User, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
import { Room, MatrixClient, RoomState, RoomMember, User, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||||
import { compare } from "matrix-js-sdk/src/utils";
|
import { compare } from "matrix-js-sdk/src/utils";
|
||||||
|
import { mocked, MockedObject } from "jest-mock";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||||
import * as TestUtils from "../../../test-utils";
|
import * as TestUtils from "../../../test-utils";
|
||||||
import MemberList from "../../../../src/components/views/rooms/MemberList";
|
import MemberList from "../../../../src/components/views/rooms/MemberList";
|
||||||
import { SDKContext } from "../../../../src/contexts/SDKContext";
|
import { SDKContext } from "../../../../src/contexts/SDKContext";
|
||||||
import { TestSdkContext } from "../../../TestSdkContext";
|
import { TestSdkContext } from "../../../TestSdkContext";
|
||||||
|
import {
|
||||||
|
filterConsole,
|
||||||
|
flushPromises,
|
||||||
|
getMockClientWithEventEmitter,
|
||||||
|
mockClientMethodsUser,
|
||||||
|
} from "../../../test-utils";
|
||||||
|
import { shouldShowComponent } from "../../../../src/customisations/helpers/UIComponents";
|
||||||
|
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
|
||||||
|
|
||||||
|
jest.mock("../../../../src/customisations/helpers/UIComponents", () => ({
|
||||||
|
shouldShowComponent: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
function generateRoomId() {
|
function generateRoomId() {
|
||||||
return "!" + Math.random().toString().slice(2, 10) + ":domain";
|
return "!" + Math.random().toString().slice(2, 10) + ":domain";
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("MemberList", () => {
|
describe("MemberList", () => {
|
||||||
|
filterConsole(
|
||||||
|
"Age for event was not available, using `now - origin_server_ts` as a fallback. If the device clock is not correct issues might occur.",
|
||||||
|
);
|
||||||
function createRoom(opts = {}) {
|
function createRoom(opts = {}) {
|
||||||
const room = new Room(generateRoomId(), client, client.getUserId()!);
|
const room = new Room(generateRoomId(), client, client.getUserId()!);
|
||||||
if (opts) {
|
if (opts) {
|
||||||
|
@ -331,5 +347,93 @@ describe("MemberList", () => {
|
||||||
);
|
);
|
||||||
expect(await screen.findByText(/User's server unreachable/)).toBeInTheDocument();
|
expect(await screen.findByText(/User's server unreachable/)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Invite button", () => {
|
||||||
|
const roomId = "!room:server.org";
|
||||||
|
let client!: MockedObject<MatrixClient>;
|
||||||
|
let room!: Room;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mocked(shouldShowComponent).mockReturnValue(true);
|
||||||
|
client = getMockClientWithEventEmitter({
|
||||||
|
...mockClientMethodsUser(),
|
||||||
|
getRoom: jest.fn(),
|
||||||
|
hasLazyLoadMembersEnabled: jest.fn(),
|
||||||
|
});
|
||||||
|
room = new Room(roomId, client, client.getSafeUserId());
|
||||||
|
client.getRoom.mockReturnValue(room);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderComponent = () => {
|
||||||
|
const context = new TestSdkContext();
|
||||||
|
context.client = client;
|
||||||
|
render(
|
||||||
|
<SDKContext.Provider value={context}>
|
||||||
|
<MemberList
|
||||||
|
searchQuery=""
|
||||||
|
onClose={jest.fn()}
|
||||||
|
onSearchQueryChanged={jest.fn()}
|
||||||
|
roomId={room.roomId}
|
||||||
|
/>
|
||||||
|
</SDKContext.Provider>,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
it("does not render invite button when current user is not a member", async () => {
|
||||||
|
renderComponent();
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(screen.queryByText("Invite to this room")).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not render invite button UI customisation hides invites", async () => {
|
||||||
|
mocked(shouldShowComponent).mockReturnValue(false);
|
||||||
|
renderComponent();
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(screen.queryByText("Invite to this room")).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders disabled invite button when current user is a member but does not have rights to invite", async () => {
|
||||||
|
jest.spyOn(room, "getMyMembership").mockReturnValue("join");
|
||||||
|
jest.spyOn(room, "canInvite").mockReturnValue(false);
|
||||||
|
|
||||||
|
renderComponent();
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
// button rendered but disabled
|
||||||
|
expect(screen.getByText("Invite to this room")).toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders enabled invite button when current user is a member and has rights to invite", async () => {
|
||||||
|
jest.spyOn(room, "getMyMembership").mockReturnValue("join");
|
||||||
|
jest.spyOn(room, "canInvite").mockReturnValue(true);
|
||||||
|
|
||||||
|
renderComponent();
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(screen.getByText("Invite to this room")).not.toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("opens room inviter on button click", async () => {
|
||||||
|
jest.spyOn(defaultDispatcher, "dispatch");
|
||||||
|
jest.spyOn(room, "getMyMembership").mockReturnValue("join");
|
||||||
|
jest.spyOn(room, "canInvite").mockReturnValue(true);
|
||||||
|
|
||||||
|
renderComponent();
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByText("Invite to this room"));
|
||||||
|
|
||||||
|
expect(defaultDispatcher.dispatch).toHaveBeenCalledWith({
|
||||||
|
action: "view_invite",
|
||||||
|
roomId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue