Files
pi-lsp/test/unit/root.test.ts
Evan Reichard aa7309b363 test: add unit and integration test suite
Add 34 tests (27 unit, 7 integration) using node:test runner:

Unit tests:
- pickServer(), findRoot(), pathToUri(), uriToPath()
- isLspCommand(), listCommands()
- formatHover(), formatDefinition(), formatReferences(), formatDiagnostics()

Integration tests:
- daemon lifecycle (status/stop) on isolated socket
- CLI --no-daemon queries (hover, documentSymbol, diagnostics)

Supporting changes:
- socketPath() honors PI_LSP_SOCKET_PATH env var for test isolation
- test fixtures for valid and broken TypeScript files
- npm test / test:unit / test:integration scripts
2026-04-30 10:36:54 -04:00

88 lines
2.9 KiB
TypeScript

// Root Unit Tests — pickServer(), findRoot(), pathToUri(), uriToPath().
import { describe, it } from "node:test";
import * as assert from "node:assert/strict";
import * as path from "node:path";
import { fileURLToPath } from "node:url";
import { pickServer, findRoot, pathToUri, uriToPath } from "../../src/root.ts";
import { UnsupportedExtensionError } from "../../src/types.ts";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const projectRoot = path.resolve(__dirname, "..", "..");
describe("pathToUri / uriToPath", () => {
it("converts a relative path to a file URI", () => {
const uri = pathToUri("cli.ts");
assert.ok(uri.startsWith("file://"));
assert.ok(uri.endsWith("cli.ts"));
});
it("converts an absolute path to a file URI", () => {
const absPath = path.resolve(projectRoot, "cli.ts");
const uri = pathToUri(absPath);
assert.strictEqual(uri, `file://${absPath}`);
});
it("round-trips path -> uri -> path", () => {
const absPath = path.resolve(projectRoot, "src", "client.ts");
const uri = pathToUri(absPath);
const back = uriToPath(uri);
assert.strictEqual(back, absPath);
});
});
describe("pickServer", () => {
it("picks gopls for .go files", () => {
const server = pickServer("/some/path/file.go");
assert.strictEqual(server.id, "gopls");
});
it("picks typescript-language-server for .ts files", () => {
const server = pickServer("/some/path/file.ts");
assert.strictEqual(server.id, "typescript-language-server");
});
it("picks typescript-language-server for .tsx files", () => {
const server = pickServer("/some/path/file.tsx");
assert.strictEqual(server.id, "typescript-language-server");
});
it("picks pyright for .py files", () => {
const server = pickServer("/some/path/file.py");
assert.strictEqual(server.id, "pyright");
});
it("throws UnsupportedExtensionError for unknown extensions", () => {
assert.throws(
() => pickServer("/some/path/file.xyz"),
UnsupportedExtensionError,
);
});
});
describe("findRoot", () => {
it("finds project root using go.mod marker", () => {
// The project root has package.json but not go.mod, so use a file in the
// project and look for tsconfig.json.
const root = findRoot(
path.join(projectRoot, "cli.ts"),
["tsconfig.json"],
);
assert.strictEqual(root, projectRoot);
});
it("finds nearest directory containing marker", () => {
// The test/fixtures/ dir doesn't have tsconfig.json, but the project root does.
const fixtureFile = path.join(projectRoot, "test", "fixtures", "sample.ts");
const root = findRoot(fixtureFile, ["tsconfig.json"]);
assert.strictEqual(root, projectRoot);
});
it("falls back to file's directory when no marker found", () => {
const root = findRoot(
path.join(projectRoot, "cli.ts"),
["nonexistent-marker-xyz"],
);
assert.strictEqual(root, projectRoot);
});
});