""" Test suite for md-render --edit functionality to prevent regression. This test suite specifically targets the critical JavaScript syntax errors that were causing edit mode to fail completely, ensuring they never happen again. """ import tempfile import pytest from pathlib import Path import re import subprocess class TestEditModeRegression: """Tests to prevent regression of the md-render --edit functionality.""" def test_edit_mode_generates_valid_javascript(self): """Test that edit mode generates syntactically valid JavaScript.""" from markitect.clean_document_manager import CleanDocumentManager # Create a CleanDocumentManager doc_manager = CleanDocumentManager() # Test markdown content test_content = "# Test Header\n\nThis is a test paragraph.\n\n## Section 2\n\nAnother paragraph." # Generate HTML with edit mode html_content = doc_manager._generate_html_template( title="Test Document", markdown_content=test_content, edit_mode=True, editor_theme='github', keyboard_shortcuts=True ) # Extract JavaScript from HTML js_match = re.search(r'', html_content, re.DOTALL) assert js_match, "No JavaScript found in edit mode HTML" js_content = js_match.group(1) # Write to temp file and validate syntax with Node.js with tempfile.NamedTemporaryFile(mode='w', suffix='.js', delete=False) as f: f.write(js_content) temp_js_path = f.name try: # Use Node.js to check JavaScript syntax result = subprocess.run( ['node', '-c', temp_js_path], capture_output=True, text=True ) assert result.returncode == 0, f"JavaScript syntax error: {result.stderr}" finally: Path(temp_js_path).unlink() def test_edit_mode_contains_required_functions(self): """Test that edit mode HTML contains all required JavaScript functions.""" from markitect.clean_document_manager import CleanDocumentManager # Create a CleanDocumentManager doc_manager = CleanDocumentManager() html_content = doc_manager._generate_html_template( title="Test", markdown_content="# Test", edit_mode=True ) # Check for critical functions that must be present required_functions = [ 'MarkitectCleanEditor', 'SectionManager', 'Section', 'DOMRenderer', 'initializeCleanEditor' ] for func_name in required_functions: assert func_name in html_content, f"Required function '{func_name}' not found in edit mode HTML" def test_edit_mode_no_broken_string_literals(self): """Test that there are no broken string literals in the generated JavaScript.""" from markitect.clean_document_manager import CleanDocumentManager # Create a CleanDocumentManager doc_manager = CleanDocumentManager() html_content = doc_manager._generate_html_template( title="Test", markdown_content="# Test", edit_mode=True ) # Extract JavaScript js_match = re.search(r'', html_content, re.DOTALL) js_content = js_match.group(1) # Check for broken string patterns that caused the original bug broken_patterns = [ r"'\s*\n\s*'", # Broken string literal across lines r'"\s*\n\s*"', # Broken string literal across lines r'reconstructed \+= .*\'\n', # Unescaped newline in string ] for pattern in broken_patterns: matches = re.findall(pattern, js_content) assert not matches, f"Found broken string pattern: {pattern} - matches: {matches}" def test_edit_mode_proper_brace_escaping(self): """Test that braces are properly escaped in f-string templates.""" from markitect.clean_document_manager import CleanDocumentManager # Create a CleanDocumentManager doc_manager = CleanDocumentManager() html_content = doc_manager._generate_html_template( title="Test", markdown_content="# Test", edit_mode=True ) # Extract JavaScript js_match = re.search(r'', html_content, re.DOTALL) js_content = js_match.group(1) # Check for inconsistent brace patterns inconsistent_patterns = [ r'(?(.*?)', html_content, re.DOTALL) js_content = js_match.group(1) # Check for problematic template literal patterns # Should NOT find double-escaped template literals like ${{ problematic_patterns = [ r'\$\{\{.*?\}\}', # Double-escaped template literals ] for pattern in problematic_patterns: matches = re.findall(pattern, js_content) assert not matches, f"Found problematic template literal: {pattern}" def test_edit_mode_contains_content_div(self): """Test that edit mode HTML contains the markdown-content div.""" from markitect.clean_document_manager import CleanDocumentManager # Create a CleanDocumentManager doc_manager = CleanDocumentManager() html_content = doc_manager._generate_html_template( title="Test", markdown_content="# Test Content", edit_mode=True ) # Should contain the content container assert 'id="markdown-content"' in html_content assert 'MARKITECT_EDIT_MODE = true' in html_content assert 'markitect-edit-mode' in html_content def test_edit_mode_error_handling_elements(self): """Test that edit mode includes proper error handling UI elements.""" from markitect.clean_document_manager import CleanDocumentManager # Create a CleanDocumentManager doc_manager = CleanDocumentManager() html_content = doc_manager._generate_html_template( title="Test", markdown_content="# Test", edit_mode=True ) # Should contain clean editor elements assert 'MARKITECT_EDIT_MODE' in html_content assert 'class="markitect-edit-mode"' in html_content assert 'initializeCleanEditor' in html_content assert 'console.error' in html_content # Error handling def test_edit_mode_vs_normal_mode_differences(self): """Test that edit mode and normal mode generate different output appropriately.""" from markitect.clean_document_manager import CleanDocumentManager # Create a CleanDocumentManager doc_manager = CleanDocumentManager() test_content = "# Test Header\n\nTest content." # Generate both modes normal_html = doc_manager._generate_html_template( title="Test", markdown_content=test_content, edit_mode=False ) edit_html = doc_manager._generate_html_template( title="Test", markdown_content=test_content, edit_mode=True ) # Edit mode should have additional elements assert len(edit_html) > len(normal_html) assert 'MarkitectEditor' in edit_html assert 'MarkitectEditor' not in normal_html assert 'markitect-edit-mode' in edit_html assert 'markitect-edit-mode' not in normal_html def test_edit_mode_javascript_execution_flow(self): """Test the logical flow of JavaScript execution in edit mode.""" from markitect.clean_document_manager import CleanDocumentManager # Create a CleanDocumentManager doc_manager = CleanDocumentManager() html_content = doc_manager._generate_html_template( title="Test", markdown_content="# Test", edit_mode=True ) # Extract JavaScript js_match = re.search(r'', html_content, re.DOTALL) js_content = js_match.group(1) # Check for proper execution flow elements flow_elements = [ 'DOMContentLoaded', # Event listener setup 'MARKITECT_EDIT_MODE', # Mode check 'initializeCleanEditor', # Editor initialization 'marked.parse', # Content rendering 'MarkitectCleanEditor' # Clean editor class ] for element in flow_elements: assert element in js_content, f"Missing execution flow element: {element}" def test_newline_escaping_in_javascript_strings(self): """Test that newlines in JavaScript strings are properly escaped.""" from markitect.clean_document_manager import CleanDocumentManager # Create a CleanDocumentManager doc_manager = CleanDocumentManager() html_content = doc_manager._generate_html_template( title="Test", markdown_content="# Test\n\nMultiple\nLines", edit_mode=True ) # Extract JavaScript js_match = re.search(r'', html_content, re.DOTALL) js_content = js_match.group(1) # Look for the specific section that was broken # Should find properly escaped newlines like '\\n\\n' in the JavaScript assert '\\n\\n' in js_content, "Newlines not properly escaped in JavaScript strings" # Should NOT find unescaped newlines in string contexts # This regex looks for string concatenation with actual newlines broken_newline_pattern = r"'\s*\+\s*text\s*\+\s*'\s*\n" matches = re.findall(broken_newline_pattern, js_content) assert not matches, f"Found unescaped newlines in string concatenation: {matches}" class TestEditModeIntegration: """Integration tests for the complete edit mode functionality.""" def test_save_functionality_javascript_presence(self): """Test that the save functionality JavaScript is properly included.""" from markitect.clean_document_manager import CleanDocumentManager # Create a CleanDocumentManager doc_manager = CleanDocumentManager() html_content = doc_manager._generate_html_template( title="Test", markdown_content="# Test Content", edit_mode=True ) # Check for save-related functionality save_elements = [ '💾 Save Document', # Button text from clean implementation 'generateSaveFilename', # Save filename generation 'getDocumentMarkdown', # Content extraction 'Blob', # File creation 'download' # Download attribute ] for element in save_elements: assert element in html_content, f"Save functionality element missing: {element}" if __name__ == "__main__": pytest.main([__file__, "-v"])