Documentation Standardisation & Unit Test Stabilization

- Overhauled README.md to serve as a unified system index and WIP tracker.
- Standardized documentation filenames (ARCH__, GUIDE__, PLAN__) for better discoverability.
- Archived completed project plans and scopes.
- Fixed regressions in unit tests (errors, models, email) caused by V3 architectural updates.
- Ensured unit tests remain non-destructive and environment-independent via mocking.
This commit is contained in:
Scott Idem
2026-01-28 12:15:01 -05:00
parent 3eaf176b05
commit 860cf80a4e
17 changed files with 118 additions and 28 deletions

View File

@@ -7,6 +7,13 @@ from unittest.mock import MagicMock, patch
# Add current directory to path
sys.path.append(os.getcwd())
# Mock app.config BEFORE imports
mock_config = MagicMock()
mock_settings = MagicMock()
mock_settings.SMTP = {}
mock_config.settings = mock_settings
sys.modules['app.config'] = mock_config
# Mock html2text before importing app.lib_email
sys.modules['html2text'] = MagicMock()
@@ -19,12 +26,7 @@ from app.config import settings
class TestEmail(unittest.TestCase):
def test_send_email_missing_settings(self):
print("\nTesting send_email with missing SMTP settings...")
# Backup original settings
original_smtp = getattr(settings, 'SMTP', {})
# Clear settings
settings.SMTP = {}
# settings is already mocked to have an empty SMTP dict
result = send_email(
from_email="test@example.com",
to_email="test@example.com",
@@ -33,15 +35,11 @@ class TestEmail(unittest.TestCase):
test=True
)
# Restore settings
settings.SMTP = original_smtp
print(f"Result (should be False): {result}")
self.assertFalse(result)
def test_send_email_invalid_port(self):
print("\nTesting send_email with invalid port...")
original_smtp = getattr(settings, 'SMTP', {})
settings.SMTP = {
'server': 'smtp.example.com',
@@ -58,10 +56,8 @@ class TestEmail(unittest.TestCase):
test=True
)
settings.SMTP = original_smtp
print(f"Result (should be False): {result}")
self.assertFalse(result)
if __name__ == "__main__":
unittest.main()
unittest.main()

View File

@@ -27,14 +27,16 @@ def test_error_formatting():
formatted = format_db_error(raw)
print(f"Raw: {raw}")
print(f"Formatted: {formatted}")
if formatted == "Duplicate entry 'abc' for key 'id_random'":
if formatted.category == "database_duplicate" and formatted.code == 1062:
print("✅ Error formatting works.")
else:
print("❌ Error formatting FAILED.")
def test_null_error_handling():
print("\n--- Testing Null Error Handling ---")
if format_db_error(None) == "":
formatted = format_db_error(None)
if formatted.category == "unknown":
print("✅ Null error handled correctly.")
else:
print("❌ Null error check FAILED.")

View File

@@ -1,6 +1,5 @@
import sys
import os
from typing import ClassVar
from unittest.mock import MagicMock
# --- Environment Setup ---
@@ -23,7 +22,7 @@ mock_lib_general = MagicMock()
mock_lib_general.log = MagicMock()
mock_lib_general.logging = MagicMock()
sys.modules['app.lib_general'] = mock_lib_general
sys.modules['app.log'] = MagicMock() # Ensure app.log is also mocked if needed separately
mock_db_sql = MagicMock()
mock_db_sql.redis_lookup_id_random.return_value = 1
mock_db_sql.get_id_random.return_value = "mock_id"
@@ -44,13 +43,7 @@ except Exception as e:
def test_person_null_given_name():
"""Test that given_name=None is converted to empty string."""
try:
# construct() bypasses validation, so we use the constructor
# We provide dummy values for other likely required fields
p = Person_Base.construct(given_name=None)
# Note: In Pydantic V1 validators run on __init__.
# Since we mocked the environment, we'll test the validator function directly if init fails.
from app.models.person_models import Person_Base
# In Pydantic V1, we test the validator classmethod directly if instantiation is too complex with mocks
val = Person_Base.given_name_validator(None)
if val == "":
print("✅ given_name validator: None -> '' (Success)")
@@ -62,7 +55,6 @@ def test_person_null_given_name():
def test_person_null_allow_auth_key():
"""Test that allow_auth_key=None is converted to True."""
try:
from app.models.person_models import Person_Base
val = Person_Base.allow_auth_key_validator(None)
if val is True:
print("✅ allow_auth_key validator: None -> True (Success)")
@@ -73,4 +65,4 @@ def test_person_null_allow_auth_key():
if __name__ == "__main__":
test_person_null_given_name()
test_person_null_allow_auth_key()
test_person_null_allow_auth_key()