Files
banban/talkingq-url/tests/test_sms_notification.py
2026-06-03 15:14:01 +08:00

137 lines
4.9 KiB
Python

import pytest
from banban.service.sms_notification import SmsNotificationService
class FakeSession:
async def execute(self, statement, params):
del statement, params
return FakeResult()
async def close(self):
pass
class FakeResult:
def mappings(self):
return self
def all(self):
return [
{"phone": "13800138000"},
{"phone": "13800138000"},
{"phone": ""},
{"phone": "13900139000"},
]
def first(self):
return {
"child_name": "孩子",
"address": "杭州市",
"lat": None,
"lng": None,
}
def configure_enabled_sms(monkeypatch):
monkeypatch.setattr("banban.service.sms_notification.settings.sms_enabled", True)
monkeypatch.setattr("banban.service.sms_notification.settings.sms_provider", "aliyun")
monkeypatch.setattr("banban.service.sms_notification.settings.sms_dry_run", False)
monkeypatch.setattr("banban.service.sms_notification.settings.sms_alarm_dedup_seconds", 300)
monkeypatch.setattr("banban.service.sms_notification.settings.sms_leave_message_dedup_seconds", 60)
monkeypatch.setattr("banban.service.sms_notification.settings.aliyun_sms_access_key_id", "access-key-id")
monkeypatch.setattr("banban.service.sms_notification.settings.aliyun_sms_access_key_secret", "access-key-secret")
monkeypatch.setattr("banban.service.sms_notification.settings.aliyun_sms_sign_name", "短信签名")
monkeypatch.setattr("banban.service.sms_notification.settings.aliyun_sms_template_code", "SMS_507185027")
monkeypatch.setattr("banban.service.sms_notification.settings.aliyun_sms_alarm_template_code", "")
monkeypatch.setattr("banban.service.sms_notification.settings.aliyun_sms_leave_message_template_code", "")
@pytest.mark.asyncio
async def test_notify_alarm_sends_to_unique_family_phone_numbers(monkeypatch):
configure_enabled_sms(monkeypatch)
service = SmsNotificationService()
sent = []
async def fake_get_session():
return FakeSession()
async def fake_send_sms(*, phone_number, template_code, template_params):
sent.append(
{
"phone_number": phone_number,
"template_code": template_code,
"template_params": template_params,
}
)
return {"ok": True, "code": "OK", "message": "OK", "request_id": "request-id"}
monkeypatch.setattr(service, "get_session", fake_get_session)
monkeypatch.setattr(service, "_send_sms", fake_send_sms)
await service.notify_alarm(
device_id="TalkingQ_XQSN00001005",
alarm_id=7,
child_name="孩子",
address="杭州市",
)
assert [item["phone_number"] for item in sent] == ["13800138000", "13900139000"]
assert all(item["template_code"] == "SMS_507185027" for item in sent)
assert sent[0]["template_params"]["conference"] == "孩子"
assert sent[0]["template_params"]["address"] == "杭州市"
@pytest.mark.asyncio
async def test_notify_alarm_dedupes_same_device_and_phone(monkeypatch):
configure_enabled_sms(monkeypatch)
service = SmsNotificationService()
sent = []
async def fake_get_session():
return FakeSession()
async def fake_send_sms(*, phone_number, template_code, template_params):
del template_code, template_params
sent.append(phone_number)
return {"ok": True, "code": "OK", "message": "OK", "request_id": "request-id"}
monkeypatch.setattr(service, "get_session", fake_get_session)
monkeypatch.setattr(service, "_send_sms", fake_send_sms)
await service.notify_alarm(device_id="TalkingQ_XQSN00001005", alarm_id=7)
await service.notify_alarm(device_id="TalkingQ_XQSN00001005", alarm_id=8)
assert sent == ["13800138000", "13900139000"]
@pytest.mark.asyncio
async def test_notify_leave_message_disabled_skips_database_and_send(monkeypatch):
monkeypatch.setattr("banban.service.sms_notification.settings.sms_enabled", False)
service = SmsNotificationService()
async def fail_get_session():
raise AssertionError("disabled SMS should not query database")
monkeypatch.setattr(service, "get_session", fail_get_session)
await service.notify_leave_message(device_id="TalkingQ_XQSN00001005", child_name="孩子")
@pytest.mark.asyncio
async def test_best_effort_swallows_send_errors(monkeypatch):
configure_enabled_sms(monkeypatch)
service = SmsNotificationService()
async def fake_get_session():
return FakeSession()
async def fake_send_sms(*, phone_number, template_code, template_params):
del phone_number, template_code, template_params
raise RuntimeError("provider failed")
monkeypatch.setattr(service, "get_session", fake_get_session)
monkeypatch.setattr(service, "_send_sms", fake_send_sms)
await service.notify_alarm_best_effort(device_id="TalkingQ_XQSN00001005", alarm_id=7)