Tests: Reorganize test suite into functional subdirectories
- Categorized scripts into tests/unit/, tests/integration/, tests/e2e/, and tests/tools/. - Adopted consistent naming prefixes (test_unit_*, test_int_*, test_e2e_*, tool_*). - Renamed conftest_mock.py to mock_config_helper.py for clarity. - Updated test_int_boot_diagnosis.py with sys.path setup for root-level execution.
This commit is contained in:
104
tests/unit/test_unit_payload_sanitization.py
Normal file
104
tests/unit/test_unit_payload_sanitization.py
Normal file
@@ -0,0 +1,104 @@
|
||||
import sys
|
||||
import os
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
# --- Environment Setup ---
|
||||
sys.modules['redis'] = MagicMock()
|
||||
sys.modules['sqlalchemy'] = MagicMock()
|
||||
sys.modules['app.config'] = MagicMock()
|
||||
sys.modules['html2text'] = MagicMock()
|
||||
sys.modules['app.log'] = MagicMock()
|
||||
sys.modules['app.lib_general'] = MagicMock()
|
||||
|
||||
# Mock app.db_sql
|
||||
mock_db_sql = MagicMock()
|
||||
# Mock ID resolution: abc -> 123
|
||||
mock_db_sql.redis_lookup_id_random.side_effect = lambda record_id_random, table_name: 123 if record_id_random == 'abc' else None
|
||||
sys.modules['app.db_sql'] = mock_db_sql
|
||||
|
||||
# Add project root to path
|
||||
sys.path.append(os.getcwd())
|
||||
|
||||
from app.lib_api_crud_v3 import sanitize_payload
|
||||
from pydantic import BaseModel, Field, ValidationError
|
||||
from typing import Optional, List, ClassVar
|
||||
|
||||
class MockModel(BaseModel):
|
||||
id: Optional[int]
|
||||
name: str = Field(None, min_length=3)
|
||||
account_id: Optional[int]
|
||||
|
||||
fields_to_exclude_from_db: ClassVar[List[str]] = ['computed_field']
|
||||
|
||||
def test_permissive_update():
|
||||
print("--- Testing Permissive Update (ignore_extra=True) ---")
|
||||
payload = {
|
||||
"name": "Test",
|
||||
"extra_field": "Should be removed",
|
||||
"computed_field": "Should be removed"
|
||||
}
|
||||
sanitize_payload(payload, MockModel, ignore_extra=True)
|
||||
print(f"Sanitized Payload: {payload}")
|
||||
|
||||
assert "extra_field" not in payload
|
||||
assert "computed_field" not in payload
|
||||
assert payload["name"] == "Test"
|
||||
print("✅ Permissive update stripping works.")
|
||||
|
||||
def test_strict_update():
|
||||
print("\n--- Testing Strict Update (ignore_extra=False) ---")
|
||||
payload = {
|
||||
"name": "Test",
|
||||
"extra_field": "Should be removed",
|
||||
"computed_field": "Should be removed"
|
||||
}
|
||||
sanitize_payload(payload, MockModel, ignore_extra=False)
|
||||
print(f"Sanitized Payload: {payload}")
|
||||
|
||||
assert "extra_field" in payload
|
||||
assert "computed_field" not in payload
|
||||
print("✅ Strict update correctly preserves unknown fields (waiting for DB error) but strips excluded fields.")
|
||||
|
||||
def test_id_resolution():
|
||||
print("\n--- Testing ID Resolution ---")
|
||||
payload = {
|
||||
"name": "Test",
|
||||
"account_id_random": "abc"
|
||||
}
|
||||
sanitize_payload(payload, MockModel)
|
||||
print(f"Sanitized Payload: {payload}")
|
||||
|
||||
assert payload.get("account_id") == 123
|
||||
assert "account_id_random" not in payload
|
||||
print("✅ ID resolution (account_id_random -> account_id) works.")
|
||||
|
||||
def test_structured_validation_errors():
|
||||
print("\n--- Testing Structured Validation Errors ---")
|
||||
payload = {
|
||||
"name": "a" # Too short
|
||||
}
|
||||
try:
|
||||
MockModel(**payload)
|
||||
except ValidationError as e:
|
||||
structured_errors = {err['loc'][-1]: err['msg'] for err in e.errors()}
|
||||
print(f"Structured Errors: {structured_errors}")
|
||||
assert "name" in structured_errors
|
||||
# Pydantic 1.x error message
|
||||
assert "at least 3 characters" in structured_errors["name"]
|
||||
print("✅ Structured validation errors work.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
test_permissive_update()
|
||||
test_strict_update()
|
||||
test_id_resolution()
|
||||
test_structured_validation_errors()
|
||||
print("\n🎉 All local logic tests passed!")
|
||||
except AssertionError as e:
|
||||
print(f"\n❌ Test failed: {e}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"\n💥 An error occurred: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user