Enable the rust-crypto labs button (#12114)
* `LabsUserSettingsTab-test.tsx`: use a real `SdkConfig` ... instead of mocking it out. Doing so allows us more flexibility, and gives a more realistic test. * Enable the rust-crypto labs button * fix up a test
This commit is contained in:
parent
b64d2e734a
commit
b6364a4cea
7 changed files with 139 additions and 20 deletions
|
@ -52,6 +52,7 @@ import ErrorDialog from "./components/views/dialogs/ErrorDialog";
|
||||||
import PlatformPeg from "./PlatformPeg";
|
import PlatformPeg from "./PlatformPeg";
|
||||||
import { formatList } from "./utils/FormattingUtils";
|
import { formatList } from "./utils/FormattingUtils";
|
||||||
import SdkConfig from "./SdkConfig";
|
import SdkConfig from "./SdkConfig";
|
||||||
|
import { Features } from "./settings/Settings";
|
||||||
|
|
||||||
export interface IMatrixClientCreds {
|
export interface IMatrixClientCreds {
|
||||||
homeserverUrl: string;
|
homeserverUrl: string;
|
||||||
|
@ -301,7 +302,7 @@ class MatrixClientPegClass implements IMatrixClientPeg {
|
||||||
throw new Error("createClient must be called first");
|
throw new Error("createClient must be called first");
|
||||||
}
|
}
|
||||||
|
|
||||||
const useRustCrypto = SettingsStore.getValue("feature_rust_crypto");
|
const useRustCrypto = SettingsStore.getValue(Features.RustCrypto);
|
||||||
|
|
||||||
// we want to make sure that the same crypto implementation is used throughout the lifetime of a device,
|
// we want to make sure that the same crypto implementation is used throughout the lifetime of a device,
|
||||||
// so persist the setting at the device layer
|
// so persist the setting at the device layer
|
||||||
|
|
|
@ -1447,7 +1447,10 @@
|
||||||
"report_to_moderators": "Report to moderators",
|
"report_to_moderators": "Report to moderators",
|
||||||
"report_to_moderators_description": "In rooms that support moderation, the “Report” button will let you report abuse to room moderators.",
|
"report_to_moderators_description": "In rooms that support moderation, the “Report” button will let you report abuse to room moderators.",
|
||||||
"rust_crypto": "Rust cryptography implementation",
|
"rust_crypto": "Rust cryptography implementation",
|
||||||
"rust_crypto_disabled_notice": "Can currently only be enabled via config.json",
|
"rust_crypto_in_config": "Rust cryptography cannot be disabled on this deployment of %(brand)s",
|
||||||
|
"rust_crypto_in_config_description": "Switching to the Rust cryptography requires a migration process that may take several minutes. It cannot be disabled; use with caution!",
|
||||||
|
"rust_crypto_optin_warning": "Switching to the Rust cryptography requires a migration process that may take several minutes. To disable you will need to log out and back in; use with caution!",
|
||||||
|
"rust_crypto_requires_logout": "Once enabled, Rust cryptography can only be disabled by logging out and in again",
|
||||||
"sliding_sync": "Sliding Sync mode",
|
"sliding_sync": "Sliding Sync mode",
|
||||||
"sliding_sync_checking": "Checking…",
|
"sliding_sync_checking": "Checking…",
|
||||||
"sliding_sync_configuration": "Sliding Sync configuration",
|
"sliding_sync_configuration": "Sliding Sync configuration",
|
||||||
|
|
|
@ -46,6 +46,7 @@ import RustCryptoSdkController from "./controllers/RustCryptoSdkController";
|
||||||
import ServerSupportUnstableFeatureController from "./controllers/ServerSupportUnstableFeatureController";
|
import ServerSupportUnstableFeatureController from "./controllers/ServerSupportUnstableFeatureController";
|
||||||
import { WatchManager } from "./WatchManager";
|
import { WatchManager } from "./WatchManager";
|
||||||
import { CustomTheme } from "../theme";
|
import { CustomTheme } from "../theme";
|
||||||
|
import SettingsStore from "./SettingsStore";
|
||||||
|
|
||||||
export const defaultWatchManager = new WatchManager();
|
export const defaultWatchManager = new WatchManager();
|
||||||
|
|
||||||
|
@ -94,6 +95,7 @@ export enum Features {
|
||||||
VoiceBroadcastForceSmallChunks = "feature_voice_broadcast_force_small_chunks",
|
VoiceBroadcastForceSmallChunks = "feature_voice_broadcast_force_small_chunks",
|
||||||
NotificationSettings2 = "feature_notification_settings2",
|
NotificationSettings2 = "feature_notification_settings2",
|
||||||
OidcNativeFlow = "feature_oidc_native_flow",
|
OidcNativeFlow = "feature_oidc_native_flow",
|
||||||
|
RustCrypto = "feature_rust_crypto",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const labGroupNames: Record<LabGroup, TranslationKey> = {
|
export const labGroupNames: Record<LabGroup, TranslationKey> = {
|
||||||
|
@ -480,15 +482,22 @@ export const SETTINGS: { [setting: string]: ISetting } = {
|
||||||
description: _td("labs|oidc_native_flow_description"),
|
description: _td("labs|oidc_native_flow_description"),
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
"feature_rust_crypto": {
|
[Features.RustCrypto]: {
|
||||||
// use the rust matrix-sdk-crypto-js for crypto.
|
// use the rust matrix-sdk-crypto-wasm for crypto.
|
||||||
isFeature: true,
|
isFeature: true,
|
||||||
labsGroup: LabGroup.Developer,
|
labsGroup: LabGroup.Developer,
|
||||||
configDisablesSetting: true,
|
// unlike most features, `configDisablesSetting` is false here.
|
||||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||||
displayName: _td("labs|rust_crypto"),
|
displayName: _td("labs|rust_crypto"),
|
||||||
description: _td("labs|under_active_development"),
|
description: () => {
|
||||||
// shouldWarn: true,
|
if (SettingsStore.getValueAt(SettingLevel.CONFIG, Features.RustCrypto)) {
|
||||||
|
// It's enabled in the config, so you can't get rid of it even by logging out.
|
||||||
|
return _t("labs|rust_crypto_in_config_description");
|
||||||
|
} else {
|
||||||
|
return _t("labs|rust_crypto_optin_warning");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
shouldWarn: true,
|
||||||
default: false,
|
default: false,
|
||||||
controller: new RustCryptoSdkController(),
|
controller: new RustCryptoSdkController(),
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,12 +15,35 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { _t } from "../../languageHandler";
|
import { _t } from "../../languageHandler";
|
||||||
|
import SettingsStore from "../SettingsStore";
|
||||||
|
import { SettingLevel } from "../SettingLevel";
|
||||||
|
import PlatformPeg from "../../PlatformPeg";
|
||||||
import SettingController from "./SettingController";
|
import SettingController from "./SettingController";
|
||||||
|
import { Features } from "../Settings";
|
||||||
|
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||||
|
import SdkConfig from "../../SdkConfig";
|
||||||
|
|
||||||
export default class RustCryptoSdkController extends SettingController {
|
export default class RustCryptoSdkController extends SettingController {
|
||||||
|
public onChange(level: SettingLevel, roomId: string | null, newValue: any): void {
|
||||||
|
// If the crypto stack has already been initialized, we'll need to reload the app to make it take effect.
|
||||||
|
if (MatrixClientPeg.get()?.getCrypto()) {
|
||||||
|
PlatformPeg.get()?.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public get settingDisabled(): boolean | string {
|
public get settingDisabled(): boolean | string {
|
||||||
// Currently this can only be changed via config.json. In future, we'll allow the user to *enable* this setting
|
if (!SettingsStore.getValueAt(SettingLevel.DEVICE, Features.RustCrypto)) {
|
||||||
// via labs, which will migrate their existing device to the rust-sdk implementation.
|
// If rust crypto has not yet been enabled for this device, you can turn it on, IF YOU DARE
|
||||||
return _t("labs|rust_crypto_disabled_notice");
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SettingsStore.getValueAt(SettingLevel.CONFIG, Features.RustCrypto)) {
|
||||||
|
// It's enabled in the config, so you can't get rid of it even by logging out.
|
||||||
|
return _t("labs|rust_crypto_in_config", { brand: SdkConfig.get().brand });
|
||||||
|
}
|
||||||
|
|
||||||
|
// The setting is enabled at the device level, but not mandated at the config level.
|
||||||
|
// You can only turn it off by logging out and in again.
|
||||||
|
return _t("labs|rust_crypto_requires_logout");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,9 @@ describe("MatrixClientPeg", () => {
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
jest.restoreAllMocks();
|
jest.restoreAllMocks();
|
||||||
|
|
||||||
|
// some of the tests assign `MatrixClientPeg.matrixClient`: clear it, to prevent leakage between tests
|
||||||
|
peg.unset();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("setJustRegisteredUserId", () => {
|
it("setJustRegisteredUserId", () => {
|
||||||
|
|
|
@ -15,15 +15,14 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { render, screen } from "@testing-library/react";
|
import { fireEvent, render, screen } from "@testing-library/react";
|
||||||
|
|
||||||
import LabsUserSettingsTab from "../../../../../../src/components/views/settings/tabs/user/LabsUserSettingsTab";
|
import LabsUserSettingsTab from "../../../../../../src/components/views/settings/tabs/user/LabsUserSettingsTab";
|
||||||
import SettingsStore from "../../../../../../src/settings/SettingsStore";
|
import SettingsStore from "../../../../../../src/settings/SettingsStore";
|
||||||
import SdkConfig from "../../../../../../src/SdkConfig";
|
import SdkConfig from "../../../../../../src/SdkConfig";
|
||||||
|
import { SettingLevel } from "../../../../../../src/settings/SettingLevel";
|
||||||
|
|
||||||
describe("<LabsUserSettingsTab />", () => {
|
describe("<LabsUserSettingsTab />", () => {
|
||||||
const sdkConfigSpy = jest.spyOn(SdkConfig, "get");
|
|
||||||
|
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
closeSettingsFn: jest.fn(),
|
closeSettingsFn: jest.fn(),
|
||||||
};
|
};
|
||||||
|
@ -34,7 +33,9 @@ describe("<LabsUserSettingsTab />", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
settingsValueSpy.mockReturnValue(false);
|
settingsValueSpy.mockReturnValue(false);
|
||||||
sdkConfigSpy.mockReturnValue(false);
|
SdkConfig.reset();
|
||||||
|
SdkConfig.add({ brand: "BrandedClient" });
|
||||||
|
localStorage.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders settings marked as beta as beta cards", () => {
|
it("renders settings marked as beta as beta cards", () => {
|
||||||
|
@ -43,6 +44,7 @@ describe("<LabsUserSettingsTab />", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not render non-beta labs settings when disabled in config", () => {
|
it("does not render non-beta labs settings when disabled in config", () => {
|
||||||
|
const sdkConfigSpy = jest.spyOn(SdkConfig, "get");
|
||||||
render(getComponent());
|
render(getComponent());
|
||||||
expect(sdkConfigSpy).toHaveBeenCalledWith("show_labs_settings");
|
expect(sdkConfigSpy).toHaveBeenCalledWith("show_labs_settings");
|
||||||
|
|
||||||
|
@ -52,7 +54,7 @@ describe("<LabsUserSettingsTab />", () => {
|
||||||
|
|
||||||
it("renders non-beta labs settings when enabled in config", () => {
|
it("renders non-beta labs settings when enabled in config", () => {
|
||||||
// enable labs
|
// enable labs
|
||||||
sdkConfigSpy.mockImplementation((configName) => configName === "show_labs_settings");
|
SdkConfig.add({ show_labs_settings: true });
|
||||||
const { container } = render(getComponent());
|
const { container } = render(getComponent());
|
||||||
|
|
||||||
// non-beta labs section
|
// non-beta labs section
|
||||||
|
@ -60,4 +62,82 @@ describe("<LabsUserSettingsTab />", () => {
|
||||||
const labsSections = container.getElementsByClassName("mx_SettingsSubsection");
|
const labsSections = container.getElementsByClassName("mx_SettingsSubsection");
|
||||||
expect(labsSections).toHaveLength(9);
|
expect(labsSections).toHaveLength(9);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Rust crypto setting", () => {
|
||||||
|
const SETTING_NAME = "Rust cryptography implementation";
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
SdkConfig.add({ show_labs_settings: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Not enabled in config", () => {
|
||||||
|
it("can be turned on if not already", async () => {
|
||||||
|
// By the time the settings panel is shown, `MatrixClientPeg.initClientCrypto` has saved the current
|
||||||
|
// value to the settings store.
|
||||||
|
await SettingsStore.setValue("feature_rust_crypto", null, SettingLevel.DEVICE, false);
|
||||||
|
|
||||||
|
const rendered = render(getComponent());
|
||||||
|
const toggle = rendered.getByRole("switch", { name: SETTING_NAME });
|
||||||
|
expect(toggle.getAttribute("aria-disabled")).toEqual("false");
|
||||||
|
expect(toggle.getAttribute("aria-checked")).toEqual("false");
|
||||||
|
|
||||||
|
const description = toggle.closest(".mx_SettingsFlag")?.querySelector(".mx_SettingsFlag_microcopy");
|
||||||
|
expect(description).toHaveTextContent(/To disable you will need to log out and back in/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("cannot be turned off once enabled", async () => {
|
||||||
|
await SettingsStore.setValue("feature_rust_crypto", null, SettingLevel.DEVICE, true);
|
||||||
|
|
||||||
|
const rendered = render(getComponent());
|
||||||
|
const toggle = rendered.getByRole("switch", { name: SETTING_NAME });
|
||||||
|
expect(toggle.getAttribute("aria-disabled")).toEqual("true");
|
||||||
|
expect(toggle.getAttribute("aria-checked")).toEqual("true");
|
||||||
|
|
||||||
|
// Hover over the toggle to make it show the tooltip
|
||||||
|
fireEvent.mouseOver(toggle);
|
||||||
|
|
||||||
|
const tooltip = rendered.getByRole("tooltip");
|
||||||
|
expect(tooltip).toHaveTextContent(
|
||||||
|
"Once enabled, Rust cryptography can only be disabled by logging out and in again",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Enabled in config", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
SdkConfig.add({ features: { feature_rust_crypto: true } });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("can be turned on if not already", async () => {
|
||||||
|
// By the time the settings panel is shown, `MatrixClientPeg.initClientCrypto` has saved the current
|
||||||
|
// value to the settings store.
|
||||||
|
await SettingsStore.setValue("feature_rust_crypto", null, SettingLevel.DEVICE, false);
|
||||||
|
|
||||||
|
const rendered = render(getComponent());
|
||||||
|
const toggle = rendered.getByRole("switch", { name: SETTING_NAME });
|
||||||
|
expect(toggle.getAttribute("aria-disabled")).toEqual("false");
|
||||||
|
expect(toggle.getAttribute("aria-checked")).toEqual("false");
|
||||||
|
|
||||||
|
const description = toggle.closest(".mx_SettingsFlag")?.querySelector(".mx_SettingsFlag_microcopy");
|
||||||
|
expect(description).toHaveTextContent(/It cannot be disabled/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("cannot be turned off once enabled", async () => {
|
||||||
|
await SettingsStore.setValue("feature_rust_crypto", null, SettingLevel.DEVICE, true);
|
||||||
|
|
||||||
|
const rendered = render(getComponent());
|
||||||
|
const toggle = rendered.getByRole("switch", { name: SETTING_NAME });
|
||||||
|
expect(toggle.getAttribute("aria-disabled")).toEqual("true");
|
||||||
|
expect(toggle.getAttribute("aria-checked")).toEqual("true");
|
||||||
|
|
||||||
|
// Hover over the toggle to make it show the tooltip
|
||||||
|
fireEvent.mouseOver(toggle);
|
||||||
|
|
||||||
|
const tooltip = rendered.getByRole("tooltip");
|
||||||
|
expect(tooltip).toHaveTextContent(
|
||||||
|
"Rust cryptography cannot be disabled on this deployment of BrandedClient",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,7 +15,7 @@ exports[`<LabsUserSettingsTab /> renders settings marked as beta as beta cards 1
|
||||||
<div
|
<div
|
||||||
class="mx_SettingsSubsection_text"
|
class="mx_SettingsSubsection_text"
|
||||||
>
|
>
|
||||||
What's next for false? Labs are the best way to get things early, test out new features and help shape them before they actually launch.
|
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>
|
||||||
<div
|
<div
|
||||||
class="mx_BetaCard"
|
class="mx_BetaCard"
|
||||||
|
@ -42,10 +42,10 @@ exports[`<LabsUserSettingsTab /> renders settings marked as beta as beta cards 1
|
||||||
class="mx_BetaCard_caption"
|
class="mx_BetaCard_caption"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
A new way to chat over voice and video in .
|
A new way to chat over voice and video in BrandedClient.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Video rooms are always-on VoIP channels embedded within a room in .
|
Video rooms are always-on VoIP channels embedded within a room in BrandedClient.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -62,7 +62,7 @@ exports[`<LabsUserSettingsTab /> renders settings marked as beta as beta cards 1
|
||||||
<div
|
<div
|
||||||
class="mx_BetaCard_refreshWarning"
|
class="mx_BetaCard_refreshWarning"
|
||||||
>
|
>
|
||||||
Joining the beta will reload .
|
Joining the beta will reload BrandedClient.
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="mx_BetaCard_faq"
|
class="mx_BetaCard_faq"
|
||||||
|
@ -104,7 +104,7 @@ exports[`<LabsUserSettingsTab /> renders settings marked as beta as beta cards 1
|
||||||
class="mx_BetaCard_caption"
|
class="mx_BetaCard_caption"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
Introducing a simpler way to change your notification settings. Customize your , just the way you like.
|
Introducing a simpler way to change your notification settings. Customize your BrandedClient, just the way you like.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
Loading…
Reference in a new issue