Files
markitect-main/capabilities/markitect-content/tests/test_content_commands.py

296 lines
11 KiB
Python

"""
TDD8 Cycle 1: Content Commands Tests (RED Phase)
Issue #38 - MarkdownMatters CLI Implementation
This test file implements the RED phase tests for content command family:
- markitect content-get [path] - Extract content without frontmatter/tailmatter
- markitect content-stats [path] - Content 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_content.parser import ContentParser
from markitect_content.stats import ContentStats
from markitect_content.commands import content_get, content_stats
class TestContentExtraction:
"""Test content extraction without matter zones."""
@pytest.fixture
def test_files_dir(self):
"""Path to test fixture files."""
return Path(__file__).parent / "fixtures" / "content_test_files"
@pytest.fixture
def content_parser(self):
"""Content parser instance."""
return ContentParser()
def test_content_get_extracts_content_without_frontmatter(self, content_parser, test_files_dir):
"""Test that content extraction removes frontmatter."""
file_path = test_files_dir / "frontmatter_only.md"
with open(file_path, 'r') as f:
text = f.read()
content = content_parser.extract_content(text)
# Content should not contain frontmatter delimiters or YAML
assert "---" not in content
assert "title:" not in content
assert "author:" not in content
assert "date:" not in content
# Content should contain the actual document content
assert "# Frontmatter Only Document" in content
assert "This document only has frontmatter" in content
def test_content_get_extracts_content_without_tailmatter(self, content_parser, test_files_dir):
"""Test that content extraction removes tailmatter."""
file_path = test_files_dir / "tailmatter_only.md"
with open(file_path, 'r') as f:
text = f.read()
content = content_parser.extract_content(text)
# Content should not contain tailmatter blocks
assert "```yaml tailmatter" not in content
assert "qa_checklist:" not in content
assert "editorial:" not in content
# Content should contain the actual document content
assert "# Tailmatter Only Document" in content
assert "This document only has tailmatter" in content
def test_content_get_extracts_content_without_both_matters(self, content_parser, test_files_dir):
"""Test that content extraction removes both frontmatter and tailmatter."""
file_path = test_files_dir / "complete_document.md"
with open(file_path, 'r') as f:
text = f.read()
content = content_parser.extract_content(text)
# Content should not contain any matter zones
assert "---" not in content or content.count("---") <= 1 # Allow section dividers
assert "title:" not in content
assert "```yaml tailmatter" not in content
assert "qa_checklist:" not in content
# Content should contain the main document content
assert "# Complete Test Document" in content
assert "This is the main content" in content
assert "## Section 1" in content
def test_content_get_preserves_contentmatter_inline_metadata(self, content_parser, test_files_dir):
"""Test that contentmatter (MMD key-value pairs) are preserved in content."""
file_path = test_files_dir / "contentmatter_inline.md"
with open(file_path, 'r') as f:
text = f.read()
content = content_parser.extract_content(text)
# Contentmatter should be preserved as it's part of the content
assert "Author: Jane Smith" in content
assert "Project: Content Testing" in content
assert "Keywords: markdown, contentmatter, testing" in content
assert "Reference: https://example.com/docs" in content
def test_content_get_handles_file_not_found(self, content_parser):
"""Test proper error handling for non-existent files."""
with pytest.raises(FileNotFoundError):
with open("non_existent_file.md", 'r') as f:
text = f.read()
content_parser.extract_content(text)
class TestContentStatistics:
"""Test content statistics calculation."""
@pytest.fixture
def test_files_dir(self):
"""Path to test fixture files."""
return Path(__file__).parent / "fixtures" / "content_test_files"
@pytest.fixture
def content_parser(self):
"""Content parser instance."""
return ContentParser()
def test_content_stats_counts_words_correctly(self, content_parser, test_files_dir):
"""Test accurate word counting in content."""
file_path = test_files_dir / "plain_markdown.md"
with open(file_path, 'r') as f:
text = f.read()
content = content_parser.extract_content(text)
stats = content_parser.calculate_stats(content)
# Should count words in content (exact count depends on test file)
assert stats.word_count > 0
assert isinstance(stats.word_count, int)
def test_content_stats_counts_paragraphs_correctly(self, content_parser, test_files_dir):
"""Test accurate paragraph counting."""
file_path = test_files_dir / "plain_markdown.md"
with open(file_path, 'r') as f:
text = f.read()
content = content_parser.extract_content(text)
stats = content_parser.calculate_stats(content)
# Should count paragraphs (non-empty text blocks)
assert stats.paragraph_count > 0
assert isinstance(stats.paragraph_count, int)
def test_content_stats_counts_lines_correctly(self, content_parser, test_files_dir):
"""Test accurate line counting."""
file_path = test_files_dir / "plain_markdown.md"
with open(file_path, 'r') as f:
text = f.read()
content = content_parser.extract_content(text)
stats = content_parser.calculate_stats(content)
# Should count lines in content
assert stats.line_count > 0
assert isinstance(stats.line_count, int)
def test_content_stats_excludes_frontmatter_from_counts(self, content_parser, test_files_dir):
"""Test that frontmatter is excluded from statistics."""
file_path = test_files_dir / "frontmatter_only.md"
with open(file_path, 'r') as f:
text = f.read()
content = content_parser.extract_content(text)
stats = content_parser.calculate_stats(content)
# Word count should not include frontmatter words
# This requires manual calculation based on test file content
assert "title:" not in content
assert stats.word_count > 0 # Should still have content words
def test_content_stats_excludes_tailmatter_from_counts(self, content_parser, test_files_dir):
"""Test that tailmatter is excluded from statistics."""
file_path = test_files_dir / "tailmatter_only.md"
with open(file_path, 'r') as f:
text = f.read()
content = content_parser.extract_content(text)
stats = content_parser.calculate_stats(content)
# Word count should not include tailmatter words
assert "qa_checklist:" not in content
assert stats.word_count > 0 # Should still have content words
def test_content_stats_includes_contentmatter_in_counts(self, content_parser, test_files_dir):
"""Test that contentmatter (MMD) is included in statistics."""
file_path = test_files_dir / "contentmatter_inline.md"
with open(file_path, 'r') as f:
text = f.read()
content = content_parser.extract_content(text)
stats = content_parser.calculate_stats(content)
# Should include contentmatter key-value pairs in word count
assert "Author: Jane Smith" in content
assert stats.word_count > 10 # Should include contentmatter words
class TestCLIIntegration:
"""Test CLI command integration."""
@pytest.fixture
def runner(self):
"""CLI test runner."""
return CliRunner()
@pytest.fixture
def test_files_dir(self):
"""Path to test fixture files."""
return Path(__file__).parent / "fixtures" / "content_test_files"
def test_content_get_cli_command_works(self, runner, test_files_dir):
"""Test that content-get CLI command executes successfully."""
file_path = test_files_dir / "plain_markdown.md"
result = runner.invoke(content_get, ['--file', str(file_path)])
assert result.exit_code == 0
assert "Plain Markdown Document" in result.output
# Should not contain frontmatter/tailmatter markers
assert "---" not in result.output or result.output.count("---") <= 1
def test_content_stats_cli_command_works(self, runner, test_files_dir):
"""Test that content-stats CLI command executes successfully."""
file_path = test_files_dir / "plain_markdown.md"
result = runner.invoke(content_stats, ['--file', str(file_path)])
assert result.exit_code == 0
assert "word_count" in result.output
assert "line_count" in result.output
assert "paragraph_count" in result.output
def test_content_commands_help_text_available(self, runner):
"""Test that help text is available for content commands."""
# Test content-get help
result = runner.invoke(content_get, ['--help'])
assert result.exit_code == 0
assert "Extract content without frontmatter and tailmatter" in result.output
# Test content-stats help
result = runner.invoke(content_stats, ['--help'])
assert result.exit_code == 0
assert "Calculate content statistics" in result.output
class TestContentStats:
"""Test ContentStats data class."""
def test_content_stats_creation(self):
"""Test ContentStats object creation."""
stats = ContentStats(
word_count=100,
line_count=20,
paragraph_count=5,
character_count=500
)
assert stats.word_count == 100
assert stats.line_count == 20
assert stats.paragraph_count == 5
assert stats.character_count == 500
def test_content_stats_to_dict(self):
"""Test ContentStats conversion to dictionary."""
stats = ContentStats(
word_count=100,
line_count=20,
paragraph_count=5,
character_count=500
)
stats_dict = stats.to_dict()
assert stats_dict == {
"word_count": 100,
"line_count": 20,
"paragraph_count": 5,
"character_count": 500
}