import unittest from arr_mcp.mcp import mcp_sonarr class FakeSonarrClient: def __init__(self, *, rejected: bool = False) -> None: self.posted = [] self.release = { "guid": "exact-guid", "title": "Murder.She.Wrote.S07.German.AC3D.DL.1080p.WebHD.x265-FuN", "indexer": "Test Indexer", "indexerId": 7, "size": 27_600_000_000, "protocol": "usenet", "downloadAllowed": not rejected, "releaseGroup": "FuN", "seasonNumber": 7, "fullSeason": True, "rejections": ["Existing file has equal or better quality"] if rejected else [], } def get_release(self, **_kwargs): return [dict(self.release)] def get_episode(self, **_kwargs): return [ {"id": 1, "seasonNumber": 7, "episodeNumber": 1, "hasFile": True}, {"id": 2, "seasonNumber": 7, "episodeNumber": 2, "hasFile": False}, ] def post_release(self, data): self.posted.append(data) return data class ReleaseGrabTests(unittest.IsolatedAsyncioTestCase): def setUp(self) -> None: mcp_sonarr._APPROVALS.clear() async def test_exact_release_requires_preview_and_ticket(self) -> None: client = FakeSonarrClient() scope = {"series_id": 42, "season_number": 7, "guid": "exact-guid"} preview = await mcp_sonarr._preview_release_grab(client, scope) self.assertFalse(preview["download_started"]) self.assertEqual(preview["existing_episode_files_in_season"], 1) self.assertTrue(preview["approval_ticket"]) result = await mcp_sonarr._grab_release( client, {**scope, "confirm": True, "approval_ticket": preview["approval_ticket"]}, ) self.assertTrue(result["download_started"]) self.assertFalse(result["replacement_guaranteed"]) self.assertEqual(len(client.posted), 1) self.assertEqual(client.posted[0]["guid"], "exact-guid") async def test_rejected_release_needs_force_in_preview(self) -> None: client = FakeSonarrClient(rejected=True) scope = {"series_id": 42, "season_number": 7, "guid": "exact-guid"} blocked = await mcp_sonarr._preview_release_grab(client, scope) self.assertTrue(blocked["force_required"]) self.assertIsNone(blocked["approval_ticket"]) approved = await mcp_sonarr._preview_release_grab(client, {**scope, "force": True}) self.assertFalse(approved["force_required"]) self.assertTrue(approved["approval_ticket"]) async def test_guid_must_still_match_current_sonarr_results(self) -> None: client = FakeSonarrClient() with self.assertRaisesRegex(ValueError, "no longer present"): await mcp_sonarr._preview_release_grab( client, {"series_id": 42, "season_number": 7, "guid": "different-guid"}, ) async def test_search_can_limit_results_to_group_and_season_pack(self) -> None: client = FakeSonarrClient() client.get_release = lambda **_kwargs: [ dict(client.release), { **client.release, "guid": "episode-guid", "title": "Mord.ist.ihr.Hobby.S07E02.German.1080p-FuN", "fullSeason": False, }, { **client.release, "guid": "other-group", "title": "Mord.ist.ihr.Hobby.S07.German.1080p-HQC", "releaseGroup": "HQC", }, ] result = await mcp_sonarr._search_releases( client, { "series_id": 42, "season_number": 7, "release_group": "FuN", "season_pack_only": True, }, ) self.assertEqual(result["results"]["total"], 1) self.assertEqual(result["results"]["items"][0]["guid"], "exact-guid") if __name__ == "__main__": unittest.main()