Persist processing-log retention settings and wire cleanup defaults
This commit is contained in:
135
backend/tests/test_processing_log_retention_settings.py
Normal file
135
backend/tests/test_processing_log_retention_settings.py
Normal file
@@ -0,0 +1,135 @@
|
||||
"""Unit coverage for persisted processing log retention settings behavior."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
BACKEND_ROOT = Path(__file__).resolve().parents[1]
|
||||
if str(BACKEND_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(BACKEND_ROOT))
|
||||
|
||||
if "pydantic_settings" not in sys.modules:
|
||||
pydantic_settings_stub = ModuleType("pydantic_settings")
|
||||
|
||||
class _BaseSettings:
|
||||
"""Minimal BaseSettings replacement for dependency-light unit test execution."""
|
||||
|
||||
def __init__(self, **kwargs: object) -> None:
|
||||
for key, value in kwargs.items():
|
||||
setattr(self, key, value)
|
||||
|
||||
def _settings_config_dict(**kwargs: object) -> dict[str, object]:
|
||||
"""Returns configuration values using dict semantics expected by settings module."""
|
||||
|
||||
return kwargs
|
||||
|
||||
pydantic_settings_stub.BaseSettings = _BaseSettings
|
||||
pydantic_settings_stub.SettingsConfigDict = _settings_config_dict
|
||||
sys.modules["pydantic_settings"] = pydantic_settings_stub
|
||||
|
||||
from app.schemas.settings import AppSettingsUpdateRequest, ProcessingLogRetentionSettingsUpdateRequest
|
||||
from app.services import app_settings
|
||||
|
||||
|
||||
def _sample_current_payload() -> dict:
|
||||
"""Builds a sanitized payload used as in-memory persistence fixture for update tests."""
|
||||
|
||||
return app_settings._sanitize_settings(app_settings._default_settings())
|
||||
|
||||
|
||||
class ProcessingLogRetentionSettingsTests(unittest.TestCase):
|
||||
"""Verifies defaulting, sanitization, schema mapping, and update merge behavior."""
|
||||
|
||||
def test_sanitize_settings_uses_default_retention_values(self) -> None:
|
||||
"""Defaults are restored when persisted payload omits retention settings."""
|
||||
|
||||
sanitized = app_settings._sanitize_settings({})
|
||||
self.assertEqual(
|
||||
sanitized["processing_log_retention"],
|
||||
{
|
||||
"keep_document_sessions": 2,
|
||||
"keep_unbound_entries": 80,
|
||||
},
|
||||
)
|
||||
|
||||
def test_sanitize_settings_clamps_retention_values(self) -> None:
|
||||
"""Retention values are clamped to same bounds enforced by trim endpoint query rules."""
|
||||
|
||||
sanitized = app_settings._sanitize_settings(
|
||||
{
|
||||
"processing_log_retention": {
|
||||
"keep_document_sessions": 99,
|
||||
"keep_unbound_entries": -5,
|
||||
}
|
||||
}
|
||||
)
|
||||
self.assertEqual(
|
||||
sanitized["processing_log_retention"],
|
||||
{
|
||||
"keep_document_sessions": 20,
|
||||
"keep_unbound_entries": 0,
|
||||
},
|
||||
)
|
||||
|
||||
def test_update_request_schema_accepts_processing_log_retention_payload(self) -> None:
|
||||
"""Settings PATCH schema keeps retention fields in serialized payloads."""
|
||||
|
||||
request_payload = AppSettingsUpdateRequest(
|
||||
processing_log_retention=ProcessingLogRetentionSettingsUpdateRequest(
|
||||
keep_document_sessions=7,
|
||||
)
|
||||
)
|
||||
self.assertEqual(
|
||||
request_payload.model_dump(exclude_none=True)["processing_log_retention"],
|
||||
{"keep_document_sessions": 7},
|
||||
)
|
||||
|
||||
def test_update_app_settings_merges_retention_block_and_sanitizes_values(self) -> None:
|
||||
"""Settings updates merge partial retention values and persist sanitized results."""
|
||||
|
||||
current_payload = _sample_current_payload()
|
||||
|
||||
with (
|
||||
patch.object(app_settings, "_read_raw_settings", return_value=current_payload),
|
||||
patch.object(app_settings, "read_app_settings", return_value={"processing_log_retention": {}}),
|
||||
patch.object(app_settings, "_write_settings") as write_settings_mock,
|
||||
):
|
||||
app_settings.update_app_settings(
|
||||
processing_log_retention={
|
||||
"keep_document_sessions": 9,
|
||||
"keep_unbound_entries": 999,
|
||||
}
|
||||
)
|
||||
|
||||
written_payload = write_settings_mock.call_args.args[0]
|
||||
self.assertEqual(
|
||||
written_payload["processing_log_retention"],
|
||||
{
|
||||
"keep_document_sessions": 9,
|
||||
"keep_unbound_entries": 400,
|
||||
},
|
||||
)
|
||||
|
||||
def test_read_processing_log_retention_settings_returns_defaults_when_key_missing(self) -> None:
|
||||
"""Reader falls back to defaults when persisted payload omits retention key."""
|
||||
|
||||
payload_without_retention = _sample_current_payload()
|
||||
payload_without_retention.pop("processing_log_retention", None)
|
||||
with patch.object(app_settings, "_read_raw_settings", return_value=payload_without_retention):
|
||||
retention = app_settings.read_processing_log_retention_settings()
|
||||
self.assertEqual(
|
||||
retention,
|
||||
{
|
||||
"keep_document_sessions": 2,
|
||||
"keep_unbound_entries": 80,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user