tests/tasks.test.ts
Rama main · réplica de lectura del repositorio original.
// Tasks (shared/tasks.ts): the plugin's grammar, the one-line toggle, the
// fence's filters.
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { filterTasks, parseTaskLine, parseTasksFence, scanTasks, toggleTaskLine } from "../shared/tasks.ts";
describe("a task line", () => {
it("reads the box, the text and the plugin's fields", () => {
const t = parseTaskLine(" - [ ] Read ch. 3 #reading 📅 2026-09-20 ⏳ 2026-09-18 ⏫ 🔁 every week", 4)!;
assert.equal(t.text, "Read ch. 3 #reading");
assert.equal(t.done, false);
assert.equal(t.due, "2026-09-20");
assert.equal(t.scheduled, "2026-09-18");
assert.equal(t.priority, "high");
assert.equal(t.recurrence, "every week");
assert.deepEqual(t.tags, ["reading"]);
assert.equal(t.indent, 2);
assert.equal(t.line, 4);
});
it("reads done, cancelled and the completion stamp; ignores non-tasks", () => {
assert.equal(parseTaskLine("- [x] done ✅ 2026-09-01", 1)!.completed, "2026-09-01");
assert.equal(parseTaskLine("- [-] dropped", 1)!.cancelled, true);
assert.equal(parseTaskLine("- plain bullet", 1), null);
assert.equal(parseTaskLine("[ ] no bullet", 1), null);
});
it("scans a note, skipping fences, with full-source lines", () => {
const md = "---\nx: 1\n---\n- [ ] one\n```\n- [ ] not a task\n```\n1. [x] two\n";
assert.deepEqual(scanTasks(md).map((t) => [t.line, t.text, t.done]), [[4, "one", false], [8, "two", true]]);
});
it("toggles a line with a tab indent and a trailing tab", () => {
assert.equal(toggleTaskLine("\t- [ ] tabbed\t", true, "2026-09-13"), "\t- [x] tabbed ✅ 2026-09-13");
});
it("toggles one line, stamping and unstamping ✅, keeping the fields", () => {
const line = "- [ ] Read ch. 3 📅 2026-09-20";
const done = toggleTaskLine(line, true, "2026-09-13");
assert.equal(done, "- [x] Read ch. 3 📅 2026-09-20 ✅ 2026-09-13");
assert.equal(toggleTaskLine(done, false, "2026-09-14"), "- [ ] Read ch. 3 📅 2026-09-20");
assert.equal(toggleTaskLine(" * [X] a ✅ 2026-01-01", false, "x"), " * [ ] a");
});
});
describe("a tasks fence", () => {
const rows = [
{ path: "A.md", tags: ["work"], task: parseTaskLine("- [ ] a 📅 2026-09-14 🔽", 1)! },
{ path: "B.md", tags: [], task: parseTaskLine("- [ ] b 📅 2026-09-10 ⏫", 1)! },
{ path: "C.md", tags: [], task: parseTaskLine("- [x] c 📅 2026-09-12 ✅ 2026-09-12", 1)! },
{ path: "D.md", tags: [], task: parseTaskLine("- [ ] d", 1)! },
];
it("defaults to open tasks, soonest due first, undated last", () => {
const spec = parseTasksFence("", "2026-09-13");
assert.deepEqual(filterTasks(rows, spec).map((r) => r.path), ["B.md", "A.md", "D.md"]);
});
it("understands the plugin's phrases", () => {
assert.deepEqual(filterTasks(rows, parseTasksFence("overdue", "2026-09-13")).map((r) => r.path), ["B.md"]);
assert.deepEqual(filterTasks(rows, parseTasksFence("due this week", "2026-09-13")).map((r) => r.path), ["B.md"]);
assert.deepEqual(filterTasks(rows, parseTasksFence("done", "2026-09-13")).map((r) => r.path), ["C.md"]);
assert.deepEqual(filterTasks(rows, parseTasksFence("tag:work", "2026-09-13")).map((r) => r.path), ["A.md"]);
assert.deepEqual(filterTasks(rows, parseTasksFence("all\nsort: priority\nlimit: 2", "2026-09-13")).map((r) => r.path), ["B.md", "C.md"]);
});
});