""" Test markdown parsing functionality for Issue #138: Explode Markdown file to markdown directory. This test module covers the core markdown structure parsing functionality, including heading extraction, content identification, and hierarchical structure analysis. """ import pytest import tempfile from pathlib import Path from unittest.mock import Mock, patch # Import will fail initially (RED phase) until implementation exists try: from markitect.plugins.builtin.markdown_commands import ( parse_markdown_structure, extract_headings, extract_section_content, MarkdownSection ) except ImportError: # Expected during RED phase - tests should fail initially parse_markdown_structure = None extract_headings = None extract_section_content = None MarkdownSection = None class TestMarkdownStructureParsing: """Test markdown file parsing and structure extraction.""" def test_parse_simple_markdown_structure(self): """Test parsing a markdown file with basic heading structure.""" markdown_content = """# Part 1: Introduction This is the introduction content. ## Chapter 1: Getting Started Content for chapter 1. ## Chapter 2: Advanced Topics Content for chapter 2. ### Section 2.1: Details Detailed content here. """ with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as f: f.write(markdown_content) temp_file = Path(f.name) try: # This should fail initially (RED phase) structure, front_matter = parse_markdown_structure(temp_file) # Verify structure assert len(structure) == 1 # One part assert structure[0].level == 1 assert structure[0].title == "Part 1: Introduction" assert len(structure[0].children) == 2 # Two chapters assert front_matter is None # No front matter in this test # Check chapters assert structure[0].children[0].level == 2 assert structure[0].children[0].title == "Chapter 1: Getting Started" assert structure[0].children[1].level == 2 assert structure[0].children[1].title == "Chapter 2: Advanced Topics" assert len(structure[0].children[1].children) == 1 # One section # Check section section = structure[0].children[1].children[0] assert section.level == 3 assert section.title == "Section 2.1: Details" finally: temp_file.unlink() def test_extract_headings_from_content(self): """Test extracting headings with their levels from markdown content.""" markdown_content = """# Main Title Some intro content. ## Chapter 1 Chapter content. ### Subsection Sub content. ## Chapter 2 More content. """ # This should fail initially (RED phase) headings = extract_headings(markdown_content) expected = [ {'level': 1, 'title': 'Main Title', 'line': 0}, {'level': 2, 'title': 'Chapter 1', 'line': 3}, {'level': 3, 'title': 'Subsection', 'line': 6}, {'level': 2, 'title': 'Chapter 2', 'line': 9} ] assert headings == expected def test_extract_section_content_between_headings(self): """Test extracting content that belongs to specific sections.""" markdown_content = """# Main Title Intro paragraph. Another intro line. ## Chapter 1 Chapter 1 content. More chapter 1 content. ### Subsection Subsection content. ## Chapter 2 Chapter 2 content. """ # This should fail initially (RED phase) headings = extract_headings(markdown_content) # Extract content for "Chapter 1" content = extract_section_content(markdown_content, headings, 1) # Index 1 = "Chapter 1" expected_content = """## Chapter 1 Chapter 1 content. More chapter 1 content. ### Subsection Subsection content.""" assert content.strip() == expected_content.strip() def test_parse_markdown_with_front_matter(self): """Test parsing markdown file with YAML front matter.""" markdown_content = """--- title: "My Document" author: "Test Author" date: 2025-10-07 --- # Chapter 1 Content for chapter 1. ## Section 1.1 Section content. """ with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as f: f.write(markdown_content) temp_file = Path(f.name) try: # This should fail initially (RED phase) structure, front_matter = parse_markdown_structure(temp_file) # Front matter should be extracted and structure parsed assert len(structure) == 1 assert structure[0].title == "Chapter 1" assert structure[0].level == 1 assert front_matter is not None assert 'title: "My Document"' in front_matter finally: temp_file.unlink() def test_parse_markdown_with_no_headings(self): """Test parsing markdown file with no headings.""" markdown_content = """This is just plain content. No headings here. Some more content. """ with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as f: f.write(markdown_content) temp_file = Path(f.name) try: # This should fail initially (RED phase) structure, front_matter = parse_markdown_structure(temp_file) # Should return empty structure or handle gracefully assert structure == [] assert front_matter is None finally: temp_file.unlink() def test_parse_markdown_with_inconsistent_levels(self): """Test parsing markdown with inconsistent heading levels (e.g., jump from # to ###).""" markdown_content = """# Main Title Main content. ### Deep Section This jumps from level 1 to level 3. ## Normal Chapter Back to level 2. """ with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as f: f.write(markdown_content) temp_file = Path(f.name) try: # This should fail initially (RED phase) structure, front_matter = parse_markdown_structure(temp_file) # Should handle inconsistent levels gracefully assert len(structure) == 1 # Main title assert front_matter is None assert structure[0].level == 1 assert len(structure[0].children) >= 1 # Should have children finally: temp_file.unlink() class TestMarkdownSectionModel: """Test the MarkdownSection data model.""" def test_markdown_section_creation(self): """Test creating MarkdownSection objects.""" # This should fail initially (RED phase) section = MarkdownSection( level=1, title="Test Section", content="Test content", line_start=0, line_end=10 ) assert section.level == 1 assert section.title == "Test Section" assert section.content == "Test content" assert section.children == [] def test_markdown_section_add_child(self): """Test adding child sections to parent sections.""" # This should fail initially (RED phase) parent = MarkdownSection(level=1, title="Parent", content="Parent content") child = MarkdownSection(level=2, title="Child", content="Child content") parent.add_child(child) assert len(parent.children) == 1 assert parent.children[0] == child assert child.parent == parent def test_markdown_section_hierarchy_validation(self): """Test that section hierarchy is validated correctly.""" # This should fail initially (RED phase) parent = MarkdownSection(level=1, title="Parent", content="Parent content") invalid_child = MarkdownSection(level=3, title="Invalid", content="Skip level 2") # Should raise exception for invalid hierarchy (skipping level 2) with pytest.raises(ValueError, match="Invalid heading hierarchy"): parent.add_child(invalid_child)