mirror of
https://github.com/Novaloop-AG/healthchat-web.git
synced 2026-11-04 10:32:44 +00:00
mv element.io @types __mocks__/ debian docker module_system/ playwright res src test webapp Dockerfile .dockerignore .eslintignore .stylelintrc.cjs babel.config.cjs recorder-worklet-loader.cjs .modernizr.json components.json config.json config.sample.json package.json project.json tsconfig.json tsconfig.module_system.json jest.config.ts playwright.config.ts webpack.config.ts build_config.sample.yaml apps/web/
mkdir apps/web/scripts
mv scripts/{cleanup.sh,ci_package.sh,copy-res.ts,deploy.py,package.sh} apps/web/scripts
And a couple of gitignore tweaks
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
+427
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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 { fireEvent, render, screen, within } from "jest-matrix-react";
|
||||
import React from "react";
|
||||
import { type MatrixClient, ThreepidMedium } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { type MockedObject } from "jest-mock";
|
||||
|
||||
import AccountUserSettingsTab from "../../../../../../../src/components/views/settings/tabs/user/AccountUserSettingsTab";
|
||||
import { SdkContextClass, SDKContext } from "../../../../../../../src/contexts/SDKContext";
|
||||
import SettingsStore from "../../../../../../../src/settings/SettingsStore";
|
||||
import {
|
||||
getMockClientWithEventEmitter,
|
||||
mockClientMethodsServer,
|
||||
mockClientMethodsUser,
|
||||
mockPlatformPeg,
|
||||
flushPromises,
|
||||
} from "../../../../../../test-utils";
|
||||
import { UIFeature } from "../../../../../../../src/settings/UIFeature";
|
||||
import { type OidcClientStore } from "../../../../../../../src/stores/oidc/OidcClientStore";
|
||||
import MatrixClientContext from "../../../../../../../src/contexts/MatrixClientContext";
|
||||
import Modal from "../../../../../../../src/Modal";
|
||||
|
||||
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";
|
||||
let mockClient: MockedObject<MatrixClient>;
|
||||
|
||||
let stores: SdkContextClass;
|
||||
|
||||
const getComponent = () => (
|
||||
<MatrixClientContext.Provider value={mockClient}>
|
||||
<SDKContext.Provider value={stores}>
|
||||
<AccountUserSettingsTab {...defaultProps} />
|
||||
</SDKContext.Provider>
|
||||
</MatrixClientContext.Provider>
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false);
|
||||
mockPlatformPeg();
|
||||
jest.clearAllMocks();
|
||||
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: [],
|
||||
});
|
||||
mockClient.deleteThreePid.mockResolvedValue({
|
||||
id_server_unbind_result: "success",
|
||||
});
|
||||
|
||||
stores = new SdkContextClass();
|
||||
stores.client = mockClient;
|
||||
// stub out this store completely to avoid mocking initialisation
|
||||
const mockOidcClientStore = {} as unknown as OidcClientStore;
|
||||
jest.spyOn(stores, "oidcClientStore", "get").mockReturnValue(mockOidcClientStore);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("does not show account management link when not available", () => {
|
||||
const { queryByTestId } = render(getComponent());
|
||||
|
||||
expect(queryByTestId("external-account-management-outer")).toBeFalsy();
|
||||
expect(queryByTestId("external-account-management-link")).toBeFalsy();
|
||||
});
|
||||
|
||||
it("show account management link in expected format", async () => {
|
||||
const accountManagementLink = "https://id.server.org/my-account";
|
||||
const mockOidcClientStore = {
|
||||
accountManagementEndpoint: accountManagementLink,
|
||||
} as unknown as OidcClientStore;
|
||||
jest.spyOn(stores, "oidcClientStore", "get").mockReturnValue(mockOidcClientStore);
|
||||
|
||||
render(getComponent());
|
||||
|
||||
const manageAccountLink = await screen.findByRole("button", { name: "Manage account" });
|
||||
expect(manageAccountLink.getAttribute("href")).toMatch(accountManagementLink);
|
||||
});
|
||||
|
||||
describe("deactivate account", () => {
|
||||
it("should not render section when account deactivation feature is disabled", () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation(
|
||||
(settingName) => settingName !== UIFeature.Deactivate,
|
||||
);
|
||||
render(getComponent());
|
||||
|
||||
expect(screen.queryByText("Deactivate Account")).not.toBeInTheDocument();
|
||||
expect(SettingsStore.getValue).toHaveBeenCalledWith(UIFeature.Deactivate);
|
||||
});
|
||||
it("should not render section when account is managed externally", async () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation(
|
||||
(settingName) => settingName === UIFeature.Deactivate,
|
||||
);
|
||||
// account is managed externally when we have delegated auth configured
|
||||
const accountManagementLink = "https://id.server.org/my-account";
|
||||
const mockOidcClientStore = {
|
||||
accountManagementEndpoint: accountManagementLink,
|
||||
} as unknown as OidcClientStore;
|
||||
jest.spyOn(stores, "oidcClientStore", "get").mockReturnValue(mockOidcClientStore);
|
||||
render(getComponent());
|
||||
|
||||
await flushPromises();
|
||||
|
||||
expect(screen.queryByText("Deactivate Account")).not.toBeInTheDocument();
|
||||
});
|
||||
it("should render section when account deactivation feature is enabled", () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation(
|
||||
(settingName) => settingName === UIFeature.Deactivate,
|
||||
);
|
||||
render(getComponent());
|
||||
|
||||
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 finishedDeferred = Promise.withResolvers<[boolean]>();
|
||||
const createDialogFn = jest.fn().mockReturnValue({ finished: finishedDeferred.promise });
|
||||
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 finishedDeferred = Promise.withResolvers<[boolean]>();
|
||||
const createDialogFn = jest.fn().mockReturnValue({ finished: finishedDeferred.promise });
|
||||
jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn);
|
||||
|
||||
render(getComponent());
|
||||
|
||||
await userEvent.click(screen.getByRole("button", { name: "Deactivate Account" }));
|
||||
|
||||
finishedDeferred.resolve([true]);
|
||||
await flushPromises();
|
||||
|
||||
expect(defaultProps.closeSettingsFn).toHaveBeenCalled();
|
||||
});
|
||||
it("should not close settings if account not deactivated", async () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation(
|
||||
(settingName) => settingName === UIFeature.Deactivate,
|
||||
);
|
||||
|
||||
const finishedDeferred = Promise.withResolvers<[boolean]>();
|
||||
const createDialogFn = jest.fn().mockReturnValue({ finished: finishedDeferred.promise });
|
||||
jest.spyOn(Modal, "createDialog").mockImplementation(createDialogFn);
|
||||
|
||||
render(getComponent());
|
||||
|
||||
await userEvent.click(screen.getByRole("button", { name: "Deactivate Account" }));
|
||||
|
||||
finishedDeferred.resolve([false]);
|
||||
await flushPromises();
|
||||
|
||||
expect(defaultProps.closeSettingsFn).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("3pids", () => {
|
||||
beforeEach(() => {
|
||||
const mockOidcClientStore = {
|
||||
accountManagementEndpoint: undefined,
|
||||
} as unknown as OidcClientStore;
|
||||
jest.spyOn(stores, "oidcClientStore", "get").mockReturnValue(mockOidcClientStore);
|
||||
|
||||
mockClient.getCapabilities.mockResolvedValue({
|
||||
"m.3pid_changes": {
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
mockClient.getThreePids.mockResolvedValue({
|
||||
threepids: [
|
||||
{
|
||||
medium: ThreepidMedium.Email,
|
||||
address: "test@test.io",
|
||||
validated_at: 1685067124552,
|
||||
added_at: 1685067124552,
|
||||
},
|
||||
{
|
||||
medium: ThreepidMedium.Phone,
|
||||
address: "123456789",
|
||||
validated_at: 1685067124552,
|
||||
added_at: 1685067124552,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
mockClient.getIdentityServerUrl.mockReturnValue(undefined);
|
||||
});
|
||||
|
||||
it("should show loaders while 3pids load", () => {
|
||||
render(getComponent());
|
||||
|
||||
expect(
|
||||
within(screen.getByTestId("mx_AccountEmailAddresses")).getByLabelText("Loading…"),
|
||||
).toBeInTheDocument();
|
||||
expect(within(screen.getByTestId("mx_AccountPhoneNumbers")).getByLabelText("Loading…")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should display 3pid email addresses and phone numbers", async () => {
|
||||
render(getComponent());
|
||||
|
||||
await flushPromises();
|
||||
|
||||
expect(screen.getByTestId("mx_AccountEmailAddresses")).toMatchSnapshot();
|
||||
expect(screen.getByTestId("mx_AccountPhoneNumbers")).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should allow removing an existing email addresses", async () => {
|
||||
render(getComponent());
|
||||
|
||||
await flushPromises();
|
||||
|
||||
const section = screen.getByTestId("mx_AccountEmailAddresses");
|
||||
|
||||
fireEvent.click(within(section).getByText("Remove"));
|
||||
|
||||
// confirm removal
|
||||
expect(screen.getByText("Remove test@test.io?")).toBeInTheDocument();
|
||||
fireEvent.click(within(section).getByText("Remove"));
|
||||
|
||||
expect(mockClient.deleteThreePid).toHaveBeenCalledWith(ThreepidMedium.Email, "test@test.io");
|
||||
});
|
||||
|
||||
it("should allow adding a new email address", async () => {
|
||||
render(getComponent());
|
||||
|
||||
await flushPromises();
|
||||
|
||||
const section = screen.getByTestId("mx_AccountEmailAddresses");
|
||||
|
||||
// just check the fields are enabled
|
||||
expect(within(section).getByLabelText("Email Address")).not.toBeDisabled();
|
||||
expect(within(section).getByText("Add")).not.toHaveAttribute("aria-disabled");
|
||||
});
|
||||
|
||||
it("should allow removing an existing phone number", async () => {
|
||||
render(getComponent());
|
||||
|
||||
await flushPromises();
|
||||
|
||||
const section = screen.getByTestId("mx_AccountPhoneNumbers");
|
||||
|
||||
fireEvent.click(within(section).getByText("Remove"));
|
||||
|
||||
// confirm removal
|
||||
expect(screen.getByText("Remove 123456789?")).toBeInTheDocument();
|
||||
fireEvent.click(within(section).getByText("Remove"));
|
||||
|
||||
expect(mockClient.deleteThreePid).toHaveBeenCalledWith(ThreepidMedium.Phone, "123456789");
|
||||
});
|
||||
|
||||
it("should allow adding a new phone number", async () => {
|
||||
render(getComponent());
|
||||
|
||||
await flushPromises();
|
||||
|
||||
const section = screen.getByTestId("mx_AccountPhoneNumbers");
|
||||
|
||||
// just check the fields are enabled
|
||||
expect(within(section).getByLabelText("Phone Number")).not.toBeDisabled();
|
||||
});
|
||||
|
||||
it("should allow 3pid changes when capabilities does not have 3pid_changes", async () => {
|
||||
// We support as far back as v1.1 which doesn't have m.3pid_changes
|
||||
// so the behaviour for when it is missing has to be assume true
|
||||
mockClient.getCapabilities.mockResolvedValue({});
|
||||
|
||||
render(getComponent());
|
||||
|
||||
await flushPromises();
|
||||
|
||||
const section = screen.getByTestId("mx_AccountEmailAddresses");
|
||||
|
||||
// just check the fields are enabled
|
||||
expect(within(section).getByLabelText("Email Address")).not.toBeDisabled();
|
||||
expect(within(section).getByText("Add")).not.toHaveAttribute("aria-disabled");
|
||||
});
|
||||
|
||||
describe("when 3pid changes capability is disabled", () => {
|
||||
beforeEach(() => {
|
||||
mockClient.getCapabilities.mockResolvedValue({
|
||||
"m.3pid_changes": {
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should not allow removing email addresses", async () => {
|
||||
render(getComponent());
|
||||
|
||||
await flushPromises();
|
||||
|
||||
const section = screen.getByTestId("mx_AccountEmailAddresses");
|
||||
|
||||
expect(within(section).getByText("Remove")).toHaveAttribute("aria-disabled");
|
||||
});
|
||||
|
||||
it("should not allow adding a new email addresses", async () => {
|
||||
render(getComponent());
|
||||
|
||||
await flushPromises();
|
||||
|
||||
const section = screen.getByTestId("mx_AccountEmailAddresses");
|
||||
|
||||
// fields are not enabled
|
||||
expect(within(section).getByLabelText("Email Address")).toBeDisabled();
|
||||
expect(within(section).getByText("Add")).toHaveAttribute("aria-disabled");
|
||||
});
|
||||
|
||||
it("should not allow removing phone numbers", async () => {
|
||||
render(getComponent());
|
||||
|
||||
await flushPromises();
|
||||
|
||||
const section = screen.getByTestId("mx_AccountPhoneNumbers");
|
||||
|
||||
expect(within(section).getByText("Remove")).toHaveAttribute("aria-disabled");
|
||||
});
|
||||
|
||||
it("should not allow adding a new phone number", async () => {
|
||||
render(getComponent());
|
||||
|
||||
await flushPromises();
|
||||
|
||||
const section = screen.getByTestId("mx_AccountPhoneNumbers");
|
||||
|
||||
expect(within(section).getByLabelText("Phone Number")).toBeDisabled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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 { render } from "jest-matrix-react";
|
||||
import React from "react";
|
||||
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import AppearanceUserSettingsTab from "../../../../../../../src/components/views/settings/tabs/user/AppearanceUserSettingsTab";
|
||||
import { withClientContextRenderOptions, stubClient } from "../../../../../../test-utils";
|
||||
|
||||
describe("AppearanceUserSettingsTab", () => {
|
||||
let client: MatrixClient;
|
||||
|
||||
beforeEach(() => {
|
||||
client = stubClient();
|
||||
});
|
||||
|
||||
it("should render", () => {
|
||||
const { asFragment } = render(<AppearanceUserSettingsTab />, withClientContextRenderOptions(client));
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright 2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { mocked } from "jest-mock";
|
||||
import React from "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,
|
||||
type State,
|
||||
} from "../../../../../../../src/components/views/settings/tabs/user/EncryptionUserSettingsTab";
|
||||
import { createTestClient, withClientContextRenderOptions } from "../../../../../../test-utils";
|
||||
import Modal from "../../../../../../../src/Modal";
|
||||
import { DeviceListener } from "../../../../../../../src/device-listener";
|
||||
|
||||
describe("<EncryptionUserSettingsTab />", () => {
|
||||
let matrixClient: MatrixClient;
|
||||
|
||||
beforeEach(() => {
|
||||
matrixClient = createTestClient();
|
||||
jest.spyOn(matrixClient.getCrypto()!, "isCrossSigningReady").mockResolvedValue(true);
|
||||
// Recovery key is available
|
||||
jest.spyOn(matrixClient.secretStorage, "getDefaultKeyId").mockResolvedValue("default key");
|
||||
// Secrets are cached
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getCrossSigningStatus").mockResolvedValue({
|
||||
privateKeysInSecretStorage: true,
|
||||
publicKeysOnDevice: true,
|
||||
privateKeysCachedLocally: {
|
||||
masterKey: true,
|
||||
selfSigningKey: true,
|
||||
userSigningKey: true,
|
||||
},
|
||||
});
|
||||
|
||||
jest.spyOn(DeviceListener.sharedInstance(), "getDeviceState").mockReturnValue("ok");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
function renderComponent(props: { initialState?: State } = {}) {
|
||||
return render(<EncryptionUserSettingsTab {...props} />, withClientContextRenderOptions(matrixClient));
|
||||
}
|
||||
|
||||
it("should display a verify button when the encryption is not set up", async () => {
|
||||
const user = userEvent.setup();
|
||||
mocked(DeviceListener.sharedInstance().getDeviceState).mockReturnValue("verify_this_session");
|
||||
|
||||
const { asFragment } = renderComponent();
|
||||
await waitFor(() =>
|
||||
expect(
|
||||
screen.getByText("You need to verify this device in order to view your encryption settings."),
|
||||
).toBeInTheDocument(),
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
|
||||
const spy = jest.spyOn(Modal, "createDialog").mockReturnValue({ finished: new Promise(() => {}) } as any);
|
||||
await user.click(screen.getByText("Verify this device"));
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
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 () => {
|
||||
mocked(DeviceListener.sharedInstance().getDeviceState).mockReturnValue("key_storage_out_of_sync");
|
||||
|
||||
const user = userEvent.setup();
|
||||
const { asFragment } = renderComponent();
|
||||
|
||||
await waitFor(() => screen.getByRole("button", { name: "Enter recovery key" }));
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Forgot recovery key?" }));
|
||||
expect(
|
||||
screen.getByRole("heading", { name: "Forgot your recovery key? You’ll need to reset your identity." }),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
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();
|
||||
await waitFor(() => {
|
||||
const button = screen.getByRole("button", { name: "Change recovery key" });
|
||||
expect(button).toBeInTheDocument();
|
||||
user.click(button);
|
||||
});
|
||||
await waitFor(() => expect(screen.getByText("Change recovery key")).toBeInTheDocument());
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
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();
|
||||
|
||||
const { asFragment } = renderComponent();
|
||||
await waitFor(() => {
|
||||
const button = screen.getByRole("button", { name: "Set up recovery" });
|
||||
expect(button).toBeInTheDocument();
|
||||
user.click(button);
|
||||
});
|
||||
await waitFor(() => expect(screen.getByText("Set up recovery")).toBeInTheDocument());
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
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();
|
||||
await waitFor(() => {
|
||||
const button = screen.getByRole("button", { name: "Reset cryptographic identity" });
|
||||
expect(button).toBeInTheDocument();
|
||||
user.click(button);
|
||||
});
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText("Are you sure you want to reset your identity?")).toBeInTheDocument(),
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should enter 'Forgot recovery' flow when initialState is set to 'reset_identity_forgot'", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1");
|
||||
|
||||
renderComponent({ initialState: "reset_identity_forgot" });
|
||||
|
||||
expect(
|
||||
await screen.findByRole("heading", {
|
||||
name: "Forgot your recovery key? You’ll need to reset your identity.",
|
||||
}),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
it("should do 'Failed to sync' reset flow when initialState is set to 'reset_identity_sync_failed'", async () => {
|
||||
jest.spyOn(matrixClient.getCrypto()!, "getActiveSessionBackupVersion").mockResolvedValue("1");
|
||||
|
||||
renderComponent({ initialState: "reset_identity_sync_failed" });
|
||||
|
||||
expect(
|
||||
await screen.findByRole("heading", {
|
||||
name: "Failed to sync key storage. You 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();
|
||||
|
||||
mocked(DeviceListener.sharedInstance().getDeviceState).mockReturnValue("key_storage_out_of_sync");
|
||||
|
||||
renderComponent({ initialState: "reset_identity_forgot" });
|
||||
|
||||
expect(
|
||||
screen.getByRole("heading", { name: "Forgot your recovery key? You’ll need to reset your identity." }),
|
||||
).toBeVisible();
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Back" }));
|
||||
await waitFor(() =>
|
||||
screen.getByText("Your key storage is out of sync. Click one of the buttons below to fix the problem."),
|
||||
);
|
||||
});
|
||||
|
||||
it("should display the identity needs reset panel when the user's identity needs resetting", async () => {
|
||||
mocked(DeviceListener.sharedInstance().getDeviceState).mockReturnValue("identity_needs_reset");
|
||||
|
||||
const user = userEvent.setup();
|
||||
const { asFragment } = renderComponent();
|
||||
|
||||
await waitFor(() => screen.getByRole("button", { name: "Continue with reset" }));
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
|
||||
await user.click(screen.getByRole("button", { name: "Continue with reset" }));
|
||||
expect(screen.getByRole("heading", { name: "You need to reset your identity" })).toBeVisible();
|
||||
});
|
||||
});
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
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 } from "jest-matrix-react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
import { InviteRulesAccountSetting } from "../../../../../../../src/components/views/settings/tabs/user/InviteRulesAccountSettings";
|
||||
import SettingsStore from "../../../../../../../src/settings/SettingsStore";
|
||||
import { type ComputedInviteConfig } from "../../../../../../../src/@types/invite-rules";
|
||||
import { SettingLevel } from "../../../../../../../src/settings/SettingLevel";
|
||||
|
||||
function mockSetting(inviteRules: ComputedInviteConfig, blockInvites: boolean) {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName) => {
|
||||
if (settingName === "inviteRules") {
|
||||
return inviteRules;
|
||||
}
|
||||
if (settingName === "blockInvites") {
|
||||
return blockInvites;
|
||||
}
|
||||
throw Error(`Unexpected setting ${settingName}`);
|
||||
});
|
||||
}
|
||||
|
||||
function mockDisabledMessage(msc4155supported: boolean, msc4380Supported: boolean) {
|
||||
jest.spyOn(SettingsStore, "disabledMessage").mockImplementation((settingName) => {
|
||||
if (settingName === "inviteRules") {
|
||||
return msc4155supported ? undefined : "test-not-supported";
|
||||
}
|
||||
if (settingName === "blockInvites") {
|
||||
return msc4380Supported ? undefined : "test-not-supported";
|
||||
}
|
||||
throw Error(`Unexpected setting ${settingName}`);
|
||||
});
|
||||
}
|
||||
|
||||
describe("InviteRulesAccountSetting", () => {
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("does not render if neither MSC4155 nor MSC4380 are supported", async () => {
|
||||
mockSetting({ allBlocked: false }, false);
|
||||
mockDisabledMessage(false, false);
|
||||
const { findByText, findByLabelText } = render(<InviteRulesAccountSetting />);
|
||||
const input = await findByLabelText("Allow users to invite you to rooms");
|
||||
await userEvent.hover(input);
|
||||
const result = await findByText("test-not-supported");
|
||||
expect(result).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe("when MSC4155 is supported", () => {
|
||||
beforeEach(() => {
|
||||
mockDisabledMessage(true, false);
|
||||
});
|
||||
|
||||
it("renders correct state when invites are not blocked", async () => {
|
||||
mockSetting({ allBlocked: false }, false);
|
||||
const { findByLabelText } = render(<InviteRulesAccountSetting />);
|
||||
const result = await findByLabelText("Allow users to invite you to rooms");
|
||||
expect(result).toBeChecked();
|
||||
});
|
||||
|
||||
it("renders correct state when invites are blocked", async () => {
|
||||
mockSetting({ allBlocked: true }, false);
|
||||
const { findByLabelText } = render(<InviteRulesAccountSetting />);
|
||||
const result = await findByLabelText("Allow users to invite you to rooms");
|
||||
expect(result).not.toBeChecked();
|
||||
});
|
||||
|
||||
it("handles disabling all invites", async () => {
|
||||
mockSetting({ allBlocked: false }, false);
|
||||
jest.spyOn(SettingsStore, "setValue").mockImplementation();
|
||||
const { findByLabelText } = render(<InviteRulesAccountSetting />);
|
||||
const result = await findByLabelText("Allow users to invite you to rooms");
|
||||
await userEvent.click(result);
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledTimes(1);
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledWith("inviteRules", null, SettingLevel.ACCOUNT, {
|
||||
allBlocked: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("handles enabling all invites", async () => {
|
||||
mockSetting({ allBlocked: true }, true);
|
||||
jest.spyOn(SettingsStore, "setValue").mockImplementation();
|
||||
const { findByLabelText } = render(<InviteRulesAccountSetting />);
|
||||
const result = await findByLabelText("Allow users to invite you to rooms");
|
||||
await userEvent.click(result);
|
||||
// Should clear both MSC4155 and MSC4380 settings
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledTimes(2);
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledWith("inviteRules", null, SettingLevel.ACCOUNT, {
|
||||
allBlocked: false,
|
||||
});
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledWith("blockInvites", null, SettingLevel.ACCOUNT, false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when MSC4380 is supported", () => {
|
||||
beforeEach(() => {
|
||||
mockDisabledMessage(false, true);
|
||||
});
|
||||
|
||||
it("renders correct state when invites are not blocked", async () => {
|
||||
mockSetting({ allBlocked: false }, false);
|
||||
const { findByLabelText } = render(<InviteRulesAccountSetting />);
|
||||
const result = await findByLabelText("Allow users to invite you to rooms");
|
||||
expect(result).toBeChecked();
|
||||
});
|
||||
|
||||
it("renders correct state when invites are blocked", async () => {
|
||||
mockSetting({ allBlocked: false }, true);
|
||||
const { findByLabelText } = render(<InviteRulesAccountSetting />);
|
||||
const result = await findByLabelText("Allow users to invite you to rooms");
|
||||
expect(result).not.toBeChecked();
|
||||
});
|
||||
|
||||
it("handles disabling all invites", async () => {
|
||||
mockSetting({ allBlocked: false }, false);
|
||||
jest.spyOn(SettingsStore, "setValue").mockImplementation();
|
||||
const { findByLabelText } = render(<InviteRulesAccountSetting />);
|
||||
const result = await findByLabelText("Allow users to invite you to rooms");
|
||||
await userEvent.click(result);
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledTimes(1);
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledWith("blockInvites", null, SettingLevel.ACCOUNT, true);
|
||||
});
|
||||
|
||||
it("handles enabling all invites", async () => {
|
||||
mockSetting({ allBlocked: true }, true);
|
||||
jest.spyOn(SettingsStore, "setValue").mockImplementation();
|
||||
const { findByLabelText } = render(<InviteRulesAccountSetting />);
|
||||
const result = await findByLabelText("Allow users to invite you to rooms");
|
||||
await userEvent.click(result);
|
||||
// Should clear both MSC4155 and MSC4380 settings
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledTimes(2);
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledWith("inviteRules", null, SettingLevel.ACCOUNT, {
|
||||
allBlocked: false,
|
||||
});
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledWith("blockInvites", null, SettingLevel.ACCOUNT, false);
|
||||
});
|
||||
});
|
||||
});
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2022 Šimon Brandner <simon.bra.ag@gmail.com>
|
||||
|
||||
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 { render } from "jest-matrix-react";
|
||||
import React from "react";
|
||||
|
||||
import KeyboardUserSettingsTab from "../../../../../../../src/components/views/settings/tabs/user/KeyboardUserSettingsTab";
|
||||
import { Key } from "../../../../../../../src/Keyboard";
|
||||
import { mockPlatformPeg } from "../../../../../../test-utils/platform";
|
||||
|
||||
const PATH_TO_KEYBOARD_SHORTCUTS = "../../../../../../../src/accessibility/KeyboardShortcuts";
|
||||
const PATH_TO_KEYBOARD_SHORTCUT_UTILS = "../../../../../../../src/accessibility/KeyboardShortcutUtils";
|
||||
|
||||
const mockKeyboardShortcuts = (override: Record<string, any>) => {
|
||||
jest.doMock(PATH_TO_KEYBOARD_SHORTCUTS, () => {
|
||||
const original = jest.requireActual(PATH_TO_KEYBOARD_SHORTCUTS);
|
||||
return {
|
||||
...original,
|
||||
...override,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const mockKeyboardShortcutUtils = (override: Record<string, any>) => {
|
||||
jest.doMock(PATH_TO_KEYBOARD_SHORTCUT_UTILS, () => {
|
||||
const original = jest.requireActual(PATH_TO_KEYBOARD_SHORTCUT_UTILS);
|
||||
return {
|
||||
...original,
|
||||
...override,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const renderKeyboardUserSettingsTab = () => {
|
||||
return render(<KeyboardUserSettingsTab />).container;
|
||||
};
|
||||
|
||||
describe("KeyboardUserSettingsTab", () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
mockPlatformPeg();
|
||||
});
|
||||
|
||||
it("renders list of keyboard shortcuts", () => {
|
||||
mockKeyboardShortcuts({
|
||||
CATEGORIES: {
|
||||
Composer: {
|
||||
settingNames: ["keybind1", "keybind2"],
|
||||
categoryLabel: "Composer",
|
||||
},
|
||||
Navigation: {
|
||||
settingNames: ["keybind3"],
|
||||
categoryLabel: "Navigation",
|
||||
},
|
||||
},
|
||||
});
|
||||
mockKeyboardShortcutUtils({
|
||||
getKeyboardShortcutValue: (name: string) => {
|
||||
switch (name) {
|
||||
case "keybind1":
|
||||
return {
|
||||
key: Key.A,
|
||||
ctrlKey: true,
|
||||
};
|
||||
case "keybind2": {
|
||||
return {
|
||||
key: Key.B,
|
||||
ctrlKey: true,
|
||||
};
|
||||
}
|
||||
case "keybind3": {
|
||||
return {
|
||||
key: Key.ENTER,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
getKeyboardShortcutDisplayName: (name: string) => {
|
||||
switch (name) {
|
||||
case "keybind1":
|
||||
return "Cancel replying to a message";
|
||||
case "keybind2":
|
||||
return "Toggle Bold";
|
||||
|
||||
case "keybind3":
|
||||
return "Select room from the room list";
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const body = renderKeyboardUserSettingsTab();
|
||||
expect(body).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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 } from "jest-matrix-react";
|
||||
|
||||
import LabsUserSettingsTab from "../../../../../../../src/components/views/settings/tabs/user/LabsUserSettingsTab";
|
||||
import SettingsStore from "../../../../../../../src/settings/SettingsStore";
|
||||
import SdkConfig from "../../../../../../../src/SdkConfig";
|
||||
|
||||
describe("<LabsUserSettingsTab />", () => {
|
||||
const getComponent = () => <LabsUserSettingsTab />;
|
||||
|
||||
const settingsValueSpy = jest.spyOn(SettingsStore, "getValue");
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
settingsValueSpy.mockReturnValue(false);
|
||||
SdkConfig.reset();
|
||||
SdkConfig.add({ brand: "BrandedClient" });
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
it("renders settings marked as beta as beta cards", () => {
|
||||
render(getComponent());
|
||||
expect(screen.getByText("Upcoming features").parentElement!).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("does not render non-beta labs settings when disabled in config", () => {
|
||||
const sdkConfigSpy = jest.spyOn(SdkConfig, "get");
|
||||
render(getComponent());
|
||||
expect(sdkConfigSpy).toHaveBeenCalledWith("show_labs_settings");
|
||||
|
||||
// only section is beta section
|
||||
expect(screen.queryByText("Early previews")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders non-beta labs settings when enabled in config", () => {
|
||||
// enable labs
|
||||
SdkConfig.add({ show_labs_settings: true });
|
||||
const { container } = render(getComponent());
|
||||
|
||||
// non-beta labs section
|
||||
expect(screen.getByText("Early previews")).toBeInTheDocument();
|
||||
const labsSections = container.getElementsByClassName("mx_SettingsSubsection");
|
||||
expect(labsSections).toHaveLength(10);
|
||||
});
|
||||
});
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
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 { render } from "jest-matrix-react";
|
||||
import React from "react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { type MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { MediaPreviewAccountSettings } from "../../../../../../../src/components/views/settings/tabs/user/MediaPreviewAccountSettings";
|
||||
import {
|
||||
getMockClientWithEventEmitter,
|
||||
mockClientMethodsServer,
|
||||
mockClientMethodsUser,
|
||||
} from "../../../../../../test-utils";
|
||||
import MatrixClientBackedController from "../../../../../../../src/settings/controllers/MatrixClientBackedController";
|
||||
import MatrixClientBackedSettingsHandler from "../../../../../../../src/settings/handlers/MatrixClientBackedSettingsHandler";
|
||||
import type { MockedObject } from "jest-mock";
|
||||
import {
|
||||
MEDIA_PREVIEW_ACCOUNT_DATA_TYPE,
|
||||
type MediaPreviewConfig,
|
||||
MediaPreviewValue,
|
||||
} from "../../../../../../../src/@types/media_preview";
|
||||
import MediaPreviewConfigController from "../../../../../../../src/settings/controllers/MediaPreviewConfigController";
|
||||
|
||||
describe("MediaPreviewAccountSettings", () => {
|
||||
let client: MockedObject<MatrixClient>;
|
||||
beforeEach(() => {
|
||||
client = getMockClientWithEventEmitter({
|
||||
...mockClientMethodsServer(),
|
||||
...mockClientMethodsUser(),
|
||||
getRoom: jest.fn(),
|
||||
setAccountData: jest.fn(),
|
||||
isVersionSupported: jest.fn().mockResolvedValue(true),
|
||||
});
|
||||
MatrixClientBackedController.matrixClient = client;
|
||||
MatrixClientBackedSettingsHandler.matrixClient = client;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("should render", () => {
|
||||
const { getByLabelText } = render(<MediaPreviewAccountSettings />);
|
||||
// Defaults
|
||||
expect(getByLabelText("Hide avatars of room and inviter")).not.toBeChecked();
|
||||
expect(getByLabelText("Always hide")).not.toBeChecked();
|
||||
expect(getByLabelText("In private rooms")).not.toBeChecked();
|
||||
expect(getByLabelText("Always show")).toBeChecked();
|
||||
});
|
||||
|
||||
it("should be able to toggle hide avatar", async () => {
|
||||
const { getByLabelText } = render(<MediaPreviewAccountSettings />);
|
||||
// Defaults
|
||||
const element = getByLabelText("Hide avatars of room and inviter");
|
||||
await userEvent.click(element);
|
||||
expect(client.setAccountData).toHaveBeenCalledWith(MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, {
|
||||
invite_avatars: MediaPreviewValue.Off,
|
||||
media_previews: MediaPreviewValue.On,
|
||||
});
|
||||
// Ensure we don't double set the account data.
|
||||
expect(client.setAccountData).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
// Skip the default.
|
||||
it.each([
|
||||
["Always hide", MediaPreviewValue.Off],
|
||||
["In private rooms", MediaPreviewValue.Private],
|
||||
["Always show", MediaPreviewValue.On],
|
||||
])("should be able to toggle media preview option %s", async (key, value) => {
|
||||
if (value === MediaPreviewConfigController.default.media_previews) {
|
||||
// This is the default, so switch away first.
|
||||
client.getAccountData.mockImplementation((type) => {
|
||||
if (type === MEDIA_PREVIEW_ACCOUNT_DATA_TYPE) {
|
||||
return new MatrixEvent({
|
||||
content: {
|
||||
media_previews: MediaPreviewValue.Off,
|
||||
} satisfies Partial<MediaPreviewConfig>,
|
||||
});
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
const { getByLabelText } = render(<MediaPreviewAccountSettings />);
|
||||
|
||||
const element = getByLabelText(key);
|
||||
await userEvent.click(element);
|
||||
expect(client.setAccountData).toHaveBeenCalledWith(MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, {
|
||||
invite_avatars: MediaPreviewValue.On,
|
||||
media_previews: value,
|
||||
});
|
||||
// Ensure we don't double set the account data.
|
||||
expect(client.setAccountData).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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 } from "jest-matrix-react";
|
||||
|
||||
import { getMockClientWithEventEmitter, mockClientMethodsUser } from "../../../../../../test-utils";
|
||||
import MjolnirUserSettingsTab from "../../../../../../../src/components/views/settings/tabs/user/MjolnirUserSettingsTab";
|
||||
import MatrixClientContext from "../../../../../../../src/contexts/MatrixClientContext";
|
||||
import SettingsStore from "../../../../../../../src/settings/SettingsStore";
|
||||
|
||||
describe("<MjolnirUserSettingsTab />", () => {
|
||||
const userId = "@alice:server.org";
|
||||
const mockClient = getMockClientWithEventEmitter({
|
||||
...mockClientMethodsUser(userId),
|
||||
getRoom: jest.fn(),
|
||||
});
|
||||
|
||||
const getComponent = () =>
|
||||
render(<MjolnirUserSettingsTab />, {
|
||||
wrapper: ({ children }) => (
|
||||
<MatrixClientContext.Provider value={mockClient}>{children}</MatrixClientContext.Provider>
|
||||
),
|
||||
});
|
||||
|
||||
it("renders correctly when user has no ignored users", () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(null);
|
||||
const { container } = getComponent();
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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 { fireEvent, render, type RenderResult, screen, waitFor } from "jest-matrix-react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
import PreferencesUserSettingsTab from "../../../../../../../src/components/views/settings/tabs/user/PreferencesUserSettingsTab";
|
||||
import { MatrixClientPeg } from "../../../../../../../src/MatrixClientPeg";
|
||||
import { mockPlatformPeg, stubClient } from "../../../../../../test-utils";
|
||||
import SettingsStore from "../../../../../../../src/settings/SettingsStore";
|
||||
import { SettingLevel } from "../../../../../../../src/settings/SettingLevel";
|
||||
import MatrixClientBackedController from "../../../../../../../src/settings/controllers/MatrixClientBackedController";
|
||||
import PlatformPeg from "../../../../../../../src/PlatformPeg";
|
||||
import { type SettingKey } from "../../../../../../../src/settings/Settings.tsx";
|
||||
|
||||
describe("PreferencesUserSettingsTab", () => {
|
||||
beforeEach(() => {
|
||||
mockPlatformPeg();
|
||||
});
|
||||
|
||||
const renderTab = (): RenderResult => {
|
||||
return render(<PreferencesUserSettingsTab closeSettingsFn={() => {}} />);
|
||||
};
|
||||
|
||||
it("should render", () => {
|
||||
const { asFragment } = renderTab();
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should reload when changing language", async () => {
|
||||
const reloadStub = jest.fn();
|
||||
PlatformPeg.get()!.reload = reloadStub;
|
||||
|
||||
renderTab();
|
||||
const languageDropdown = await screen.findByRole("button", { name: "Language Dropdown" });
|
||||
expect(languageDropdown).toBeInTheDocument();
|
||||
|
||||
await userEvent.click(languageDropdown);
|
||||
|
||||
const germanOption = await screen.findByText("Deutsch");
|
||||
await userEvent.click(germanOption);
|
||||
expect(reloadStub).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should search and select a user timezone", async () => {
|
||||
renderTab();
|
||||
|
||||
expect(await screen.findByText(/Browser default/)).toBeInTheDocument();
|
||||
const timezoneDropdown = await screen.findByRole("button", { name: "Set timezone" });
|
||||
await userEvent.click(timezoneDropdown);
|
||||
|
||||
// Without filtering `expect(screen.queryByRole("option" ...` take over 1s.
|
||||
await fireEvent.change(screen.getByRole("combobox", { name: "Set timezone" }), {
|
||||
target: { value: "Africa/Abidjan" },
|
||||
});
|
||||
|
||||
expect(screen.queryByRole("option", { name: "Africa/Abidjan" })).toBeInTheDocument();
|
||||
expect(screen.queryByRole("option", { name: "Europe/Paris" })).not.toBeInTheDocument();
|
||||
|
||||
await fireEvent.change(screen.getByRole("combobox", { name: "Set timezone" }), {
|
||||
target: { value: "Europe/Paris" },
|
||||
});
|
||||
|
||||
expect(screen.queryByRole("option", { name: "Africa/Abidjan" })).not.toBeInTheDocument();
|
||||
const option = await screen.getByRole("option", { name: "Europe/Paris" });
|
||||
await userEvent.click(option);
|
||||
|
||||
expect(await screen.findByText("Europe/Paris")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should not show spell check setting if unsupported", async () => {
|
||||
PlatformPeg.get()!.supportsSpellCheckSettings = jest.fn().mockReturnValue(false);
|
||||
|
||||
renderTab();
|
||||
expect(screen.queryByRole("switch", { name: "Allow spell check" })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should enable spell check", async () => {
|
||||
const spellCheckEnableFn = jest.fn();
|
||||
PlatformPeg.get()!.supportsSpellCheckSettings = jest.fn().mockReturnValue(true);
|
||||
PlatformPeg.get()!.getSpellCheckEnabled = jest.fn().mockReturnValue(false);
|
||||
PlatformPeg.get()!.setSpellCheckEnabled = spellCheckEnableFn;
|
||||
|
||||
renderTab();
|
||||
const toggle = await screen.findByRole("switch", { name: "Allow spell check" });
|
||||
expect(toggle).not.toBeDisabled();
|
||||
|
||||
await userEvent.click(toggle);
|
||||
|
||||
expect(spellCheckEnableFn).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
describe("send read receipts", () => {
|
||||
beforeEach(() => {
|
||||
stubClient();
|
||||
jest.spyOn(SettingsStore, "setValue");
|
||||
jest.spyOn(window, "matchMedia").mockReturnValue({ matches: false } as MediaQueryList);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
const getToggle = () => renderTab().getByRole("switch", { name: "Send read receipts" });
|
||||
|
||||
const mockIsVersionSupported = (val: boolean) => {
|
||||
const client = MatrixClientPeg.safeGet();
|
||||
jest.spyOn(client, "doesServerSupportUnstableFeature").mockResolvedValue(false);
|
||||
jest.spyOn(client, "isVersionSupported").mockImplementation(async (version: string) => {
|
||||
if (version === "v1.4") return val;
|
||||
return false;
|
||||
});
|
||||
MatrixClientBackedController.matrixClient = client;
|
||||
};
|
||||
|
||||
const mockGetValue = (val: boolean) => {
|
||||
const copyOfGetValueAt = SettingsStore.getValueAt;
|
||||
|
||||
SettingsStore.getValueAt = (
|
||||
level: SettingLevel,
|
||||
name: SettingKey,
|
||||
roomId?: string,
|
||||
isExplicit?: boolean,
|
||||
) => {
|
||||
if (name === "sendReadReceipts") return val;
|
||||
return copyOfGetValueAt(level, name, roomId, isExplicit);
|
||||
};
|
||||
};
|
||||
|
||||
const expectSetValueToHaveBeenCalled = (
|
||||
name: string,
|
||||
roomId: string | null,
|
||||
level: SettingLevel,
|
||||
value: boolean,
|
||||
) => expect(SettingsStore.setValue).toHaveBeenCalledWith(name, roomId, level, value);
|
||||
|
||||
describe("with server support", () => {
|
||||
beforeEach(() => {
|
||||
mockIsVersionSupported(true);
|
||||
});
|
||||
|
||||
it("can be enabled", async () => {
|
||||
mockGetValue(false);
|
||||
const toggle = getToggle();
|
||||
|
||||
await waitFor(() => expect(toggle).not.toBeDisabled());
|
||||
fireEvent.click(toggle);
|
||||
expectSetValueToHaveBeenCalled("sendReadReceipts", null, SettingLevel.ACCOUNT, true);
|
||||
});
|
||||
|
||||
it("can be disabled", async () => {
|
||||
mockGetValue(true);
|
||||
const toggle = getToggle();
|
||||
|
||||
await waitFor(() => expect(toggle).not.toBeDisabled());
|
||||
fireEvent.click(toggle);
|
||||
expectSetValueToHaveBeenCalled("sendReadReceipts", null, SettingLevel.ACCOUNT, false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("without server support", () => {
|
||||
beforeEach(() => {
|
||||
mockIsVersionSupported(false);
|
||||
});
|
||||
|
||||
it("is forcibly enabled", async () => {
|
||||
const toggle = getToggle();
|
||||
await waitFor(() => {
|
||||
expect(toggle).toBeChecked();
|
||||
expect(toggle).toBeDisabled();
|
||||
});
|
||||
});
|
||||
|
||||
it("cannot be disabled", async () => {
|
||||
mockGetValue(true);
|
||||
const toggle = getToggle();
|
||||
|
||||
await waitFor(() => expect(toggle).toBeDisabled());
|
||||
console.log(toggle.innerHTML);
|
||||
fireEvent.click(toggle);
|
||||
expect(SettingsStore.setValue).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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 { render, screen } from "jest-matrix-react";
|
||||
import React, { act } from "react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
import SecurityUserSettingsTab from "../../../../../../../src/components/views/settings/tabs/user/SecurityUserSettingsTab";
|
||||
import MatrixClientContext from "../../../../../../../src/contexts/MatrixClientContext";
|
||||
import {
|
||||
getMockClientWithEventEmitter,
|
||||
mockClientMethodsServer,
|
||||
mockClientMethodsUser,
|
||||
mockClientMethodsCrypto,
|
||||
mockClientMethodsDevice,
|
||||
mockPlatformPeg,
|
||||
} from "../../../../../../test-utils";
|
||||
import { SDKContext, SdkContextClass } from "../../../../../../../src/contexts/SDKContext";
|
||||
import defaultDispatcher from "../../../../../../../src/dispatcher/dispatcher";
|
||||
import { UIFeature } from "../../../../../../../src/settings/UIFeature";
|
||||
import SettingsStore from "../../../../../../../src/settings/SettingsStore";
|
||||
|
||||
describe("<SecurityUserSettingsTab />", () => {
|
||||
const defaultProps = {
|
||||
closeSettingsFn: jest.fn(),
|
||||
};
|
||||
|
||||
const getIgnoredUsers = jest.fn();
|
||||
const setIgnoredUsers = jest.fn();
|
||||
|
||||
const userId = "@alice:server.org";
|
||||
const deviceId = "alices-device";
|
||||
const mockClient = getMockClientWithEventEmitter({
|
||||
...mockClientMethodsUser(userId),
|
||||
...mockClientMethodsServer(),
|
||||
...mockClientMethodsDevice(deviceId),
|
||||
...mockClientMethodsCrypto(),
|
||||
getRooms: jest.fn().mockReturnValue([]),
|
||||
getPushers: jest.fn().mockReturnValue([]),
|
||||
getIgnoredUsers,
|
||||
setIgnoredUsers,
|
||||
});
|
||||
|
||||
const sdkContext = new SdkContextClass();
|
||||
sdkContext.client = mockClient;
|
||||
|
||||
const getComponent = () => (
|
||||
<MatrixClientContext.Provider value={mockClient}>
|
||||
<SDKContext.Provider value={sdkContext}>
|
||||
<SecurityUserSettingsTab {...defaultProps} />
|
||||
</SDKContext.Provider>
|
||||
</MatrixClientContext.Provider>
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
mockPlatformPeg();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it("renders security section", () => {
|
||||
const { container } = render(getComponent());
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders ignored users", () => {
|
||||
getIgnoredUsers.mockReturnValue(["@bob:example.org"]);
|
||||
const { getByRole } = render(getComponent());
|
||||
const ignoredUsers = getByRole("list", { name: "Ignored users" });
|
||||
|
||||
expect(ignoredUsers).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("allows unignoring a user", async () => {
|
||||
getIgnoredUsers.mockReturnValue(["@bob:example.org"]);
|
||||
const { getByText, getByRole } = render(getComponent());
|
||||
await userEvent.click(getByRole("button", { name: "Unignore" }));
|
||||
expect(setIgnoredUsers).toHaveBeenCalledWith([]);
|
||||
await act(() => {
|
||||
getIgnoredUsers.mockReturnValue([]);
|
||||
defaultDispatcher.dispatch(
|
||||
{
|
||||
action: "ignore_state_changed",
|
||||
},
|
||||
true,
|
||||
);
|
||||
});
|
||||
expect(getByText("You have no ignored users.")).toBeVisible();
|
||||
});
|
||||
|
||||
it("does not render privacy header if 3pid features are disabled", async () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((key: any): any => {
|
||||
if (key === UIFeature.ThirdPartyID) return false;
|
||||
});
|
||||
|
||||
render(getComponent());
|
||||
|
||||
expect(screen.queryByRole("heading", { name: "Privacy" })).toBeNull();
|
||||
});
|
||||
});
|
||||
+1678
File diff suppressed because it is too large
Load Diff
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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 { fireEvent, render, screen } from "jest-matrix-react";
|
||||
|
||||
import SidebarUserSettingsTab from "../../../../../../../src/components/views/settings/tabs/user/SidebarUserSettingsTab";
|
||||
import PosthogTrackers from "../../../../../../../src/PosthogTrackers";
|
||||
import SettingsStore from "../../../../../../../src/settings/SettingsStore";
|
||||
import { MetaSpace } from "../../../../../../../src/stores/spaces";
|
||||
import { SettingLevel } from "../../../../../../../src/settings/SettingLevel";
|
||||
import { flushPromises } from "../../../../../../test-utils";
|
||||
import SdkConfig from "../../../../../../../src/SdkConfig";
|
||||
|
||||
describe("<SidebarUserSettingsTab />", () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(PosthogTrackers, "trackInteraction").mockClear();
|
||||
jest.spyOn(SettingsStore, "getValue").mockRestore();
|
||||
jest.spyOn(SettingsStore, "setValue").mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
it("renders sidebar settings with guest spa url", () => {
|
||||
const spy = jest.spyOn(SdkConfig, "get").mockReturnValue({ guest_spa_url: "https://somewhere.org" });
|
||||
const originalGetValue = SettingsStore.getValue;
|
||||
const spySettingsStore = jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
|
||||
return setting === "feature_video_rooms" ? true : originalGetValue(setting);
|
||||
});
|
||||
const { container } = render(<SidebarUserSettingsTab />);
|
||||
expect(container).toMatchSnapshot();
|
||||
spySettingsStore.mockRestore();
|
||||
spy.mockRestore();
|
||||
});
|
||||
it("renders sidebar settings without guest spa url", () => {
|
||||
const originalGetValue = SettingsStore.getValue;
|
||||
const spySettingsStore = jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => {
|
||||
return setting === "feature_video_rooms" ? true : originalGetValue(setting);
|
||||
});
|
||||
const { container } = render(<SidebarUserSettingsTab />);
|
||||
expect(container).toMatchSnapshot();
|
||||
spySettingsStore.mockRestore();
|
||||
});
|
||||
|
||||
it("toggles all rooms in home setting", async () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName) => {
|
||||
if (settingName === "Spaces.enabledMetaSpaces") {
|
||||
return {
|
||||
[MetaSpace.Home]: true,
|
||||
[MetaSpace.Favourites]: true,
|
||||
[MetaSpace.People]: true,
|
||||
[MetaSpace.Orphans]: true,
|
||||
};
|
||||
}
|
||||
return false;
|
||||
});
|
||||
render(<SidebarUserSettingsTab />);
|
||||
|
||||
fireEvent.click(screen.getByTestId("mx_SidebarUserSettingsTab_homeAllRoomsCheckbox"));
|
||||
|
||||
await flushPromises();
|
||||
expect(SettingsStore.setValue).toHaveBeenCalledWith("Spaces.allRoomsInHome", null, SettingLevel.ACCOUNT, true);
|
||||
|
||||
expect(PosthogTrackers.trackInteraction).toHaveBeenCalledWith(
|
||||
"WebSettingsSidebarTabSpacesCheckbox",
|
||||
// synthetic event from checkbox
|
||||
expect.objectContaining({ type: "change" }),
|
||||
1,
|
||||
);
|
||||
});
|
||||
|
||||
it("disables all rooms in home setting when home space is disabled", () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName) => {
|
||||
if (settingName === "Spaces.enabledMetaSpaces") {
|
||||
return {
|
||||
[MetaSpace.Home]: false,
|
||||
[MetaSpace.Favourites]: true,
|
||||
[MetaSpace.People]: true,
|
||||
[MetaSpace.Orphans]: true,
|
||||
};
|
||||
}
|
||||
return false;
|
||||
});
|
||||
render(<SidebarUserSettingsTab />);
|
||||
|
||||
expect(screen.getByTestId("mx_SidebarUserSettingsTab_homeAllRoomsCheckbox")).toBeDisabled();
|
||||
});
|
||||
});
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
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 { mocked } from "jest-mock";
|
||||
import { fireEvent, render, screen } from "jest-matrix-react";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import VoiceUserSettingsTab from "../../../../../../../src/components/views/settings/tabs/user/VoiceUserSettingsTab";
|
||||
import MediaDeviceHandler, {
|
||||
type IMediaDevices,
|
||||
MediaDeviceKindEnum,
|
||||
} from "../../../../../../../src/MediaDeviceHandler";
|
||||
import { flushPromises } from "../../../../../../test-utils";
|
||||
|
||||
jest.mock("../../../../../../../src/MediaDeviceHandler");
|
||||
const MediaDeviceHandlerMock = mocked(MediaDeviceHandler);
|
||||
|
||||
describe("<VoiceUserSettingsTab />", () => {
|
||||
const getComponent = (): React.ReactElement => <VoiceUserSettingsTab />;
|
||||
|
||||
const audioIn1 = {
|
||||
deviceId: "1",
|
||||
groupId: "g1",
|
||||
kind: MediaDeviceKindEnum.AudioInput,
|
||||
label: "Audio input test 1",
|
||||
};
|
||||
const videoIn1 = {
|
||||
deviceId: "2",
|
||||
groupId: "g1",
|
||||
kind: MediaDeviceKindEnum.VideoInput,
|
||||
label: "Video input test 1",
|
||||
};
|
||||
const videoIn2 = {
|
||||
deviceId: "3",
|
||||
groupId: "g1",
|
||||
kind: MediaDeviceKindEnum.VideoInput,
|
||||
label: "Video input test 2",
|
||||
};
|
||||
const defaultMediaDevices = {
|
||||
[MediaDeviceKindEnum.AudioOutput]: [],
|
||||
[MediaDeviceKindEnum.AudioInput]: [audioIn1],
|
||||
[MediaDeviceKindEnum.VideoInput]: [videoIn1, videoIn2],
|
||||
} as unknown as IMediaDevices;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
MediaDeviceHandlerMock.hasAnyLabeledDevices.mockResolvedValue(true);
|
||||
MediaDeviceHandlerMock.getDevices.mockResolvedValue(defaultMediaDevices);
|
||||
MediaDeviceHandlerMock.getVideoInput.mockReturnValue(videoIn1.deviceId);
|
||||
|
||||
// @ts-ignore bad mocking
|
||||
MediaDeviceHandlerMock.instance = { setDevice: jest.fn().mockResolvedValue(undefined) };
|
||||
});
|
||||
|
||||
describe("devices", () => {
|
||||
it("renders dropdowns for input devices", async () => {
|
||||
render(getComponent());
|
||||
|
||||
await expect(screen.findByLabelText("Microphone")).resolves.toHaveDisplayValue(audioIn1.label);
|
||||
await expect(screen.findByLabelText("Camera")).resolves.toHaveDisplayValue(videoIn1.label);
|
||||
});
|
||||
|
||||
it("updates device", async () => {
|
||||
render(getComponent());
|
||||
await flushPromises();
|
||||
|
||||
fireEvent.change(await screen.findByLabelText("Camera"), { target: { value: videoIn2.deviceId } });
|
||||
|
||||
expect(MediaDeviceHandlerMock.instance.setDevice).toHaveBeenCalledWith(
|
||||
videoIn2.deviceId,
|
||||
MediaDeviceKindEnum.VideoInput,
|
||||
);
|
||||
|
||||
expect(screen.getByLabelText("Camera")).toHaveDisplayValue(videoIn2.label);
|
||||
});
|
||||
|
||||
it("logs and resets device when update fails", async () => {
|
||||
// stub to avoid littering console with expected error
|
||||
jest.spyOn(logger, "error").mockImplementation(() => {});
|
||||
MediaDeviceHandlerMock.instance.setDevice.mockRejectedValue("oups!");
|
||||
render(getComponent());
|
||||
await flushPromises();
|
||||
|
||||
fireEvent.change(screen.getByLabelText("Camera"), { target: { value: videoIn2.deviceId } });
|
||||
|
||||
expect(MediaDeviceHandlerMock.instance.setDevice).toHaveBeenCalledWith(
|
||||
videoIn2.deviceId,
|
||||
MediaDeviceKindEnum.VideoInput,
|
||||
);
|
||||
|
||||
expect(screen.getByLabelText("Camera")).toHaveDisplayValue(videoIn2.label);
|
||||
|
||||
await flushPromises();
|
||||
|
||||
expect(logger.error).toHaveBeenCalledWith("Failed to set device videoinput: 3");
|
||||
// reset to original
|
||||
expect(screen.getByLabelText("Camera")).toHaveDisplayValue(videoIn1.label);
|
||||
});
|
||||
|
||||
it("does not render dropdown when no devices exist for type", async () => {
|
||||
render(getComponent());
|
||||
await flushPromises();
|
||||
|
||||
expect(screen.getByText("No Audio Outputs detected")).toBeInTheDocument();
|
||||
expect(screen.queryByLabelText("Audio Output")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it("renders audio processing settings", () => {
|
||||
const { getByRole } = render(getComponent());
|
||||
expect(getByRole("switch", { name: "Automatically adjust the microphone volume" })).toBeTruthy();
|
||||
expect(getByRole("switch", { name: "Noise suppression" })).toBeTruthy();
|
||||
expect(getByRole("switch", { name: "Echo cancellation" })).toBeTruthy();
|
||||
});
|
||||
|
||||
it("sets and displays audio processing settings", () => {
|
||||
MediaDeviceHandlerMock.getAudioAutoGainControl.mockReturnValue(false);
|
||||
MediaDeviceHandlerMock.getAudioEchoCancellation.mockReturnValue(true);
|
||||
MediaDeviceHandlerMock.getAudioNoiseSuppression.mockReturnValue(false);
|
||||
|
||||
const { getByRole } = render(getComponent());
|
||||
|
||||
getByRole("switch", { name: "Automatically adjust the microphone volume" }).click();
|
||||
getByRole("switch", { name: "Noise suppression" }).click();
|
||||
getByRole("switch", { name: "Echo cancellation" }).click();
|
||||
|
||||
expect(MediaDeviceHandler.setAudioAutoGainControl).toHaveBeenCalledWith(true);
|
||||
expect(MediaDeviceHandler.setAudioEchoCancellation).toHaveBeenCalledWith(false);
|
||||
expect(MediaDeviceHandler.setAudioNoiseSuppression).toHaveBeenCalledWith(true);
|
||||
});
|
||||
});
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<AccountUserSettingsTab /> 3pids should display 3pid email addresses and phone numbers 1`] = `
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
data-testid="mx_AccountEmailAddresses"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Email addresses
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content mx_SettingsSubsection_contentStretch"
|
||||
>
|
||||
<div
|
||||
class="mx_AddRemoveThreepids_existing"
|
||||
>
|
||||
<span
|
||||
class="mx_AddRemoveThreepids_existing_address"
|
||||
>
|
||||
test@test.io
|
||||
</span>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_danger_sm"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Remove
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
autocomplete="off"
|
||||
novalidate=""
|
||||
>
|
||||
<div
|
||||
class="mx_Field mx_Field_input"
|
||||
>
|
||||
<input
|
||||
autocomplete="email"
|
||||
id="mx_Field_3"
|
||||
label="Email Address"
|
||||
placeholder="Email Address"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<label
|
||||
for="mx_Field_3"
|
||||
>
|
||||
Email Address
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Add
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<AccountUserSettingsTab /> 3pids should display 3pid email addresses and phone numbers 2`] = `
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
data-testid="mx_AccountPhoneNumbers"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Phone numbers
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content mx_SettingsSubsection_contentStretch"
|
||||
>
|
||||
<div
|
||||
class="mx_AddRemoveThreepids_existing"
|
||||
>
|
||||
<span
|
||||
class="mx_AddRemoveThreepids_existing_address"
|
||||
>
|
||||
123456789
|
||||
</span>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_danger_sm"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Remove
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
autocomplete="off"
|
||||
novalidate=""
|
||||
>
|
||||
<div
|
||||
class="mx_Field mx_Field_input mx_Field_labelAlwaysTopLeft"
|
||||
>
|
||||
<span
|
||||
class="mx_Field_prefix"
|
||||
>
|
||||
<div
|
||||
class="mx_Dropdown mx_PhoneNumbers_country mx_CountryDropdown"
|
||||
>
|
||||
<div
|
||||
aria-describedby="mx_CountryDropdown_value"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-label="Country Dropdown"
|
||||
aria-owns="mx_CountryDropdown_input"
|
||||
class="mx_AccessibleButton mx_Dropdown_input mx_no_textinput"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="mx_Dropdown_option"
|
||||
id="mx_CountryDropdown_value"
|
||||
>
|
||||
<span
|
||||
class="mx_CountryDropdown_shortOption"
|
||||
>
|
||||
<div
|
||||
class="mx_Dropdown_option_emoji"
|
||||
>
|
||||
🇺🇸
|
||||
</div>
|
||||
+1
|
||||
</span>
|
||||
</div>
|
||||
<svg
|
||||
class="mx_Dropdown_arrow"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
<input
|
||||
autocomplete="tel-national"
|
||||
id="mx_Field_4"
|
||||
label="Phone Number"
|
||||
placeholder="Phone Number"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<label
|
||||
for="mx_Field_4"
|
||||
>
|
||||
Phone Number
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Add
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<AccountUserSettingsTab /> deactivate account should render section when account deactivation feature is enabled 1`] = `
|
||||
<div
|
||||
class="mx_SettingsSection"
|
||||
>
|
||||
<h2
|
||||
class="mx_Heading_h3"
|
||||
>
|
||||
Deactivate Account
|
||||
</h2>
|
||||
<div
|
||||
class="mx_SettingsSection_subSections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
data-testid="account-management-section"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Account management
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_description"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection_text"
|
||||
>
|
||||
Deactivating your account is a permanent action — be careful!
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_danger"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Deactivate Account
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
+907
@@ -0,0 +1,907 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`AppearanceUserSettingsTab should render 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_SettingsTab"
|
||||
data-testid="mx_AppearanceUserSettingsTab"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsTab_sections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection_subSections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection mx_SettingsSubsection_newUi"
|
||||
data-testid="themePanel"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Theme
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content mx_SettingsSubsection_content_newUi"
|
||||
>
|
||||
<form
|
||||
class="_root_19upo_16 mx_ThemeChoicePanel_ThemeSelectors"
|
||||
>
|
||||
<div
|
||||
class="_inline-field_19upo_32 mx_ThemeChoicePanel_themeSelector mx_ThemeChoicePanel_themeSelector_disabled cpd-theme-light"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_1ug7n_10"
|
||||
>
|
||||
<input
|
||||
class="_input_1ug7n_18"
|
||||
disabled=""
|
||||
id="radix-_r_0_"
|
||||
name="themeSelector"
|
||||
title=""
|
||||
type="radio"
|
||||
value="light"
|
||||
/>
|
||||
<div
|
||||
class="_ui_1ug7n_19"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
|
||||
for="radix-_r_0_"
|
||||
>
|
||||
Light
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field_19upo_32 mx_ThemeChoicePanel_themeSelector mx_ThemeChoicePanel_themeSelector_disabled cpd-theme-dark"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_1ug7n_10"
|
||||
>
|
||||
<input
|
||||
class="_input_1ug7n_18"
|
||||
disabled=""
|
||||
id="radix-_r_1_"
|
||||
name="themeSelector"
|
||||
title=""
|
||||
type="radio"
|
||||
value="dark"
|
||||
/>
|
||||
<div
|
||||
class="_ui_1ug7n_19"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
|
||||
for="radix-_r_1_"
|
||||
>
|
||||
Dark
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field_19upo_32 mx_ThemeChoicePanel_themeSelector mx_ThemeChoicePanel_themeSelector_disabled cpd-theme-light"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_1ug7n_10"
|
||||
>
|
||||
<input
|
||||
class="_input_1ug7n_18"
|
||||
disabled=""
|
||||
id="radix-_r_2_"
|
||||
name="themeSelector"
|
||||
title=""
|
||||
type="radio"
|
||||
value="light-high-contrast"
|
||||
/>
|
||||
<div
|
||||
class="_ui_1ug7n_19"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59 mx_ThemeChoicePanel_themeSelector_Label"
|
||||
for="radix-_r_2_"
|
||||
>
|
||||
High contrast
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div
|
||||
class="_separator_cqpyv_8"
|
||||
data-kind="primary"
|
||||
data-orientation="horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection mx_SettingsSubsection_newUi"
|
||||
data-testid="layoutPanel"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Message layout
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content mx_SettingsSubsection_content_newUi"
|
||||
>
|
||||
<form
|
||||
class="_root_19upo_16 mx_LayoutSwitcher_LayoutSelector"
|
||||
>
|
||||
<div
|
||||
class="_field_19upo_26 mxLayoutSwitcher_LayoutSelector_LayoutRadio"
|
||||
>
|
||||
<label
|
||||
aria-label="Modern"
|
||||
class="_label_19upo_59"
|
||||
for="radix-_r_3_"
|
||||
>
|
||||
<div
|
||||
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline"
|
||||
>
|
||||
<div
|
||||
class="_container_1ug7n_10"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="_input_1ug7n_18"
|
||||
id="radix-_r_3_"
|
||||
name="layout"
|
||||
title=""
|
||||
type="radio"
|
||||
value="group"
|
||||
/>
|
||||
<div
|
||||
class="_ui_1ug7n_19"
|
||||
/>
|
||||
</div>
|
||||
<span>
|
||||
Modern
|
||||
</span>
|
||||
</div>
|
||||
<hr
|
||||
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_separator"
|
||||
/>
|
||||
<div
|
||||
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_EventTilePreview"
|
||||
role="presentation"
|
||||
>
|
||||
<div
|
||||
aria-atomic="true"
|
||||
aria-live="off"
|
||||
class="mx_EventTile"
|
||||
data-event-id="$9999999999999999999999999999999999999999999"
|
||||
data-has-reply="false"
|
||||
data-layout="group"
|
||||
data-scroll-tokens="$9999999999999999999999999999999999999999999"
|
||||
data-self="true"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_DisambiguatedProfile _disambiguatedProfile_oa3at_8"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="mx_Username_color2 _disambiguatedProfile_displayName_oa3at_14 mx_DisambiguatedProfile_displayName"
|
||||
dir="auto"
|
||||
>
|
||||
@userId:matrix.org
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_EventTile_avatar"
|
||||
>
|
||||
<span
|
||||
class="_avatar_zysgz_8 mx_BaseAvatar _avatar-imageless_zysgz_55"
|
||||
data-color="2"
|
||||
data-testid="avatar-img"
|
||||
data-type="round"
|
||||
role="presentation"
|
||||
style="--cpd-avatar-size: 30px;"
|
||||
title="@userId:matrix.org"
|
||||
>
|
||||
u
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_EventTile_line"
|
||||
id="1"
|
||||
>
|
||||
<div
|
||||
class="mx_MTextBody mx_EventTile_content"
|
||||
>
|
||||
<div
|
||||
class="mx_EventTile_body translate"
|
||||
dir="auto"
|
||||
>
|
||||
Hey you. You're the best!
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Message Actions"
|
||||
aria-live="off"
|
||||
class="mx_MessageActionBar"
|
||||
role="toolbar"
|
||||
>
|
||||
<div
|
||||
aria-label="Edit"
|
||||
class="mx_AccessibleButton mx_MessageActionBar_iconButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M15.706 2.637a2 2 0 0 1 2.829 0l2.828 2.828a2 2 0 0 1 0 2.829L9.605 20.052a1 1 0 0 1-.465.263L3.483 21.73a1 1 0 0 1-1.212-1.213l1.414-5.657a1 1 0 0 1 .263-.465zm1.224 7.262L14.102 7.07l-8.544 8.544-.943 3.771 3.771-.943z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-label="Options"
|
||||
class="mx_AccessibleButton mx_MessageActionBar_iconButton mx_MessageActionBar_optionsButton"
|
||||
role="button"
|
||||
tabindex="-1"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="_field_19upo_26 mxLayoutSwitcher_LayoutSelector_LayoutRadio"
|
||||
>
|
||||
<label
|
||||
aria-label="Message bubbles"
|
||||
class="_label_19upo_59"
|
||||
for="radix-_r_c_"
|
||||
>
|
||||
<div
|
||||
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline"
|
||||
>
|
||||
<div
|
||||
class="_container_1ug7n_10"
|
||||
>
|
||||
<input
|
||||
class="_input_1ug7n_18"
|
||||
id="radix-_r_c_"
|
||||
name="layout"
|
||||
title=""
|
||||
type="radio"
|
||||
value="bubble"
|
||||
/>
|
||||
<div
|
||||
class="_ui_1ug7n_19"
|
||||
/>
|
||||
</div>
|
||||
<span>
|
||||
Message bubbles
|
||||
</span>
|
||||
</div>
|
||||
<hr
|
||||
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_separator"
|
||||
/>
|
||||
<div
|
||||
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_EventTilePreview"
|
||||
role="presentation"
|
||||
>
|
||||
<div
|
||||
aria-atomic="true"
|
||||
aria-live="off"
|
||||
class="mx_EventTile"
|
||||
data-event-id="$9999999999999999999999999999999999999999999"
|
||||
data-has-reply="false"
|
||||
data-layout="bubble"
|
||||
data-scroll-tokens="$9999999999999999999999999999999999999999999"
|
||||
data-self="true"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
class="mx_DisambiguatedProfile _disambiguatedProfile_oa3at_8"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="mx_Username_color2 _disambiguatedProfile_displayName_oa3at_14 mx_DisambiguatedProfile_displayName"
|
||||
dir="auto"
|
||||
>
|
||||
@userId:matrix.org
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_EventTile_avatar"
|
||||
>
|
||||
<span
|
||||
class="_avatar_zysgz_8 mx_BaseAvatar _avatar-imageless_zysgz_55"
|
||||
data-color="2"
|
||||
data-testid="avatar-img"
|
||||
data-type="round"
|
||||
role="presentation"
|
||||
style="--cpd-avatar-size: 30px;"
|
||||
title="@userId:matrix.org"
|
||||
>
|
||||
u
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_EventTile_line"
|
||||
id="2"
|
||||
>
|
||||
<div
|
||||
class="mx_MTextBody mx_EventTile_content"
|
||||
>
|
||||
<div
|
||||
class="mx_EventTile_body translate"
|
||||
dir="auto"
|
||||
>
|
||||
Hey you. You're the best!
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Message Actions"
|
||||
aria-live="off"
|
||||
class="mx_MessageActionBar"
|
||||
role="toolbar"
|
||||
>
|
||||
<div
|
||||
aria-label="Edit"
|
||||
class="mx_AccessibleButton mx_MessageActionBar_iconButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M15.706 2.637a2 2 0 0 1 2.829 0l2.828 2.828a2 2 0 0 1 0 2.829L9.605 20.052a1 1 0 0 1-.465.263L3.483 21.73a1 1 0 0 1-1.212-1.213l1.414-5.657a1 1 0 0 1 .263-.465zm1.224 7.262L14.102 7.07l-8.544 8.544-.943 3.771 3.771-.943z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-label="Options"
|
||||
class="mx_AccessibleButton mx_MessageActionBar_iconButton mx_MessageActionBar_optionsButton"
|
||||
role="button"
|
||||
tabindex="-1"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="_field_19upo_26 mxLayoutSwitcher_LayoutSelector_LayoutRadio"
|
||||
>
|
||||
<label
|
||||
aria-label="IRC (experimental)"
|
||||
class="_label_19upo_59"
|
||||
for="radix-_r_l_"
|
||||
>
|
||||
<div
|
||||
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_inline"
|
||||
>
|
||||
<div
|
||||
class="_container_1ug7n_10"
|
||||
>
|
||||
<input
|
||||
class="_input_1ug7n_18"
|
||||
id="radix-_r_l_"
|
||||
name="layout"
|
||||
title=""
|
||||
type="radio"
|
||||
value="irc"
|
||||
/>
|
||||
<div
|
||||
class="_ui_1ug7n_19"
|
||||
/>
|
||||
</div>
|
||||
<span>
|
||||
IRC (experimental)
|
||||
</span>
|
||||
</div>
|
||||
<hr
|
||||
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_separator"
|
||||
/>
|
||||
<div
|
||||
class="mxLayoutSwitcher_LayoutSelector_LayoutRadio_EventTilePreview mx_IRCLayout"
|
||||
role="presentation"
|
||||
>
|
||||
<div
|
||||
aria-atomic="true"
|
||||
aria-live="off"
|
||||
class="mx_EventTile"
|
||||
data-event-id="$9999999999999999999999999999999999999999999"
|
||||
data-has-reply="false"
|
||||
data-layout="irc"
|
||||
data-scroll-tokens="$9999999999999999999999999999999999999999999"
|
||||
data-self="true"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
class="mx_MessageTimestamp"
|
||||
/>
|
||||
<div
|
||||
class="mx_DisambiguatedProfile _disambiguatedProfile_oa3at_8"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="mx_Username_color2 _disambiguatedProfile_displayName_oa3at_14 mx_DisambiguatedProfile_displayName"
|
||||
dir="auto"
|
||||
>
|
||||
@userId:matrix.org
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_EventTile_avatar"
|
||||
>
|
||||
<span
|
||||
class="_avatar_zysgz_8 mx_BaseAvatar _avatar-imageless_zysgz_55"
|
||||
data-color="2"
|
||||
data-testid="avatar-img"
|
||||
data-type="round"
|
||||
role="presentation"
|
||||
style="--cpd-avatar-size: 14px;"
|
||||
title="@userId:matrix.org"
|
||||
>
|
||||
u
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_EventTile_line"
|
||||
id="3"
|
||||
>
|
||||
<div
|
||||
class="mx_MTextBody mx_EventTile_content"
|
||||
>
|
||||
<div
|
||||
class="mx_EventTile_body translate"
|
||||
dir="auto"
|
||||
>
|
||||
Hey you. You're the best!
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
aria-label="Message Actions"
|
||||
aria-live="off"
|
||||
class="mx_MessageActionBar"
|
||||
role="toolbar"
|
||||
>
|
||||
<div
|
||||
aria-label="Edit"
|
||||
class="mx_AccessibleButton mx_MessageActionBar_iconButton"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M15.706 2.637a2 2 0 0 1 2.829 0l2.828 2.828a2 2 0 0 1 0 2.829L9.605 20.052a1 1 0 0 1-.465.263L3.483 21.73a1 1 0 0 1-1.212-1.213l1.414-5.657a1 1 0 0 1 .263-.465zm1.224 7.262L14.102 7.07l-8.544 8.544-.943 3.771 3.771-.943z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-label="Options"
|
||||
class="mx_AccessibleButton mx_MessageActionBar_iconButton mx_MessageActionBar_optionsButton"
|
||||
role="button"
|
||||
tabindex="-1"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
<form
|
||||
class="_root_19upo_16"
|
||||
>
|
||||
<div
|
||||
class="_inline-field_19upo_32"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_udcm8_10"
|
||||
>
|
||||
<input
|
||||
aria-describedby="radix-_r_v_"
|
||||
class="_input_udcm8_24"
|
||||
id="radix-_r_u_"
|
||||
name="compactLayout"
|
||||
role="switch"
|
||||
title=""
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
class="_ui_udcm8_34"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59"
|
||||
for="radix-_r_u_"
|
||||
>
|
||||
Show compact text and messages
|
||||
</label>
|
||||
<span
|
||||
class="_message_19upo_85 _help-message_19upo_91"
|
||||
id="radix-_r_v_"
|
||||
>
|
||||
Modern layout must be selected to use this feature.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div
|
||||
class="_separator_cqpyv_8"
|
||||
data-kind="primary"
|
||||
data-orientation="horizontal"
|
||||
role="separator"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
data-testid="mx_FontScalingPanel"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Font size
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content mx_SettingsSubsection_contentStretch"
|
||||
>
|
||||
<div
|
||||
class="mx_Field mx_Field_select mx_FontScalingPanel_Dropdown"
|
||||
>
|
||||
<select
|
||||
id="mx_Field_1"
|
||||
label="Font size"
|
||||
placeholder="Font size"
|
||||
type="text"
|
||||
>
|
||||
<option
|
||||
value="-7"
|
||||
>
|
||||
9
|
||||
</option>
|
||||
<option
|
||||
value="-6"
|
||||
>
|
||||
10
|
||||
</option>
|
||||
<option
|
||||
value="-5"
|
||||
>
|
||||
11
|
||||
</option>
|
||||
<option
|
||||
value="-4"
|
||||
>
|
||||
12
|
||||
</option>
|
||||
<option
|
||||
value="-3"
|
||||
>
|
||||
13
|
||||
</option>
|
||||
<option
|
||||
value="-2"
|
||||
>
|
||||
14
|
||||
</option>
|
||||
<option
|
||||
value="-1"
|
||||
>
|
||||
15
|
||||
</option>
|
||||
<option
|
||||
value="0"
|
||||
>
|
||||
16 (default)
|
||||
</option>
|
||||
<option
|
||||
value="1"
|
||||
>
|
||||
17
|
||||
</option>
|
||||
<option
|
||||
value="2"
|
||||
>
|
||||
18
|
||||
</option>
|
||||
<option
|
||||
value="4"
|
||||
>
|
||||
20
|
||||
</option>
|
||||
<option
|
||||
value="6"
|
||||
>
|
||||
22
|
||||
</option>
|
||||
<option
|
||||
value="8"
|
||||
>
|
||||
24
|
||||
</option>
|
||||
<option
|
||||
value="10"
|
||||
>
|
||||
26
|
||||
</option>
|
||||
<option
|
||||
value="12"
|
||||
>
|
||||
28
|
||||
</option>
|
||||
<option
|
||||
value="14"
|
||||
>
|
||||
30
|
||||
</option>
|
||||
<option
|
||||
value="16"
|
||||
>
|
||||
32
|
||||
</option>
|
||||
<option
|
||||
value="18"
|
||||
>
|
||||
34
|
||||
</option>
|
||||
<option
|
||||
value="20"
|
||||
>
|
||||
36
|
||||
</option>
|
||||
</select>
|
||||
<label
|
||||
for="mx_Field_1"
|
||||
>
|
||||
Font size
|
||||
</label>
|
||||
<svg
|
||||
class="mx_Field_select_chevron"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="mx_FontScalingPanel_preview mx_EventTilePreview_loader"
|
||||
>
|
||||
<div
|
||||
class="mx_Spinner"
|
||||
>
|
||||
<svg
|
||||
aria-label="Loading…"
|
||||
class="_icon_11k6c_18"
|
||||
data-testid="spinner"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
role="progressbar"
|
||||
style="width: 32px; height: 32px;"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M12 4.031a8 8 0 1 0 8 8 1 1 0 0 1 2 0c0 5.523-4.477 10-10 10s-10-4.477-10-10 4.477-10 10-10a1 1 0 1 1 0 2"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content mx_SettingsSubsection_noHeading"
|
||||
>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Show advanced
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Image size in the timeline
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
>
|
||||
<div
|
||||
class="mx_ImageSizePanel_radios"
|
||||
>
|
||||
<label>
|
||||
<div
|
||||
class="mx_ImageSizePanel_size"
|
||||
/>
|
||||
<label
|
||||
class="mx_StyledRadioButton mx_StyledRadioButton_enabled mx_StyledRadioButton_checked"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
name="image_size"
|
||||
type="radio"
|
||||
value="normal"
|
||||
/>
|
||||
<div>
|
||||
<div />
|
||||
</div>
|
||||
<div
|
||||
class="mx_StyledRadioButton_content"
|
||||
>
|
||||
Default
|
||||
</div>
|
||||
<div
|
||||
class="mx_StyledRadioButton_spacer"
|
||||
/>
|
||||
</label>
|
||||
</label>
|
||||
<label>
|
||||
<div
|
||||
class="mx_ImageSizePanel_size"
|
||||
/>
|
||||
<label
|
||||
class="mx_StyledRadioButton mx_StyledRadioButton_enabled"
|
||||
>
|
||||
<input
|
||||
name="image_size"
|
||||
type="radio"
|
||||
value="large"
|
||||
/>
|
||||
<div>
|
||||
<div />
|
||||
</div>
|
||||
<div
|
||||
class="mx_StyledRadioButton_content"
|
||||
>
|
||||
Large
|
||||
</div>
|
||||
<div
|
||||
class="mx_StyledRadioButton_spacer"
|
||||
/>
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
+431
@@ -0,0 +1,431 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<EncryptionUserSettingsTab /> should display a verify button when the encryption is not set up 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_SettingsTab mx_EncryptionUserSettingsTab"
|
||||
data-testid="encryptionTab"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsTab_sections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection mx_SettingsSection_newUi"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection_header"
|
||||
>
|
||||
<h2
|
||||
class="_typography_6v6n8_153 _font-heading-sm-semibold_6v6n8_93 mx_SettingsHeader"
|
||||
>
|
||||
Device not verified
|
||||
</h2>
|
||||
<div
|
||||
class="mx_SettingsSubheader"
|
||||
>
|
||||
<span
|
||||
class="mx_SettingsSubheader_error"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="20px"
|
||||
viewBox="0 0 24 24"
|
||||
width="20px"
|
||||
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>
|
||||
You need to verify this device in order to view your encryption settings.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="_button_13vu4_8 _has-icon_13vu4_60"
|
||||
data-kind="primary"
|
||||
data-size="sm"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
width="20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M4 18q-.824 0-1.412-.587A1.93 1.93 0 0 1 2 16V5q0-.824.587-1.412A1.93 1.93 0 0 1 4 3h16q.824 0 1.413.587Q22 4.176 22 5v11q0 .824-.587 1.413A1.93 1.93 0 0 1 20 18zm0-2h16V5H4zm-2 5a.97.97 0 0 1-.712-.288A.97.97 0 0 1 1 20q0-.424.288-.712A.97.97 0 0 1 2 19h20q.424 0 .712.288.288.287.288.712 0 .424-.288.712A.97.97 0 0 1 22 21z"
|
||||
/>
|
||||
</svg>
|
||||
Verify this device
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<EncryptionUserSettingsTab /> should display the change recovery key panel when the user clicks on the change recovery button 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_SettingsTab mx_EncryptionUserSettingsTab"
|
||||
data-testid="encryptionTab"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsTab_sections"
|
||||
/>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<EncryptionUserSettingsTab /> should display the identity needs reset panel when the user's identity needs resetting 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_SettingsTab mx_EncryptionUserSettingsTab"
|
||||
data-testid="encryptionTab"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsTab_sections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection mx_SettingsSection_newUi"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection_header"
|
||||
>
|
||||
<h2
|
||||
class="_typography_6v6n8_153 _font-heading-sm-semibold_6v6n8_93 mx_SettingsHeader"
|
||||
>
|
||||
Your key storage is out of sync.
|
||||
</h2>
|
||||
<div
|
||||
class="mx_SettingsSubheader"
|
||||
>
|
||||
<span
|
||||
class="mx_SettingsSubheader_error"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="20px"
|
||||
viewBox="0 0 24 24"
|
||||
width="20px"
|
||||
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>
|
||||
You have to reset your cryptographic identity in order to ensure access to your message history
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="_button_13vu4_8"
|
||||
data-kind="primary"
|
||||
data-size="sm"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Continue with reset
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<EncryptionUserSettingsTab /> should display the recovery out of sync panel when secrets are not cached 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_SettingsTab mx_EncryptionUserSettingsTab"
|
||||
data-testid="encryptionTab"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsTab_sections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection mx_SettingsSection_newUi"
|
||||
data-testid="recoveryPanel"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection_header"
|
||||
>
|
||||
<h2
|
||||
class="_typography_6v6n8_153 _font-heading-sm-semibold_6v6n8_93 mx_SettingsHeader"
|
||||
>
|
||||
Recovery
|
||||
</h2>
|
||||
<div
|
||||
class="mx_SettingsSubheader"
|
||||
>
|
||||
Recover your cryptographic identity and message history with a recovery key if you’ve lost all your existing devices.
|
||||
<span
|
||||
class="mx_SettingsSubheader_error"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="20px"
|
||||
viewBox="0 0 24 24"
|
||||
width="20px"
|
||||
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>
|
||||
Your key storage is out of sync. Click one of the buttons below to fix the problem.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_RecoveryPanelOutOfSync"
|
||||
>
|
||||
<button
|
||||
class="_button_13vu4_8"
|
||||
data-kind="secondary"
|
||||
data-size="sm"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Forgot recovery key?
|
||||
</button>
|
||||
<button
|
||||
class="_button_13vu4_8 _has-icon_13vu4_60"
|
||||
data-kind="primary"
|
||||
data-size="sm"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
width="20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 5 12q0-.825.588-1.412A1.93 1.93 0 0 1 7 10q.824 0 1.412.588Q9 11.175 9 12t-.588 1.412A1.93 1.93 0 0 1 7 14m0 4q-2.5 0-4.25-1.75T1 12t1.75-4.25T7 6q1.676 0 3.037.825A6.2 6.2 0 0 1 12.2 9h8.375q.2 0 .387.075.188.075.338.225l2 2q.15.15.212.325.063.175.063.375t-.062.375a.9.9 0 0 1-.213.325l-3.175 3.175a1 1 0 0 1-.3.2q-.175.075-.35.1a.8.8 0 0 1-.35-.025.9.9 0 0 1-.325-.175L17.5 15l-1.425 1.075a.95.95 0 0 1-.887.15.9.9 0 0 1-.288-.15L13.375 15H12.2a6.2 6.2 0 0 1-2.162 2.175Q8.675 18 7 18m0-2q1.4 0 2.463-.85A4.03 4.03 0 0 0 10.875 13H14l1.45 1.025L17.5 12.5l1.775 1.375L21.15 12l-1-1h-9.275a4.03 4.03 0 0 0-1.412-2.15Q8.4 8 7 8 5.35 8 4.175 9.175T3 12t1.175 2.825T7 16"
|
||||
/>
|
||||
</svg>
|
||||
Enter recovery key
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<EncryptionUserSettingsTab /> should display the reset identity panel when the user clicks on the reset cryptographic identity panel 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_SettingsTab mx_EncryptionUserSettingsTab"
|
||||
data-testid="encryptionTab"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsTab_sections"
|
||||
>
|
||||
<nav
|
||||
class="_breadcrumb_1xygz_8"
|
||||
>
|
||||
<button
|
||||
aria-label="Back"
|
||||
class="_icon-button_1215g_8"
|
||||
data-kind="secondary"
|
||||
role="button"
|
||||
style="--cpd-icon-button-size: 28px;"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="_indicator-icon_147l5_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"
|
||||
>
|
||||
Reset encryption
|
||||
</span>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<div
|
||||
class="mx_EncryptionCard"
|
||||
>
|
||||
<div
|
||||
class="mx_EncryptionCard_header"
|
||||
>
|
||||
<div
|
||||
class="_content_1r8kr_8 _destructive_1r8kr_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 reset your identity?
|
||||
</h2>
|
||||
</div>
|
||||
<div
|
||||
class="_flex_4dswl_9 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;"
|
||||
>
|
||||
<ul
|
||||
class="_visual-list_1mgc1_8"
|
||||
>
|
||||
<li
|
||||
class="_visual-list-item_1nc1y_8"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="_visual-list-item-icon_1nc1y_17 _visual-list-item-icon-success_1nc1y_22"
|
||||
fill="currentColor"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.55 17.575q-.2 0-.375-.062a.9.9 0 0 1-.325-.213L4.55 13q-.274-.274-.262-.713.012-.437.287-.712a.95.95 0 0 1 .7-.275q.425 0 .7.275L9.55 15.15l8.475-8.475q.274-.275.713-.275.437 0 .712.275.275.274.275.713 0 .437-.275.712l-9.2 9.2q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
Your account details, contacts, preferences, and chat list will be kept
|
||||
</li>
|
||||
<li
|
||||
class="_visual-list-item_1nc1y_8"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="_visual-list-item-icon_1nc1y_17"
|
||||
fill="currentColor"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.288 7.288A.97.97 0 0 1 12 7q.424 0 .713.287Q13 7.576 13 8t-.287.713A.97.97 0 0 1 12 9a.97.97 0 0 1-.713-.287A.97.97 0 0 1 11 8q0-.424.287-.713m.001 4.001A.97.97 0 0 1 12 11q.424 0 .713.287.287.288.287.713v4q0 .424-.287.712A.97.97 0 0 1 12 17a.97.97 0 0 1-.713-.288A.97.97 0 0 1 11 16v-4q0-.424.287-.713"
|
||||
/>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10m-2 0a8 8 0 1 1-16 0 8 8 0 0 1 16 0"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
You will lose any message history that’s stored only on the server
|
||||
</li>
|
||||
<li
|
||||
class="_visual-list-item_1nc1y_8"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="_visual-list-item-icon_1nc1y_17"
|
||||
fill="currentColor"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
width="24px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11.288 7.288A.97.97 0 0 1 12 7q.424 0 .713.287Q13 7.576 13 8t-.287.713A.97.97 0 0 1 12 9a.97.97 0 0 1-.713-.287A.97.97 0 0 1 11 8q0-.424.287-.713m.001 4.001A.97.97 0 0 1 12 11q.424 0 .713.287.287.288.287.713v4q0 .424-.287.712A.97.97 0 0 1 12 17a.97.97 0 0 1-.713-.288A.97.97 0 0 1 11 16v-4q0-.424.287-.713"
|
||||
/>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10m-2 0a8 8 0 1 1-16 0 8 8 0 0 1 16 0"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
You will need to verify all your existing devices and contacts again
|
||||
</li>
|
||||
</ul>
|
||||
<span>
|
||||
Only do this if you believe your account has been compromised.
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_EncryptionCard_buttons"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
class="_button_13vu4_8 _destructive_13vu4_110"
|
||||
data-kind="primary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Continue
|
||||
</button>
|
||||
<button
|
||||
class="_button_13vu4_8"
|
||||
data-kind="tertiary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
exports[`<EncryptionUserSettingsTab /> should display the set up recovery key when the user clicks on the set up recovery key button 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mx_SettingsTab mx_EncryptionUserSettingsTab"
|
||||
data-testid="encryptionTab"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsTab_sections"
|
||||
/>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
+1155
File diff suppressed because it is too large
Load Diff
+147
@@ -0,0 +1,147 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<LabsUserSettingsTab /> renders settings marked as beta as beta cards 1`] = `
|
||||
<div
|
||||
class="mx_SettingsSection"
|
||||
>
|
||||
<h2
|
||||
class="mx_Heading_h3"
|
||||
>
|
||||
Upcoming features
|
||||
</h2>
|
||||
<div
|
||||
class="mx_SettingsSection_subSections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection_text"
|
||||
>
|
||||
What's next for BrandedClient? Labs are the best way to get things early, test out new features and help shape them before they actually launch.
|
||||
</div>
|
||||
<div
|
||||
class="mx_BetaCard"
|
||||
>
|
||||
<div
|
||||
class="mx_BetaCard_columns"
|
||||
>
|
||||
<div
|
||||
class="mx_BetaCard_columns_description"
|
||||
>
|
||||
<h3
|
||||
class="mx_BetaCard_title"
|
||||
>
|
||||
<span>
|
||||
Video rooms
|
||||
</span>
|
||||
<span
|
||||
class="mx_BetaCard_betaPill"
|
||||
>
|
||||
Beta
|
||||
</span>
|
||||
</h3>
|
||||
<div
|
||||
class="mx_BetaCard_caption"
|
||||
>
|
||||
<p>
|
||||
A new way to chat over voice and video in BrandedClient.
|
||||
</p>
|
||||
<p>
|
||||
Video rooms are always-on VoIP channels embedded within a room in BrandedClient.
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="mx_BetaCard_buttons"
|
||||
>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Join the beta
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_BetaCard_refreshWarning"
|
||||
>
|
||||
Joining the beta will reload BrandedClient.
|
||||
</div>
|
||||
<div
|
||||
class="mx_BetaCard_faq"
|
||||
>
|
||||
<h4>
|
||||
How can I create a video room?
|
||||
</h4>
|
||||
<p>
|
||||
Use the “+” button in the room section of the left panel.
|
||||
</p>
|
||||
<h4>
|
||||
Can I use text chat alongside the video call?
|
||||
</h4>
|
||||
<p>
|
||||
Yes, the chat timeline is displayed alongside the video.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_BetaCard_columns_image_wrapper"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
class="mx_BetaCard_columns_image"
|
||||
src="image-file-stub"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_BetaCard"
|
||||
>
|
||||
<div
|
||||
class="mx_BetaCard_columns"
|
||||
>
|
||||
<div
|
||||
class="mx_BetaCard_columns_description"
|
||||
>
|
||||
<h3
|
||||
class="mx_BetaCard_title"
|
||||
>
|
||||
<span>
|
||||
Notification Settings
|
||||
</span>
|
||||
<span
|
||||
class="mx_BetaCard_betaPill"
|
||||
>
|
||||
Beta
|
||||
</span>
|
||||
</h3>
|
||||
<div
|
||||
class="mx_BetaCard_caption"
|
||||
>
|
||||
<p>
|
||||
Introducing a simpler way to change your notification settings. Customize your BrandedClient, just the way you like.
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="mx_BetaCard_buttons"
|
||||
>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Join the beta
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_BetaCard_columns_image_wrapper"
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
class="mx_BetaCard_columns_image"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<MjolnirUserSettingsTab /> renders correctly when user has no ignored users 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="mx_SettingsTab"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsTab_sections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection_subSections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection_text"
|
||||
>
|
||||
<strong
|
||||
class="warning"
|
||||
>
|
||||
⚠ These settings are meant for advanced users.
|
||||
</strong>
|
||||
<p>
|
||||
<span>
|
||||
Add users and servers you want to ignore here. Use asterisks to have Element match any characters. For example,
|
||||
<code>
|
||||
@bot:*
|
||||
</code>
|
||||
would ignore all users that have the name 'bot' on any server.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
Ignoring people is done through ban lists which contain rules for who to ban. Subscribing to a ban list means the users/servers blocked by that list will be hidden from you.
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Personal ban list
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_description"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection_text"
|
||||
>
|
||||
Your personal ban list holds all the users/servers you personally don't want to see messages from. After ignoring your first user/server, a new room will show up in your room list named 'My Ban List' - stay in this room to keep the ban list in effect.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
>
|
||||
<i>
|
||||
You have not ignored anyone.
|
||||
</i>
|
||||
<form
|
||||
autocomplete="off"
|
||||
>
|
||||
<div
|
||||
class="mx_Field mx_Field_input"
|
||||
>
|
||||
<input
|
||||
id="mx_Field_1"
|
||||
label="Server or user ID to ignore"
|
||||
placeholder="eg: @bot:* or example.org"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<label
|
||||
for="mx_Field_1"
|
||||
>
|
||||
Server or user ID to ignore
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Ignore
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Subscribed lists
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_description"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection_text"
|
||||
>
|
||||
<strong
|
||||
class="warning"
|
||||
>
|
||||
Subscribing to a ban list will cause you to join it!
|
||||
</strong>
|
||||
|
||||
<span>
|
||||
If this isn't what you want, please use a different tool to ignore users.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
>
|
||||
<i>
|
||||
You are not subscribed to any lists
|
||||
</i>
|
||||
<form
|
||||
autocomplete="off"
|
||||
>
|
||||
<div
|
||||
class="mx_Field mx_Field_input"
|
||||
>
|
||||
<input
|
||||
id="mx_Field_2"
|
||||
label="Room ID or address of ban list"
|
||||
placeholder="Room ID or address of ban list"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<label
|
||||
for="mx_Field_2"
|
||||
>
|
||||
Room ID or address of ban list
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Subscribe
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
+1769
File diff suppressed because it is too large
Load Diff
+288
@@ -0,0 +1,288 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<SecurityUserSettingsTab /> renders ignored users 1`] = `
|
||||
<ul
|
||||
aria-label="Ignored users"
|
||||
class="mx_SecurityUserSettingsTab_ignoredUsers"
|
||||
>
|
||||
<li
|
||||
aria-label="@bob:example.org"
|
||||
class="mx_SecurityUserSettingsTab_ignoredUser"
|
||||
>
|
||||
<div
|
||||
aria-describedby="mx_SecurityUserSettingsTab_ignoredUser_@bob:example.org"
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary_sm"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Unignore
|
||||
</div>
|
||||
<span
|
||||
id="mx_SecurityUserSettingsTab_ignoredUser_@bob:example.org"
|
||||
>
|
||||
@bob:example.org
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
`;
|
||||
|
||||
exports[`<SecurityUserSettingsTab /> renders security section 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="mx_SettingsTab"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsTab_sections"
|
||||
>
|
||||
<form
|
||||
class="_root_19upo_16 mx_SetIntegrationManager"
|
||||
data-testid="mx_SetIntegrationManager"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsFlag"
|
||||
>
|
||||
<div
|
||||
class="mx_SetIntegrationManager_heading_manager"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h3"
|
||||
>
|
||||
Manage integrations
|
||||
</h3>
|
||||
<h4
|
||||
class="mx_Heading_h4"
|
||||
id="mx_SetIntegrationManager_ManagerName"
|
||||
>
|
||||
(scalar.vector.im)
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_text"
|
||||
id="mx_SetIntegrationManager_BodyText"
|
||||
>
|
||||
<span>
|
||||
Use an integration manager
|
||||
<strong>
|
||||
(scalar.vector.im)
|
||||
</strong>
|
||||
to manage bots, widgets, and sticker packs.
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_text"
|
||||
>
|
||||
Integration managers receive configuration data, and can modify widgets, send room invites, and set power levels on your behalf.
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field_19upo_32"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_udcm8_10"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="_input_udcm8_24"
|
||||
id="_r_0_"
|
||||
role="switch"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
class="_ui_udcm8_34"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59"
|
||||
for="_r_0_"
|
||||
>
|
||||
Enable the integration manager
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div
|
||||
class="mx_SettingsSection"
|
||||
>
|
||||
<h2
|
||||
class="mx_Heading_h3"
|
||||
>
|
||||
Encryption
|
||||
</h2>
|
||||
<div
|
||||
class="mx_SettingsSection_subSections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Message search
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection_text"
|
||||
>
|
||||
<span>
|
||||
Element can't securely cache encrypted messages locally while running in a web browser. Use
|
||||
<a
|
||||
class="mx_ExternalLink"
|
||||
href="https://element.io/download"
|
||||
rel="noreferrer noopener"
|
||||
target="_blank"
|
||||
>
|
||||
Element Desktop
|
||||
<svg
|
||||
class="mx_ExternalLink_icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M5 3h6a1 1 0 1 1 0 2H5v14h14v-6a1 1 0 1 1 2 0v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2"
|
||||
/>
|
||||
<path
|
||||
d="M15 3h5a1 1 0 0 1 1 1v5a1 1 0 1 1-2 0V6.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L17.586 5H15a1 1 0 1 1 0-2"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
for encrypted messages to appear in search results.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSection"
|
||||
>
|
||||
<h2
|
||||
class="mx_Heading_h3"
|
||||
>
|
||||
Privacy
|
||||
</h2>
|
||||
<div
|
||||
class="mx_SettingsSection_subSections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
data-testid="discoverySection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
How to find you
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content mx_SettingsSubsection_contentStretch"
|
||||
>
|
||||
<fieldset
|
||||
class="mx_SettingsFieldset"
|
||||
>
|
||||
<legend
|
||||
class="mx_SettingsFieldset_legend"
|
||||
>
|
||||
Identity server
|
||||
</legend>
|
||||
<div
|
||||
class="mx_SettingsFieldset_description"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection_text"
|
||||
>
|
||||
You are not currently using an identity server. To discover and be discoverable by existing contacts you know, add one below.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsFieldset_content"
|
||||
>
|
||||
<form
|
||||
class="_root_19upo_16 mx_IdentityServerPicker"
|
||||
>
|
||||
<div
|
||||
class="_field_19upo_26"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59"
|
||||
for="radix-_r_2_"
|
||||
>
|
||||
Enter a new identity server
|
||||
</label>
|
||||
<div
|
||||
class="_controls_17lij_8"
|
||||
>
|
||||
<input
|
||||
class="_control_sqdq4_10"
|
||||
id="radix-_r_2_"
|
||||
name="input"
|
||||
placeholder=""
|
||||
title=""
|
||||
value=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSection"
|
||||
>
|
||||
<h2
|
||||
class="mx_Heading_h3"
|
||||
>
|
||||
Advanced
|
||||
</h2>
|
||||
<div
|
||||
class="mx_SettingsSection_subSections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Ignored users
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection_text"
|
||||
>
|
||||
You have no ignored users.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
+530
@@ -0,0 +1,530 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<SessionManagerTab /> Device verification does not allow device verification on session that do not support encryption 1`] = `
|
||||
HTMLCollection [
|
||||
<div
|
||||
class="mx_DeviceSecurityCard"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_icon Unverified"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
width="16"
|
||||
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>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_content"
|
||||
>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_heading"
|
||||
>
|
||||
Unverified session
|
||||
</p>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_description"
|
||||
>
|
||||
This session doesn't support encryption and thus can't be verified.
|
||||
<div
|
||||
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Learn more
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
</div>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`<SessionManagerTab /> Sign out Signs out of current device 1`] = `
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_danger_inline"
|
||||
data-testid="device-detail-sign-out-cta"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="mx_DeviceDetails_signOutButtonContent"
|
||||
>
|
||||
Sign out of this session
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<SessionManagerTab /> Sign out for an OIDC-aware server Signs out of current device 1`] = `
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_danger_inline"
|
||||
data-testid="device-detail-sign-out-cta"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
class="mx_DeviceDetails_signOutButtonContent"
|
||||
>
|
||||
Sign out of this session
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<SessionManagerTab /> current session section renders current session section with a verified session 1`] = `
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
data-testid="current-session-section"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Current session
|
||||
</h3>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-label="Options"
|
||||
class="mx_AccessibleButton"
|
||||
data-testid="current-session-menu"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
class="mx_KebabContextMenu_icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceTile mx_DeviceTile_interactive"
|
||||
data-testid="device-tile-alices_device"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<svg
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M3.5 20q-.625 0-1.062-.437A1.45 1.45 0 0 1 2 18.5q0-.625.438-1.062A1.45 1.45 0 0 1 3.5 17H4V6q0-.824.588-1.412A1.93 1.93 0 0 1 6 4h14q.424 0 .712.287Q21 4.576 21 5t-.288.713A.97.97 0 0 1 20 6H6v11h4.5q.624 0 1.063.438.437.437.437 1.062t-.437 1.063A1.45 1.45 0 0 1 10.5 20zM15 20a.97.97 0 0 1-.713-.288A.97.97 0 0 1 14 19V9q0-.424.287-.713A.97.97 0 0 1 15 8h6q.424 0 .712.287Q22 8.576 22 9v10q0 .424-.288.712A.97.97 0 0 1 21 20zm1-3h4v-7h-4z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<svg
|
||||
aria-label="Verified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon verified"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M11.106 2.447a2 2 0 0 1 1.789 0l6 3A2 2 0 0 1 20 7.237V12c0 6.742-5.773 9.246-7.51 9.846-.32.111-.66.111-.98 0C9.774 21.246 4 18.743 4 12V7.236a2 2 0 0 1 1.105-1.789zm4.601 6.846a1 1 0 0 0-1.414 0L11 12.586l-1.293-1.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 0-1.414"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="mx_DeviceTile_info"
|
||||
>
|
||||
<h4
|
||||
class="mx_Heading_h4"
|
||||
>
|
||||
Alices device
|
||||
</h4>
|
||||
<div
|
||||
class="mx_DeviceTile_metadata"
|
||||
>
|
||||
<span
|
||||
data-testid="device-metadata-isVerified"
|
||||
>
|
||||
Verified
|
||||
</span>
|
||||
·
|
||||
<span
|
||||
data-testid="device-metadata-deviceId"
|
||||
>
|
||||
alices_device
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_DeviceTile_actions"
|
||||
>
|
||||
<div
|
||||
aria-label="Show details"
|
||||
class="mx_AccessibleButton mx_DeviceExpandDetailsButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_icon"
|
||||
data-testid="current-session-toggle-details"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
class="mx_DeviceExpandDetailsButton_icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div
|
||||
class="mx_DeviceSecurityCard"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_icon Verified"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M11.106 2.447a2 2 0 0 1 1.789 0l6 3A2 2 0 0 1 20 7.237V12c0 6.742-5.773 9.246-7.51 9.846-.32.111-.66.111-.98 0C9.774 21.246 4 18.743 4 12V7.236a2 2 0 0 1 1.105-1.789zm4.601 6.846a1 1 0 0 0-1.414 0L11 12.586l-1.293-1.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0 0-1.414"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_content"
|
||||
>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_heading"
|
||||
>
|
||||
Verified session
|
||||
</p>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_description"
|
||||
>
|
||||
Your current session is ready for secure messaging.
|
||||
<div
|
||||
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Learn more
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<SessionManagerTab /> current session section renders current session section with an unverified session 1`] = `
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
data-testid="current-session-section"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Current session
|
||||
</h3>
|
||||
<div
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-label="Options"
|
||||
class="mx_AccessibleButton"
|
||||
data-testid="current-session-menu"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
class="mx_KebabContextMenu_icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 14q-.824 0-1.412-.588A1.93 1.93 0 0 1 4 12q0-.825.588-1.412A1.93 1.93 0 0 1 6 10q.824 0 1.412.588Q8 11.175 8 12t-.588 1.412A1.93 1.93 0 0 1 6 14m6 0q-.825 0-1.412-.588A1.93 1.93 0 0 1 10 12q0-.825.588-1.412A1.93 1.93 0 0 1 12 10q.825 0 1.412.588Q14 11.175 14 12t-.588 1.412A1.93 1.93 0 0 1 12 14m6 0q-.824 0-1.413-.588A1.93 1.93 0 0 1 16 12q0-.825.587-1.412A1.93 1.93 0 0 1 18 10q.824 0 1.413.588Q20 11.175 20 12t-.587 1.412A1.93 1.93 0 0 1 18 14"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceTile mx_DeviceTile_interactive"
|
||||
data-testid="device-tile-alices_device"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceTypeIcon"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceTypeIcon_deviceIconWrapper"
|
||||
>
|
||||
<svg
|
||||
aria-label="Unknown session type"
|
||||
class="mx_DeviceTypeIcon_deviceIcon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M3.5 20q-.625 0-1.062-.437A1.45 1.45 0 0 1 2 18.5q0-.625.438-1.062A1.45 1.45 0 0 1 3.5 17H4V6q0-.824.588-1.412A1.93 1.93 0 0 1 6 4h14q.424 0 .712.287Q21 4.576 21 5t-.288.713A.97.97 0 0 1 20 6H6v11h4.5q.624 0 1.063.438.437.437.437 1.062t-.437 1.063A1.45 1.45 0 0 1 10.5 20zM15 20a.97.97 0 0 1-.713-.288A.97.97 0 0 1 14 19V9q0-.424.287-.713A.97.97 0 0 1 15 8h6q.424 0 .712.287Q22 8.576 22 9v10q0 .424-.288.712A.97.97 0 0 1 21 20zm1-3h4v-7h-4z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<svg
|
||||
aria-label="Unverified"
|
||||
class="mx_DeviceTypeIcon_verificationIcon unverified"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
role="img"
|
||||
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>
|
||||
<div
|
||||
class="mx_DeviceTile_info"
|
||||
>
|
||||
<h4
|
||||
class="mx_Heading_h4"
|
||||
>
|
||||
Alices device
|
||||
</h4>
|
||||
<div
|
||||
class="mx_DeviceTile_metadata"
|
||||
>
|
||||
<span
|
||||
data-testid="device-metadata-isVerified"
|
||||
>
|
||||
Unverified
|
||||
</span>
|
||||
·
|
||||
<span
|
||||
data-testid="device-metadata-deviceId"
|
||||
>
|
||||
alices_device
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_DeviceTile_actions"
|
||||
>
|
||||
<div
|
||||
aria-label="Show details"
|
||||
class="mx_AccessibleButton mx_DeviceExpandDetailsButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_icon"
|
||||
data-testid="current-session-toggle-details"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
class="mx_DeviceExpandDetailsButton_icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div
|
||||
class="mx_DeviceSecurityCard"
|
||||
>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_icon Unverified"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
width="16"
|
||||
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>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_content"
|
||||
>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_heading"
|
||||
>
|
||||
Unverified session
|
||||
</p>
|
||||
<p
|
||||
class="mx_DeviceSecurityCard_description"
|
||||
>
|
||||
Verify your current session for enhanced secure messaging.
|
||||
<div
|
||||
class="mx_AccessibleButton mx_LearnMore_button mx_AccessibleButton_hasKind mx_AccessibleButton_kind_link_inline"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Learn more
|
||||
</div>
|
||||
</p>
|
||||
<div
|
||||
class="mx_DeviceSecurityCard_actions"
|
||||
>
|
||||
<div
|
||||
class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary"
|
||||
data-testid="verification-status-button-alices_device"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Verify session
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<SessionManagerTab /> goes to filtered list from security recommendations 1`] = `
|
||||
<div
|
||||
class="mx_FilteredDeviceListHeader"
|
||||
>
|
||||
<span
|
||||
tabindex="0"
|
||||
>
|
||||
<form
|
||||
class="_root_19upo_16"
|
||||
>
|
||||
<div
|
||||
class="_inline-field_19upo_32"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_153f2_10"
|
||||
>
|
||||
<input
|
||||
aria-label="Select all"
|
||||
aria-labelledby="_r_4q_"
|
||||
class="_input_153f2_18"
|
||||
data-testid="device-select-all-checkbox"
|
||||
id="device-select-all-checkbox"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
class="_ui_153f2_19"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.55 17.575q-.2 0-.375-.062a.9.9 0 0 1-.325-.213L4.55 13q-.274-.274-.262-.713.012-.437.287-.712a.95.95 0 0 1 .7-.275q.425 0 .7.275L9.55 15.15l8.475-8.475q.274-.275.713-.275.437 0 .712.275.275.274.275.713 0 .437-.275.712l-9.2 9.2q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</span>
|
||||
<span
|
||||
class="mx_FilteredDeviceListHeader_label"
|
||||
>
|
||||
Sessions
|
||||
</span>
|
||||
<div
|
||||
class="mx_Dropdown mx_FilterDropdown"
|
||||
>
|
||||
<div
|
||||
aria-describedby="device-list-filter_value"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-label="Filter devices"
|
||||
aria-owns="device-list-filter_input"
|
||||
class="mx_AccessibleButton mx_Dropdown_input mx_no_textinput"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="mx_Dropdown_option"
|
||||
id="device-list-filter_value"
|
||||
>
|
||||
Show: Unverified
|
||||
</div>
|
||||
<svg
|
||||
class="mx_Dropdown_arrow"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 14.95q-.2 0-.375-.062a.9.9 0 0 1-.325-.213l-4.6-4.6a.95.95 0 0 1-.275-.7q0-.425.275-.7a.95.95 0 0 1 .7-.275q.425 0 .7.275l3.9 3.9 3.9-3.9a.95.95 0 0 1 .7-.275q.425 0 .7.275a.95.95 0 0 1 .275.7.95.95 0 0 1-.275.7l-4.6 4.6q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
+581
@@ -0,0 +1,581 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`<SidebarUserSettingsTab /> renders sidebar settings with guest spa url 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="mx_SettingsTab"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsTab_sections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection_subSections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Spaces to show
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_description"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection_text"
|
||||
>
|
||||
Spaces are ways to group rooms and people. Alongside the spaces you're in, you can use some pre-built ones too.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
>
|
||||
<form
|
||||
class="_root_19upo_16"
|
||||
>
|
||||
<div
|
||||
class="_inline-field_19upo_32 mx_SidebarUserSettingsTab_checkbox"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_153f2_10"
|
||||
>
|
||||
<input
|
||||
aria-describedby="_r_1_"
|
||||
checked=""
|
||||
class="_input_153f2_18"
|
||||
disabled=""
|
||||
id="checkbox_vY7Q4uEh9K"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
class="_ui_153f2_19"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.55 17.575q-.2 0-.375-.062a.9.9 0 0 1-.325-.213L4.55 13q-.274-.274-.262-.713.012-.437.287-.712a.95.95 0 0 1 .7-.275q.425 0 .7.275L9.55 15.15l8.475-8.475q.274-.275.713-.275.437 0 .712.275.275.274.275.713 0 .437-.275.712l-9.2 9.2q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59"
|
||||
for="checkbox_vY7Q4uEh9K"
|
||||
>
|
||||
<svg
|
||||
class="mx_SidebarUserSettingsTab_icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="m12.971 3.54 7 3.889A2 2 0 0 1 21 9.177V19a2 2 0 0 1-2 2h-4v-9H9v9H5a2 2 0 0 1-2-2V9.177a2 2 0 0 1 1.029-1.748l7-3.89a2 2 0 0 1 1.942 0"
|
||||
/>
|
||||
</svg>
|
||||
Home
|
||||
</label>
|
||||
<span
|
||||
class="_message_19upo_85 _help-message_19upo_91"
|
||||
id="_r_1_"
|
||||
>
|
||||
Home is useful for getting an overview of everything.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form
|
||||
class="_root_19upo_16"
|
||||
>
|
||||
<div
|
||||
class="_inline-field_19upo_32 mx_SidebarUserSettingsTab_checkbox mx_SidebarUserSettingsTab_homeAllRoomsCheckbox"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_153f2_10"
|
||||
>
|
||||
<input
|
||||
aria-describedby="_r_5_"
|
||||
class="_input_153f2_18"
|
||||
data-testid="mx_SidebarUserSettingsTab_homeAllRoomsCheckbox"
|
||||
id="checkbox_38QgU2Pomx"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
class="_ui_153f2_19"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.55 17.575q-.2 0-.375-.062a.9.9 0 0 1-.325-.213L4.55 13q-.274-.274-.262-.713.012-.437.287-.712a.95.95 0 0 1 .7-.275q.425 0 .7.275L9.55 15.15l8.475-8.475q.274-.275.713-.275.437 0 .712.275.275.274.275.713 0 .437-.275.712l-9.2 9.2q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59"
|
||||
for="checkbox_38QgU2Pomx"
|
||||
>
|
||||
Show all rooms
|
||||
</label>
|
||||
<span
|
||||
class="_message_19upo_85 _help-message_19upo_91"
|
||||
id="_r_5_"
|
||||
>
|
||||
Show all your rooms in Home, even if they're in a space.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form
|
||||
class="_root_19upo_16"
|
||||
>
|
||||
<div
|
||||
class="_inline-field_19upo_32 mx_SidebarUserSettingsTab_checkbox"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_153f2_10"
|
||||
>
|
||||
<input
|
||||
aria-describedby="_r_9_"
|
||||
class="_input_153f2_18"
|
||||
id="checkbox_wKpa6hpi3Y"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
class="_ui_153f2_19"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.55 17.575q-.2 0-.375-.062a.9.9 0 0 1-.325-.213L4.55 13q-.274-.274-.262-.713.012-.437.287-.712a.95.95 0 0 1 .7-.275q.425 0 .7.275L9.55 15.15l8.475-8.475q.274-.275.713-.275.437 0 .712.275.275.274.275.713 0 .437-.275.712l-9.2 9.2q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59"
|
||||
for="checkbox_wKpa6hpi3Y"
|
||||
>
|
||||
Rooms outside of a space
|
||||
</label>
|
||||
<span
|
||||
class="_message_19upo_85 _help-message_19upo_91"
|
||||
id="_r_9_"
|
||||
>
|
||||
Group all your rooms that aren't part of a space in one place.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form
|
||||
class="_root_19upo_16"
|
||||
>
|
||||
<div
|
||||
class="_inline-field_19upo_32 mx_SidebarUserSettingsTab_checkbox"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_153f2_10"
|
||||
>
|
||||
<input
|
||||
aria-describedby="_r_d_"
|
||||
class="_input_153f2_18"
|
||||
id="checkbox_EetmBG4yVC"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
class="_ui_153f2_19"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.55 17.575q-.2 0-.375-.062a.9.9 0 0 1-.325-.213L4.55 13q-.274-.274-.262-.713.012-.437.287-.712a.95.95 0 0 1 .7-.275q.425 0 .7.275L9.55 15.15l8.475-8.475q.274-.275.713-.275.437 0 .712.275.275.274.275.713 0 .437-.275.712l-9.2 9.2q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59"
|
||||
for="checkbox_EetmBG4yVC"
|
||||
>
|
||||
<svg
|
||||
class="mx_SidebarUserSettingsTab_icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 4h10a2 2 0 0 1 2 2v4.286l3.35-2.871a1 1 0 0 1 1.65.76v7.65a1 1 0 0 1-1.65.76L18 13.715V18a2 2 0 0 1-2 2H6a4 4 0 0 1-4-4V8a4 4 0 0 1 4-4"
|
||||
/>
|
||||
</svg>
|
||||
Video rooms and conferences
|
||||
</label>
|
||||
<span
|
||||
class="_message_19upo_85 _help-message_19upo_91"
|
||||
id="_r_d_"
|
||||
>
|
||||
Group all private video rooms and conferences. In conferences you can invite people outside of matrix.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`<SidebarUserSettingsTab /> renders sidebar settings without guest spa url 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="mx_SettingsTab"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsTab_sections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSection_subSections"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsectionHeading"
|
||||
>
|
||||
<h3
|
||||
class="mx_Heading_h4 mx_SettingsSubsectionHeading_heading"
|
||||
>
|
||||
Spaces to show
|
||||
</h3>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_description"
|
||||
>
|
||||
<div
|
||||
class="mx_SettingsSubsection_text"
|
||||
>
|
||||
Spaces are ways to group rooms and people. Alongside the spaces you're in, you can use some pre-built ones too.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mx_SettingsSubsection_content"
|
||||
>
|
||||
<form
|
||||
class="_root_19upo_16"
|
||||
>
|
||||
<div
|
||||
class="_inline-field_19upo_32 mx_SidebarUserSettingsTab_checkbox"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_153f2_10"
|
||||
>
|
||||
<input
|
||||
aria-describedby="_r_h_"
|
||||
checked=""
|
||||
class="_input_153f2_18"
|
||||
disabled=""
|
||||
id="checkbox_vY7Q4uEh9K"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
class="_ui_153f2_19"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.55 17.575q-.2 0-.375-.062a.9.9 0 0 1-.325-.213L4.55 13q-.274-.274-.262-.713.012-.437.287-.712a.95.95 0 0 1 .7-.275q.425 0 .7.275L9.55 15.15l8.475-8.475q.274-.275.713-.275.437 0 .712.275.275.274.275.713 0 .437-.275.712l-9.2 9.2q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59"
|
||||
for="checkbox_vY7Q4uEh9K"
|
||||
>
|
||||
<svg
|
||||
class="mx_SidebarUserSettingsTab_icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="m12.971 3.54 7 3.889A2 2 0 0 1 21 9.177V19a2 2 0 0 1-2 2h-4v-9H9v9H5a2 2 0 0 1-2-2V9.177a2 2 0 0 1 1.029-1.748l7-3.89a2 2 0 0 1 1.942 0"
|
||||
/>
|
||||
</svg>
|
||||
Home
|
||||
</label>
|
||||
<span
|
||||
class="_message_19upo_85 _help-message_19upo_91"
|
||||
id="_r_h_"
|
||||
>
|
||||
Home is useful for getting an overview of everything.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form
|
||||
class="_root_19upo_16"
|
||||
>
|
||||
<div
|
||||
class="_inline-field_19upo_32 mx_SidebarUserSettingsTab_checkbox mx_SidebarUserSettingsTab_homeAllRoomsCheckbox"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_153f2_10"
|
||||
>
|
||||
<input
|
||||
aria-describedby="_r_l_"
|
||||
class="_input_153f2_18"
|
||||
data-testid="mx_SidebarUserSettingsTab_homeAllRoomsCheckbox"
|
||||
id="checkbox_38QgU2Pomx"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
class="_ui_153f2_19"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.55 17.575q-.2 0-.375-.062a.9.9 0 0 1-.325-.213L4.55 13q-.274-.274-.262-.713.012-.437.287-.712a.95.95 0 0 1 .7-.275q.425 0 .7.275L9.55 15.15l8.475-8.475q.274-.275.713-.275.437 0 .712.275.275.274.275.713 0 .437-.275.712l-9.2 9.2q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59"
|
||||
for="checkbox_38QgU2Pomx"
|
||||
>
|
||||
Show all rooms
|
||||
</label>
|
||||
<span
|
||||
class="_message_19upo_85 _help-message_19upo_91"
|
||||
id="_r_l_"
|
||||
>
|
||||
Show all your rooms in Home, even if they're in a space.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form
|
||||
class="_root_19upo_16"
|
||||
>
|
||||
<div
|
||||
class="_inline-field_19upo_32 mx_SidebarUserSettingsTab_checkbox"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_153f2_10"
|
||||
>
|
||||
<input
|
||||
aria-describedby="_r_p_"
|
||||
class="_input_153f2_18"
|
||||
id="checkbox_wKpa6hpi3Y"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
class="_ui_153f2_19"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.55 17.575q-.2 0-.375-.062a.9.9 0 0 1-.325-.213L4.55 13q-.274-.274-.262-.713.012-.437.287-.712a.95.95 0 0 1 .7-.275q.425 0 .7.275L9.55 15.15l8.475-8.475q.274-.275.713-.275.437 0 .712.275.275.274.275.713 0 .437-.275.712l-9.2 9.2q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59"
|
||||
for="checkbox_wKpa6hpi3Y"
|
||||
>
|
||||
Rooms outside of a space
|
||||
</label>
|
||||
<span
|
||||
class="_message_19upo_85 _help-message_19upo_91"
|
||||
id="_r_p_"
|
||||
>
|
||||
Group all your rooms that aren't part of a space in one place.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form
|
||||
class="_root_19upo_16"
|
||||
>
|
||||
<div
|
||||
class="_inline-field_19upo_32 mx_SidebarUserSettingsTab_checkbox"
|
||||
>
|
||||
<div
|
||||
class="_inline-field-control_19upo_44"
|
||||
>
|
||||
<div
|
||||
class="_container_153f2_10"
|
||||
>
|
||||
<input
|
||||
aria-describedby="_r_t_"
|
||||
class="_input_153f2_18"
|
||||
id="checkbox_EetmBG4yVC"
|
||||
type="checkbox"
|
||||
/>
|
||||
<div
|
||||
class="_ui_153f2_19"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.55 17.575q-.2 0-.375-.062a.9.9 0 0 1-.325-.213L4.55 13q-.274-.274-.262-.713.012-.437.287-.712a.95.95 0 0 1 .7-.275q.425 0 .7.275L9.55 15.15l8.475-8.475q.274-.275.713-.275.437 0 .712.275.275.274.275.713 0 .437-.275.712l-9.2 9.2q-.15.15-.325.212a1.1 1.1 0 0 1-.375.063"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="_inline-field-body_19upo_38"
|
||||
>
|
||||
<label
|
||||
class="_label_19upo_59"
|
||||
for="checkbox_EetmBG4yVC"
|
||||
>
|
||||
<svg
|
||||
class="mx_SidebarUserSettingsTab_icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 4h10a2 2 0 0 1 2 2v4.286l3.35-2.871a1 1 0 0 1 1.65.76v7.65a1 1 0 0 1-1.65.76L18 13.715V18a2 2 0 0 1-2 2H6a4 4 0 0 1-4-4V8a4 4 0 0 1 4-4"
|
||||
/>
|
||||
</svg>
|
||||
Video rooms and conferences
|
||||
</label>
|
||||
<span
|
||||
class="_message_19upo_85 _help-message_19upo_91"
|
||||
id="_r_t_"
|
||||
>
|
||||
Group all private video rooms and conferences.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
Reference in New Issue
Block a user