ForcePilot/backend/test/unit/channels/test_twitch_config_schema.py
Kris 69fe97a90d test: 批量修复并新增单元测试用例
1. 移除Telegram格式化测试中未使用的导入项
2. 修复Teams测试用例,添加monkeypatch参数并配置通配符开关
3. 更新钉钉适配器测试,替换弃用的流属性检查
4. 修正Twitch规范化测试,更新ROOMSTATE测试逻辑
5. 重构会话映射测试,完善数据库执行结果模拟
6. 格式化Slack块构建测试的长参数调用
7. 修复LINE适配器测试,更新能力断言和异步锁使用
8. 修正Slack会话解析测试,修复聊天类型判断错误
9. 更新能力测试,补充缺失的字段检查
10. 修复Matrix适配器测试,修正位置参数和配置校验逻辑
11. 为飞书分析模块测试添加跳过标记
12. 新增微信能力、限流、链接格式、会话路由等模块的单元测试
13. 修复Twitch适配器导入路径和测试断言
14. 新增Discord Webhook、Nextcloud Talk、Signal多账户等模块的单元测试
15. 修复Manager阶段测试的导入路径
16. 新增iMessage异常和命令处理的单元测试
17. 新增Nostr健康检查和相关模块的单元测试
18. 新增Signal守护进程和SSE重连相关测试
2026-05-13 16:43:01 +08:00

323 lines
11 KiB
Python

from __future__ import annotations
from yuxi.channels.adapters.twitch.config_schema import (
TwitchAccountSchema,
TwitchConfigSchema,
super_refine_twitch_config,
validate_twitch_config,
)
class TestTwitchConfigSchemaDefaults:
def test_defaults(self):
schema = TwitchConfigSchema()
assert schema.bot_username == ""
assert schema.access_token == ""
assert schema.client_id == ""
assert schema.channels == []
assert schema.group_policy == "open"
assert schema.rate_limit == 20
assert schema.rate_window == 30
assert schema.irc_host == "irc.chat.twitch.tv"
assert schema.irc_port == 6697
assert schema.strip_markdown is True
assert schema.dm_policy == "pairing"
assert schema.silent is False
assert schema.prefer_helix_send is False
def test_account_schema_defaults(self):
schema = TwitchAccountSchema()
assert schema.bot_username == ""
assert schema.access_token == ""
assert schema.channels == []
assert schema.group_policy == "open"
assert schema.rate_limit == 20
class TestTwitchConfigSchemaValidation:
def test_valid_group_policy_accepted(self):
schema = TwitchConfigSchema(group_policy="allowlist")
assert schema.group_policy == "allowlist"
def test_rate_limit_minimum(self):
schema = TwitchConfigSchema(rate_limit=1)
assert schema.rate_limit == 1
def test_valid_irc_port(self):
schema = TwitchConfigSchema(irc_port=6697)
assert schema.irc_port == 6697
def test_accounts_dict(self):
schema = TwitchConfigSchema(accounts={"default": TwitchAccountSchema(bot_username="bot1")})
assert "default" in schema.accounts
assert schema.accounts["default"].bot_username == "bot1"
def test_require_mention_default(self):
schema = TwitchConfigSchema()
assert schema.require_mention is True
def test_pairing_disabled_default(self):
schema = TwitchConfigSchema()
assert schema.pairing_enabled is False
def test_response_prefix_default(self):
schema = TwitchConfigSchema()
assert schema.response_prefix == ""
class TestValidateTwitchConfig:
def test_valid_config_no_errors(self):
config = {
"bot_username": "testbot",
"access_token": "oauth:abc",
"client_id": "client123",
"channels": ["test_channel"],
}
errors = validate_twitch_config(config)
assert errors == []
def test_missing_client_id(self):
errors = validate_twitch_config({"bot_username": "bot", "access_token": "tok", "channels": ["ch"]})
assert any("client_id" in e for e in errors)
def test_missing_access_token(self):
errors = validate_twitch_config({"bot_username": "bot", "client_id": "cid", "channels": ["ch"]})
assert any("access_token" in e for e in errors)
def test_missing_bot_username(self):
errors = validate_twitch_config({"access_token": "tok", "client_id": "cid", "channels": ["ch"]})
assert any("bot_username" in e for e in errors)
def test_missing_channels(self):
errors = validate_twitch_config({"bot_username": "bot", "access_token": "tok", "client_id": "cid"})
assert any("channel" in e for e in errors)
def test_invalid_group_policy(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"group_policy": "invalid_policy",
}
errors = validate_twitch_config(config)
assert any("group_policy" in e for e in errors)
def test_allowlist_with_empty_allow_from(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"group_policy": "allowlist",
}
errors = validate_twitch_config(config)
assert any("allowlist" in e for e in errors)
def test_allowlist_with_per_channel_allow_from_is_ok(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"group_policy": "allowlist",
"channels_config": {"ch": {"allow_from": ["user1"]}},
}
errors = validate_twitch_config(config)
assert not any("allowlist" in e for e in errors)
def test_invalid_role_in_allowed_roles(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"allowedRoles": ["admin"],
}
errors = validate_twitch_config(config)
assert any("allowedRoles" in e for e in errors)
def test_all_roles_with_allowlist_redundant(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"allowedRoles": ["all"],
"group_policy": "allowlist",
"group_allow_from": ["user1"],
}
errors = validate_twitch_config(config)
assert any("redundant" in e for e in errors)
def test_invalid_rate_limit(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"rate_limit": 0,
}
errors = validate_twitch_config(config)
assert any("rate_limit" in e for e in errors)
def test_invalid_irc_port(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"irc_port": 99999,
}
errors = validate_twitch_config(config)
assert any("irc_port" in e for e in errors)
def test_account_missing_bot_username(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"accounts": {"acct1": {"access_token": "tok"}},
}
errors = validate_twitch_config(config)
assert any("bot_username" in e for e in errors)
def test_account_missing_access_token(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"accounts": {"acct1": {"bot_username": "bot2"}},
}
errors = validate_twitch_config(config)
assert any("access_token" in e for e in errors)
def test_default_account_not_found(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"accounts": {"acct1": {"bot_username": "b", "access_token": "t"}},
"defaultAccount": "nonexistent",
}
errors = validate_twitch_config(config)
assert any("defaultAccount" in e for e in errors)
def test_invalid_dm_policy(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"dm_policy": "block_all",
}
errors = validate_twitch_config(config)
assert any("dm_policy" in e for e in errors)
def test_probe_timeout_too_small(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"probe_timeout_ms": 500,
}
errors = validate_twitch_config(config)
assert any("probe_timeout" in e for e in errors)
def test_valid_roles_accepted(self):
config = {
"bot_username": "bot",
"access_token": "tok",
"client_id": "cid",
"channels": ["ch"],
"allowedRoles": ["moderator", "vip", "subscriber"],
}
errors = validate_twitch_config(config)
assert errors == []
def test_empty_config_all_errors(self):
errors = validate_twitch_config({})
assert len(errors) >= 4
class TestSuperRefineTwitchConfig:
def test_converts_allowall_to_open(self):
config = {"group_policy": "allowall"}
refined = super_refine_twitch_config(config)
assert refined["group_policy"] == "open"
def test_converts_mention_only_to_mention(self):
config = {"group_policy": "mention_only"}
refined = super_refine_twitch_config(config)
assert refined["group_policy"] == "mention"
def test_adds_oauth_prefix(self):
config = {"access_token": "mytoken123"}
refined = super_refine_twitch_config(config)
assert refined["access_token"] == "oauth:mytoken123"
def test_preserves_existing_oauth_prefix(self):
config = {"access_token": "oauth:mytoken"}
refined = super_refine_twitch_config(config)
assert refined["access_token"] == "oauth:mytoken"
def test_strips_channel_hash_prefix(self):
config = {"channels": ["#testchannel", "@otherchannel", "plainchannel"]}
refined = super_refine_twitch_config(config)
assert refined["channels"] == ["testchannel", "otherchannel", "plainchannel"]
def test_account_tokens_normalized(self):
config = {
"access_token": "oauth:master",
"client_id": "master_cid",
"accounts": {
"acct1": {"bot_username": "b1", "access_token": "rawtoken"},
},
}
refined = super_refine_twitch_config(config)
assert refined["accounts"]["acct1"]["access_token"] == "oauth:rawtoken"
def test_account_channels_normalized(self):
config = {
"accounts": {
"acct1": {"bot_username": "b1", "access_token": "tok", "channels": ["#CH1", "@CH2"]},
},
}
refined = super_refine_twitch_config(config)
assert refined["accounts"]["acct1"]["channels"] == ["ch1", "ch2"]
def test_account_inherits_parent_fields(self):
config = {
"client_id": "parent_cid",
"rate_limit": 50,
"accounts": {
"acct1": {"bot_username": "b1", "access_token": "tok"},
},
}
refined = super_refine_twitch_config(config)
assert refined["accounts"]["acct1"]["client_id"] == "parent_cid"
assert refined["accounts"]["acct1"]["rate_limit"] == 50
def test_account_own_field_not_overwritten(self):
config = {
"client_id": "parent_cid",
"accounts": {
"acct1": {"bot_username": "b1", "access_token": "tok", "client_id": "own_cid"},
},
}
refined = super_refine_twitch_config(config)
assert refined["accounts"]["acct1"]["client_id"] == "own_cid"
def test_wildcard_allow_from_with_open_policy(self):
config = {"group_policy": "open", "group_allow_from": ["*"]}
refined = super_refine_twitch_config(config)
assert refined["group_policy"] == "open"
def test_skip_non_dict_account(self):
config = {"accounts": {"acct1": "not_a_dict"}}
refined = super_refine_twitch_config(config)
assert refined["accounts"]["acct1"] == "not_a_dict"