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