Files
reverse-engineering-anything/src/setupEnvironment.test.ts
T
Swatantra Yadav 2abfe53dbd fix(setup): preserve overridden runner variables and test isolation on Windows
Support case-insensitive environment value lookup in ClientRegistrationIdentity while preserving JavaScript property order precedence with findLast(). Add unit regression coverage for ambient uppercase npm variables on Windows. Isolate USERPROFILE in cliSetup tests so child processes do not touch the host profile directory. Harden JSON decision extraction in runJourney against ConPTY trailing ANSI escape codes. Deterministically sequence multiselect prompt navigation before confirmation. Filter ambient runner variables case-insensitively before launching interactive setup completion tests.
2026-10-15 00:56:31 +05:30

194 lines
6.8 KiB
TypeScript

import { mkdtemp, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, expect, it, vi } from "vitest";
import { createDoctorHostFixture } from "./application/Doctor.fixture.js";
import { runSetup } from "./application/Setup.js";
import { options } from "./application/Setup.fixture.js";
import { systemSetupHost } from "./application/SetupHost.js";
import { systemUninstallHost } from "./application/Uninstall.js";
import { runUpdateCommand } from "./application/UpdateRuntime.js";
import { createSystemDoctorHost } from "./doctorRuntime.js";
import { PRODUCT_IDENTITY } from "./identity.js";
import {
invokingPackageRunner,
packageRunnerRegistrationCommand,
withoutPackageRunnerIdentity,
} from "./application/ClientRegistrationIdentity.js";
import { snapshotEnvironment } from "./process/snapshotEnvironment.js";
afterEach(() => vi.unstubAllEnvs());
it("plans setup and uninstall against selected home and client overrides", async () => {
const root = await mkdtemp(join(tmpdir(), "rea-selected-setup-"));
const environment = {
HOME: join(root, "selected-home"),
USERPROFILE: join(root, "selected-home"),
CODEX_HOME: join(root, "selected-codex"),
npm_command: "exec",
};
vi.stubEnv("HOME", join(root, "ambient-home"));
vi.stubEnv("CODEX_HOME", join(root, "ambient-codex"));
vi.stubEnv("npm_command", "other");
try {
const doctor = createDoctorHostFixture({ homeDirectory: environment.HOME });
const host = systemSetupHost(doctor, environment);
const result = await runSetup(
{
...options(false),
dryRun: true,
clientIds: ["codex"],
installSkill: true,
},
host,
);
expect(result.status).toBe("planned");
expect(result.plannedActions).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: "configure_client:codex",
target: join(environment.CODEX_HOME, "config.toml"),
}),
expect.objectContaining({
id: "install_skill",
target: join(
environment.HOME,
".agents/skills",
PRODUCT_IDENTITY.skillName,
),
}),
]),
);
expect(host.registrationCommand).toContain(
PRODUCT_IDENTITY.registrationPackageSpecifier,
);
const clients = await systemUninstallHost(
environment.HOME,
undefined,
environment,
).clients();
expect(clients.find(({ name }) => name === "codex")?.configPath).toBe(
join(environment.CODEX_HOME, "config.toml"),
);
expect(JSON.stringify(result)).not.toContain("ambient-");
} finally {
await rm(root, { recursive: true, force: true });
}
});
it("composes provider diagnostics from selected configuration rather than ambient configuration", async () => {
vi.stubEnv("GHIDRA_INSTALL_DIR", "/ambient/ghidra");
vi.stubEnv("REA_IDA_MCP_CONFIG", "/ambient/ida.json");
const host = createSystemDoctorHost({
GHIDRA_INSTALL_DIR: "/selected/ghidra",
REA_IDA_MCP_CONFIG: "/selected/ida.json",
});
const inspections = await host.providerInspections?.();
expect(inspections?.find(({ id }) => id === "ghidra")?.configured).toBe(true);
expect(JSON.stringify(inspections)).toContain("/selected/ghidra");
expect(JSON.stringify(inspections)).toContain("/selected/ida.json");
expect(JSON.stringify(inspections)).not.toContain("/ambient/");
});
it("preserves a validated selected JEB endpoint in setup registrations without claiming live readiness", async () => {
const root = await mkdtemp(join(tmpdir(), "rea-jeb-setup-"));
const endpoint = "http://127.0.0.1:8425/mcp/";
const ambientEndpoint = "http://127.0.0.1:8426/mcp";
vi.stubEnv("REA_JEB_MCP_URL", ambientEndpoint);
try {
const environment = {
HOME: root,
USERPROFILE: root,
CODEX_HOME: join(root, "codex"),
REA_JEB_MCP_URL: endpoint,
};
const doctorHost = createSystemDoctorHost(environment);
const setupHost = systemSetupHost(doctorHost, environment);
const state = await setupHost.initialSetupState();
expect(state.providerEnvironment).toHaveProperty(
"REA_JEB_MCP_URL",
endpoint,
);
const planned = await runSetup(
{
...options(false),
dryRun: true,
clientIds: ["codex"],
installSkill: false,
},
setupHost,
);
expect(planned.status).toBe("planned");
expect(JSON.stringify(planned.plannedActions)).toContain(endpoint);
expect(JSON.stringify(planned.plannedActions)).not.toContain(
ambientEndpoint,
);
expect(
createSystemDoctorHost({}).providerRegistrationEnvironment?.(),
).toEqual({});
expect(
createSystemDoctorHost({
REA_JEB_MCP_URL: "http://127.0.0.1:8425/mcp",
}).providerRegistrationEnvironment?.(),
).toEqual({ REA_JEB_MCP_URL: "http://127.0.0.1:8425/mcp" });
expect(
createSystemDoctorHost({
REA_JEB_MCP_URL: "https://example.com/mcp",
}).providerRegistrationEnvironment?.(),
).toEqual({});
} finally {
vi.unstubAllEnvs();
await rm(root, { recursive: true, force: true });
}
});
it("passes only selected environment to updater subprocesses and drops npm invocation identity", async () => {
vi.stubEnv("REA_UPDATE_MARKER", "ambient");
const result = await runUpdateCommand(
[
process.execPath,
"-e",
"process.stdout.write(JSON.stringify({marker:process.env.REA_UPDATE_MARKER,npm:process.env.npm_command,ambient:process.env.HOME}))",
],
{ REA_UPDATE_MARKER: "selected", npm_command: "exec" },
);
expect(result).toEqual({ ok: true, value: '{"marker":"selected"}' });
});
it.each([
{ userAgent: "npm/10.9.0 node/v24.11.0 win32 x64", runner: "npx" },
{ userAgent: "bun/1.4.2 npm/? node/v26.3.0 win32 x64", runner: "bunx" },
] as const)(
"registers the $runner launcher from a Windows CLI environment snapshot",
({ userAgent, runner }) => {
// The CLI snapshot canonicalizes Windows variable names to upper case.
const environment = snapshotEnvironment(
{ npm_command: "exec", npm_config_user_agent: userAgent },
"win32",
);
expect(invokingPackageRunner(environment, "win32")).toBe(runner);
expect(
systemSetupHost(
createDoctorHostFixture({ platform: "win32" }),
environment,
).registrationCommand,
).toEqual(packageRunnerRegistrationCommand(runner, "win32"));
expect(withoutPackageRunnerIdentity(environment, "win32")).toEqual({
NPM_CONFIG_USER_AGENT: userAgent,
});
},
);
it("prioritizes overridden package runner environment variables over ambient keys with differing case on Windows", () => {
const environment = {
NPM_COMMAND: "run",
npm_command: "exec",
NPM_CONFIG_USER_AGENT: "npm/10.9.0 node/v24.11.0 win32 x64",
};
expect(invokingPackageRunner(environment, "win32")).toBe("npx");
});