from types import SimpleNamespace from app.chain.transfer import TransferChain from app.domain.context import MediaInfo from app.domain.metainfo import MetaInfo from app.schemas import FileItem, TransferDirectoryConf from app.application.transfer import TransferTask from app.schemas.types import MediaSource, MediaType def test_transfer_rejects_partial_or_invalid_explicit_identity() -> None: """整理公共入口不得把半套身份或格式非法来源传入后台任务。""" chain = object.__new__(TransferChain) fileitem = FileItem( storage="local", path="/downloads/Test.Movie.2024.mkv", type="file", ) partial_state, partial_message = chain.do_transfer( fileitem=fileitem, media_source=MediaSource.TMDB, ) invalid_state, invalid_message = chain.do_transfer( fileitem=fileitem, media_source="plugin source:invalid", media_id="1234", ) assert not partial_state assert "media_source" in partial_message assert not invalid_state assert "media_source" in invalid_message def test_transfer_resolves_complete_identity_before_building_tasks(monkeypatch) -> None: """整理入口收到完整身份时应精确识别,失败后不得退化为标题识别。""" chain = object.__new__(TransferChain) fileitem = FileItem( storage="local", path="/downloads/Test.Movie.2024.mkv", type="file", ) recognize = monkeypatch.setattr calls = [] class FakeMediaChain: """记录精确识别参数并返回空结果。""" def recognize_media(self, **kwargs): """模拟显式身份识别失败。""" calls.append(kwargs) return None recognize("app.chain.transfer.MediaChain", FakeMediaChain) state, message = chain.do_transfer( fileitem=fileitem, media_source="tmdb", media_id="1234", mtype=MediaType.MOVIE, ) assert not state assert "未识别到媒体信息" in message assert calls == [{ "mtype": MediaType.MOVIE, "media_source": MediaSource.TMDB, "media_id": "1234", "music_type": None, }] def test_transfer_stops_when_automatic_category_has_no_tmdb_result(monkeypatch) -> None: """启用自动类别目录时,缺少 TMDB 分类必须在文件操作前明确失败。""" chain = object.__new__(TransferChain) chain.jobview = SimpleNamespace(try_remove_job=lambda _task: None) monkeypatch.setattr( "app.chain.transfer.TransferHistoryOper", lambda: SimpleNamespace(), ) monkeypatch.setattr("app.chain._transfer.TransferHistoryOper", lambda: SimpleNamespace()) monkeypatch.setattr( "app.chain.transfer.MediaChain", lambda: SimpleNamespace( supplement_tmdb_info=lambda media, _meta: media, ), ) monkeypatch.setattr("app.chain._transfer.MediaChain", lambda: SimpleNamespace( supplement_tmdb_info=lambda media, _meta: media, )) task = TransferTask( fileitem=FileItem( storage="local", path="/downloads/Test.Movie.2024.mkv", type="file", name="Test.Movie.2024.mkv", extension="mkv", size=1024, ), meta=MetaInfo("Test Movie 2024"), mediainfo=MediaInfo( media_source=MediaSource.AniList, media_id="1234", anilist_id=1234, type=MediaType.MOVIE, title="Test Movie", year="2024", ), target_directory=TransferDirectoryConf( library_storage="local", library_path="/library", library_category_folder=True, ), library_category_folder=True, preview=True, ) state, message = chain._TransferChain__handle_transfer(task) assert not state assert message == "未识别到 TMDB 辅助信息,无法按媒体类别整理" assert task.mediainfo.media_source == MediaSource.AniList assert task.mediainfo.media_id == "1234"