mirror of
https://github.com/element-hq/element-web
synced 2024-11-28 12:28:50 +03:00
Use test helpers from js-sdk for encrypted events (#12364)
* Use test helpers from js-sdk for encrypted events Rather than gut-wrenching into the matrix-js-sdk, let's use the newly-exported test helpers to generate encrypted events. * Fix up
This commit is contained in:
parent
8f22550f19
commit
64806d0490
4 changed files with 57 additions and 110 deletions
|
@ -78,6 +78,7 @@ module.exports = {
|
|||
"!matrix-js-sdk/src/matrix",
|
||||
"!matrix-js-sdk/src/crypto-api",
|
||||
"!matrix-js-sdk/src/types",
|
||||
"!matrix-js-sdk/src/testing",
|
||||
"matrix-js-sdk/lib",
|
||||
"matrix-js-sdk/lib/",
|
||||
"matrix-js-sdk/lib/**",
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { mkDecryptionFailureMatrixEvent } from "matrix-js-sdk/src/testing";
|
||||
|
||||
import { DecryptionFailureTracker } from "../src/DecryptionFailureTracker";
|
||||
|
||||
|
@ -26,20 +26,18 @@ class MockDecryptionError extends Error {
|
|||
}
|
||||
}
|
||||
|
||||
function createFailedDecryptionEvent() {
|
||||
const event = new MatrixEvent({
|
||||
event_id: "event-id-" + Math.random().toString(16).slice(2),
|
||||
content: {
|
||||
algorithm: "m.megolm.v1.aes-sha2",
|
||||
},
|
||||
async function createFailedDecryptionEvent() {
|
||||
return await mkDecryptionFailureMatrixEvent({
|
||||
roomId: "!room:id",
|
||||
sender: "@alice:example.com",
|
||||
code: "UNKNOWN_ERROR",
|
||||
msg: ":(",
|
||||
});
|
||||
event.setClearData(event.badEncryptedMessage(":("));
|
||||
return event;
|
||||
}
|
||||
|
||||
describe("DecryptionFailureTracker", function () {
|
||||
it("tracks a failed decryption for a visible event", function () {
|
||||
const failedDecryptionEvent = createFailedDecryptionEvent();
|
||||
it("tracks a failed decryption for a visible event", async function () {
|
||||
const failedDecryptionEvent = await createFailedDecryptionEvent();
|
||||
|
||||
let count = 0;
|
||||
const tracker = new DecryptionFailureTracker(
|
||||
|
@ -61,8 +59,8 @@ describe("DecryptionFailureTracker", function () {
|
|||
expect(count).not.toBe(0, "should track a failure for an event that failed decryption");
|
||||
});
|
||||
|
||||
it("tracks a failed decryption with expected raw error for a visible event", function () {
|
||||
const failedDecryptionEvent = createFailedDecryptionEvent();
|
||||
it("tracks a failed decryption with expected raw error for a visible event", async function () {
|
||||
const failedDecryptionEvent = await createFailedDecryptionEvent();
|
||||
|
||||
let count = 0;
|
||||
let reportedRawCode = "";
|
||||
|
@ -89,8 +87,8 @@ describe("DecryptionFailureTracker", function () {
|
|||
expect(reportedRawCode).toBe("INBOUND_SESSION_MISMATCH_ROOM_ID", "Should add the rawCode to the event context");
|
||||
});
|
||||
|
||||
it("tracks a failed decryption for an event that becomes visible later", function () {
|
||||
const failedDecryptionEvent = createFailedDecryptionEvent();
|
||||
it("tracks a failed decryption for an event that becomes visible later", async function () {
|
||||
const failedDecryptionEvent = await createFailedDecryptionEvent();
|
||||
|
||||
let count = 0;
|
||||
const tracker = new DecryptionFailureTracker(
|
||||
|
@ -112,8 +110,8 @@ describe("DecryptionFailureTracker", function () {
|
|||
expect(count).not.toBe(0, "should track a failure for an event that failed decryption");
|
||||
});
|
||||
|
||||
it("does not track a failed decryption for an event that never becomes visible", function () {
|
||||
const failedDecryptionEvent = createFailedDecryptionEvent();
|
||||
it("does not track a failed decryption for an event that never becomes visible", async function () {
|
||||
const failedDecryptionEvent = await createFailedDecryptionEvent();
|
||||
|
||||
let count = 0;
|
||||
const tracker = new DecryptionFailureTracker(
|
||||
|
@ -133,8 +131,8 @@ describe("DecryptionFailureTracker", function () {
|
|||
expect(count).toBe(0, "should not track a failure for an event that never became visible");
|
||||
});
|
||||
|
||||
it("does not track a failed decryption where the event is subsequently successfully decrypted", () => {
|
||||
const decryptedEvent = createFailedDecryptionEvent();
|
||||
it("does not track a failed decryption where the event is subsequently successfully decrypted", async () => {
|
||||
const decryptedEvent = await createFailedDecryptionEvent();
|
||||
const tracker = new DecryptionFailureTracker(
|
||||
(total) => {
|
||||
expect(true).toBe(false, "should not track an event that has since been decrypted correctly");
|
||||
|
@ -161,8 +159,8 @@ describe("DecryptionFailureTracker", function () {
|
|||
it(
|
||||
"does not track a failed decryption where the event is subsequently successfully decrypted " +
|
||||
"and later becomes visible",
|
||||
() => {
|
||||
const decryptedEvent = createFailedDecryptionEvent();
|
||||
async () => {
|
||||
const decryptedEvent = await createFailedDecryptionEvent();
|
||||
const tracker = new DecryptionFailureTracker(
|
||||
(total) => {
|
||||
expect(true).toBe(false, "should not track an event that has since been decrypted correctly");
|
||||
|
@ -187,9 +185,9 @@ describe("DecryptionFailureTracker", function () {
|
|||
},
|
||||
);
|
||||
|
||||
it("only tracks a single failure per event, despite multiple failed decryptions for multiple events", () => {
|
||||
const decryptedEvent = createFailedDecryptionEvent();
|
||||
const decryptedEvent2 = createFailedDecryptionEvent();
|
||||
it("only tracks a single failure per event, despite multiple failed decryptions for multiple events", async () => {
|
||||
const decryptedEvent = await createFailedDecryptionEvent();
|
||||
const decryptedEvent2 = await createFailedDecryptionEvent();
|
||||
|
||||
let count = 0;
|
||||
const tracker = new DecryptionFailureTracker(
|
||||
|
@ -223,8 +221,8 @@ describe("DecryptionFailureTracker", function () {
|
|||
expect(count).toBe(2, count + " failures tracked, should only track a single failure per event");
|
||||
});
|
||||
|
||||
it("should not track a failure for an event that was tracked previously", () => {
|
||||
const decryptedEvent = createFailedDecryptionEvent();
|
||||
it("should not track a failure for an event that was tracked previously", async () => {
|
||||
const decryptedEvent = await createFailedDecryptionEvent();
|
||||
|
||||
let count = 0;
|
||||
const tracker = new DecryptionFailureTracker(
|
||||
|
@ -251,11 +249,11 @@ describe("DecryptionFailureTracker", function () {
|
|||
expect(count).toBe(1, "should only track a single failure per event");
|
||||
});
|
||||
|
||||
it.skip("should not track a failure for an event that was tracked in a previous session", () => {
|
||||
it.skip("should not track a failure for an event that was tracked in a previous session", async () => {
|
||||
// This test uses localStorage, clear it beforehand
|
||||
localStorage.clear();
|
||||
|
||||
const decryptedEvent = createFailedDecryptionEvent();
|
||||
const decryptedEvent = await createFailedDecryptionEvent();
|
||||
|
||||
let count = 0;
|
||||
const tracker = new DecryptionFailureTracker(
|
||||
|
@ -292,16 +290,16 @@ describe("DecryptionFailureTracker", function () {
|
|||
expect(count).toBe(1, count + " failures tracked, should only track a single failure per event");
|
||||
});
|
||||
|
||||
it("should count different error codes separately for multiple failures with different error codes", () => {
|
||||
it("should count different error codes separately for multiple failures with different error codes", async () => {
|
||||
const counts = {};
|
||||
const tracker = new DecryptionFailureTracker(
|
||||
(total, errorCode) => (counts[errorCode] = (counts[errorCode] || 0) + total),
|
||||
(error) => (error === "UnknownError" ? "UnknownError" : "OlmKeysNotSentError"),
|
||||
);
|
||||
|
||||
const decryptedEvent1 = createFailedDecryptionEvent();
|
||||
const decryptedEvent2 = createFailedDecryptionEvent();
|
||||
const decryptedEvent3 = createFailedDecryptionEvent();
|
||||
const decryptedEvent1 = await createFailedDecryptionEvent();
|
||||
const decryptedEvent2 = await createFailedDecryptionEvent();
|
||||
const decryptedEvent3 = await createFailedDecryptionEvent();
|
||||
|
||||
const error1 = new MockDecryptionError("UnknownError");
|
||||
const error2 = new MockDecryptionError("OlmKeysNotSentError");
|
||||
|
@ -325,16 +323,16 @@ describe("DecryptionFailureTracker", function () {
|
|||
expect(counts["OlmKeysNotSentError"]).toBe(2, "should track two OlmKeysNotSentError");
|
||||
});
|
||||
|
||||
it("should aggregate error codes correctly", () => {
|
||||
it("should aggregate error codes correctly", async () => {
|
||||
const counts = {};
|
||||
const tracker = new DecryptionFailureTracker(
|
||||
(total, errorCode) => (counts[errorCode] = (counts[errorCode] || 0) + total),
|
||||
(errorCode) => "OlmUnspecifiedError",
|
||||
);
|
||||
|
||||
const decryptedEvent1 = createFailedDecryptionEvent();
|
||||
const decryptedEvent2 = createFailedDecryptionEvent();
|
||||
const decryptedEvent3 = createFailedDecryptionEvent();
|
||||
const decryptedEvent1 = await createFailedDecryptionEvent();
|
||||
const decryptedEvent2 = await createFailedDecryptionEvent();
|
||||
const decryptedEvent3 = await createFailedDecryptionEvent();
|
||||
|
||||
const error1 = new MockDecryptionError("ERROR_CODE_1");
|
||||
const error2 = new MockDecryptionError("ERROR_CODE_2");
|
||||
|
@ -359,14 +357,14 @@ describe("DecryptionFailureTracker", function () {
|
|||
);
|
||||
});
|
||||
|
||||
it("should remap error codes correctly", () => {
|
||||
it("should remap error codes correctly", async () => {
|
||||
const counts = {};
|
||||
const tracker = new DecryptionFailureTracker(
|
||||
(total, errorCode) => (counts[errorCode] = (counts[errorCode] || 0) + total),
|
||||
(errorCode) => Array.from(errorCode).reverse().join(""),
|
||||
);
|
||||
|
||||
const decryptedEvent = createFailedDecryptionEvent();
|
||||
const decryptedEvent = await createFailedDecryptionEvent();
|
||||
|
||||
const error = new MockDecryptionError("ERROR_CODE_1");
|
||||
|
||||
|
|
|
@ -30,20 +30,13 @@ import {
|
|||
} from "matrix-js-sdk/src/matrix";
|
||||
import { EventEncryptionInfo, EventShieldColour, EventShieldReason } from "matrix-js-sdk/src/crypto-api";
|
||||
import { TooltipProvider } from "@vector-im/compound-web";
|
||||
import { mkEncryptedMatrixEvent } from "matrix-js-sdk/src/testing";
|
||||
|
||||
import EventTile, { EventTileProps } from "../../../../src/components/views/rooms/EventTile";
|
||||
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
||||
import RoomContext, { TimelineRenderingType } from "../../../../src/contexts/RoomContext";
|
||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||
import {
|
||||
filterConsole,
|
||||
flushPromises,
|
||||
getRoomContext,
|
||||
mkEncryptedEvent,
|
||||
mkEvent,
|
||||
mkMessage,
|
||||
stubClient,
|
||||
} from "../../../test-utils";
|
||||
import { filterConsole, flushPromises, getRoomContext, mkEvent, mkMessage, stubClient } from "../../../test-utils";
|
||||
import { mkThread } from "../../../test-utils/threads";
|
||||
import DMRoomMap from "../../../../src/utils/DMRoomMap";
|
||||
import dis from "../../../../src/dispatcher/dispatcher";
|
||||
|
@ -225,11 +218,11 @@ describe("EventTile", () => {
|
|||
});
|
||||
|
||||
it("shows a warning for an event from an unverified device", async () => {
|
||||
mxEvent = await mkEncryptedEvent({
|
||||
mxEvent = await mkEncryptedMatrixEvent({
|
||||
plainContent: { msgtype: "m.text", body: "msg1" },
|
||||
plainType: "m.room.message",
|
||||
user: "@alice:example.org",
|
||||
room: room.roomId,
|
||||
sender: "@alice:example.org",
|
||||
roomId: room.roomId,
|
||||
});
|
||||
eventToEncryptionInfoMap.set(mxEvent.getId()!, {
|
||||
shieldColour: EventShieldColour.RED,
|
||||
|
@ -250,11 +243,11 @@ describe("EventTile", () => {
|
|||
});
|
||||
|
||||
it("shows no shield for a verified event", async () => {
|
||||
mxEvent = await mkEncryptedEvent({
|
||||
mxEvent = await mkEncryptedMatrixEvent({
|
||||
plainContent: { msgtype: "m.text", body: "msg1" },
|
||||
plainType: "m.room.message",
|
||||
user: "@alice:example.org",
|
||||
room: room.roomId,
|
||||
sender: "@alice:example.org",
|
||||
roomId: room.roomId,
|
||||
});
|
||||
eventToEncryptionInfoMap.set(mxEvent.getId()!, {
|
||||
shieldColour: EventShieldColour.NONE,
|
||||
|
@ -279,11 +272,11 @@ describe("EventTile", () => {
|
|||
[EventShieldReason.AUTHENTICITY_NOT_GUARANTEED, "can't be guaranteed"],
|
||||
[EventShieldReason.MISMATCHED_SENDER_KEY, "Encrypted by an unverified session"],
|
||||
])("shows the correct reason code for %i (%s)", async (reasonCode: EventShieldReason, expectedText: string) => {
|
||||
mxEvent = await mkEncryptedEvent({
|
||||
mxEvent = await mkEncryptedMatrixEvent({
|
||||
plainContent: { msgtype: "m.text", body: "msg1" },
|
||||
plainType: "m.room.message",
|
||||
user: "@alice:example.org",
|
||||
room: room.roomId,
|
||||
sender: "@alice:example.org",
|
||||
roomId: room.roomId,
|
||||
});
|
||||
eventToEncryptionInfoMap.set(mxEvent.getId()!, {
|
||||
shieldColour: EventShieldColour.GREY,
|
||||
|
@ -337,11 +330,11 @@ describe("EventTile", () => {
|
|||
|
||||
it("should update the warning when the event is edited", async () => {
|
||||
// we start out with an event from the trusted device
|
||||
mxEvent = await mkEncryptedEvent({
|
||||
mxEvent = await mkEncryptedMatrixEvent({
|
||||
plainContent: { msgtype: "m.text", body: "msg1" },
|
||||
plainType: "m.room.message",
|
||||
user: "@alice:example.org",
|
||||
room: room.roomId,
|
||||
sender: "@alice:example.org",
|
||||
roomId: room.roomId,
|
||||
});
|
||||
eventToEncryptionInfoMap.set(mxEvent.getId()!, {
|
||||
shieldColour: EventShieldColour.NONE,
|
||||
|
@ -360,11 +353,11 @@ describe("EventTile", () => {
|
|||
expect(container.getElementsByClassName("mx_EventTile_e2eIcon")).toHaveLength(0);
|
||||
|
||||
// then we replace the event with one from the unverified device
|
||||
const replacementEvent = await mkEncryptedEvent({
|
||||
const replacementEvent = await mkEncryptedMatrixEvent({
|
||||
plainContent: { msgtype: "m.text", body: "msg1" },
|
||||
plainType: "m.room.message",
|
||||
user: "@alice:example.org",
|
||||
room: room.roomId,
|
||||
sender: "@alice:example.org",
|
||||
roomId: room.roomId,
|
||||
});
|
||||
eventToEncryptionInfoMap.set(replacementEvent.getId()!, {
|
||||
shieldColour: EventShieldColour.RED,
|
||||
|
@ -388,11 +381,11 @@ describe("EventTile", () => {
|
|||
jest.spyOn(client, "isRoomEncrypted").mockReturnValue(true);
|
||||
|
||||
// we start out with an event from the trusted device
|
||||
mxEvent = await mkEncryptedEvent({
|
||||
mxEvent = await mkEncryptedMatrixEvent({
|
||||
plainContent: { msgtype: "m.text", body: "msg1" },
|
||||
plainType: "m.room.message",
|
||||
user: "@alice:example.org",
|
||||
room: room.roomId,
|
||||
sender: "@alice:example.org",
|
||||
roomId: room.roomId,
|
||||
});
|
||||
|
||||
eventToEncryptionInfoMap.set(mxEvent.getId()!, {
|
||||
|
|
|
@ -36,7 +36,6 @@ import {
|
|||
IPushRules,
|
||||
RelationType,
|
||||
JoinRule,
|
||||
IEventDecryptionResult,
|
||||
OidcClientConfig,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
|
@ -404,50 +403,6 @@ export function mkEvent(opts: MakeEventProps): MatrixEvent {
|
|||
return mxEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an m.room.encrypted event
|
||||
*
|
||||
* @param opts - Values for the event
|
||||
* @param opts.room - The ID of the room for the event
|
||||
* @param opts.user - The sender of the event
|
||||
* @param opts.plainType - The type the event will have, once it has been decrypted
|
||||
* @param opts.plainContent - The content the event will have, once it has been decrypted
|
||||
*/
|
||||
export async function mkEncryptedEvent(opts: {
|
||||
room: Room["roomId"];
|
||||
user: User["userId"];
|
||||
plainType: string;
|
||||
plainContent: IContent;
|
||||
}): Promise<MatrixEvent> {
|
||||
// we construct an event which has been decrypted by stubbing out CryptoBackend.decryptEvent and then
|
||||
// calling MatrixEvent.attemptDecryption.
|
||||
|
||||
const mxEvent = mkEvent({
|
||||
type: "m.room.encrypted",
|
||||
room: opts.room,
|
||||
user: opts.user,
|
||||
event: true,
|
||||
content: {},
|
||||
});
|
||||
|
||||
const decryptionResult: IEventDecryptionResult = {
|
||||
claimedEd25519Key: "",
|
||||
clearEvent: {
|
||||
type: opts.plainType,
|
||||
content: opts.plainContent,
|
||||
},
|
||||
forwardingCurve25519KeyChain: [],
|
||||
senderCurve25519Key: "",
|
||||
untrusted: false,
|
||||
};
|
||||
|
||||
const mockCrypto = {
|
||||
decryptEvent: async (_ev): Promise<IEventDecryptionResult> => decryptionResult,
|
||||
} as Parameters<MatrixEvent["attemptDecryption"]>[0];
|
||||
await mxEvent.attemptDecryption(mockCrypto);
|
||||
return mxEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an m.room.member event.
|
||||
* @param {Object} opts Values for the membership.
|
||||
|
|
Loading…
Reference in a new issue