2026-07-02 03:28:19 +08:00
|
|
|
|
"""channels plugins/wechat_ilink 层单元测试共享 fixture。
|
|
|
|
|
|
|
|
|
|
|
|
提供 ``fake_ilink_client`` 桩,模拟 ``ILinkClient``
|
|
|
|
|
|
(``yuxi.channels.plugins.wechat_ilink.ilink_client.ILinkClient``)。
|
|
|
|
|
|
微信 iLink 适配器测试通过此桩注入客户端依赖,不发起真实 HTTP 请求。
|
|
|
|
|
|
|
|
|
|
|
|
桩使用 ``AsyncMock()``,预设主要方法返回值(消息列表 / client_id /
|
2026-07-04 00:18:04 +08:00
|
|
|
|
二维码 / 空字节等),调用方可按需覆盖。方法签名以 ``ILinkClient``
|
|
|
|
|
|
实现为准。单文件独有的 helper 应保留在对应测试文件内
|
2026-07-02 03:28:19 +08:00
|
|
|
|
(见 testing-guidelines.md)。
|
2026-07-04 00:18:04 +08:00
|
|
|
|
|
|
|
|
|
|
注意:凭证管理(get_credentials / set_credentials / clear_credentials)
|
|
|
|
|
|
与 qr_token 缓存(get_qr_token / set_qr_token / clear_qr_token)已分别
|
|
|
|
|
|
迁移至 ``CredentialService`` 与 ``QrLoginService`` 会话管理,
|
|
|
|
|
|
``ILinkClient`` 不再持有这些方法,本桩亦不预设。
|
2026-07-02 03:28:19 +08:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
from unittest.mock import AsyncMock
|
|
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
|
|
def fake_ilink_client() -> AsyncMock:
|
|
|
|
|
|
"""ILinkClient 桩。
|
|
|
|
|
|
|
|
|
|
|
|
``AsyncMock()`` 模拟 ``ILinkClient``,预设主要方法返回值:
|
|
|
|
|
|
- ``get_updates`` 返回 ``{"msgs": [], "get_updates_buf": "fake-cursor"}``;
|
|
|
|
|
|
- ``send_message`` 返回 ``{"client_id": "fake-client-id"}``;
|
|
|
|
|
|
- ``get_bot_qrcode`` 返回 ``{"qrcode_img_content": "", "qrcode": "fake-qrcode"}``;
|
|
|
|
|
|
- ``get_qrcode_status`` 返回 ``{"status": "CONFIRM"}``;
|
|
|
|
|
|
- ``getconfig`` 返回 ``{}``;
|
|
|
|
|
|
- ``getuploadurl`` 返回含 upload_url / encrypt_query_param / aes_key /
|
|
|
|
|
|
file_id 的字典;
|
|
|
|
|
|
- ``cdn_upload`` 返回 ``None``;
|
|
|
|
|
|
- ``cdn_download`` 返回 ``b""``;
|
2026-07-04 00:18:04 +08:00
|
|
|
|
- ``get_context_token`` 返回 ``None``;
|
2026-07-02 03:28:19 +08:00
|
|
|
|
- ``get_cursor`` 返回 ``""``;
|
2026-07-08 22:59:24 +08:00
|
|
|
|
- ``set_context_token`` 返回 ``None``。
|
2026-07-02 03:28:19 +08:00
|
|
|
|
"""
|
|
|
|
|
|
client = AsyncMock()
|
2026-07-04 00:18:04 +08:00
|
|
|
|
# 配置读取:按 key 返回合理默认值(与 manifest.json 默认值一致)
|
|
|
|
|
|
_config_defaults = {
|
|
|
|
|
|
"baseurl": "https://ilinkai.weixin.qq.com",
|
|
|
|
|
|
"channel_version": "2.0.0",
|
|
|
|
|
|
"cdn_url": "https://novac2c.cdn.weixin.qq.com/c2c",
|
|
|
|
|
|
"long_poll_timeout_ms": 35000,
|
|
|
|
|
|
"qr_poll_interval_ms": 2000,
|
|
|
|
|
|
"qr_timeout_ms": 120000,
|
|
|
|
|
|
"max_message_length": 4000,
|
|
|
|
|
|
}
|
|
|
|
|
|
client.get_channel_config.side_effect = lambda key, default=None, **kw: _config_defaults.get(key, default)
|
2026-07-02 03:28:19 +08:00
|
|
|
|
# 长轮询
|
|
|
|
|
|
client.get_updates.return_value = {
|
|
|
|
|
|
"msgs": [],
|
|
|
|
|
|
"get_updates_buf": "fake-cursor",
|
|
|
|
|
|
}
|
|
|
|
|
|
# 消息发送
|
|
|
|
|
|
client.send_message.return_value = {"client_id": "fake-client-id"}
|
|
|
|
|
|
# 二维码登录
|
|
|
|
|
|
client.get_bot_qrcode.return_value = {
|
|
|
|
|
|
"qrcode_img_content": "",
|
|
|
|
|
|
"qrcode": "fake-qrcode",
|
|
|
|
|
|
}
|
|
|
|
|
|
client.get_qrcode_status.return_value = {
|
|
|
|
|
|
"status": "CONFIRM",
|
|
|
|
|
|
"redirect_host": None,
|
|
|
|
|
|
"bot_token": "fake-bot-token",
|
|
|
|
|
|
"ilink_bot_id": "fake-bot-id",
|
|
|
|
|
|
"ilink_user_id": "fake-user-id",
|
|
|
|
|
|
"baseurl": "https://ilinkai.weixin.qq.com",
|
|
|
|
|
|
}
|
|
|
|
|
|
# 健康探活
|
|
|
|
|
|
client.getconfig.return_value = {}
|
2026-07-06 20:52:20 +08:00
|
|
|
|
client.getconfig_with_token.return_value = {}
|
2026-07-02 03:28:19 +08:00
|
|
|
|
# CDN 上传/下载
|
|
|
|
|
|
client.getuploadurl.return_value = {
|
|
|
|
|
|
"upload_url": "https://fake-cdn.example.com/upload",
|
|
|
|
|
|
"encrypt_query_param": "fake-encrypt-param",
|
|
|
|
|
|
"aes_key": "fake-aes-key",
|
|
|
|
|
|
"file_id": "fake-file-id",
|
|
|
|
|
|
}
|
|
|
|
|
|
client.cdn_upload.return_value = None
|
|
|
|
|
|
client.cdn_download.return_value = b""
|
2026-07-04 00:18:04 +08:00
|
|
|
|
# context_token 运行时缓存(ILinkClient 自管理)
|
2026-07-02 03:28:19 +08:00
|
|
|
|
client.get_context_token.return_value = None
|
|
|
|
|
|
client.set_context_token.return_value = None
|
2026-07-04 00:18:04 +08:00
|
|
|
|
# cursor 缓存(仅读,写入由框架通过 PollResult.next_cursor 管理)
|
2026-07-02 03:28:19 +08:00
|
|
|
|
client.get_cursor.return_value = ""
|
|
|
|
|
|
return client
|