import { describe, expect, test } from "vitest"; import { composeFrontmatter, docFrontmatterToPairs, parseNote, serializeFrontmatter } from "./frontmatter"; describe("parseNote", () => { test("splits frontmatter and body, strips BOM", () => { const { frontmatter, body } = parseNote("---\ntitle: Hi\n---\nHello\n"); expect(frontmatter).toEqual({ title: "Hi" }); expect(body).toBe("Hello\n"); }); test("no frontmatter returns empty object and full body", () => { expect(parseNote("Just text")).toEqual({ frontmatter: {}, body: "Just text" }); }); }); describe("docFrontmatterToPairs", () => { test("converts a record to ordered string pairs", () => { const pairs = docFrontmatterToPairs({ title: "Hello", date: new Date("2026-02-06T00:00:00Z"), draft: true, }); expect(pairs).toEqual([ { key: "title", value: "Hello" }, { key: "date", value: "2026-02-06" }, { key: "draft", value: "true" }, ]); }); test("empty record yields an empty array", () => { expect(docFrontmatterToPairs({})).toEqual([]); }); }); describe("composeFrontmatter", () => { const doc = [ { key: "title", value: "Hello" }, { key: "date", value: "2026-02-06" }, ]; const editable = [ { key: "layout", value: "post" }, { key: "kind", value: "essay" }, ]; test("merge on: document fields first, then editable rows", () => { expect(composeFrontmatter(doc, editable, true)).toEqual([ { key: "title", value: "Hello" }, { key: "date", value: "2026-02-06" }, { key: "layout", value: "post" }, { key: "kind", value: "essay" }, ]); }); test("merge off: only the editable rows", () => { expect(composeFrontmatter(doc, editable, false)).toEqual(editable); }); test("an editable row overrides a document field with the same key (doc field dropped)", () => { const ed = [ { key: "title", value: "Override" }, { key: "layout", value: "post" }, ]; expect(composeFrontmatter(doc, ed, true)).toEqual([ { key: "date", value: "2026-02-06" }, { key: "title", value: "Override" }, { key: "layout", value: "post" }, ]); }); test("blank-key editable rows are skipped", () => { const ed = [ { key: "", value: "" }, { key: "layout", value: "post" }, { key: " ", value: "x" }, ]; expect(composeFrontmatter([], ed, true)).toEqual([{ key: "layout", value: "post" }]); }); test("duplicate editable keys: last value wins at first position", () => { const ed = [ { key: "tag", value: "a" }, { key: "tag", value: "b" }, ]; expect(composeFrontmatter([], ed, false)).toEqual([{ key: "tag", value: "b" }]); }); }); describe("serializeFrontmatter", () => { test("bare-safe values unquoted, others JSON-quoted", () => { const out = serializeFrontmatter([ { key: "layout", value: "post" }, { key: "date", value: "2026-06-11" }, { key: "title", value: "On making a game" }, { key: "description", value: "And how it's different" }, ]); expect(out).toBe( `---\nlayout: post\ndate: 2026-06-11\ntitle: On making a game\ndescription: "And how it's different"\n---\n` ); }); test("empty value becomes quoted empty string", () => { expect(serializeFrontmatter([{ key: "tags", value: "" }])).toBe(`---\ntags: ""\n---\n`); }); test("YAML-special boolean strings are quoted", () => { expect(serializeFrontmatter([{ key: "draft", value: "true" }])).toBe(`---\ndraft: "true"\n---\n`); expect(serializeFrontmatter([{ key: "published", value: "false" }])).toBe(`---\npublished: "false"\n---\n`); }); test("numeric-looking strings are quoted", () => { expect(serializeFrontmatter([{ key: "n", value: "42" }])).toBe(`---\nn: "42"\n---\n`); }); test("ISO date strings remain bare (not quoted as numeric)", () => { expect(serializeFrontmatter([{ key: "date", value: "2026-06-11" }])).toBe(`---\ndate: 2026-06-11\n---\n`); }); });