import { describe, it, expect, beforeAll } from "vitest"; import PocketBase from "pocketbase"; import { APP_URL, DEMO, adminPb, requireServices, signIn } from "./helpers"; let admin: PocketBase; let projectId: string; beforeAll(async () => { await requireServices(); admin = await adminPb(); projectId = ( await admin.collection("projects").getFirstListItem(`slug = "${DEMO.projectSlug}"`) ).id; }); describe("a card with no commits gets no narrative", () => { it("is left empty rather than invented", async () => { const { narrateProject } = await import("@/lib/ai/narrate"); await narrateProject(projectId); const cards = await admin.collection("cards").getFullList({ filter: `project = "${projectId}" && archived = false`, fields: "id,narrative", }); for (const card of cards) { const linked = ( await admin .collection("commits") .getList(1, 1, { filter: `card = "${card.id}"`, fields: "id" }) ).totalItems; if (linked === 0) { expect(card.narrative ?? "").toBe(""); } } }); }); describe("the card page always shows something for a commit", () => { it("falls back to the raw subject when there is no summary", async () => { const card = await admin .collection("cards") .getFirstListItem(`project = "${projectId}"`); const marker = `raw-subject-probe-${Date.now()}`; const commit = await admin.collection("commits").create({ project: projectId, sha: `narrative-probe-${Date.now()}`, short_sha: "narprb", message: `feat(probe): ${marker}`, subject: `feat(probe): ${marker}`, type: "feat", scope: "probe", authored_at: new Date().toISOString(), is_merge: false, card: card.id, link_source: "manual", summary: "", }); const cookie = await signIn(DEMO.managerEmail, DEMO.managerPassword); const response = await fetch( `${APP_URL}/p/${DEMO.clientSlug}/${DEMO.projectSlug}/c/${card.id}`, { headers: { cookie } } ); const html = await response.text(); expect(response.status).toBe(200); // A gap here would look to the client like no work happened. expect(html).toContain(marker); await admin.collection("commits").delete(commit.id); }); });