From 7b669a8313a32c0c84eb26c93569b2112670f51c Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Thu, 17 Oct 2024 13:26:35 +0100 Subject: [PATCH] Support specifying the config location manually (outside of the user's profile) (#1921) * Add support for loading the config from a given config location. * Support using an env variable too. * Add docs. * Add test for configuration arguments * remove .only --- README.md | 4 ++ playwright/e2e/launch/config-options.spec.ts | 41 ++++++++++++++++++++ playwright/element-desktop-test.ts | 20 ++++++++-- playwright/fixtures/custom-config.json | 10 +++++ src/electron-main.ts | 10 ++++- 5 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 playwright/e2e/launch/config-options.spec.ts create mode 100644 playwright/fixtures/custom-config.json diff --git a/README.md b/README.md index f39e2cb..e284729 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,10 @@ $PROFILE` in which case it becomes `Element-$PROFILE`, or it is using one of the above created by a pre-1.7 install, in which case it will be `Riot` or `Riot-$PROFILE`. +You may also specify a different path entirely for the `config.json` file by +providing the `--config $YOUR_CONFIG_JSON_FILE` to the process, or via the +`ELEMENT_DESKTOP_CONFIG_JSON` environment variable. + # Translations To add a new translation, head to the [translating doc](https://github.com/vector-im/element-web/blob/develop/docs/translating.md). diff --git a/playwright/e2e/launch/config-options.spec.ts b/playwright/e2e/launch/config-options.spec.ts new file mode 100644 index 0000000..90afb19 --- /dev/null +++ b/playwright/e2e/launch/config-options.spec.ts @@ -0,0 +1,41 @@ +/* +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 { resolve } from "node:path"; + +import { test, expect } from "../../element-desktop-test"; + +test.describe("App config options", () => { + test.describe("Should load custom config via env", () => { + test.slow(); + test.use({ + extraEnv: { + ELEMENT_DESKTOP_CONFIG_JSON: resolve(__dirname, "../..", "fixtures/custom-config.json"), + }, + }); + test("should launch and use configured homeserver", async ({ page }) => { + await page.locator("#matrixchat").waitFor(); + await page.locator(".mx_Welcome").waitFor(); + await expect(page).toHaveURL("vector://vector/webapp/#/welcome"); + await page.getByText("Sign in").click(); + await page.getByText("matrix.example.org", { exact: true }).waitFor(); + }); + }); + test.describe("Should load custom config via argument", () => { + test.slow(); + test.use({ + extraArgs: ["--config", resolve(__dirname, "../..", "fixtures/custom-config.json")], + }); + test("should launch and use configured homeserver", async ({ page }) => { + await page.locator("#matrixchat").waitFor(); + await page.locator(".mx_Welcome").waitFor(); + await expect(page).toHaveURL("vector://vector/webapp/#/welcome"); + await page.getByText("Sign in").click(); + await page.getByText("matrix.example.org", { exact: true }).waitFor(); + }); + }); +}); diff --git a/playwright/element-desktop-test.ts b/playwright/element-desktop-test.ts index 49d4e13..4bdf691 100644 --- a/playwright/element-desktop-test.ts +++ b/playwright/element-desktop-test.ts @@ -11,7 +11,16 @@ import fs from "node:fs/promises"; import path from "node:path"; import os from "node:os"; -export const test = base.extend<{ app: ElectronApplication; tmpDir: string }>({ +interface Fixtures { + app: ElectronApplication; + tmpDir: string; + extraEnv: Record; + extraArgs: string[]; +} + +export const test = base.extend({ + extraEnv: {}, + extraArgs: [], // eslint-disable-next-line no-empty-pattern tmpDir: async ({}, use) => { const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "element-desktop-tests-")); @@ -19,7 +28,7 @@ export const test = base.extend<{ app: ElectronApplication; tmpDir: string }>({ await use(tmpDir); await fs.rm(tmpDir, { recursive: true }); }, - app: async ({ tmpDir }, use) => { + app: async ({ tmpDir, extraEnv, extraArgs }, use) => { const args = ["--profile-dir", tmpDir]; const executablePath = process.env["ELEMENT_DESKTOP_EXECUTABLE"]; @@ -29,9 +38,12 @@ export const test = base.extend<{ app: ElectronApplication; tmpDir: string }>({ } const app = await electron.launch({ - env: process.env, + env: { + ...process.env, + ...extraEnv, + }, executablePath, - args, + args: [...args, ...extraArgs], }); app.process().stdout.pipe(process.stdout); diff --git a/playwright/fixtures/custom-config.json b/playwright/fixtures/custom-config.json new file mode 100644 index 0000000..bcbc938 --- /dev/null +++ b/playwright/fixtures/custom-config.json @@ -0,0 +1,10 @@ +{ + "default_server_config": { + "m.homeserver": { + "base_url": "https://matrix.example.org" + }, + "m.identity_server": { + "base_url": "https://identity.example.org" + } + } +} diff --git a/src/electron-main.ts b/src/electron-main.ts index 5a948cb..76547ae 100644 --- a/src/electron-main.ts +++ b/src/electron-main.ts @@ -44,6 +44,10 @@ if (argv["help"]) { console.log(" --profile-dir {path}: Path to where to store the profile."); console.log(" --profile {name}: Name of alternate profile to use, allows for running multiple accounts."); console.log(" --devtools: Install and use react-devtools and react-perf."); + console.log( + ` --config: Path to the config.json file. May also be specified via the ELEMENT_DESKTOP_CONFIG_JSON environment variable.\n` + + ` Otherwise use the default user location '${app.getPath("userData")}'`, + ); console.log(" --no-update: Disable automatic updating."); console.log(" --hidden: Start the application hidden in the system tray."); console.log(" --help: Displays this help message."); @@ -51,6 +55,8 @@ if (argv["help"]) { app.exit(); } +const LocalConfigLocation = process.env.ELEMENT_DESKTOP_CONFIG_JSON ?? argv["config"]; + // Electron creates the user data directory (with just an empty 'Dictionaries' directory...) // as soon as the app path is set, so pick a random path in it that must exist if it's a // real user data directory. @@ -147,7 +153,9 @@ async function loadConfig(): Promise { try { // Load local config and use it to override values from the one baked with the build - const localConfig = loadJsonFile(app.getPath("userData"), "config.json"); + const localConfig = LocalConfigLocation + ? loadJsonFile(LocalConfigLocation) + : loadJsonFile(app.getPath("userData"), "config.json"); // If the local config has a homeserver defined, don't use the homeserver from the build // config. This is to avoid a problem where Riot thinks there are multiple homeservers