import pytest from bson import ObjectId from app.services.human_handoff_service import ( MESSAGE_SCOPE_EXTERNAL, MESSAGE_SCOPE_HANDOFF, resolve_handoff_from_inbound, ) class FakeCollection: def __init__(self, documents=None): self.documents = list(documents or []) async def find_one(self, query): for document in self.documents: if all(document.get(key) == value for key, value in query.items()): return document if "$ne" in query.get("status", {}): if document.get("status") == query["status"]["$ne"]: continue for document in self.documents: matches = True for key, value in query.items(): if key == "status" and isinstance(value, dict) and "$ne" in value: if document.get("status") == value["$ne"]: matches = False break elif document.get(key) != value: matches = False break if matches: return document return None def find(self, query): class Cursor: def __init__(self, items): self.items = items async def to_list(self, length): return self.items[:length] filtered = [ document for document in self.documents if all(document.get(key) == value for key, value in query.items()) ] return Cursor(filtered) class FakeDatabase: def __init__(self): self.human_handoff_rules = FakeCollection() self.messages = FakeCollection() self.mailbox_entries = FakeCollection() self.human_handoffs = FakeCollection() @pytest.mark.asyncio async def test_resolve_handoff_requires_owner_and_thread_context(): database = FakeDatabase() handoff_thread_id = ObjectId() message_id = ObjectId() database.human_handoff_rules.documents = [ { "account_id": "acct-1", "owner_email": "owner@gmail.com", "active": True, } ] database.messages.documents = [ { "_id": message_id, "message_id": "", "message_scope": MESSAGE_SCOPE_HANDOFF, } ] database.mailbox_entries.documents = [ { "account_id": "acct-1", "message_id": message_id, "thread_id": handoff_thread_id, "message_scope": MESSAGE_SCOPE_HANDOFF, } ] database.human_handoffs.documents = [ { "_id": ObjectId(), "account_id": "acct-1", "handoff_thread_id": handoff_thread_id, "human_email": "owner@gmail.com", "status": "WAITING_FOR_HUMAN", } ] handoff = await resolve_handoff_from_inbound( database, account_id="acct-1", agent_email="support@gentic.email", sender_address="owner@gmail.com", in_reply_to="", references=[], ) assert handoff is not None @pytest.mark.asyncio async def test_resolve_handoff_rejects_unknown_sender(): database = FakeDatabase() handoff = await resolve_handoff_from_inbound( database, account_id="acct-1", agent_email="support@gentic.email", sender_address="stranger@example.com", in_reply_to="", references=[], ) assert handoff is None @pytest.mark.asyncio async def test_external_scope_constant_isolated_from_handoff(): assert MESSAGE_SCOPE_EXTERNAL != MESSAGE_SCOPE_HANDOFF