# #region Test.Encryption [C:3] [TYPE Module] [SEMANTICS test,encryption,fernet,key,crypto] # @BRIEF Tests for core/encryption.py and core/encryption_key.py — Fernet key loading, encrypt/decrypt. # @RELATION BINDS_TO -> [EncryptionCore] from pathlib import Path import sys sys.path.insert(0, str(Path(__file__).parent.parent / "src")) import os import tempfile from unittest.mock import patch, MagicMock import pytest class TestRequireFernetKey: """_require_fernet_key — loads and validates Fernet key from environment.""" def test_valid_key(self): from src.core.encryption import _require_fernet_key key = "MldUHg5kwSAcPnnYxmhWDS6ASb6e_bWQRV5gtwHrjQ0=" with patch.dict(os.environ, {"ENCRYPTION_KEY": key}, clear=True): result = _require_fernet_key() assert result == key.encode() def test_missing_key_raises(self): from src.core.encryption import _require_fernet_key with patch.dict(os.environ, {}, clear=True): with pytest.raises(RuntimeError, match="ENCRYPTION_KEY must be set"): _require_fernet_key() def test_invalid_key_raises(self): from src.core.encryption import _require_fernet_key with patch.dict(os.environ, {"ENCRYPTION_KEY": "not-a-valid-fernet-key"}, clear=True): with pytest.raises(RuntimeError, match="valid Fernet key"): _require_fernet_key() def test_empty_key_raises(self): from src.core.encryption import _require_fernet_key with patch.dict(os.environ, {"ENCRYPTION_KEY": " "}, clear=True): with pytest.raises(RuntimeError, match="ENCRYPTION_KEY must be set"): _require_fernet_key() class TestEncryptionManager: """EncryptionManager — encrypt and decrypt operations.""" def test_encrypt_decrypt_cycle(self): from src.core.encryption import EncryptionManager key = "MldUHg5kwSAcPnnYxmhWDS6ASb6e_bWQRV5gtwHrjQ0=" with patch.dict(os.environ, {"ENCRYPTION_KEY": key}, clear=True): mgr = EncryptionManager() encrypted = mgr.encrypt("my_secret_data") assert encrypted != "my_secret_data" decrypted = mgr.decrypt(encrypted) assert decrypted == "my_secret_data" def test_empty_string_encryption(self): from src.core.encryption import EncryptionManager key = "MldUHg5kwSAcPnnYxmhWDS6ASb6e_bWQRV5gtwHrjQ0=" with patch.dict(os.environ, {"ENCRYPTION_KEY": key}, clear=True): mgr = EncryptionManager() encrypted = mgr.encrypt("") decrypted = mgr.decrypt(encrypted) assert decrypted == "" def test_decrypt_invalid_data_raises(self): from src.core.encryption import EncryptionManager key = "MldUHg5kwSAcPnnYxmhWDS6ASb6e_bWQRV5gtwHrjQ0=" with patch.dict(os.environ, {"ENCRYPTION_KEY": key}, clear=True): mgr = EncryptionManager() with pytest.raises(Exception): mgr.decrypt("not-encrypted-data") class TestEnsureEncryptionKey: """ensure_encryption_key — resolve key from env or .env file.""" def test_from_environment(self): from src.core.encryption_key import ensure_encryption_key key = "MldUHg5kwSAcPnnYxmhWDS6ASb6e_bWQRV5gtwHrjQ0=" with patch.dict(os.environ, {"ENCRYPTION_KEY": key}, clear=True): result = ensure_encryption_key() assert result == key def test_from_env_file(self): from src.core.encryption_key import ensure_encryption_key key = "MldUHg5kwSAcPnnYxmhWDS6ASb6e_bWQRV5gtwHrjQ0=" with patch.dict(os.environ, {}, clear=True): with tempfile.TemporaryDirectory() as tmpdir: env_file = Path(tmpdir) / ".env" env_file.write_text(f"ENCRYPTION_KEY={key}\nOTHER=value\n") result = ensure_encryption_key(env_file) assert result == key # Should also set it in environment assert os.environ.get("ENCRYPTION_KEY") == key def test_env_file_not_found_raises(self): from src.core.encryption_key import ensure_encryption_key with patch.dict(os.environ, {}, clear=True): with pytest.raises(RuntimeError, match="ENCRYPTION_KEY is not set"): ensure_encryption_key(Path("/nonexistent/.env")) def test_env_file_without_key_raises(self): from src.core.encryption_key import ensure_encryption_key with patch.dict(os.environ, {}, clear=True): with tempfile.TemporaryDirectory() as tmpdir: env_file = Path(tmpdir) / ".env" env_file.write_text("OTHER=value\n") with pytest.raises(RuntimeError, match="ENCRYPTION_KEY is not set"): ensure_encryption_key(env_file) # #endregion Test.Encryption