Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/nu-bang/__tests__/settings.test.ts

Raw
import {
	chmodSync,
	mkdirSync,
	mkdtempSync,
	rmSync,
	writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { createTestSession, type TestSession } from "../../../test/harness";

const extensionPath = path.resolve(import.meta.dirname, "../index.ts");

type Case = {
	user?: unknown;
	project?: unknown;
	env?: string;
	untrusted?: boolean;
};

describe("nu-bang.command resolution", () => {
	let t: TestSession | undefined;
	let root: string | undefined;
	afterEach(async () => {
		await t?.session.extensionRunner.emit({
			type: "session_shutdown",
			reason: "quit",
		});
		t?.dispose();
		t = undefined;
		if (root) rmSync(root, { recursive: true, force: true });
		root = undefined;
	});

	/** Start a session, run `print real-nu` as bang input, and report which executable ran it. */
	async function run(input: Case) {
		const dir = mkdtempSync(path.join(tmpdir(), "pi-ext-nu-bang-settings-"));
		root = dir;
		// Fake executables print their own name instead of running Nushell.
		const fake = (name: string) => {
			const file = path.join(dir, name);
			writeFileSync(file, '#!/bin/sh\necho "fake:${0##*/}"\n');
			chmodSync(file, 0o755);
			return file;
		};
		const resolve = (value: unknown) =>
			typeof value === "string" && value.startsWith("fake-")
				? fake(value)
				: value;
		const write = (settingsDir: string, value: unknown) => {
			mkdirSync(settingsDir, { recursive: true });
			writeFileSync(
				path.join(settingsDir, "settings.json"),
				JSON.stringify({ "nu-bang": { command: resolve(value) } }),
			);
		};
		if ("user" in input)
			write(path.join(dir, ".test-home/.pi/agent"), input.user);
		if ("project" in input) write(path.join(dir, ".pi"), input.project);
		const env =
			input.env === undefined
				? {}
				: { PI_NU_BANG_COMMAND: String(resolve(input.env)) };
		t = await createTestSession({ cwd: dir, env, extensions: [extensionPath] });
		if (input.untrusted) t.session.settingsManager.setProjectTrusted(false);
		const before = t.events.uiCallsFor("notify").length;
		await t.session.extensionRunner.emit({
			type: "session_start",
			reason: "startup",
		});
		const warnings = t.events
			.uiCallsFor("notify")
			.slice(before)
			.filter((call) => call.args[1] === "warning")
			.map((call) => call.args[0]);
		const result = await t.session.extensionRunner.emitUserBash({
			type: "user_bash",
			command: "print real-nu",
			excludeFromContext: false,
			cwd: dir,
		});
		let output = "";
		await result?.operations?.exec("print real-nu", dir, {
			onData: (chunk) => {
				output += chunk.toString("utf8");
			},
		});
		return { ran: output.trim(), warnings };
	}

	it.each([
		["default nu", {}, "real-nu"],
		["user path", { user: "fake-user" }, "fake:fake-user"],
		[
			"env over settings",
			{ user: "fake-user", env: "fake-env" },
			"fake:fake-env",
		],
		[
			"trusted project over user",
			{ user: "fake-user", project: "fake-project" },
			"fake:fake-project",
		],
		[
			"untrusted project ignored",
			{ user: "fake-user", project: "fake-project", untrusted: true },
			"fake:fake-user",
		],
	] satisfies [string, Case, string][])(
		"%s",
		async (_name, input, expected) => {
			const { ran, warnings } = await run(input);
			expect(ran).toBe(expected);
			expect(warnings).toEqual([]);
		},
	);

	it.each([
		["numeric user", { user: 5 }, "user settings"],
		["empty project", { user: "fake-user", project: "" }, "project settings"],
		[
			"blank env",
			{ user: "fake-user", env: "  " },
			"environment variable PI_NU_BANG_COMMAND",
		],
	] satisfies [string, Case, string][])(
		"rejects %s without falling through",
		async (_name, input, source) => {
			const { ran, warnings } = await run(input);
			expect(ran).toBe("real-nu");
			expect(warnings).toEqual([
				`Invalid nu-bang.command from ${source}; using nu`,
			]);
		},
	);
});