feat(crypto): Support verification violation composer banner (#29067)
* feat(crypto): Support verification violation composer banner * refactor UserIdentityWarning by using now a ViewModel fixup: logger import fixup: test lint type problems fix test having an unexpected verification violation fixup sonarcubes warnings * review: comments on types and inline some const * review: Quick refactor, better handling of action on button click * review: Small updates, remove commented code
This commit is contained in:
@@ -424,7 +424,7 @@ describe("RoomView", () => {
|
||||
jest.spyOn(cli, "getCrypto").mockReturnValue(crypto);
|
||||
jest.spyOn(cli.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true);
|
||||
jest.spyOn(cli.getCrypto()!, "getUserVerificationStatus").mockResolvedValue(
|
||||
new UserVerificationStatus(false, true, false),
|
||||
new UserVerificationStatus(false, false, false),
|
||||
);
|
||||
localRoom.encrypted = true;
|
||||
localRoom.currentState.setStateEvents([
|
||||
|
||||
@@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
import { sleep, defer } from "matrix-js-sdk/src/utils";
|
||||
import {
|
||||
EventType,
|
||||
MatrixClient,
|
||||
@@ -37,6 +37,50 @@ function mockRoom(): Room {
|
||||
return room;
|
||||
}
|
||||
|
||||
function mockMembershipForRoom(room: Room, users: string[] | [string, "joined" | "invited"][]): void {
|
||||
const encryptToInvited = room.shouldEncryptForInvitedMembers();
|
||||
const members = users
|
||||
.filter((user) => {
|
||||
if (Array.isArray(user)) {
|
||||
return encryptToInvited || user[1] === "joined";
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
})
|
||||
.map((id) => {
|
||||
if (Array.isArray(id)) {
|
||||
return mockRoomMember(id[0]);
|
||||
} else {
|
||||
return mockRoomMember(id);
|
||||
}
|
||||
});
|
||||
|
||||
jest.spyOn(room, "getEncryptionTargetMembers").mockResolvedValue(members);
|
||||
|
||||
jest.spyOn(room, "getMember").mockImplementation((userId) => {
|
||||
return members.find((member) => member.userId === userId) ?? null;
|
||||
});
|
||||
}
|
||||
|
||||
function emitMembershipChange(client: MatrixClient, userId: string, membership: "join" | "leave" | "invite"): void {
|
||||
const sender = membership === "invite" ? "@carol:example.org" : userId;
|
||||
client.emit(
|
||||
RoomStateEvent.Events,
|
||||
new MatrixEvent({
|
||||
event_id: "$event_id",
|
||||
type: EventType.RoomMember,
|
||||
state_key: userId,
|
||||
content: {
|
||||
membership: membership,
|
||||
},
|
||||
room_id: ROOM_ID,
|
||||
sender: sender,
|
||||
}),
|
||||
dummyRoomState(),
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
function mockRoomMember(userId: string, name?: string): RoomMember {
|
||||
return {
|
||||
userId,
|
||||
@@ -97,7 +141,7 @@ describe("UserIdentityWarning", () => {
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockResolvedValue(
|
||||
new UserVerificationStatus(false, false, false, true),
|
||||
);
|
||||
crypto.pinCurrentUserIdentity = jest.fn();
|
||||
crypto.pinCurrentUserIdentity = jest.fn().mockResolvedValue(undefined);
|
||||
renderComponent(client, room);
|
||||
|
||||
await waitFor(() =>
|
||||
@@ -109,6 +153,49 @@ describe("UserIdentityWarning", () => {
|
||||
await waitFor(() => expect(crypto.pinCurrentUserIdentity).toHaveBeenCalledWith("@alice:example.org"));
|
||||
});
|
||||
|
||||
// This tests the basic functionality of the component. If we have a room
|
||||
// member whose identity is in verification violation, we should display a warning. When
|
||||
// the "Withdraw verification" button gets pressed, it should call `withdrawVerification`.
|
||||
it("displays a warning when a user's identity is in verification violation", async () => {
|
||||
jest.spyOn(room, "getEncryptionTargetMembers").mockResolvedValue([
|
||||
mockRoomMember("@alice:example.org", "Alice"),
|
||||
]);
|
||||
const crypto = client.getCrypto()!;
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockResolvedValue(
|
||||
new UserVerificationStatus(false, true, false, true),
|
||||
);
|
||||
crypto.withdrawVerificationRequirement = jest.fn().mockResolvedValue(undefined);
|
||||
renderComponent(client, room);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(getWarningByText("Alice's (@alice:example.org) verified identity has changed.")).toBeInTheDocument(),
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByRole("button", {
|
||||
name: "Withdraw verification",
|
||||
}),
|
||||
).toBeInTheDocument();
|
||||
await userEvent.click(screen.getByRole("button")!);
|
||||
await waitFor(() => expect(crypto.withdrawVerificationRequirement).toHaveBeenCalledWith("@alice:example.org"));
|
||||
});
|
||||
|
||||
it("Should not display a warning if the user was verified and is still verified", async () => {
|
||||
jest.spyOn(room, "getEncryptionTargetMembers").mockResolvedValue([
|
||||
mockRoomMember("@alice:example.org", "Alice"),
|
||||
]);
|
||||
const crypto = client.getCrypto()!;
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockResolvedValue(
|
||||
new UserVerificationStatus(true, true, false, false),
|
||||
);
|
||||
|
||||
renderComponent(client, room);
|
||||
await sleep(10); // give it some time to finish initialising
|
||||
|
||||
expect(() => getWarningByText("Alice's (@alice:example.org) identity appears to have changed.")).toThrow();
|
||||
expect(() => getWarningByText("Alice's (@alice:example.org) verified identity has changed.")).toThrow();
|
||||
});
|
||||
|
||||
// We don't display warnings in non-encrypted rooms, but if encryption is
|
||||
// enabled, then we should display a warning if there are any users whose
|
||||
// identity need accepting.
|
||||
@@ -124,6 +211,7 @@ describe("UserIdentityWarning", () => {
|
||||
);
|
||||
|
||||
renderComponent(client, room);
|
||||
|
||||
await sleep(10); // give it some time to finish initialising
|
||||
expect(() => getWarningByText("Alice's (@alice:example.org) identity appears to have changed.")).toThrow();
|
||||
|
||||
@@ -152,6 +240,57 @@ describe("UserIdentityWarning", () => {
|
||||
);
|
||||
});
|
||||
|
||||
describe("Warnings are displayed in consistent order", () => {
|
||||
it("Ensure lexicographic order for prompt", async () => {
|
||||
// members are not returned lexicographic order
|
||||
mockMembershipForRoom(room, ["@b:example.org", "@a:example.org"]);
|
||||
|
||||
const crypto = client.getCrypto()!;
|
||||
|
||||
// All identities needs approval
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockResolvedValue(
|
||||
new UserVerificationStatus(false, false, false, true),
|
||||
);
|
||||
|
||||
crypto.pinCurrentUserIdentity = jest.fn();
|
||||
renderComponent(client, room);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(getWarningByText("@a:example.org's identity appears to have changed.")).toBeInTheDocument(),
|
||||
);
|
||||
});
|
||||
|
||||
it("Ensure existing prompt stays even if a new violation with lower lexicographic order detected", async () => {
|
||||
mockMembershipForRoom(room, ["@b:example.org"]);
|
||||
|
||||
const crypto = client.getCrypto()!;
|
||||
|
||||
// All identities needs approval
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockResolvedValue(
|
||||
new UserVerificationStatus(false, false, false, true),
|
||||
);
|
||||
|
||||
crypto.pinCurrentUserIdentity = jest.fn();
|
||||
renderComponent(client, room);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(getWarningByText("@b:example.org's identity appears to have changed.")).toBeInTheDocument(),
|
||||
);
|
||||
|
||||
// Simulate a new member joined with lower lexico order and also in violation
|
||||
mockMembershipForRoom(room, ["@a:example.org", "@b:example.org"]);
|
||||
|
||||
act(() => {
|
||||
emitMembershipChange(client, "@a:example.org", "join");
|
||||
});
|
||||
|
||||
// We should still display the warning for @b:example.org
|
||||
await waitFor(() =>
|
||||
expect(getWarningByText("@b:example.org's identity appears to have changed.")).toBeInTheDocument(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// When a user's identity needs approval, or has been approved, the display
|
||||
// should update appropriately.
|
||||
it("updates the display when identity changes", async () => {
|
||||
@@ -163,18 +302,20 @@ describe("UserIdentityWarning", () => {
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockResolvedValue(
|
||||
new UserVerificationStatus(false, false, false, false),
|
||||
);
|
||||
renderComponent(client, room);
|
||||
await sleep(10); // give it some time to finish initialising
|
||||
await act(async () => {
|
||||
renderComponent(client, room);
|
||||
await sleep(50);
|
||||
});
|
||||
|
||||
expect(() => getWarningByText("Alice's (@alice:example.org) identity appears to have changed.")).toThrow();
|
||||
|
||||
// The user changes their identity, so we should show the warning.
|
||||
act(() => {
|
||||
client.emit(
|
||||
CryptoEvent.UserTrustStatusChanged,
|
||||
"@alice:example.org",
|
||||
new UserVerificationStatus(false, false, false, true),
|
||||
);
|
||||
const newStatus = new UserVerificationStatus(false, false, false, true);
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockResolvedValue(newStatus);
|
||||
client.emit(CryptoEvent.UserTrustStatusChanged, "@alice:example.org", newStatus);
|
||||
});
|
||||
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
getWarningByText("Alice's (@alice:example.org) identity appears to have changed."),
|
||||
@@ -184,11 +325,9 @@ describe("UserIdentityWarning", () => {
|
||||
// Simulate the user's new identity having been approved, so we no
|
||||
// longer show the warning.
|
||||
act(() => {
|
||||
client.emit(
|
||||
CryptoEvent.UserTrustStatusChanged,
|
||||
"@alice:example.org",
|
||||
new UserVerificationStatus(false, false, false, false),
|
||||
);
|
||||
const newStatus = new UserVerificationStatus(false, false, false, false);
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockResolvedValue(newStatus);
|
||||
client.emit(CryptoEvent.UserTrustStatusChanged, "@alice:example.org", newStatus);
|
||||
});
|
||||
await waitFor(() =>
|
||||
expect(() => getWarningByText("Alice's (@alice:example.org) identity appears to have changed.")).toThrow(),
|
||||
@@ -200,8 +339,7 @@ describe("UserIdentityWarning", () => {
|
||||
describe("updates the display when a member joins/leaves", () => {
|
||||
it("when invited users can see encrypted messages", async () => {
|
||||
// Nobody in the room yet
|
||||
jest.spyOn(room, "getEncryptionTargetMembers").mockResolvedValue([]);
|
||||
jest.spyOn(room, "getMember").mockImplementation((userId) => mockRoomMember(userId));
|
||||
mockMembershipForRoom(room, []);
|
||||
jest.spyOn(room, "shouldEncryptForInvitedMembers").mockReturnValue(true);
|
||||
const crypto = client.getCrypto()!;
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockResolvedValue(
|
||||
@@ -211,62 +349,29 @@ describe("UserIdentityWarning", () => {
|
||||
await sleep(10); // give it some time to finish initialising
|
||||
|
||||
// Alice joins. Her identity needs approval, so we should show a warning.
|
||||
client.emit(
|
||||
RoomStateEvent.Events,
|
||||
new MatrixEvent({
|
||||
event_id: "$event_id",
|
||||
type: EventType.RoomMember,
|
||||
state_key: "@alice:example.org",
|
||||
content: {
|
||||
membership: "join",
|
||||
},
|
||||
room_id: ROOM_ID,
|
||||
sender: "@alice:example.org",
|
||||
}),
|
||||
dummyRoomState(),
|
||||
null,
|
||||
);
|
||||
act(() => {
|
||||
mockMembershipForRoom(room, ["@alice:example.org"]);
|
||||
emitMembershipChange(client, "@alice:example.org", "join");
|
||||
});
|
||||
|
||||
await waitFor(() =>
|
||||
expect(getWarningByText("@alice:example.org's identity appears to have changed.")).toBeInTheDocument(),
|
||||
);
|
||||
|
||||
// Bob is invited. His identity needs approval, so we should show a
|
||||
// warning for him after Alice's warning is resolved by her leaving.
|
||||
client.emit(
|
||||
RoomStateEvent.Events,
|
||||
new MatrixEvent({
|
||||
event_id: "$event_id",
|
||||
type: EventType.RoomMember,
|
||||
state_key: "@bob:example.org",
|
||||
content: {
|
||||
membership: "invite",
|
||||
},
|
||||
room_id: ROOM_ID,
|
||||
sender: "@carol:example.org",
|
||||
}),
|
||||
dummyRoomState(),
|
||||
null,
|
||||
);
|
||||
act(() => {
|
||||
mockMembershipForRoom(room, ["@alice:example.org", "@bob:example.org"]);
|
||||
emitMembershipChange(client, "@bob:example.org", "invite");
|
||||
});
|
||||
|
||||
// Alice leaves, so we no longer show her warning, but we will show
|
||||
// a warning for Bob.
|
||||
act(() => {
|
||||
client.emit(
|
||||
RoomStateEvent.Events,
|
||||
new MatrixEvent({
|
||||
event_id: "$event_id",
|
||||
type: EventType.RoomMember,
|
||||
state_key: "@alice:example.org",
|
||||
content: {
|
||||
membership: "leave",
|
||||
},
|
||||
room_id: ROOM_ID,
|
||||
sender: "@alice:example.org",
|
||||
}),
|
||||
dummyRoomState(),
|
||||
null,
|
||||
);
|
||||
mockMembershipForRoom(room, ["@bob:example.org"]);
|
||||
emitMembershipChange(client, "@alice:example.org", "leave");
|
||||
});
|
||||
|
||||
await waitFor(() =>
|
||||
expect(() => getWarningByText("@alice:example.org's identity appears to have changed.")).toThrow(),
|
||||
);
|
||||
@@ -277,8 +382,9 @@ describe("UserIdentityWarning", () => {
|
||||
|
||||
it("when invited users cannot see encrypted messages", async () => {
|
||||
// Nobody in the room yet
|
||||
jest.spyOn(room, "getEncryptionTargetMembers").mockResolvedValue([]);
|
||||
jest.spyOn(room, "getMember").mockImplementation((userId) => mockRoomMember(userId));
|
||||
mockMembershipForRoom(room, []);
|
||||
// jest.spyOn(room, "getEncryptionTargetMembers").mockResolvedValue([]);
|
||||
// jest.spyOn(room, "getMember").mockImplementation((userId) => mockRoomMember(userId));
|
||||
jest.spyOn(room, "shouldEncryptForInvitedMembers").mockReturnValue(false);
|
||||
const crypto = client.getCrypto()!;
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockResolvedValue(
|
||||
@@ -288,21 +394,10 @@ describe("UserIdentityWarning", () => {
|
||||
await sleep(10); // give it some time to finish initialising
|
||||
|
||||
// Alice joins. Her identity needs approval, so we should show a warning.
|
||||
client.emit(
|
||||
RoomStateEvent.Events,
|
||||
new MatrixEvent({
|
||||
event_id: "$event_id",
|
||||
type: EventType.RoomMember,
|
||||
state_key: "@alice:example.org",
|
||||
content: {
|
||||
membership: "join",
|
||||
},
|
||||
room_id: ROOM_ID,
|
||||
sender: "@alice:example.org",
|
||||
}),
|
||||
dummyRoomState(),
|
||||
null,
|
||||
);
|
||||
act(() => {
|
||||
mockMembershipForRoom(room, ["@alice:example.org"]);
|
||||
emitMembershipChange(client, "@alice:example.org", "join");
|
||||
});
|
||||
await waitFor(() =>
|
||||
expect(getWarningByText("@alice:example.org's identity appears to have changed.")).toBeInTheDocument(),
|
||||
);
|
||||
@@ -310,40 +405,19 @@ describe("UserIdentityWarning", () => {
|
||||
// Bob is invited. His identity needs approval, but we don't encrypt
|
||||
// to him, so we won't show a warning. (When Alice leaves, the
|
||||
// display won't be updated to show a warningfor Bob.)
|
||||
client.emit(
|
||||
RoomStateEvent.Events,
|
||||
new MatrixEvent({
|
||||
event_id: "$event_id",
|
||||
type: EventType.RoomMember,
|
||||
state_key: "@bob:example.org",
|
||||
content: {
|
||||
membership: "invite",
|
||||
},
|
||||
room_id: ROOM_ID,
|
||||
sender: "@carol:example.org",
|
||||
}),
|
||||
dummyRoomState(),
|
||||
null,
|
||||
);
|
||||
act(() => {
|
||||
mockMembershipForRoom(room, [
|
||||
["@alice:example.org", "joined"],
|
||||
["@bob:example.org", "invited"],
|
||||
]);
|
||||
emitMembershipChange(client, "@bob:example.org", "invite");
|
||||
});
|
||||
|
||||
// Alice leaves, so we no longer show her warning, and we don't show
|
||||
// a warning for Bob.
|
||||
act(() => {
|
||||
client.emit(
|
||||
RoomStateEvent.Events,
|
||||
new MatrixEvent({
|
||||
event_id: "$event_id",
|
||||
type: EventType.RoomMember,
|
||||
state_key: "@alice:example.org",
|
||||
content: {
|
||||
membership: "leave",
|
||||
},
|
||||
room_id: ROOM_ID,
|
||||
sender: "@alice:example.org",
|
||||
}),
|
||||
dummyRoomState(),
|
||||
null,
|
||||
);
|
||||
mockMembershipForRoom(room, [["@bob:example.org", "invited"]]);
|
||||
emitMembershipChange(client, "@alice:example.org", "leave");
|
||||
});
|
||||
await waitFor(() =>
|
||||
expect(() => getWarningByText("@alice:example.org's identity appears to have changed.")).toThrow(),
|
||||
@@ -354,37 +428,26 @@ describe("UserIdentityWarning", () => {
|
||||
});
|
||||
|
||||
it("when member leaves immediately after component is loaded", async () => {
|
||||
let hasLeft = false;
|
||||
jest.spyOn(room, "getEncryptionTargetMembers").mockImplementation(async () => {
|
||||
if (hasLeft) return [];
|
||||
setTimeout(() => {
|
||||
// Alice immediately leaves after we get the room
|
||||
// membership, so we shouldn't show the warning any more
|
||||
client.emit(
|
||||
RoomStateEvent.Events,
|
||||
new MatrixEvent({
|
||||
event_id: "$event_id",
|
||||
type: EventType.RoomMember,
|
||||
state_key: "@alice:example.org",
|
||||
content: {
|
||||
membership: "leave",
|
||||
},
|
||||
room_id: ROOM_ID,
|
||||
sender: "@alice:example.org",
|
||||
}),
|
||||
dummyRoomState(),
|
||||
null,
|
||||
);
|
||||
emitMembershipChange(client, "@alice:example.org", "leave");
|
||||
hasLeft = true;
|
||||
});
|
||||
return [mockRoomMember("@alice:example.org")];
|
||||
});
|
||||
jest.spyOn(room, "getMember").mockImplementation((userId) => mockRoomMember(userId));
|
||||
|
||||
jest.spyOn(room, "shouldEncryptForInvitedMembers").mockReturnValue(false);
|
||||
const crypto = client.getCrypto()!;
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockResolvedValue(
|
||||
new UserVerificationStatus(false, false, false, true),
|
||||
);
|
||||
renderComponent(client, room);
|
||||
|
||||
await sleep(10);
|
||||
await act(async () => {
|
||||
renderComponent(client, room);
|
||||
await sleep(10);
|
||||
});
|
||||
expect(() => getWarningByText("@alice:example.org's identity appears to have changed.")).toThrow();
|
||||
});
|
||||
|
||||
@@ -461,6 +524,51 @@ describe("UserIdentityWarning", () => {
|
||||
// Simulate Alice's new identity having been approved, so now we warn
|
||||
// about Bob's identity.
|
||||
act(() => {
|
||||
const newStatus = new UserVerificationStatus(false, false, false, false);
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockImplementation(async (userId) => {
|
||||
if (userId == "@alice:example.org") {
|
||||
return newStatus;
|
||||
} else {
|
||||
return new UserVerificationStatus(false, false, false, true);
|
||||
}
|
||||
});
|
||||
client.emit(CryptoEvent.UserTrustStatusChanged, "@alice:example.org", newStatus);
|
||||
});
|
||||
await waitFor(() =>
|
||||
expect(getWarningByText("@bob:example.org's identity appears to have changed.")).toBeInTheDocument(),
|
||||
);
|
||||
});
|
||||
|
||||
it("displays the next user when the verification requirement is withdrawn", async () => {
|
||||
jest.spyOn(room, "getEncryptionTargetMembers").mockResolvedValue([
|
||||
mockRoomMember("@alice:example.org", "Alice"),
|
||||
mockRoomMember("@bob:example.org"),
|
||||
]);
|
||||
const crypto = client.getCrypto()!;
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockImplementation(async (userId) => {
|
||||
if (userId == "@alice:example.org") {
|
||||
return new UserVerificationStatus(false, true, false, true);
|
||||
} else {
|
||||
return new UserVerificationStatus(false, false, false, true);
|
||||
}
|
||||
});
|
||||
|
||||
renderComponent(client, room);
|
||||
// We should warn about Alice's identity first.
|
||||
await waitFor(() =>
|
||||
expect(getWarningByText("Alice's (@alice:example.org) verified identity has changed.")).toBeInTheDocument(),
|
||||
);
|
||||
|
||||
// Simulate Alice's new identity having been approved, so now we warn
|
||||
// about Bob's identity.
|
||||
act(() => {
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockImplementation(async (userId) => {
|
||||
if (userId == "@alice:example.org") {
|
||||
return new UserVerificationStatus(false, false, false, false);
|
||||
} else {
|
||||
return new UserVerificationStatus(false, false, false, true);
|
||||
}
|
||||
});
|
||||
client.emit(
|
||||
CryptoEvent.UserTrustStatusChanged,
|
||||
"@alice:example.org",
|
||||
@@ -484,51 +592,36 @@ describe("UserIdentityWarning", () => {
|
||||
]);
|
||||
jest.spyOn(room, "getMember").mockReturnValue(mockRoomMember("@alice:example.org", "Alice"));
|
||||
const crypto = client.getCrypto()!;
|
||||
|
||||
const firstStatusPromise = defer();
|
||||
let callNumber = 0;
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockImplementation(async () => {
|
||||
act(() => {
|
||||
client.emit(
|
||||
CryptoEvent.UserTrustStatusChanged,
|
||||
"@alice:example.org",
|
||||
new UserVerificationStatus(false, false, false, true),
|
||||
);
|
||||
});
|
||||
return Promise.resolve(new UserVerificationStatus(false, false, false, false));
|
||||
await firstStatusPromise.promise;
|
||||
callNumber++;
|
||||
if (callNumber == 1) {
|
||||
await sleep(40);
|
||||
return new UserVerificationStatus(false, false, false, false);
|
||||
} else {
|
||||
return new UserVerificationStatus(false, false, false, true);
|
||||
}
|
||||
});
|
||||
|
||||
renderComponent(client, room);
|
||||
await sleep(10); // give it some time to finish initialising
|
||||
|
||||
act(() => {
|
||||
client.emit(
|
||||
CryptoEvent.UserTrustStatusChanged,
|
||||
"@alice:example.org",
|
||||
new UserVerificationStatus(false, false, false, true),
|
||||
);
|
||||
firstStatusPromise.resolve(undefined);
|
||||
});
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
getWarningByText("Alice's (@alice:example.org) identity appears to have changed."),
|
||||
).toBeInTheDocument(),
|
||||
);
|
||||
});
|
||||
|
||||
// Second case: check that if the update says that the user identity
|
||||
// doesn't needs approval, but the fetch says it does, we don't show the
|
||||
// warning.
|
||||
it("update says identity doesn't need approval", async () => {
|
||||
jest.spyOn(room, "getEncryptionTargetMembers").mockResolvedValue([
|
||||
mockRoomMember("@alice:example.org", "Alice"),
|
||||
]);
|
||||
jest.spyOn(room, "getMember").mockReturnValue(mockRoomMember("@alice:example.org", "Alice"));
|
||||
const crypto = client.getCrypto()!;
|
||||
jest.spyOn(crypto, "getUserVerificationStatus").mockImplementation(async () => {
|
||||
act(() => {
|
||||
client.emit(
|
||||
CryptoEvent.UserTrustStatusChanged,
|
||||
"@alice:example.org",
|
||||
new UserVerificationStatus(false, false, false, false),
|
||||
);
|
||||
});
|
||||
return Promise.resolve(new UserVerificationStatus(false, false, false, true));
|
||||
});
|
||||
renderComponent(client, room);
|
||||
await sleep(10); // give it some time to finish initialising
|
||||
await waitFor(() =>
|
||||
expect(() =>
|
||||
getWarningByText("Alice's (@alice:example.org) identity appears to have changed."),
|
||||
).toThrow(),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user