统一聊天排序并支持公众号跳转小程序
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
from urllib.parse import parse_qs, urlparse
|
||||
|
||||
import pytest
|
||||
from fastapi import HTTPException
|
||||
|
||||
from banban.service.wechat_mp_notification import WechatMpNotificationService
|
||||
from banban.service.wechat_mp_notification import WechatMpNotificationService, WechatMpRecipient
|
||||
|
||||
|
||||
def configure_enabled_wechat_mp(monkeypatch):
|
||||
@@ -17,6 +18,8 @@ def configure_enabled_wechat_mp(monkeypatch):
|
||||
monkeypatch.setattr("banban.service.wechat_mp_notification.settings.wechat_mp_miniprogram_link_enabled", True)
|
||||
monkeypatch.setattr("banban.service.wechat_mp_notification.settings.wechat_mp_miniprogram_appid", "wx-mini")
|
||||
monkeypatch.setattr("banban.service.wechat_mp_notification.settings.wechat_mp_chat_page", "pages/chat/detail/index")
|
||||
monkeypatch.setattr("banban.service.wechat_mp_notification.settings.wechat_mp_notification_page", "pages/notification/index")
|
||||
monkeypatch.setattr("banban.service.wechat_mp_notification.settings.wechat_mp_notification_token_expire_minutes", 10080)
|
||||
monkeypatch.setattr("banban.service.wechat_mp_notification.settings.wechat_mp_device_page", "pages/device/index")
|
||||
monkeypatch.setattr("banban.service.wechat_mp_notification.settings.wechat_mp_oauth_redirect_uri", "https://example.com/banban/wechat-mp/oauth/callback")
|
||||
monkeypatch.setattr("banban.service.wechat_mp_notification.settings.wechat_mp_leave_message_dedup_seconds", 60)
|
||||
@@ -34,13 +37,83 @@ async def test_notify_leave_message_sends_template_to_unique_subscribed_recipien
|
||||
|
||||
async def fake_list_recipients(*, device_id):
|
||||
assert device_id == "TalkingQ_XQSN00001007"
|
||||
return ["openid-1", "openid-2"]
|
||||
return [
|
||||
WechatMpRecipient(user_id=4, openid="openid-1"),
|
||||
WechatMpRecipient(user_id=5, openid="openid-2"),
|
||||
]
|
||||
|
||||
async def fake_send_template_message(**kwargs):
|
||||
sent.append(kwargs)
|
||||
return {"ok": True, "msgid": "msg-id"}
|
||||
|
||||
monkeypatch.setattr(service, "_list_device_family_mp_openids", fake_list_recipients)
|
||||
monkeypatch.setattr(service, "_list_device_family_mp_recipients", fake_list_recipients)
|
||||
monkeypatch.setattr(service, "_send_template_message", fake_send_template_message)
|
||||
|
||||
await service.notify_leave_message(
|
||||
device_id="TalkingQ_XQSN00001007",
|
||||
child_name="小明",
|
||||
targets=[
|
||||
{
|
||||
"parent_user_id": 4,
|
||||
"conversation_id": 6,
|
||||
"message_id": 209,
|
||||
"child_id": 8,
|
||||
"child_name": "小明",
|
||||
"device_id": "TalkingQ_XQSN00001007",
|
||||
},
|
||||
{
|
||||
"parent_user_id": 5,
|
||||
"conversation_id": 7,
|
||||
"message_id": 210,
|
||||
"child_id": 8,
|
||||
"child_name": "小明",
|
||||
"device_id": "TalkingQ_XQSN00001007",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
assert len(sent) == 2
|
||||
assert sent[0] == {
|
||||
"openid": "openid-1",
|
||||
"template_id": "template-id",
|
||||
"title": "小明",
|
||||
"condition": "收到新的设备留言",
|
||||
"page": sent[0]["page"],
|
||||
}
|
||||
assert sent[1] == {
|
||||
"openid": "openid-2",
|
||||
"template_id": "template-id",
|
||||
"title": "小明",
|
||||
"condition": "收到新的设备留言",
|
||||
"page": sent[1]["page"],
|
||||
}
|
||||
assert sent[0]["page"].startswith("pages/notification/index?token=")
|
||||
assert sent[1]["page"].startswith("pages/notification/index?token=")
|
||||
assert sent[0]["page"] != sent[1]["page"]
|
||||
|
||||
first_token = sent[0]["page"].split("token=", 1)[1]
|
||||
second_token = sent[1]["page"].split("token=", 1)[1]
|
||||
assert service._decode_notification_token(first_token)["conversation_id"] == 6
|
||||
assert service._decode_notification_token(first_token)["user_id"] == 4
|
||||
assert service._decode_notification_token(second_token)["conversation_id"] == 7
|
||||
assert service._decode_notification_token(second_token)["user_id"] == 5
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_notify_leave_message_falls_back_to_chat_page_without_targets(monkeypatch):
|
||||
configure_enabled_wechat_mp(monkeypatch)
|
||||
service = WechatMpNotificationService()
|
||||
sent = []
|
||||
|
||||
async def fake_list_recipients(*, device_id):
|
||||
del device_id
|
||||
return [WechatMpRecipient(user_id=4, openid="openid-1")]
|
||||
|
||||
async def fake_send_template_message(**kwargs):
|
||||
sent.append(kwargs)
|
||||
return {"ok": True, "msgid": "msg-id"}
|
||||
|
||||
monkeypatch.setattr(service, "_list_device_family_mp_recipients", fake_list_recipients)
|
||||
monkeypatch.setattr(service, "_send_template_message", fake_send_template_message)
|
||||
|
||||
await service.notify_leave_message(device_id="TalkingQ_XQSN00001007", child_name="小明")
|
||||
@@ -52,14 +125,7 @@ async def test_notify_leave_message_sends_template_to_unique_subscribed_recipien
|
||||
"title": "小明",
|
||||
"condition": "收到新的设备留言",
|
||||
"page": "pages/chat/detail/index",
|
||||
},
|
||||
{
|
||||
"openid": "openid-2",
|
||||
"template_id": "template-id",
|
||||
"title": "小明",
|
||||
"condition": "收到新的设备留言",
|
||||
"page": "pages/chat/detail/index",
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -71,13 +137,13 @@ async def test_notify_leave_message_dedupes_same_device_and_openid(monkeypatch):
|
||||
|
||||
async def fake_list_recipients(*, device_id):
|
||||
del device_id
|
||||
return ["openid-1"]
|
||||
return [WechatMpRecipient(user_id=4, openid="openid-1")]
|
||||
|
||||
async def fake_send_template_message(**kwargs):
|
||||
sent.append(kwargs["openid"])
|
||||
return {"ok": True, "msgid": "msg-id"}
|
||||
|
||||
monkeypatch.setattr(service, "_list_device_family_mp_openids", fake_list_recipients)
|
||||
monkeypatch.setattr(service, "_list_device_family_mp_recipients", fake_list_recipients)
|
||||
monkeypatch.setattr(service, "_send_template_message", fake_send_template_message)
|
||||
|
||||
await service.notify_leave_message(device_id="TalkingQ_XQSN00001007", child_name="小明")
|
||||
@@ -86,6 +152,91 @@ async def test_notify_leave_message_dedupes_same_device_and_openid(monkeypatch):
|
||||
assert sent == ["openid-1"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_notification_link_returns_chat_detail_params(monkeypatch):
|
||||
configure_enabled_wechat_mp(monkeypatch)
|
||||
service = WechatMpNotificationService()
|
||||
token = service._create_notification_token(
|
||||
{
|
||||
"type": "leave_message",
|
||||
"user_id": 4,
|
||||
"conversation_id": 6,
|
||||
"message_id": 209,
|
||||
"child_id": 8,
|
||||
"child_name": "小明",
|
||||
"device_id": "TalkingQ_XQSN00001007",
|
||||
}
|
||||
)
|
||||
|
||||
class FakeResult:
|
||||
def mappings(self):
|
||||
return self
|
||||
|
||||
def first(self):
|
||||
return {
|
||||
"conversation_id": 6,
|
||||
"child_id": 8,
|
||||
"child_name": "小明",
|
||||
"device_id": "TalkingQ_XQSN00001007",
|
||||
}
|
||||
|
||||
class FakeSession:
|
||||
async def execute(self, sql, params):
|
||||
assert params["message_id"] == 209
|
||||
assert params["conversation_id"] == 6
|
||||
assert params["child_id"] == 8
|
||||
assert params["user_id"] == 4
|
||||
return FakeResult()
|
||||
|
||||
async def close(self):
|
||||
pass
|
||||
|
||||
async def fake_get_session():
|
||||
return FakeSession()
|
||||
|
||||
monkeypatch.setattr(service, "get_session", fake_get_session)
|
||||
|
||||
result = await service.resolve_notification_link(token=token, user_id=4)
|
||||
|
||||
assert result["route"] == "pages/chat/detail/index"
|
||||
assert result["params"] == {
|
||||
"id": 6,
|
||||
"source": "im",
|
||||
"name": "家长沟通",
|
||||
"peerKind": "parent",
|
||||
"roleKey": "",
|
||||
"conversationTypeName": "parent_child",
|
||||
"peerId": "4",
|
||||
"childId": 8,
|
||||
"childName": "小明",
|
||||
"parentUserId": 4,
|
||||
"deviceId": "TalkingQ_XQSN00001007",
|
||||
"channelLabel": "微信小程序",
|
||||
"canSend": "1",
|
||||
"messageId": 209,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_notification_link_rejects_other_user(monkeypatch):
|
||||
configure_enabled_wechat_mp(monkeypatch)
|
||||
service = WechatMpNotificationService()
|
||||
token = service._create_notification_token(
|
||||
{
|
||||
"type": "leave_message",
|
||||
"user_id": 4,
|
||||
"conversation_id": 6,
|
||||
"message_id": 209,
|
||||
"child_id": 8,
|
||||
}
|
||||
)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
await service.resolve_notification_link(token=token, user_id=5)
|
||||
|
||||
assert exc_info.value.status_code == 403
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bind_url_persists_state_and_builds_oauth_url(monkeypatch):
|
||||
configure_enabled_wechat_mp(monkeypatch)
|
||||
|
||||
Reference in New Issue
Block a user