Add watchlist episode offset naming
This commit is contained in:
+123
-1
@@ -365,6 +365,42 @@ class QueueApiTests(unittest.TestCase):
|
||||
self.assertFalse(source.exists())
|
||||
self.assertTrue(Path(moved[0]).exists())
|
||||
|
||||
def test_tv_finalizer_applies_episode_offset_to_named_files(self):
|
||||
with tempfile.TemporaryDirectory() as temp_root:
|
||||
job = APP.app_support.build_job(
|
||||
{
|
||||
"query": "Split Season Show",
|
||||
"title": "Split Season Show",
|
||||
"anime_name": "Split Season Show",
|
||||
"media_type": "tv",
|
||||
"mode": "sub",
|
||||
"quality": "best",
|
||||
"episodes": "1-2",
|
||||
"download_dir": temp_root,
|
||||
"season": "2",
|
||||
"episode_offset": "13",
|
||||
},
|
||||
{"mode": "sub", "quality": "best", "download_dir": temp_root},
|
||||
)
|
||||
staging_dir = APP.app_support.job_staging_dir(job)
|
||||
staging_dir.mkdir(parents=True, exist_ok=True)
|
||||
first = staging_dir / "Split Season Show Episode 1.mp4"
|
||||
second = staging_dir / "Split Season Show Episode 2.mp4"
|
||||
first.write_bytes(b"ep1")
|
||||
second.write_bytes(b"ep2")
|
||||
|
||||
moved = APP.app_support.finalize_library_files(job)
|
||||
|
||||
self.assertEqual(
|
||||
moved,
|
||||
[
|
||||
f"{temp_root}/tv/Split Season Show/Season 02/Split Season Show - S02E13.mp4",
|
||||
f"{temp_root}/tv/Split Season Show/Season 02/Split Season Show - S02E14.mp4",
|
||||
],
|
||||
)
|
||||
self.assertTrue(Path(moved[0]).exists())
|
||||
self.assertTrue(Path(moved[1]).exists())
|
||||
|
||||
def test_shutdown_wait_cancels_active_process_for_deterministic_teardown(self):
|
||||
queue = object.__new__(APP.DownloadQueue)
|
||||
queue.lock = threading.RLock()
|
||||
@@ -1113,6 +1149,14 @@ class WatchlistCompletionTests(unittest.TestCase):
|
||||
|
||||
self.assertEqual(result["item"]["auto_download_series"], "4")
|
||||
|
||||
def test_add_uses_requested_auto_download_offset(self):
|
||||
with mock.patch.object(APP.WATCHLIST, "schedule_refresh", side_effect=lambda show_id, source="manual": APP.WATCHLIST.get(show_id)):
|
||||
result = APP.WATCHLIST.add(
|
||||
{"show_id": "show-23b", "title": "Queued Show", "category": "watching", "auto_download_offset": "13"}
|
||||
)
|
||||
|
||||
self.assertEqual(result["item"]["auto_download_offset"], "13")
|
||||
|
||||
def test_add_uses_requested_media_type(self):
|
||||
with mock.patch.object(APP.WATCHLIST, "schedule_refresh", side_effect=lambda show_id, source="manual": APP.WATCHLIST.get(show_id)):
|
||||
result = APP.WATCHLIST.add(
|
||||
@@ -1202,6 +1246,7 @@ class WatchlistCompletionTests(unittest.TestCase):
|
||||
"anime_name": "Queue Show Library",
|
||||
"media_type": "movie",
|
||||
"season": "4",
|
||||
"episode_offset": None,
|
||||
"index": 3,
|
||||
"mode": "dub",
|
||||
"quality": "best",
|
||||
@@ -1699,6 +1744,7 @@ class AutoDownloadQueueTests(unittest.TestCase):
|
||||
"auto_download_quality": "best",
|
||||
"auto_download_name": 'Queue Show: Alt/Name',
|
||||
"auto_download_series": "3",
|
||||
"auto_download_offset": "13",
|
||||
"downloaded_dub_episodes": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
|
||||
"downloaded_sub_episodes": [],
|
||||
}
|
||||
@@ -1733,6 +1779,7 @@ class AutoDownloadQueueTests(unittest.TestCase):
|
||||
"anime_name": "Queue Show- Alt-Name",
|
||||
"media_type": "tv",
|
||||
"season": "3",
|
||||
"episode_offset": "13",
|
||||
"index": 2,
|
||||
"mode": "dub",
|
||||
"quality": "best",
|
||||
@@ -1754,6 +1801,7 @@ class AutoDownloadQueueTests(unittest.TestCase):
|
||||
"auto_download_quality": "best",
|
||||
"auto_download_name": "Backlog Show",
|
||||
"auto_download_series": "1",
|
||||
"auto_download_offset": None,
|
||||
"downloaded_dub_episodes": [],
|
||||
"downloaded_sub_episodes": [],
|
||||
}
|
||||
@@ -1778,6 +1826,76 @@ class AutoDownloadQueueTests(unittest.TestCase):
|
||||
|
||||
self.assertTrue(result["queued"])
|
||||
self.assertEqual(result["episodes"], ["1-3"])
|
||||
download_queue.add.assert_called_once_with(
|
||||
{
|
||||
"show_id": "show-99",
|
||||
"query": "Backlog Show",
|
||||
"title": "Backlog Show",
|
||||
"anime_name": "Backlog Show",
|
||||
"media_type": "tv",
|
||||
"season": "1",
|
||||
"episode_offset": None,
|
||||
"index": 1,
|
||||
"mode": "dub",
|
||||
"quality": "best",
|
||||
"episodes": "1-3",
|
||||
"download_dir": "/tmp/downloads",
|
||||
}
|
||||
)
|
||||
|
||||
def test_queue_watchlist_auto_download_passes_episode_offset_to_jobs(self):
|
||||
item = {
|
||||
"show_id": "show-77",
|
||||
"title": "Split Season Show",
|
||||
"category": "watching",
|
||||
"previous_last_checked": "2026-05-25T10:00:00+00:00",
|
||||
"had_new_episodes": False,
|
||||
"dub_episode_values": ["1", "2"],
|
||||
"sub_episode_values": [],
|
||||
"auto_download_mode": "dub",
|
||||
"auto_download_quality": "best",
|
||||
"auto_download_name": "Split Season Show",
|
||||
"auto_download_series": "2",
|
||||
"auto_download_offset": "13",
|
||||
"downloaded_dub_episodes": [],
|
||||
"downloaded_sub_episodes": [],
|
||||
}
|
||||
download_queue = mock.Mock()
|
||||
download_queue.covered_episodes.return_value = set()
|
||||
download_queue.add.return_value = {"id": "job-split", "episodes": "1-2"}
|
||||
runtime = {
|
||||
"config": {
|
||||
"auto_download_enabled": True,
|
||||
"auto_download_mode": "dub",
|
||||
"auto_download_quality": "best",
|
||||
"download_dir": "/tmp/downloads",
|
||||
},
|
||||
"download_queue": download_queue,
|
||||
}
|
||||
with mock.patch.object(APP, "ensure_runtime", return_value=runtime), mock.patch.object(
|
||||
APP,
|
||||
"search_anime",
|
||||
return_value=[{"id": "show-77", "title": "Split Season Show", "query": "Split Season Show", "index": 1}],
|
||||
):
|
||||
result = APP.queue_watchlist_auto_download(item, refresh_source="manual")
|
||||
|
||||
self.assertTrue(result["queued"])
|
||||
download_queue.add.assert_called_once_with(
|
||||
{
|
||||
"show_id": "show-77",
|
||||
"query": "Split Season Show",
|
||||
"title": "Split Season Show",
|
||||
"anime_name": "Split Season Show",
|
||||
"media_type": "tv",
|
||||
"season": "2",
|
||||
"episode_offset": "13",
|
||||
"index": 1,
|
||||
"mode": "dub",
|
||||
"quality": "best",
|
||||
"episodes": "1-2",
|
||||
"download_dir": "/tmp/downloads",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class StartupBehaviorTests(unittest.TestCase):
|
||||
@@ -2119,13 +2237,16 @@ class HandlerRouteTests(unittest.TestCase):
|
||||
self.assertEqual(handler.json_status, HTTPStatus.CREATED)
|
||||
|
||||
def test_watchlist_auto_download_settings_post_returns_updated_item(self):
|
||||
body = b'{"show_id":"show-1","mode":"dub","quality":"best","name":"Example Name","series":"2"}'
|
||||
body = b'{"show_id":"show-1","mode":"dub","quality":"best","name":"Example Name","series":"2","episode_offset":"13"}'
|
||||
handler = DummyHandler("/api/watchlist/update-auto-download", body=body, content_length=len(body))
|
||||
payload = {"message": "Saved auto-download settings for Show 1.", "item": {"show_id": "show-1"}}
|
||||
handler.handler_context = mock.Mock(update_watchlist_auto_download=mock.Mock(return_value=payload))
|
||||
APP.Handler.do_POST(handler)
|
||||
self.assertEqual(handler.json_payload, payload)
|
||||
self.assertEqual(handler.json_status, HTTPStatus.OK)
|
||||
handler.handler_context.update_watchlist_auto_download.assert_called_once_with(
|
||||
"show-1", "dub", "best", "Example Name", "2", "13"
|
||||
)
|
||||
|
||||
def test_watchlist_media_type_post_returns_updated_item(self):
|
||||
body = b'{"show_id":"show-1","media_type":"movie"}'
|
||||
@@ -2273,6 +2394,7 @@ class TemplateHelperTests(unittest.TestCase):
|
||||
self.assertIn('class="wide-half">Name', APP.WATCHLIST_HTML)
|
||||
self.assertIn("Custom", APP.WATCHLIST_HTML)
|
||||
self.assertIn("Series", APP.WATCHLIST_HTML)
|
||||
self.assertIn("Episode offset", APP.WATCHLIST_HTML)
|
||||
|
||||
def test_watchlist_thumbnail_warmup_skips_repeated_attempts(self):
|
||||
self.assertIn("thumbnailWarmupPending: new Set()", APP.WATCHLIST_HTML)
|
||||
|
||||
Reference in New Issue
Block a user