syntaxai/tdd.md · main · src / b32_goals_meta.test.ts

b32_goals_meta.test.ts 185 lines · 4711 bytes raw
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<GoalEntry> = [
  {
    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();
  });
});