""" Settings matrix tests. Verify that each settings profile has the required keys and safe defaults — without needing to boot each profile as a full Django app. These run under the test settings module and import the other modules directly for inspection. """ import importlib import os import sys from unittest.mock import patch import pytest def _load_settings(module_path: str): """Import a settings module with minimal env vars patched in.""" env_patch = { "DJANGO_SECRET_KEY": "test-secret-key", "DJANGO_ALLOWED_HOSTS": "localhost", "DATABASE_URL": "postgres://training:training@localhost:5432/training", "REDIS_URL": "redis://localhost:6379/0", # prod extras "AWS_STORAGE_BUCKET_NAME": "test-bucket", "EMAIL_HOST": "smtp.example.com", "EMAIL_HOST_USER": "user@example.com", "EMAIL_HOST_PASSWORD": "password", "DEFAULT_FROM_EMAIL": "noreply@example.com", } with patch.dict(os.environ, env_patch, clear=False): if module_path in sys.modules: return importlib.reload(sys.modules[module_path]) return importlib.import_module(module_path) @pytest.mark.settings class TestBaseSettings: def test_secret_key_required(self): """SECRET_KEY must be set from environment (not a default fallback).""" mod = _load_settings("config.settings.base") assert mod.SECRET_KEY == "test-secret-key" def test_debug_is_false(self): mod = _load_settings("config.settings.base") assert mod.DEBUG is False def test_rest_framework_has_exception_handler(self): mod = _load_settings("config.settings.base") assert mod.REST_FRAMEWORK["EXCEPTION_HANDLER"] == "api.exceptions.custom_exception_handler" def test_rest_framework_default_closed(self): mod = _load_settings("config.settings.base") perms = mod.REST_FRAMEWORK["DEFAULT_PERMISSION_CLASSES"] assert "rest_framework.permissions.IsAuthenticated" in perms def test_celery_serializer_json(self): mod = _load_settings("config.settings.base") assert mod.CELERY_TASK_SERIALIZER == "json" assert mod.CELERY_RESULT_SERIALIZER == "json" assert "json" in mod.CELERY_ACCEPT_CONTENT def test_language_code_german(self): mod = _load_settings("config.settings.base") assert mod.LANGUAGE_CODE == "de-de" def test_timezone_europe_berlin(self): mod = _load_settings("config.settings.base") assert mod.TIME_ZONE == "Europe/Berlin" @pytest.mark.settings class TestLocalSettings: def test_debug_is_true(self): mod = _load_settings("config.settings.local") assert mod.DEBUG is True def test_debug_toolbar_in_installed_apps(self): mod = _load_settings("config.settings.local") assert "debug_toolbar" in mod.INSTALLED_APPS def test_email_console_backend(self): mod = _load_settings("config.settings.local") assert "console" in mod.EMAIL_BACKEND.lower() @pytest.mark.settings class TestTestSettings: def test_celery_always_eager(self): mod = _load_settings("config.settings.test") assert getattr(mod, "CELERY_TASK_ALWAYS_EAGER", False) is True def test_debug_is_false(self): mod = _load_settings("config.settings.test") assert mod.DEBUG is False def test_fast_password_hasher(self): mod = _load_settings("config.settings.test") assert any("MD5" in h for h in mod.PASSWORD_HASHERS) @pytest.mark.settings class TestProdSettings: def test_debug_is_false(self): mod = _load_settings("config.settings.prod") assert mod.DEBUG is False def test_ssl_redirect_enabled(self): mod = _load_settings("config.settings.prod") assert mod.SECURE_SSL_REDIRECT is True def test_hsts_configured(self): mod = _load_settings("config.settings.prod") assert mod.SECURE_HSTS_SECONDS >= 31536000 def test_session_cookie_secure(self): mod = _load_settings("config.settings.prod") assert mod.SESSION_COOKIE_SECURE is True def test_csrf_cookie_secure(self): mod = _load_settings("config.settings.prod") assert mod.CSRF_COOKIE_SECURE is True