""" TDD8 Cycle 3: Contentmatter Commands Tests (RED Phase) Issue #38 - MarkdownMatters CLI Implementation This test file implements the RED phase tests for contentmatter command family: - markitect contentmatter-get [key] [path] - Get MMD key-value from content - markitect contentmatter-set key=value [path] - Set MMD key-value in content - markitect contentmatter-keys [path] - List all contentmatter keys - markitect contentmatter-stats [path] - Contentmatter statistics Following TDD8 methodology, these tests MUST FAIL initially. """ import pytest import tempfile import os from pathlib import Path from click.testing import CliRunner from markitect.matter_contentmatter.parser import ContentmatterParser from markitect.matter_contentmatter.stats import ContentmatterStats from markitect.matter_contentmatter.commands import contentmatter_get, contentmatter_set, contentmatter_keys, contentmatter_stats class TestContentmatterExtraction: """Test contentmatter extraction and parsing.""" @pytest.fixture def test_files_dir(self): """Path to contentmatter test fixture files.""" return Path(__file__).parent / "fixtures" / "contentmatter_test_files" @pytest.fixture def contentmatter_parser(self): """Contentmatter parser instance.""" return ContentmatterParser() def test_contentmatter_parser_extracts_mmd_keyvalues(self, contentmatter_parser, test_files_dir): """Test that parser extracts MultiMarkdown key-value pairs.""" file_path = test_files_dir / "simple_contentmatter.md" with open(file_path, 'r') as f: text = f.read() contentmatter = contentmatter_parser.extract_contentmatter(text) # Should extract basic key-value pairs assert contentmatter["Author"] == "Jane Smith" assert contentmatter["Project"] == "Contentmatter Testing" assert contentmatter["Version"] == "2.0" assert contentmatter["Status"] == "Active" assert contentmatter["License"] == "MIT" assert contentmatter["Repository"] == "https://github.com/example/project" assert contentmatter["Documentation"] == "https://docs.example.com" assert contentmatter["Updated"] == "2025-10-02" assert contentmatter["Reviewer"] == "John Doe" assert contentmatter["Category"] == "Testing" def test_contentmatter_parser_extracts_complex_content(self, contentmatter_parser, test_files_dir): """Test extraction from document with rich contentmatter.""" file_path = test_files_dir / "mmd_rich_content.md" with open(file_path, 'r') as f: text = f.read() contentmatter = contentmatter_parser.extract_contentmatter(text) # Should extract author information assert contentmatter["Author"] == "Dr. Sarah Johnson" assert contentmatter["Institution"] == "MIT Computer Science Department" assert contentmatter["Email"] == "sarah.johnson@mit.edu" # Should extract research metadata assert contentmatter["Keywords"] == "algorithms, distributed systems, optimization, performance" assert contentmatter["Classification"] == "Computer Science - Distributed Computing" assert contentmatter["Grant Number"] == "NSF-CS-2025-001" # Should extract methodology details assert contentmatter["Research Method"] == "Experimental Analysis" assert contentmatter["Sample Size"] == "1000 distributed nodes" assert contentmatter["Performance Improvement"] == "23% average speedup" def test_contentmatter_parser_handles_no_contentmatter(self, contentmatter_parser, test_files_dir): """Test that parser handles documents without contentmatter.""" file_path = test_files_dir / "no_contentmatter.md" with open(file_path, 'r') as f: text = f.read() contentmatter = contentmatter_parser.extract_contentmatter(text) # Should return empty dict for no contentmatter assert contentmatter == {} def test_contentmatter_parser_ignores_frontmatter_and_tailmatter(self, contentmatter_parser, test_files_dir): """Test that parser only extracts from content, not matter zones.""" file_path = test_files_dir / "mmd_rich_content.md" with open(file_path, 'r') as f: text = f.read() contentmatter = contentmatter_parser.extract_contentmatter(text) # Should not include frontmatter values assert "title" not in contentmatter # This is in frontmatter assert "qa_checklist" not in contentmatter # This is in tailmatter # Should only include content key-values assert "Author" in contentmatter # This is in content def test_contentmatter_get_specific_value(self, contentmatter_parser, test_files_dir): """Test getting specific contentmatter values.""" file_path = test_files_dir / "simple_contentmatter.md" with open(file_path, 'r') as f: text = f.read() value = contentmatter_parser.get_contentmatter_value(text, "Author") assert value == "Jane Smith" value = contentmatter_parser.get_contentmatter_value(text, "Repository") assert value == "https://github.com/example/project" # Should return None for non-existent keys value = contentmatter_parser.get_contentmatter_value(text, "NonExistent") assert value is None class TestContentmatterModification: """Test contentmatter modification operations.""" @pytest.fixture def contentmatter_parser(self): """Contentmatter parser instance.""" return ContentmatterParser() def test_contentmatter_set_new_value(self, contentmatter_parser): """Test adding new contentmatter to document.""" text = """# Test Document Some content here. ## Section More content.""" new_text = contentmatter_parser.set_contentmatter_value(text, "Author", "New Author") # Should add the contentmatter contentmatter = contentmatter_parser.extract_contentmatter(new_text) assert contentmatter["Author"] == "New Author" # Should preserve original content assert "# Test Document" in new_text assert "Some content here." in new_text def test_contentmatter_update_existing_value(self, contentmatter_parser): """Test updating existing contentmatter value.""" text = """# Test Document Author: Original Author Project: Test Project Some content here.""" new_text = contentmatter_parser.set_contentmatter_value(text, "Author", "Updated Author") # Should update the existing value contentmatter = contentmatter_parser.extract_contentmatter(new_text) assert contentmatter["Author"] == "Updated Author" assert contentmatter["Project"] == "Test Project" # Should preserve other values def test_contentmatter_set_multiple_values(self, contentmatter_parser): """Test setting multiple contentmatter values.""" text = """# Test Document Some content here.""" # Add multiple values text = contentmatter_parser.set_contentmatter_value(text, "Author", "Test Author") text = contentmatter_parser.set_contentmatter_value(text, "Version", "1.0") text = contentmatter_parser.set_contentmatter_value(text, "Status", "Active") contentmatter = contentmatter_parser.extract_contentmatter(text) assert contentmatter["Author"] == "Test Author" assert contentmatter["Version"] == "1.0" assert contentmatter["Status"] == "Active" class TestContentmatterKeys: """Test contentmatter key listing functionality.""" @pytest.fixture def test_files_dir(self): """Path to contentmatter test fixture files.""" return Path(__file__).parent / "fixtures" / "contentmatter_test_files" @pytest.fixture def contentmatter_parser(self): """Contentmatter parser instance.""" return ContentmatterParser() def test_contentmatter_keys_simple_document(self, contentmatter_parser, test_files_dir): """Test listing keys from simple contentmatter document.""" file_path = test_files_dir / "simple_contentmatter.md" with open(file_path, 'r') as f: text = f.read() keys = contentmatter_parser.get_contentmatter_keys(text) # Should return all contentmatter keys expected_keys = ["Author", "Project", "Version", "Status", "License", "Repository", "Documentation", "Updated", "Reviewer", "Category"] assert set(keys) == set(expected_keys) def test_contentmatter_keys_complex_document(self, contentmatter_parser, test_files_dir): """Test listing keys from complex contentmatter document.""" file_path = test_files_dir / "mmd_rich_content.md" with open(file_path, 'r') as f: text = f.read() keys = contentmatter_parser.get_contentmatter_keys(text) # Should include research paper metadata keys assert "Author" in keys assert "Institution" in keys assert "Keywords" in keys assert "Research Method" in keys assert "Performance Improvement" in keys # Should not include frontmatter or tailmatter keys assert "title" not in keys # frontmatter assert "qa_checklist" not in keys # tailmatter def test_contentmatter_keys_empty_document(self, contentmatter_parser, test_files_dir): """Test listing keys from document without contentmatter.""" file_path = test_files_dir / "no_contentmatter.md" with open(file_path, 'r') as f: text = f.read() keys = contentmatter_parser.get_contentmatter_keys(text) # Should return empty list assert keys == [] class TestContentmatterStatistics: """Test contentmatter statistics calculation.""" @pytest.fixture def test_files_dir(self): """Path to contentmatter test fixture files.""" return Path(__file__).parent / "fixtures" / "contentmatter_test_files" @pytest.fixture def contentmatter_parser(self): """Contentmatter parser instance.""" return ContentmatterParser() def test_contentmatter_stats_simple_document(self, contentmatter_parser, test_files_dir): """Test statistics calculation for simple contentmatter.""" file_path = test_files_dir / "simple_contentmatter.md" with open(file_path, 'r') as f: text = f.read() stats = contentmatter_parser.calculate_contentmatter_stats(text) # Should count contentmatter correctly assert stats.total_pairs == 10 # Number of key-value pairs assert stats.has_contentmatter is True assert stats.average_key_length > 0 assert stats.average_value_length > 0 # Should categorize value types assert stats.url_values > 0 # Repository and Documentation URLs assert stats.date_values > 0 # Updated field assert stats.email_values == 0 # No email in simple document def test_contentmatter_stats_complex_document(self, contentmatter_parser, test_files_dir): """Test statistics calculation for complex contentmatter.""" file_path = test_files_dir / "mmd_rich_content.md" with open(file_path, 'r') as f: text = f.read() stats = contentmatter_parser.calculate_contentmatter_stats(text) # Should count rich contentmatter assert stats.total_pairs > 15 # Many key-value pairs in research paper assert stats.has_contentmatter is True # Should detect email values assert stats.email_values > 0 # Email field in author info def test_contentmatter_stats_no_contentmatter(self, contentmatter_parser, test_files_dir): """Test statistics for document without contentmatter.""" file_path = test_files_dir / "no_contentmatter.md" with open(file_path, 'r') as f: text = f.read() stats = contentmatter_parser.calculate_contentmatter_stats(text) # Should indicate no contentmatter assert stats.has_contentmatter is False assert stats.total_pairs == 0 assert stats.url_values == 0 assert stats.email_values == 0 class TestContentmatterCLICommands: """Test CLI command integration.""" @pytest.fixture def runner(self): """CLI test runner.""" return CliRunner() @pytest.fixture def test_files_dir(self): """Path to contentmatter test fixture files.""" return Path(__file__).parent / "fixtures" / "contentmatter_test_files" def test_contentmatter_get_command(self, runner, test_files_dir): """Test contentmatter-get CLI command.""" file_path = test_files_dir / "simple_contentmatter.md" # Test getting simple value result = runner.invoke(contentmatter_get, ['Author', '--file', str(file_path)]) assert result.exit_code == 0 assert "Jane Smith" in result.output # Test getting URL value result = runner.invoke(contentmatter_get, ['Repository', '--file', str(file_path)]) assert result.exit_code == 0 assert "https://github.com/example/project" in result.output def test_contentmatter_keys_command(self, runner, test_files_dir): """Test contentmatter-keys CLI command.""" file_path = test_files_dir / "simple_contentmatter.md" result = runner.invoke(contentmatter_keys, ['--file', str(file_path)]) assert result.exit_code == 0 assert "Author" in result.output assert "Project" in result.output assert "Repository" in result.output def test_contentmatter_stats_command(self, runner, test_files_dir): """Test contentmatter-stats CLI command.""" file_path = test_files_dir / "simple_contentmatter.md" result = runner.invoke(contentmatter_stats, ['--file', str(file_path)]) assert result.exit_code == 0 assert "total_pairs" in result.output assert "has_contentmatter" in result.output def test_contentmatter_set_command(self, runner, test_files_dir): """Test contentmatter-set CLI command.""" # Create temporary file for testing with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False) as f: f.write("""# Test Document Author: Original Author Some content here.""") temp_file = f.name try: result = runner.invoke(contentmatter_set, ['Author=New Author', '--file', temp_file]) assert result.exit_code == 0 # Verify the change was made with open(temp_file, 'r') as f: content = f.read() assert "Author: New Author" in content finally: os.unlink(temp_file) def test_contentmatter_commands_help_text(self, runner): """Test that help text is available for all contentmatter commands.""" commands = [contentmatter_get, contentmatter_keys, contentmatter_stats, contentmatter_set] for command in commands: result = runner.invoke(command, ['--help']) assert result.exit_code == 0 assert "contentmatter" in result.output.lower() class TestContentmatterStats: """Test ContentmatterStats data class.""" def test_contentmatter_stats_creation(self): """Test ContentmatterStats object creation.""" stats = ContentmatterStats( has_contentmatter=True, total_pairs=10, average_key_length=8.5, average_value_length=15.2, url_values=2, email_values=1, date_values=1 ) assert stats.has_contentmatter is True assert stats.total_pairs == 10 assert stats.average_key_length == 8.5 assert stats.url_values == 2 def test_contentmatter_stats_to_dict(self): """Test ContentmatterStats conversion to dictionary.""" stats = ContentmatterStats( has_contentmatter=True, total_pairs=5, average_key_length=8.0, average_value_length=12.0, url_values=1, email_values=0, date_values=1 ) stats_dict = stats.to_dict() assert stats_dict["has_contentmatter"] is True assert stats_dict["total_pairs"] == 5 assert stats_dict["url_values"] == 1