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

123 lines
3.9 KiB
Python
Raw Normal View History

from __future__ import annotations
import asyncio
import pytest
from yuxi.channels.adapters.wechat.debounce import WeChatQueueDebounce
from yuxi.channels.models import (
ChannelIdentity,
ChannelMessage,
ChannelType,
ChatType,
)
def _make_msg(content: str) -> ChannelMessage:
return ChannelMessage(
identity=ChannelIdentity(
channel_id="wechat",
channel_type=ChannelType.WECHAT,
channel_user_id="u1",
channel_chat_id="c1",
),
content=content,
)
class TestWeChatQueueDebounce:
@pytest.fixture
def debouncer(self) -> WeChatQueueDebounce:
return WeChatQueueDebounce(debounce_ms=100)
@pytest.mark.asyncio
async def test_single_message_flushed(self, debouncer):
results: list[list[ChannelMessage]] = []
async def handler(msgs):
results.append(msgs)
msg = _make_msg("hello")
await debouncer.enqueue("session-1", msg, handler)
await asyncio.sleep(0.3)
assert len(results) == 1
assert len(results[0]) == 1
assert results[0][0].content == "hello"
@pytest.mark.asyncio
async def test_multiple_messages_merged(self, debouncer):
results: list[list[ChannelMessage]] = []
async def handler(msgs):
results.append(msgs)
for content in ["m1", "m2", "m3"]:
await debouncer.enqueue("session-1", _make_msg(content), handler)
await asyncio.sleep(0.02)
await asyncio.sleep(0.3)
assert len(results) == 1
assert [m.content for m in results[0]] == ["m1", "m2", "m3"]
@pytest.mark.asyncio
async def test_different_sessions_not_merged(self, debouncer):
results: list[tuple[str, str]] = []
async def make_handler(sid: str):
async def handler(msgs):
for m in msgs:
results.append((sid, m.content))
return handler
await debouncer.enqueue("session-a", _make_msg("a1"), await make_handler("session-a"))
await debouncer.enqueue("session-b", _make_msg("b1"), await make_handler("session-b"))
await debouncer.enqueue("session-a", _make_msg("a2"), await make_handler("session-a"))
await asyncio.sleep(0.3)
a_msgs = [c for s, c in results if s == "session-a"]
b_msgs = [c for s, c in results if s == "session-b"]
assert a_msgs == ["a1", "a2"]
assert b_msgs == ["b1"]
@pytest.mark.asyncio
async def test_consecutive_enqueues_reset_timer(self, debouncer):
debouncer_long = WeChatQueueDebounce(debounce_ms=300)
results: list[list[ChannelMessage]] = []
async def handler(msgs):
results.append(msgs)
await debouncer_long.enqueue("s1", _make_msg("first"), handler)
await asyncio.sleep(0.1)
await debouncer_long.enqueue("s1", _make_msg("second"), handler)
await asyncio.sleep(0.1)
await debouncer_long.enqueue("s1", _make_msg("third"), handler)
await asyncio.sleep(0.15)
assert len(results) == 0
await asyncio.sleep(0.3)
assert len(results) == 1
assert [m.content for m in results[0]] == ["first", "second", "third"]
@pytest.mark.asyncio
async def test_flush_all_clears_pending(self, debouncer):
results: list[list[ChannelMessage]] = []
async def handler(msgs):
results.append(msgs)
await debouncer.enqueue("session-1", _make_msg("m1"), handler)
await debouncer.enqueue("session-2", _make_msg("m2"), handler)
await debouncer.flush_all()
assert len(results) == 0
@pytest.mark.asyncio
async def test_debounce_ms_property(self):
debouncer = WeChatQueueDebounce(debounce_ms=500)
assert debouncer.debounce_ms == 500
@pytest.mark.asyncio
async def test_default_debounce_value(self):
debouncer = WeChatQueueDebounce()
assert debouncer.debounce_ms == 500