From 87d44a7792a9dcccdce89dea49c3c6898fe8df03 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 6 Feb 2025 14:02:14 +0100 Subject: [PATCH] Test for the view model --- test/test-utils/test-utils.ts | 2 + .../KeyStoragePanelViewModel-test.ts | 113 ++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 test/unit-tests/components/viewmodels/settings/encryption/KeyStoragePanelViewModel-test.ts diff --git a/test/test-utils/test-utils.ts b/test/test-utils/test-utils.ts index f752daf530..183aab3dcf 100644 --- a/test/test-utils/test-utils.ts +++ b/test/test-utils/test-utils.ts @@ -154,6 +154,7 @@ export function createTestClient(): MatrixClient { resetEncryption: jest.fn(), getSessionBackupPrivateKey: jest.fn().mockResolvedValue(null), isSecretStorageReady: jest.fn().mockResolvedValue(false), + deleteKeyBackupVersion: jest.fn(), }), getPushActionsForEvent: jest.fn(), @@ -192,6 +193,7 @@ export function createTestClient(): MatrixClient { }), mxcUrlToHttp: jest.fn().mockImplementation((mxc: string) => `http://this.is.a.url/${mxc.substring(6)}`), setAccountData: jest.fn(), + deleteAccountData: jest.fn(), setRoomAccountData: jest.fn(), setRoomTopic: jest.fn(), setRoomReadMarkers: jest.fn().mockResolvedValue({}), diff --git a/test/unit-tests/components/viewmodels/settings/encryption/KeyStoragePanelViewModel-test.ts b/test/unit-tests/components/viewmodels/settings/encryption/KeyStoragePanelViewModel-test.ts new file mode 100644 index 0000000000..03907671f7 --- /dev/null +++ b/test/unit-tests/components/viewmodels/settings/encryption/KeyStoragePanelViewModel-test.ts @@ -0,0 +1,113 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import { renderHook } from "jest-matrix-react"; +import { act } from "react"; +import { mocked } from "jest-mock"; +import { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; + +import type { KeyBackupCheck, KeyBackupInfo } from "matrix-js-sdk/src/crypto-api"; +import { useKeyStoragePanelViewModel } from "../../../../../../src/components/viewmodels/settings/encryption/KeyStoragePanelViewModel"; +import { createTestClient, withClientContextRenderOptions } from "../../../../../test-utils"; + +describe("KeyStoragePanelViewModel", () => { + let matrixClient: MatrixClient; + + beforeEach(() => { + matrixClient = createTestClient(); + }); + + it("should update the pending value immediately", async () => { + const { result } = renderHook( + () => useKeyStoragePanelViewModel(), + withClientContextRenderOptions(matrixClient), + ); + act(() => { + result.current.setEnabled(true); + }); + expect(result.current.isEnabled).toBe(true); + expect(result.current.busy).toBe(true); + }); + + it("should call resetKeyBackup if there is no backup currently", async () => { + mocked(matrixClient.getCrypto()!.checkKeyBackupAndEnable).mockResolvedValue(null); + + const { result } = renderHook( + () => useKeyStoragePanelViewModel(), + withClientContextRenderOptions(matrixClient), + ); + + await result.current.setEnabled(true); + expect(mocked(matrixClient.getCrypto()!.resetKeyBackup)).toHaveBeenCalled(); + }); + + it("should not call resetKeyBackup if there is a backup currently", async () => { + mocked(matrixClient.getCrypto()!.checkKeyBackupAndEnable).mockResolvedValue({} as KeyBackupCheck); + + const { result } = renderHook( + () => useKeyStoragePanelViewModel(), + withClientContextRenderOptions(matrixClient), + ); + + await result.current.setEnabled(true); + expect(mocked(matrixClient.getCrypto()!.resetKeyBackup)).not.toHaveBeenCalled(); + }); + + it("should set account data flag when enabling", async () => { + mocked(matrixClient.getCrypto()!.checkKeyBackupAndEnable).mockResolvedValue(null); + + const { result } = renderHook( + () => useKeyStoragePanelViewModel(), + withClientContextRenderOptions(matrixClient), + ); + + await result.current.setEnabled(true); + expect(mocked(matrixClient.setAccountData)).toHaveBeenCalledWith("m.org.matrix.custom.backup_disabled", { + disabled: false, + }); + }); + + it("should delete backup when disabling", async () => { + mocked(matrixClient.getCrypto()!.checkKeyBackupAndEnable).mockResolvedValue({} as KeyBackupCheck); + mocked(matrixClient.getCrypto()!.getKeyBackupInfo).mockResolvedValue({ version: "99" } as KeyBackupInfo); + + const { result } = renderHook( + () => useKeyStoragePanelViewModel(), + withClientContextRenderOptions(matrixClient), + ); + + await result.current.setEnabled(false); + + expect(mocked(matrixClient.getCrypto()!.deleteKeyBackupVersion)).toHaveBeenCalled(); + }); + + it("should delete data stored in 4s when disabling", async () => { + mocked(matrixClient.getCrypto()!.checkKeyBackupAndEnable).mockResolvedValue({} as KeyBackupCheck); + mocked(matrixClient.getCrypto()!.getKeyBackupInfo).mockResolvedValue({ version: "99" } as KeyBackupInfo); + mocked(matrixClient.getAccountData).mockImplementation((k): MatrixEvent | undefined => { + if (k === "m.secret_storage.default_key") { + return new MatrixEvent({ content: { key: "thekey" } }); + } + + return undefined; + }); + + const { result } = renderHook( + () => useKeyStoragePanelViewModel(), + withClientContextRenderOptions(matrixClient), + ); + + await result.current.setEnabled(false); + + expect(mocked(matrixClient.deleteAccountData)).toHaveBeenCalledWith("m.cross_signing.master"); + expect(mocked(matrixClient.deleteAccountData)).toHaveBeenCalledWith("m.cross_signing.self_signing"); + expect(mocked(matrixClient.deleteAccountData)).toHaveBeenCalledWith("m.cross_signing.user_signing"); + expect(mocked(matrixClient.deleteAccountData)).toHaveBeenCalledWith("m.megolm_backup.v1"); + expect(mocked(matrixClient.deleteAccountData)).toHaveBeenCalledWith("m.secret_storage.default_key"); + expect(mocked(matrixClient.deleteAccountData)).toHaveBeenCalledWith("m.secret_storage.key.thekey"); + }); +});