import { describe, expect, test } from "bun:test"; import { findGoalByMergeSha, parseGoalFrontmatter, } from "./b32_goals_meta.ts"; import type { GoalEntry } from "./a31_goals.ts"; const fullFrontmatter = `--- slug: example-goal title: An example goal date: 2026-05-25 branch: example-goal pr_number: 42 merge_sha: abc1234 status: shipped related_posts: [plan-post, postmortem-post] --- Goal: do the thing. Done when: - it is done. `; const minimalFrontmatter = `--- slug: minimal title: Minimal goal date: 2026-05-25 branch: minimal status: pending --- Body here. `; describe("parseGoalFrontmatter", () => { test("full frontmatter parses every field", () => { const parsed = parseGoalFrontmatter(fullFrontmatter); expect(parsed).not.toBeNull(); expect(parsed!.meta.slug).toBe("example-goal"); expect(parsed!.meta.title).toBe("An example goal"); expect(parsed!.meta.date).toBe("2026-05-25"); expect(parsed!.meta.branch).toBe("example-goal"); expect(parsed!.meta.prNumber).toBe(42); expect(parsed!.meta.mergeSha).toBe("abc1234"); expect(parsed!.meta.status).toBe("shipped"); expect(parsed!.meta.relatedPosts).toEqual(["plan-post", "postmortem-post"]); expect(parsed!.body).toContain("Goal: do the thing."); }); test("missing optional fields default sensibly", () => { const parsed = parseGoalFrontmatter(minimalFrontmatter); expect(parsed).not.toBeNull(); expect(parsed!.meta.prNumber).toBeNull(); expect(parsed!.meta.mergeSha).toBeNull(); expect(parsed!.meta.relatedPosts).toEqual([]); expect(parsed!.meta.status).toBe("pending"); }); test("missing required field returns null", () => { const noTitle = `--- slug: x date: 2026-05-25 branch: x status: pending --- body`; expect(parseGoalFrontmatter(noTitle)).toBeNull(); }); test("malformed frontmatter (no opening ---) returns null", () => { expect(parseGoalFrontmatter("just some text")).toBeNull(); }); test("unclosed frontmatter returns null", () => { expect(parseGoalFrontmatter("---\nslug: x\ntitle: y\n")).toBeNull(); }); test("invalid status returns null", () => { const bad = `--- slug: x title: y date: 2026-05-25 branch: x status: half-done --- body`; expect(parseGoalFrontmatter(bad)).toBeNull(); }); test('status: "lossy" parses correctly', () => { const lossy = `--- slug: x title: A lossy goal date: 2026-05-24 branch: x pr_number: 32 merge_sha: 43c6f7a status: lossy --- Recovered partially from conversation.`; const parsed = parseGoalFrontmatter(lossy); expect(parsed).not.toBeNull(); expect(parsed!.meta.status).toBe("lossy"); expect(parsed!.meta.prNumber).toBe(32); expect(parsed!.meta.mergeSha).toBe("43c6f7a"); }); test('status: "lost" parses correctly (registry-only goals still parse if a file exists)', () => { const lost = `--- slug: x title: A lost goal date: 2026-05-24 branch: x pr_number: 31 merge_sha: f244dbb status: lost --- (intentionally empty body — no /goal text recoverable)`; const parsed = parseGoalFrontmatter(lost); expect(parsed).not.toBeNull(); expect(parsed!.meta.status).toBe("lost"); }); }); const sampleGoals: ReadonlyArray = [ { slug: "alpha", title: "Alpha", date: "2026-05-25", branch: "alpha", prNumber: 1, mergeSha: "968890f8a3bc1234deadbeef0000000000000000", status: "shipped", relatedPosts: [], }, { slug: "beta", title: "Beta", date: "2026-05-24", branch: "beta", prNumber: 2, mergeSha: "684f257", status: "shipped", relatedPosts: [], }, { slug: "pending-thing", title: "Pending", date: "2026-05-26", branch: "pending", prNumber: null, mergeSha: null, status: "pending", relatedPosts: [], }, ]; describe("findGoalByMergeSha", () => { test("short query hits long stored SHA (prefix match)", () => { const found = findGoalByMergeSha("968890f", sampleGoals); expect(found?.slug).toBe("alpha"); }); test("long query hits short stored SHA (reverse prefix)", () => { const found = findGoalByMergeSha("684f257b24c002f6", sampleGoals); expect(found?.slug).toBe("beta"); }); test("exact short-to-short match", () => { const found = findGoalByMergeSha("684f257", sampleGoals); expect(found?.slug).toBe("beta"); }); test("no match returns null", () => { expect(findGoalByMergeSha("deadbeef", sampleGoals)).toBeNull(); }); test("empty query returns null", () => { expect(findGoalByMergeSha("", sampleGoals)).toBeNull(); }); test("skips pending goals (null mergeSha)", () => { expect(findGoalByMergeSha("pending-thing", sampleGoals)).toBeNull(); }); });