import { describe, it, expect, beforeAll, afterAll } from "vitest"; import PocketBase from "pocketbase"; import { DEMO, adminPb, requireServices } from "./helpers"; let admin: PocketBase; let projectId: string; const created: string[] = []; beforeAll(async () => { await requireServices(); admin = await adminPb(); projectId = ( await admin.collection("projects").getFirstListItem(`slug = "${DEMO.projectSlug}"`) ).id; }); afterAll(async () => { for (const id of created) { await admin.collection("commits").delete(id).catch(() => {}); } }); describe("merge commits are never summarised", () => { it("excludes them from the pending set", async () => { const { summaryStatus } = await import("@/lib/ai/summarise"); const status = await summaryStatus(projectId); const merges = ( await admin .collection("commits") .getList(1, 1, { filter: `project = "${projectId}" && is_merge = true`, fields: "id" }) ).totalItems; const all = ( await admin .collection("commits") .getList(1, 1, { filter: `project = "${projectId}"`, fields: "id" }) ).totalItems; // status.total counts non-merge commits only. expect(status.total).toBe(all - merges); expect(merges).toBeGreaterThan(0); }); }); describe("summarisation degrades rather than failing", () => { it("returns a skipped result when no provider is configured", async () => { const settings = await admin .collection("settings") .getFirstListItem("id != ''") .catch(() => null); const previousKey = settings?.ai_api_key ?? ""; if (settings) { await admin.collection("settings").update(settings.id, { ai_api_key: "" }); } const { summariseProject } = await import("@/lib/ai/summarise"); const result = await summariseProject(projectId); // Must not throw. The dashboard and board depend on this. expect(result.skipped).toBe(true); expect(result.summarised).toBe(0); if (settings && previousKey) { await admin.collection("settings").update(settings.id, { ai_api_key: previousKey }); } }); }); describe("a stored summary survives re-ingestion", () => { it("is not cleared when the same commit arrives again", async () => { const commit = await admin.collection("commits").create({ project: projectId, sha: `summary-probe-${Date.now()}`, short_sha: "sumprb", message: "feat(probe): a thing", subject: "a thing", type: "feat", scope: "probe", authored_at: new Date().toISOString(), is_merge: false, link_source: "none", summary: "Did a thing for the client.", summary_version: 1, summary_attempts: 0, }); created.push(commit.id); const { relinkProject } = await import("@/lib/linking/engine"); await relinkProject(projectId); const after = await admin.collection("commits").getOne(commit.id); expect(after.summary).toBe("Did a thing for the client."); }); });