diff --git a/app/deleterr.py b/app/deleterr.py index 81ba82c..0074c1a 100644 --- a/app/deleterr.py +++ b/app/deleterr.py @@ -34,7 +34,7 @@ def __init__(self, config): self.process_radarr() def delete_series(self, sonarr, sonarr_show): - ## PyArr doesn't support deleting the series files, so we need to do it manually + # PyArr doesn't support deleting the series files, so we need to do it manually episodes = sonarr.get_episode(sonarr_show["id"], series=True) # Mark all episodes as unmonitored so they don't get re-downloaded while we're deleting them diff --git a/app/media_cleaner.py b/app/media_cleaner.py index 29a7f9e..c7fd486 100644 --- a/app/media_cleaner.py +++ b/app/media_cleaner.py @@ -3,8 +3,7 @@ from app import logger from app.utils import print_readable_freed_space, parse_size_to_bytes -from datetime import datetime, timedelta -from plexapi.exceptions import NotFound +from datetime import datetime from plexapi.server import PlexServer from app.modules.trakt import Trakt from app.modules.tautulli import Tautulli diff --git a/requirements.txt b/requirements.txt index daf726e..ed5267d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ PyYAML==6.0.1 requests==2.31.0 tautulli==3.6.0.2120 trakt.py==4.4.0 -coverage==6.3 \ No newline at end of file +coverage==6.3 +pytest-mock==3.6.1 \ No newline at end of file diff --git a/tests/test_media_cleaner.py b/tests/test_media_cleaner.py index 92c6f77..06306b8 100644 --- a/tests/test_media_cleaner.py +++ b/tests/test_media_cleaner.py @@ -1,5 +1,5 @@ import unittest - +import pytest from app.media_cleaner import ( find_watched_data, library_meets_disk_space_threshold, @@ -7,6 +7,31 @@ DEFAULT_MAX_ACTIONS_PER_RUN, ) from unittest.mock import Mock, patch, MagicMock +from app.config import Config +from app.modules import trakt, tautulli +from plexapi.server import PlexServer + + +@pytest.fixture +def standard_config(): + return MagicMock( + settings={ + "max_actions_per_run": 10, + "library": { + "name": "Test Library", + "exclude": {}, + "max_age_days": 30, + "max_size_gb": 500, + "min_disk_space_gb": 100, + }, + "sonarr": {"api_key": "test_api_key", "url": "http://localhost:8989"}, + "plex": { + "url": "http://localhost:32400", + "api_key": "test_api_key", + }, + "tautulli": {"url": "http://localhost:8181", "api_key": "test_api_key"}, + } + ) class TestLibraryMeetsDiskSpaceThreshold(unittest.TestCase): @@ -96,70 +121,70 @@ def test_no_match(self): self.assertIsNone(find_watched_data(plex_media_item, self.activity_data)) -class TestMediaCleaner(unittest.TestCase): - @patch("app.media_cleaner.logger") - @patch.object(MediaCleaner, "process_shows") - @patch.object(MediaCleaner, "get_show_activity") - @patch.object(MediaCleaner, "get_plex_library") - @patch.object(MediaCleaner, "get_trakt_items") - @patch.object(MediaCleaner, "filter_shows") - @patch("app.media_cleaner._get_config_value") - @patch("app.media_cleaner.library_meets_disk_space_threshold") - def test_process_library( - self, - mock_library_meets_disk_space_threshold, - mock_get_config_value, - mock_filter_shows, - mock_get_trakt_items, - mock_get_plex_library, - mock_get_show_activity, - mock_process_shows, - mock_logger, - ): - # Arrange - media_cleaner = MediaCleaner({}) - library = {"name": "Test Library"} - sonarr_instance = Mock() - unfiltered_all_show_data = MagicMock() - - mock_library_meets_disk_space_threshold.return_value = True - mock_get_config_value.return_value = 10 - mock_filter_shows.return_value = MagicMock() - - mock_get_trakt_items.return_value = MagicMock() - mock_get_plex_library.return_value = MagicMock(totalSize=20) - mock_get_show_activity.return_value = MagicMock() - mock_process_shows.return_value = 5 - - # Act - result = media_cleaner.process_library( - library, sonarr_instance, unfiltered_all_show_data - ) - - # Assert - mock_library_meets_disk_space_threshold.assert_called_once_with( - library, sonarr_instance - ) - mock_get_config_value.assert_called_once_with( - library, "max_actions_per_run", DEFAULT_MAX_ACTIONS_PER_RUN - ) - mock_filter_shows.assert_called_once_with(library, unfiltered_all_show_data) - mock_get_trakt_items.assert_called_once_with("show", library) - mock_get_plex_library.assert_called_once_with(library) - mock_get_show_activity.assert_called_once_with( - library, mock_get_plex_library.return_value - ) - mock_process_shows.assert_called_once_with( - library, - sonarr_instance, - mock_get_plex_library.return_value, - mock_filter_shows.return_value, - mock_get_show_activity.return_value, - mock_get_trakt_items.return_value, - mock_get_config_value.return_value, - ) - self.assertEqual(result, 5) - - -if __name__ == "__main__": - unittest.main() +def test_process_library(mocker, standard_config): + # Arrange + library = {"name": "Test Library"} + sonarr_instance = Mock() + unfiltered_all_show_data = MagicMock() + + mocker.patch.object(trakt.Trakt, "test_connection") + mocker.patch.object(Config, "test_api_connection") + mocker.patch.object(tautulli.Tautulli, "test_connection") + + # Mock plex server constructor + mocker.patch("app.media_cleaner.PlexServer", return_value=MagicMock()) + + mock_library_meets_disk_space_threshold = mocker.patch( + "app.media_cleaner.library_meets_disk_space_threshold", return_value=True + ) + mock_get_config_value = mocker.patch( + "app.media_cleaner._get_config_value", return_value=10 + ) + mock_filter_shows = mocker.patch.object( + MediaCleaner, "filter_shows", return_value=MagicMock() + ) + mock_get_trakt_items = mocker.patch.object( + MediaCleaner, "get_trakt_items", return_value=MagicMock() + ) + mock_get_plex_library = mocker.patch.object( + MediaCleaner, "get_plex_library", return_value=MagicMock(totalSize=20) + ) + mock_get_show_activity = mocker.patch.object( + MediaCleaner, "get_show_activity", return_value=MagicMock() + ) + mock_process_shows = mocker.patch.object( + MediaCleaner, "process_shows", return_value=5 + ) + + mock_logger = mocker.patch("app.media_cleaner.logger") + + # Act + media_cleaner = MediaCleaner(standard_config) + + result = media_cleaner.process_library( + library, sonarr_instance, unfiltered_all_show_data + ) + + # Assert + mock_library_meets_disk_space_threshold.assert_called_once_with( + library, sonarr_instance + ) + mock_get_config_value.assert_called_once_with( + library, "max_actions_per_run", DEFAULT_MAX_ACTIONS_PER_RUN + ) + mock_filter_shows.assert_called_once_with(library, unfiltered_all_show_data) + mock_get_trakt_items.assert_called_once_with("show", library) + mock_get_plex_library.assert_called_once_with(library) + mock_get_show_activity.assert_called_once_with( + library, mock_get_plex_library.return_value + ) + mock_process_shows.assert_called_once_with( + library, + sonarr_instance, + mock_get_plex_library.return_value, + mock_filter_shows.return_value, + mock_get_show_activity.return_value, + mock_get_trakt_items.return_value, + mock_get_config_value.return_value, + ) + assert result == 5 diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..63ae200 --- /dev/null +++ b/tox.ini @@ -0,0 +1,5 @@ +[flake8] +max-line-length = 200 +extend-ignore = E203 +exclude = tests/* +max-complexity = 15 \ No newline at end of file