134 lines
3.9 KiB
TypeScript
134 lines
3.9 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { TaskPriority } from "@/model/taskPriority";
|
|
import { TaskStatus } from "@/model/taskStatus";
|
|
import {
|
|
extractFrontmatterBlock,
|
|
findFieldRange,
|
|
formatTagsYamlValue,
|
|
replaceFrontmatterField,
|
|
setFrontmatterTags,
|
|
} from "./frontmatterFields";
|
|
|
|
const sample = `---
|
|
id: abc
|
|
title: Hello
|
|
status: todo
|
|
priority: medium
|
|
tags: [old]
|
|
---
|
|
|
|
Body
|
|
`;
|
|
|
|
describe("replaceFrontmatterField", () => {
|
|
it("replaces status value", () => {
|
|
const result = replaceFrontmatterField(sample, "status", TaskStatus.DONE);
|
|
expect(result.ok).toBe(true);
|
|
if (!result.ok) return;
|
|
expect(result.content).toContain("status: done");
|
|
expect(result.content).toContain("title: Hello");
|
|
expect(result.content).toContain("Body");
|
|
});
|
|
|
|
it("replaces priority value", () => {
|
|
const result = replaceFrontmatterField(sample, "priority", TaskPriority.CRITICAL);
|
|
expect(result.ok).toBe(true);
|
|
if (!result.ok) return;
|
|
expect(result.content).toContain("priority: critical");
|
|
});
|
|
|
|
it("fails when field is missing", () => {
|
|
const result = replaceFrontmatterField(sample, "assignee", "me");
|
|
expect(result).toEqual({ ok: false, reason: "no-field" });
|
|
});
|
|
|
|
it("fails without frontmatter", () => {
|
|
const result = replaceFrontmatterField("plain", "status", "todo");
|
|
expect(result).toEqual({ ok: false, reason: "no-frontmatter" });
|
|
});
|
|
});
|
|
|
|
describe("findFieldRange", () => {
|
|
it("points at the value column", () => {
|
|
const range = findFieldRange(sample, "status");
|
|
expect(range).toBeDefined();
|
|
const line = sample.split("\n")[range!.startLine];
|
|
expect(line.slice(range!.startCol, range!.endCol)).toBe("todo");
|
|
});
|
|
});
|
|
|
|
describe("formatTagsYamlValue", () => {
|
|
it("formats empty and simple lists", () => {
|
|
expect(formatTagsYamlValue([])).toBe("[]");
|
|
expect(formatTagsYamlValue(["bug", "frontend"])).toBe(
|
|
"[bug, frontend]",
|
|
);
|
|
});
|
|
|
|
it("quotes tags with spaces", () => {
|
|
expect(formatTagsYamlValue(["my tag"])).toBe('["my tag"]');
|
|
});
|
|
});
|
|
|
|
describe("setFrontmatterTags", () => {
|
|
it("replaces the tags line", () => {
|
|
const result = setFrontmatterTags(sample, ["bug", "docs"]);
|
|
expect(result.ok).toBe(true);
|
|
if (!result.ok) return;
|
|
expect(result.content).toContain("tags: [bug, docs]");
|
|
expect(result.content).not.toContain("tags: [old]");
|
|
});
|
|
});
|
|
|
|
describe("extractFrontmatterBlock", () => {
|
|
it("extracts yaml from a valid block", () => {
|
|
const block = extractFrontmatterBlock(
|
|
"---\ntitle: Hello\nstatus: todo\n---\nbody",
|
|
);
|
|
expect(block).not.toBeNull();
|
|
expect(block!.yaml).toBe("title: Hello\nstatus: todo");
|
|
expect(block!.closeLine).toBe(3);
|
|
});
|
|
|
|
it("returns null when content does not start with ---", () => {
|
|
expect(extractFrontmatterBlock("no frontmatter")).toBeNull();
|
|
expect(extractFrontmatterBlock("")).toBeNull();
|
|
});
|
|
|
|
it("handles unclosed frontmatter with trailing newline", () => {
|
|
const block = extractFrontmatterBlock("---\ntitle: x\n");
|
|
expect(block).not.toBeNull();
|
|
expect(block!.closeLine).toBe(-1);
|
|
expect(block!.yaml).toBe("title: x\n");
|
|
});
|
|
|
|
it("handles unclosed frontmatter without trailing newline", () => {
|
|
const block = extractFrontmatterBlock("---\ntitle: x");
|
|
expect(block).not.toBeNull();
|
|
expect(block!.closeLine).toBe(-1);
|
|
expect(block!.yaml).toBe("title: x");
|
|
});
|
|
|
|
it("handles CRLF line endings (yaml is normalized to LF)", () => {
|
|
const block = extractFrontmatterBlock(
|
|
"---\r\ntitle: Hello\r\nstatus: todo\r\n---\r\nbody",
|
|
);
|
|
expect(block).not.toBeNull();
|
|
expect(block!.yaml).toBe("title: Hello\nstatus: todo");
|
|
});
|
|
|
|
it("handles --- with trailing whitespace", () => {
|
|
const block = extractFrontmatterBlock(
|
|
"--- \ntitle: Hello\n--- \nbody",
|
|
);
|
|
expect(block).not.toBeNull();
|
|
expect(block!.yaml).toBe("title: Hello");
|
|
expect(block!.closeLine).toBe(2);
|
|
});
|
|
|
|
it("only matches --- on the first line", () => {
|
|
const block = extractFrontmatterBlock("text\n---\ntitle: x\n---\n");
|
|
expect(block).toBeNull();
|
|
});
|
|
});
|