Automate repair completion confirmation
This commit is contained in:
@@ -1575,6 +1575,8 @@ class MediaReplacementTests(unittest.IsolatedAsyncioTestCase):
|
||||
radarr.search.assert_awaited_once_with(44)
|
||||
add_activity.assert_called_once()
|
||||
self.assertEqual(add_activity.call_args.kwargs["event_type"], "replacement_started")
|
||||
self.assertIn('"repairTracking"', add_activity.call_args.kwargs["metadata_json"])
|
||||
self.assertIn('"originalFileIds":[77]', add_activity.call_args.kwargs["metadata_json"])
|
||||
update_issue.assert_called_once_with(12, status="in_progress", issue_resolved_at=None)
|
||||
|
||||
async def test_tv_replacement_options_return_only_safe_file_details(self) -> None:
|
||||
@@ -1709,8 +1711,8 @@ class MediaReplacementTests(unittest.IsolatedAsyncioTestCase):
|
||||
{"id": 89, "relativePath": "S01E02.mkv"},
|
||||
]),
|
||||
get_episodes=AsyncMock(return_value=[
|
||||
{"id": 101, "episodeFileId": 88},
|
||||
{"id": 102, "episodeFileId": 89},
|
||||
{"id": 101, "episodeFileId": 88, "seasonNumber": 1, "episodeNumber": 1},
|
||||
{"id": 102, "episodeFileId": 89, "seasonNumber": 1, "episodeNumber": 2},
|
||||
]),
|
||||
monitor_episodes=AsyncMock(return_value={"monitored": True}),
|
||||
delete_episode_file=AsyncMock(return_value=None),
|
||||
@@ -2182,6 +2184,87 @@ class IssueResolutionWorkflowTests(TempDatabaseMixin, unittest.IsolatedAsyncioTe
|
||||
self.assertIsNotNone(closed["issue_resolved_at"])
|
||||
self.assertEqual(db.list_portal_item_activity(int(issue["id"]))[-1]["event_type"], "resolution_confirmed")
|
||||
|
||||
async def test_replacement_waits_for_jellyfin_to_refresh_existing_movie(self) -> None:
|
||||
tracking = {
|
||||
"requestId": "144",
|
||||
"actionId": "replace_media",
|
||||
"mediaType": "movie",
|
||||
"collectorId": 12,
|
||||
"originalFileIds": [40],
|
||||
"episodes": [],
|
||||
"jellyfinFoundAtStart": True,
|
||||
"jellyfinBaseline": [{"Id": "jf-1", "Etag": "old", "Path": "/movies/test.mkv"}],
|
||||
}
|
||||
unchanged = Snapshot(
|
||||
request_id="144",
|
||||
title="Test movie",
|
||||
raw={
|
||||
"arr": {"item": {"id": 12, "hasFile": True, "movieFile": {"id": 41}}},
|
||||
"jellyfin": {
|
||||
"found": True,
|
||||
"item": {"Id": "jf-1", "Etag": "old", "Path": "/movies/test.mkv"},
|
||||
},
|
||||
},
|
||||
)
|
||||
refreshed = unchanged.model_copy(deep=True)
|
||||
refreshed.raw["jellyfin"]["item"]["Etag"] = "new"
|
||||
|
||||
with patch.object(issue_resolution, "build_snapshot", new=AsyncMock(return_value=unchanged)):
|
||||
waiting = await issue_resolution._media_repair_evidence(tracking)
|
||||
with patch.object(issue_resolution, "build_snapshot", new=AsyncMock(return_value=refreshed)):
|
||||
complete = await issue_resolution._media_repair_evidence(tracking)
|
||||
|
||||
self.assertFalse(waiting["complete"])
|
||||
self.assertEqual(waiting["phase"], "indexing")
|
||||
self.assertTrue(complete["complete"])
|
||||
|
||||
async def test_verified_media_repair_starts_confirmation_without_admin(self) -> None:
|
||||
issue = self._create_issue()
|
||||
db.add_portal_item_activity(
|
||||
int(issue["id"]),
|
||||
event_type="replacement_started",
|
||||
actor_username="reporter",
|
||||
actor_role="user",
|
||||
message="Radarr started the replacement.",
|
||||
metadata_json=(
|
||||
'{"repairTracking":{"requestId":"144","actionId":"replace_media",'
|
||||
'"mediaType":"movie","collectorId":12,"originalFileIds":[40],'
|
||||
'"episodes":[],"jellyfinFoundAtStart":true,'
|
||||
'"jellyfinBaseline":[{"Id":"jf-1","Etag":"old"}]}}'
|
||||
),
|
||||
)
|
||||
|
||||
with (
|
||||
patch.object(
|
||||
issue_resolution,
|
||||
"_media_repair_evidence",
|
||||
new=AsyncMock(
|
||||
return_value={
|
||||
"complete": True,
|
||||
"phase": "complete",
|
||||
"message": "Radarr imported the repaired movie and Jellyfin indexed it.",
|
||||
}
|
||||
),
|
||||
),
|
||||
patch.object(
|
||||
issue_resolution,
|
||||
"begin_issue_confirmation",
|
||||
new=AsyncMock(return_value={"status": "awaiting_confirmation"}),
|
||||
) as begin_confirmation,
|
||||
):
|
||||
result = await issue_resolution.process_active_media_repairs()
|
||||
|
||||
self.assertEqual(result["completed"], 1)
|
||||
begin_confirmation.assert_awaited_once_with(
|
||||
int(issue["id"]),
|
||||
actor_username="Magent",
|
||||
actor_role="system",
|
||||
)
|
||||
self.assertEqual(
|
||||
db.list_portal_item_activity(int(issue["id"]))[-1]["event_type"],
|
||||
"repair_verified",
|
||||
)
|
||||
|
||||
async def test_zero_confirmation_emails_closes_issue_immediately(self) -> None:
|
||||
issue = self._create_issue()
|
||||
with patch.object(issue_resolution, "_workflow_settings", return_value=(0, 1, "days")):
|
||||
|
||||
Reference in New Issue
Block a user