Files
MoviePilot/tests/test_delete_transfer_history_tool.py
2026-06-21 08:17:32 +08:00

356 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import asyncio
from types import SimpleNamespace
from app.agent.tools.impl.delete_transfer_history import DeleteTransferHistoryTool
from app.agent.prompt.transfer_redo import build_manual_redo_template_context
def test_delete_transfer_history_tool_removes_old_dest_file_before_history(monkeypatch):
"""AI 重新整理删除整理记录前,应按历史目标文件清理旧媒体库文件。"""
calls = []
history = SimpleNamespace(
id=7,
title="奔跑吧",
src="/downloads/Keep.Running.mkv",
status=True,
mode="link",
dest_fileitem={
"storage": "local",
"path": "/library/奔跑吧 (2014)/Keep.Running.mkv",
"name": "Keep.Running.mkv",
"type": "file",
},
)
class FakeTransferHistoryOper:
async def async_get(self, history_id):
calls.append(("get", history_id))
return history
async def async_delete(self, history_id):
calls.append(("delete_history", history_id))
class FakeStorageChain:
def exists(self, fileitem):
calls.append(("exists_dest", fileitem.path))
return True
def delete_media_file(self, fileitem):
calls.append(("delete_dest", fileitem.path))
return True
monkeypatch.setattr(
"app.agent.tools.impl.delete_transfer_history.TransferHistoryOper",
FakeTransferHistoryOper,
)
monkeypatch.setattr(
"app.agent.tools.impl.delete_transfer_history.StorageChain",
FakeStorageChain,
)
tool = DeleteTransferHistoryTool(session_id="redo-session", user_id="10001")
result = asyncio.run(tool.run(history_id=7))
assert "已删除整理历史记录" in result
assert calls == [
("get", 7),
("exists_dest", "/library/奔跑吧 (2014)/Keep.Running.mkv"),
("delete_dest", "/library/奔跑吧 (2014)/Keep.Running.mkv"),
("delete_history", 7),
]
def test_delete_transfer_history_tool_keeps_history_when_old_dest_delete_fails(monkeypatch):
"""旧媒体库文件删除失败时不得删除整理记录,避免重整链路丢失回滚依据。"""
calls = []
history = SimpleNamespace(
id=8,
title="奔跑吧",
src="/downloads/Keep.Running.mkv",
status=True,
mode="copy",
dest_fileitem={
"storage": "local",
"path": "/library/奔跑吧 (2014)/Keep.Running.mkv",
"name": "Keep.Running.mkv",
"type": "file",
},
)
class FakeTransferHistoryOper:
async def async_get(self, history_id):
calls.append(("get", history_id))
return history
async def async_delete(self, history_id):
calls.append(("delete_history", history_id))
class FakeStorageChain:
def exists(self, fileitem):
calls.append(("exists_dest", fileitem.path))
return True
def delete_media_file(self, fileitem):
calls.append(("delete_dest", fileitem.path))
return False
monkeypatch.setattr(
"app.agent.tools.impl.delete_transfer_history.TransferHistoryOper",
FakeTransferHistoryOper,
)
monkeypatch.setattr(
"app.agent.tools.impl.delete_transfer_history.StorageChain",
FakeStorageChain,
)
tool = DeleteTransferHistoryTool(session_id="redo-session", user_id="10001")
result = asyncio.run(tool.run(history_id=8))
assert "旧媒体库文件删除失败" in result
assert calls == [
("get", 8),
("exists_dest", "/library/奔跑吧 (2014)/Keep.Running.mkv"),
("delete_dest", "/library/奔跑吧 (2014)/Keep.Running.mkv"),
]
def test_delete_transfer_history_tool_deletes_history_when_old_dest_is_missing(monkeypatch):
"""旧媒体库文件已不存在时应视为已清理,继续删除整理记录。"""
calls = []
history = SimpleNamespace(
id=13,
title="奔跑吧",
src="/downloads/Keep.Running.mkv",
status=True,
mode="link",
dest_fileitem={
"storage": "local",
"path": "/library/奔跑吧 (2014)/Keep.Running.mkv",
"name": "Keep.Running.mkv",
"type": "file",
},
)
class FakeTransferHistoryOper:
async def async_get(self, history_id):
calls.append(("get", history_id))
return history
async def async_delete(self, history_id):
calls.append(("delete_history", history_id))
class FakeStorageChain:
def exists(self, fileitem):
calls.append(("exists_dest", fileitem.path))
return False
def delete_media_file(self, fileitem):
calls.append(("delete_dest", fileitem.path))
return False
monkeypatch.setattr(
"app.agent.tools.impl.delete_transfer_history.TransferHistoryOper",
FakeTransferHistoryOper,
)
monkeypatch.setattr(
"app.agent.tools.impl.delete_transfer_history.StorageChain",
FakeStorageChain,
)
tool = DeleteTransferHistoryTool(session_id="redo-session", user_id="10001")
result = asyncio.run(tool.run(history_id=13))
assert "已删除整理历史记录" in result
assert "已删除旧媒体库文件" not in result
assert calls == [
("get", 13),
("exists_dest", "/library/奔跑吧 (2014)/Keep.Running.mkv"),
("delete_history", 13),
]
def test_delete_transfer_history_tool_keeps_successful_move_dest_as_reorganize_source(monkeypatch):
"""成功 move 记录的目标文件是重新整理输入,不应在删除历史时先删除。"""
calls = []
history = SimpleNamespace(
id=9,
title="奔跑吧",
src="/downloads/Keep.Running.mkv",
status=True,
mode="move",
dest_fileitem={
"storage": "local",
"path": "/library/奔跑吧 (2014)/Keep.Running.mkv",
"name": "Keep.Running.mkv",
"type": "file",
},
)
class FakeTransferHistoryOper:
async def async_get(self, history_id):
calls.append(("get", history_id))
return history
async def async_delete(self, history_id):
calls.append(("delete_history", history_id))
class FakeStorageChain:
def exists(self, fileitem):
calls.append(("exists_dest", fileitem.path))
return True
def delete_media_file(self, fileitem):
calls.append(("delete_dest", fileitem.path))
return True
monkeypatch.setattr(
"app.agent.tools.impl.delete_transfer_history.TransferHistoryOper",
FakeTransferHistoryOper,
)
monkeypatch.setattr(
"app.agent.tools.impl.delete_transfer_history.StorageChain",
FakeStorageChain,
)
tool = DeleteTransferHistoryTool(session_id="redo-session", user_id="10001")
result = asyncio.run(tool.run(history_id=9))
assert "已删除整理历史记录" in result
assert calls == [
("get", 9),
("delete_history", 9),
]
def test_delete_transfer_history_tool_only_treats_exact_move_as_reorganize_source(monkeypatch):
"""整理方式必须精确等于 move其他模式仍应清理旧目标文件。"""
calls = []
history = SimpleNamespace(
id=11,
title="奔跑吧",
src="/downloads/Keep.Running.mkv",
status=True,
mode="not-move",
dest_fileitem={
"storage": "local",
"path": "/library/奔跑吧 (2014)/Keep.Running.mkv",
"name": "Keep.Running.mkv",
"type": "file",
},
)
class FakeTransferHistoryOper:
async def async_get(self, history_id):
calls.append(("get", history_id))
return history
async def async_delete(self, history_id):
calls.append(("delete_history", history_id))
class FakeStorageChain:
def exists(self, fileitem):
calls.append(("exists_dest", fileitem.path))
return True
def delete_media_file(self, fileitem):
calls.append(("delete_dest", fileitem.path))
return True
monkeypatch.setattr(
"app.agent.tools.impl.delete_transfer_history.TransferHistoryOper",
FakeTransferHistoryOper,
)
monkeypatch.setattr(
"app.agent.tools.impl.delete_transfer_history.StorageChain",
FakeStorageChain,
)
tool = DeleteTransferHistoryTool(session_id="redo-session", user_id="10001")
result = asyncio.run(tool.run(history_id=11))
assert "已删除旧媒体库文件" in result
assert calls == [
("get", 11),
("exists_dest", "/library/奔跑吧 (2014)/Keep.Running.mkv"),
("delete_dest", "/library/奔跑吧 (2014)/Keep.Running.mkv"),
("delete_history", 11),
]
def test_manual_redo_context_uses_dest_path_for_successful_move_record():
"""成功 move 记录重新整理时,旧目标文件才是可继续整理的输入路径。"""
history = SimpleNamespace(
id=10,
status=True,
title="奔跑吧",
type="电视剧",
category="综艺",
year="2014",
seasons="S01",
episodes="E01",
src="/downloads/Keep.Running.mkv",
src_storage="local",
src_fileitem={
"storage": "local",
"path": "/downloads/Keep.Running.mkv",
"name": "Keep.Running.mkv",
"type": "file",
},
dest="/library/奔跑吧 (2014)/Keep.Running.mkv",
dest_storage="local",
dest_fileitem={
"storage": "local",
"path": "/library/奔跑吧 (2014)/Keep.Running.mkv",
"name": "Keep.Running.mkv",
"type": "file",
},
mode="move",
tmdbid=100,
doubanid=None,
errmsg=None,
)
context = build_manual_redo_template_context(history)
assert context["source_path"] == "/library/奔跑吧 (2014)/Keep.Running.mkv"
assert context["source_storage"] == "local"
def test_manual_redo_context_only_treats_exact_move_as_dest_source():
"""非 move 整理方式即使名称包含 move也应继续使用原始来源。"""
history = SimpleNamespace(
id=12,
status=True,
title="奔跑吧",
type="电视剧",
category="综艺",
year="2014",
seasons="S01",
episodes="E01",
src="/downloads/Keep.Running.mkv",
src_storage="local",
src_fileitem={
"storage": "local",
"path": "/downloads/Keep.Running.mkv",
"name": "Keep.Running.mkv",
"type": "file",
},
dest="/library/奔跑吧 (2014)/Keep.Running.mkv",
dest_storage="local",
dest_fileitem={
"storage": "local",
"path": "/library/奔跑吧 (2014)/Keep.Running.mkv",
"name": "Keep.Running.mkv",
"type": "file",
},
mode="not-move",
tmdbid=100,
doubanid=None,
errmsg=None,
)
context = build_manual_redo_template_context(history)
assert context["source_path"] == "/downloads/Keep.Running.mkv"
assert context["source_storage"] == "local"