Files
MoviePilot/tests/test_recognize_source_selection.py
T
jxxghp 6504cb36f5 fix(recognize): 修复识别测试仅传数据源时被成对身份校验误拒,名称识别与临时识别词恢复生效
- 8bf2f601 引入的显式身份成对校验把'仅传 media_source'也视为显式身份,识别测试恒传数据源导致直接返回未识别
- 成对约束仅在显式传 media_id 时生效;仅传数据源时保留为请求级识别源约束,按名称在指定数据源内识别
- 字符串来源经 normalize_media_source 规范,meta 自带同源身份(如 {tmdbid=})时优先按身份识别
- 新增 tests/test_recognize_source_selection.py 覆盖 source-only、同源身份采纳与成对拒绝场景
2026-08-16 05:36:40 +08:00

147 lines
5.5 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.
# -*- coding: utf-8 -*-
"""识别测试类请求的数据源选择回归测试。
识别测试(名称测试)前端只传请求级数据源 media_source,不携带 media_id
该路径必须按名称在指定数据源内识别,而不是被"显式身份必须成对"规则拦截。
"""
import asyncio
from unittest.mock import AsyncMock, Mock, patch
from app.chain import ChainBase
from app.domain.context import MediaInfo
from app.domain.metainfo import MetaInfo
from app.schemas.types import MediaSource, MediaType
# 用户反馈的识别测试失败样例
FAILING_TITLE = "[ANI] 關於我轉生變成史萊姆這檔事 第四季 - 90 [1080P][Baha][WEB-DL][AAC AVC][CHT].mp4"
def _tmdb_media() -> MediaInfo:
"""构造带 TMDB 身份的识别结果。"""
return MediaInfo(
media_source=MediaSource.TMDB,
media_id="120089",
tmdb_id=120089,
title="关于我转生变成史莱姆这档事",
type=MediaType.TV,
)
def test_recognize_media_with_source_only_uses_name_search():
"""仅传 media_source 时应按名称在指定数据源识别,不得直接拒绝。"""
chain = ChainBase()
meta = MetaInfo(FAILING_TITLE)
captured = {}
def fake_native(module_kwargs, cache):
captured.update(module_kwargs)
return _tmdb_media()
with patch.object(chain, "_run_native_media_recognize", side_effect=fake_native), \
patch.object(chain, "_supplement_media_recognize", side_effect=lambda **kw: kw["mediainfo"]), \
patch("app.chain.MoviePilotServerHelper"):
result = chain.recognize_media(meta=meta, media_source=MediaSource.TMDB, cache=False)
assert result is not None
assert result.tmdb_id == 120089
# 数据源约束透传到模块层,且无显式 ID
assert captured["media_source"] == MediaSource.TMDB
assert captured["media_id"] is None
# 名称识别应沿用 meta 推断的类型
assert captured["mtype"] == MediaType.TV
def test_async_recognize_media_with_source_only_uses_name_search():
"""异步入口与同步入口保持同一语义。"""
chain = ChainBase()
meta = MetaInfo(FAILING_TITLE)
captured = {}
async def fake_native(module_kwargs, cache):
captured.update(module_kwargs)
return _tmdb_media()
async def fake_supplement(**kwargs):
return kwargs["mediainfo"]
# 异步路径上报共享识别为协程,需要可 await 的桩
helper = Mock()
helper.async_report_recognize_share = AsyncMock()
with patch.object(chain, "_async_run_native_media_recognize", side_effect=fake_native), \
patch.object(chain, "_async_supplement_media_recognize", side_effect=fake_supplement), \
patch("app.chain.MoviePilotServerHelper", helper):
result = asyncio.run(
chain.async_recognize_media(meta=meta, media_source=MediaSource.TMDB, cache=False)
)
assert result is not None
assert result.tmdb_id == 120089
assert captured["media_source"] == MediaSource.TMDB
assert captured["media_id"] is None
def test_recognize_media_accepts_string_source_only():
"""第三方客户端可能传字符串数据源,应规范为枚举后按名称识别。"""
chain = ChainBase()
meta = MetaInfo(FAILING_TITLE)
captured = {}
def fake_native(module_kwargs, cache):
captured.update(module_kwargs)
return _tmdb_media()
with patch.object(chain, "_run_native_media_recognize", side_effect=fake_native), \
patch.object(chain, "_supplement_media_recognize", side_effect=lambda **kw: kw["mediainfo"]), \
patch("app.chain.MoviePilotServerHelper"):
result = chain.recognize_media(meta=meta, media_source="themoviedb", cache=False)
assert result is not None
assert captured["media_source"] == MediaSource.TMDB
def test_recognize_media_meta_identity_same_source_uses_id():
"""仅传数据源且 meta 自带同源身份(如 {tmdbid=})时应直接按身份识别。"""
chain = ChainBase()
meta = MetaInfo("空之境界 第五章 矛盾螺旋 (2008) {tmdbid=23155}")
captured = {}
def fake_native(module_kwargs, cache):
captured.update(module_kwargs)
return _tmdb_media()
with patch.object(chain, "_run_native_media_recognize", side_effect=fake_native), \
patch.object(chain, "_supplement_media_recognize", side_effect=lambda **kw: kw["mediainfo"]), \
patch("app.chain.MoviePilotServerHelper"):
result = chain.recognize_media(meta=meta, media_source=MediaSource.TMDB, cache=False)
assert result is not None
assert captured["media_source"] == MediaSource.TMDB
assert captured["media_id"] == "23155"
def test_recognize_media_media_id_without_source_still_rejected():
"""显式 media_id 缺少有效来源时仍应拒绝,成对约束不放宽。"""
chain = ChainBase()
native = Mock()
with patch.object(chain, "_run_native_media_recognize", native):
result = chain.recognize_media(meta=MetaInfo("任意标题"), media_id="12345")
assert result is None
native.assert_not_called()
def test_recognize_media_invalid_pair_still_rejected():
"""media_id 为 0 等无效值与来源组合仍应拒绝。"""
chain = ChainBase()
native = Mock()
with patch.object(chain, "_run_native_media_recognize", native):
result = chain.recognize_media(
meta=MetaInfo("任意标题"), media_source=MediaSource.TMDB, media_id="0"
)
assert result is None
native.assert_not_called()