95 lines
3.1 KiB
TypeScript
95 lines
3.1 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
import * as fs from "node:fs";
|
|
import * as os from "node:os";
|
|
import * as path from "node:path";
|
|
import { CombinedAutocompleteProvider } from "@oh-my-pi/pi-tui/autocomplete";
|
|
|
|
describe("CombinedAutocompleteProvider", () => {
|
|
describe("extractPathPrefix", () => {
|
|
it("extracts / from 'hey /' when forced", async () => {
|
|
const provider = new CombinedAutocompleteProvider([], "/tmp");
|
|
const lines = ["hey /"];
|
|
const cursorLine = 0;
|
|
const cursorCol = 5; // After the "/"
|
|
|
|
const result = await provider.getForceFileSuggestions(lines, cursorLine, cursorCol);
|
|
|
|
expect(result).not.toBeNull();
|
|
if (result) {
|
|
expect(result.prefix).toBe("/");
|
|
}
|
|
});
|
|
|
|
it("extracts /A from '/A' when forced", async () => {
|
|
const provider = new CombinedAutocompleteProvider([], "/tmp");
|
|
const lines = ["/A"];
|
|
const cursorLine = 0;
|
|
const cursorCol = 2; // After the "A"
|
|
|
|
const result = await provider.getForceFileSuggestions(lines, cursorLine, cursorCol);
|
|
|
|
// This might return null if /A doesn't match anything, which is fine
|
|
// We're mainly testing that the prefix extraction works
|
|
if (result) {
|
|
expect(result.prefix).toBe("/A");
|
|
}
|
|
});
|
|
|
|
it("does not trigger for slash commands", async () => {
|
|
const provider = new CombinedAutocompleteProvider([], "/tmp");
|
|
const lines = ["/model"];
|
|
const cursorLine = 0;
|
|
const cursorCol = 6; // After "model"
|
|
|
|
const result = await provider.getForceFileSuggestions(lines, cursorLine, cursorCol);
|
|
|
|
expect(result).toBe(null);
|
|
});
|
|
|
|
it("triggers for absolute paths after slash command argument", async () => {
|
|
const provider = new CombinedAutocompleteProvider([], "/tmp");
|
|
const lines = ["/command /"];
|
|
const cursorLine = 0;
|
|
const cursorCol = 10; // After the second "/"
|
|
|
|
const result = await provider.getForceFileSuggestions(lines, cursorLine, cursorCol);
|
|
|
|
expect(result).not.toBeNull();
|
|
if (result) {
|
|
expect(result.prefix).toBe("/");
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("hidden paths", () => {
|
|
let baseDir: string;
|
|
|
|
beforeEach(() => {
|
|
baseDir = fs.mkdtempSync(path.join(os.tmpdir(), "autocomplete-test-"));
|
|
});
|
|
|
|
afterEach(() => {
|
|
fs.rmSync(baseDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it("includes hidden paths but excludes .git", async () => {
|
|
for (const dir of [".pi", ".github", ".git"]) {
|
|
fs.mkdirSync(path.join(baseDir, dir), { recursive: true });
|
|
}
|
|
fs.mkdirSync(path.join(baseDir, ".github", "workflows"), { recursive: true });
|
|
fs.writeFileSync(path.join(baseDir, ".pi", "config.json"), "{}");
|
|
fs.writeFileSync(path.join(baseDir, ".github", "workflows", "ci.yml"), "name: ci");
|
|
fs.writeFileSync(path.join(baseDir, ".git", "config"), "[core]");
|
|
|
|
const provider = new CombinedAutocompleteProvider([], baseDir);
|
|
const line = "@";
|
|
const result = await provider.getSuggestions([line], 0, line.length);
|
|
|
|
const values = result?.items.map(item => item.value) ?? [];
|
|
expect(values).toContain("@.pi/");
|
|
expect(values).toContain("@.github/");
|
|
expect(values.some(value => value === "@.git" || value.startsWith("@.git/"))).toBe(false);
|
|
});
|
|
});
|
|
});
|