83 lines
2.4 KiB
Python
83 lines
2.4 KiB
Python
from datetime import datetime, timezone
|
|
|
|
import pytest
|
|
from bson import ObjectId
|
|
|
|
from app.services import human_handoff_service
|
|
from app.services.handoff_delivery import (
|
|
STATUS_AMBIGUOUS,
|
|
STATUS_PENDING,
|
|
STATUS_SENT,
|
|
process_handoff_delivery_once,
|
|
)
|
|
|
|
|
|
class FakeJobs:
|
|
def __init__(self):
|
|
self.job = {
|
|
"_id": ObjectId(),
|
|
"kind": "MIRROR_TO_HUMAN",
|
|
"account_id": "account-1",
|
|
"handoff_id": ObjectId(),
|
|
"source_message_id": ObjectId(),
|
|
"status": STATUS_PENDING,
|
|
"created_at": datetime.now(timezone.utc),
|
|
"next_attempt_at": datetime.now(timezone.utc),
|
|
}
|
|
|
|
async def find_one_and_update(self, query, update, **kwargs):
|
|
if self.job["status"] != STATUS_PENDING:
|
|
return None
|
|
self.job["status"] = "SENDING"
|
|
self.job["attempt_count"] = self.job.get("attempt_count", 0) + 1
|
|
return dict(self.job)
|
|
|
|
async def update_one(self, query, update):
|
|
self.job.update(update.get("$set", {}))
|
|
|
|
|
|
class FakeMessages:
|
|
async def update_one(self, query, update):
|
|
return None
|
|
|
|
|
|
class FakeDatabase:
|
|
def __init__(self):
|
|
self.handoff_delivery_jobs = FakeJobs()
|
|
self.messages = FakeMessages()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delivery_job_is_claimed_and_sent_once(monkeypatch):
|
|
database = FakeDatabase()
|
|
calls = 0
|
|
|
|
async def deliver(database, job):
|
|
nonlocal calls
|
|
calls += 1
|
|
return ObjectId()
|
|
|
|
monkeypatch.setattr(human_handoff_service, "deliver_handoff_job", deliver)
|
|
|
|
assert await process_handoff_delivery_once(database) is True
|
|
assert await process_handoff_delivery_once(database) is False
|
|
assert calls == 1
|
|
assert database.handoff_delivery_jobs.job["status"] == STATUS_SENT
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_ambiguous_smtp_failure_is_not_automatically_retried(monkeypatch):
|
|
database = FakeDatabase()
|
|
calls = 0
|
|
|
|
async def deliver(database, job):
|
|
nonlocal calls
|
|
calls += 1
|
|
raise TimeoutError("SMTP acknowledgement lost")
|
|
|
|
monkeypatch.setattr(human_handoff_service, "deliver_handoff_job", deliver)
|
|
|
|
assert await process_handoff_delivery_once(database) is True
|
|
assert await process_handoff_delivery_once(database) is False
|
|
assert calls == 1
|
|
assert database.handoff_delivery_jobs.job["status"] == STATUS_AMBIGUOUS
|