Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/intellij/__tests__/settings.test.ts

Raw
import { 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";
import intellijExtension from "../index";

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

describe("intellij.url resolution", () => {
	let t: TestSession | undefined;
	let root: string | undefined;
	afterEach(() => {
		t?.dispose();
		t = undefined;
		if (root) rmSync(root, { recursive: true, force: true });
		root = undefined;
	});

	async function run(input: Case, command: string) {
		root = mkdtempSync(path.join(tmpdir(), "pi-ext-intellij-settings-"));
		const write = (dir: string, value: unknown) => {
			mkdirSync(dir, { recursive: true });
			writeFileSync(
				path.join(dir, "settings.json"),
				JSON.stringify({ intellij: { url: value } }),
			);
		};
		if ("user" in input)
			write(path.join(root, ".test-home/.pi/agent"), input.user);
		if ("project" in input) write(path.join(root, ".pi"), input.project);
		t = await createTestSession({
			cwd: root,
			extensionFactories: [intellijExtension],
		});
		if (input.untrusted) t.session.settingsManager.setProjectTrusted(false);
		const [extension] = t.session.extensionRunner.extensions;
		await extension.commands
			.get("intellij")
			.handler(command, t.session.extensionRunner.createCommandContext());
		return t.events.uiCallsFor("notify").at(-1)?.args;
	}

	it.each([
		["none", {}, "none"],
		["user", { user: "http://127.0.0.1:1/user" }, "http://127.0.0.1:1/user"],
		[
			"project over user",
			{ user: "http://127.0.0.1:1/user", project: "http://127.0.0.1:1/proj" },
			"http://127.0.0.1:1/proj",
		],
		[
			"untrusted project ignored",
			{
				user: "http://127.0.0.1:1/user",
				project: "http://127.0.0.1:1/proj",
				untrusted: true,
			},
			"http://127.0.0.1:1/user",
		],
	] satisfies [string, Case, string][])(
		"status shows %s",
		async (_name, input, endpoint) => {
			const [message, level] = (await run(input, "status")) ?? [];
			expect(message).toContain(`endpoint: ${endpoint}\n`);
			expect(level).toBe("info");
		},
	);

	const invalid = [
		["project", { user: "http://127.0.0.1:1/user", project: 1 }],
		["user", { user: true }],
	] satisfies [string, Case][];

	it.each(invalid)(
		"status rejects non-string %s value without falling through",
		async (source, input) => {
			expect(await run(input, "status")).toEqual([
				expect.stringContaining(
					`endpoint: unavailable (Invalid intellij.url from ${source} settings)`,
				),
				"warning",
			]);
		},
	);

	it.each(invalid)(
		"connect rejects non-string %s value without falling through",
		async (source, input) => {
			expect(await run(input, "connect")).toEqual([
				expect.stringMatching(
					new RegExp(`^Invalid intellij\\.url from ${source} settings\\. `),
				),
				"warning",
			]);
		},
	);
});