Rename general user settings to account (#12841)

* Rename general user settings to account

Everything 'general' is now elsewhere, so this is ready for its
new name.

* Update snapshots

* Rename & update playwright test

* Rename class & remove unused CSS class

* Change test ID

* rethemendex

* More tests!!

* snapshots

* Put the screenshots back in the new place

* Fix tests with restoreAllMocks

* More screenshot renaming

* More test fixes & screenshot updates

* More test fixes

* un-skip

* Typo

Co-authored-by: Robin <robin@robin.town>

---------

Co-authored-by: Robin <robin@robin.town>
This commit is contained in:
David Baker 2024-08-06 18:05:08 +01:00 committed by GitHub
parent 1be4c12fd2
commit 4e4c5c7768
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 172 additions and 54 deletions

View file

@ -98,7 +98,7 @@ describe("<UserSettingsDialog />", () => {
it("should render general settings tab when no initialTabId", () => {
const { container } = render(getComponent());
expect(getActiveTabLabel(container)).toEqual("General");
expect(getActiveTabLabel(container)).toEqual("Account");
});
it("should render initial tab when initialTabId is set", () => {
@ -111,7 +111,7 @@ describe("<UserSettingsDialog />", () => {
// mjolnir tab is only rendered in some configs
const { container } = render(getComponent({ initialTabId: UserTab.Mjolnir }));
expect(getActiveTabLabel(container)).toEqual("General");
expect(getActiveTabLabel(container)).toEqual("Account");
});
it("renders tabs correctly", () => {

View file

@ -3,10 +3,10 @@
exports[`<UserSettingsDialog /> renders tabs correctly 1`] = `
NodeList [
<li
aria-controls="mx_tabpanel_USER_GENERAL_TAB"
aria-controls="mx_tabpanel_USER_ACCOUNT_TAB"
aria-selected="true"
class="mx_AccessibleButton mx_TabbedView_tabLabel mx_TabbedView_tabLabel_active"
data-testid="settings-tab-USER_GENERAL_TAB"
data-testid="settings-tab-USER_ACCOUNT_TAB"
role="tab"
tabindex="0"
>
@ -29,9 +29,9 @@ NodeList [
</svg>
<span
class="mx_TabbedView_tabLabel_text"
id="mx_tabpanel_USER_GENERAL_TAB_label"
id="mx_tabpanel_USER_ACCOUNT_TAB_label"
>
General
Account
</span>
</li>,
<li

View file

@ -13,10 +13,12 @@ limitations under the License.
import { fireEvent, render, screen, within } from "@testing-library/react";
import React from "react";
import { ThreepidMedium } from "matrix-js-sdk/src/matrix";
import { MatrixClient, ThreepidMedium } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
import userEvent from "@testing-library/user-event";
import { MockedObject } from "jest-mock";
import GeneralUserSettingsTab from "../../../../../../src/components/views/settings/tabs/user/GeneralUserSettingsTab";
import AccountUserSettingsTab from "../../../../../../src/components/views/settings/tabs/user/AccountUserSettingsTab";
import { SdkContextClass, SDKContext } from "../../../../../../src/contexts/SDKContext";
import SettingsStore from "../../../../../../src/settings/SettingsStore";
import {
@ -29,28 +31,35 @@ import {
import { UIFeature } from "../../../../../../src/settings/UIFeature";
import { OidcClientStore } from "../../../../../../src/stores/oidc/OidcClientStore";
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
import Modal from "../../../../../../src/Modal";
describe("<GeneralUserSettingsTab />", () => {
let changePasswordOnError: (e: Error) => void;
let changePasswordOnFinished: () => void;
jest.mock(
"../../../../../../src/components/views/settings/ChangePassword",
() =>
({ onError, onFinished }: { onError: (e: Error) => void; onFinished: () => void }) => {
changePasswordOnError = onError;
changePasswordOnFinished = onFinished;
return <button>Mock change password</button>;
},
);
describe("<AccountUserSettingsTab />", () => {
const defaultProps = {
closeSettingsFn: jest.fn(),
};
const userId = "@alice:server.org";
const mockClient = getMockClientWithEventEmitter({
...mockClientMethodsUser(userId),
...mockClientMethodsServer(),
getCapabilities: jest.fn(),
getThreePids: jest.fn(),
getIdentityServerUrl: jest.fn(),
deleteThreePid: jest.fn(),
});
let mockClient: MockedObject<MatrixClient>;
let stores: SdkContextClass;
const getComponent = () => (
<MatrixClientContext.Provider value={mockClient}>
<SDKContext.Provider value={stores}>
<GeneralUserSettingsTab {...defaultProps} />
<AccountUserSettingsTab {...defaultProps} />
</SDKContext.Provider>
</MatrixClientContext.Provider>
);
@ -62,6 +71,15 @@ describe("<GeneralUserSettingsTab />", () => {
jest.spyOn(SettingsStore, "getValue").mockRestore();
jest.spyOn(logger, "error").mockRestore();
mockClient = getMockClientWithEventEmitter({
...mockClientMethodsUser(userId),
...mockClientMethodsServer(),
getCapabilities: jest.fn(),
getThreePids: jest.fn(),
getIdentityServerUrl: jest.fn(),
deleteThreePid: jest.fn(),
});
mockClient.getCapabilities.mockResolvedValue({});
mockClient.getThreePids.mockResolvedValue({
threepids: [],
@ -77,6 +95,10 @@ describe("<GeneralUserSettingsTab />", () => {
jest.spyOn(stores, "oidcClientStore", "get").mockReturnValue(mockOidcClientStore);
});
afterEach(() => {
jest.restoreAllMocks();
});
it("does not show account management link when not available", () => {
const { queryByTestId } = render(getComponent());
@ -131,6 +153,52 @@ describe("<GeneralUserSettingsTab />", () => {
expect(screen.getByText("Deactivate Account", { selector: "h2" }).parentElement!).toMatchSnapshot();
});
it("should display the deactivate account dialog when clicked", async () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation(
(settingName) => settingName === UIFeature.Deactivate,
);
const createDialogFn = jest.fn();
jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn);
render(getComponent());
await userEvent.click(screen.getByRole("button", { name: "Deactivate Account" }));
expect(createDialogFn).toHaveBeenCalled();
});
it("should close settings if account deactivated", async () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation(
(settingName) => settingName === UIFeature.Deactivate,
);
const createDialogFn = jest.fn();
jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn);
render(getComponent());
await userEvent.click(screen.getByRole("button", { name: "Deactivate Account" }));
createDialogFn.mock.calls[0][1].onFinished(true);
expect(defaultProps.closeSettingsFn).toHaveBeenCalled();
});
it("should not close settings if account not deactivated", async () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation(
(settingName) => settingName === UIFeature.Deactivate,
);
const createDialogFn = jest.fn();
jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn);
render(getComponent());
await userEvent.click(screen.getByRole("button", { name: "Deactivate Account" }));
createDialogFn.mock.calls[0][1].onFinished(false);
expect(defaultProps.closeSettingsFn).not.toHaveBeenCalled();
});
});
describe("3pids", () => {
@ -302,4 +370,53 @@ describe("<GeneralUserSettingsTab />", () => {
});
});
});
describe("Password change", () => {
beforeEach(() => {
mockClient.getCapabilities.mockResolvedValue({
"m.change_password": {
enabled: true,
},
});
});
it("should display a dialog if password change succeeded", async () => {
const createDialogFn = jest.fn();
jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn);
render(getComponent());
const changeButton = await screen.findByRole("button", { name: "Mock change password" });
userEvent.click(changeButton);
expect(changePasswordOnFinished).toBeDefined();
changePasswordOnFinished();
expect(createDialogFn).toHaveBeenCalledWith(expect.anything(), {
title: "Success",
description: "Your password was successfully changed.",
});
});
it("should display an error if password change failed", async () => {
const ERROR_STRING =
"Your password must contain exactly 5 lowercase letters, a box drawing character and the badger emoji.";
const createDialogFn = jest.fn();
jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn);
render(getComponent());
const changeButton = await screen.findByRole("button", { name: "Mock change password" });
userEvent.click(changeButton);
expect(changePasswordOnError).toBeDefined();
changePasswordOnError(new Error(ERROR_STRING));
expect(createDialogFn).toHaveBeenCalledWith(expect.anything(), {
title: "Error changing password",
description: ERROR_STRING,
});
});
});
});

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<GeneralUserSettingsTab /> 3pids should display 3pid email addresses and phone numbers 1`] = `
exports[`<AccountUserSettingsTab /> 3pids should display 3pid email addresses and phone numbers 1`] = `
<div
class="mx_SettingsSubsection"
data-testid="mx_AccountEmailAddresses"
@ -42,14 +42,14 @@ exports[`<GeneralUserSettingsTab /> 3pids should display 3pid email addresses an
>
<input
autocomplete="email"
id="mx_Field_27"
id="mx_Field_9"
label="Email Address"
placeholder="Email Address"
type="text"
value=""
/>
<label
for="mx_Field_27"
for="mx_Field_9"
>
Email Address
</label>
@ -66,7 +66,7 @@ exports[`<GeneralUserSettingsTab /> 3pids should display 3pid email addresses an
</div>
`;
exports[`<GeneralUserSettingsTab /> 3pids should display 3pid email addresses and phone numbers 2`] = `
exports[`<AccountUserSettingsTab /> 3pids should display 3pid email addresses and phone numbers 2`] = `
<div
class="mx_SettingsSubsection"
data-testid="mx_AccountPhoneNumbers"
@ -150,14 +150,14 @@ exports[`<GeneralUserSettingsTab /> 3pids should display 3pid email addresses an
</span>
<input
autocomplete="tel-national"
id="mx_Field_28"
id="mx_Field_10"
label="Phone Number"
placeholder="Phone Number"
type="text"
value=""
/>
<label
for="mx_Field_28"
for="mx_Field_10"
>
Phone Number
</label>
@ -175,7 +175,7 @@ exports[`<GeneralUserSettingsTab /> 3pids should display 3pid email addresses an
</div>
`;
exports[`<GeneralUserSettingsTab /> deactive account should render section when account deactivation feature is enabled 1`] = `
exports[`<AccountUserSettingsTab /> deactive account should render section when account deactivation feature is enabled 1`] = `
<div
class="mx_SettingsSection"
>