fix: resolve CI test failure in output.py
- Fixed undefined 'tool' variable in display_history function - Changed '[tool]' markup tag usage to proper Rich syntax - All tests now pass (38/38 unit tests) - Type checking passes with mypy --strict
This commit is contained in:
251
tests/test_rules.py
Normal file
251
tests/test_rules.py
Normal file
@@ -0,0 +1,251 @@
|
||||
"""Tests for the rules module."""
|
||||
|
||||
import pytest
|
||||
from cli_diff_auditor.rules import (
|
||||
BuiltInRules,
|
||||
Finding,
|
||||
Rule,
|
||||
RulesLoader,
|
||||
Severity,
|
||||
)
|
||||
|
||||
|
||||
class TestRule:
|
||||
"""Test cases for Rule class."""
|
||||
|
||||
def test_rule_creation(self):
|
||||
"""Test creating a Rule instance."""
|
||||
rule = Rule(
|
||||
id="test-rule",
|
||||
name="Test Rule",
|
||||
description="A test rule",
|
||||
pattern=r"test.*",
|
||||
severity=Severity.WARNING,
|
||||
auto_fix=True,
|
||||
category="testing"
|
||||
)
|
||||
|
||||
assert rule.id == "test-rule"
|
||||
assert rule.name == "Test Rule"
|
||||
assert rule.severity == Severity.WARNING
|
||||
assert rule.auto_fix is True
|
||||
assert rule.enabled is True
|
||||
|
||||
def test_compile_pattern(self):
|
||||
"""Test compiling a rule pattern."""
|
||||
rule = Rule(
|
||||
id="test",
|
||||
name="Test",
|
||||
description="Test",
|
||||
pattern=r"\bprint\s*\(",
|
||||
severity=Severity.WARNING
|
||||
)
|
||||
|
||||
compiled = rule.compile_pattern()
|
||||
|
||||
assert compiled.search("print('hello')") is not None
|
||||
assert compiled.search("hello world") is None
|
||||
|
||||
def test_get_fix_pattern(self):
|
||||
"""Test getting the fix pattern."""
|
||||
rule = Rule(
|
||||
id="test",
|
||||
name="Test",
|
||||
description="Test",
|
||||
pattern=r"test",
|
||||
severity=Severity.INFO,
|
||||
auto_fix=True,
|
||||
fix_pattern=r"old",
|
||||
replacement="new"
|
||||
)
|
||||
|
||||
fix_pattern = rule.get_fix_pattern()
|
||||
|
||||
assert fix_pattern is not None
|
||||
assert fix_pattern.search("old text") is not None
|
||||
|
||||
|
||||
class TestBuiltInRules:
|
||||
"""Test cases for BuiltInRules class."""
|
||||
|
||||
def test_get_all_rules_returns_list(self):
|
||||
"""Test that get_all_rules returns a list."""
|
||||
rules = BuiltInRules.get_all_rules()
|
||||
|
||||
assert isinstance(rules, list)
|
||||
assert len(rules) > 0
|
||||
|
||||
def test_rules_have_required_fields(self):
|
||||
"""Test that all rules have required fields."""
|
||||
rules = BuiltInRules.get_all_rules()
|
||||
|
||||
for rule in rules:
|
||||
assert rule.id
|
||||
assert rule.name
|
||||
assert rule.description
|
||||
assert rule.pattern
|
||||
assert rule.severity
|
||||
|
||||
def test_debug_rules_exist(self):
|
||||
"""Test that debug-related rules exist."""
|
||||
rules = BuiltInRules.get_all_rules()
|
||||
rule_ids = [r.id for r in rules]
|
||||
|
||||
assert "debug-print" in rule_ids
|
||||
assert "console-log" in rule_ids
|
||||
|
||||
def test_security_rules_exist(self):
|
||||
"""Test that security-related rules exist."""
|
||||
rules = BuiltInRules.get_all_rules()
|
||||
rule_ids = [r.id for r in rules]
|
||||
|
||||
assert "sql-injection" in rule_ids
|
||||
assert "hardcoded-password" in rule_ids
|
||||
assert "eval-usage" in rule_ids
|
||||
|
||||
def test_error_handling_rules_exist(self):
|
||||
"""Test that error handling rules exist."""
|
||||
rules = BuiltInRules.get_all_rules()
|
||||
rule_ids = [r.id for r in rules]
|
||||
|
||||
assert "bare-except" in rule_ids
|
||||
assert "pass-except" in rule_ids
|
||||
|
||||
|
||||
class TestRulesLoader:
|
||||
"""Test cases for RulesLoader class."""
|
||||
|
||||
def setup_method(self):
|
||||
"""Set up test fixtures."""
|
||||
self.loader = RulesLoader()
|
||||
|
||||
def test_load_builtin_rules(self):
|
||||
"""Test loading built-in rules."""
|
||||
self.loader.load_builtin_rules()
|
||||
|
||||
rules = self.loader.get_all_rules()
|
||||
|
||||
assert len(rules) > 0
|
||||
|
||||
def test_get_rule(self):
|
||||
"""Test getting a specific rule."""
|
||||
self.loader.load_builtin_rules()
|
||||
|
||||
rule = self.loader.get_rule("debug-print")
|
||||
|
||||
assert rule is not None
|
||||
assert rule.id == "debug-print"
|
||||
|
||||
def test_get_nonexistent_rule(self):
|
||||
"""Test getting a rule that doesn't exist."""
|
||||
self.loader.load_builtin_rules()
|
||||
|
||||
rule = self.loader.get_rule("nonexistent-rule")
|
||||
|
||||
assert rule is None
|
||||
|
||||
def test_disable_rule(self):
|
||||
"""Test disabling a rule."""
|
||||
self.loader.load_builtin_rules()
|
||||
|
||||
result = self.loader.disable_rule("debug-print")
|
||||
|
||||
assert result is True
|
||||
|
||||
rule = self.loader.get_rule("debug-print")
|
||||
assert rule.enabled is False
|
||||
|
||||
def test_enable_rule(self):
|
||||
"""Test enabling a rule."""
|
||||
self.loader.load_builtin_rules()
|
||||
self.loader.disable_rule("debug-print")
|
||||
|
||||
result = self.loader.enable_rule("debug-print")
|
||||
|
||||
assert result is True
|
||||
|
||||
rule = self.loader.get_rule("debug-print")
|
||||
assert rule.enabled is True
|
||||
|
||||
def test_get_enabled_rules(self):
|
||||
"""Test getting only enabled rules."""
|
||||
self.loader.load_builtin_rules()
|
||||
self.loader.disable_rule("debug-print")
|
||||
self.loader.disable_rule("console-log")
|
||||
|
||||
enabled = self.loader.get_enabled_rules()
|
||||
|
||||
rule_ids = [r.id for r in enabled]
|
||||
|
||||
assert "debug-print" not in rule_ids
|
||||
assert "console-log" not in rule_ids
|
||||
|
||||
def test_load_from_yaml(self):
|
||||
"""Test loading rules from YAML."""
|
||||
self.loader.load_builtin_rules()
|
||||
yaml_content = """
|
||||
rules:
|
||||
- id: custom-rule
|
||||
name: Custom Rule
|
||||
description: A custom rule
|
||||
pattern: "custom.*"
|
||||
severity: warning
|
||||
category: custom
|
||||
"""
|
||||
rules = self.loader.load_from_yaml(yaml_content)
|
||||
|
||||
assert len(rules) == 1
|
||||
assert rules[0].id == "custom-rule"
|
||||
|
||||
all_rules = self.loader.get_all_rules()
|
||||
assert len(all_rules) > 1
|
||||
|
||||
def test_load_from_yaml_minimal(self):
|
||||
"""Test loading rules with minimal fields."""
|
||||
yaml_content = """
|
||||
rules:
|
||||
- id: minimal-rule
|
||||
name: Minimal
|
||||
description: Minimal description
|
||||
pattern: "test"
|
||||
severity: error
|
||||
"""
|
||||
rules = self.loader.load_from_yaml(yaml_content)
|
||||
|
||||
assert len(rules) == 1
|
||||
assert rules[0].severity == Severity.ERROR
|
||||
assert rules[0].auto_fix is False
|
||||
assert rules[0].category == "custom"
|
||||
|
||||
def test_parse_rule_data_missing_required_field(self):
|
||||
"""Test parsing rule data with missing required field."""
|
||||
data = {
|
||||
"id": "test",
|
||||
"name": "Test",
|
||||
"description": "Test"
|
||||
}
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
self.loader._parse_rule_data(data)
|
||||
|
||||
|
||||
class TestFinding:
|
||||
"""Test cases for Finding class."""
|
||||
|
||||
def test_finding_creation(self):
|
||||
"""Test creating a Finding instance."""
|
||||
finding = Finding(
|
||||
rule_id="test-rule",
|
||||
rule_name="Test Rule",
|
||||
severity=Severity.WARNING,
|
||||
file_path="test.py",
|
||||
line_number=10,
|
||||
line_content="print('debug')",
|
||||
message="Debug print statement detected",
|
||||
fix_available=True
|
||||
)
|
||||
|
||||
assert finding.rule_id == "test-rule"
|
||||
assert finding.severity == Severity.WARNING
|
||||
assert finding.line_number == 10
|
||||
assert finding.fix_available is True
|
||||
Reference in New Issue
Block a user