Menu
popagent
publicLatest change ac1b32888da9db0a129d0e91ff5cb4dac22c12f0 - Add workspace documentation RAG by AkurAI Build
import { afterEach, describe, expect, test } from "bun:test";
import { mkdir, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { DocumentationFiles, DocumentationConflictError } from "./documentation-files";
const roots: string[] = [];
async function fixture() {
const root = join(import.meta.dir, `.tmp-docs-${crypto.randomUUID()}`);
roots.push(root);
await mkdir(join(root, "repo", "docs", "guide"), { recursive: true });
await writeFile(join(root, "repo", "README.md"), "# Project\n\nHome");
await writeFile(join(root, "repo", "docs", "guide", "start.md"), "# Start here\n\nHello");
await writeFile(join(root, "repo", "docs", "ignored.txt"), "ignore");
const workspaces = {
resolveRepository: async () => ({
workspace: { id: "workspace-1", name: "Project", repositoryPath: "repo", createdAt: "", updatedAt: "" },
path: join(root, "repo"),
}),
};
return { docs: new DocumentationFiles(workspaces), root };
}
afterEach(async () => {
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
});
describe("DocumentationFiles", () => {
test("lists only README.md and contained docs Markdown with heading titles", async () => {
const { docs } = await fixture();
expect(await docs.list("workspace-1")).toEqual([
expect.objectContaining({ path: "README.md", title: "Project" }),
expect.objectContaining({ path: "docs/guide/start.md", title: "Start here" }),
]);
});
test("creates, updates, and deletes Markdown using content revisions", async () => {
const { docs } = await fixture();
const created = await docs.save("workspace-1", { path: "docs/architecture.md", content: "# Architecture\n" });
expect(created.title).toBe("Architecture");
await expect(docs.save("workspace-1", { path: created.path, content: "stale", revision: "bad" }))
.rejects.toBeInstanceOf(DocumentationConflictError);
const updated = await docs.save("workspace-1", { path: created.path, content: "# System\n", revision: created.revision });
expect(updated.revision).not.toBe(created.revision);
const renamed = await docs.move("workspace-1", updated.path, "docs/system/design.md", updated.revision);
expect(renamed.path).toBe("docs/system/design.md");
await expect(docs.remove("workspace-1", renamed.path, created.revision))
.rejects.toBeInstanceOf(DocumentationConflictError);
await docs.remove("workspace-1", renamed.path, renamed.revision);
await expect(docs.read("workspace-1", renamed.path)).rejects.toThrow("Documentation page not found");
});
test("rejects paths outside the managed Markdown roots", async () => {
const { docs } = await fixture();
await expect(docs.save("workspace-1", { path: "../secret.md", content: "no" })).rejects.toThrow("Invalid documentation path");
await expect(docs.save("workspace-1", { path: "src/private.md", content: "no" })).rejects.toThrow("Invalid documentation path");
await expect(docs.save("workspace-1", { path: "docs/.private/page.md", content: "no" })).rejects.toThrow("Invalid documentation path");
await expect(docs.save("workspace-1", { path: "docs/not-markdown.txt", content: "no" })).rejects.toThrow("Invalid documentation path");
});
});