Files
echo-core/tests/test_config.py
MoltBot Service f2973aa76f stage-1: project bootstrap
Structure, config loader, personality/tools/memory from clawd, venv, 22 tests passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 10:20:55 +00:00

162 lines
4.7 KiB
Python

"""Comprehensive tests for src/config.py."""
import json
import pytest
from pathlib import Path
from src.config import Config, load_config
@pytest.fixture
def tmp_config(tmp_path):
"""Create a temporary config file and return its path."""
data = {
"bot": {
"name": "TestBot",
"default_model": "sonnet",
"owner": None,
"admins": []
},
"channels": {},
"heartbeat": {
"enabled": True,
"interval_minutes": 30
},
"ollama": {
"url": "http://localhost:11434"
},
"paths": {
"personality": "personality/",
"tools": "tools/",
"memory": "memory/"
}
}
config_file = tmp_path / "config.json"
config_file.write_text(json.dumps(data, indent=2))
return config_file
class TestConfigLoad:
def test_load_from_path(self, tmp_config):
cfg = Config(tmp_config)
assert cfg.get("bot.name") == "TestBot"
def test_load_config_convenience(self, tmp_config):
cfg = load_config(tmp_config)
assert cfg.get("bot.name") == "TestBot"
def test_load_missing_file_raises(self, tmp_path):
with pytest.raises(FileNotFoundError):
Config(tmp_path / "nonexistent.json")
def test_load_invalid_json_raises(self, tmp_path):
bad = tmp_path / "bad.json"
bad.write_text("not json {{{")
with pytest.raises(json.JSONDecodeError):
Config(bad)
class TestConfigGet:
def test_top_level_key(self, tmp_config):
cfg = Config(tmp_config)
assert cfg.get("channels") == {}
def test_nested_key(self, tmp_config):
cfg = Config(tmp_config)
assert cfg.get("bot.default_model") == "sonnet"
def test_deeply_nested(self, tmp_config):
cfg = Config(tmp_config)
assert cfg.get("heartbeat.interval_minutes") == 30
def test_missing_key_returns_none(self, tmp_config):
cfg = Config(tmp_config)
assert cfg.get("nonexistent") is None
def test_missing_key_returns_default(self, tmp_config):
cfg = Config(tmp_config)
assert cfg.get("nonexistent", "fallback") == "fallback"
def test_missing_nested_key_returns_default(self, tmp_config):
cfg = Config(tmp_config)
assert cfg.get("bot.nonexistent.deep", 42) == 42
def test_null_value_returned_as_none(self, tmp_config):
cfg = Config(tmp_config)
assert cfg.get("bot.owner") is None
def test_list_value(self, tmp_config):
cfg = Config(tmp_config)
assert cfg.get("bot.admins") == []
def test_bool_value(self, tmp_config):
cfg = Config(tmp_config)
assert cfg.get("heartbeat.enabled") is True
class TestConfigSet:
def test_set_existing_key(self, tmp_config):
cfg = Config(tmp_config)
cfg.set("bot.name", "NewName")
assert cfg.get("bot.name") == "NewName"
def test_set_new_nested_key(self, tmp_config):
cfg = Config(tmp_config)
cfg.set("new.nested.key", 42)
assert cfg.get("new.nested.key") == 42
def test_set_top_level_key(self, tmp_config):
cfg = Config(tmp_config)
cfg.set("debug", True)
assert cfg.get("debug") is True
def test_set_overwrites_non_dict(self, tmp_config):
cfg = Config(tmp_config)
cfg.set("bot.name.sub", "value")
assert cfg.get("bot.name.sub") == "value"
class TestConfigSave:
def test_save_persists_changes(self, tmp_config):
cfg = Config(tmp_config)
cfg.set("bot.name", "Saved")
cfg.save()
cfg2 = Config(tmp_config)
assert cfg2.get("bot.name") == "Saved"
def test_save_preserves_structure(self, tmp_config):
cfg = Config(tmp_config)
cfg.set("new_key", "new_value")
cfg.save()
raw = json.loads(tmp_config.read_text())
assert raw["bot"]["name"] == "TestBot"
assert raw["new_key"] == "new_value"
class TestConfigReload:
def test_reload_picks_up_external_changes(self, tmp_config):
cfg = Config(tmp_config)
assert cfg.get("bot.name") == "TestBot"
data = json.loads(tmp_config.read_text())
data["bot"]["name"] = "ExternalChange"
tmp_config.write_text(json.dumps(data))
cfg.reload()
assert cfg.get("bot.name") == "ExternalChange"
class TestConfigRaw:
def test_raw_returns_dict(self, tmp_config):
cfg = Config(tmp_config)
raw = cfg.raw()
assert isinstance(raw, dict)
assert raw["bot"]["name"] == "TestBot"
def test_raw_is_reference(self, tmp_config):
cfg = Config(tmp_config)
raw = cfg.raw()
raw["bot"]["name"] = "Mutated"
assert cfg.get("bot.name") == "Mutated"