""" Tests for the check-env-vars pre-commit hook. Ensures the hook enforces centralized configuration through SettingsManager instead of direct os.environ access, which prevents hardcoded secrets and ensures consistent config management. """ import ast import sys from importlib import import_module from pathlib import Path HOOKS_DIR = Path(__file__).parent.parent.parent / ".pre-commit-hooks" sys.path.insert(0, str(HOOKS_DIR)) hook_module = import_module("check-env-vars") EnvVarChecker = hook_module.EnvVarChecker def _check_code( code: str, filename: str = "src/local_deep_research/module.py" ) -> list: """Parse code and run the env var checker.""" tree = ast.parse(code) checker = EnvVarChecker(filename) checker.visit(tree) return checker.errors class TestDetectsDirectEnvAccess: """Ensures os.environ usage is flagged in application code.""" def test_detects_os_environ_get(self): code = 'import os\nval = os.environ.get("LDR_SECRET_KEY")\n' errors = _check_code(code) assert len(errors) >= 1 assert any("SettingsManager" in e[1] for e in errors) def test_detects_os_environ_bracket(self): code = 'import os\nval = os.environ["LDR_DATA_DIR"]\n' errors = _check_code(code) assert len(errors) >= 1 def test_detects_os_getenv(self): code = 'import os\nval = os.getenv("LDR_API_KEY")\n' errors = _check_code(code) assert len(errors) >= 1 def test_detects_from_os_import_environ(self): code = "from os import environ\n" errors = _check_code(code) assert len(errors) >= 1 def test_detects_environ_alias(self): code = "import os\nenv = os.environ\n" errors = _check_code(code) assert len(errors) >= 1 def test_detects_in_environ_check(self): code = 'import os\nif "LDR_KEY" in os.environ:\n pass\n' errors = _check_code(code) assert len(errors) >= 1 class TestAllowsSystemVars: """Ensures standard system env vars are not flagged.""" def test_allows_path(self): code = 'import os\npath = os.environ.get("PATH")\n' errors = _check_code(code) assert len(errors) == 0 def test_allows_home(self): code = 'import os\nhome = os.environ.get("HOME")\n' errors = _check_code(code) assert len(errors) == 0 def test_allows_ci(self): code = 'import os\nis_ci = os.environ.get("CI")\n' errors = _check_code(code) assert len(errors) == 0 def test_allows_pytest_current_test(self): code = 'import os\ntest = os.environ.get("PYTEST_CURRENT_TEST")\n' errors = _check_code(code) assert len(errors) == 0 class TestAllowsExemptFiles: """Ensures settings/config/test files are exempt.""" def test_allows_settings_files(self): code = 'import os\nval = os.environ.get("LDR_KEY")\n' errors = _check_code(code, filename="src/settings/manager.py") assert len(errors) == 0 def test_allows_config_files(self): code = 'import os\nval = os.environ.get("LDR_KEY")\n' errors = _check_code(code, filename="src/config/paths.py") assert len(errors) == 0 def test_allows_test_files(self): code = 'import os\nval = os.environ.get("LDR_KEY")\n' errors = _check_code(code, filename="tests/test_something.py") assert len(errors) == 0 def test_allows_migration_files(self): code = 'import os\nval = os.environ.get("LDR_KEY")\n' errors = _check_code(code, filename="migrations/env.py") assert len(errors) == 0 class TestAllowsSafePatterns: """Ensures normal code without env access is not flagged.""" def test_allows_normal_code(self): code = """ def process_data(data): return data.upper() """ errors = _check_code(code) assert len(errors) == 0 def test_allows_settings_manager_usage(self): code = """ from settings.manager import SettingsManager settings = SettingsManager() val = settings.get_setting("my_key") """ errors = _check_code(code) assert len(errors) == 0