obsidian-plugin-markdown-tasks/test/pendingTasks.test.ts
Felipe M. 11c5944c42
Some checks failed
Release / build (push) Failing after 11s
CI / build (push) Failing after 7s
Skip code blocks and frontmatter in task detection
Task counting and rollover were doing pure line-by-line regex matching,
so `- [ ] foo` inside a fenced code block or YAML frontmatter was
counted as a real pending task and migrated by rollover. Add a shared
classifier that marks each line as frontmatter, code, or content, and
skip non-content lines in detectTasks and rolloverCore's parser and
heading helpers.
2026-05-04 08:47:53 +02:00

100 lines
3.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {describe, expect, it} from "bun:test";
import {detectTasks} from "../src/pendingTasks";
import type {MarkdownTasksSettings} from "../src/settings";
const baseSettings = {
completedSymbol: "x",
movedSymbol: ">",
countRootTasksOnly: false,
} as unknown as MarkdownTasksSettings;
const settings = (overrides: Partial<MarkdownTasksSettings> = {}): MarkdownTasksSettings => ({
...baseSettings,
...overrides,
});
describe("detectTasks basic counting", () => {
it("counts open tasks as pending", () => {
const result = detectTasks("- [ ] one\n- [ ] two\n", settings());
expect(result.totalTasks).toBe(2);
expect(result.pendingTasks).toBe(2);
expect(result.hasPendingTasks).toBe(true);
});
it("treats completed and moved tasks as not pending", () => {
const result = detectTasks("- [ ] open\n- [x] done\n- [>] moved\n", settings());
expect(result.totalTasks).toBe(3);
expect(result.pendingTasks).toBe(1);
});
it("returns no tasks for empty content", () => {
const result = detectTasks("", settings());
expect(result.totalTasks).toBe(0);
expect(result.pendingTasks).toBe(0);
expect(result.hasPendingTasks).toBe(false);
});
});
describe("detectTasks code block exclusion", () => {
it("does not count tasks inside a backtick-fenced code block", () => {
const input = [
"# Notes",
"",
"```markdown",
"- [ ] not a real task",
"- [ ] also not real",
"```",
"",
"- [ ] real task",
].join("\n");
const result = detectTasks(input, settings());
expect(result.totalTasks).toBe(1);
expect(result.pendingTasks).toBe(1);
});
it("does not count tasks inside a tilde-fenced code block", () => {
const input = ["~~~", "- [ ] not real", "~~~", "- [x] done"].join("\n");
const result = detectTasks(input, settings());
expect(result.totalTasks).toBe(1);
expect(result.pendingTasks).toBe(0);
});
it("returns no pending tasks when only code-block tasks exist", () => {
const input = ["```", "- [ ] not real", "```"].join("\n");
const result = detectTasks(input, settings());
expect(result.totalTasks).toBe(0);
expect(result.pendingTasks).toBe(0);
expect(result.hasPendingTasks).toBe(false);
});
it("handles tasks before, inside, and after a code block", () => {
const input = [
"- [ ] before",
"```",
"- [ ] inside (ignored)",
"```",
"- [x] after done",
].join("\n");
const result = detectTasks(input, settings());
expect(result.totalTasks).toBe(2);
expect(result.pendingTasks).toBe(1);
});
});
describe("detectTasks frontmatter exclusion", () => {
it("ignores task-like lines inside YAML frontmatter", () => {
const input = ["---", "- [ ] not a task", "---", "- [ ] real task"].join("\n");
const result = detectTasks(input, settings());
expect(result.totalTasks).toBe(1);
expect(result.pendingTasks).toBe(1);
});
});
describe("detectTasks root-only counting still skips code blocks", () => {
it("skips code-block tasks when countRootTasksOnly is enabled", () => {
const input = ["```", "- [ ] inside", "```", "- [ ] real"].join("\n");
const result = detectTasks(input, settings({countRootTasksOnly: true}));
expect(result.totalTasks).toBe(1);
expect(result.pendingTasks).toBe(1);
});
});