124 lines
4.1 KiB
Python
124 lines
4.1 KiB
Python
"""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)
|