ForcePilot/backend/test/unit/channels/test_nextcloudtalk_config_enhanced.py

251 lines
8.6 KiB
Python
Raw Normal View History

from __future__ import annotations
import pytest
from yuxi.channels.adapters.nextcloudtalk.config import (
resolve_history_limit,
resolve_room_allow_from,
resolve_room_config,
resolve_room_enabled,
resolve_room_require_mention,
resolve_room_skills,
resolve_room_system_prompt,
)
from yuxi.channels.adapters.nextcloudtalk.config_schema import (
NextcloudTalkWebhookConfig,
validate_config,
)
class TestResolveRoomRequireMention:
def test_default_true_when_no_config(self):
assert resolve_room_require_mention("room-1", {}) is True
def test_camel_case_key(self):
config = {"rooms": {"room-1": {"requireMention": False}}}
assert resolve_room_require_mention("room-1", config) is False
def test_snake_case_key(self):
config = {"rooms": {"room-1": {"require_mention": False}}}
assert resolve_room_require_mention("room-1", config) is False
def test_wildcard_fallback(self):
config = {"rooms": {"*": {"requireMention": False}}}
assert resolve_room_require_mention("unknown-room", config) is False
class TestResolveRoomAllowFrom:
def test_empty_default(self):
assert resolve_room_allow_from("room-1", {}) == []
def test_camel_case(self):
config = {"rooms": {"room-1": {"allowFrom": ["user-1", "user-2"]}}}
assert resolve_room_allow_from("room-1", config) == ["user-1", "user-2"]
def test_snake_case(self):
config = {"rooms": {"room-1": {"allow_from": ["user-3"]}}}
assert resolve_room_allow_from("room-1", config) == ["user-3"]
def test_wildcard(self):
config = {"rooms": {"*": {"allowFrom": ["global-user"]}}}
assert resolve_room_allow_from("unknown-room", config) == ["global-user"]
def test_direct_overrides_wildcard(self):
config = {
"rooms": {
"room-1": {"allowFrom": ["specific-user"]},
"*": {"allowFrom": ["global-user"]},
}
}
assert resolve_room_allow_from("room-1", config) == ["specific-user"]
class TestResolveRoomSkills:
def test_empty_default(self):
assert resolve_room_skills("room-1", {}) == []
def test_exact_match(self):
config = {"rooms": {"room-1": {"skills": ["skill-a"]}}}
assert resolve_room_skills("room-1", config) == ["skill-a"]
def test_wildcard(self):
config = {"rooms": {"*": {"skills": ["base-skill"]}}}
assert resolve_room_skills("any-room", config) == ["base-skill"]
def test_direct_overrides(self):
config = {
"rooms": {
"room-1": {"skills": ["premium-skill"]},
"*": {"skills": ["base-skill"]},
}
}
assert resolve_room_skills("room-1", config) == ["premium-skill"]
class TestResolveRoomSystemPromptNoneEmpty:
def test_none_when_no_config(self):
assert resolve_room_system_prompt("room-1", {}) is None
def test_empty_string_when_empty_value(self):
config = {"rooms": {"room-1": {"systemPrompt": ""}}}
assert resolve_room_system_prompt("room-1", config) == ""
class TestResolveRoomEnabledEdgeCases:
def test_enabled_key(self):
config = {"rooms": {"room-1": {"enabled": True}}}
assert resolve_room_enabled("room-1", config) is True
def test_enabled_underscore_key(self):
config = {"rooms": {"room-1": {"enabled_": False}}}
assert resolve_room_enabled("room-1", config) is False
def test_wildcard_fallback(self):
config = {"rooms": {"*": {"enabled": False}}}
assert resolve_room_enabled("unknown-room", config) is False
def test_default_true_when_no_rooms(self):
assert resolve_room_enabled("room-1", {}) is True
class TestResolveHistoryLimitEdgeCases:
def test_group_wildcard_room(self):
config = {"rooms": {"*": {"historyLimit": 10}}}
assert resolve_history_limit("any-room", config, "group") == 10
def test_group_global_and_room_both_set(self):
config = {
"historyLimit": 50,
"rooms": {"room-1": {"historyLimit": 25}},
}
assert resolve_history_limit("room-1", config, "group") == 25
def test_group_global_only(self):
assert resolve_history_limit("room-1", {"historyLimit": 50}, "group") == 50
def test_dm_global_snake_case(self):
assert resolve_history_limit("user-1", {"dm_history_limit": 30}, "direct") == 30
def test_dm_per_user_overrides_global(self):
config = {
"dmHistoryLimit": 30,
"dms": {"user-1": {"historyLimit": 10}},
}
assert resolve_history_limit("user-1", config, "direct") == 10
def test_dm_default_zero(self):
assert resolve_history_limit("user-1", {}, "direct") == 0
class TestResolveRoomConfigEdgeCases:
def test_no_rooms_key(self):
result = resolve_room_config("token", {})
assert result["_match_source"] == "none"
def test_empty_rooms_returns_none_source(self):
result = resolve_room_config("token", {"rooms": {}})
assert result["_match_source"] == "none"
def test_no_wildcard_no_match(self):
result = resolve_room_config("token", {"rooms": {"other": {"enabled": True}}})
assert result["_match_source"] == "wildcard"
class TestWebhookConfigSchema:
def test_default_values(self):
cfg = NextcloudTalkWebhookConfig()
assert cfg.enabled is False
assert cfg.port == 8788
assert cfg.host == "0.0.0.0"
assert cfg.path == "/nextcloud-talk-webhook"
assert cfg.rate_limit_max_requests == 10
assert cfg.rate_limit_window_s == 60
assert cfg.rate_limit_lockout_s == 300
assert cfg.max_body_size == 1 * 1024 * 1024
assert cfg.pre_auth_max_body_size == 64 * 1024
def test_custom_values(self):
cfg = NextcloudTalkWebhookConfig(
port=9999,
host="127.0.0.1",
path="/custom-webhook",
rateLimitMaxRequests=5,
rateLimitWindowS=30,
rateLimitLockoutS=60,
maxBodySize=2 * 1024 * 1024,
preAuthMaxBodySize=128 * 1024,
)
assert cfg.port == 9999
assert cfg.host == "127.0.0.1"
assert cfg.path == "/custom-webhook"
assert cfg.rate_limit_max_requests == 5
assert cfg.rate_limit_window_s == 30
assert cfg.rate_limit_lockout_s == 60
assert cfg.max_body_size == 2 * 1024 * 1024
assert cfg.pre_auth_max_body_size == 128 * 1024
class TestValidateConfigEdgeCases:
def test_invalid_group_policy(self):
with pytest.raises(ValueError, match="group_policy"):
validate_config({
"serverUrl": "https://nc.example.com",
"botUser": "bot",
"appPassword": "secret",
"groupPolicy": "unknown",
})
def test_invalid_chunk_mode(self):
with pytest.raises(ValueError, match="chunk_mode"):
validate_config({
"serverUrl": "https://nc.example.com",
"botUser": "bot",
"appPassword": "secret",
"chunkMode": "invalid_mode",
})
def test_empty_server_url_passes_validation(self):
config = validate_config({
"serverUrl": "",
"botUser": "bot",
"appPassword": "secret",
})
assert config.server_url == ""
def test_http_url_allowed(self):
config = validate_config({
"serverUrl": "http://nc.example.com",
"botUser": "bot",
"appPassword": "secret",
})
assert config.server_url == "http://nc.example.com"
def test_all_policies_valid(self):
for policy in ("open", "pairing", "allowlist", "disabled"):
config = validate_config({
"serverUrl": "https://nc.example.com",
"botUser": "bot",
"appPassword": "secret",
"dmPolicy": policy,
})
assert config.dm_policy == policy
def test_all_group_policies_valid(self):
for policy in ("open", "allowlist", "disabled"):
config = validate_config({
"serverUrl": "https://nc.example.com",
"botUser": "bot",
"appPassword": "secret",
"groupPolicy": policy,
})
assert config.group_policy == policy
def test_all_chunk_modes_valid(self):
for mode in ("split", "stop", "truncate"):
config = validate_config({
"serverUrl": "https://nc.example.com",
"botUser": "bot",
"appPassword": "secret",
"chunkMode": mode,
})
assert config.chunk_mode == mode