Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/intellij/__serial__/activation.test.ts

Raw
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { stat } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
import { afterEach, expect, it, vi } from "vitest";
import {
	createPiSession,
	type PiSession,
} from "../../../test/fixture/create-pi-session.ts";
import intellijExtension, { findIdeaProjectRoot } from "../index.ts";

vi.mock("node:fs/promises", async (importOriginal) => {
	const actual = await importOriginal<typeof import("node:fs/promises")>();
	return { ...actual, stat: vi.fn(actual.stat) };
});

let session: PiSession | undefined;
let root: string | undefined;
afterEach(async () => {
	await session?.dispose();
	session = undefined;
	if (root) rmSync(root, { recursive: true, force: true });
	root = undefined;
	vi.mocked(stat).mockReset();
	const actual =
		await vi.importActual<typeof import("node:fs/promises")>(
			"node:fs/promises",
		);
	vi.mocked(stat).mockImplementation(actual.stat);
});

it("does not treat an .idea file as project metadata", async () => {
	root = mkdtempSync(join(tmpdir(), "intellij-idea-file-"));
	writeFileSync(join(root, ".idea"), "not a directory");
	expect(await findIdeaProjectRoot(root)).toBeUndefined();
});

it("does not register an MCP server after shutdown interrupts project detection", async () => {
	root = mkdtempSync(join(tmpdir(), "intellij-shutdown-"));
	mkdirSync(join(root, ".idea"));
	const actual =
		await vi.importActual<typeof import("node:fs/promises")>(
			"node:fs/promises",
		);
	const metadata = await actual.stat(join(root, ".idea"));
	let release!: (value: typeof metadata) => void;
	const blocked = new Promise<typeof metadata>((resolve) => {
		release = resolve;
	});
	vi.mocked(stat).mockImplementation(((path, options) =>
		String(path).endsWith(".idea")
			? blocked
			: actual.stat(path, options)) as typeof stat);
	let serverNames = (): string[] => [];
	const probe = (pi: ExtensionAPI) => {
		serverNames = () => pi.getMcpServers().map((server) => server.name);
	};
	session = await createPiSession({
		cwd: root,
		userSettings: { intellij: { url: "http://127.0.0.1:63342/mcp" } },
		extensionFactories: [intellijExtension, probe],
	});
	await session.session.extensionRunner.emit({
		type: "session_shutdown",
		reason: "quit",
	});
	release(metadata);
	await new Promise<void>((resolve) => setImmediate(resolve));
	expect(serverNames()).toEqual([]);
	expect(session.errors).toEqual([]);
});