Files

73 lines
3.6 KiB
TypeScript

import assert from "node:assert/strict";
import { test } from "bun:test";
import { parseMdtodoImport } from "./mdtodo-import.ts";
test("MDTODO import preserves three Rxx levels and attaches reports", () => {
const plan = parseMdtodoImport({
sourcePath: "/tmp/demo/MDTODO.md",
sourceModifiedAt: "2026-07-15T12:00:00.000Z",
markdown: `# Demo\n\n## R1 Root [in_progress]\n\nSee [任务报告](./details/R1_Task_Report.md).\n\n### R1.1 Child [completed]\n\n#### R1.1.1 Deep child [blocked]\n`,
reports: [{ href: "./details/R1_Task_Report.md", sourcePath: "/tmp/demo/details/R1_Task_Report.md", body: "# R1 report\n\nPassed.", modifiedAt: "2026-07-17T09:30:00.000Z" }]
});
assert.equal(plan.groupName, "Demo");
assert.deepEqual(plan.summary, { taskCount: 1, subtaskCount: 1, subsubtaskCount: 1, reportCount: 1, missingReportCount: 0, flattenedTaskCount: 0, warningCount: 0 });
assert.equal(plan.tasks[0]?.status, "in_progress");
assert.equal(plan.tasks[1]?.status, "completed");
assert.equal(plan.tasks[2]?.status, "blocked");
assert.equal(plan.tasks[2]?.parentSourceId, "R1.1");
assert.equal(plan.tasks[0]?.reports[0]?.body, "# R1 report\n\nPassed.");
assert.equal(plan.tasks[0]?.startAt, "2026-07-14T12:00:00.000Z");
assert.equal(plan.tasks[0]?.dueAt, "2026-07-17T09:30:00.000Z");
assert.equal(plan.tasks[1]?.startAt, "2026-07-14T12:00:00.000Z");
assert.equal(plan.tasks[1]?.dueAt, "2026-07-15T12:00:00.000Z");
});
test("MDTODO import flattens only levels deeper than subsubtask", () => {
const plan = parseMdtodoImport({
sourcePath: "/tmp/demo/MDTODO.md",
sourceModifiedAt: "2026-07-15T12:00:00.000Z",
markdown: "# Demo\n\n## R2 Root\n\n### R2.9 Child\n\n#### R2.9.1 Grandchild\n\n##### R2.9.1.1 Deeper\n",
reports: []
});
assert.equal(plan.tasks[2]?.parentSourceId, "R2.9");
assert.equal(plan.tasks[3]?.parentSourceId, "R2.9");
assert.equal(plan.summary.subsubtaskCount, 2);
assert.equal(plan.summary.flattenedTaskCount, 1);
});
test("MDTODO import reports missing linked report files", () => {
const plan = parseMdtodoImport({
sourcePath: "/tmp/demo/MDTODO.md",
sourceModifiedAt: "2026-07-15T12:00:00.000Z",
markdown: "# Demo\n\n## R1 Root\n\n[Task report](./R1_Task_Report.md)\n",
reports: []
});
assert.equal(plan.summary.missingReportCount, 1);
assert.equal(plan.warnings[0]?.code, "report_file_missing");
});
test("MDTODO import expands a parent range to contain report-dated children", () => {
const plan = parseMdtodoImport({
sourcePath: "/tmp/demo/MDTODO.md",
sourceModifiedAt: "2026-07-15T12:00:00.000Z",
markdown: `# Demo\n\n## R1 Root\n\n### R1.1 Child\n\nSee [Task report](./R1.1_Task_Report.md).\n`,
reports: [{ href: "./R1.1_Task_Report.md", sourcePath: "/tmp/demo/R1.1_Task_Report.md", body: "# Child report", modifiedAt: "2026-07-17T09:30:00.000Z" }]
});
assert.equal(plan.tasks[1]?.startAt, "2026-07-16T09:30:00.000Z");
assert.equal(plan.tasks[1]?.dueAt, "2026-07-17T09:30:00.000Z");
assert.equal(plan.tasks[0]?.startAt, "2026-07-14T12:00:00.000Z");
assert.equal(plan.tasks[0]?.dueAt, "2026-07-17T09:30:00.000Z");
});
test("MDTODO import never truncates title content at URL colons", () => {
const plan = parseMdtodoImport({
sourcePath: "/tmp/demo/MDTODO.md",
sourceModifiedAt: "2026-07-15T12:00:00.000Z",
markdown: "# Demo\n\n## R1\n\n完成 [UniDesk #2361](https://github.com/pikasTech/unidesk/issues/2361) 并保留后续文本。\n",
reports: []
});
assert.equal(plan.tasks[0]?.title, "R1 完成 [UniDesk #2361](https://github.com/pikasTech/unidesk/issues/2361) 并保留后续文本。");
});