mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-14 02:05:13 +08:00
189 lines
5.9 KiB
Python
189 lines
5.9 KiB
Python
import asyncio
|
|
import json
|
|
from unittest.mock import AsyncMock, patch
|
|
|
|
from app.agent.tools.impl.update_subscribe import UpdateSubscribeTool
|
|
from app.schemas.types import EventType, MediaType
|
|
|
|
|
|
def test_agent_update_subscribe_sends_modified_event_payload_with_agent_scene():
|
|
"""
|
|
Agent 更新订阅后只发送 modify 事件,并标记 agent_update 场景。
|
|
"""
|
|
subscribe = _AgentSubscribe(id=9, name="旧标题", state="R", total_episode=8)
|
|
oper = _SubscribeOperStub(subscribe)
|
|
|
|
with patch(
|
|
"app.agent.tools.impl.update_subscribe.SubscribeOper",
|
|
return_value=oper,
|
|
), patch(
|
|
"app.agent.tools.impl.update_subscribe.eventmanager.async_send_event",
|
|
new=AsyncMock(),
|
|
) as send_event:
|
|
result = asyncio.run(
|
|
UpdateSubscribeTool(session_id="session-1", user_id="10001").run(
|
|
subscribe_id=9,
|
|
name="新标题",
|
|
state="S",
|
|
)
|
|
)
|
|
|
|
payload = json.loads(result)
|
|
assert payload["success"] is True
|
|
assert oper.updates == [(9, {"name": "新标题", "state": "S"})]
|
|
send_event.assert_awaited_once()
|
|
event_type, event_payload = send_event.await_args.args
|
|
assert event_type == EventType.SubscribeModified
|
|
assert event_payload["subscribe_id"] == 9
|
|
assert event_payload["scene"] == "agent_update"
|
|
assert event_payload["fields"] == ["name", "state"]
|
|
assert event_payload["old_subscribe_info"]["name"] == "旧标题"
|
|
assert event_payload["subscribe_info"]["name"] == "新标题"
|
|
|
|
|
|
def test_agent_update_subscribe_ignores_unchanged_total_episode():
|
|
"""Agent 回传相同总集数时,不应产生数据库写入或订阅调整事件。"""
|
|
subscribe = _AgentSubscribe(
|
|
id=160,
|
|
name="测试剧集",
|
|
type=MediaType.TV.value,
|
|
state="R",
|
|
total_episode=175,
|
|
lack_episode=0,
|
|
manual_total_episode=0,
|
|
)
|
|
oper = _SubscribeOperStub(subscribe)
|
|
|
|
with patch(
|
|
"app.agent.tools.impl.update_subscribe.SubscribeOper",
|
|
return_value=oper,
|
|
), patch(
|
|
"app.agent.tools.impl.update_subscribe.eventmanager.async_send_event",
|
|
new=AsyncMock(),
|
|
) as send_event:
|
|
result = asyncio.run(
|
|
UpdateSubscribeTool(session_id="session-1", user_id="10001").run(
|
|
subscribe_id=160,
|
|
total_episode=175,
|
|
)
|
|
)
|
|
|
|
payload = json.loads(result)
|
|
assert payload == {"success": False, "message": "没有提供要更新的字段"}
|
|
assert oper.updates == []
|
|
send_event.assert_not_awaited()
|
|
|
|
|
|
def test_agent_update_subscribe_only_updates_other_fields_with_unchanged_total_episode():
|
|
"""Agent 同时回传相同总集数和洗版设置时,只更新实际请求的其他字段。"""
|
|
subscribe = _AgentSubscribe(
|
|
id=160,
|
|
name="测试剧集",
|
|
type=MediaType.TV.value,
|
|
state="R",
|
|
total_episode=175,
|
|
lack_episode=0,
|
|
manual_total_episode=0,
|
|
best_version=0,
|
|
)
|
|
oper = _SubscribeOperStub(subscribe)
|
|
|
|
with patch(
|
|
"app.agent.tools.impl.update_subscribe.SubscribeOper",
|
|
return_value=oper,
|
|
), patch(
|
|
"app.agent.tools.impl.update_subscribe.eventmanager.async_send_event",
|
|
new=AsyncMock(),
|
|
) as send_event:
|
|
result = asyncio.run(
|
|
UpdateSubscribeTool(session_id="session-1", user_id="10001").run(
|
|
subscribe_id=160,
|
|
total_episode=175,
|
|
best_version=1,
|
|
)
|
|
)
|
|
|
|
payload = json.loads(result)
|
|
assert payload["success"] is True
|
|
assert payload["updated_fields"] == ["best_version"]
|
|
assert payload["subscribe"]["manual_total_episode"] == 0
|
|
assert oper.updates == [(160, {"best_version": 1})]
|
|
send_event.assert_awaited_once()
|
|
_, event_payload = send_event.await_args.args
|
|
assert event_payload["fields"] == ["best_version"]
|
|
|
|
|
|
def test_agent_update_subscribe_marks_changed_total_episode_as_manual():
|
|
"""Agent 真正修改总集数时,保持 Web API 的手动总集数语义。"""
|
|
subscribe = _AgentSubscribe(
|
|
id=160,
|
|
name="测试剧集",
|
|
type=MediaType.TV.value,
|
|
state="R",
|
|
total_episode=175,
|
|
lack_episode=0,
|
|
manual_total_episode=0,
|
|
)
|
|
oper = _SubscribeOperStub(subscribe)
|
|
|
|
with patch(
|
|
"app.agent.tools.impl.update_subscribe.SubscribeOper",
|
|
return_value=oper,
|
|
), patch(
|
|
"app.agent.tools.impl.update_subscribe.eventmanager.async_send_event",
|
|
new=AsyncMock(),
|
|
):
|
|
result = asyncio.run(
|
|
UpdateSubscribeTool(session_id="session-1", user_id="10001").run(
|
|
subscribe_id=160,
|
|
total_episode=190,
|
|
)
|
|
)
|
|
|
|
payload = json.loads(result)
|
|
assert payload["success"] is True
|
|
assert payload["subscribe"]["manual_total_episode"] == 1
|
|
assert oper.updates == [
|
|
(
|
|
160,
|
|
{
|
|
"total_episode": 190,
|
|
"lack_episode": 15,
|
|
"manual_total_episode": 1,
|
|
},
|
|
)
|
|
]
|
|
|
|
|
|
class _AgentSubscribe:
|
|
"""
|
|
最小订阅替身,模拟 Agent 工具依赖的订阅对象接口。
|
|
"""
|
|
|
|
def __init__(self, **kwargs):
|
|
self.__dict__.update(kwargs)
|
|
|
|
def __getattr__(self, item):
|
|
return None
|
|
|
|
def to_dict(self):
|
|
return dict(self.__dict__)
|
|
|
|
|
|
class _SubscribeOperStub:
|
|
"""
|
|
内存订阅操作替身,记录工具最终提交的更新字段。
|
|
"""
|
|
|
|
def __init__(self, subscribe):
|
|
self.subscribe = subscribe
|
|
self.updates = []
|
|
|
|
async def async_get(self, subscribe_id):
|
|
return self.subscribe if subscribe_id == self.subscribe.id else None
|
|
|
|
async def async_update(self, subscribe_id, payload):
|
|
self.updates.append((subscribe_id, dict(payload)))
|
|
self.subscribe.__dict__.update(payload)
|
|
return self.subscribe
|