Total: 170 tests (74 parse + 47 mutation + 49 unit)
Golden tests that verify markdown → Task object parsing.
Test
Description
simple
Single open task with title only
subtask
Parent task with one child subtask (2-space indent)
deep_subtasks
4-level nested subtasks (level 0→1→2→3) with sibling at level 1
subtask_metadata
Subtasks with their own tags, assignees, and projects
state_open
Open state marker [ ] parsed as "open"
state_done
Done state marker [x] parsed as "done"
state_blocked
Blocked state marker [!] parsed as "blocked"
state_cancelled
Cancelled state marker [-] parsed as "cancelled"
star_marker
Asterisk * as list marker (alternative to -)
frontmatter
YAML frontmatter block ignored, tasks parsed after
Test
Description
assignee
Single @name parsed into assignees list
multiple_assignees
Multiple @alice @bob in one task
tag
Single #tag parsed into tags list
multiple_tags
Multiple #tag1 #tag2 in one task
project
Simple +project sets project_path
hierarchical_project
Nested +parent/child/leaf creates path hierarchy
version_project
Version numbers in project +app/v1.2.3
project_decomposition
Complex project path parsing and normalization
priority
Priority marker (A) through (Z)
priority_first
Priority at start of line before title text
due_date
Due date due:2025-01-15 as explicit key:value
duration
Time estimates ~2h, ~30m, ~1d converted to minutes
recurrence
Recurrence patterns repeat:daily, repeat:weekly
position_date
Single positional date becomes planned_date
position_dates_both
Two positional dates: first=planned, second=done
custom_field
Arbitrary key:value pairs stored in custom_fields
quoted_value
Quoted values key:"value with spaces"
url_custom_field
URL as custom field value link:https://...
escape_at
Escaped \@ becomes literal @ in title
comprehensive
All metadata types combined in one task
frontmatter_timezone
YAML frontmatter with timezone and locale
frontmatter_locale
Locale field in YAML frontmatter
frontmatter_invalid_timezone
Invalid timezone stored without validation error
duplicate_priority
Multiple priorities - first one used
Test
Description
inherit_project
Task inherits +project from parent heading
inherit_tag
Task inherits #tag from parent heading
inherit_section
Tasks under heading inherit section context
heading_assignees
@owner on heading inherited by tasks below
heading_custom_fields
key:value on heading inherited by tasks below
heading_level_pop
H1→H2→H1 resets inheritance context
heading_skip_level
H1→H4 (skipping H2, H3) still builds path correctly
deep_heading_nesting
4+ heading levels build deep project paths
all_levels_max
All 6 heading levels (H1-H6) with full metadata accumulation
custom_field_override
Child heading env:prod overrides parent env:dev
multiple_custom_field_levels
Custom fields accumulated from multiple heading levels
empty_project_segment
Heading without +project between project headings
tag_deduplication
Duplicate tags (heading + task) appear once in merged list
subtask_inheritance
Subtask inherits parent task's tags and assignees
subtask_override_parent
Subtask adds own metadata to inherited parent metadata
inheritance_tracking
Separate tracking of inherited_* vs explicit_* fields
Test
Description
empty_title
Task line with only metadata, no title text
metadata_only_task
Task with just #tag @user, empty title allowed
multiple_priorities
(A) (B) (C) - only first priority used, others stripped
multiple_escapes
Multiple \@ and \# escapes in same title
invalid_date_format
Malformed dates: 2025-13-45 stored as-is, 25-01-15 ignored
duration_boundaries
Edge values: ~0h, ~1m, ~999d
malformed_keyvalue
key:value:extra:colons - only first colon splits
three_positional_dates
Third date silently consumed, not in title
heading_level_7
Seven ####### is invalid heading, treated as text
odd_indent
3-space indent still creates subtask hierarchy
mixed_list_markers
Both - and * markers in same file
unicode_title
Unicode characters (emoji, CJK) in task title
long_title
Very long title line with many metadata tokens
Test
Description
file_links
[[other.md]] link resolves and includes tasks
nested_links
Linked file contains its own [[deeper.md]] links
link_after_heading
Link within heading scope inherits heading context
circular_links
A→B→A circular reference handled without infinite loop
missing_link
[[nonexistent.md]] produces warning, continues parsing
Test
Description
personal_tasks
Typical personal todo list with mixed projects
project_hierarchy
Multi-level project organization with teams
sprint_planning
Agile sprint board with epics, stories, subtasks
team_standup
Daily standup notes with blockers and assignments
Mutation Tests (47 tests)
Golden tests that verify Task modification and file rewriting.
Test
Description
mark_done
state: done adds done_date, changes [ ] to [x]
mark_open
state: open clears done_date, changes [x] to [ ]
mark_blocked
state: blocked adds paused_date, changes to [!]
unblock
state: open from blocked clears paused_date
change_title
Update task title text, preserve other metadata
change_priority
Add or change priority (A)
add_due_date
Add due:2025-01-15 to existing task
update_estimate
Change ~2h to ~4h
remove_field
REMOVE sentinel clears optional field
Test
Description
set_tags
Replace explicit_tags list, merged with inherited
set_assignees
Replace explicit_assignees list
set_custom_fields
Replace explicit_custom_fields dict
preserve_inherited
Mutation preserves inherited_* metadata from heading
Test
Description
daily
Complete daily recurring task
weekly
Complete weekly recurring task
biweekly
Complete biweekly (2 weeks) recurring task
monthly
Complete monthly recurring task
yearly
Complete yearly recurring task
cancelled
Cancel recurring task: no new occurrence created
blocked
Block recurring task: paused_date set
no_planned_date
Recurrence uses due_date when no planned_date
month_end
Jan 31 monthly → Feb 28 (clamped)
year_end
Dec 31 yearly → Dec 31 next year
leap_year
Feb 29 yearly → Feb 28 in non-leap year
leap_month_end
Jan 31 monthly in leap year → Feb 29
with_metadata
Recurring task with tags, assignees preserved
2nd_tuesday
Nth weekday pattern: 2nd Tuesday of month
last_friday
Last weekday pattern: last Friday of month
15th_of_month
Day of month pattern: 15th
31st_clamping
31st clamps to month end (Feb 28)
5th_monday_missing
5th Monday skips months without 5 Mondays
same_day_nth_weekday
Complete on exact nth weekday → next month
natural_language_every_other
Natural language: "every other week"
Test
Description
not_found
Target task doesn't exist → fail status
ambiguous
Multiple tasks match target → fail status
Test
Description
remove_title
title: REMOVE rejected, returns partial status
remove_state
state: REMOVE rejected, returns partial status
blocked_to_done
Blocked→done transition: done_date set, paused_date kept
done_date_already_set
Reopen done task: clears done_date, keeps planned_date
multiple_changes
Apply state, title, priority, tags, due_date, estimate at once
modify_subtask
Target and mutate a subtask by title
Test
Description
linked_file_update
Mutation targets task in linked file, updates correct file
Test
Description
comprehensive
Complex real-world mutation scenario
project_subtasks
Mutate tasks within project hierarchy
batch_operations
Multiple updates in batch
inherited_context
Mutation preserves heading context
Python unit tests for serialization and equality.
Class
Tests
Description
TestToMarkdownLine
4
Single task → markdown line conversion
TestToMarkdownBlock
3
Task with subtasks → indented block
TestToMarkdown
4
Full document reconstruction
TestFormatDuration
3
Minutes → ~Xh / ~Xm formatting
TestEquality
8
Task __eq__, __hash__, content_eq, identical_to
Function
Description
test_parse
Parameterized: runs all parse/ golden tests
test_mutation
Parameterized: runs all mutate/ golden tests