137 lines
4.9 KiB
Python
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)
|