95 lines
3.2 KiB
TypeScript
95 lines
3.2 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
|
|
const prompts = vi.hoisted(() => ({
|
|
note: vi.fn(),
|
|
multiselect: vi.fn(async () => {
|
|
throw new Error("interactive multiselect should not run in non-TTY onboarding");
|
|
}),
|
|
select: vi.fn(async () => {
|
|
throw new Error("interactive select should not run in non-TTY onboarding");
|
|
}),
|
|
confirm: vi.fn(async () => true),
|
|
isCancel: vi.fn(() => false),
|
|
cancel: vi.fn(),
|
|
log: {
|
|
warn: vi.fn(),
|
|
step: vi.fn(),
|
|
error: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
vi.mock("@clack/prompts", () => prompts);
|
|
vi.mock("../src/cli/connect/index.js", () => ({
|
|
resolveAdapter: vi.fn(),
|
|
runAdapter: vi.fn(),
|
|
}));
|
|
|
|
const ORIGINAL_HOME = process.env["HOME"];
|
|
const ORIGINAL_USERPROFILE = process.env["USERPROFILE"];
|
|
const stdinTtyDescriptor = Object.getOwnPropertyDescriptor(process.stdin, "isTTY");
|
|
const stdoutTtyDescriptor = Object.getOwnPropertyDescriptor(process.stdout, "isTTY");
|
|
|
|
let sandboxHome: string;
|
|
|
|
function setTTY(value: boolean): void {
|
|
Object.defineProperty(process.stdin, "isTTY", { value, configurable: true });
|
|
Object.defineProperty(process.stdout, "isTTY", { value, configurable: true });
|
|
}
|
|
|
|
function restoreTTY(): void {
|
|
if (stdinTtyDescriptor) Object.defineProperty(process.stdin, "isTTY", stdinTtyDescriptor);
|
|
else delete (process.stdin as NodeJS.ReadStream & { isTTY?: boolean }).isTTY;
|
|
if (stdoutTtyDescriptor) Object.defineProperty(process.stdout, "isTTY", stdoutTtyDescriptor);
|
|
else delete (process.stdout as NodeJS.WriteStream & { isTTY?: boolean }).isTTY;
|
|
}
|
|
|
|
async function freshOnboarding() {
|
|
vi.resetModules();
|
|
return await import("../src/cli/onboarding.js");
|
|
}
|
|
|
|
describe("cli onboarding", () => {
|
|
beforeEach(() => {
|
|
sandboxHome = mkdtempSync(join(tmpdir(), "agentmemory-onboarding-"));
|
|
process.env["HOME"] = sandboxHome;
|
|
process.env["USERPROFILE"] = sandboxHome;
|
|
setTTY(false);
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
afterEach(() => {
|
|
restoreTTY();
|
|
if (ORIGINAL_HOME === undefined) delete process.env["HOME"];
|
|
else process.env["HOME"] = ORIGINAL_HOME;
|
|
if (ORIGINAL_USERPROFILE === undefined) delete process.env["USERPROFILE"];
|
|
else process.env["USERPROFILE"] = ORIGINAL_USERPROFILE;
|
|
rmSync(sandboxHome, { recursive: true, force: true });
|
|
});
|
|
|
|
it("does not prompt and records default preferences when onboarding runs without a TTY", async () => {
|
|
const { runOnboarding } = await freshOnboarding();
|
|
|
|
const result = await runOnboarding();
|
|
|
|
expect(result).toEqual({ agents: [], provider: null });
|
|
expect(prompts.multiselect).not.toHaveBeenCalled();
|
|
expect(prompts.select).not.toHaveBeenCalled();
|
|
expect(prompts.confirm).not.toHaveBeenCalled();
|
|
|
|
const preferencesPath = join(sandboxHome, ".agentmemory", "preferences.json");
|
|
expect(existsSync(preferencesPath)).toBe(true);
|
|
const preferences = JSON.parse(readFileSync(preferencesPath, "utf-8"));
|
|
expect(preferences).toMatchObject({
|
|
schemaVersion: 1,
|
|
lastAgent: null,
|
|
lastAgents: [],
|
|
lastProvider: null,
|
|
skipSplash: true,
|
|
});
|
|
expect(typeof preferences.firstRunAt).toBe("string");
|
|
});
|
|
});
|