forked from erp-dev/erp
192 lines
7.4 KiB
Python
192 lines
7.4 KiB
Python
from unittest.mock import patch
|
||
|
||
from django.test import TestCase
|
||
|
||
from basic_info.models import Merchant, MerchantTypeEnum
|
||
from mission.models import MissionCategory
|
||
from notifier.models import NotificationEventKeyEnum, Notifier, NotifierChannelEnum, NotifierRoute
|
||
from notifier.services import (
|
||
dispatch_notification_event,
|
||
enqueue_notification_event,
|
||
render_notification_content,
|
||
send_notification_with_notifier,
|
||
)
|
||
|
||
|
||
class NotifierServiceTestCase(TestCase):
|
||
def setUp(self):
|
||
self.merchant = Merchant.objects.create(name="通知商户", type=MerchantTypeEnum.STORE)
|
||
self.general_category = MissionCategory.objects.create(merchant=self.merchant, name="通用")
|
||
self.after_sale_category = MissionCategory.objects.create(merchant=self.merchant, name="售后")
|
||
self.notifier = Notifier.objects.create(
|
||
merchant=self.merchant,
|
||
name="任务创建通知",
|
||
channel=NotifierChannelEnum.WECOM_WEBHOOK,
|
||
template_key="mission_created",
|
||
config={"key": "abc123", "msgtype": "markdown"},
|
||
)
|
||
self.global_route = NotifierRoute.objects.create(
|
||
merchant=self.merchant,
|
||
notifier=self.notifier,
|
||
event_key=NotificationEventKeyEnum.MISSION_CREATED,
|
||
)
|
||
|
||
def test_render_notification_content(self):
|
||
content = render_notification_content(
|
||
notifier=self.notifier,
|
||
payload={
|
||
"mission_id": 12,
|
||
"created_by_name": "张三",
|
||
"creator_name": "张三",
|
||
"category_name": "通用",
|
||
"is_urgent": False,
|
||
"participant_names_display": "李四、王五",
|
||
"description": "检查打印质量",
|
||
},
|
||
)
|
||
|
||
self.assertIn("任务已创建", content)
|
||
self.assertIn("任务ID:12", content)
|
||
self.assertIn("创建人:张三", content)
|
||
|
||
@patch("notifier.backends.send_wecom_webhook_message")
|
||
def test_send_notification_with_notifier_uses_wecom_backend(self, mock_send):
|
||
mock_send.return_value.ok = True
|
||
mock_send.return_value.errcode = 0
|
||
mock_send.return_value.errmsg = "ok"
|
||
|
||
result = send_notification_with_notifier(
|
||
notifier=self.notifier,
|
||
payload={
|
||
"mission_id": 12,
|
||
"created_by_name": "张三",
|
||
"creator_name": "张三",
|
||
"category_name": "通用",
|
||
"is_urgent": True,
|
||
"participant_names_display": "无",
|
||
"description": "检查打印质量",
|
||
},
|
||
)
|
||
|
||
self.assertEqual(result["status"], "sent")
|
||
self.assertEqual(result["channel"], NotifierChannelEnum.WECOM_WEBHOOK)
|
||
mock_send.assert_called_once()
|
||
|
||
@patch("notifier.services.send_notification_with_notifier")
|
||
def test_dispatch_notification_event_filters_by_route_event_and_enabled(self, mock_send):
|
||
mock_send.side_effect = lambda *, notifier, payload: {
|
||
"notifier_id": notifier.id,
|
||
"status": "sent",
|
||
}
|
||
replied_notifier = Notifier.objects.create(
|
||
merchant=self.merchant,
|
||
name="任务回应通知",
|
||
channel=NotifierChannelEnum.WECOM_WEBHOOK,
|
||
template_key="mission_replied",
|
||
config={"key": "def456"},
|
||
)
|
||
NotifierRoute.objects.create(
|
||
merchant=self.merchant,
|
||
notifier=replied_notifier,
|
||
event_key=NotificationEventKeyEnum.MISSION_REPLIED,
|
||
)
|
||
disabled_notifier = Notifier.objects.create(
|
||
merchant=self.merchant,
|
||
name="停用通知器",
|
||
channel=NotifierChannelEnum.WECOM_WEBHOOK,
|
||
template_key="mission_created",
|
||
is_enabled=False,
|
||
config={"key": "ghi789"},
|
||
)
|
||
NotifierRoute.objects.create(
|
||
merchant=self.merchant,
|
||
notifier=disabled_notifier,
|
||
event_key=NotificationEventKeyEnum.MISSION_CREATED,
|
||
)
|
||
|
||
results = dispatch_notification_event(
|
||
event_key=NotificationEventKeyEnum.MISSION_CREATED,
|
||
merchant_id=self.merchant.id,
|
||
payload={"mission_id": 99},
|
||
)
|
||
|
||
self.assertEqual(
|
||
results,
|
||
[
|
||
{
|
||
"notifier_id": self.notifier.id,
|
||
"status": "sent",
|
||
"event_key": NotificationEventKeyEnum.MISSION_CREATED,
|
||
"route_id": self.global_route.id,
|
||
"route_event_key": NotificationEventKeyEnum.MISSION_CREATED,
|
||
"route_mission_category_id": None,
|
||
}
|
||
],
|
||
)
|
||
self.assertEqual(mock_send.call_count, 1)
|
||
self.assertEqual(mock_send.call_args.kwargs["notifier"].id, self.notifier.id)
|
||
|
||
@patch("notifier.services.send_notification_with_notifier")
|
||
def test_dispatch_notification_event_prefers_category_specific_route(self, mock_send):
|
||
mock_send.side_effect = lambda *, notifier, payload: {
|
||
"notifier_id": notifier.id,
|
||
"status": "sent",
|
||
}
|
||
specific_route = NotifierRoute.objects.create(
|
||
merchant=self.merchant,
|
||
notifier=self.notifier,
|
||
event_key=NotificationEventKeyEnum.MISSION_CREATED,
|
||
mission_category=self.after_sale_category,
|
||
)
|
||
|
||
results = dispatch_notification_event(
|
||
event_key=NotificationEventKeyEnum.MISSION_CREATED,
|
||
merchant_id=self.merchant.id,
|
||
payload={"mission_id": 99, "category_id": self.after_sale_category.id},
|
||
)
|
||
|
||
self.assertEqual(mock_send.call_count, 1)
|
||
self.assertEqual(results[0]["route_id"], specific_route.id)
|
||
self.assertEqual(results[0]["route_mission_category_id"], self.after_sale_category.id)
|
||
|
||
@patch("notifier.services.send_notification_with_notifier")
|
||
def test_dispatch_notification_event_falls_back_to_global_route(self, mock_send):
|
||
mock_send.side_effect = lambda *, notifier, payload: {
|
||
"notifier_id": notifier.id,
|
||
"status": "sent",
|
||
}
|
||
|
||
results = dispatch_notification_event(
|
||
event_key=NotificationEventKeyEnum.MISSION_CREATED,
|
||
merchant_id=self.merchant.id,
|
||
payload={"mission_id": 99, "category_id": self.general_category.id},
|
||
)
|
||
|
||
self.assertEqual(mock_send.call_count, 1)
|
||
self.assertEqual(results[0]["route_id"], self.global_route.id)
|
||
self.assertIsNone(results[0]["route_mission_category_id"])
|
||
|
||
@patch("notifier.tasks.dispatch_notification_event_task.delay")
|
||
def test_enqueue_notification_event_returns_task_id(self, mock_delay):
|
||
mock_delay.return_value.id = "task-123"
|
||
|
||
task_id = enqueue_notification_event(
|
||
event_key=NotificationEventKeyEnum.MISSION_CREATED,
|
||
merchant_id=self.merchant.id,
|
||
payload={"mission_id": 1},
|
||
)
|
||
|
||
self.assertEqual(task_id, "task-123")
|
||
mock_delay.assert_called_once()
|
||
|
||
@patch("notifier.tasks.dispatch_notification_event_task.delay", side_effect=RuntimeError("broker down"))
|
||
def test_enqueue_notification_event_fails_open(self, mock_delay):
|
||
task_id = enqueue_notification_event(
|
||
event_key=NotificationEventKeyEnum.MISSION_CREATED,
|
||
merchant_id=self.merchant.id,
|
||
payload={"mission_id": 1},
|
||
)
|
||
|
||
self.assertIsNone(task_id)
|
||
mock_delay.assert_called_once()
|