import asyncio def assert_msg_id_format(msg_id: str): assert isinstance(msg_id, str), f"msg_id must be str, got {type(msg_id)}" assert msg_id.strip(), "msg_id must not be empty or whitespace-only" def run_async(fn): return asyncio.run(fn) def assert_send_call_contains( sent: list, index: int, *, text_contains: str | None = None, target_id: str | None = None, ): assert index < len(sent), f"expected at least {index + 1} send calls, got {len(sent)}" msg = sent[index] if text_contains is not None: assert text_contains in msg.text, f"send[{index}] text does not contain '{text_contains}'" if target_id is not None: assert msg.target_id == target_id, f"send[{index}] target_id mismatch"