refactor(scheduler): separate scheduler logic from scan/rescan logic
- Extract rescan logic into new RescanService (src/server/services/rescan_service.py) - SchedulerService now only handles APScheduler cron scheduling - Move scheduler sub-services (folder_rename, folder_scan, key_resolution) to scheduler/ folder - Keep RescanOrchestrator as backward-compatible alias - Update all imports across api/, server/, and test files
This commit is contained in:
@@ -216,7 +216,7 @@ async def test_update_config_with_anime_directory_starts_scheduler(
|
||||
"""PUT /api/config with anime_directory syncs and starts scheduler."""
|
||||
mock_scheduler = AsyncMock()
|
||||
|
||||
with patch("src.server.services.scheduler_service.get_scheduler_service") as mock_sched_fn:
|
||||
with patch("src.server.services.scheduler.scheduler_service.get_scheduler_service") as mock_sched_fn:
|
||||
mock_sched_fn.return_value = mock_scheduler
|
||||
|
||||
with patch("src.config.settings.settings") as mock_settings:
|
||||
@@ -238,7 +238,7 @@ async def test_update_config_without_anime_directory_does_not_start_scheduler(
|
||||
"""PUT /api/config without new anime_directory does not call scheduler.ensure_started()."""
|
||||
mock_scheduler = AsyncMock()
|
||||
|
||||
with patch("src.server.services.scheduler_service.get_scheduler_service") as mock_sched_fn:
|
||||
with patch("src.server.services.scheduler.scheduler_service.get_scheduler_service") as mock_sched_fn:
|
||||
mock_sched_fn.return_value = mock_scheduler
|
||||
|
||||
with patch("src.config.settings.settings") as mock_settings:
|
||||
|
||||
@@ -17,7 +17,7 @@ class TestFolderRenameScanCalledInFolderScan:
|
||||
import importlib
|
||||
|
||||
source = importlib.util.find_spec(
|
||||
"src.server.services.folder_scan_service"
|
||||
"src.server.services.scheduler.folder_scan_service"
|
||||
).origin
|
||||
with open(source, "r", encoding="utf-8") as fh:
|
||||
content = fh.read()
|
||||
@@ -31,7 +31,7 @@ class TestFolderRenameScanCalledInFolderScan:
|
||||
import importlib
|
||||
|
||||
source = importlib.util.find_spec(
|
||||
"src.server.services.folder_scan_service"
|
||||
"src.server.services.scheduler.folder_scan_service"
|
||||
).origin
|
||||
with open(source, "r", encoding="utf-8") as fh:
|
||||
content = fh.read()
|
||||
@@ -52,7 +52,7 @@ class TestFolderRenameIntegration:
|
||||
@pytest.mark.asyncio
|
||||
async def test_folder_rename_runs_during_scan(self, tmp_path):
|
||||
"""When folder_scan_enabled is true, the scan renames mismatched folders."""
|
||||
from src.server.services.folder_scan_service import FolderScanService
|
||||
from src.server.services.scheduler.folder_scan_service import FolderScanService
|
||||
|
||||
anime_dir = tmp_path / "anime"
|
||||
anime_dir.mkdir()
|
||||
@@ -69,15 +69,15 @@ class TestFolderRenameIntegration:
|
||||
with patch(
|
||||
"src.config.settings.settings", mock_settings
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.settings", mock_settings
|
||||
"src.server.services.scheduler.folder_rename_service.settings", mock_settings
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service._is_series_being_downloaded",
|
||||
"src.server.services.scheduler.folder_rename_service._is_series_being_downloaded",
|
||||
return_value=False,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service._update_database_paths",
|
||||
"src.server.services.scheduler.folder_rename_service._update_database_paths",
|
||||
new_callable=AsyncMock,
|
||||
):
|
||||
service = FolderScanService()
|
||||
@@ -89,7 +89,7 @@ class TestFolderRenameIntegration:
|
||||
@pytest.mark.asyncio
|
||||
async def test_folder_rename_skipped_when_prerequisites_not_met(self, tmp_path):
|
||||
"""If anime directory is missing, rename logic is skipped gracefully."""
|
||||
from src.server.services.folder_scan_service import FolderScanService
|
||||
from src.server.services.scheduler.folder_scan_service import FolderScanService
|
||||
|
||||
mock_settings = MagicMock()
|
||||
mock_settings.tmdb_api_key = "test-key"
|
||||
@@ -98,10 +98,10 @@ class TestFolderRenameIntegration:
|
||||
with patch(
|
||||
"src.config.settings.settings", mock_settings
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders"
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders"
|
||||
) as mock_rename:
|
||||
service = FolderScanService()
|
||||
await service.run_folder_scan()
|
||||
|
||||
@@ -34,7 +34,7 @@ class TestNfoRepairScanCalledInFolderScan:
|
||||
"""folder_scan_service.py imports perform_nfo_repair_scan."""
|
||||
import importlib
|
||||
|
||||
source = importlib.util.find_spec("src.server.services.folder_scan_service").origin
|
||||
source = importlib.util.find_spec("src.server.services.scheduler.folder_scan_service").origin
|
||||
with open(source, "r", encoding="utf-8") as fh:
|
||||
content = fh.read()
|
||||
|
||||
@@ -46,7 +46,7 @@ class TestNfoRepairScanCalledInFolderScan:
|
||||
"""perform_nfo_repair_scan must be called inside run_folder_scan."""
|
||||
import importlib
|
||||
|
||||
source = importlib.util.find_spec("src.server.services.folder_scan_service").origin
|
||||
source = importlib.util.find_spec("src.server.services.scheduler.folder_scan_service").origin
|
||||
with open(source, "r", encoding="utf-8") as fh:
|
||||
content = fh.read()
|
||||
|
||||
@@ -67,7 +67,9 @@ class TestNfoRepairScanIntegrationWithBackgroundLoader:
|
||||
@pytest.mark.asyncio
|
||||
async def test_incomplete_nfo_series_scheduled_for_repair(self, tmp_path):
|
||||
"""Series whose tvshow.nfo is missing required tags are scheduled via asyncio.create_task."""
|
||||
from src.server.services.folder_scan_service import perform_nfo_repair_scan
|
||||
from src.server.services.scheduler.folder_scan_service import (
|
||||
perform_nfo_repair_scan,
|
||||
)
|
||||
|
||||
series_dir = tmp_path / "IncompleteAnime"
|
||||
series_dir.mkdir()
|
||||
@@ -83,7 +85,7 @@ class TestNfoRepairScanIntegrationWithBackgroundLoader:
|
||||
mock_repair_service.repair_series = AsyncMock(return_value=True)
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_scan_service._settings", mock_settings
|
||||
"src.server.services.scheduler.folder_scan_service._settings", mock_settings
|
||||
), patch(
|
||||
"src.core.services.nfo_repair_service.nfo_needs_repair",
|
||||
return_value=True,
|
||||
@@ -103,7 +105,9 @@ class TestNfoRepairScanIntegrationWithBackgroundLoader:
|
||||
@pytest.mark.asyncio
|
||||
async def test_complete_nfo_series_not_scheduled(self, tmp_path):
|
||||
"""Series whose tvshow.nfo has all required tags are not scheduled for repair."""
|
||||
from src.server.services.folder_scan_service import perform_nfo_repair_scan
|
||||
from src.server.services.scheduler.folder_scan_service import (
|
||||
perform_nfo_repair_scan,
|
||||
)
|
||||
|
||||
series_dir = tmp_path / "CompleteAnime"
|
||||
series_dir.mkdir()
|
||||
@@ -116,7 +120,7 @@ class TestNfoRepairScanIntegrationWithBackgroundLoader:
|
||||
mock_settings.anime_directory = str(tmp_path)
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_scan_service._settings", mock_settings
|
||||
"src.server.services.scheduler.folder_scan_service._settings", mock_settings
|
||||
), patch(
|
||||
"src.core.services.nfo_repair_service.nfo_needs_repair",
|
||||
return_value=False,
|
||||
|
||||
@@ -19,7 +19,7 @@ class TestPosterCheckScanCalledInFolderScan:
|
||||
import importlib
|
||||
|
||||
source = importlib.util.find_spec(
|
||||
"src.server.services.folder_scan_service"
|
||||
"src.server.services.scheduler.folder_scan_service"
|
||||
).origin
|
||||
with open(source, "r", encoding="utf-8") as fh:
|
||||
content = fh.read()
|
||||
@@ -33,7 +33,7 @@ class TestPosterCheckScanCalledInFolderScan:
|
||||
import importlib
|
||||
|
||||
source = importlib.util.find_spec(
|
||||
"src.server.services.folder_scan_service"
|
||||
"src.server.services.scheduler.folder_scan_service"
|
||||
).origin
|
||||
with open(source, "r", encoding="utf-8") as fh:
|
||||
content = fh.read()
|
||||
@@ -54,7 +54,7 @@ class TestPosterCheckIntegration:
|
||||
@pytest.mark.asyncio
|
||||
async def test_poster_check_downloads_missing_poster(self, tmp_path):
|
||||
"""When poster.jpg is missing, the scan downloads it from the NFO thumb URL."""
|
||||
from src.server.services.folder_scan_service import FolderScanService
|
||||
from src.server.services.scheduler.folder_scan_service import FolderScanService
|
||||
|
||||
anime_dir = tmp_path / "anime"
|
||||
anime_dir.mkdir()
|
||||
@@ -91,14 +91,14 @@ class TestPosterCheckIntegration:
|
||||
with patch(
|
||||
"src.config.settings.settings", mock_settings
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders",
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders",
|
||||
new_callable=AsyncMock,
|
||||
return_value={"scanned": 0, "renamed": 0, "skipped": 0, "errors": 0},
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.ImageDownloader",
|
||||
"src.server.services.scheduler.folder_scan_service.ImageDownloader",
|
||||
new=MockDownloader,
|
||||
):
|
||||
service = FolderScanService()
|
||||
@@ -112,7 +112,7 @@ class TestPosterCheckIntegration:
|
||||
@pytest.mark.asyncio
|
||||
async def test_poster_check_skips_valid_poster(self, tmp_path):
|
||||
"""When poster.jpg exists and is large enough, the scan skips it."""
|
||||
from src.server.services.folder_scan_service import FolderScanService
|
||||
from src.server.services.scheduler.folder_scan_service import FolderScanService
|
||||
|
||||
anime_dir = tmp_path / "anime"
|
||||
anime_dir.mkdir()
|
||||
@@ -136,14 +136,14 @@ class TestPosterCheckIntegration:
|
||||
with patch(
|
||||
"src.config.settings.settings", mock_settings
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders",
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders",
|
||||
new_callable=AsyncMock,
|
||||
return_value={"scanned": 0, "renamed": 0, "skipped": 0, "errors": 0},
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.ImageDownloader"
|
||||
"src.server.services.scheduler.folder_scan_service.ImageDownloader"
|
||||
) as mock_downloader_cls:
|
||||
service = FolderScanService()
|
||||
await service.run_folder_scan()
|
||||
@@ -153,7 +153,7 @@ class TestPosterCheckIntegration:
|
||||
@pytest.mark.asyncio
|
||||
async def test_poster_check_skips_when_no_thumb_url(self, tmp_path):
|
||||
"""When NFO has no thumb URL, the scan skips the folder."""
|
||||
from src.server.services.folder_scan_service import FolderScanService
|
||||
from src.server.services.scheduler.folder_scan_service import FolderScanService
|
||||
|
||||
anime_dir = tmp_path / "anime"
|
||||
anime_dir.mkdir()
|
||||
@@ -173,14 +173,14 @@ class TestPosterCheckIntegration:
|
||||
with patch(
|
||||
"src.config.settings.settings", mock_settings
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders",
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders",
|
||||
new_callable=AsyncMock,
|
||||
return_value={"scanned": 0, "renamed": 0, "skipped": 0, "errors": 0},
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.ImageDownloader"
|
||||
"src.server.services.scheduler.folder_scan_service.ImageDownloader"
|
||||
) as mock_downloader_cls:
|
||||
service = FolderScanService()
|
||||
await service.run_folder_scan()
|
||||
@@ -190,7 +190,7 @@ class TestPosterCheckIntegration:
|
||||
@pytest.mark.asyncio
|
||||
async def test_poster_check_skipped_when_prerequisites_not_met(self, tmp_path):
|
||||
"""If anime directory is missing, poster check logic is skipped gracefully."""
|
||||
from src.server.services.folder_scan_service import FolderScanService
|
||||
from src.server.services.scheduler.folder_scan_service import FolderScanService
|
||||
|
||||
mock_settings = MagicMock()
|
||||
mock_settings.tmdb_api_key = "test-key"
|
||||
@@ -199,12 +199,12 @@ class TestPosterCheckIntegration:
|
||||
with patch(
|
||||
"src.config.settings.settings", mock_settings
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders"
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders"
|
||||
) as mock_rename, patch(
|
||||
"src.server.services.folder_scan_service.ImageDownloader"
|
||||
"src.server.services.scheduler.folder_scan_service.ImageDownloader"
|
||||
) as mock_downloader_cls:
|
||||
service = FolderScanService()
|
||||
await service.run_folder_scan()
|
||||
@@ -220,7 +220,7 @@ class TestPosterCheckSemaphore:
|
||||
import importlib
|
||||
|
||||
source = importlib.util.find_spec(
|
||||
"src.server.services.folder_scan_service"
|
||||
"src.server.services.scheduler.folder_scan_service"
|
||||
).origin
|
||||
with open(source, "r", encoding="utf-8") as fh:
|
||||
content = fh.read()
|
||||
@@ -232,7 +232,7 @@ class TestPosterCheckSemaphore:
|
||||
@pytest.mark.asyncio
|
||||
async def test_poster_download_uses_semaphore(self, tmp_path):
|
||||
"""Poster downloads are gated by the semaphore."""
|
||||
from src.server.services.folder_scan_service import (
|
||||
from src.server.services.scheduler.folder_scan_service import (
|
||||
_POSTER_DOWNLOAD_SEMAPHORE,
|
||||
FolderScanService,
|
||||
)
|
||||
@@ -270,14 +270,14 @@ class TestPosterCheckSemaphore:
|
||||
with patch(
|
||||
"src.config.settings.settings", mock_settings
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders",
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders",
|
||||
new_callable=AsyncMock,
|
||||
return_value={"scanned": 0, "renamed": 0, "skipped": 0, "errors": 0},
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.ImageDownloader"
|
||||
"src.server.services.scheduler.folder_scan_service.ImageDownloader"
|
||||
) as mock_downloader_cls:
|
||||
mock_downloader = AsyncMock()
|
||||
mock_downloader.download_poster = AsyncMock(side_effect=tracked_download)
|
||||
|
||||
@@ -11,15 +11,14 @@ from unittest.mock import AsyncMock, Mock, patch
|
||||
import pytest
|
||||
|
||||
from src.server.models.config import AppConfig, SchedulerConfig
|
||||
from src.server.services.scheduler_service import (
|
||||
from src.server.services.scheduler.scheduler_service import (
|
||||
_JOB_ID,
|
||||
SchedulerService,
|
||||
SchedulerServiceError,
|
||||
_JOB_ID,
|
||||
get_scheduler_service,
|
||||
reset_scheduler_service,
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Shared fixtures
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -27,7 +26,7 @@ from src.server.services.scheduler_service import (
|
||||
@pytest.fixture
|
||||
def mock_config_service():
|
||||
"""Patch get_config_service used by SchedulerService.start()."""
|
||||
with patch("src.server.services.scheduler_service.get_config_service") as mock:
|
||||
with patch("src.server.services.scheduler.scheduler_service.get_config_service") as mock:
|
||||
config_service = Mock()
|
||||
app_config = AppConfig(
|
||||
scheduler=SchedulerConfig(
|
||||
|
||||
@@ -474,7 +474,7 @@ class TestSchedulerConcurrentScanPrevention:
|
||||
@pytest.mark.asyncio
|
||||
async def test_scheduler_skips_rescan_if_already_running(self):
|
||||
"""Test scheduler skips scheduled rescan if one is already running."""
|
||||
from src.server.services.scheduler_service import SchedulerService
|
||||
from src.server.services.scheduler.scheduler_service import SchedulerService
|
||||
|
||||
scheduler = SchedulerService()
|
||||
|
||||
@@ -495,7 +495,7 @@ class TestSchedulerConcurrentScanPrevention:
|
||||
@pytest.mark.asyncio
|
||||
async def test_scheduler_sets_flag_during_rescan(self):
|
||||
"""Test that scheduler properly sets scan_in_progress flag."""
|
||||
from src.server.services.scheduler_service import SchedulerService
|
||||
from src.server.services.scheduler.scheduler_service import SchedulerService
|
||||
|
||||
scheduler = SchedulerService()
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class TestFfmpegHealthCheck:
|
||||
with patch("src.server.utils.dependencies.get_anime_service"):
|
||||
with patch("src.server.utils.dependencies.get_download_service"):
|
||||
with patch("src.server.utils.dependencies.get_background_loader_service"):
|
||||
with patch("src.server.services.scheduler_service.get_scheduler_service") as mock_get_sched:
|
||||
with patch("src.server.services.scheduler.scheduler_service.get_scheduler_service") as mock_get_sched:
|
||||
mock_sched = MagicMock()
|
||||
mock_sched.start = AsyncMock(return_value=None)
|
||||
mock_get_sched.return_value = mock_sched
|
||||
@@ -64,7 +64,7 @@ class TestFfmpegHealthCheck:
|
||||
with patch("src.server.utils.dependencies.get_anime_service"):
|
||||
with patch("src.server.utils.dependencies.get_download_service"):
|
||||
with patch("src.server.utils.dependencies.get_background_loader_service"):
|
||||
with patch("src.server.services.scheduler_service.get_scheduler_service") as mock_get_sched:
|
||||
with patch("src.server.services.scheduler.scheduler_service.get_scheduler_service") as mock_get_sched:
|
||||
mock_sched = MagicMock()
|
||||
mock_sched.start = AsyncMock(return_value=None)
|
||||
mock_get_sched.return_value = mock_sched
|
||||
|
||||
@@ -8,7 +8,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from src.server.services.folder_rename_service import (
|
||||
from src.server.services.scheduler.folder_rename_service import (
|
||||
_cleanup_orphaned_folder,
|
||||
_compute_expected_folder_name,
|
||||
_is_series_being_downloaded,
|
||||
@@ -163,7 +163,7 @@ class TestIsSeriesBeingDownloaded:
|
||||
mock_service._active_download = None
|
||||
mock_service._pending_queue = []
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.get_download_service",
|
||||
"src.server.services.scheduler.folder_rename_service.get_download_service",
|
||||
return_value=mock_service,
|
||||
):
|
||||
assert _is_series_being_downloaded("Some Show") is False
|
||||
@@ -175,7 +175,7 @@ class TestIsSeriesBeingDownloaded:
|
||||
mock_service._active_download = mock_item
|
||||
mock_service._pending_queue = []
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.get_download_service",
|
||||
"src.server.services.scheduler.folder_rename_service.get_download_service",
|
||||
return_value=mock_service,
|
||||
):
|
||||
assert _is_series_being_downloaded("Some Show") is True
|
||||
@@ -187,14 +187,14 @@ class TestIsSeriesBeingDownloaded:
|
||||
mock_service._active_download = None
|
||||
mock_service._pending_queue = [mock_item]
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.get_download_service",
|
||||
"src.server.services.scheduler.folder_rename_service.get_download_service",
|
||||
return_value=mock_service,
|
||||
):
|
||||
assert _is_series_being_downloaded("Some Show") is True
|
||||
|
||||
def test_exception_returns_true_for_safety(self) -> None:
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.get_download_service",
|
||||
"src.server.services.scheduler.folder_rename_service.get_download_service",
|
||||
side_effect=RuntimeError("boom"),
|
||||
):
|
||||
assert _is_series_being_downloaded("Some Show") is True
|
||||
@@ -213,13 +213,13 @@ class TestUpdateDatabasePaths:
|
||||
mock_series.folder = "Old Name"
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.get_db_session"
|
||||
"src.server.services.scheduler.folder_rename_service.get_db_session"
|
||||
) as mock_get_db, patch(
|
||||
"src.server.services.folder_rename_service.AnimeSeriesService"
|
||||
"src.server.services.scheduler.folder_rename_service.AnimeSeriesService"
|
||||
) as mock_series_svc, patch(
|
||||
"src.server.services.folder_rename_service.EpisodeService"
|
||||
"src.server.services.scheduler.folder_rename_service.EpisodeService"
|
||||
) as mock_episode_svc, patch(
|
||||
"src.server.services.folder_rename_service.DownloadQueueService"
|
||||
"src.server.services.scheduler.folder_rename_service.DownloadQueueService"
|
||||
) as mock_queue_svc:
|
||||
|
||||
mock_db = AsyncMock()
|
||||
@@ -254,13 +254,13 @@ class TestUpdateDatabasePaths:
|
||||
mock_episode.file_path = str(old_path)
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.get_db_session"
|
||||
"src.server.services.scheduler.folder_rename_service.get_db_session"
|
||||
) as mock_get_db, patch(
|
||||
"src.server.services.folder_rename_service.AnimeSeriesService"
|
||||
"src.server.services.scheduler.folder_rename_service.AnimeSeriesService"
|
||||
) as mock_series_svc, patch(
|
||||
"src.server.services.folder_rename_service.EpisodeService"
|
||||
"src.server.services.scheduler.folder_rename_service.EpisodeService"
|
||||
) as mock_episode_svc, patch(
|
||||
"src.server.services.folder_rename_service.DownloadQueueService"
|
||||
"src.server.services.scheduler.folder_rename_service.DownloadQueueService"
|
||||
) as mock_queue_svc:
|
||||
|
||||
mock_db = AsyncMock()
|
||||
@@ -350,7 +350,7 @@ class TestValidateAndRenameSeriesFolders:
|
||||
@pytest.mark.asyncio
|
||||
async def test_no_anime_directory(self) -> None:
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.settings.anime_directory",
|
||||
"src.server.services.scheduler.folder_rename_service.settings.anime_directory",
|
||||
"",
|
||||
):
|
||||
stats = await validate_and_rename_series_folders()
|
||||
@@ -367,13 +367,13 @@ class TestValidateAndRenameSeriesFolders:
|
||||
)
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.settings.anime_directory",
|
||||
"src.server.services.scheduler.folder_rename_service.settings.anime_directory",
|
||||
str(anime_dir),
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service._is_series_being_downloaded",
|
||||
"src.server.services.scheduler.folder_rename_service._is_series_being_downloaded",
|
||||
return_value=False,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service._update_database_paths",
|
||||
"src.server.services.scheduler.folder_rename_service._update_database_paths",
|
||||
new_callable=AsyncMock,
|
||||
) as mock_update_db:
|
||||
stats = await validate_and_rename_series_folders()
|
||||
@@ -397,7 +397,7 @@ class TestValidateAndRenameSeriesFolders:
|
||||
)
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.settings.anime_directory",
|
||||
"src.server.services.scheduler.folder_rename_service.settings.anime_directory",
|
||||
str(anime_dir),
|
||||
):
|
||||
stats = await validate_and_rename_series_folders()
|
||||
@@ -419,7 +419,7 @@ class TestValidateAndRenameSeriesFolders:
|
||||
)
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.settings.anime_directory",
|
||||
"src.server.services.scheduler.folder_rename_service.settings.anime_directory",
|
||||
str(anime_dir),
|
||||
):
|
||||
stats = await validate_and_rename_series_folders()
|
||||
@@ -440,10 +440,10 @@ class TestValidateAndRenameSeriesFolders:
|
||||
)
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.settings.anime_directory",
|
||||
"src.server.services.scheduler.folder_rename_service.settings.anime_directory",
|
||||
str(anime_dir),
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service._is_series_being_downloaded",
|
||||
"src.server.services.scheduler.folder_rename_service._is_series_being_downloaded",
|
||||
return_value=True,
|
||||
):
|
||||
stats = await validate_and_rename_series_folders()
|
||||
@@ -474,20 +474,20 @@ class TestValidateAndRenameSeriesFolders:
|
||||
mock_db.__aexit__.return_value = None
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.settings.anime_directory",
|
||||
"src.server.services.scheduler.folder_rename_service.settings.anime_directory",
|
||||
str(anime_dir),
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service._is_series_being_downloaded",
|
||||
"src.server.services.scheduler.folder_rename_service._is_series_being_downloaded",
|
||||
return_value=False,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.get_db_session",
|
||||
"src.server.services.scheduler.folder_rename_service.get_db_session",
|
||||
return_value=mock_db,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.AnimeSeriesService.get_by_key",
|
||||
"src.server.services.scheduler.folder_rename_service.AnimeSeriesService.get_by_key",
|
||||
new_callable=AsyncMock,
|
||||
return_value=None,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.AnimeSeriesService.get_all",
|
||||
"src.server.services.scheduler.folder_rename_service.AnimeSeriesService.get_all",
|
||||
new_callable=AsyncMock,
|
||||
return_value=[],
|
||||
):
|
||||
@@ -527,13 +527,13 @@ class TestValidateAndRenameSeriesFolders:
|
||||
(d3 / "tvshow.nfo").write_text("<tvshow><title>Show C</title></tvshow>")
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.settings.anime_directory",
|
||||
"src.server.services.scheduler.folder_rename_service.settings.anime_directory",
|
||||
str(anime_dir),
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service._is_series_being_downloaded",
|
||||
"src.server.services.scheduler.folder_rename_service._is_series_being_downloaded",
|
||||
return_value=False,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service._update_database_paths",
|
||||
"src.server.services.scheduler.folder_rename_service._update_database_paths",
|
||||
new_callable=AsyncMock,
|
||||
):
|
||||
stats = await validate_and_rename_series_folders()
|
||||
@@ -558,10 +558,10 @@ class TestValidateAndRenameSeriesFolders:
|
||||
)
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_rename_service.settings.anime_directory",
|
||||
"src.server.services.scheduler.folder_rename_service.settings.anime_directory",
|
||||
str(anime_dir),
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service._is_series_being_downloaded",
|
||||
"src.server.services.scheduler.folder_rename_service._is_series_being_downloaded",
|
||||
return_value=False,
|
||||
):
|
||||
stats = await validate_and_rename_series_folders(dry_run=True)
|
||||
|
||||
@@ -15,7 +15,7 @@ from unittest.mock import AsyncMock, MagicMock, Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from src.server.services.folder_scan_service import (
|
||||
from src.server.services.scheduler.folder_scan_service import (
|
||||
_POSTER_DOWNLOAD_SEMAPHORE,
|
||||
_TMDB_SEMAPHORE,
|
||||
FolderScanService,
|
||||
@@ -97,7 +97,7 @@ class TestRunFolderScanPrerequisites:
|
||||
with patch.object(
|
||||
folder_scan_service, "_prerequisites_met", return_value=False
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan"
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan"
|
||||
) as mock_repair:
|
||||
await folder_scan_service.run_folder_scan()
|
||||
mock_repair.assert_not_called()
|
||||
@@ -108,10 +108,10 @@ class TestRunFolderScanPrerequisites:
|
||||
with patch.object(
|
||||
folder_scan_service, "_prerequisites_met", return_value=True
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders",
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders",
|
||||
new_callable=AsyncMock,
|
||||
return_value={"scanned": 0, "renamed": 0, "skipped": 0, "errors": 0},
|
||||
), patch.object(
|
||||
@@ -148,10 +148,10 @@ class TestNfoRepairIntegration:
|
||||
with patch.object(
|
||||
folder_scan_service, "_prerequisites_met", return_value=True
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
) as mock_repair, patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders",
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders",
|
||||
new_callable=AsyncMock,
|
||||
return_value={"scanned": 0, "renamed": 0, "skipped": 0, "errors": 0},
|
||||
), patch.object(
|
||||
@@ -172,11 +172,11 @@ class TestNfoRepairIntegration:
|
||||
with patch.object(
|
||||
folder_scan_service, "_prerequisites_met", return_value=True
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
side_effect=RuntimeError("repair failed"),
|
||||
) as mock_repair, patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders",
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders",
|
||||
new_callable=AsyncMock,
|
||||
return_value={"scanned": 0, "renamed": 0, "skipped": 0, "errors": 0},
|
||||
) as mock_rename, patch.object(
|
||||
@@ -204,10 +204,10 @@ class TestFolderRenameIntegration:
|
||||
with patch.object(
|
||||
folder_scan_service, "_prerequisites_met", return_value=True
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders",
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders",
|
||||
new_callable=AsyncMock,
|
||||
return_value={"scanned": 5, "renamed": 2, "skipped": 2, "errors": 1},
|
||||
) as mock_rename, patch.object(
|
||||
@@ -228,10 +228,10 @@ class TestFolderRenameIntegration:
|
||||
with patch.object(
|
||||
folder_scan_service, "_prerequisites_met", return_value=True
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders",
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders",
|
||||
new_callable=AsyncMock,
|
||||
side_effect=RuntimeError("rename failed"),
|
||||
), patch.object(
|
||||
@@ -344,7 +344,7 @@ class TestPosterCheck:
|
||||
mock_settings.nfo_download_poster = True
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_scan_service.ImageDownloader",
|
||||
"src.server.services.scheduler.folder_scan_service.ImageDownloader",
|
||||
return_value=mock_downloader,
|
||||
):
|
||||
stats = await folder_scan_service.check_and_download_missing_posters()
|
||||
@@ -423,7 +423,7 @@ class TestPosterCheck:
|
||||
mock_settings.nfo_download_poster = True
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_scan_service.ImageDownloader",
|
||||
"src.server.services.scheduler.folder_scan_service.ImageDownloader",
|
||||
return_value=mock_downloader,
|
||||
):
|
||||
stats = await folder_scan_service.check_and_download_missing_posters()
|
||||
@@ -456,7 +456,7 @@ class TestPosterCheck:
|
||||
mock_settings.nfo_download_poster = True
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_scan_service.ImageDownloader",
|
||||
"src.server.services.scheduler.folder_scan_service.ImageDownloader",
|
||||
return_value=mock_downloader,
|
||||
):
|
||||
stats = await folder_scan_service.check_and_download_missing_posters()
|
||||
@@ -491,7 +491,7 @@ class TestPosterCheck:
|
||||
mock_settings.nfo_download_poster = True
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_scan_service.ImageDownloader",
|
||||
"src.server.services.scheduler.folder_scan_service.ImageDownloader",
|
||||
return_value=mock_downloader,
|
||||
):
|
||||
stats = await folder_scan_service.check_and_download_missing_posters()
|
||||
@@ -569,10 +569,10 @@ class TestRunFolderScanFull:
|
||||
with patch.object(
|
||||
folder_scan_service, "_prerequisites_met", return_value=True
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
) as mock_repair, patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders",
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders",
|
||||
new_callable=AsyncMock,
|
||||
return_value={"scanned": 3, "renamed": 1, "skipped": 1, "errors": 1},
|
||||
) as mock_rename, patch.object(
|
||||
@@ -593,10 +593,10 @@ class TestRunFolderScanFull:
|
||||
with patch.object(
|
||||
folder_scan_service, "_prerequisites_met", return_value=True
|
||||
), patch(
|
||||
"src.server.services.folder_scan_service.perform_nfo_repair_scan",
|
||||
"src.server.services.scheduler.folder_scan_service.perform_nfo_repair_scan",
|
||||
new_callable=AsyncMock,
|
||||
), patch(
|
||||
"src.server.services.folder_rename_service.validate_and_rename_series_folders",
|
||||
"src.server.services.scheduler.folder_rename_service.validate_and_rename_series_folders",
|
||||
new_callable=AsyncMock,
|
||||
return_value={"scanned": 0, "renamed": 0, "skipped": 0, "errors": 0},
|
||||
), patch.object(
|
||||
|
||||
@@ -10,7 +10,6 @@ from unittest.mock import AsyncMock, MagicMock, call, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from src.server.services.folder_scan_service import perform_nfo_repair_scan
|
||||
from src.server.services.initialization_service import (
|
||||
_check_initial_scan_status,
|
||||
_check_media_scan_status,
|
||||
@@ -30,6 +29,7 @@ from src.server.services.initialization_service import (
|
||||
perform_media_scan_if_needed,
|
||||
perform_nfo_scan_if_needed,
|
||||
)
|
||||
from src.server.services.scheduler.folder_scan_service import perform_nfo_repair_scan
|
||||
|
||||
|
||||
class TestCheckScanStatus:
|
||||
@@ -771,7 +771,7 @@ class TestPerformNfoRepairScan:
|
||||
mock_settings.anime_directory = str(tmp_path)
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_scan_service._settings", mock_settings
|
||||
"src.server.services.scheduler.folder_scan_service._settings", mock_settings
|
||||
):
|
||||
await perform_nfo_repair_scan()
|
||||
|
||||
@@ -785,7 +785,7 @@ class TestPerformNfoRepairScan:
|
||||
mock_settings.anime_directory = ""
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_scan_service._settings", mock_settings
|
||||
"src.server.services.scheduler.folder_scan_service._settings", mock_settings
|
||||
):
|
||||
await perform_nfo_repair_scan()
|
||||
|
||||
@@ -805,7 +805,7 @@ class TestPerformNfoRepairScan:
|
||||
mock_repair_service.repair_series = AsyncMock(return_value=True)
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_scan_service._settings", mock_settings
|
||||
"src.server.services.scheduler.folder_scan_service._settings", mock_settings
|
||||
), patch(
|
||||
"src.core.services.nfo_repair_service.nfo_needs_repair",
|
||||
return_value=True,
|
||||
@@ -838,7 +838,7 @@ class TestPerformNfoRepairScan:
|
||||
mock_settings.anime_directory = str(tmp_path)
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_scan_service._settings", mock_settings
|
||||
"src.server.services.scheduler.folder_scan_service._settings", mock_settings
|
||||
), patch(
|
||||
"src.core.services.nfo_repair_service.nfo_needs_repair",
|
||||
return_value=False,
|
||||
@@ -868,7 +868,7 @@ class TestPerformNfoRepairScan:
|
||||
mock_repair_service.repair_series = AsyncMock(return_value=True)
|
||||
|
||||
with patch(
|
||||
"src.server.services.folder_scan_service._settings", mock_settings
|
||||
"src.server.services.scheduler.folder_scan_service._settings", mock_settings
|
||||
), patch(
|
||||
"src.core.services.nfo_repair_service.nfo_needs_repair",
|
||||
return_value=True,
|
||||
|
||||
@@ -5,7 +5,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from src.server.services.key_resolution_service import (
|
||||
from src.server.services.scheduler.key_resolution_service import (
|
||||
_extract_key_from_link,
|
||||
_extract_year_from_folder,
|
||||
_normalize_for_comparison,
|
||||
@@ -104,7 +104,7 @@ class TestResolveKeyForFolder:
|
||||
]
|
||||
|
||||
with patch(
|
||||
"src.server.services.key_resolution_service._search_provider",
|
||||
"src.server.services.scheduler.key_resolution_service._search_provider",
|
||||
return_value=search_results,
|
||||
):
|
||||
key = await resolve_key_for_folder("Rent-A-Girlfriend (2020)")
|
||||
@@ -114,7 +114,7 @@ class TestResolveKeyForFolder:
|
||||
async def test_no_results_returns_none(self):
|
||||
"""When provider returns no results, returns None."""
|
||||
with patch(
|
||||
"src.server.services.key_resolution_service._search_provider",
|
||||
"src.server.services.scheduler.key_resolution_service._search_provider",
|
||||
return_value=[],
|
||||
):
|
||||
key = await resolve_key_for_folder("Unknown Anime (2020)")
|
||||
@@ -129,7 +129,7 @@ class TestResolveKeyForFolder:
|
||||
]
|
||||
|
||||
with patch(
|
||||
"src.server.services.key_resolution_service._search_provider",
|
||||
"src.server.services.scheduler.key_resolution_service._search_provider",
|
||||
return_value=search_results,
|
||||
):
|
||||
key = await resolve_key_for_folder("My Anime (2022)")
|
||||
@@ -144,7 +144,7 @@ class TestResolveKeyForFolder:
|
||||
]
|
||||
|
||||
with patch(
|
||||
"src.server.services.key_resolution_service._search_provider",
|
||||
"src.server.services.scheduler.key_resolution_service._search_provider",
|
||||
return_value=search_results,
|
||||
):
|
||||
key = await resolve_key_for_folder("Rent-A-Girlfriend (2020)")
|
||||
@@ -158,7 +158,7 @@ class TestResolveKeyForFolder:
|
||||
]
|
||||
|
||||
with patch(
|
||||
"src.server.services.key_resolution_service._search_provider",
|
||||
"src.server.services.scheduler.key_resolution_service._search_provider",
|
||||
return_value=search_results,
|
||||
):
|
||||
key = await resolve_key_for_folder("Naruto (2002)")
|
||||
@@ -168,7 +168,7 @@ class TestResolveKeyForFolder:
|
||||
async def test_provider_error_returns_none(self):
|
||||
"""When provider search raises an exception, returns None gracefully."""
|
||||
with patch(
|
||||
"src.server.services.key_resolution_service._search_provider",
|
||||
"src.server.services.scheduler.key_resolution_service._search_provider",
|
||||
side_effect=RuntimeError("Network error"),
|
||||
):
|
||||
key = await resolve_key_for_folder("Some Anime (2020)")
|
||||
@@ -182,7 +182,7 @@ class TestResolveKeyForFolder:
|
||||
]
|
||||
|
||||
with patch(
|
||||
"src.server.services.key_resolution_service._search_provider",
|
||||
"src.server.services.scheduler.key_resolution_service._search_provider",
|
||||
return_value=search_results,
|
||||
):
|
||||
key = await resolve_key_for_folder("One Piece (1999)")
|
||||
@@ -196,7 +196,7 @@ class TestResolveKeyForFolder:
|
||||
]
|
||||
|
||||
with patch(
|
||||
"src.server.services.key_resolution_service._search_provider",
|
||||
"src.server.services.scheduler.key_resolution_service._search_provider",
|
||||
return_value=search_results,
|
||||
):
|
||||
key = await resolve_key_for_folder("Naruto")
|
||||
@@ -211,7 +211,7 @@ class TestResolveKeyForFolder:
|
||||
]
|
||||
|
||||
with patch(
|
||||
"src.server.services.key_resolution_service._search_provider",
|
||||
"src.server.services.scheduler.key_resolution_service._search_provider",
|
||||
return_value=search_results,
|
||||
):
|
||||
key = await resolve_key_for_folder("Dororo (2019)")
|
||||
|
||||
@@ -15,7 +15,7 @@ import pytest
|
||||
from apscheduler.triggers.cron import CronTrigger
|
||||
|
||||
from src.server.models.config import AppConfig, SchedulerConfig
|
||||
from src.server.services.scheduler_service import (
|
||||
from src.server.services.scheduler.scheduler_service import (
|
||||
_JOB_ID,
|
||||
SchedulerService,
|
||||
SchedulerServiceError,
|
||||
@@ -36,7 +36,7 @@ def _make_app_config(**scheduler_kwargs) -> AppConfig:
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_service():
|
||||
with patch("src.server.services.scheduler_service.get_config_service") as mock:
|
||||
with patch("src.server.services.scheduler.scheduler_service.get_config_service") as mock:
|
||||
svc = Mock()
|
||||
svc.load_config.return_value = _make_app_config(
|
||||
enabled=True,
|
||||
@@ -105,7 +105,7 @@ class TestStart:
|
||||
self, scheduler_service, mock_config_service
|
||||
):
|
||||
with patch(
|
||||
"src.server.services.scheduler_service.AsyncIOScheduler"
|
||||
"src.server.services.scheduler.scheduler_service.AsyncIOScheduler"
|
||||
) as MockScheduler:
|
||||
mock_sched = MagicMock()
|
||||
mock_sched.running = False
|
||||
@@ -137,9 +137,9 @@ class TestStartEmptyDays:
|
||||
@pytest.mark.asyncio
|
||||
async def test_no_job_added_when_days_empty(self, scheduler_service):
|
||||
with patch(
|
||||
"src.server.services.scheduler_service.get_config_service"
|
||||
"src.server.services.scheduler.scheduler_service.get_config_service"
|
||||
) as mock_cs, patch(
|
||||
"src.server.services.scheduler_service.AsyncIOScheduler"
|
||||
"src.server.services.scheduler.scheduler_service.AsyncIOScheduler"
|
||||
) as MockScheduler:
|
||||
svc = Mock()
|
||||
svc.load_config.return_value = _make_app_config(
|
||||
@@ -409,7 +409,7 @@ class TestPerformRescanFolderScan:
|
||||
|
||||
with patch("src.server.utils.dependencies.get_anime_service", return_value=mock_anime), \
|
||||
patch("src.server.services.websocket_service.get_websocket_service", return_value=mock_ws), \
|
||||
patch("src.server.services.folder_scan_service.FolderScanService") as MockFSS:
|
||||
patch("src.server.services.scheduler.folder_scan_service.FolderScanService") as MockFSS:
|
||||
MockFSS.return_value.run_folder_scan = mock_folder_scan
|
||||
await scheduler_service._perform_rescan()
|
||||
|
||||
@@ -434,7 +434,7 @@ class TestPerformRescanFolderScan:
|
||||
|
||||
with patch("src.server.utils.dependencies.get_anime_service", return_value=mock_anime), \
|
||||
patch("src.server.services.websocket_service.get_websocket_service", return_value=mock_ws), \
|
||||
patch("src.server.services.folder_scan_service.FolderScanService") as MockFSS:
|
||||
patch("src.server.services.scheduler.folder_scan_service.FolderScanService") as MockFSS:
|
||||
MockFSS.return_value.run_folder_scan = mock_folder_scan
|
||||
await scheduler_service._perform_rescan()
|
||||
|
||||
@@ -459,7 +459,7 @@ class TestPerformRescanFolderScan:
|
||||
|
||||
with patch("src.server.utils.dependencies.get_anime_service", return_value=mock_anime), \
|
||||
patch("src.server.services.websocket_service.get_websocket_service", return_value=mock_ws), \
|
||||
patch("src.server.services.folder_scan_service.FolderScanService") as MockFSS:
|
||||
patch("src.server.services.scheduler.folder_scan_service.FolderScanService") as MockFSS:
|
||||
MockFSS.return_value.run_folder_scan = mock_folder_scan
|
||||
# Should NOT raise
|
||||
await scheduler_service._perform_rescan()
|
||||
@@ -498,7 +498,7 @@ class TestInMemoryJobStore:
|
||||
self, scheduler_service, mock_config_service
|
||||
):
|
||||
with patch(
|
||||
"src.server.services.scheduler_service.AsyncIOScheduler"
|
||||
"src.server.services.scheduler.scheduler_service.AsyncIOScheduler"
|
||||
) as MockScheduler:
|
||||
mock_sched = MagicMock()
|
||||
mock_sched.running = False
|
||||
@@ -517,7 +517,7 @@ class TestInMemoryJobStore:
|
||||
self, scheduler_service, mock_config_service
|
||||
):
|
||||
with patch(
|
||||
"src.server.services.scheduler_service.AsyncIOScheduler"
|
||||
"src.server.services.scheduler.scheduler_service.AsyncIOScheduler"
|
||||
) as MockScheduler:
|
||||
mock_sched = MagicMock()
|
||||
mock_sched.running = False
|
||||
@@ -540,7 +540,7 @@ class TestStartupRecovery:
|
||||
self, scheduler_service, mock_config_service
|
||||
):
|
||||
with patch(
|
||||
"src.server.services.scheduler_service.AsyncIOScheduler"
|
||||
"src.server.services.scheduler.scheduler_service.AsyncIOScheduler"
|
||||
) as MockScheduler:
|
||||
mock_job = MagicMock()
|
||||
next_run_dt = datetime(2026, 5, 25, 3, 0, tzinfo=timezone.utc)
|
||||
@@ -551,7 +551,7 @@ class TestStartupRecovery:
|
||||
MockScheduler.return_value = mock_sched
|
||||
|
||||
with patch(
|
||||
"src.server.services.scheduler_service.logger"
|
||||
"src.server.services.scheduler.scheduler_service.logger"
|
||||
) as mock_logger:
|
||||
await scheduler_service.start()
|
||||
info_calls = [str(c) for c in mock_logger.info.call_args_list]
|
||||
|
||||
Reference in New Issue
Block a user