mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-07-21 04:31:59 +08:00
修复手动整理按集数定位模板过滤 (#6043)
This commit is contained in:
@@ -53,6 +53,111 @@ def test_manual_transfer_from_history_preserves_download_context(monkeypatch):
|
||||
assert captured["season"] == 1
|
||||
|
||||
|
||||
def test_manual_transfer_from_history_passes_old_dest_cleanup_to_chain(monkeypatch):
|
||||
history = SimpleNamespace(
|
||||
status=0,
|
||||
mode="copy",
|
||||
src_fileitem={
|
||||
"storage": "local",
|
||||
"path": "/downloads/test.mkv",
|
||||
"name": "test.mkv",
|
||||
"type": "file",
|
||||
},
|
||||
dest_fileitem={
|
||||
"storage": "local",
|
||||
"path": "/library/test.mkv",
|
||||
"name": "test.mkv",
|
||||
"type": "file",
|
||||
},
|
||||
downloader="qbittorrent",
|
||||
download_hash="abc123",
|
||||
type=None,
|
||||
tmdbid=None,
|
||||
doubanid=None,
|
||||
seasons=None,
|
||||
episodes=None,
|
||||
episode_group=None,
|
||||
)
|
||||
captured = {}
|
||||
|
||||
def fake_get(_db, logid):
|
||||
assert logid == 1
|
||||
return history
|
||||
|
||||
class FakeTransferChain:
|
||||
def manual_transfer(self, **kwargs):
|
||||
captured.update(kwargs)
|
||||
return True, ""
|
||||
|
||||
monkeypatch.setattr("app.api.endpoints.transfer.TransferHistory.get", fake_get)
|
||||
monkeypatch.setattr("app.api.endpoints.transfer.TransferChain", FakeTransferChain)
|
||||
|
||||
resp = manual_transfer(
|
||||
transer_item=ManualTransferItem(logid=1),
|
||||
background=False,
|
||||
db=object(),
|
||||
_="token",
|
||||
)
|
||||
|
||||
assert resp.success is True
|
||||
assert captured["fileitem"].path == "/downloads/test.mkv"
|
||||
assert captured["cleanup_dest_fileitem"].path == "/library/test.mkv"
|
||||
|
||||
|
||||
def test_manual_transfer_from_history_preview_does_not_cleanup_old_dest(monkeypatch):
|
||||
history = SimpleNamespace(
|
||||
status=0,
|
||||
mode="copy",
|
||||
src_fileitem={
|
||||
"storage": "local",
|
||||
"path": "/downloads/test.mkv",
|
||||
"name": "test.mkv",
|
||||
"type": "file",
|
||||
},
|
||||
dest_fileitem={
|
||||
"storage": "local",
|
||||
"path": "/library/test.mkv",
|
||||
"name": "test.mkv",
|
||||
"type": "file",
|
||||
},
|
||||
downloader="qbittorrent",
|
||||
download_hash="abc123",
|
||||
type=None,
|
||||
tmdbid=None,
|
||||
doubanid=None,
|
||||
seasons=None,
|
||||
episodes=None,
|
||||
episode_group=None,
|
||||
)
|
||||
captured = {}
|
||||
|
||||
def fake_get(_db, logid):
|
||||
assert logid == 1
|
||||
return history
|
||||
|
||||
class FakeTransferChain:
|
||||
def manual_transfer(self, **kwargs):
|
||||
captured.update(kwargs)
|
||||
return True, {
|
||||
"summary": {"total": 0, "success": 0, "failed": 0},
|
||||
"items": [],
|
||||
"message": "",
|
||||
}
|
||||
|
||||
monkeypatch.setattr("app.api.endpoints.transfer.TransferHistory.get", fake_get)
|
||||
monkeypatch.setattr("app.api.endpoints.transfer.TransferChain", FakeTransferChain)
|
||||
|
||||
resp = manual_transfer(
|
||||
transer_item=ManualTransferItem(logid=1, preview=True),
|
||||
background=False,
|
||||
db=object(),
|
||||
_="token",
|
||||
)
|
||||
|
||||
assert resp.success is True
|
||||
assert captured["cleanup_dest_fileitem"] is None
|
||||
|
||||
|
||||
def test_manual_transfer_preview_uses_explicit_fileitems_instead_of_directory(monkeypatch):
|
||||
dir_item = {
|
||||
"storage": "local",
|
||||
|
||||
@@ -807,7 +807,7 @@ class TransferJobManagerTest(unittest.TestCase):
|
||||
self.assertEqual("", errmsg)
|
||||
self.assertFalse(captured["sync_extra_files"])
|
||||
|
||||
def test_do_transfer_keeps_manual_single_extra_file_when_epformat_misses(self):
|
||||
def test_do_transfer_skips_manual_single_file_when_epformat_misses(self):
|
||||
chain = make_transfer_chain()
|
||||
planned = []
|
||||
subtitle_fileitem = make_fileitem(
|
||||
@@ -854,13 +854,21 @@ class TransferJobManagerTest(unittest.TestCase):
|
||||
fileitem=subtitle_fileitem,
|
||||
background=False,
|
||||
manual=True,
|
||||
preview=True,
|
||||
sync_extra_files=True,
|
||||
epformat=EpisodeFormat(format="Show - {ep}.mkv"),
|
||||
)
|
||||
|
||||
self.assertTrue(state)
|
||||
self.assertEqual("", errmsg)
|
||||
self.assertEqual([(subtitle_fileitem.path, 1)], planned)
|
||||
self.assertEqual(
|
||||
{
|
||||
"summary": {"total": 0, "success": 0, "failed": 0},
|
||||
"items": [],
|
||||
"message": "",
|
||||
},
|
||||
errmsg,
|
||||
)
|
||||
self.assertEqual([], planned)
|
||||
|
||||
def test_do_transfer_syncs_extra_files_when_epformat_only_matches_main_video(self):
|
||||
chain = make_transfer_chain()
|
||||
@@ -936,7 +944,6 @@ class TransferJobManagerTest(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
[
|
||||
(main_fileitem.path, 1),
|
||||
(subtitle_fileitem.path, 1),
|
||||
],
|
||||
planned,
|
||||
)
|
||||
|
||||
@@ -3,7 +3,7 @@ from types import SimpleNamespace
|
||||
|
||||
from app.chain.transfer import JobManager, TransferChain
|
||||
from app.core.config import settings
|
||||
from app.schemas import FileItem
|
||||
from app.schemas import EpisodeFormat, FileItem
|
||||
from app.schemas.types import MediaType
|
||||
|
||||
|
||||
@@ -356,3 +356,450 @@ def test_single_video_transfer_lists_parent_once_for_same_name_extra(monkeypatch
|
||||
assert errmsg == ""
|
||||
assert planned == [main_fileitem.path, subtitle_fileitem.path]
|
||||
assert list_files_calls == [(parent_fileitem.path, False)]
|
||||
|
||||
|
||||
def test_episode_format_filters_extra_files_before_sync_planning(monkeypatch):
|
||||
"""
|
||||
存在集数定位模板时,不匹配模板的附加文件不应被主视频带入整理计划。
|
||||
"""
|
||||
chain = make_transfer_chain()
|
||||
planned = []
|
||||
main_fileitem = make_fileitem(
|
||||
"/downloads/Test Show (2026)/Show - 01.mkv"
|
||||
)
|
||||
subtitle_fileitem = make_fileitem(
|
||||
"/downloads/Test Show (2026)/Show - 01.sc.ass"
|
||||
)
|
||||
parent_fileitem = FileItem(
|
||||
storage="local",
|
||||
path="/downloads/Test Show (2026)/",
|
||||
type="dir",
|
||||
name="Test Show (2026)",
|
||||
)
|
||||
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__get_trans_fileitems",
|
||||
lambda fileitem, predicate: [
|
||||
(main_fileitem, False),
|
||||
(subtitle_fileitem, False),
|
||||
],
|
||||
)
|
||||
monkeypatch.setattr(chain, "_TransferChain__put_to_jobview", lambda task: True)
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__register_scrape_batch_task",
|
||||
lambda task: None,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__close_scrape_batch",
|
||||
lambda batch_id: None,
|
||||
)
|
||||
|
||||
def fake_handle_transfer(task, callback=None):
|
||||
"""
|
||||
记录进入整理执行阶段的文件。
|
||||
"""
|
||||
planned.append(task.fileitem.path)
|
||||
return True, ""
|
||||
|
||||
monkeypatch.setattr(chain, "_TransferChain__handle_transfer", fake_handle_transfer)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.TransferHistoryOper",
|
||||
lambda: SimpleNamespace(get_by_src=lambda src, storage=None: None),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.DownloadHistoryOper",
|
||||
lambda: SimpleNamespace(
|
||||
get_by_hash=lambda download_hash: None,
|
||||
get_file_by_fullpath=lambda fullpath: None,
|
||||
get_files_by_savepath=lambda savepath: [],
|
||||
get_by_path=lambda path: None,
|
||||
),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.SystemConfigOper",
|
||||
lambda: SimpleNamespace(get=lambda key: None),
|
||||
)
|
||||
monkeypatch.setattr("app.chain.transfer.MetaInfoPath", lambda path, custom_words=None: FakeMeta(1))
|
||||
|
||||
state, errmsg = TransferChain.do_transfer(
|
||||
chain,
|
||||
fileitem=parent_fileitem,
|
||||
background=False,
|
||||
sync_extra_files=True,
|
||||
epformat=EpisodeFormat(format="Show - {ep}.mkv"),
|
||||
)
|
||||
|
||||
assert state is True
|
||||
assert errmsg == ""
|
||||
assert planned == [main_fileitem.path]
|
||||
|
||||
|
||||
def test_episode_format_keeps_matching_extra_files_following_main(monkeypatch):
|
||||
"""
|
||||
附加文件自身匹配集数定位模板时,仍可跟随同名主视频整理。
|
||||
"""
|
||||
chain = make_transfer_chain()
|
||||
planned = []
|
||||
main_fileitem = make_fileitem(
|
||||
"/downloads/Test Show (2026)/Show - 01.mkv"
|
||||
)
|
||||
subtitle_fileitem = make_fileitem(
|
||||
"/downloads/Test Show (2026)/Show - 01.ass"
|
||||
)
|
||||
parent_fileitem = FileItem(
|
||||
storage="local",
|
||||
path="/downloads/Test Show (2026)/",
|
||||
type="dir",
|
||||
name="Test Show (2026)",
|
||||
)
|
||||
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__get_trans_fileitems",
|
||||
lambda fileitem, predicate: [
|
||||
(main_fileitem, False),
|
||||
(subtitle_fileitem, False),
|
||||
],
|
||||
)
|
||||
monkeypatch.setattr(chain, "_TransferChain__put_to_jobview", lambda task: True)
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__register_scrape_batch_task",
|
||||
lambda task: None,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__close_scrape_batch",
|
||||
lambda batch_id: None,
|
||||
)
|
||||
|
||||
def fake_handle_transfer(task, callback=None):
|
||||
"""
|
||||
记录进入整理执行阶段的文件和集数。
|
||||
"""
|
||||
planned.append((task.fileitem.path, task.meta.begin_episode))
|
||||
return True, ""
|
||||
|
||||
monkeypatch.setattr(chain, "_TransferChain__handle_transfer", fake_handle_transfer)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.TransferHistoryOper",
|
||||
lambda: SimpleNamespace(get_by_src=lambda src, storage=None: None),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.DownloadHistoryOper",
|
||||
lambda: SimpleNamespace(
|
||||
get_by_hash=lambda download_hash: None,
|
||||
get_file_by_fullpath=lambda fullpath: None,
|
||||
get_files_by_savepath=lambda savepath: [],
|
||||
get_by_path=lambda path: None,
|
||||
),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.SystemConfigOper",
|
||||
lambda: SimpleNamespace(get=lambda key: None),
|
||||
)
|
||||
monkeypatch.setattr("app.chain.transfer.MetaInfoPath", lambda path, custom_words=None: FakeMeta(1))
|
||||
|
||||
state, errmsg = TransferChain.do_transfer(
|
||||
chain,
|
||||
fileitem=parent_fileitem,
|
||||
background=False,
|
||||
sync_extra_files=True,
|
||||
epformat=EpisodeFormat(format="Show - {ep}.{a}"),
|
||||
)
|
||||
|
||||
assert state is True
|
||||
assert errmsg == ""
|
||||
assert planned == [
|
||||
(main_fileitem.path, 1),
|
||||
(subtitle_fileitem.path, 1),
|
||||
]
|
||||
|
||||
|
||||
def test_single_matching_subtitle_uses_unmatched_video_only_as_context(monkeypatch):
|
||||
"""
|
||||
单独整理匹配模板的字幕时,同名主视频只提供识别上下文,不会被额外加入整理计划。
|
||||
"""
|
||||
chain = make_transfer_chain()
|
||||
planned = []
|
||||
main_fileitem = make_fileitem(
|
||||
"/downloads/Test Show (2026)/Show - 02.mkv"
|
||||
)
|
||||
subtitle_fileitem = make_fileitem(
|
||||
"/downloads/Test Show (2026)/Show - 02.ass"
|
||||
)
|
||||
parent_fileitem = FileItem(
|
||||
storage="local",
|
||||
path="/downloads/Test Show (2026)/",
|
||||
type="dir",
|
||||
name="Test Show (2026)",
|
||||
)
|
||||
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__get_trans_fileitems",
|
||||
lambda fileitem, predicate: [(subtitle_fileitem, False)],
|
||||
)
|
||||
monkeypatch.setattr(chain, "_TransferChain__put_to_jobview", lambda task: True)
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__register_scrape_batch_task",
|
||||
lambda task: None,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__close_scrape_batch",
|
||||
lambda batch_id: None,
|
||||
)
|
||||
|
||||
def fake_handle_transfer(task, callback=None):
|
||||
"""
|
||||
记录单独字幕整理时实际使用的集数。
|
||||
"""
|
||||
planned.append((task.fileitem.path, task.meta.begin_episode))
|
||||
return True, ""
|
||||
|
||||
def fake_meta_info_path(path, custom_words=None):
|
||||
"""
|
||||
模拟字幕自身识别不准,但同名主视频可提供正确集数。
|
||||
"""
|
||||
file_name = Path(path).name
|
||||
if file_name.endswith(".mkv"):
|
||||
return FakeMeta(2)
|
||||
return FakeMeta(1)
|
||||
|
||||
monkeypatch.setattr(chain, "_TransferChain__handle_transfer", fake_handle_transfer)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.TransferHistoryOper",
|
||||
lambda: SimpleNamespace(get_by_src=lambda src, storage=None: None),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.DownloadHistoryOper",
|
||||
lambda: SimpleNamespace(
|
||||
get_by_hash=lambda download_hash: None,
|
||||
get_file_by_fullpath=lambda fullpath: None,
|
||||
get_files_by_savepath=lambda savepath: [],
|
||||
get_by_path=lambda path: None,
|
||||
),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.SystemConfigOper",
|
||||
lambda: SimpleNamespace(get=lambda key: None),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.StorageChain",
|
||||
lambda: SimpleNamespace(
|
||||
get_parent_item=lambda fileitem: parent_fileitem,
|
||||
list_files=lambda fileitem, recursion=False: [
|
||||
main_fileitem,
|
||||
subtitle_fileitem,
|
||||
],
|
||||
),
|
||||
)
|
||||
monkeypatch.setattr("app.chain.transfer.MetaInfoPath", fake_meta_info_path)
|
||||
|
||||
state, errmsg = TransferChain.do_transfer(
|
||||
chain,
|
||||
fileitem=subtitle_fileitem,
|
||||
background=False,
|
||||
sync_extra_files=True,
|
||||
epformat=EpisodeFormat(format="Show - {ep}.ass"),
|
||||
)
|
||||
|
||||
assert state is True
|
||||
assert errmsg == ""
|
||||
assert planned == [(subtitle_fileitem.path, 2)]
|
||||
|
||||
|
||||
def test_cleanup_dest_fileitem_is_deleted_only_after_allowed_items_exist(monkeypatch):
|
||||
"""
|
||||
旧目标文件只应在模板筛选后确实存在待整理任务时清理。
|
||||
"""
|
||||
chain = make_transfer_chain()
|
||||
delete_calls = []
|
||||
planned = []
|
||||
main_fileitem = make_fileitem(
|
||||
"/downloads/Test Show (2026)/Show - 01.mkv"
|
||||
)
|
||||
old_dest_fileitem = make_fileitem(
|
||||
"/library/Test Show/Show - 01.mkv"
|
||||
)
|
||||
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__get_trans_fileitems",
|
||||
lambda fileitem, predicate: [(main_fileitem, False)],
|
||||
)
|
||||
monkeypatch.setattr(chain, "_TransferChain__put_to_jobview", lambda task: True)
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__register_scrape_batch_task",
|
||||
lambda task: None,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__close_scrape_batch",
|
||||
lambda batch_id: None,
|
||||
)
|
||||
|
||||
def fake_handle_transfer(task, callback=None):
|
||||
"""
|
||||
记录旧目标清理后的整理任务。
|
||||
"""
|
||||
planned.append(task.fileitem.path)
|
||||
return True, ""
|
||||
|
||||
monkeypatch.setattr(chain, "_TransferChain__handle_transfer", fake_handle_transfer)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.TransferHistoryOper",
|
||||
lambda: SimpleNamespace(get_by_src=lambda src, storage=None: None),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.DownloadHistoryOper",
|
||||
lambda: SimpleNamespace(
|
||||
get_by_hash=lambda download_hash: None,
|
||||
get_file_by_fullpath=lambda fullpath: None,
|
||||
get_files_by_savepath=lambda savepath: [],
|
||||
get_by_path=lambda path: None,
|
||||
),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.SystemConfigOper",
|
||||
lambda: SimpleNamespace(get=lambda key: None),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.StorageChain",
|
||||
lambda: SimpleNamespace(
|
||||
delete_media_file=lambda fileitem: delete_calls.append(fileitem.path) or True,
|
||||
),
|
||||
)
|
||||
monkeypatch.setattr("app.chain.transfer.MetaInfoPath", lambda path, custom_words=None: FakeMeta(1))
|
||||
|
||||
state, errmsg = TransferChain.do_transfer(
|
||||
chain,
|
||||
fileitem=main_fileitem,
|
||||
background=False,
|
||||
epformat=EpisodeFormat(format="Show - {ep}.mkv"),
|
||||
cleanup_dest_fileitem=old_dest_fileitem,
|
||||
)
|
||||
|
||||
assert state is True
|
||||
assert errmsg == ""
|
||||
assert delete_calls == [old_dest_fileitem.path]
|
||||
assert planned == [main_fileitem.path]
|
||||
|
||||
|
||||
def test_cleanup_dest_fileitem_is_kept_when_episode_format_matches_nothing(monkeypatch):
|
||||
"""
|
||||
集数定位模板匹配不到文件时,不应清理历史记录中的旧目标文件。
|
||||
"""
|
||||
chain = make_transfer_chain()
|
||||
delete_calls = []
|
||||
source_fileitem = make_fileitem(
|
||||
"/downloads/Test Show (2026)/Show - 01.sc.ass"
|
||||
)
|
||||
old_dest_fileitem = make_fileitem(
|
||||
"/library/Test Show/Show - 01.sc.ass"
|
||||
)
|
||||
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__get_trans_fileitems",
|
||||
lambda fileitem, predicate: [(source_fileitem, False)],
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.SystemConfigOper",
|
||||
lambda: SimpleNamespace(get=lambda key: None),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.StorageChain",
|
||||
lambda: SimpleNamespace(
|
||||
delete_media_file=lambda fileitem: delete_calls.append(fileitem.path) or True,
|
||||
),
|
||||
)
|
||||
|
||||
state, errmsg = TransferChain.do_transfer(
|
||||
chain,
|
||||
fileitem=source_fileitem,
|
||||
background=False,
|
||||
epformat=EpisodeFormat(format="Show - {ep}.mkv"),
|
||||
cleanup_dest_fileitem=old_dest_fileitem,
|
||||
)
|
||||
|
||||
assert state is True
|
||||
assert errmsg == ""
|
||||
assert delete_calls == []
|
||||
|
||||
|
||||
def test_episode_format_matched_but_filtered_by_size_returns_failure(monkeypatch):
|
||||
"""
|
||||
文件名匹配集数定位模板但被大小过滤时,不应误报为模板无匹配的安全跳过。
|
||||
"""
|
||||
chain = make_transfer_chain()
|
||||
source_fileitem = make_fileitem(
|
||||
"/downloads/Test Show (2026)/Show - 01.mkv"
|
||||
)
|
||||
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__get_trans_fileitems",
|
||||
lambda fileitem, predicate: [(source_fileitem, False)],
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.SystemConfigOper",
|
||||
lambda: SimpleNamespace(get=lambda key: None),
|
||||
)
|
||||
|
||||
state, errmsg = TransferChain.do_transfer(
|
||||
chain,
|
||||
fileitem=source_fileitem,
|
||||
background=False,
|
||||
epformat=EpisodeFormat(format="Show - {ep}.mkv"),
|
||||
min_filesize=2,
|
||||
)
|
||||
|
||||
assert state is False
|
||||
assert errmsg == f"{source_fileitem.name} 没有找到可整理的媒体文件"
|
||||
|
||||
|
||||
def test_candidate_collection_checks_continue_callback(monkeypatch):
|
||||
"""
|
||||
候选文件收集阶段应响应取消,避免大目录或远程存储继续完整遍历。
|
||||
"""
|
||||
chain = make_transfer_chain()
|
||||
source_fileitem = make_fileitem(
|
||||
"/downloads/Test Show (2026)/Show - 01.mkv"
|
||||
)
|
||||
callback_calls = []
|
||||
|
||||
def fake_get_trans_fileitems(fileitem, predicate):
|
||||
"""
|
||||
模拟递归收集候选文件时调用 predicate。
|
||||
"""
|
||||
callback_calls.append("collect")
|
||||
predicate(source_fileitem, False)
|
||||
return [(source_fileitem, False)]
|
||||
|
||||
monkeypatch.setattr(
|
||||
chain,
|
||||
"_TransferChain__get_trans_fileitems",
|
||||
fake_get_trans_fileitems,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
"app.chain.transfer.SystemConfigOper",
|
||||
lambda: SimpleNamespace(get=lambda key: None),
|
||||
)
|
||||
|
||||
state, errmsg = TransferChain.do_transfer(
|
||||
chain,
|
||||
fileitem=source_fileitem,
|
||||
background=False,
|
||||
continue_callback=lambda: False,
|
||||
)
|
||||
|
||||
assert state is False
|
||||
assert errmsg == f"{source_fileitem.name} 已取消"
|
||||
assert callback_calls == ["collect"]
|
||||
|
||||
Reference in New Issue
Block a user