import { describe, test, expect, beforeEach, afterEach } from "bun:test" import { isServerInstalled } from "./config" import { mkdtempSync, rmSync, writeFileSync } from "fs" import { join } from "path" import { tmpdir } from "os" describe("isServerInstalled", () => { let tempDir: string let savedEnv: { [key: string]: string | undefined } beforeEach(() => { tempDir = mkdtempSync(join(tmpdir(), "lsp-config-test-")) savedEnv = { PATH: process.env.PATH, Path: process.env.Path, PATHEXT: process.env.PATHEXT, } }) afterEach(() => { try { rmSync(tempDir, { recursive: true, force: true }) } catch (e) { console.error(`Failed to clean up temp dir: ${e}`) } const keys = ["PATH", "Path", "PATHEXT"] for (const key of keys) { const val = savedEnv[key] if (val === undefined) { delete process.env[key] } else { process.env[key] = val } } }) test("detects executable in PATH", () => { const binName = "test-lsp-server" const ext = process.platform === "win32" ? ".cmd" : "" const binPath = join(tempDir, binName + ext) writeFileSync(binPath, "echo hello") const pathSep = process.platform === "win32" ? ";" : ":" process.env.PATH = `${tempDir}${pathSep}${process.env.PATH || ""}` expect(isServerInstalled([binName])).toBe(true) }) test("returns false for missing executable", () => { expect(isServerInstalled(["non-existent-server"])).toBe(false) }) if (process.platform === "win32") { test("Windows: detects executable with Path env var", () => { const binName = "test-lsp-server-case" const binPath = join(tempDir, binName + ".cmd") writeFileSync(binPath, "echo hello") delete process.env.PATH process.env.Path = tempDir expect(isServerInstalled([binName])).toBe(true) }) test("Windows: respects PATHEXT", () => { const binName = "test-lsp-server-custom" const binPath = join(tempDir, binName + ".COM") writeFileSync(binPath, "echo hello") process.env.PATH = tempDir process.env.PATHEXT = ".COM;.EXE" expect(isServerInstalled([binName])).toBe(true) }) test("Windows: ensures default extensions are checked even if PATHEXT is missing", () => { const binName = "test-lsp-server-default" const binPath = join(tempDir, binName + ".bat") writeFileSync(binPath, "echo hello") process.env.PATH = tempDir delete process.env.PATHEXT expect(isServerInstalled([binName])).toBe(true) }) test("Windows: ensures default extensions are checked even if PATHEXT does not include them", () => { const binName = "test-lsp-server-ps1" const binPath = join(tempDir, binName + ".ps1") writeFileSync(binPath, "echo hello") process.env.PATH = tempDir process.env.PATHEXT = ".COM" expect(isServerInstalled([binName])).toBe(true) }) } else { test("Non-Windows: does not use windows extensions", () => { const binName = "test-lsp-server-win" const binPath = join(tempDir, binName + ".cmd") writeFileSync(binPath, "echo hello") process.env.PATH = tempDir expect(isServerInstalled([binName])).toBe(false) }) } })