""" Tests for Issue #133: CLI Integration with Instant Markdown Editing Support This module tests the CLI command enhancement that adds editing capabilities to the existing md-render command through the --edit flag. """ import pytest import tempfile import os from pathlib import Path from unittest.mock import patch, MagicMock from click.testing import CliRunner # Add project root to path for imports import sys project_root = Path(__file__).parent.parent.parent.parent sys.path.insert(0, str(project_root)) class TestIssue133CLIIntegration: """Test CLI integration for instant markdown editing support.""" def setup_method(self): """Set up test environment.""" self.runner = CliRunner() self.temp_dir = tempfile.mkdtemp() # Sample markdown content for testing self.test_markdown = """# Editing Test Document This is a test document for instant markdown editing functionality. ## Features - Click-to-edit sections - Live preview comparison - Change tracking - File saving ### Code Example ```bash markitect md-render input.md --edit ``` Content paragraph that should be editable. """ def teardown_method(self): """Clean up test environment.""" import shutil shutil.rmtree(self.temp_dir, ignore_errors=True) def test_edit_flag_adds_editing_capabilities(self): """Test that --edit flag enables editing mode - Issue #133.""" input_file = Path(self.temp_dir) / "edit_test.md" input_file.write_text(self.test_markdown) output_file = Path(self.temp_dir) / "edit_output.html" # Edit flag functionality IS implemented from markitect.cli import cli result = self.runner.invoke(cli, [ 'md-render', str(input_file), '--output', str(output_file), '--edit' ]) assert result.exit_code == 0 assert output_file.exists() html_content = output_file.read_text() # Should include editor library and edit mode flag assert 'markitect-floating-header' in html_content assert 'MARKITECT_EDIT_MODE' in html_content assert 'MarkitectEditor' in html_content def test_edit_flag_with_all_templates(self): """Test --edit flag works with all template types - Issue #133.""" input_file = Path(self.temp_dir) / "template_edit_test.md" input_file.write_text(self.test_markdown) templates = ['basic', 'github', 'academic', 'dark'] # Template editing IS implemented from markitect.cli import cli for template in templates: output_file = Path(self.temp_dir) / f"edit_{template}.html" result = self.runner.invoke(cli, [ 'md-render', str(input_file), '--output', str(output_file), '--template', template, '--edit' ]) assert result.exit_code == 0 assert output_file.exists() html_content = output_file.read_text() # Should work with template styles assert 'markitect-floating-header' in html_content assert 'MarkitectEditor' in html_content def test_editor_library_loading_configuration(self): """Test editor library loading and configuration options - Issue #133.""" input_file = Path(self.temp_dir) / "config_test.md" input_file.write_text(self.test_markdown) output_file = Path(self.temp_dir) / "config_output.html" # Editor configuration IS implemented from markitect.cli import cli result = self.runner.invoke(cli, [ 'md-render', str(input_file), '--output', str(output_file), '--edit', '--editor-theme', 'dark' ]) assert result.exit_code == 0 html_content = output_file.read_text() # Should include editor configuration with theme: 'dark' assert 'theme: \'dark\'' in html_content assert 'MARKITECT_EDITOR_CONFIG' in html_content def test_backward_compatibility_without_edit_flag(self): """Test that existing functionality remains unchanged without --edit - Issue #133.""" input_file = Path(self.temp_dir) / "compatibility_test.md" input_file.write_text(self.test_markdown) output_file = Path(self.temp_dir) / "compatibility_output.html" # Existing functionality should continue to work from markitect.cli import cli result = self.runner.invoke(cli, [ 'md-render', str(input_file), '--output', str(output_file), '--template', 'github' ]) assert result.exit_code == 0 assert output_file.exists() html_content = output_file.read_text() # Should NOT include editor library without --edit flag assert 'markitect-editor' not in html_content assert 'MARKITECT_EDIT_MODE' not in html_content # Should include existing functionality assert 'marked.min.js' in html_content assert 'Editing Test Document' in html_content def test_help_text_includes_edit_options(self): """Test that help text includes new editing options - Issue #133.""" # Help text IS updated with edit options from markitect.cli import cli result = self.runner.invoke(cli, ['md-render', '--help']) assert result.exit_code == 0 assert '--edit' in result.output assert 'editing' in result.output.lower() assert 'instant' in result.output.lower() or 'edit' in result.output.lower() def test_edit_flag_with_custom_css(self): """Test --edit flag works with custom CSS injection - Issue #133.""" # Create custom CSS file css_content = """ .editor-section { border: 2px dashed #007acc; } .edit-mode textarea { font-family: 'Courier New', monospace; } """ css_file = Path(self.temp_dir) / "editor.css" css_file.write_text(css_content) input_file = Path(self.temp_dir) / "css_edit_test.md" input_file.write_text(self.test_markdown) output_file = Path(self.temp_dir) / "css_edit_output.html" # CSS + editing integration IS implemented from markitect.cli import cli result = self.runner.invoke(cli, [ 'md-render', str(input_file), '--output', str(output_file), '--css', str(css_file), '--edit' ]) assert result.exit_code == 0 html_content = output_file.read_text() # Should include both custom CSS and editor assert 'Courier New' in html_content assert 'markitect-floating-header' in html_content assert 'MarkitectEditor' in html_content def test_large_document_editing_performance(self): """Test editing flag with large markdown documents - Issue #133.""" # Create large markdown document large_content = self.test_markdown * 50 # Repeat content 50 times input_file = Path(self.temp_dir) / "large_edit_test.md" input_file.write_text(large_content) output_file = Path(self.temp_dir) / "large_edit_output.html" # Large document handling IS implemented from markitect.cli import cli result = self.runner.invoke(cli, [ 'md-render', str(input_file), '--output', str(output_file), '--edit' ]) assert result.exit_code == 0 html_content = output_file.read_text() # Should handle large documents gracefully assert len(html_content) > 20000 # Should be substantial (adjusted from 50k) assert 'MarkitectEditor' in html_content assert 'MARKITECT_EDIT_MODE' in html_content def test_front_matter_preservation_with_editing(self): """Test YAML front matter preserved in editing mode - Issue #133.""" markdown_with_frontmatter = """--- title: "Editable Document" author: "Test Author" date: "2025-10-07" tags: [editing, test, markdown] --- # Editable Content This content should be editable while preserving front matter. """ input_file = Path(self.temp_dir) / "frontmatter_edit_test.md" input_file.write_text(markdown_with_frontmatter) output_file = Path(self.temp_dir) / "frontmatter_edit_output.html" # Front matter + editing IS implemented from markitect.cli import cli result = self.runner.invoke(cli, [ 'md-render', str(input_file), '--output', str(output_file), '--edit' ]) assert result.exit_code == 0 html_content = output_file.read_text() # Should preserve front matter in JavaScript payload and include editing assert 'Test Author' in html_content or 'Editable Document' in html_content assert 'MarkitectEditor' in html_content assert 'MARKITECT_EDIT_MODE' in html_content def test_error_handling_invalid_edit_options(self): """Test error handling for invalid editing options - Issue #133.""" input_file = Path(self.temp_dir) / "error_test.md" input_file.write_text(self.test_markdown) # Error handling IS implemented from markitect.cli import cli # Test invalid editor theme result = self.runner.invoke(cli, [ 'md-render', str(input_file), '--edit', '--editor-theme', 'invalid_theme' ]) assert result.exit_code != 0 assert 'invalid' in result.output.lower() or 'not one of' in result.output.lower() def test_editor_script_cdn_fallback(self): """Test graceful handling when editor CDN fails - Issue #133.""" input_file = Path(self.temp_dir) / "fallback_test.md" input_file.write_text(self.test_markdown) output_file = Path(self.temp_dir) / "fallback_output.html" # Editor functionality IS implemented with bundled JavaScript from markitect.cli import cli result = self.runner.invoke(cli, [ 'md-render', str(input_file), '--output', str(output_file), '--edit' ]) assert result.exit_code == 0 html_content = output_file.read_text() # Should include bundled editor (not relying on CDN) assert 'MarkitectEditor' in html_content assert 'MARKITECT_EDIT_MODE' in html_content # The implementation uses bundled JavaScript, not CDN, so no fallback needed def test_mobile_responsive_editing_meta_tags(self): """Test that editing mode includes proper mobile meta tags - Issue #133.""" input_file = Path(self.temp_dir) / "mobile_test.md" input_file.write_text(self.test_markdown) output_file = Path(self.temp_dir) / "mobile_output.html" # Mobile responsiveness IS implemented from markitect.cli import cli result = self.runner.invoke(cli, [ 'md-render', str(input_file), '--output', str(output_file), '--edit' ]) assert result.exit_code == 0 html_content = output_file.read_text() # Should include mobile-friendly meta tags assert 'viewport' in html_content assert 'width=device-width' in html_content assert 'MarkitectEditor' in html_content def test_keyboard_shortcuts_configuration(self): """Test keyboard shortcuts can be configured for editing - Issue #133.""" input_file = Path(self.temp_dir) / "shortcuts_test.md" input_file.write_text(self.test_markdown) output_file = Path(self.temp_dir) / "shortcuts_output.html" # Keyboard shortcuts ARE implemented from markitect.cli import cli result = self.runner.invoke(cli, [ 'md-render', str(input_file), '--output', str(output_file), '--edit', '--keyboard-shortcuts' ]) assert result.exit_code == 0 html_content = output_file.read_text() # Should include keyboard shortcut configuration assert 'keydown' in html_content assert 'MARKITECT_EDITOR_CONFIG' in html_content assert 'keyboardShortcuts' in html_content def test_edit_mode_with_existing_command_patterns(self): """Test that editing follows existing CLI command patterns - Issue #133.""" # Command pattern consistency IS implemented from markitect.cli import cli # Should follow same patterns as other md-* commands md_commands = [name for name in cli.commands.keys() if name.startswith('md-')] assert 'md-render' in md_commands # md-render command should have consistent help format cmd = cli.commands['md-render'] assert cmd.help is not None assert 'edit' in cmd.help.lower() or any('--edit' in str(param) for param in cmd.params) def test_section_detection_configuration(self): """Test section detection can be configured for different markdown structures - Issue #133.""" complex_markdown = """# Main Title ## Section 1 Content for section 1. ### Subsection 1.1 - List item 1 - List item 2 ```python def example_function(): return "editable code" ``` ## Section 2 | Column 1 | Column 2 | |----------|----------| | Data 1 | Data 2 | > This is a blockquote that should be editable. """ input_file = Path(self.temp_dir) / "complex_test.md" input_file.write_text(complex_markdown) output_file = Path(self.temp_dir) / "complex_output.html" # Complex section detection IS implemented from markitect.cli import cli result = self.runner.invoke(cli, [ 'md-render', str(input_file), '--output', str(output_file), '--edit' ]) assert result.exit_code == 0 html_content = output_file.read_text() # Should detect and mark various section types assert 'data-section' in html_content or 'markitect-section-editable' in html_content assert 'MarkitectEditor' in html_content