"""Tests for markitect.llm.config.""" import os from pathlib import Path from unittest import mock import pytest from markitect.llm.config import ( LLMConfig, resolve_api_key, find_project_root, load_config, ) class TestResolveApiKey: def test_explicit_key_wins(self): key = resolve_api_key(explicit="sk-explicit") assert key == "sk-explicit" def test_env_var_fallback(self): with mock.patch.dict(os.environ, {"MY_KEY": "sk-env"}): key = resolve_api_key(explicit=None, env_var="MY_KEY") assert key == "sk-env" def test_env_var_stripped(self): with mock.patch.dict(os.environ, {"MY_KEY": " sk-env \n"}): key = resolve_api_key(explicit=None, env_var="MY_KEY") assert key == "sk-env" def test_file_fallback(self, tmp_path): key_file = tmp_path / "key.txt" key_file.write_text("sk-file\n") key = resolve_api_key( explicit=None, env_var="NONEXISTENT_VAR_XYZ", key_file_paths=[key_file], ) assert key == "sk-file" def test_file_skips_empty(self, tmp_path): empty = tmp_path / "empty.txt" empty.write_text("") good = tmp_path / "good.txt" good.write_text("sk-good") key = resolve_api_key( explicit=None, env_var="NONEXISTENT_VAR_XYZ", key_file_paths=[empty, good], ) assert key == "sk-good" def test_file_skips_missing(self, tmp_path): missing = tmp_path / "no-such-file.txt" key = resolve_api_key( explicit=None, env_var="NONEXISTENT_VAR_XYZ", key_file_paths=[missing], ) assert key is None def test_returns_none_when_nothing_found(self): key = resolve_api_key( explicit=None, env_var="NONEXISTENT_VAR_XYZ", key_file_paths=[], ) assert key is None class TestFindProjectRoot: def test_finds_root(self, tmp_path): (tmp_path / "pyproject.toml").write_text("[project]") sub = tmp_path / "a" / "b" sub.mkdir(parents=True) assert find_project_root(sub) == tmp_path def test_returns_none_if_no_marker(self, tmp_path): sub = tmp_path / "a" / "b" sub.mkdir(parents=True) # tmp_path itself won't have pyproject.toml result = find_project_root(sub) # Could be None or could find the real project root above; # the important thing is it doesn't crash assert result is None or (result / "pyproject.toml").exists() class TestLoadConfig: def test_returns_llmconfig(self): cfg = load_config(provider="claude-code") assert isinstance(cfg, LLMConfig) assert cfg.provider == "claude-code" def test_model_override(self): cfg = load_config(model="my-model") assert cfg.model == "my-model" def test_explicit_key(self): cfg = load_config(api_key="sk-test") assert cfg.api_key == "sk-test" def test_extra_overrides(self): cfg = load_config(timeout_seconds=60) assert cfg.timeout_seconds == 60