Fix #30439: "Forgot recovery key" should go to "reset" (#30771)

* Fix #30439: "Forgot recovery key" should go to "reset"

* Wrap showToast in act() to ensure React render is finished

* Remove duplicated code
This commit is contained in:
Andy Balaam
2025-09-16 14:29:45 +01:00
committed by GitHub
parent 81fc054b8b
commit c9f375a02b
2 changed files with 16 additions and 25 deletions

View File

@@ -197,7 +197,8 @@ export const showToast = (kind: Kind): void => {
deviceListener.dismissEncryptionSetup(); deviceListener.dismissEncryptionSetup();
break; break;
} }
case Kind.KEY_STORAGE_OUT_OF_SYNC: { case Kind.KEY_STORAGE_OUT_OF_SYNC:
case Kind.KEY_STORAGE_OUT_OF_SYNC_STORE: {
// Open the user settings dialog to the encryption tab and start the flow to reset encryption // Open the user settings dialog to the encryption tab and start the flow to reset encryption
const payload: OpenToTabPayload = { const payload: OpenToTabPayload = {
action: Action.ViewUserSettings, action: Action.ViewUserSettings,
@@ -207,16 +208,6 @@ export const showToast = (kind: Kind): void => {
defaultDispatcher.dispatch(payload); defaultDispatcher.dispatch(payload);
break; break;
} }
case Kind.KEY_STORAGE_OUT_OF_SYNC_STORE: {
// Open the user settings dialog to the encryption tab and start the flow to reset 4S
const payload: OpenToTabPayload = {
action: Action.ViewUserSettings,
initialTabId: UserTab.Encryption,
props: { initialEncryptionState: "change_recovery_key" },
};
defaultDispatcher.dispatch(payload);
break;
}
case Kind.TURN_ON_KEY_STORAGE: { case Kind.TURN_ON_KEY_STORAGE: {
// The user clicked "Dismiss": offer them "Are you sure?" // The user clicked "Dismiss": offer them "Are you sure?"
const modal = Modal.createDialog( const modal = Modal.createDialog(

View File

@@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details.
*/ */
import React from "react"; import React from "react";
import { render, screen } from "jest-matrix-react"; import { act, render, screen } from "jest-matrix-react";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
import * as SecurityManager from "../../../src/SecurityManager"; import * as SecurityManager from "../../../src/SecurityManager";
@@ -31,7 +31,7 @@ describe("SetupEncryptionToast", () => {
describe("Set up recovery", () => { describe("Set up recovery", () => {
it("should render the toast", async () => { it("should render the toast", async () => {
showToast(Kind.SET_UP_RECOVERY); act(() => showToast(Kind.SET_UP_RECOVERY));
expect(await screen.findByRole("heading", { name: "Set up recovery" })).toBeInTheDocument(); expect(await screen.findByRole("heading", { name: "Set up recovery" })).toBeInTheDocument();
}); });
@@ -40,7 +40,7 @@ describe("SetupEncryptionToast", () => {
jest.spyOn(DeviceListener.sharedInstance(), "recordRecoveryDisabled"); jest.spyOn(DeviceListener.sharedInstance(), "recordRecoveryDisabled");
jest.spyOn(DeviceListener.sharedInstance(), "dismissEncryptionSetup"); jest.spyOn(DeviceListener.sharedInstance(), "dismissEncryptionSetup");
showToast(Kind.SET_UP_RECOVERY); act(() => showToast(Kind.SET_UP_RECOVERY));
const user = userEvent.setup(); const user = userEvent.setup();
await user.click(await screen.findByRole("button", { name: "Dismiss" })); await user.click(await screen.findByRole("button", { name: "Dismiss" }));
@@ -52,13 +52,13 @@ describe("SetupEncryptionToast", () => {
describe("Key storage out of sync (retrieve secrets)", () => { describe("Key storage out of sync (retrieve secrets)", () => {
it("should render the toast", async () => { it("should render the toast", async () => {
showToast(Kind.KEY_STORAGE_OUT_OF_SYNC); act(() => showToast(Kind.KEY_STORAGE_OUT_OF_SYNC));
await expect(screen.findByText("Your key storage is out of sync.")).resolves.toBeInTheDocument(); await expect(screen.findByText("Your key storage is out of sync.")).resolves.toBeInTheDocument();
}); });
it("should open settings to the reset flow when 'forgot recovery key' clicked", async () => { it("should open settings to the reset flow when 'forgot recovery key' clicked", async () => {
showToast(Kind.KEY_STORAGE_OUT_OF_SYNC); act(() => showToast(Kind.KEY_STORAGE_OUT_OF_SYNC));
const user = userEvent.setup(); const user = userEvent.setup();
await user.click(await screen.findByText("Forgot recovery key?")); await user.click(await screen.findByText("Forgot recovery key?"));
@@ -75,7 +75,7 @@ describe("SetupEncryptionToast", () => {
throw new Error("Something went wrong while recovering!"); throw new Error("Something went wrong while recovering!");
}); });
showToast(Kind.KEY_STORAGE_OUT_OF_SYNC); act(() => showToast(Kind.KEY_STORAGE_OUT_OF_SYNC));
const user = userEvent.setup(); const user = userEvent.setup();
await user.click(await screen.findByText("Enter recovery key")); await user.click(await screen.findByText("Enter recovery key"));
@@ -88,15 +88,15 @@ describe("SetupEncryptionToast", () => {
}); });
}); });
describe("Key storage out of sync (store secrets)", () => { describe("Key storage out of sync (secrets are missing from 4S)", () => {
it("should render the toast", async () => { it("should render the toast", async () => {
showToast(Kind.KEY_STORAGE_OUT_OF_SYNC_STORE); act(() => showToast(Kind.KEY_STORAGE_OUT_OF_SYNC_STORE));
await expect(screen.findByText("Your key storage is out of sync.")).resolves.toBeInTheDocument(); await expect(screen.findByText("Your key storage is out of sync.")).resolves.toBeInTheDocument();
}); });
it("should open settings to the reset flow when 'forgot recovery key' clicked", async () => { it("should open settings to the reset flow when 'forgot recovery key' clicked", async () => {
showToast(Kind.KEY_STORAGE_OUT_OF_SYNC_STORE); act(() => showToast(Kind.KEY_STORAGE_OUT_OF_SYNC_STORE));
const user = userEvent.setup(); const user = userEvent.setup();
await user.click(await screen.findByText("Forgot recovery key?")); await user.click(await screen.findByText("Forgot recovery key?"));
@@ -104,7 +104,7 @@ describe("SetupEncryptionToast", () => {
expect(dis.dispatch).toHaveBeenCalledWith({ expect(dis.dispatch).toHaveBeenCalledWith({
action: "view_user_settings", action: "view_user_settings",
initialTabId: "USER_ENCRYPTION_TAB", initialTabId: "USER_ENCRYPTION_TAB",
props: { initialEncryptionState: "change_recovery_key" }, props: { initialEncryptionState: "reset_identity_forgot" },
}); });
}); });
@@ -113,7 +113,7 @@ describe("SetupEncryptionToast", () => {
throw new Error("Something went wrong while recovering!"); throw new Error("Something went wrong while recovering!");
}); });
showToast(Kind.KEY_STORAGE_OUT_OF_SYNC_STORE); act(() => showToast(Kind.KEY_STORAGE_OUT_OF_SYNC_STORE));
const user = userEvent.setup(); const user = userEvent.setup();
await user.click(await screen.findByText("Enter recovery key")); await user.click(await screen.findByText("Enter recovery key"));
@@ -128,7 +128,7 @@ describe("SetupEncryptionToast", () => {
describe("Turn on key storage", () => { describe("Turn on key storage", () => {
it("should render the toast", async () => { it("should render the toast", async () => {
showToast(Kind.TURN_ON_KEY_STORAGE); act(() => showToast(Kind.TURN_ON_KEY_STORAGE));
await expect(screen.findByText("Turn on key storage")).resolves.toBeInTheDocument(); await expect(screen.findByText("Turn on key storage")).resolves.toBeInTheDocument();
await expect(screen.findByRole("button", { name: "Dismiss" })).resolves.toBeInTheDocument(); await expect(screen.findByRole("button", { name: "Dismiss" })).resolves.toBeInTheDocument();
@@ -138,7 +138,7 @@ describe("SetupEncryptionToast", () => {
it("should open settings to the Encryption tab when 'Continue' clicked", async () => { it("should open settings to the Encryption tab when 'Continue' clicked", async () => {
jest.spyOn(DeviceListener.sharedInstance(), "recordKeyBackupDisabled"); jest.spyOn(DeviceListener.sharedInstance(), "recordKeyBackupDisabled");
showToast(Kind.TURN_ON_KEY_STORAGE); act(() => showToast(Kind.TURN_ON_KEY_STORAGE));
const user = userEvent.setup(); const user = userEvent.setup();
await user.click(await screen.findByRole("button", { name: "Continue" })); await user.click(await screen.findByRole("button", { name: "Continue" }));
@@ -160,7 +160,7 @@ describe("SetupEncryptionToast", () => {
}); });
// When we show the toast, and click Dismiss // When we show the toast, and click Dismiss
showToast(Kind.TURN_ON_KEY_STORAGE); act(() => showToast(Kind.TURN_ON_KEY_STORAGE));
const user = userEvent.setup(); const user = userEvent.setup();
await user.click(await screen.findByRole("button", { name: "Dismiss" })); await user.click(await screen.findByRole("button", { name: "Dismiss" }));