268 lines
6.4 KiB
Python
268 lines
6.4 KiB
Python
"""Pytest configuration and fixtures for hook tests."""
|
|
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
from collections.abc import Generator
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
import pytest
|
|
|
|
# Add hooks directory to path for imports
|
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "hooks"))
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_python_file() -> Generator[Path, None, None]:
|
|
"""Create a temporary Python file for testing."""
|
|
with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as tmp:
|
|
tmp_path = Path(tmp.name)
|
|
yield tmp_path
|
|
tmp_path.unlink(missing_ok=True)
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_hook_input_pretooluse() -> dict[str, Any]:
|
|
"""Create mock PreToolUse hook input."""
|
|
return {
|
|
"tool_name": "Write",
|
|
"tool_input": {
|
|
"file_path": "test.py",
|
|
"content": "def test():\n pass",
|
|
},
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_hook_input_posttooluse() -> dict[str, Any]:
|
|
"""Create mock PostToolUse hook input."""
|
|
return {
|
|
"tool_name": "Write",
|
|
"tool_output": {
|
|
"file_path": "test.py",
|
|
"status": "success",
|
|
},
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def complex_code() -> str:
|
|
"""Sample complex code for testing."""
|
|
return """
|
|
def process_data(data, config, mode, validate, transform, options):
|
|
if not data:
|
|
return None
|
|
if mode == 'simple':
|
|
if validate:
|
|
if len(data) > 100:
|
|
if transform:
|
|
if options.get('uppercase'):
|
|
return data.upper()
|
|
elif options.get('lowercase'):
|
|
return data.lower()
|
|
else:
|
|
return data
|
|
else:
|
|
return data
|
|
else:
|
|
if transform and options.get('trim'):
|
|
return data.strip()
|
|
else:
|
|
return data
|
|
else:
|
|
return data
|
|
elif mode == 'complex':
|
|
if validate and len(data) > 50:
|
|
if transform:
|
|
if options.get('reverse'):
|
|
return data[::-1]
|
|
elif options.get('double'):
|
|
return data * 2
|
|
else:
|
|
return data
|
|
else:
|
|
return data
|
|
else:
|
|
return data
|
|
else:
|
|
return None
|
|
"""
|
|
|
|
|
|
@pytest.fixture
|
|
def duplicate_code() -> str:
|
|
"""Sample code with internal duplicates."""
|
|
return """
|
|
def calculate_user_total(users):
|
|
total = 0
|
|
for user in users:
|
|
if user.active:
|
|
total += user.amount * user.tax_rate
|
|
return total
|
|
|
|
def calculate_product_total(products):
|
|
total = 0
|
|
for product in products:
|
|
if product.active:
|
|
total += product.amount * product.tax_rate
|
|
return total
|
|
|
|
def calculate_order_total(orders):
|
|
total = 0
|
|
for order in orders:
|
|
if order.active:
|
|
total += order.amount * order.tax_rate
|
|
return total
|
|
"""
|
|
|
|
|
|
@pytest.fixture
|
|
def clean_code() -> str:
|
|
"""Sample clean, modern Python code."""
|
|
return """
|
|
from typing import List, Optional, Dict
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass
|
|
class User:
|
|
name: str
|
|
email: str
|
|
active: bool = True
|
|
|
|
|
|
def process_users(users: List[User]) -> Dict[str, int]:
|
|
\"\"\"Process active users and return counts.\"\"\"
|
|
active_count = sum(1 for user in users if user.active)
|
|
return {"active": active_count, "total": len(users)}
|
|
|
|
|
|
def find_user(users: List[User], email: str) -> Optional[User]:
|
|
\"\"\"Find user by email.\"\"\"
|
|
return next((u for u in users if u.email == email), None)
|
|
"""
|
|
|
|
|
|
@pytest.fixture
|
|
def non_pep8_code() -> str:
|
|
"""Code with PEP8 naming violations."""
|
|
return """
|
|
def calculateTotal(items): # Should be snake_case
|
|
return sum(items)
|
|
|
|
class user_manager: # Should be PascalCase
|
|
def GetUser(self, id): # Should be snake_case
|
|
pass
|
|
|
|
def processHTTPRequest(request): # Should be snake_case
|
|
pass
|
|
|
|
class API_handler: # Should be PascalCase
|
|
pass
|
|
"""
|
|
|
|
|
|
@pytest.fixture
|
|
def old_style_code() -> str:
|
|
"""Code with outdated Python patterns."""
|
|
return """
|
|
def process_data(items):
|
|
result = []
|
|
for i in range(len(items)): # Should use enumerate
|
|
if items[i] != None: # Should use 'is not None'
|
|
result.append(items[i])
|
|
|
|
# Old string formatting
|
|
message = "Found %d items" % len(result)
|
|
|
|
# No type hints
|
|
def add(a, b):
|
|
return a + b
|
|
|
|
return result
|
|
"""
|
|
|
|
|
|
@pytest.fixture
|
|
def test_file_code() -> str:
|
|
"""Sample test file code."""
|
|
return """
|
|
import pytest
|
|
|
|
def test_something():
|
|
assert 1 + 1 == 2
|
|
|
|
def test_another():
|
|
x = 10
|
|
y = 20
|
|
assert x < y
|
|
|
|
class TestClass:
|
|
def test_method(self):
|
|
assert True
|
|
"""
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def reset_environment():
|
|
"""Reset environment variables before each test."""
|
|
# Store original environment
|
|
original_env = os.environ.copy()
|
|
|
|
# Clear quality-related environment variables
|
|
quality_vars = [k for k in os.environ if k.startswith("QUALITY_")]
|
|
for var in quality_vars:
|
|
del os.environ[var]
|
|
|
|
yield
|
|
|
|
# Restore original environment
|
|
os.environ.clear()
|
|
os.environ.update(original_env)
|
|
|
|
|
|
@pytest.fixture
|
|
def set_env_strict():
|
|
"""Set environment for strict mode."""
|
|
os.environ.update(
|
|
{
|
|
"QUALITY_ENFORCEMENT": "strict",
|
|
"QUALITY_DUP_THRESHOLD": "0.7",
|
|
"QUALITY_COMPLEXITY_THRESHOLD": "10",
|
|
"QUALITY_DUP_ENABLED": "true",
|
|
"QUALITY_COMPLEXITY_ENABLED": "true",
|
|
"QUALITY_MODERN_ENABLED": "true",
|
|
"QUALITY_REQUIRE_TYPES": "true",
|
|
},
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def set_env_permissive():
|
|
"""Set environment for permissive mode."""
|
|
os.environ.update(
|
|
{
|
|
"QUALITY_ENFORCEMENT": "permissive",
|
|
"QUALITY_DUP_THRESHOLD": "0.9",
|
|
"QUALITY_COMPLEXITY_THRESHOLD": "20",
|
|
"QUALITY_DUP_ENABLED": "true",
|
|
"QUALITY_COMPLEXITY_ENABLED": "true",
|
|
"QUALITY_MODERN_ENABLED": "false",
|
|
"QUALITY_REQUIRE_TYPES": "false",
|
|
},
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def set_env_posttooluse():
|
|
"""Set environment for PostToolUse features."""
|
|
os.environ.update(
|
|
{
|
|
"QUALITY_STATE_TRACKING": "true",
|
|
"QUALITY_CROSS_FILE_CHECK": "true",
|
|
"QUALITY_VERIFY_NAMING": "true",
|
|
"QUALITY_SHOW_SUCCESS": "true",
|
|
},
|
|
)
|