fix tests
This commit is contained in:
@@ -6,7 +6,7 @@ error handling, and progress reporting integration.
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -15,16 +15,17 @@ from src.server.services.progress_service import ProgressService
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_series_app():
|
||||
def mock_series_app(tmp_path):
|
||||
"""Create a mock SeriesApp instance."""
|
||||
with patch("src.server.services.anime_service.SeriesApp") as mock_class:
|
||||
mock_instance = MagicMock()
|
||||
mock_instance.series_list = []
|
||||
mock_instance.search = MagicMock(return_value=[])
|
||||
mock_instance.ReScan = MagicMock()
|
||||
mock_instance.download = MagicMock(return_value=True)
|
||||
mock_class.return_value = mock_instance
|
||||
yield mock_instance
|
||||
mock_instance = MagicMock()
|
||||
mock_instance.directory_to_search = str(tmp_path)
|
||||
mock_instance.series_list = []
|
||||
mock_instance.search = AsyncMock(return_value=[])
|
||||
mock_instance.rescan = AsyncMock()
|
||||
mock_instance.download = AsyncMock(return_value=True)
|
||||
mock_instance.download_status = None
|
||||
mock_instance.scan_status = None
|
||||
return mock_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -42,8 +43,7 @@ def mock_progress_service():
|
||||
def anime_service(tmp_path, mock_series_app, mock_progress_service):
|
||||
"""Create an AnimeService instance for testing."""
|
||||
return AnimeService(
|
||||
directory=str(tmp_path),
|
||||
max_workers=2,
|
||||
series_app=mock_series_app,
|
||||
progress_service=mock_progress_service,
|
||||
)
|
||||
|
||||
@@ -51,35 +51,38 @@ def anime_service(tmp_path, mock_series_app, mock_progress_service):
|
||||
class TestAnimeServiceInitialization:
|
||||
"""Test AnimeService initialization."""
|
||||
|
||||
def test_initialization_success(self, tmp_path, mock_progress_service):
|
||||
def test_initialization_success(
|
||||
self, mock_series_app, mock_progress_service
|
||||
):
|
||||
"""Test successful service initialization."""
|
||||
with patch("src.server.services.anime_service.SeriesApp"):
|
||||
service = AnimeService(
|
||||
directory=str(tmp_path),
|
||||
max_workers=2,
|
||||
progress_service=mock_progress_service,
|
||||
)
|
||||
|
||||
assert service._directory == str(tmp_path)
|
||||
assert service._executor is not None
|
||||
assert service._progress_service is mock_progress_service
|
||||
service = AnimeService(
|
||||
series_app=mock_series_app,
|
||||
progress_service=mock_progress_service,
|
||||
)
|
||||
|
||||
assert service._app is mock_series_app
|
||||
assert service._progress_service is mock_progress_service
|
||||
|
||||
def test_initialization_failure_raises_error(
|
||||
self, tmp_path, mock_progress_service
|
||||
):
|
||||
"""Test SeriesApp initialization failure raises error."""
|
||||
with patch(
|
||||
"src.server.services.anime_service.SeriesApp"
|
||||
) as mock_class:
|
||||
mock_class.side_effect = Exception("Initialization failed")
|
||||
|
||||
with pytest.raises(
|
||||
AnimeServiceError, match="Initialization failed"
|
||||
):
|
||||
AnimeService(
|
||||
directory=str(tmp_path),
|
||||
progress_service=mock_progress_service,
|
||||
)
|
||||
bad_series_app = MagicMock()
|
||||
bad_series_app.directory_to_search = str(tmp_path)
|
||||
|
||||
# Make event subscription fail
|
||||
def raise_error(*args):
|
||||
raise Exception("Initialization failed")
|
||||
|
||||
bad_series_app.__setattr__ = raise_error
|
||||
|
||||
with pytest.raises(
|
||||
AnimeServiceError, match="Initialization failed"
|
||||
):
|
||||
AnimeService(
|
||||
series_app=bad_series_app,
|
||||
progress_service=mock_progress_service,
|
||||
)
|
||||
|
||||
|
||||
class TestListMissing:
|
||||
@@ -321,12 +324,12 @@ class TestConcurrency:
|
||||
class TestFactoryFunction:
|
||||
"""Test factory function."""
|
||||
|
||||
def test_get_anime_service(self, tmp_path):
|
||||
def test_get_anime_service(self):
|
||||
"""Test get_anime_service factory function."""
|
||||
from src.server.services.anime_service import get_anime_service
|
||||
|
||||
# The factory function doesn't take directory anymore
|
||||
service = get_anime_service()
|
||||
|
||||
with patch("src.server.services.anime_service.SeriesApp"):
|
||||
service = get_anime_service(directory=str(tmp_path))
|
||||
|
||||
assert isinstance(service, AnimeService)
|
||||
assert service._directory == str(tmp_path)
|
||||
assert isinstance(service, AnimeService)
|
||||
assert service._app is not None
|
||||
|
||||
@@ -48,15 +48,15 @@ class TestDownloadPriority:
|
||||
|
||||
def test_all_priorities_exist(self):
|
||||
"""Test that all expected priorities are defined."""
|
||||
assert DownloadPriority.LOW == "low"
|
||||
assert DownloadPriority.NORMAL == "normal"
|
||||
assert DownloadPriority.HIGH == "high"
|
||||
assert DownloadPriority.LOW == "LOW"
|
||||
assert DownloadPriority.NORMAL == "NORMAL"
|
||||
assert DownloadPriority.HIGH == "HIGH"
|
||||
|
||||
def test_priority_values(self):
|
||||
"""Test that priority values are lowercase strings."""
|
||||
"""Test that priority values are uppercase strings."""
|
||||
for priority in DownloadPriority:
|
||||
assert isinstance(priority.value, str)
|
||||
assert priority.value.islower()
|
||||
assert priority.value.isupper()
|
||||
|
||||
|
||||
class TestEpisodeIdentifier:
|
||||
|
||||
@@ -76,15 +76,11 @@ def progress_service():
|
||||
@pytest.fixture
|
||||
async def anime_service(mock_series_app, progress_service):
|
||||
"""Create an AnimeService with mocked dependencies."""
|
||||
with patch(
|
||||
"src.server.services.anime_service.SeriesApp",
|
||||
return_value=mock_series_app
|
||||
):
|
||||
service = AnimeService(
|
||||
directory="/test/anime",
|
||||
progress_service=progress_service,
|
||||
)
|
||||
yield service
|
||||
service = AnimeService(
|
||||
series_app=mock_series_app,
|
||||
progress_service=progress_service,
|
||||
)
|
||||
yield service
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -118,7 +114,7 @@ class TestDownloadProgressWebSocket:
|
||||
# Add item to queue
|
||||
item_ids = await download_service.add_to_queue(
|
||||
serie_id="test_serie_1",
|
||||
serie_folder="test_folder",
|
||||
serie_folder="test_serie_1",
|
||||
serie_name="Test Anime",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
priority=DownloadPriority.NORMAL,
|
||||
@@ -168,7 +164,7 @@ class TestDownloadProgressWebSocket:
|
||||
# Add item with specific episode info
|
||||
await download_service.add_to_queue(
|
||||
serie_id="test_serie_2",
|
||||
serie_folder="test_folder",
|
||||
serie_folder="test_serie_2",
|
||||
serie_name="My Test Anime",
|
||||
episodes=[EpisodeIdentifier(season=2, episode=5)],
|
||||
priority=DownloadPriority.HIGH,
|
||||
@@ -203,7 +199,7 @@ class TestDownloadProgressWebSocket:
|
||||
|
||||
await download_service.add_to_queue(
|
||||
serie_id="test_serie_3",
|
||||
serie_folder="test_folder",
|
||||
serie_folder="test_serie_3",
|
||||
serie_name="Progress Test",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -240,7 +236,7 @@ class TestDownloadProgressWebSocket:
|
||||
|
||||
await download_service.add_to_queue(
|
||||
serie_id="test_serie_4",
|
||||
serie_folder="test_folder",
|
||||
serie_folder="test_serie_4",
|
||||
serie_name="Speed Test",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -272,7 +268,7 @@ class TestDownloadProgressWebSocket:
|
||||
|
||||
await download_service.add_to_queue(
|
||||
serie_id="test_serie_5",
|
||||
serie_folder="test_folder",
|
||||
serie_folder="test_serie_5",
|
||||
serie_name="No Broadcast Test",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -300,7 +296,7 @@ class TestDownloadProgressWebSocket:
|
||||
|
||||
await download_service.add_to_queue(
|
||||
serie_id="test_serie_6",
|
||||
serie_folder="test_folder",
|
||||
serie_folder="test_serie_6",
|
||||
serie_name="Error Handling Test",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -331,7 +327,7 @@ class TestDownloadProgressWebSocket:
|
||||
# Add multiple episodes
|
||||
item_ids = await download_service.add_to_queue(
|
||||
serie_id="test_serie_7",
|
||||
serie_folder="test_folder",
|
||||
serie_folder="test_serie_7",
|
||||
serie_name="Multi Episode Test",
|
||||
episodes=[
|
||||
EpisodeIdentifier(season=1, episode=1),
|
||||
@@ -378,7 +374,7 @@ class TestDownloadProgressWebSocket:
|
||||
|
||||
await download_service.add_to_queue(
|
||||
serie_id="test_serie_8",
|
||||
serie_folder="test_folder",
|
||||
serie_folder="test_serie_8",
|
||||
serie_name="Model Test",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
|
||||
@@ -118,6 +118,7 @@ class TestQueueManagement:
|
||||
|
||||
item_ids = await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=episodes,
|
||||
priority=DownloadPriority.NORMAL,
|
||||
@@ -142,6 +143,7 @@ class TestQueueManagement:
|
||||
|
||||
item_ids = await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=episodes,
|
||||
priority=DownloadPriority.NORMAL,
|
||||
@@ -155,6 +157,7 @@ class TestQueueManagement:
|
||||
"""Test removing items from pending queue."""
|
||||
item_ids = await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -171,6 +174,7 @@ class TestQueueManagement:
|
||||
# Add items to queue
|
||||
item_ids = await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=[
|
||||
EpisodeIdentifier(season=1, episode=1),
|
||||
@@ -200,6 +204,7 @@ class TestQueueManagement:
|
||||
# Add items and start one
|
||||
await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=[
|
||||
EpisodeIdentifier(season=1, episode=1),
|
||||
@@ -236,6 +241,7 @@ class TestQueueManagement:
|
||||
# Add item
|
||||
await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -258,6 +264,7 @@ class TestQueueManagement:
|
||||
# Add item
|
||||
await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -279,6 +286,7 @@ class TestQueueStatus:
|
||||
# Add items to queue
|
||||
await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=[
|
||||
EpisodeIdentifier(season=1, episode=1),
|
||||
@@ -302,6 +310,7 @@ class TestQueueStatus:
|
||||
# Add items
|
||||
await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=[
|
||||
EpisodeIdentifier(season=1, episode=1),
|
||||
@@ -380,6 +389,7 @@ class TestPersistence:
|
||||
"""Test that queue state is persisted to disk."""
|
||||
await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -408,6 +418,7 @@ class TestPersistence:
|
||||
|
||||
await service1.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=[
|
||||
EpisodeIdentifier(season=1, episode=1),
|
||||
@@ -491,6 +502,7 @@ class TestBroadcastCallbacks:
|
||||
|
||||
await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -530,6 +542,7 @@ class TestBroadcastCallbacks:
|
||||
# Add an item to the queue
|
||||
await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
@@ -617,6 +630,7 @@ class TestErrorHandling:
|
||||
|
||||
await download_service.add_to_queue(
|
||||
serie_id="series-1",
|
||||
serie_folder="series",
|
||||
serie_name="Test Series",
|
||||
episodes=[EpisodeIdentifier(season=1, episode=1)],
|
||||
)
|
||||
|
||||
@@ -7,11 +7,10 @@ Tests the functionality of SeriesApp including:
|
||||
- Download with progress callbacks
|
||||
- Directory scanning with progress reporting
|
||||
- Async versions of operations
|
||||
- Cancellation support
|
||||
- Error handling
|
||||
"""
|
||||
|
||||
from unittest.mock import Mock, patch
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -35,62 +34,30 @@ class TestSeriesAppInitialization:
|
||||
|
||||
# Verify initialization
|
||||
assert app.directory_to_search == test_dir
|
||||
assert app._operation_status == OperationStatus.IDLE
|
||||
assert app._cancel_flag is False
|
||||
assert app._current_operation is None
|
||||
mock_loaders.assert_called_once()
|
||||
mock_scanner.assert_called_once()
|
||||
|
||||
@patch('src.core.SeriesApp.Loaders')
|
||||
@patch('src.core.SeriesApp.SerieScanner')
|
||||
@patch('src.core.SeriesApp.SerieList')
|
||||
def test_init_with_callbacks(
|
||||
self, mock_serie_list, mock_scanner, mock_loaders
|
||||
):
|
||||
"""Test initialization with progress and error callbacks."""
|
||||
def test_init_failure_raises_error(self, mock_loaders):
|
||||
"""Test that initialization failure raises error."""
|
||||
test_dir = "/test/anime"
|
||||
progress_callback = Mock()
|
||||
error_callback = Mock()
|
||||
|
||||
# Create app with callbacks
|
||||
app = SeriesApp(
|
||||
test_dir,
|
||||
progress_callback=progress_callback,
|
||||
error_callback=error_callback
|
||||
)
|
||||
|
||||
# Verify callbacks are stored
|
||||
assert app.progress_callback == progress_callback
|
||||
assert app.error_callback == error_callback
|
||||
|
||||
@patch('src.core.SeriesApp.Loaders')
|
||||
def test_init_failure_calls_error_callback(self, mock_loaders):
|
||||
"""Test that initialization failure triggers error callback."""
|
||||
test_dir = "/test/anime"
|
||||
error_callback = Mock()
|
||||
|
||||
# Make Loaders raise an exception
|
||||
mock_loaders.side_effect = RuntimeError("Init failed")
|
||||
|
||||
# Create app should raise but call error callback
|
||||
# Create app should raise
|
||||
with pytest.raises(RuntimeError):
|
||||
SeriesApp(test_dir, error_callback=error_callback)
|
||||
|
||||
# Verify error callback was called
|
||||
error_callback.assert_called_once()
|
||||
assert isinstance(
|
||||
error_callback.call_args[0][0],
|
||||
RuntimeError
|
||||
)
|
||||
SeriesApp(test_dir)
|
||||
|
||||
|
||||
class TestSeriesAppSearch:
|
||||
"""Test search functionality."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch('src.core.SeriesApp.Loaders')
|
||||
@patch('src.core.SeriesApp.SerieScanner')
|
||||
@patch('src.core.SeriesApp.SerieList')
|
||||
def test_search_success(
|
||||
async def test_search_success(
|
||||
self, mock_serie_list, mock_scanner, mock_loaders
|
||||
):
|
||||
"""Test successful search."""
|
||||
@@ -104,34 +71,32 @@ class TestSeriesAppSearch:
|
||||
]
|
||||
app.loader.search = Mock(return_value=expected_results)
|
||||
|
||||
# Perform search
|
||||
results = app.search("test anime")
|
||||
# Perform search (now async)
|
||||
results = await app.search("test anime")
|
||||
|
||||
# Verify results
|
||||
assert results == expected_results
|
||||
app.loader.search.assert_called_once_with("test anime")
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch('src.core.SeriesApp.Loaders')
|
||||
@patch('src.core.SeriesApp.SerieScanner')
|
||||
@patch('src.core.SeriesApp.SerieList')
|
||||
def test_search_failure_calls_error_callback(
|
||||
async def test_search_failure_raises_error(
|
||||
self, mock_serie_list, mock_scanner, mock_loaders
|
||||
):
|
||||
"""Test search failure triggers error callback."""
|
||||
"""Test search failure raises error."""
|
||||
test_dir = "/test/anime"
|
||||
error_callback = Mock()
|
||||
app = SeriesApp(test_dir, error_callback=error_callback)
|
||||
app = SeriesApp(test_dir)
|
||||
|
||||
# Make search raise an exception
|
||||
app.loader.search = Mock(
|
||||
side_effect=RuntimeError("Search failed")
|
||||
)
|
||||
|
||||
# Search should raise and call error callback
|
||||
# Search should raise
|
||||
with pytest.raises(RuntimeError):
|
||||
app.search("test")
|
||||
|
||||
error_callback.assert_called_once()
|
||||
await app.search("test")
|
||||
|
||||
|
||||
class TestSeriesAppDownload:
|
||||
|
||||
Reference in New Issue
Block a user