Harden queue identity and Jellyfin move checks
This commit is contained in:
+63
-1
@@ -1279,6 +1279,37 @@ class WatchlistCompletionTests(unittest.TestCase):
|
||||
self.assertEqual(prepared["show_id"], "show-42")
|
||||
self.assertEqual(prepared["title"], "Queue Show Season 2")
|
||||
|
||||
def test_prepare_download_job_resolves_unique_match_without_result_index(self):
|
||||
job = {"query": "Queue Show", "mode": "sub", "title": "Queue Show", "show_id": ""}
|
||||
|
||||
with mock.patch.object(
|
||||
APP,
|
||||
"search_anime",
|
||||
return_value=[
|
||||
{"id": "show-42", "title": "Queue Show"},
|
||||
{"id": "show-99", "title": "Different Show"},
|
||||
],
|
||||
):
|
||||
prepared = APP.prepare_download_job(dict(job))
|
||||
|
||||
self.assertEqual(prepared["show_id"], "show-42")
|
||||
self.assertEqual(prepared["title"], "Queue Show")
|
||||
|
||||
def test_prepare_download_job_skips_ambiguous_match_without_result_index(self):
|
||||
job = {"query": "Queue Show", "mode": "sub", "title": "Queue Show", "show_id": ""}
|
||||
|
||||
with mock.patch.object(
|
||||
APP,
|
||||
"search_anime",
|
||||
return_value=[
|
||||
{"id": "show-42", "title": "Queue Show"},
|
||||
{"id": "show-99", "title": "Queue Show (2024)"},
|
||||
],
|
||||
):
|
||||
prepared = APP.prepare_download_job(dict(job))
|
||||
|
||||
self.assertEqual(prepared["show_id"], "")
|
||||
|
||||
def test_command_for_job_omits_result_switch_when_result_index_missing(self):
|
||||
job = APP.app_support.build_job(
|
||||
{
|
||||
@@ -1448,11 +1479,13 @@ class JellyfinSyncTests(unittest.TestCase):
|
||||
self.assertEqual(send_webhook.call_args.args[2]["reason"], "target_missing")
|
||||
|
||||
def test_trigger_jellyfin_sync_for_item_skips_already_moved_notification(self):
|
||||
self.seed_watchlist_item()
|
||||
self.seed_watchlist_item(expected_count=1, dub_count=1, downloaded_dub_episodes_json=APP.encode_episode_values(["1"]))
|
||||
item = APP.WATCHLIST.get("show-jelly-1")
|
||||
with tempfile.TemporaryDirectory() as temp_root:
|
||||
jellyfin_tv = Path(temp_root) / "jellyfin-tv" / "Jelly Show"
|
||||
jellyfin_tv.mkdir(parents=True, exist_ok=True)
|
||||
(jellyfin_tv / "Season 01").mkdir(parents=True, exist_ok=True)
|
||||
(jellyfin_tv / "Season 01" / "Jelly Show - S01E01.mp4").write_bytes(b"episode-data")
|
||||
with mock.patch.object(APP, "send_discord_webhook_event") as send_webhook:
|
||||
result = APP.trigger_jellyfin_sync_for_item(
|
||||
item,
|
||||
@@ -1471,6 +1504,31 @@ class JellyfinSyncTests(unittest.TestCase):
|
||||
self.assertEqual(result["reason"], "already_moved")
|
||||
send_webhook.assert_not_called()
|
||||
|
||||
def test_trigger_jellyfin_sync_for_item_flags_incomplete_target_when_source_missing(self):
|
||||
self.seed_watchlist_item(expected_count=12, dub_count=12)
|
||||
item = APP.WATCHLIST.get("show-jelly-1")
|
||||
with tempfile.TemporaryDirectory() as temp_root:
|
||||
jellyfin_tv = Path(temp_root) / "jellyfin-tv" / "Jelly Show"
|
||||
jellyfin_tv.mkdir(parents=True, exist_ok=True)
|
||||
with mock.patch.object(APP, "send_discord_webhook_event") as send_webhook:
|
||||
result = APP.trigger_jellyfin_sync_for_item(
|
||||
item,
|
||||
automatic=False,
|
||||
config={
|
||||
"download_dir": str(Path(temp_root) / "downloads"),
|
||||
"jellyfin_sync_enabled": True,
|
||||
"jellyfin_tv_dir": str(Path(temp_root) / "jellyfin-tv"),
|
||||
"jellyfin_movie_dir": "",
|
||||
"discord_webhook_url": "https://discord.example/webhook",
|
||||
"discord_webhook_events": ["jellyfin_sync_failed"],
|
||||
},
|
||||
)
|
||||
|
||||
self.assertFalse(result["moved"])
|
||||
self.assertEqual(result["reason"], "target_incomplete")
|
||||
send_webhook.assert_called_once()
|
||||
self.assertEqual(send_webhook.call_args.args[1], "jellyfin_sync_failed")
|
||||
|
||||
def test_trigger_jellyfin_sync_for_item_skips_incomplete_series(self):
|
||||
self.seed_watchlist_item(
|
||||
expected_count=12,
|
||||
@@ -2568,6 +2626,10 @@ class TemplateHelperTests(unittest.TestCase):
|
||||
def test_search_page_sends_watchlist_auto_download_series(self):
|
||||
self.assertIn('auto_download_series: $("seasonInput").value || "1"', APP.INDEX_HTML)
|
||||
|
||||
def test_search_page_queues_selected_title_without_result_index(self):
|
||||
self.assertIn('query: state.selected.title,', APP.INDEX_HTML)
|
||||
self.assertNotIn('index: state.selected.index,', APP.INDEX_HTML)
|
||||
|
||||
def test_pages_share_serial_polling_helper(self):
|
||||
self.assertIn("function startSerialPoll(callback, intervalMs)", APP.QUEUE_HTML)
|
||||
self.assertIn("function startSerialPoll(callback, intervalMs)", APP.WATCHLIST_HTML)
|
||||
|
||||
Reference in New Issue
Block a user