Add key storage toggle to Encryption settings (#29310)
* Add key storage toggle to Encryption settings
* Keys in the acceptable order
* Fix some tests
* Fix import
* Fix toast showing condition
* Fix import order
* Fix playwright tests
* Fix bits lost in merge
* Add key storage delete confirm screen
* Fix hardcoded Element string
* Fix type imports
* Fix tests
* Tests for key storage delete panel
* Fix test
* Type import
* Test for the view model
* Fix type import
* Actually fix type imports
* Test updating
* Add playwright test & clarify slightly confusing comment
* Show the advnced section whatever the state of key storage
* Update screenshots
* Copy css to its own file
* Add missing doc & merge loading states
* Add tsdoc & loading alt text to spinner
* Turn comments into proper tsdoc
* Switch to TypedEventEmitter and remove unnecessary loading state
* Add screenshot
* Use higher level interface
* Merge the two hooks in EncryptionUserSettingsTab
* Remove unused import
* Don't check key backup enabled state separately
as we don't need it for all the screens
* Update snapshot
* Use fixed recovery key function
* Amalgamate duplicated CSS files
* Have "key storage disabled" as a separate state
* Update snapshot
* Fix... bad merge?
* Add backup enabled mock to more tests
* More snapshots
* Use defer util
* Update to use EncryptionCardButtons
* Update snapshots
* Use EncryptionCardEmphasisedContent
* Update snapshots
* Update snapshot
* Try screenshot from CI playwright
* Try playwright screenshots again
* More screenshots
* Rename to match files
* Test that 4S secrets are deleted
* Make description clearer
* Fix typo & move related states together
* Add comment
* More comments
* Fix hook docs
* restoreAllMocks
* Update snapshot
because pulling in upstream has caused IDs to shift
* Switch icon
as apparenty the error icon has changed
* Update snapshot
* Missing copyright
* Re-order states
and also sort out indenting
* Remove phantom space
* Clarify 'button'
* Clarify docs more
* Explain thinking behind updating
* Switch to getActiveBackupVersion
which checks that key backup is happining on this device, which is
consistent with EX.
* Add use of Key Storage Panel
Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
* Change key storage panel to be consistent
ie. using getActiveBackupVersion(), and add comment
* Add tsdoc
Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
* Use BACKUP_DISABLED_ACCOUNT_DATA_KEY in more places
* Expand doc
Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
* Undo random yarn lock change
* Use aggregate method for disabling key storage
in https://github.com/matrix-org/matrix-js-sdk/pull/4742
* Fix tests
* Use key backup status event to update
* Comment formatting
Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
* Fix comment & put check inside if statement
* Add comment
* Prettier
* Fix comment
* Update snapshot
Which has gained nowrap due to 917d53a56f
---------
Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
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 type { MatrixClient } 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();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
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 key storage 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()!.disableKeyStorage)).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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 React from "react";
|
||||
import { render, screen, waitFor } from "jest-matrix-react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { mocked } from "jest-mock";
|
||||
import { defer } from "matrix-js-sdk/src/utils";
|
||||
|
||||
import type { MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { createTestClient, withClientContextRenderOptions } from "../../../../../test-utils";
|
||||
import { DeleteKeyStoragePanel } from "../../../../../../src/components/views/settings/encryption/DeleteKeyStoragePanel";
|
||||
import { useKeyStoragePanelViewModel } from "../../../../../../src/components/viewmodels/settings/encryption/KeyStoragePanelViewModel";
|
||||
|
||||
jest.mock("../../../../../../src/components/viewmodels/settings/encryption/KeyStoragePanelViewModel", () => ({
|
||||
useKeyStoragePanelViewModel: jest
|
||||
.fn()
|
||||
.mockReturnValue({ setEnabled: jest.fn(), isEnabled: true, loading: false, busy: false }),
|
||||
}));
|
||||
|
||||
describe("<DeleteKeyStoragePanel />", () => {
|
||||
let matrixClient: MatrixClient;
|
||||
|
||||
beforeEach(() => {
|
||||
matrixClient = createTestClient();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("should match snapshot", async () => {
|
||||
const { asFragment } = render(
|
||||
<DeleteKeyStoragePanel onFinish={() => {}} />,
|
||||
withClientContextRenderOptions(matrixClient),
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should call onFinished when cancel pressed", async () => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
const onFinish = jest.fn();
|
||||
render(<DeleteKeyStoragePanel onFinish={onFinish} />, withClientContextRenderOptions(matrixClient));
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Cancel" }));
|
||||
expect(onFinish).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should call disable key storage when confirm pressed", async () => {
|
||||
const setEnabled = jest.fn();
|
||||
|
||||
mocked(useKeyStoragePanelViewModel).mockReturnValue({
|
||||
setEnabled,
|
||||
isEnabled: true,
|
||||
loading: false,
|
||||
busy: false,
|
||||
});
|
||||
|
||||
const user = userEvent.setup();
|
||||
|
||||
const onFinish = jest.fn();
|
||||
render(<DeleteKeyStoragePanel onFinish={onFinish} />, withClientContextRenderOptions(matrixClient));
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Delete key storage" }));
|
||||
|
||||
expect(setEnabled).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
it("should wait with button disabled while setEnabled runs", async () => {
|
||||
const setEnabledDefer = defer();
|
||||
|
||||
mocked(useKeyStoragePanelViewModel).mockReturnValue({
|
||||
setEnabled: jest.fn().mockReturnValue(setEnabledDefer.promise),
|
||||
isEnabled: true,
|
||||
loading: false,
|
||||
busy: false,
|
||||
});
|
||||
|
||||
const user = userEvent.setup();
|
||||
|
||||
const onFinish = jest.fn();
|
||||
render(<DeleteKeyStoragePanel onFinish={onFinish} />, withClientContextRenderOptions(matrixClient));
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Delete key storage" }));
|
||||
|
||||
expect(onFinish).not.toHaveBeenCalled();
|
||||
expect(screen.getByRole("button", { name: "Delete key storage" })).toHaveAttribute("aria-disabled", "true");
|
||||
setEnabledDefer.resolve();
|
||||
await waitFor(() => expect(onFinish).toHaveBeenCalled());
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,156 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<DeleteKeyStoragePanel /> should match snapshot 1`] = `
|
||||
<DocumentFragment>
|
||||
<nav
|
||||
class="_breadcrumb_1xygz_8"
|
||||
>
|
||||
<button
|
||||
aria-label="Back"
|
||||
class="_icon-button_m2erp_8 _subtle-bg_m2erp_29"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 28px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_zr2a0_17"
|
||||
style="--cpd-icon-button-size: 100%;"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="m13.3 17.3-4.6-4.6a.9.9 0 0 1-.213-.325A1.1 1.1 0 0 1 8.425 12q0-.2.062-.375A.9.9 0 0 1 8.7 11.3l4.6-4.6a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7L10.8 12l3.9 3.9a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7.95.95 0 0 1-.7.275.95.95 0 0 1-.7-.275"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
<ol
|
||||
class="_pages_1xygz_17"
|
||||
>
|
||||
<li>
|
||||
<a
|
||||
class="_link_1v5rz_8"
|
||||
data-kind="primary"
|
||||
data-size="small"
|
||||
rel="noreferrer noopener"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Encryption
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<span
|
||||
aria-current="page"
|
||||
class="_last-page_1xygz_30"
|
||||
>
|
||||
Delete key storage
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<div
|
||||
class="mx_EncryptionCard"
|
||||
>
|
||||
<div
|
||||
class="mx_EncryptionCard_header"
|
||||
>
|
||||
<div
|
||||
class="_content_o77nw_8 _destructive_o77nw_34"
|
||||
data-size="large"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 17q.424 0 .713-.288A.97.97 0 0 0 13 16a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 15a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 16q0 .424.287.712.288.288.713.288m0-4q.424 0 .713-.287A.97.97 0 0 0 13 12V8a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 7a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 8v4q0 .424.287.713.288.287.713.287m0 9a9.7 9.7 0 0 1-3.9-.788 10.1 10.1 0 0 1-3.175-2.137q-1.35-1.35-2.137-3.175A9.7 9.7 0 0 1 2 12q0-2.075.788-3.9a10.1 10.1 0 0 1 2.137-3.175q1.35-1.35 3.175-2.137A9.7 9.7 0 0 1 12 2q2.075 0 3.9.788a10.1 10.1 0 0 1 3.175 2.137q1.35 1.35 2.137 3.175A9.7 9.7 0 0 1 22 12a9.7 9.7 0 0 1-.788 3.9 10.1 10.1 0 0 1-2.137 3.175q-1.35 1.35-3.175 2.137A9.7 9.7 0 0 1 12 22"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h2
|
||||
class="_typography_6v6n8_153 _font-heading-sm-semibold_6v6n8_93"
|
||||
>
|
||||
Are you sure you want to turn off key storage and delete it?
|
||||
</h2>
|
||||
</div>
|
||||
<div
|
||||
class="mx_Flex mx_EncryptionCard_emphasisedContent"
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: column; --mx-flex-align: normal; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-3x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
Deleting key storage will remove your cryptographic identity and message keys from the server and turn off the following security features:
|
||||
<ul
|
||||
class="_visual-list_15wzx_8"
|
||||
>
|
||||
<li
|
||||
class="_visual-list-item_1ma3e_8"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="_visual-list-item-icon_1ma3e_17 _visual-list-item-icon-destructive_1ma3e_26"
|
||||
fill="currentColor"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6.293 6.293a1 1 0 0 1 1.414 0L12 10.586l4.293-4.293a1 1 0 1 1 1.414 1.414L13.414 12l4.293 4.293a1 1 0 0 1-1.414 1.414L12 13.414l-4.293 4.293a1 1 0 0 1-1.414-1.414L10.586 12 6.293 7.707a1 1 0 0 1 0-1.414"
|
||||
/>
|
||||
</svg>
|
||||
You will not have encrypted message history on new devices
|
||||
</li>
|
||||
<li
|
||||
class="_visual-list-item_1ma3e_8"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="_visual-list-item-icon_1ma3e_17 _visual-list-item-icon-destructive_1ma3e_26"
|
||||
fill="currentColor"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6.293 6.293a1 1 0 0 1 1.414 0L12 10.586l4.293-4.293a1 1 0 1 1 1.414 1.414L13.414 12l4.293 4.293a1 1 0 0 1-1.414 1.414L12 13.414l-4.293 4.293a1 1 0 0 1-1.414-1.414L10.586 12 6.293 7.707a1 1 0 0 1 0-1.414"
|
||||
/>
|
||||
</svg>
|
||||
You will lose access to your encrypted messages if you are signed out of Element everywhere
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
class="mx_EncryptionCard_buttons"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
class="_button_vczzf_8 _destructive_vczzf_107"
|
||||
data-kind="primary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Delete key storage
|
||||
</button>
|
||||
<button
|
||||
class="_button_vczzf_8"
|
||||
data-kind="tertiary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
@@ -6,10 +6,11 @@
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { render, screen } from "jest-matrix-react";
|
||||
import { act, render, screen } from "jest-matrix-react";
|
||||
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { waitFor } from "@testing-library/dom";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { CryptoEvent } from "matrix-js-sdk/src/crypto-api";
|
||||
|
||||
import {
|
||||
EncryptionUserSettingsTab,
|
||||
@@ -66,12 +67,21 @@ describe("<EncryptionUserSettingsTab />", () => {
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should display the recovery panel when the encryption is set up", async () => {
|
||||
it("should display the recovery panel when key storage is enabled", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1");
|
||||
renderComponent();
|
||||
await waitFor(() => expect(screen.getByText("Recovery")).toBeInTheDocument());
|
||||
});
|
||||
|
||||
it("should not display the recovery panel when key storage is not enabled", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getKeyBackupInfo").mockResolvedValue(null);
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue(null);
|
||||
renderComponent();
|
||||
await expect(screen.queryByText("Recovery")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should display the recovery out of sync panel when secrets are not cached", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1");
|
||||
// Secrets are not cached
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getCrossSigningStatus").mockResolvedValue({
|
||||
privateKeysInSecretStorage: true,
|
||||
@@ -96,6 +106,7 @@ describe("<EncryptionUserSettingsTab />", () => {
|
||||
});
|
||||
|
||||
it("should display the change recovery key panel when the user clicks on the change recovery button", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1");
|
||||
const user = userEvent.setup();
|
||||
|
||||
const { asFragment } = renderComponent();
|
||||
@@ -109,6 +120,7 @@ describe("<EncryptionUserSettingsTab />", () => {
|
||||
});
|
||||
|
||||
it("should display the set up recovery key when the user clicks on the set up recovery key button", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1");
|
||||
jest.spyOn(matrixClient.secretStorage, "getDefaultKeyId").mockResolvedValue(null);
|
||||
const user = userEvent.setup();
|
||||
|
||||
@@ -123,6 +135,8 @@ describe("<EncryptionUserSettingsTab />", () => {
|
||||
});
|
||||
|
||||
it("should display the reset identity panel when the user clicks on the reset cryptographic identity panel", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1");
|
||||
|
||||
const user = userEvent.setup();
|
||||
|
||||
const { asFragment } = renderComponent();
|
||||
@@ -137,17 +151,41 @@ describe("<EncryptionUserSettingsTab />", () => {
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should enter reset flow when showResetIdentity is set", () => {
|
||||
it("should enter reset flow when showResetIdentity is set", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1");
|
||||
|
||||
renderComponent({ initialState: "reset_identity_forgot" });
|
||||
|
||||
expect(
|
||||
screen.getByRole("heading", { name: "Forgot your recovery key? You’ll need to reset your identity." }),
|
||||
await expect(
|
||||
await screen.findByRole("heading", {
|
||||
name: "Forgot your recovery key? You’ll need to reset your identity.",
|
||||
}),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
it("should update when key backup status event is fired", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1");
|
||||
|
||||
renderComponent();
|
||||
|
||||
await expect(await screen.findByRole("heading", { name: "Recovery" })).toBeVisible();
|
||||
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue(null);
|
||||
|
||||
act(() => {
|
||||
matrixClient.emit(CryptoEvent.KeyBackupStatus, false);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByRole("heading", { name: "Recovery" })).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
it("should re-check the encryption state and displays the correct panel when the user clicks cancel the reset identity flow", async () => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1");
|
||||
|
||||
// Secrets are not cached
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getCrossSigningStatus").mockResolvedValue({
|
||||
privateKeysInSecretStorage: true,
|
||||
|
||||
Reference in New Issue
Block a user