101 lines
3.9 KiB
Python
101 lines
3.9 KiB
Python
"""微信三项验收 + P0 路由离线回归(不依赖真机)
|
||
|
||
确保 frida 一上线即可跑通:请求模型字段、路由可导入、159 action 对齐。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
import pytest
|
||
|
||
APP = Path(__file__).resolve().parents[1] / "app"
|
||
if str(APP) not in sys.path:
|
||
sys.path.insert(0, str(APP))
|
||
|
||
|
||
def test_send_message_request_fields():
|
||
from routers.unified import SendMessageRequest
|
||
f = SendMessageRequest.model_fields
|
||
for k in ("device_id", "platform", "to_id", "content", "msg_type"):
|
||
assert k in f, f"SendMessageRequest 缺字段 {k}"
|
||
|
||
|
||
def test_get_messages_request_fields():
|
||
from routers.unified import GetMessagesRequest
|
||
f = GetMessagesRequest.model_fields
|
||
for k in ("device_id", "platform", "conversation_id", "limit"):
|
||
assert k in f, f"GetMessagesRequest 缺字段 {k}"
|
||
|
||
|
||
def test_post_moments_request_fields():
|
||
from routers.unified import PostMomentsRequest
|
||
f = PostMomentsRequest.model_fields
|
||
for k in ("device_id", "platform", "content", "images"):
|
||
assert k in f, f"PostMomentsRequest 缺字段 {k}"
|
||
|
||
|
||
def test_wechat_159_actions_aligned():
|
||
# 仓库根 sdk/skills 会抢占 "skills" 命名空间,这里按 app 下的真实文件稳健加载
|
||
import importlib.util
|
||
|
||
skill_path = APP / "skills" / "wechat" / "skill_v2.py"
|
||
assert skill_path.is_file(), f"skill_v2.py 缺失: {skill_path}"
|
||
spec = importlib.util.spec_from_file_location("_wechat_skill_v2_offline", skill_path)
|
||
mod = importlib.util.module_from_spec(spec)
|
||
assert spec and spec.loader
|
||
spec.loader.exec_module(mod)
|
||
WECHAT_ACTIONS = mod.WECHAT_ACTIONS
|
||
WechatSkillV2 = mod.WechatSkillV2
|
||
assert len(WECHAT_ACTIONS) == 159, f"WECHAT_ACTIONS={len(WECHAT_ACTIONS)} != 159"
|
||
catalog = WechatSkillV2.get_catalog_action_list()
|
||
assert len(catalog) >= 174, f"catalog={len(catalog)} < 174"
|
||
|
||
|
||
def test_friend_add_route_importable():
|
||
"""TODO-02 friend-add → 存客宝线索链路可导入。"""
|
||
from services.cunke_bao_service import CunKeBaoService, LeadData
|
||
assert hasattr(CunKeBaoService, "report_friend_add")
|
||
assert hasattr(CunKeBaoService, "report_lead")
|
||
lead = LeadData(wechat_id="wxid_test", wechat_nickname="t", source="测试")
|
||
params = lead.to_api_params()
|
||
assert params.get("wechatId") == "wxid_test"
|
||
|
||
|
||
def test_ai_chat_orchestrator_importable():
|
||
"""TODO-03 AI chat → send_message 编排可导入。"""
|
||
from services.karuo_device_ai import chat_and_execute_on_device, device_status
|
||
assert callable(chat_and_execute_on_device)
|
||
assert callable(device_status)
|
||
|
||
|
||
def test_unblock_customer_service_exists():
|
||
"""TODO-01 解封客服 Skill 文件存在。"""
|
||
p = Path(__file__).resolve().parents[1] / "agent" / "skills" / "wechat" / "unblock_customer_service.py"
|
||
assert p.is_file(), "解封客服 Skill 缺失"
|
||
|
||
|
||
def test_three_acceptance_scripts_exist():
|
||
base = Path(__file__).resolve().parents[1] / "scripts"
|
||
for s in ("run_three_acceptance.sh", "auto_accept_when_ready.sh", "termux_frida_up_onphone.sh"):
|
||
assert (base / s).is_file(), f"脚本缺失 {s}"
|
||
|
||
|
||
def test_wp_wx04_scan_routes_and_agent_skill():
|
||
"""WP-WX-04 离线路由 + Agent u2 skill 对齐(不替代真机 E2E)。"""
|
||
from routers import unified
|
||
|
||
assert callable(getattr(unified, "extract_qr_from_image", None))
|
||
assert callable(getattr(unified, "add_friend_from_image", None))
|
||
skill_path = Path(__file__).resolve().parents[1] / "agent" / "skills" / "wechat" / "skill.py"
|
||
src = skill_path.read_text(encoding="utf-8")
|
||
assert "def add_friend_from_image" in src
|
||
assert "_save_qr_image_to_album" in src
|
||
agent_py = Path(__file__).resolve().parents[1] / "agent" / "agent.py"
|
||
assert '"add_friend_from_image"' in agent_py.read_text(encoding="utf-8")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(pytest.main([__file__, "-q"]))
|