mirror of
https://github.com/doum1004/llmwiki-cli.git
synced 2026-05-09 12:46:12 +02:00
- Renamed sections in the wiki index from Entities/Sources/Concepts to a more structured format. - Removed the log.md file and its associated tests to streamline the logging process. - Updated the ai-agent-patterns.md to include JSON write examples and demo conventions. - Modified commands tests to handle JSON input for writing and reading pages. - Implemented delete functionality for pages and ensured proper index updates. - Enhanced index management to support upserting entries and handling duplicates. - Removed deprecated profile tests and log manager tests to clean up the codebase. - Adjusted storage tests to reflect changes in file writing locations.
181 lines
5.9 KiB
TypeScript
181 lines
5.9 KiB
TypeScript
import { describe, it, expect, beforeEach, afterEach } from "bun:test";
|
|
import { mkdtemp, rm, writeFile, readFile, mkdir } from "fs/promises";
|
|
import { join } from "path";
|
|
import { tmpdir } from "os";
|
|
import { WikiManager } from "../src/lib/wiki.ts";
|
|
|
|
let testDir: string;
|
|
let wiki: WikiManager;
|
|
|
|
beforeEach(async () => {
|
|
testDir = await mkdtemp(join(tmpdir(), "llmwiki-rw-"));
|
|
wiki = new WikiManager(testDir);
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await rm(testDir, { recursive: true, force: true });
|
|
});
|
|
|
|
describe("WikiManager.writePage", () => {
|
|
it("creates file with correct content", async () => {
|
|
await wiki.writePage("test.md", "# Hello\n");
|
|
const content = await readFile(join(testDir, "test.md"), "utf-8");
|
|
expect(content).toBe("# Hello\n");
|
|
});
|
|
|
|
it("creates parent directories automatically", async () => {
|
|
await wiki.writePage("wiki/concepts/deep.md", "content");
|
|
const content = await readFile(
|
|
join(testDir, "wiki/concepts/deep.md"),
|
|
"utf-8",
|
|
);
|
|
expect(content).toBe("content");
|
|
});
|
|
|
|
it("overwrites existing file", async () => {
|
|
await wiki.writePage("page.md", "old");
|
|
await wiki.writePage("page.md", "new");
|
|
const content = await wiki.readPage("page.md");
|
|
expect(content).toBe("new");
|
|
});
|
|
});
|
|
|
|
describe("WikiManager.readPage", () => {
|
|
it("returns file content", async () => {
|
|
await writeFile(join(testDir, "hello.md"), "world", "utf-8");
|
|
const content = await wiki.readPage("hello.md");
|
|
expect(content).toBe("world");
|
|
});
|
|
|
|
it("returns null for missing file", async () => {
|
|
const content = await wiki.readPage("nonexistent.md");
|
|
expect(content).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("WikiManager.deletePage", () => {
|
|
it("removes an existing file", async () => {
|
|
await wiki.writePage("gone.md", "x");
|
|
await wiki.deletePage("gone.md");
|
|
expect(await wiki.pageExists("gone.md")).toBe(false);
|
|
expect(await wiki.readPage("gone.md")).toBeNull();
|
|
});
|
|
|
|
it("throws for missing file", async () => {
|
|
await expect(wiki.deletePage("missing.md")).rejects.toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe("WikiManager.pageExists", () => {
|
|
it("returns true for existing file", async () => {
|
|
await wiki.writePage("exists.md", "hi");
|
|
expect(await wiki.pageExists("exists.md")).toBe(true);
|
|
});
|
|
|
|
it("returns false for missing file", async () => {
|
|
expect(await wiki.pageExists("nope.md")).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("WikiManager.listPages", () => {
|
|
it("returns all .md files", async () => {
|
|
await wiki.writePage("a.md", "a");
|
|
await wiki.writePage("b.md", "b");
|
|
await wiki.writePage("sub/c.md", "c");
|
|
const pages = await wiki.listPages();
|
|
expect(pages).toEqual(["a.md", "b.md", "sub/c.md"]);
|
|
});
|
|
|
|
it("filters by subdirectory", async () => {
|
|
await wiki.writePage("root.md", "r");
|
|
await wiki.writePage("wiki/page.md", "p");
|
|
await wiki.writePage("wiki/sub/deep.md", "d");
|
|
const pages = await wiki.listPages("wiki");
|
|
expect(pages).toEqual(["wiki/page.md", "wiki/sub/deep.md"]);
|
|
});
|
|
|
|
it("returns empty array for empty dir", async () => {
|
|
const pages = await wiki.listPages();
|
|
expect(pages).toEqual([]);
|
|
});
|
|
|
|
it("skips non-.md files", async () => {
|
|
await writeFile(join(testDir, "notes.txt"), "text", "utf-8");
|
|
await wiki.writePage("page.md", "md");
|
|
const pages = await wiki.listPages();
|
|
expect(pages).toEqual(["page.md"]);
|
|
});
|
|
|
|
it("returns sorted results", async () => {
|
|
await wiki.writePage("z.md", "z");
|
|
await wiki.writePage("a.md", "a");
|
|
await wiki.writePage("m.md", "m");
|
|
const pages = await wiki.listPages();
|
|
expect(pages).toEqual(["a.md", "m.md", "z.md"]);
|
|
});
|
|
|
|
it("skips .git directory", async () => {
|
|
await wiki.writePage("page.md", "content");
|
|
await mkdir(join(testDir, ".git"), { recursive: true });
|
|
await writeFile(join(testDir, ".git/config.md"), "git config", "utf-8");
|
|
const pages = await wiki.listPages();
|
|
expect(pages).toEqual(["page.md"]);
|
|
});
|
|
|
|
it("skips node_modules directory", async () => {
|
|
await wiki.writePage("page.md", "content");
|
|
await mkdir(join(testDir, "node_modules/pkg"), { recursive: true });
|
|
await writeFile(join(testDir, "node_modules/pkg/readme.md"), "readme", "utf-8");
|
|
const pages = await wiki.listPages();
|
|
expect(pages).toEqual(["page.md"]);
|
|
});
|
|
|
|
it("handles deeply nested directories", async () => {
|
|
await wiki.writePage("a/b/c/d/deep.md", "deep");
|
|
const pages = await wiki.listPages();
|
|
expect(pages).toEqual(["a/b/c/d/deep.md"]);
|
|
const content = await wiki.readPage("a/b/c/d/deep.md");
|
|
expect(content).toBe("deep");
|
|
});
|
|
|
|
it("listPages with nonexistent dir returns empty", async () => {
|
|
const pages = await wiki.listPages("nonexistent");
|
|
expect(pages).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe("WikiManager edge cases", () => {
|
|
it("readPage re-throws non-ENOENT errors", async () => {
|
|
// Reading a directory path should throw
|
|
await mkdir(join(testDir, "adir"), { recursive: true });
|
|
// On some systems reading a dir as file throws EISDIR
|
|
try {
|
|
await wiki.readPage("adir");
|
|
// Some systems return null, some throw - either is acceptable
|
|
} catch (err: unknown) {
|
|
expect(err).toBeDefined();
|
|
}
|
|
});
|
|
|
|
it("appendPage to empty file adds content directly", async () => {
|
|
await wiki.writePage("empty.md", "");
|
|
await wiki.appendPage("empty.md", "new content");
|
|
const content = await wiki.readPage("empty.md");
|
|
expect(content).toBe("\nnew content");
|
|
});
|
|
|
|
it("writePage with empty content creates empty file", async () => {
|
|
await wiki.writePage("blank.md", "");
|
|
expect(await wiki.pageExists("blank.md")).toBe(true);
|
|
const content = await wiki.readPage("blank.md");
|
|
expect(content).toBe("");
|
|
});
|
|
|
|
it("uses forward slashes on all platforms", async () => {
|
|
await wiki.writePage("sub/page.md", "content");
|
|
const pages = await wiki.listPages();
|
|
expect(pages[0]).toBe("sub/page.md");
|
|
expect(pages[0]).not.toContain("\\");
|
|
});
|
|
});
|