"""Tests for the CLI interface.""" import json import pytest from click.testing import CliRunner from regex_humanizer.cli import main, explain, test, flavors, validate, convert class TestCLIMain: """Test the main CLI entry point.""" def test_main_help(self): """Test that main help works.""" runner = CliRunner() result = runner.invoke(main, ["--help"]) assert result.exit_code == 0 assert "Regex Humanizer" in result.output assert "explain" in result.output assert "test" in result.output assert "interactive" in result.output class TestCLIExplain: """Test the explain command.""" def test_explain_simple_literal(self): """Test explaining a simple literal.""" runner = CliRunner() result = runner.invoke(explain, ["hello"]) assert result.exit_code == 0 assert "Pattern" in result.output or "hello" in result.output def test_explain_with_flavor_option(self): """Test explaining with a flavor option.""" runner = CliRunner() result = runner.invoke(explain, ["--flavor", "javascript", "test"]) assert result.exit_code == 0 assert "Flavor" in result.output or "javascript" in result.output def test_explain_with_json_output(self): """Test explaining with JSON output.""" runner = CliRunner() result = runner.invoke(explain, ["--output", "json", "\\d+"]) assert result.exit_code == 0 assert "{", "}" in result.output def test_explain_with_verbose(self): """Test explaining with verbose flag.""" runner = CliRunner() result = runner.invoke(explain, ["--verbose", "\\d+"]) assert result.exit_code == 0 assert "Features" in result.output or "digit" in result.output.lower() def test_explain_complex_pattern(self): """Test explaining a complex pattern.""" runner = CliRunner() pattern = r"^(?:http|https)://[\w.-]+\.(?:com|org|net)$" result = runner.invoke(explain, [pattern]) assert result.exit_code == 0 assert "Pattern" in result.output def test_explain_phone_pattern(self): """Test explaining a phone pattern.""" runner = CliRunner() result = runner.invoke(explain, [r"\d{3}-\d{4}"]) assert result.exit_code == 0 def test_explain_character_class(self): """Test explaining a character class.""" runner = CliRunner() result = runner.invoke(explain, ["[a-zA-Z]+"]) assert result.exit_code == 0 class TestCLITest: """Test the test command.""" def test_test_simple_literal(self): """Test generating test cases for a simple literal.""" runner = CliRunner() result = runner.invoke(test, ["hello"]) assert result.exit_code == 0 assert "Matching" in result.output or "hello" in result.output assert "Non-matching" in result.output def test_test_with_count_option(self): """Test generating a specific number of test cases.""" runner = CliRunner() result = runner.invoke(test, ["--count", "3", "a"]) assert result.exit_code == 0 def test_test_with_json_output(self): """Test generating test cases with JSON output.""" runner = CliRunner() result = runner.invoke(test, ["--output", "json", "test"]) assert result.exit_code == 0 data = json.loads(result.output) assert "matching" in data assert "non_matching" in data def test_test_phone_pattern(self): """Test generating test cases for a phone pattern.""" runner = CliRunner() result = runner.invoke(test, [r"\d{3}-\d{4}"]) assert result.exit_code == 0 assert "Matching" in result.output def test_test_email_pattern(self): """Test generating test cases for an email pattern.""" runner = CliRunner() result = runner.invoke(test, [r"[a-z]+@[a-z]+\.[a-z]+"]) assert result.exit_code == 0 def test_test_quantifier_pattern(self): """Test generating test cases for a quantifier pattern.""" runner = CliRunner() result = runner.invoke(test, ["a{2,4}"]) assert result.exit_code == 0 class TestCLIFlavors: """Test the flavors command.""" def test_flavors_list(self): """Test listing available flavors.""" runner = CliRunner() result = runner.invoke(flavors) assert result.exit_code == 0 assert "pcre" in result.output.lower() assert "javascript" in result.output.lower() assert "python" in result.output.lower() class TestCLIValidate: """Test the validate command.""" def test_validate_valid_pattern(self): """Test validating a valid pattern.""" runner = CliRunner() result = runner.invoke(validate, ["hello"]) assert result.exit_code == 0 assert "PASSED" in result.output or "Validation" in result.output def test_validate_with_flavor(self): """Test validating with a specific flavor.""" runner = CliRunner() result = runner.invoke(validate, ["--flavor", "javascript", "test"]) assert result.exit_code == 0 def test_validate_complex_pattern(self): """Test validating a complex pattern.""" runner = CliRunner() pattern = r"^(?:http|https)://[\w.-]+\.(?:com|org|net)$" result = runner.invoke(validate, [pattern]) assert result.exit_code == 0 class TestCLIConvert: """Test the convert command.""" def test_convert_pcre_to_js(self): """Test converting a pattern from PCRE to JavaScript.""" runner = CliRunner() result = runner.invoke(convert, ["(?Phello)", "--from-flavor", "pcre", "--to-flavor", "javascript"]) assert result.exit_code == 0 assert "Converted" in result.output def test_convert_with_defaults(self): """Test converting with default flavors.""" runner = CliRunner() result = runner.invoke(convert, ["test"]) assert result.exit_code == 0 assert "Original" in result.output assert "Converted" in result.output class TestCLIInteractive: """Test the interactive command.""" def test_interactive_command_exists(self): """Test that interactive command is available.""" runner = CliRunner() result = runner.invoke(main, ["interactive", "--help"]) assert result.exit_code == 0 assert "interactive" in result.output.lower() def test_interactive_with_flavor(self): """Test interactive mode with a specific flavor.""" runner = CliRunner() result = runner.invoke(main, ["interactive", "--flavor", "python"]) assert result.exit_code == 0 class TestCLIIntegration: """Integration tests for CLI.""" def test_flavor_option_global(self): """Test that global flavor option works.""" runner = CliRunner() result = runner.invoke(main, ["--flavor", "python", "explain", "test"]) assert result.exit_code == 0 def test_error_handling_invalid_pattern(self): """Test error handling for invalid patterns.""" runner = CliRunner() result = runner.invoke(explain, ["["]) assert result.exit_code == 0 def test_output_json_structure(self): """Test JSON output has correct structure.""" runner = CliRunner() result = runner.invoke(explain, ["--output", "json", "\\d+"]) assert result.exit_code == 0 data = json.loads(result.output) assert "pattern" in data assert "flavor" in data assert "explanation" in data def test_output_test_json_structure(self): """Test JSON test output has correct structure.""" runner = CliRunner() result = runner.invoke(test, ["--output", "json", "\\d"]) assert result.exit_code == 0 data = json.loads(result.output) assert "pattern" in data assert "matching" in data assert "non_matching" in data