diff --git a/tests/test_dicmusic_indexer.py b/tests/test_dicmusic_indexer.py new file mode 100644 index 000000000..36e1b88b8 --- /dev/null +++ b/tests/test_dicmusic_indexer.py @@ -0,0 +1,118 @@ +from typing import Any, NoReturn +from unittest.mock import patch + +import pytest + +from app.adapters.system import rust as rust_accel +from app.modules.indexer.spider import SiteSpider +from app.schemas.types import MediaType + +DICMUSIC_HTML = """ + + + + + + + + + + +
+ + DL + + BTS - ARIRANG + today1.00 GiB2482
+ +""" + + +def _dicmusic_indexer() -> dict[str, Any]: + """构造与 DIC Music 资源配置一致的非分组 Gazelle 索引器。""" + detail_selector = 'a[href*="torrents.php?id="][href*="torrentid="]' + return { + "id": "dicmusic", + "name": "海豚", + "domain": "https://dicmusic.com/", + "media_type": "music", + "schema": "Gazelle", + "search": { + "paths": [{"path": "torrents.php", "method": "get"}], + "params": { + "searchsubmit": 1, + "group_results": 0, + "searchstr": "{keyword}", + }, + }, + "torrents": { + "list": {"selector": "table#torrent_table > tbody > tr.torrent"}, + "fields": { + "id": { + "selector": detail_selector, + "attribute": "href", + "filters": [ + {"name": "re_search", "args": [r"torrentid=(\d+)", 1]} + ], + }, + "title": {"selector": detail_selector}, + "details": {"selector": detail_selector, "attribute": "href"}, + "download": { + "selector": 'a[href*="torrents.php?action=download"]', + "attribute": "href", + }, + "size": {"selector": "td.td_size"}, + "seeders": {"selector": "td.td_seeders"}, + "leechers": {"selector": "td.td_leechers"}, + "grabs": {"selector": "td.td_snatched"}, + "date_elapsed": { + "selector": "td.td_time > span", + "attribute": "title", + "optional": True, + }, + "date": { + "text": "{% if fields['date_elapsed'] %}{{ fields['date_elapsed'] }}{% else %}now{% endif %}", + "filters": [{"name": "dateparse", "args": "%b %d %Y, %H:%M"}], + }, + }, + }, + } + + +def test_dicmusic_search_uses_complete_music_title_in_python_fallback() -> None: + """DIC Music Python 兜底解析应从非分组行保留完整音乐名。""" + with patch( + "app.modules.indexer.spider.rust_accel.parse_indexer_torrents", + return_value=None, + ): + results = SiteSpider( + _dicmusic_indexer(), keyword="ARIRANG", mtype=MediaType.MUSIC + ).parse(DICMUSIC_HTML) + + assert len(results) == 1 + assert results[0]["title"] == "BTS - ARIRANG" + assert results[0]["page_url"].endswith("torrents.php?id=123&torrentid=456") + assert results[0]["enclosure"].endswith("torrents.php?action=download&id=456") + + +def test_dicmusic_search_uses_complete_music_title_in_rust_parser( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """DIC Music Rust 解析应与 Python 解析共享完整音乐名。""" + if not rust_accel.is_available(): + pytest.skip("moviepilot_rust 扩展未安装") + + monkeypatch.setattr(rust_accel, "is_enabled", lambda: True) + + def fail_python_fallback(*_args: object, **_kwargs: object) -> NoReturn: + """Rust 解析异常回退时让测试显式失败。""" + raise AssertionError("DIC Music Rust 解析不应回退 Python") + + monkeypatch.setattr(SiteSpider, "get_info", fail_python_fallback) + + results = SiteSpider( + _dicmusic_indexer(), keyword="ARIRANG", mtype=MediaType.MUSIC + ).parse(DICMUSIC_HTML) + + assert len(results) == 1 + assert results[0]["title"] == "BTS - ARIRANG"