mirror of
https://github.com/doum1004/llmwiki-cli.git
synced 2026-04-28 23:16:09 +02:00
- Enhance git.test.ts with tests for commit messages with special characters, log limits, diff outputs, branch retrieval, remote addition, file deletion staging, conflict detection, and file-specific logs. - Introduce github.test.ts to validate GitHub API functions including repository listing, filtering, error handling, and repository creation with various scenarios. - Expand index-manager.test.ts to cover entry addition, duplicate handling, reading from missing files, entry removal, and case-insensitive category matching. - Update links.test.ts to ensure proper link resolution, handling of self-referential links, and multiple links to the same target. - Add lint.test.ts for frontmatter edge cases, including handling empty frontmatter, invalid YAML, and ensuring parseable output. - Enhance log-manager.test.ts with tests for empty logs, filtering by type and count, log creation, timestamp format, and preserving entry formats. - Extend read-write.test.ts to skip certain directories, handle deeply nested paths, and ensure consistent path formatting across platforms. - Improve search.test.ts to escape regex characters, filter by directory, manage snippet generation, enforce default limits, and handle searches in empty wikis.
133 lines
4.8 KiB
TypeScript
133 lines
4.8 KiB
TypeScript
import { describe, it, expect, beforeEach, afterEach } from "bun:test";
|
|
import { mkdtemp, rm } from "fs/promises";
|
|
import { join } from "path";
|
|
import { tmpdir } from "os";
|
|
import { WikiManager } from "../src/lib/wiki.ts";
|
|
import { search } from "../src/lib/search.ts";
|
|
|
|
let testDir: string;
|
|
let wiki: WikiManager;
|
|
|
|
beforeEach(async () => {
|
|
testDir = await mkdtemp(join(tmpdir(), "llmwiki-search-"));
|
|
wiki = new WikiManager(testDir);
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await rm(testDir, { recursive: true, force: true });
|
|
});
|
|
|
|
describe("search", () => {
|
|
it("finds pages containing query terms", async () => {
|
|
await wiki.writePage("a.md", "The attention mechanism is important.");
|
|
await wiki.writePage("b.md", "Unrelated content about cooking.");
|
|
const results = await search(wiki, "attention");
|
|
expect(results).toHaveLength(1);
|
|
expect(results[0]!.path).toBe("a.md");
|
|
});
|
|
|
|
it("ranks by term frequency", async () => {
|
|
await wiki.writePage(
|
|
"few.md",
|
|
"Attention is used once in this document.",
|
|
);
|
|
await wiki.writePage(
|
|
"many.md",
|
|
"Attention attention attention. The attention mechanism uses attention.",
|
|
);
|
|
const results = await search(wiki, "attention");
|
|
expect(results).toHaveLength(2);
|
|
expect(results[0]!.path).toBe("many.md");
|
|
expect(results[0]!.score).toBeGreaterThan(results[1]!.score);
|
|
});
|
|
|
|
it("returns snippets around first match", async () => {
|
|
await wiki.writePage("page.md", "Some preamble text. The key concept is transformers. More text after.");
|
|
const results = await search(wiki, "transformers");
|
|
expect(results).toHaveLength(1);
|
|
expect(results[0]!.snippet).toContain("transformers");
|
|
});
|
|
|
|
it("respects --limit", async () => {
|
|
for (let i = 0; i < 5; i++) {
|
|
await wiki.writePage(`p${i}.md`, `This page mentions topic number ${i}.`);
|
|
}
|
|
const results = await search(wiki, "topic", { limit: 3 });
|
|
expect(results).toHaveLength(3);
|
|
});
|
|
|
|
it("returns empty array for no matches", async () => {
|
|
await wiki.writePage("page.md", "Some content here.");
|
|
const results = await search(wiki, "nonexistent");
|
|
expect(results).toEqual([]);
|
|
});
|
|
|
|
it("handles multi-word queries", async () => {
|
|
await wiki.writePage("a.md", "Machine learning is a field of study.");
|
|
await wiki.writePage("b.md", "This is about machine design only.");
|
|
const results = await search(wiki, "machine learning");
|
|
expect(results).toHaveLength(2);
|
|
// "a.md" matches both terms, "b.md" matches only one
|
|
expect(results[0]!.path).toBe("a.md");
|
|
expect(results[0]!.score).toBeGreaterThan(results[1]!.score);
|
|
});
|
|
|
|
it("is case insensitive", async () => {
|
|
await wiki.writePage("page.md", "Attention and ATTENTION and attention.");
|
|
const results = await search(wiki, "ATTENTION");
|
|
expect(results).toHaveLength(1);
|
|
expect(results[0]!.score).toBe(3);
|
|
});
|
|
|
|
it("returns empty for empty query", async () => {
|
|
await wiki.writePage("page.md", "content");
|
|
const results = await search(wiki, " ");
|
|
expect(results).toEqual([]);
|
|
});
|
|
|
|
it("escapes regex special characters without crashing", async () => {
|
|
await wiki.writePage("code.md", "The function uses array.map for mapping.");
|
|
// Searching with regex special chars should not throw
|
|
const results = await search(wiki, "array.map");
|
|
expect(results).toHaveLength(1);
|
|
expect(results[0]!.path).toBe("code.md");
|
|
});
|
|
|
|
it("handles dir filter", async () => {
|
|
await wiki.writePage("wiki/concepts/a.md", "Machine learning concept.");
|
|
await wiki.writePage("wiki/sources/b.md", "Machine learning paper.");
|
|
const results = await search(wiki, "machine", { dir: "wiki/concepts" });
|
|
expect(results).toHaveLength(1);
|
|
expect(results[0]!.path).toBe("wiki/concepts/a.md");
|
|
});
|
|
|
|
it("snippet adds ellipsis for middle-of-content matches", async () => {
|
|
const longContent = "A".repeat(200) + " target word " + "B".repeat(200);
|
|
await wiki.writePage("long.md", longContent);
|
|
const results = await search(wiki, "target");
|
|
expect(results).toHaveLength(1);
|
|
expect(results[0]!.snippet).toContain("...");
|
|
});
|
|
|
|
it("default limit is 10", async () => {
|
|
for (let i = 0; i < 15; i++) {
|
|
await wiki.writePage(`p${i}.md`, `Topic keyword in page ${i}.`);
|
|
}
|
|
const results = await search(wiki, "keyword");
|
|
expect(results).toHaveLength(10);
|
|
});
|
|
|
|
it("handles empty wiki", async () => {
|
|
const results = await search(wiki, "anything");
|
|
expect(results).toEqual([]);
|
|
});
|
|
|
|
it("search with limit 1 returns top result", async () => {
|
|
await wiki.writePage("high.md", "attention attention attention");
|
|
await wiki.writePage("low.md", "attention once");
|
|
const results = await search(wiki, "attention", { limit: 1 });
|
|
expect(results).toHaveLength(1);
|
|
expect(results[0]!.path).toBe("high.md");
|
|
});
|
|
});
|