"""Tests for CLI interface.""" import pytest from click.testing import CliRunner from pathlib import Path import tempfile import os from src.cli import cli, analyze, fix, rules, languages class TestCLI: """Tests for CLI commands.""" def test_cli_group_exists(self): assert cli is not None def test_rules_command(self): runner = CliRunner() result = runner.invoke(rules) assert result.exit_code == 0 assert "security" in result.output.lower() or "Rule ID" in result.output def test_languages_command(self): runner = CliRunner() result = runner.invoke(languages) assert result.exit_code == 0 assert "python" in result.output.lower() assert "javascript" in result.output.lower() assert "typescript" in result.output.lower() def test_analyze_nonexistent_file(self): runner = CliRunner() result = runner.invoke(analyze, ["/nonexistent/path"]) assert result.exit_code != 0 def test_analyze_file_with_issues(self): with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write('result = eval("os.system(\'rm -rf /\')")\n') f.write('password = "secret123"\n') temp_path = f.name try: runner = CliRunner() result = runner.invoke(analyze, [temp_path, "--json"]) assert result.exit_code == 0 assert "password" in result.output or "eval" in result.output finally: os.unlink(temp_path) def test_analyze_file_without_issues(self): with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write("def hello():\n print('Hello, World!')\n") temp_path = f.name try: runner = CliRunner() result = runner.invoke(analyze, [temp_path]) assert result.exit_code == 0 finally: os.unlink(temp_path) def test_analyze_with_fix_flag(self): with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write("result = eval('os.system(\"ls\")')\n") temp_path = f.name try: runner = CliRunner() result = runner.invoke(analyze, [temp_path, "--fix"]) assert result.exit_code == 0 assert "# eval(" in result.output or "Fixed" in result.output finally: backup_path = temp_path + ".bak" if os.path.exists(backup_path): os.unlink(backup_path) def test_analyze_directory(self): with tempfile.TemporaryDirectory() as tmpdir: subdir = Path(tmpdir) / "subdir" subdir.mkdir() test_file = subdir / "test.py" test_file.write_text("result = eval('test')\n") runner = CliRunner() result = runner.invoke(analyze, [tmpdir]) assert result.exit_code == 0 def test_analyze_unsupported_file_type(self): with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f: f.write("This is a text file\n") temp_path = f.name try: runner = CliRunner() result = runner.invoke(analyze, [temp_path]) assert result.exit_code == 0 finally: os.unlink(temp_path) class TestOutputFormatting: """Tests for output formatting.""" def test_json_output(self): with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f: f.write('password = "secret123"\n') temp_path = f.name try: runner = CliRunner() result = runner.invoke(analyze, [temp_path, "--json"]) assert result.exit_code == 0 import json json_start = result.output.find('{') json_end = result.output.rfind('}') + 1 json_output = result.output[json_start:json_end] data = json.loads(json_output) assert "files_analyzed" in data assert "results" in data finally: os.unlink(temp_path)