Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/app/providers/tmdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,4 +586,16 @@ def episode(media_id, season_number, episode_number):
"image": get_image_url(episode["still_path"]),
}

return None
# Episode not found - throw ProviderAPIError
msg = (
f"Episode {episode_number} not found in season {season_number} "
f"for {Sources.TMDB.label} with ID {media_id}"
)
# Create a new response object with 404 status
not_found_response = requests.Response()
not_found_response.status_code = 404
# Set the error attribute to match what ProviderAPIError expects
not_found_error = type("Error", (), {"response": not_found_response})
raise services.ProviderAPIError(
Sources.TMDB.value, error=not_found_error, details=msg,
)
46 changes: 42 additions & 4 deletions src/app/tests/test_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,13 @@ def test_tmdb_episode(self, mock_tv_with_seasons):
self.assertEqual(result["episode_title"], "Pilot")
self.assertEqual(result["image"], tmdb.get_image_url("/path/to/still1.jpg"))

# Test getting a non-existent episode
result = tmdb.episode("1396", "1", "3")
self.assertIsNone(result)
# Test getting a non-existent episode - should raise ProviderAPIError
with self.assertRaises(services.ProviderAPIError) as cm:
tmdb.episode("1396", "1", "3")

# Verify the error message contains expected details
self.assertIn("Episode 3 not found in season 1", str(cm.exception))
self.assertIn("The Movie Database with ID 1396", str(cm.exception))

# Verify tv_with_seasons was called with correct parameters
mock_tv_with_seasons.assert_called_with("1396", ["1"])
Expand Down Expand Up @@ -565,7 +569,7 @@ def test_manual_episode(self):
episode_number=1,
)

# Test episode metadata
# Test episode metadata for existing episode
response = manual.episode("4", 1, 1)

# Check episode data
Expand All @@ -574,6 +578,10 @@ def test_manual_episode(self):
self.assertEqual(response["season_title"], "Season 1")
self.assertEqual(response["episode_title"], "Special Episode")

# Test episode metadata for non-existing episode
result = manual.episode("4", 1, 2)
self.assertIsNone(result)

def test_manual_process_episodes(self):
"""Test the process_episodes function for manual episodes."""
# Create test data
Expand Down Expand Up @@ -1249,6 +1257,36 @@ def test_get_media_metadata_manual_episode(self, mock_episode):
# Verify the correct function was called
mock_episode.assert_called_once_with("1", 1, "2")

@patch("app.providers.tmdb.episode")
def test_get_media_metadata_tmdb_episode_not_found(self, mock_episode):
"""Test the get_media_metadata function for TMDB episodes that don't exist."""
# Setup mock to raise ProviderAPIError
mock_response = type(
"Response", (), {"status_code": 404, "text": "Episode not found"},
)()
mock_error = type("Error", (), {"response": mock_response})()
mock_episode.side_effect = services.ProviderAPIError(
Sources.TMDB.value,
mock_error,
)

# Call the function and expect ProviderAPIError
with self.assertRaises(services.ProviderAPIError) as cm:
services.get_media_metadata(
MediaTypes.EPISODE.value,
"1396",
Sources.TMDB.value,
season_numbers=[1],
episode_number="3",
)

# Verify the exception contains the correct provider
self.assertEqual(cm.exception.provider, Sources.TMDB.value)

# Verify the correct function was called
mock_episode.assert_called_once_with("1396", 1, "3")


@patch("app.providers.hardcover.book")
def test_get_media_metadata_hardcover_book(self, mock_book):
"""Test the get_media_metadata function for books from Hardcover."""
Expand Down