More tests for UserInfo (#10677)
* UserInfo-test: move mocking to `beforeEach` ... so that changes to the mocks do not leak between tests * Add some more tests for UserInfopull/28788/head^2
parent
893feed13b
commit
83f12fcba0
|
@ -15,9 +15,9 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { fireEvent, render, screen, waitFor, cleanup, act } from "@testing-library/react";
|
import { fireEvent, render, screen, waitFor, cleanup, act, within } from "@testing-library/react";
|
||||||
import userEvent from "@testing-library/user-event";
|
import userEvent from "@testing-library/user-event";
|
||||||
import { mocked } from "jest-mock";
|
import { Mocked, mocked } from "jest-mock";
|
||||||
import { Room, User, MatrixClient, RoomMember, MatrixEvent, EventType } from "matrix-js-sdk/src/matrix";
|
import { Room, User, MatrixClient, RoomMember, MatrixEvent, EventType } from "matrix-js-sdk/src/matrix";
|
||||||
import { Phase, VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
|
import { Phase, VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest";
|
||||||
import { DeviceTrustLevel, UserTrustLevel } from "matrix-js-sdk/src/crypto/CrossSigning";
|
import { DeviceTrustLevel, UserTrustLevel } from "matrix-js-sdk/src/crypto/CrossSigning";
|
||||||
|
@ -72,73 +72,78 @@ jest.mock("../../../../src/utils/DMRoomMap", () => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const mockRoom = mocked({
|
const defaultRoomId = "!fkfk";
|
||||||
roomId: "!fkfk",
|
|
||||||
getType: jest.fn().mockReturnValue(undefined),
|
|
||||||
isSpaceRoom: jest.fn().mockReturnValue(false),
|
|
||||||
getMember: jest.fn().mockReturnValue(undefined),
|
|
||||||
getMxcAvatarUrl: jest.fn().mockReturnValue("mock-avatar-url"),
|
|
||||||
name: "test room",
|
|
||||||
on: jest.fn(),
|
|
||||||
off: jest.fn(),
|
|
||||||
currentState: {
|
|
||||||
getStateEvents: jest.fn(),
|
|
||||||
on: jest.fn(),
|
|
||||||
},
|
|
||||||
getEventReadUpTo: jest.fn(),
|
|
||||||
} as unknown as Room);
|
|
||||||
|
|
||||||
const mockSpace = mocked({
|
|
||||||
roomId: "!fkfk",
|
|
||||||
getType: jest.fn().mockReturnValue("m.space"),
|
|
||||||
isSpaceRoom: jest.fn().mockReturnValue(true),
|
|
||||||
getMember: jest.fn().mockReturnValue(undefined),
|
|
||||||
getMxcAvatarUrl: jest.fn().mockReturnValue("mock-avatar-url"),
|
|
||||||
name: "test room",
|
|
||||||
on: jest.fn(),
|
|
||||||
off: jest.fn(),
|
|
||||||
currentState: {
|
|
||||||
getStateEvents: jest.fn(),
|
|
||||||
on: jest.fn(),
|
|
||||||
},
|
|
||||||
getEventReadUpTo: jest.fn(),
|
|
||||||
} as unknown as Room);
|
|
||||||
|
|
||||||
const mockClient = mocked({
|
|
||||||
getUser: jest.fn(),
|
|
||||||
isGuest: jest.fn().mockReturnValue(false),
|
|
||||||
isUserIgnored: jest.fn(),
|
|
||||||
getIgnoredUsers: jest.fn(),
|
|
||||||
setIgnoredUsers: jest.fn(),
|
|
||||||
isCryptoEnabled: jest.fn(),
|
|
||||||
getUserId: jest.fn(),
|
|
||||||
getSafeUserId: jest.fn(),
|
|
||||||
on: jest.fn(),
|
|
||||||
off: jest.fn(),
|
|
||||||
isSynapseAdministrator: jest.fn().mockResolvedValue(false),
|
|
||||||
isRoomEncrypted: jest.fn().mockReturnValue(false),
|
|
||||||
doesServerSupportUnstableFeature: jest.fn().mockReturnValue(false),
|
|
||||||
mxcUrlToHttp: jest.fn().mockReturnValue("mock-mxcUrlToHttp"),
|
|
||||||
removeListener: jest.fn(),
|
|
||||||
currentState: {
|
|
||||||
on: jest.fn(),
|
|
||||||
},
|
|
||||||
checkDeviceTrust: jest.fn(),
|
|
||||||
checkUserTrust: jest.fn(),
|
|
||||||
getRoom: jest.fn(),
|
|
||||||
credentials: {},
|
|
||||||
setPowerLevel: jest.fn(),
|
|
||||||
} as unknown as MatrixClient);
|
|
||||||
|
|
||||||
const defaultUserId = "@user:example.com";
|
const defaultUserId = "@user:example.com";
|
||||||
const defaultUser = new User(defaultUserId);
|
const defaultUser = new User(defaultUserId);
|
||||||
|
|
||||||
beforeEach(() => {
|
let mockRoom: Mocked<Room>;
|
||||||
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(mockClient);
|
let mockSpace: Mocked<Room>;
|
||||||
});
|
let mockClient: Mocked<MatrixClient>;
|
||||||
|
|
||||||
afterEach(() => {
|
beforeEach(() => {
|
||||||
mockClient.getUser.mockClear().mockReturnValue({} as unknown as User);
|
mockRoom = mocked({
|
||||||
|
roomId: defaultRoomId,
|
||||||
|
getType: jest.fn().mockReturnValue(undefined),
|
||||||
|
isSpaceRoom: jest.fn().mockReturnValue(false),
|
||||||
|
getMember: jest.fn().mockReturnValue(undefined),
|
||||||
|
getMxcAvatarUrl: jest.fn().mockReturnValue("mock-avatar-url"),
|
||||||
|
name: "test room",
|
||||||
|
on: jest.fn(),
|
||||||
|
off: jest.fn(),
|
||||||
|
currentState: {
|
||||||
|
getStateEvents: jest.fn(),
|
||||||
|
on: jest.fn(),
|
||||||
|
off: jest.fn(),
|
||||||
|
},
|
||||||
|
getEventReadUpTo: jest.fn(),
|
||||||
|
} as unknown as Room);
|
||||||
|
|
||||||
|
mockSpace = mocked({
|
||||||
|
roomId: defaultRoomId,
|
||||||
|
getType: jest.fn().mockReturnValue("m.space"),
|
||||||
|
isSpaceRoom: jest.fn().mockReturnValue(true),
|
||||||
|
getMember: jest.fn().mockReturnValue(undefined),
|
||||||
|
getMxcAvatarUrl: jest.fn().mockReturnValue("mock-avatar-url"),
|
||||||
|
name: "test room",
|
||||||
|
on: jest.fn(),
|
||||||
|
off: jest.fn(),
|
||||||
|
currentState: {
|
||||||
|
getStateEvents: jest.fn(),
|
||||||
|
on: jest.fn(),
|
||||||
|
off: jest.fn(),
|
||||||
|
},
|
||||||
|
getEventReadUpTo: jest.fn(),
|
||||||
|
} as unknown as Room);
|
||||||
|
|
||||||
|
mockClient = mocked({
|
||||||
|
getUser: jest.fn(),
|
||||||
|
isGuest: jest.fn().mockReturnValue(false),
|
||||||
|
isUserIgnored: jest.fn(),
|
||||||
|
getIgnoredUsers: jest.fn(),
|
||||||
|
setIgnoredUsers: jest.fn(),
|
||||||
|
isCryptoEnabled: jest.fn(),
|
||||||
|
getUserId: jest.fn(),
|
||||||
|
getSafeUserId: jest.fn(),
|
||||||
|
on: jest.fn(),
|
||||||
|
off: jest.fn(),
|
||||||
|
isSynapseAdministrator: jest.fn().mockResolvedValue(false),
|
||||||
|
isRoomEncrypted: jest.fn().mockReturnValue(false),
|
||||||
|
doesServerSupportUnstableFeature: jest.fn().mockReturnValue(false),
|
||||||
|
mxcUrlToHttp: jest.fn().mockReturnValue("mock-mxcUrlToHttp"),
|
||||||
|
removeListener: jest.fn(),
|
||||||
|
currentState: {
|
||||||
|
on: jest.fn(),
|
||||||
|
},
|
||||||
|
checkDeviceTrust: jest.fn(),
|
||||||
|
checkUserTrust: jest.fn(),
|
||||||
|
getRoom: jest.fn(),
|
||||||
|
credentials: {},
|
||||||
|
setPowerLevel: jest.fn(),
|
||||||
|
downloadKeys: jest.fn(),
|
||||||
|
getStoredDevicesForUser: jest.fn(),
|
||||||
|
} as unknown as MatrixClient);
|
||||||
|
|
||||||
|
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(mockClient);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("<UserInfo />", () => {
|
describe("<UserInfo />", () => {
|
||||||
|
@ -241,14 +246,76 @@ describe("<UserInfo />", () => {
|
||||||
expect(screen.getByText(/try with a different client/i)).toBeInTheDocument();
|
expect(screen.getByText(/try with a different client/i)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("with crypto enabled", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mockClient.isCryptoEnabled.mockReturnValue(true);
|
||||||
|
mockClient.checkUserTrust.mockReturnValue(new UserTrustLevel(false, false, false));
|
||||||
|
mockClient.checkDeviceTrust.mockReturnValue(new DeviceTrustLevel(false, false, false, false));
|
||||||
|
|
||||||
|
const device1 = DeviceInfo.fromStorage(
|
||||||
|
{
|
||||||
|
unsigned: { device_display_name: "my device" },
|
||||||
|
},
|
||||||
|
"d1",
|
||||||
|
);
|
||||||
|
mockClient.getStoredDevicesForUser.mockReturnValue([device1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders a device list which can be expanded", async () => {
|
||||||
|
renderComponent();
|
||||||
|
await act(flushPromises);
|
||||||
|
|
||||||
|
// check the button exists with the expected text
|
||||||
|
const devicesButton = screen.getByRole("button", { name: "1 session" });
|
||||||
|
|
||||||
|
// click it
|
||||||
|
await userEvent.click(devicesButton);
|
||||||
|
|
||||||
|
// there should now be a button with the device id ...
|
||||||
|
const deviceButton = screen.getByRole("button", { description: "d1" });
|
||||||
|
|
||||||
|
// ... which should contain the device name
|
||||||
|
expect(within(deviceButton).getByText("my device")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("with an encrypted room", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mockClient.isCryptoEnabled.mockReturnValue(true);
|
||||||
|
mockClient.isRoomEncrypted.mockReturnValue(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders unverified user info", async () => {
|
||||||
|
mockClient.checkUserTrust.mockReturnValue(new UserTrustLevel(false, false, false));
|
||||||
|
renderComponent({ room: mockRoom });
|
||||||
|
await act(flushPromises);
|
||||||
|
|
||||||
|
const userHeading = screen.getByRole("heading", { name: defaultUserId });
|
||||||
|
|
||||||
|
// there should be a "normal" E2E padlock
|
||||||
|
expect(userHeading.getElementsByClassName("mx_E2EIcon_normal")).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders verified user info", async () => {
|
||||||
|
mockClient.checkUserTrust.mockReturnValue(new UserTrustLevel(true, false, false));
|
||||||
|
renderComponent({ room: mockRoom });
|
||||||
|
await act(flushPromises);
|
||||||
|
|
||||||
|
const userHeading = screen.getByRole("heading", { name: defaultUserId });
|
||||||
|
|
||||||
|
// there should be a "verified" E2E padlock
|
||||||
|
expect(userHeading.getElementsByClassName("mx_E2EIcon_verified")).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("<UserInfoHeader />", () => {
|
describe("<UserInfoHeader />", () => {
|
||||||
const defaultMember = new RoomMember(mockRoom.roomId, defaultUserId);
|
const defaultMember = new RoomMember(defaultRoomId, defaultUserId);
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
member: defaultMember,
|
member: defaultMember,
|
||||||
roomId: mockRoom.roomId,
|
roomId: defaultRoomId,
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderComponent = (props = {}) => {
|
const renderComponent = (props = {}) => {
|
||||||
|
@ -399,7 +466,7 @@ describe("<DeviceItem />", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("<UserOptionsSection />", () => {
|
describe("<UserOptionsSection />", () => {
|
||||||
const member = new RoomMember(mockRoom.roomId, defaultUserId);
|
const member = new RoomMember(defaultRoomId, defaultUserId);
|
||||||
const defaultProps = { member, isIgnored: false, canInvite: false, isSpace: false };
|
const defaultProps = { member, isIgnored: false, canInvite: false, isSpace: false };
|
||||||
|
|
||||||
const renderComponent = (props = {}) => {
|
const renderComponent = (props = {}) => {
|
||||||
|
@ -644,17 +711,20 @@ describe("<UserOptionsSection />", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("<PowerLevelEditor />", () => {
|
describe("<PowerLevelEditor />", () => {
|
||||||
const defaultMember = new RoomMember(mockRoom.roomId, defaultUserId);
|
const defaultMember = new RoomMember(defaultRoomId, defaultUserId);
|
||||||
|
|
||||||
const defaultProps = {
|
let defaultProps: Parameters<typeof PowerLevelEditor>[0];
|
||||||
user: defaultMember,
|
beforeEach(() => {
|
||||||
room: mockRoom,
|
defaultProps = {
|
||||||
roomPermissions: {
|
user: defaultMember,
|
||||||
modifyLevelMax: 100,
|
room: mockRoom,
|
||||||
canEdit: false,
|
roomPermissions: {
|
||||||
canInvite: false,
|
modifyLevelMax: 100,
|
||||||
},
|
canEdit: false,
|
||||||
};
|
canInvite: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
const renderComponent = (props = {}) => {
|
const renderComponent = (props = {}) => {
|
||||||
const Wrapper = (wrapperProps = {}) => {
|
const Wrapper = (wrapperProps = {}) => {
|
||||||
|
@ -705,11 +775,14 @@ describe("<PowerLevelEditor />", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("<RoomKickButton />", () => {
|
describe("<RoomKickButton />", () => {
|
||||||
const defaultMember = new RoomMember(mockRoom.roomId, defaultUserId);
|
const defaultMember = new RoomMember(defaultRoomId, defaultUserId);
|
||||||
const memberWithInviteMembership = { ...defaultMember, membership: "invite" };
|
const memberWithInviteMembership = { ...defaultMember, membership: "invite" };
|
||||||
const memberWithJoinMembership = { ...defaultMember, membership: "join" };
|
const memberWithJoinMembership = { ...defaultMember, membership: "join" };
|
||||||
|
|
||||||
const defaultProps = { room: mockRoom, member: defaultMember, startUpdating: jest.fn(), stopUpdating: jest.fn() };
|
let defaultProps: Parameters<typeof RoomKickButton>[0];
|
||||||
|
beforeEach(() => {
|
||||||
|
defaultProps = { room: mockRoom, member: defaultMember, startUpdating: jest.fn(), stopUpdating: jest.fn() };
|
||||||
|
});
|
||||||
|
|
||||||
const renderComponent = (props = {}) => {
|
const renderComponent = (props = {}) => {
|
||||||
const Wrapper = (wrapperProps = {}) => {
|
const Wrapper = (wrapperProps = {}) => {
|
||||||
|
@ -805,10 +878,12 @@ describe("<RoomKickButton />", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("<BanToggleButton />", () => {
|
describe("<BanToggleButton />", () => {
|
||||||
const defaultMember = new RoomMember(mockRoom.roomId, defaultUserId);
|
const defaultMember = new RoomMember(defaultRoomId, defaultUserId);
|
||||||
const memberWithBanMembership = { ...defaultMember, membership: "ban" };
|
const memberWithBanMembership = { ...defaultMember, membership: "ban" };
|
||||||
|
let defaultProps: Parameters<typeof BanToggleButton>[0];
|
||||||
const defaultProps = { room: mockRoom, member: defaultMember, startUpdating: jest.fn(), stopUpdating: jest.fn() };
|
beforeEach(() => {
|
||||||
|
defaultProps = { room: mockRoom, member: defaultMember, startUpdating: jest.fn(), stopUpdating: jest.fn() };
|
||||||
|
});
|
||||||
|
|
||||||
const renderComponent = (props = {}) => {
|
const renderComponent = (props = {}) => {
|
||||||
const Wrapper = (wrapperProps = {}) => {
|
const Wrapper = (wrapperProps = {}) => {
|
||||||
|
@ -927,16 +1002,19 @@ describe("<BanToggleButton />", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("<RoomAdminToolsContainer />", () => {
|
describe("<RoomAdminToolsContainer />", () => {
|
||||||
const defaultMember = new RoomMember(mockRoom.roomId, defaultUserId);
|
const defaultMember = new RoomMember(defaultRoomId, defaultUserId);
|
||||||
defaultMember.membership = "invite";
|
defaultMember.membership = "invite";
|
||||||
|
|
||||||
const defaultProps = {
|
let defaultProps: Parameters<typeof RoomAdminToolsContainer>[0];
|
||||||
room: mockRoom,
|
beforeEach(() => {
|
||||||
member: defaultMember,
|
defaultProps = {
|
||||||
startUpdating: jest.fn(),
|
room: mockRoom,
|
||||||
stopUpdating: jest.fn(),
|
member: defaultMember,
|
||||||
powerLevels: {},
|
startUpdating: jest.fn(),
|
||||||
};
|
stopUpdating: jest.fn(),
|
||||||
|
powerLevels: {},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
const renderComponent = (props = {}) => {
|
const renderComponent = (props = {}) => {
|
||||||
const Wrapper = (wrapperProps = {}) => {
|
const Wrapper = (wrapperProps = {}) => {
|
||||||
|
@ -1039,7 +1117,7 @@ describe("disambiguateDevices", () => {
|
||||||
|
|
||||||
describe("isMuted", () => {
|
describe("isMuted", () => {
|
||||||
// this member has a power level of 0
|
// this member has a power level of 0
|
||||||
const isMutedMember = new RoomMember(mockRoom.roomId, defaultUserId);
|
const isMutedMember = new RoomMember(defaultRoomId, defaultUserId);
|
||||||
|
|
||||||
it("returns false if either argument is falsy", () => {
|
it("returns false if either argument is falsy", () => {
|
||||||
// @ts-ignore to let us purposely pass incorrect args
|
// @ts-ignore to let us purposely pass incorrect args
|
||||||
|
|
|
@ -127,7 +127,7 @@ export function untilEmission(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const flushPromises = async () => await new Promise((resolve) => window.setTimeout(resolve));
|
export const flushPromises = async () => await new Promise<void>((resolve) => window.setTimeout(resolve));
|
||||||
|
|
||||||
// with jest's modern fake timers process.nextTick is also mocked,
|
// with jest's modern fake timers process.nextTick is also mocked,
|
||||||
// flushing promises in the normal way then waits for some advancement
|
// flushing promises in the normal way then waits for some advancement
|
||||||
|
|
Loading…
Reference in New Issue