129 lines
4.5 KiB
Python
129 lines
4.5 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from datetime import datetime
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
|
||
|
|
from yuxi.channels.adapters.qqbot.thread_simulator import QQBotThreadSimulator
|
||
|
|
from yuxi.channels.adapters.irc.thread_simulator import IRCThreadSimulator
|
||
|
|
|
||
|
|
|
||
|
|
class TestQQBotThreadSimulator:
|
||
|
|
def test_resolve_c2c_thread_id(self):
|
||
|
|
simulator = QQBotThreadSimulator()
|
||
|
|
msg = {
|
||
|
|
"message_type": "c2c",
|
||
|
|
"author": {"id": "user_openid_123"},
|
||
|
|
"seq": 25,
|
||
|
|
}
|
||
|
|
tid = simulator.resolve_simulated_thread_id(msg)
|
||
|
|
assert "qqbot:c2c" in tid
|
||
|
|
assert "user_openid_123" in tid
|
||
|
|
assert "seq" in tid
|
||
|
|
|
||
|
|
def test_resolve_group_thread_id(self):
|
||
|
|
simulator = QQBotThreadSimulator()
|
||
|
|
msg = {
|
||
|
|
"message_type": "group",
|
||
|
|
"group_id": "group_456",
|
||
|
|
"seq": 30,
|
||
|
|
}
|
||
|
|
tid = simulator.resolve_simulated_thread_id(msg)
|
||
|
|
assert "qqbot:group" in tid
|
||
|
|
assert "group_456" in tid
|
||
|
|
|
||
|
|
def test_build_thread_context_empty(self):
|
||
|
|
simulator = QQBotThreadSimulator()
|
||
|
|
context = simulator.build_thread_context(
|
||
|
|
{"id": "m1", "author": {"username": "alice"}, "content": "hello"},
|
||
|
|
"session_c2c_openid",
|
||
|
|
)
|
||
|
|
assert context == ""
|
||
|
|
|
||
|
|
def test_build_thread_context_has_history(self):
|
||
|
|
simulator = QQBotThreadSimulator(window_size=5)
|
||
|
|
session_key = "session_c2c_openid"
|
||
|
|
simulator.build_thread_context(
|
||
|
|
{"id": "m1", "author": {"username": "alice"}, "content": "msg1"},
|
||
|
|
session_key,
|
||
|
|
)
|
||
|
|
context = simulator.build_thread_context(
|
||
|
|
{"id": "m2", "author": {"username": "bob"}, "content": "msg2"},
|
||
|
|
session_key,
|
||
|
|
)
|
||
|
|
assert "alice: msg1" in context
|
||
|
|
assert "bob: msg2" not in context
|
||
|
|
|
||
|
|
def test_context_window_size_limit(self):
|
||
|
|
simulator = QQBotThreadSimulator(window_size=3)
|
||
|
|
session_key = "session_test"
|
||
|
|
for i in range(5):
|
||
|
|
simulator.build_thread_context(
|
||
|
|
{"id": f"m{i}", "author": {"username": f"user{i}"}, "content": f"msg{i}"},
|
||
|
|
session_key,
|
||
|
|
)
|
||
|
|
context = simulator.build_thread_context(
|
||
|
|
{"id": "m_new", "author": {"username": "new"}, "content": "latest"},
|
||
|
|
session_key,
|
||
|
|
)
|
||
|
|
assert "user0: msg0" not in context
|
||
|
|
|
||
|
|
def test_get_context_as_history(self):
|
||
|
|
simulator = QQBotThreadSimulator()
|
||
|
|
session_key = "session_test"
|
||
|
|
simulator.build_thread_context(
|
||
|
|
{"id": "m1", "author": {"username": "alice"}, "content": "hello"},
|
||
|
|
session_key,
|
||
|
|
)
|
||
|
|
history = simulator.get_context_as_history(session_key)
|
||
|
|
assert len(history) == 1
|
||
|
|
assert history[0].sender_name == "alice"
|
||
|
|
|
||
|
|
|
||
|
|
class TestIRCThreadSimulator:
|
||
|
|
def test_add_channel_message(self):
|
||
|
|
sim = IRCThreadSimulator(context_size=3)
|
||
|
|
sim.add_message("#general", "alice", "hello world")
|
||
|
|
context = sim.get_context_text("#general")
|
||
|
|
assert "alice" in context
|
||
|
|
assert "hello world" in context
|
||
|
|
|
||
|
|
def test_add_dm_message(self):
|
||
|
|
sim = IRCThreadSimulator(context_size=3)
|
||
|
|
sim.add_message("alice", "alice", "hi bot", is_dm=True)
|
||
|
|
context = sim.get_context_text("alice", is_dm=True)
|
||
|
|
assert "alice" in context
|
||
|
|
assert "hi bot" in context
|
||
|
|
|
||
|
|
def test_context_size_limit(self):
|
||
|
|
sim = IRCThreadSimulator(context_size=2)
|
||
|
|
for i in range(4):
|
||
|
|
sim.add_message("#general", f"user{i}", f"msg{i}")
|
||
|
|
context = sim.get_context_text("#general")
|
||
|
|
assert "user0" not in context
|
||
|
|
assert "user2" in context
|
||
|
|
assert "user3" in context
|
||
|
|
|
||
|
|
def test_format_reply_prefix(self):
|
||
|
|
result = IRCThreadSimulator.format_reply_prefix("bob")
|
||
|
|
assert result == "@bob: "
|
||
|
|
|
||
|
|
def test_clear_context(self):
|
||
|
|
sim = IRCThreadSimulator()
|
||
|
|
sim.add_message("#general", "alice", "hello")
|
||
|
|
sim.clear_context("#general")
|
||
|
|
context = sim.get_context_text("#general")
|
||
|
|
assert context == ""
|
||
|
|
|
||
|
|
def test_channel_dm_isolation(self):
|
||
|
|
sim = IRCThreadSimulator()
|
||
|
|
sim.add_message("#general", "alice", "public msg")
|
||
|
|
sim.add_message("alice", "alice", "private msg", is_dm=True)
|
||
|
|
|
||
|
|
channel_ctx = sim.get_context_text("#general")
|
||
|
|
dm_ctx = sim.get_context_text("alice", is_dm=True)
|
||
|
|
|
||
|
|
assert "public msg" in channel_ctx
|
||
|
|
assert "private msg" not in channel_ctx
|
||
|
|
assert "private msg" in dm_ctx
|
||
|
|
assert "public msg" not in dm_ctx
|