""" CLI Integration Tests - Prevent CLI Entry Point Regressions This test module validates that the CLI entry point is properly accessible and core commands work as expected. It prevents regressions like broken imports or missing entry points that would break user accessibility. Tests focus on: - CLI entry point accessibility (markitect --help) - Core command availability and help text - Template rendering CLI functionality - Error handling in CLI commands """ import subprocess import tempfile import json import os import pytest from pathlib import Path class TestCLIEntryPoint: """Test CLI entry point accessibility.""" def test_markitect_help_accessible(self): """Test that markitect --help works and shows expected content. This prevents regressions where import errors break CLI accessibility. """ # Run markitect --help result = subprocess.run( ['markitect', '--help'], capture_output=True, text=True ) # Should exit successfully assert result.returncode == 0, f"CLI help failed with error: {result.stderr}" # Should contain core CLI information output = result.stdout assert "MarkiTect - Advanced Markdown engine" in output assert "Commands:" in output assert "--help" in output # Should not have import errors assert "ModuleNotFoundError" not in result.stderr assert "ImportError" not in result.stderr def test_core_commands_available(self): """Test that core commands are listed in help output.""" result = subprocess.run( ['markitect', '--help'], capture_output=True, text=True ) output = result.stdout # Core functionality commands assert "ingest" in output assert "list" in output assert "status" in output or "stats" in output # Template engine command (Issue #65) assert "template-render" in output # Schema commands assert "schema-generate" in output assert "validate" in output def test_template_render_command_help(self): """Test that template-render command help is accessible.""" result = subprocess.run( ['markitect', 'template-render', '--help'], capture_output=True, text=True ) assert result.returncode == 0 output = result.stdout assert "Render a template with data" in output assert "TEMPLATE_FILE" in output assert "DATA_FILE" in output assert "--output" in output assert "--strict" in output assert "--lenient" in output class TestTemplateRenderCLI: """Test template-render CLI functionality end-to-end.""" def test_template_render_basic_functionality(self): """Test basic template rendering via CLI.""" with tempfile.TemporaryDirectory() as temp_dir: temp_path = Path(temp_dir) # Create test template template_file = temp_path / "test.md" template_file.write_text("# {{title}}\n\nHello {{name}}!") # Create test data data_file = temp_path / "data.json" data = {"title": "Test Document", "name": "World"} data_file.write_text(json.dumps(data)) # Run template rendering result = subprocess.run( ['markitect', 'template-render', str(template_file), str(data_file)], capture_output=True, text=True ) assert result.returncode == 0, f"Template rendering failed: {result.stderr}" output = result.stdout assert "# Test Document" in output assert "Hello World!" in output def test_template_render_with_output_file(self): """Test template rendering with output file option.""" with tempfile.TemporaryDirectory() as temp_dir: temp_path = Path(temp_dir) # Create test files template_file = temp_path / "template.md" template_file.write_text("Result: {{value}}") data_file = temp_path / "data.json" data_file.write_text(json.dumps({"value": "SUCCESS"})) output_file = temp_path / "output.md" # Run with output option result = subprocess.run( ['markitect', 'template-render', str(template_file), str(data_file), '--output', str(output_file)], capture_output=True, text=True ) assert result.returncode == 0 assert "Template rendered successfully" in result.stdout # Check output file was created assert output_file.exists() content = output_file.read_text() assert "Result: SUCCESS" in content def test_template_render_validation_mode(self): """Test template rendering with validation options.""" with tempfile.TemporaryDirectory() as temp_dir: temp_path = Path(temp_dir) # Create valid template template_file = temp_path / "valid.md" template_file.write_text("Valid: {{name}}") data_file = temp_path / "data.json" data_file.write_text(json.dumps({"name": "test"})) # Run with validation result = subprocess.run( ['markitect', 'template-render', str(template_file), str(data_file), '--validate', '--check-data'], capture_output=True, text=True ) assert result.returncode == 0 assert "Valid: test" in result.stdout def test_template_render_error_handling(self): """Test CLI error handling for invalid inputs.""" with tempfile.TemporaryDirectory() as temp_dir: temp_path = Path(temp_dir) # Test with non-existent template file result = subprocess.run( ['markitect', 'template-render', 'nonexistent.md', 'data.json'], capture_output=True, text=True ) assert result.returncode != 0 assert "does not exist" in result.stderr.lower() or "not found" in result.stderr.lower() def test_template_render_strict_vs_lenient_mode(self): """Test strict vs lenient mode behavior.""" with tempfile.TemporaryDirectory() as temp_dir: temp_path = Path(temp_dir) # Template with missing variable template_file = temp_path / "template.md" template_file.write_text("Hello {{name}}, missing: {{missing}}") # Data missing the 'missing' variable data_file = temp_path / "data.json" data_file.write_text(json.dumps({"name": "Alice"})) # Test strict mode (should fail) result_strict = subprocess.run( ['markitect', 'template-render', str(template_file), str(data_file), '--strict'], capture_output=True, text=True ) assert result_strict.returncode != 0 # Test lenient mode (should succeed) result_lenient = subprocess.run( ['markitect', 'template-render', str(template_file), str(data_file), '--lenient'], capture_output=True, text=True ) assert result_lenient.returncode == 0 output = result_lenient.stdout assert "Hello Alice" in output assert "{{missing}}" in output # Placeholder preserved class TestCLIRegressionPrevention: """Tests specifically designed to catch common CLI regression patterns.""" def test_import_paths_valid(self): """Test that all CLI module imports work correctly. This catches issues like the domain module import that broke CLI access. """ # Try to import the CLI module directly try: import markitect.cli # Should not raise ImportError or ModuleNotFoundError except (ImportError, ModuleNotFoundError) as e: pytest.fail(f"CLI module import failed: {e}") def test_cli_entry_point_configuration(self): """Test that the CLI entry point is properly configured.""" # Check that the entry point script exists and is executable import shutil markitect_path = shutil.which('markitect') assert markitect_path is not None, "markitect command not found in PATH" assert os.access(markitect_path, os.X_OK), "markitect command is not executable" def test_no_runtime_import_errors(self): """Test that basic CLI commands don't have runtime import errors.""" # Test a few key commands to ensure no import errors at runtime commands_to_test = [ ['markitect', '--version'], # Should show version or error gracefully ['markitect', 'list', '--help'], # Core command help ['markitect', 'template-render', '--help'], # New template command help ] for cmd in commands_to_test: result = subprocess.run(cmd, capture_output=True, text=True) # Even if command fails, it shouldn't be due to import errors assert "ModuleNotFoundError" not in result.stderr assert "ImportError" not in result.stderr assert "No module named" not in result.stderr def test_template_engine_availability(self): """Test that template engine is properly available to CLI.""" # Create minimal test to ensure template engine can be imported by CLI with tempfile.TemporaryDirectory() as temp_dir: temp_path = Path(temp_dir) template_file = temp_path / "minimal.md" template_file.write_text("test") data_file = temp_path / "minimal.json" data_file.write_text("{}") # This should not fail with import errors result = subprocess.run( ['markitect', 'template-render', str(template_file), str(data_file)], capture_output=True, text=True ) # Should succeed or fail gracefully, but not with import errors assert "ImportError" not in result.stderr assert "ModuleNotFoundError" not in result.stderr assert "Template engine not available" not in result.stderr if __name__ == '__main__': pytest.main([__file__, '-v'])