Files
llmwiki-cli/test/read-write.test.ts
doum1004 428e3e516e Refactor wiki structure and improve command functionality
- 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.
2026-04-30 23:31:06 -04:00

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("\\");
});
});