165 lines
6.4 KiB
Python
165 lines
6.4 KiB
Python
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from app.features.tasks.definitions.handlers.tver import TverHandler
|
|
from app.features.tasks.definitions.results import TaskResult
|
|
from app.features.tasks.definitions.results import HandleTask
|
|
|
|
|
|
class DummyResponse:
|
|
def __init__(self, data: dict):
|
|
self.data = data
|
|
|
|
def json(self):
|
|
return self.data
|
|
|
|
def raise_for_status(self) -> None:
|
|
return None
|
|
|
|
|
|
class DummyOpts:
|
|
def __init__(self, data):
|
|
self._data = data
|
|
|
|
def get_all(self):
|
|
return self._data
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_tver_handler_extract(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
|
|
"""Test tver handler extraction of episodes from series."""
|
|
session_response = {
|
|
"result": {
|
|
"platform_uid": "test_uid_123",
|
|
"platform_token": "test_token_456",
|
|
}
|
|
}
|
|
|
|
episodes_response = {
|
|
"result": {
|
|
"contents": [
|
|
{
|
|
"seasonTitle": "本編",
|
|
"hasNext": False,
|
|
"contents": [
|
|
{
|
|
"type": "episode",
|
|
"content": {
|
|
"id": "eppcxhym1e",
|
|
"version": 12,
|
|
"title": "木村拓哉がタクシー 運転手!目黒蓮が木村と二人旅",
|
|
"seriesID": "sr1jg44pbb",
|
|
"endAt": 1766404799,
|
|
"broadcastDateLabel": "11月24日(月)放送 分",
|
|
"isNHKContent": False,
|
|
"isSubtitle": False,
|
|
"ribbonID": 0,
|
|
"seriesTitle": "ウルトラタクシー",
|
|
"isAvailable": True,
|
|
"broadcasterName": "TBS",
|
|
"productionProviderName": "TBS",
|
|
"isEndingSoon": False,
|
|
"thumbnailPath": "/images/content/thumbnail/episode/xlarge/eppcxhym1e.jpg?v=84b0ee80",
|
|
},
|
|
"resume": {"lastViewedDuration": 0, "contentDuration": 3796, "completed": False},
|
|
"isFavorite": False,
|
|
"isGood": False,
|
|
"isLater": False,
|
|
"goodCount": 5553,
|
|
},
|
|
{
|
|
"type": "episode",
|
|
"content": {
|
|
"id": "epejwb9mvx",
|
|
"version": 9,
|
|
"title": "木村拓哉がタクシー運転手!蒼井優&上戸彩高校の同級生コンビがディズニーリゾートを大満喫!",
|
|
"seriesID": "sr1jg44pbb",
|
|
"endAt": 1764590399,
|
|
"broadcastDateLabel": "11月24日(月)放送分",
|
|
"isNHKContent": False,
|
|
"isSubtitle": False,
|
|
"ribbonID": 0,
|
|
"seriesTitle": "ウルトラタクシー",
|
|
"isAvailable": True,
|
|
"broadcasterName": "TBS",
|
|
"productionProviderName": "TBS",
|
|
"isEndingSoon": False,
|
|
"thumbnailPath": "/images/content/thumbnail/episode/xlarge/epejwb9mvx.jpg?v=ab478281",
|
|
},
|
|
"resume": {"lastViewedDuration": 0, "contentDuration": 1896, "completed": False},
|
|
"isFavorite": False,
|
|
"isGood": False,
|
|
"isLater": False,
|
|
"goodCount": 1298,
|
|
},
|
|
],
|
|
}
|
|
],
|
|
"seasons": [
|
|
{
|
|
"type": "season",
|
|
"content": {"id": "sshbu1ycq8", "version": 2, "title": "本編", "season_extended": None},
|
|
}
|
|
],
|
|
}
|
|
}
|
|
|
|
call_count = 0
|
|
|
|
async def fake_request(url: str, **kwargs): # noqa: ARG001
|
|
nonlocal call_count
|
|
call_count += 1
|
|
|
|
if "browser/create" in url:
|
|
return DummyResponse(session_response)
|
|
|
|
if "callSeriesEpisodes" in url:
|
|
return DummyResponse(episodes_response)
|
|
|
|
msg = f"Unexpected URL: {url}"
|
|
raise RuntimeError(msg)
|
|
|
|
archive_path = tmp_path / "archive.txt"
|
|
|
|
monkeypatch.setattr(TverHandler, "request", staticmethod(fake_request))
|
|
monkeypatch.setattr(HandleTask, "get_ytdlp_opts", lambda _: DummyOpts({"download_archive": str(archive_path)}))
|
|
|
|
task = HandleTask(id=1, name="Test Tver Series", url="https://tver.jp/series/sr8sb9pnhc", preset="default")
|
|
|
|
result = await TverHandler.extract(task)
|
|
|
|
assert isinstance(result, TaskResult)
|
|
assert len(result.items) == 2
|
|
assert result.items[0].url == "https://tver.jp/episodes/eppcxhym1e"
|
|
assert "木村拓哉がタクシー 運転手!目黒蓮が木村と二人旅" == result.items[0].title
|
|
|
|
assert result.items[1].url == "https://tver.jp/episodes/epejwb9mvx"
|
|
assert (
|
|
"木村拓哉がタクシー運転手!蒼井優&上戸彩高校の同級生コンビがディズニーリゾートを大満喫!"
|
|
== result.items[1].title
|
|
)
|
|
|
|
assert result.metadata.get("has_entries") is True
|
|
assert "callSeriesEpisodes" in result.metadata.get("feed_url", "")
|
|
assert call_count == 2
|
|
|
|
|
|
@pytest.mark.parametrize(("url", "should_match"), TverHandler.tests())
|
|
def test_parse(url: str, should_match: bool) -> None:
|
|
"""Test tver URL parsing."""
|
|
result = TverHandler.parse(url)
|
|
if should_match:
|
|
assert result is not None
|
|
assert result.startswith("sr")
|
|
else:
|
|
assert result is None
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_can_handle() -> None:
|
|
"""Test tver handler can_handle method."""
|
|
task_valid = HandleTask(id=1, name="Test", url="https://tver.jp/series/sr8sb9pnhc", preset="default")
|
|
task_invalid = HandleTask(id=2, name="Test", url="https://youtube.com/watch?v=123", preset="default")
|
|
assert await TverHandler.can_handle(task_valid) is True
|
|
assert await TverHandler.can_handle(task_invalid) is False
|