新增了Twitch、Telegram、Discord、Slack、Mattermost、WeChat、Zalo等多渠道的单元测试用例,覆盖了令牌处理、速率限制、消息去重、会话解析、格式转换、安全策略等模块 同时在测试配置中添加了测试用的OpenAI API密钥环境变量
122 lines
4.4 KiB
Python
122 lines
4.4 KiB
Python
"""P0优化验证测试: dedup, merge_text, media validation, button styles"""
|
|
|
|
import hashlib
|
|
|
|
from yuxi.channels.adapters.feishu.cards import resolve_button_type
|
|
from yuxi.channels.adapters.feishu.dedup import FeishuDedupStore
|
|
from yuxi.channels.adapters.feishu.media import MediaSizeError, validate_media_size
|
|
from yuxi.channels.adapters.feishu.stream import merge_streaming_text
|
|
from yuxi.channels.adapters.feishu.verify import check_webhook_rate_limit, verify_and_decrypt_webhook
|
|
|
|
|
|
class TestFeishuP0Enhancements:
|
|
def test_dedup_has_processed(self):
|
|
store = FeishuDedupStore()
|
|
event = {
|
|
"event": {"message": {"message_id": "msg1"}, "event_id": "evt1"},
|
|
"event_type": "im.message.receive_v1",
|
|
}
|
|
assert not store.has_processed(event)
|
|
store.record_processed(event)
|
|
assert store.has_processed(event)
|
|
store.finalize_processing(event)
|
|
assert store.has_processed(event)
|
|
|
|
def test_dedup_different_events(self):
|
|
store = FeishuDedupStore()
|
|
event1 = {
|
|
"event": {"message": {"message_id": "msg1"}, "event_id": "evt1"},
|
|
"event_type": "im.message.receive_v1",
|
|
}
|
|
event2 = {
|
|
"event": {"message": {"message_id": "msg2"}, "event_id": "evt2"},
|
|
"event_type": "im.message.receive_v1",
|
|
}
|
|
store.finalize_processing(event1)
|
|
assert store.has_processed(event1)
|
|
assert not store.has_processed(event2)
|
|
|
|
def test_rate_limit_enforced(self):
|
|
for _ in range(1000):
|
|
assert check_webhook_rate_limit("test_ip_limit")
|
|
assert not check_webhook_rate_limit("test_ip_limit")
|
|
|
|
def test_merge_startswith(self):
|
|
assert merge_streaming_text("", "Hello") == "Hello"
|
|
assert merge_streaming_text("Hello", "Hello World") == "Hello World"
|
|
|
|
def test_merge_existing_contains_prefix(self):
|
|
assert merge_streaming_text("Hello World", "Hello") == "Hello World"
|
|
|
|
def test_merge_concatenation(self):
|
|
assert merge_streaming_text("Hello, ", "World") == "Hello, World"
|
|
|
|
def test_merge_with_prefix_overlap(self):
|
|
assert merge_streaming_text("today is", "is lovely") == "today is lovely"
|
|
|
|
def test_media_size_valid(self):
|
|
validate_media_size(b"x" * 512, max_mb=1)
|
|
|
|
def test_media_size_invalid(self):
|
|
try:
|
|
validate_media_size(b"x" * (2 * 1024 * 1024), max_mb=1)
|
|
assert False, "Should have raised MediaSizeError"
|
|
except MediaSizeError:
|
|
pass
|
|
|
|
def test_button_type_default(self):
|
|
assert resolve_button_type(None) == "default"
|
|
assert resolve_button_type("") == "default"
|
|
|
|
def test_button_type_primary(self):
|
|
assert resolve_button_type("primary") == "primary"
|
|
|
|
def test_button_type_danger(self):
|
|
assert resolve_button_type("danger") == "danger"
|
|
|
|
def test_button_type_unknown(self):
|
|
assert resolve_button_type("unknown") == "default"
|
|
|
|
def test_verify_signature_ok(self):
|
|
body = b"{test: true}"
|
|
ts = "1234567890"
|
|
nonce = "abc"
|
|
key = "secret"
|
|
raw = f"{ts}{nonce}{key}".encode() + body
|
|
sig = hashlib.sha256(raw).hexdigest()
|
|
headers = {
|
|
"X-Lark-Request-Timestamp": ts,
|
|
"X-Lark-Request-Nonce": nonce,
|
|
"X-Lark-Signature": sig,
|
|
}
|
|
ok, result_body, status = verify_and_decrypt_webhook(headers, body, key, "test_p0_verify")
|
|
assert ok
|
|
assert status == "ok"
|
|
assert result_body == body
|
|
|
|
def test_verify_signature_bad(self):
|
|
body = b"{test: true}"
|
|
headers = {
|
|
"X-Lark-Request-Timestamp": "bad",
|
|
"X-Lark-Request-Nonce": "bad",
|
|
"X-Lark-Signature": "bad",
|
|
}
|
|
ok, result_body, status = verify_and_decrypt_webhook(headers, body, "", "test_p0_verify2")
|
|
assert not ok
|
|
assert status == "signature_mismatch"
|
|
|
|
def test_oversized_body_rejected(self):
|
|
huge_body = b"x" * (11 * 1024 * 1024)
|
|
ts = "1234567890"
|
|
nonce = "abc"
|
|
key = "secret"
|
|
raw = f"{ts}{nonce}{key}".encode() + huge_body
|
|
sig = hashlib.sha256(raw).hexdigest()
|
|
headers = {
|
|
"X-Lark-Request-Timestamp": ts,
|
|
"X-Lark-Request-Nonce": nonce,
|
|
"X-Lark-Signature": sig,
|
|
}
|
|
ok, _, status = verify_and_decrypt_webhook(headers, huge_body, key, "test_p0_size")
|
|
assert not ok
|
|
assert status == "signature_mismatch" |