"""Unit tests for TodoParser.""" import pytest from datetime import datetime from src.parsers.todo_parser import TodoParser, Task class TestTodoParser: """Tests for TodoParser class.""" def test_parse_simple_task(self) -> None: """Test parsing a simple task without metadata.""" line = "Buy milk" task = TodoParser.parse_line(line) assert task is not None assert task.description == "Buy milk" assert task.completed == False assert task.priority is None assert len(task.projects) == 0 assert len(task.contexts) == 0 def test_parse_task_with_priority(self) -> None: """Test parsing a task with priority.""" line = "(A) Write blog post" task = TodoParser.parse_line(line) assert task is not None assert task.priority == "A" assert task.description == "Write blog post" def test_parse_task_with_creation_date(self) -> None: """Test parsing a task with creation date.""" line = "(B) 2026-01-31 Finish implementation" task = TodoParser.parse_line(line) assert task is not None assert task.priority == "B" assert task.creation_date == datetime(2026, 1, 31) assert task.description == "Finish implementation" def test_parse_task_with_projects(self) -> None: """Test parsing a task with project tags.""" line = "Write tests +myorg-assistant +testing" task = TodoParser.parse_line(line) assert task is not None assert "myorg-assistant" in task.projects assert "testing" in task.projects assert task.description == "Write tests" def test_parse_task_with_contexts(self) -> None: """Test parsing a task with context tags.""" line = "Call dentist @telefon @recados" task = TodoParser.parse_line(line) assert task is not None assert "telefon" in task.contexts assert "recados" in task.contexts assert task.description == "Call dentist" def test_parse_task_with_due_date(self) -> None: """Test parsing a task with due date metadata.""" line = "(A) Submit report +work due:2026-02-15" task = TodoParser.parse_line(line) assert task is not None assert task.due_date == datetime(2026, 2, 15) assert "due" in task.metadata assert task.metadata["due"] == "2026-02-15" def test_parse_completed_task(self) -> None: """Test parsing a completed task.""" line = "x 2026-01-31 Buy groceries" task = TodoParser.parse_line(line) assert task is not None assert task.completed == True assert task.completion_date == datetime(2026, 1, 31) assert task.description == "Buy groceries" def test_parse_complex_task(self) -> None: """Test parsing a complex task with all features.""" line = "(A) 2026-01-31 Write observability blog post +observability-blog @computer-deep due:2026-02-15 priority:high" task = TodoParser.parse_line(line) assert task is not None assert task.priority == "A" assert task.creation_date == datetime(2026, 1, 31) assert task.description == "Write observability blog post" assert "observability-blog" in task.projects assert "computer-deep" in task.contexts assert task.due_date == datetime(2026, 2, 15) assert task.metadata["priority"] == "high" def test_parse_empty_line(self) -> None: """Test parsing an empty line returns None.""" task = TodoParser.parse_line("") assert task is None def test_parse_comment_line(self) -> None: """Test parsing a comment line returns None.""" task = TodoParser.parse_line("# This is a comment") assert task is None def test_format_simple_task(self) -> None: """Test formatting a simple task.""" formatted = TodoParser.format_task(description="Buy milk") assert formatted == "Buy milk" def test_format_task_with_priority(self) -> None: """Test formatting a task with priority.""" formatted = TodoParser.format_task( description="Write tests", priority="A" ) assert formatted == "(A) Write tests" def test_format_task_with_all_features(self) -> None: """Test formatting a complex task.""" formatted = TodoParser.format_task( description="Write blog post", priority="B", creation_date=datetime(2026, 1, 31), projects=["observability-blog"], contexts=["computer-deep"], metadata={"due": "2026-02-15"} ) assert "(B)" in formatted assert "2026-01-31" in formatted assert "Write blog post" in formatted assert "+observability-blog" in formatted assert "@computer-deep" in formatted assert "due:2026-02-15" in formatted def test_format_completed_task(self) -> None: """Test formatting a completed task.""" formatted = TodoParser.format_task( description="Buy groceries", completed=True, completion_date=datetime(2026, 1, 31) ) assert formatted.startswith("x 2026-01-31") assert "Buy groceries" in formatted def test_parse_file(self) -> None: """Test parsing multiple tasks from file content.""" content = """# Tasks (A) Write tests +myorg-assistant Buy milk @recados x 2026-01-30 Completed task (B) 2026-01-31 Another task +project due:2026-02-01""" tasks = TodoParser.parse_file(content) assert len(tasks) == 4 assert tasks[0].description == "Write tests" assert tasks[1].description == "Buy milk" assert tasks[2].completed == True assert tasks[3].priority == "B" def test_filter_tasks_by_completion(self) -> None: """Test filtering tasks by completion status.""" tasks = [ Task(raw_line="x Task 1", line_number=1, completed=True, description="Task 1"), Task(raw_line="Task 2", line_number=2, completed=False, description="Task 2"), Task(raw_line="Task 3", line_number=3, completed=False, description="Task 3"), ] active = TodoParser.filter_tasks(tasks, completed=False) assert len(active) == 2 completed = TodoParser.filter_tasks(tasks, completed=True) assert len(completed) == 1 def test_filter_tasks_by_priority(self) -> None: """Test filtering tasks by priority.""" tasks = [ Task(raw_line="(A) Task 1", line_number=1, priority="A", description="Task 1"), Task(raw_line="(B) Task 2", line_number=2, priority="B", description="Task 2"), Task(raw_line="Task 3", line_number=3, description="Task 3"), ] high_priority = TodoParser.filter_tasks(tasks, priority="A") assert len(high_priority) == 1 assert high_priority[0].description == "Task 1" def test_filter_tasks_by_project(self) -> None: """Test filtering tasks by project tag.""" tasks = [ Task(raw_line="Task 1 +project1", line_number=1, description="Task 1", projects=["project1"]), Task(raw_line="Task 2 +project2", line_number=2, description="Task 2", projects=["project2"]), Task(raw_line="Task 3 +project1", line_number=3, description="Task 3", projects=["project1"]), ] project1_tasks = TodoParser.filter_tasks(tasks, project="project1") assert len(project1_tasks) == 2 def test_filter_tasks_by_context(self) -> None: """Test filtering tasks by context tag.""" tasks = [ Task(raw_line="Task 1 @home", line_number=1, description="Task 1", contexts=["home"]), Task(raw_line="Task 2 @work", line_number=2, description="Task 2", contexts=["work"]), Task(raw_line="Task 3 @home", line_number=3, description="Task 3", contexts=["home"]), ] home_tasks = TodoParser.filter_tasks(tasks, context="home") assert len(home_tasks) == 2