test: add config, format_msg, and Bot API tests
New test_config.py: merge, load, resolve_config tests. Extend test_irc.py: format_msg edge cases (colon, empty, multi-param). Extend test_plugin.py: Bot API via FakeConnection, _split_utf8 tests. Test count: 92 -> 120. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
93
tests/test_config.py
Normal file
93
tests/test_config.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""Tests for configuration loading and merging."""
|
||||
|
||||
import copy
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from derp.config import DEFAULTS, _merge, load, resolve_config
|
||||
|
||||
|
||||
class TestMerge:
|
||||
"""Test deep merge logic."""
|
||||
|
||||
def test_flat_override(self):
|
||||
base = {"a": 1, "b": 2}
|
||||
result = _merge(base, {"b": 99})
|
||||
assert result == {"a": 1, "b": 99}
|
||||
|
||||
def test_nested_merge(self):
|
||||
base = {"server": {"host": "a", "port": 1}}
|
||||
result = _merge(base, {"server": {"port": 2}})
|
||||
assert result == {"server": {"host": "a", "port": 2}}
|
||||
|
||||
def test_list_replacement(self):
|
||||
base = {"channels": ["#old"]}
|
||||
result = _merge(base, {"channels": ["#new"]})
|
||||
assert result == {"channels": ["#new"]}
|
||||
|
||||
def test_empty_override(self):
|
||||
base = {"a": 1, "b": 2}
|
||||
result = _merge(base, {})
|
||||
assert result == {"a": 1, "b": 2}
|
||||
|
||||
def test_new_keys(self):
|
||||
base = {"a": 1}
|
||||
result = _merge(base, {"b": 2})
|
||||
assert result == {"a": 1, "b": 2}
|
||||
|
||||
def test_base_not_mutated(self):
|
||||
base = {"server": {"host": "original"}}
|
||||
original = copy.deepcopy(base)
|
||||
_merge(base, {"server": {"host": "changed"}})
|
||||
assert base == original
|
||||
|
||||
|
||||
class TestLoad:
|
||||
"""Test TOML file loading."""
|
||||
|
||||
def test_minimal_toml(self, tmp_path: Path):
|
||||
config_file = tmp_path / "test.toml"
|
||||
config_file.write_text('[server]\nnick = "testbot"\n')
|
||||
result = load(config_file)
|
||||
# Overridden value
|
||||
assert result["server"]["nick"] == "testbot"
|
||||
# Default preserved
|
||||
assert result["server"]["host"] == "irc.libera.chat"
|
||||
assert result["server"]["port"] == 6697
|
||||
|
||||
def test_full_override(self, tmp_path: Path):
|
||||
config_file = tmp_path / "test.toml"
|
||||
config_file.write_text(
|
||||
'[server]\nhost = "custom.irc"\nport = 6667\n'
|
||||
'[bot]\nprefix = "."\n'
|
||||
)
|
||||
result = load(config_file)
|
||||
assert result["server"]["host"] == "custom.irc"
|
||||
assert result["server"]["port"] == 6667
|
||||
assert result["bot"]["prefix"] == "."
|
||||
# Unset defaults still present
|
||||
assert result["bot"]["channels"] == ["#test"]
|
||||
|
||||
|
||||
class TestResolveConfig:
|
||||
"""Test config path resolution and fallback."""
|
||||
|
||||
def test_explicit_path(self, tmp_path: Path):
|
||||
config_file = tmp_path / "explicit.toml"
|
||||
config_file.write_text('[server]\nnick = "explicit"\n')
|
||||
result = resolve_config(str(config_file))
|
||||
assert result["server"]["nick"] == "explicit"
|
||||
|
||||
def test_no_file_fallback(self, tmp_path: Path, monkeypatch: "pytest.MonkeyPatch"):
|
||||
# Run from tmp_path so config/derp.toml isn't found
|
||||
monkeypatch.chdir(tmp_path)
|
||||
result = resolve_config(str(tmp_path / "nonexistent.toml"))
|
||||
# Should fall back to DEFAULTS
|
||||
assert result["server"]["host"] == DEFAULTS["server"]["host"]
|
||||
assert result["bot"]["prefix"] == DEFAULTS["bot"]["prefix"]
|
||||
|
||||
def test_defaults_not_mutated(self):
|
||||
original = copy.deepcopy(DEFAULTS)
|
||||
resolve_config(None)
|
||||
assert DEFAULTS == original
|
||||
Reference in New Issue
Block a user