Files
rea/tests/boundary/filesystem/qwenClientConfiguration.test.ts
Ysopwnable 16d9c5adef fix(ci): preserve cleanup boundaries and bounded failure assertions (#1618)
Interrupt optional CDP domain shutdown on caller cancellation while preserving an independent bounded detach attempt. Retain original overflow and cleanup failures, verify workspace recovery, preserve user skill files, and reject another unverified firmware worker.

Validation: 149 integrated tests; repeated 64 affected boundary tests; full local check. Standalone CI includes real Chrome CLI/stdio MCP and real Web runtime checks.

Refs #1613
2026-10-11 02:54:12 +08:00

192 lines
7.2 KiB
TypeScript

import { access, mkdir, readFile, writeFile } from "node:fs/promises";
import { join, resolve } from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { parse as parseJsonc } from "jsonc-parser";
import { readClientRegistrationStatuses } from "../../../src/application/ClientRegistrationStatus.js";
import { configureClientConfiguration } from "../../../src/application/SetupClientConfiguration.js";
import { systemSetupHost } from "../../../src/application/SetupHost.js";
import { MANAGED_SKILL_FILES } from "../../../src/application/SetupSkill.js";
import { supportedClients } from "../../../src/application/SupportedClients.js";
import { systemUninstallHost } from "../../../src/application/Uninstall.js";
import { PRODUCT_IDENTITY } from "../../../src/identity.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import {
clearClientLocationEnvironment,
NPX_REGISTRATION_COMMAND,
} from "../../fixtures/clientEnvironment.js";
const command = NPX_REGISTRATION_COMMAND;
beforeEach(clearClientLocationEnvironment);
afterEach(() => vi.unstubAllEnvs());
const qwenPath = (
home: string,
platform: NodeJS.Platform,
env: Parameters<typeof supportedClients>[2] = {},
) =>
supportedClients(home, platform, env).find(
({ name }) => name === "qwen_code",
);
describe("Qwen Code configuration paths", () => {
it("resolves the user settings file and marker directory", () => {
expect(qwenPath("/home/a", "linux")).toEqual({
name: "qwen_code",
displayName: "Qwen Code",
configPath: join("/home/a", ".qwen", "settings.json"),
markerPath: join("/home/a", ".qwen"),
format: "json",
});
expect(qwenPath("/Users/a", "darwin")?.configPath).toBe(
join("/Users/a", ".qwen", "settings.json"),
);
});
it.each([
["", join("/home/a", ".qwen")],
["~", "/home/a"],
["~/profiles/work", join("/home/a", "profiles", "work")],
["~\\profiles\\work", join("/home/a", "profiles", "work")],
["profiles/work", resolve("profiles/work")],
[" profile ", resolve(" profile ")],
["$PROFILE", resolve("$PROFILE")],
])("matches Qwen's QWEN_HOME resolution for %j", (override, directory) => {
vi.stubEnv("QWEN_HOME", override);
const client = qwenPath("/home/a", process.platform, {
QWEN_HOME: override,
});
expect(
supportedClients("/home/a").find(({ name }) => name === "qwen_code"),
).toEqual(client);
expect(client).toMatchObject({
configPath: join(directory, "settings.json"),
markerPath: directory,
});
});
});
describe("Qwen Code client lifecycle", () => {
const qwenClient = async () => {
const home = await createTestTempDirectory("rea-qwen-");
const client = qwenPath(home, process.platform, {});
if (client?.markerPath === undefined)
throw new Error("missing Qwen Code client");
await mkdir(client.markerPath, { recursive: true });
return { home, client };
};
it("registers rea in mcpServers while preserving unrelated settings and comments", async () => {
const { home, client } = await qwenClient();
await writeFile(
client.configPath,
`{
// Keep this note.
"model": { "name": "qwen3-coder-plus" },
"mcpServers": { "other": { "command": "other-server" } }
}
`,
);
expect(
(await configureClientConfiguration(client, {}, command)).status,
).toBe("configured");
const text = await readFile(client.configPath, "utf8");
expect(text).toContain("// Keep this note.");
expect(parseJsonc(text)).toEqual({
model: { name: "qwen3-coder-plus" },
mcpServers: {
other: { command: "other-server" },
rea: { command: "npx", args: command.slice(1) },
},
});
expect(await configureClientConfiguration(client, {}, command)).toEqual({
status: "unchanged",
});
expect((await systemUninstallHost(home).removeClient(client)).status).toBe(
"removed",
);
const removedText = await readFile(client.configPath, "utf8");
const removed = parseJsonc(removedText);
expect(removed).toEqual({
model: { name: "qwen3-coder-plus" },
mcpServers: { other: { command: "other-server" } },
});
expect(removedText).toContain("// Keep this note.");
});
it("reports a package-runner registration as aligned", async () => {
const { home, client } = await qwenClient();
expect(
(await configureClientConfiguration(client, {}, command)).status,
).toBe("configured");
const entry = resolve("scripts/rea.mjs");
const status = (
await readClientRegistrationStatuses(home, entry, { environment: {} })
).find(({ client: name }) => name === "qwen_code");
expect(status).toMatchObject({ state: "aligned" });
});
});
describe("Qwen Code profile setup", () => {
it.each([false, true])(
"installs and removes the shared skill with a custom home: %s",
async (customHome) => {
const home = await createTestTempDirectory("rea-qwen-profile-");
const profile = join(home, customHome ? "qwen-profile" : ".qwen");
const environment = {
HOME: home,
USERPROFILE: home,
...(customHome ? { QWEN_HOME: profile } : {}),
};
await mkdir(profile);
const setup = systemSetupHost(undefined, environment);
const client = (await setup.detectedClients()).find(
({ name }) => name === "qwen_code",
);
if (client === undefined) throw new Error("missing Qwen Code client");
expect(client.configPath).toBe(join(profile, "settings.json"));
expect(await setup.configureClient(client, {}, command)).toEqual({
status: "configured",
});
expect(await setup.installSkill([client.name])).toBe("installed");
const skill = join(home, ".agents", "skills", PRODUCT_IDENTITY.skillName);
await writeFile(join(skill, "user-notes.txt"), "user-authored");
expect(await readFile(join(skill, "SKILL.md"), "utf8")).toContain(
"reverse-engineer-anything",
);
expect(await setup.clientNeedsConfigure(client, {}, command)).toBe(false);
expect(await setup.skillNeedsInstall([client.name])).toBe(false);
expect(await setup.installSkill([client.name])).toBe("unchanged");
expect(
(
await readClientRegistrationStatuses(
home,
resolve("scripts/rea.mjs"),
{ environment },
)
).find(({ client: name }) => name === "qwen_code"),
).toMatchObject({ state: "aligned" });
const uninstall = systemUninstallHost(home, undefined, environment);
const registered = (await uninstall.clients()).find(
({ name }) => name === "qwen_code",
);
expect(registered).toEqual(client);
expect((await uninstall.removeClient(client)).status).toBe("removed");
expect((await uninstall.removeSkill()).status).toBe("removed");
for (const relativePath of MANAGED_SKILL_FILES)
await expect(access(join(skill, relativePath))).rejects.toMatchObject({
code: "ENOENT",
});
expect(await readFile(join(skill, "user-notes.txt"), "utf8")).toBe(
"user-authored",
);
if (customHome)
await expect(access(join(home, ".qwen"))).rejects.toMatchObject({
code: "ENOENT",
});
},
);
});