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
This commit is contained in:
Will Hunt 2024-10-17 13:26:35 +01:00 committed by GitHub
parent 7886e4c604
commit 7b669a8313
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 80 additions and 5 deletions

View File

@ -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 the above created by a pre-1.7 install, in which case it will be `Riot` or
`Riot-$PROFILE`. `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 # Translations
To add a new translation, head to the [translating doc](https://github.com/vector-im/element-web/blob/develop/docs/translating.md). To add a new translation, head to the [translating doc](https://github.com/vector-im/element-web/blob/develop/docs/translating.md).

View File

@ -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();
});
});
});

View File

@ -11,7 +11,16 @@ import fs from "node:fs/promises";
import path from "node:path"; import path from "node:path";
import os from "node:os"; import os from "node:os";
export const test = base.extend<{ app: ElectronApplication; tmpDir: string }>({ interface Fixtures {
app: ElectronApplication;
tmpDir: string;
extraEnv: Record<string, string>;
extraArgs: string[];
}
export const test = base.extend<Fixtures>({
extraEnv: {},
extraArgs: [],
// eslint-disable-next-line no-empty-pattern // eslint-disable-next-line no-empty-pattern
tmpDir: async ({}, use) => { tmpDir: async ({}, use) => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "element-desktop-tests-")); 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 use(tmpDir);
await fs.rm(tmpDir, { recursive: true }); await fs.rm(tmpDir, { recursive: true });
}, },
app: async ({ tmpDir }, use) => { app: async ({ tmpDir, extraEnv, extraArgs }, use) => {
const args = ["--profile-dir", tmpDir]; const args = ["--profile-dir", tmpDir];
const executablePath = process.env["ELEMENT_DESKTOP_EXECUTABLE"]; 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({ const app = await electron.launch({
env: process.env, env: {
...process.env,
...extraEnv,
},
executablePath, executablePath,
args, args: [...args, ...extraArgs],
}); });
app.process().stdout.pipe(process.stdout); app.process().stdout.pipe(process.stdout);

View File

@ -0,0 +1,10 @@
{
"default_server_config": {
"m.homeserver": {
"base_url": "https://matrix.example.org"
},
"m.identity_server": {
"base_url": "https://identity.example.org"
}
}
}

View File

@ -44,6 +44,10 @@ if (argv["help"]) {
console.log(" --profile-dir {path}: Path to where to store the profile."); 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(" --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(" --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(" --no-update: Disable automatic updating.");
console.log(" --hidden: Start the application hidden in the system tray."); console.log(" --hidden: Start the application hidden in the system tray.");
console.log(" --help: Displays this help message."); console.log(" --help: Displays this help message.");
@ -51,6 +55,8 @@ if (argv["help"]) {
app.exit(); app.exit();
} }
const LocalConfigLocation = process.env.ELEMENT_DESKTOP_CONFIG_JSON ?? argv["config"];
// Electron creates the user data directory (with just an empty 'Dictionaries' directory...) // 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 // 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. // real user data directory.
@ -147,7 +153,9 @@ async function loadConfig(): Promise<void> {
try { try {
// Load local config and use it to override values from the one baked with the build // 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 // 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 // config. This is to avoid a problem where Riot thinks there are multiple homeservers