Files
rea/tests/boundary/filesystem/vscodeUserDataSetup.test.ts
T
2026-10-27 05:42:50 +08:00

117 lines
4.2 KiB
TypeScript

import { access, mkdir, readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { parse } from "jsonc-parser";
import { expect, it } from "vitest";
import { supportedClients } from "../../../src/application/SupportedClients.js";
import { configureClientConfiguration } from "../../../src/application/SetupClientConfiguration.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
it("registers VS Code in VSCODE_APPDATA and preserves its configuration", async () => {
const root = await createTestTempDirectory("rea-vscode-appdata-");
const home = join(root, "home");
const appdata = join(root, "selected data");
const expectedPath = join(appdata, "Code", "User", "mcp.json");
await mkdir(join(appdata, "Code", "User"), { recursive: true });
const original =
'{\n // Keep this comment.\n "servers": {"other": {"command": "other"}}\n}\n';
await writeFile(expectedPath, original);
const client = supportedClients(home, "linux", {
VSCODE_APPDATA: appdata,
}).find(({ name }) => name === "vscode");
expect(client).toBeDefined();
if (client === undefined) throw new Error("VS Code client missing");
expect(
await configureClientConfiguration(client, {}, ["rea", "mcp"]),
).toMatchObject({ status: "configured" });
expect(parse(await readFile(expectedPath, "utf8"))).toMatchObject({
servers: {
other: { command: "other" },
rea: { command: "rea", args: ["mcp"] },
},
});
expect(await readFile(expectedPath, "utf8")).toContain(
"// Keep this comment.",
);
expect(await readFile(`${expectedPath}.rea.backup`, "utf8")).toBe(original);
expect(
await configureClientConfiguration(client, {}, ["rea", "mcp"]),
).toMatchObject({ status: "unchanged" });
await expect(access(join(home, ".config", "Code"))).rejects.toMatchObject({
code: "ENOENT",
});
});
it.each([
{
name: "portable wins over appdata",
env: { VSCODE_PORTABLE: "portable", VSCODE_APPDATA: "ignored" },
suffix: "portable/user-data",
},
{
name: "empty portable allows appdata",
env: { VSCODE_PORTABLE: "", VSCODE_APPDATA: "appdata" },
suffix: "appdata/Code",
},
{
name: "relative appdata uses VSCODE_CWD",
env: { VSCODE_APPDATA: "appdata" },
suffix: "appdata/Code",
},
{
name: "empty overrides use relative XDG default",
env: { VSCODE_PORTABLE: "", VSCODE_APPDATA: "", XDG_CONFIG_HOME: "xdg" },
suffix: "xdg/Code",
},
])("writes the selected VS Code file when $name", async ({ env, suffix }) => {
const root = await createTestTempDirectory("rea-vscode-precedence-");
const home = join(root, "home");
const expectedPath = join(root, suffix, "User", "mcp.json");
const client = supportedClients(home, "linux", {
...env,
VSCODE_CWD: root,
}).find(({ name }) => name === "vscode");
expect(client?.configPath).toBe(expectedPath);
if (client === undefined) throw new Error("VS Code client missing");
expect(
await configureClientConfiguration(client, {}, ["rea", "mcp"]),
).toMatchObject({ status: "configured" });
expect(parse(await readFile(expectedPath, "utf8"))).toMatchObject({
servers: { rea: { command: "rea" } },
});
await expect(access(join(home, ".config", "Code"))).rejects.toMatchObject({
code: "ENOENT",
});
});
it.each(["", undefined])(
"resolves relative VS Code data against cwd when VSCODE_CWD is %s",
(cwd) => {
const client = supportedClients("/unused-home", "linux", {
VSCODE_APPDATA: "relative data",
VSCODE_CWD: cwd,
}).find(({ name }) => name === "vscode");
expect(client?.configPath).toBe(
join(process.cwd(), "relative data", "Code", "User", "mcp.json"),
);
},
);
it.each([
{ platform: "linux", suffix: ".config/Code/User/mcp.json" },
{
platform: "darwin",
suffix: "Library/Application Support/Code/User/mcp.json",
},
{ platform: "win32", suffix: "AppData/Roaming/Code/User/mcp.json" },
] as const)(
"retains the $platform default without VS Code overrides",
async ({ platform, suffix }) => {
const home = await createTestTempDirectory("rea-vscode-default-");
const client = supportedClients(home, platform, {}).find(
({ name }) => name === "vscode",
);
expect(client?.configPath).toBe(join(home, suffix));
},
);